yacc.y revision 1.1 1 /* $NetBSD: yacc.y,v 1.1 2003/06/26 06:30:15 tshiozak Exp $ */
2
3 %{
4 /*-
5 * Copyright (c)2003 Citrus Project,
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #include <sys/cdefs.h>
35 #if defined(LIBC_SCCS) && !defined(lint)
36 __RCSID("$NetBSD: yacc.y,v 1.1 2003/06/26 06:30:15 tshiozak Exp $");
37 #endif /* LIBC_SCCS and not lint */
38
39 #include <assert.h>
40 #include <err.h>
41 #include <errno.h>
42 #include <limits.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <unistd.h>
47 #include <sys/types.h>
48
49 #include "ldef.h"
50
51 #ifndef __packed
52 #define __packed
53 #endif
54
55 #include "citrus_namespace.h"
56 #include "citrus_types.h"
57 #include "citrus_mapper_std_file.h"
58 #include "citrus_region.h"
59 #include "citrus_db_factory.h"
60 #include "citrus_db_hash.h"
61 #include "citrus_lookup_factory.h"
62 #include "citrus_pivot_factory.h"
63
64 int debug = 0;
65 static char *output = NULL;
66 static void *table = NULL;
67 static size_t table_size;
68 static char *map_name;
69 static int map_type;
70 static zone_t src_zone;
71 static u_int32_t colmask, rowmask;
72 static u_int32_t dst_invalid, dst_unit_bits;
73 static void (*putfunc)(void *, size_t, u_int32_t) = 0;
74
75 static u_int32_t src_next;
76 static int next_valid;
77
78 static u_int32_t done_flag = 0;
79 #define DF_TYPE 0x00000001
80 #define DF_NAME 0x00000002
81 #define DF_SRC_ZONE 0x00000004
82 #define DF_DST_INVALID 0x00000008
83 #define DF_DST_UNIT_BITS 0x00000010
84
85 static void dump_file(void);
86 static void setup_map(void);
87 static void set_type(int);
88 static void set_name(char *);
89 static void set_src_zone(const zone_t *);
90 static void set_dst_invalid(u_int32_t);
91 static void set_dst_unit_bits(u_int32_t);
92 static void calc_next(void);
93 static int check_src(u_int32_t, u_int32_t);
94 static void store(const linear_zone_t *, u_int32_t, int);
95 static void put8(void *, size_t, u_int32_t);
96 static void put16(void *, size_t, u_int32_t);
97 static void put32(void *, size_t, u_int32_t);
98 %}
99
100 %union {
101 u_int32_t i_value;
102 char *s_value;
103 zone_t z_value;
104 linear_zone_t lz_value;
105 }
106
107 %token R_TYPE R_NAME R_SRC_ZONE R_DST_INVALID R_DST_UNIT_BITS
108 %token R_BEGIN_MAP R_END_MAP R_INVALID R_ROWCOL
109 %token R_LN
110 %token <i_value> L_IMM
111 %token <s_value> L_STRING
112
113 %type <z_value> zone
114 %type <lz_value> src
115 %type <i_value> dst types
116
117 %%
118
119 file : property mapping lns
120 { dump_file(); }
121
122 property : /* empty */
123 | property R_LN
124 | property name
125 | property type
126 | property src_zone
127 | property dst_invalid
128 | property dst_unit_bits
129
130 name : R_NAME L_STRING { set_name($2); $2 = NULL; }
131 type : R_TYPE types { set_type($2); }
132 types : R_ROWCOL { $$ = R_ROWCOL; }
133 src_zone : R_SRC_ZONE zone { set_src_zone(&$2); }
134 zone : L_IMM '-' L_IMM {
135 $$.row_begin = $$.row_end = 0;
136 $$.col_begin = $1; $$.col_end = $3;
137 $$.col_bits = 32;
138 }
139 | L_IMM '-' L_IMM '/' L_IMM '-' L_IMM '/' L_IMM {
140 $$.row_begin = $1; $$.row_end = $3;
141 $$.col_begin = $5; $$.col_end = $7;
142 $$.col_bits = $9;
143 }
144
145 dst_invalid : R_DST_INVALID L_IMM { set_dst_invalid($2); }
146 dst_unit_bits : R_DST_UNIT_BITS L_IMM { set_dst_unit_bits($2); }
147
148
149 mapping : begin_map map_elems R_END_MAP
150 begin_map : R_BEGIN_MAP lns { setup_map(); }
151
152 map_elems : /* empty */
153 | map_elems map_elem lns
154
155 map_elem : src '=' dst
156 { store(&$1, $3, 0); }
157 | src '=' L_IMM '-'
158 { store(&$1, $3, 1); }
159 dst : L_IMM
160 {
161 $$ = $1;
162 }
163 | R_INVALID
164 {
165 $$ = dst_invalid;
166 }
167
168 src : /* empty */
169 {
170 if (!next_valid) {
171 yyerror("cannot omit src");
172 }
173 $$.begin = $$.end = src_next;
174 calc_next();
175 }
176 | L_IMM
177 {
178 if (check_src($1, $1)) {
179 yyerror("illegal zone");
180 }
181 $$.begin = $$.end = $1;
182 src_next = $1;
183 calc_next();
184 }
185 | L_IMM '-' L_IMM
186 {
187 if (check_src($1, $3)) {
188 yyerror("illegal zone");
189 }
190 $$.begin = $1; $$.end = $3;
191 src_next = $3;
192 calc_next();
193 }
194 | '-' L_IMM
195 {
196 if (!next_valid) {
197 yyerror("cannot omit src");
198 }
199 if (check_src(src_next, $2)) {
200 yyerror("illegal zone");
201 }
202 $$.begin = src_next; $$.end = $2;
203 src_next = $2;
204 calc_next();
205 }
206 lns : R_LN
207 | lns R_LN
208
209 %%
210
211 static void
212 warning(const char *s)
213 {
214 fprintf(stderr, "%s in %d\n", s, line_number);
215 }
216
217 int
218 yyerror(const char *s)
219 {
220 warning(s);
221 exit(1);
222 }
223
224 void
225 put8(void *ptr, size_t ofs, u_int32_t val)
226 {
227 *((u_int8_t *)ptr + ofs) = val;
228 }
229
230 void
231 put16(void *ptr, size_t ofs, u_int32_t val)
232 {
233 u_int16_t oval = htons(val);
234 memcpy((u_int16_t *)ptr + ofs, &oval, 2);
235 }
236
237 void
238 put32(void *ptr, size_t ofs, u_int32_t val)
239 {
240 u_int32_t oval = htonl(val);
241 memcpy((u_int32_t *)ptr + ofs, &oval, 4);
242 }
243
244 static void
245 alloc_table(void)
246 {
247 size_t i;
248
249 table_size =
250 (src_zone.row_end-src_zone.row_begin+1)*
251 (src_zone.col_end-src_zone.col_begin+1);
252 table = malloc(table_size*dst_unit_bits/8);
253 if (!table) {
254 perror("malloc");
255 exit(1);
256 }
257
258 for (i=0; i<table_size; i++)
259 (*putfunc)(table, i, dst_invalid);
260 }
261
262 static void
263 setup_map(void)
264 {
265
266 if ((done_flag & DF_SRC_ZONE)==0) {
267 fprintf(stderr, "SRC_ZONE is mandatory.\n");
268 exit(1);
269 }
270 if ((done_flag & DF_DST_UNIT_BITS)==0) {
271 fprintf(stderr, "DST_UNIT_BITS is mandatory.\n");
272 exit(1);
273 }
274
275 if ((done_flag & DF_DST_INVALID) == 0)
276 dst_invalid = 0xFFFFFFFF;
277
278 alloc_table();
279 }
280
281 static void
282 create_rowcol_info(struct _region *r)
283 {
284 void *ptr;
285 size_t ofs;
286
287 ofs = 0;
288 ptr = malloc(_CITRUS_MAPPER_STD_ROWCOL_INFO_SIZE);
289 if (ptr==NULL)
290 err(EXIT_FAILURE, "malloc");
291
292 put32(ptr, ofs, src_zone.col_bits); ofs++;
293 put32(ptr, ofs, dst_invalid); ofs++;
294 put32(ptr, ofs, src_zone.row_begin); ofs++;
295 put32(ptr, ofs, src_zone.row_end); ofs++;
296 put32(ptr, ofs, src_zone.col_begin); ofs++;
297 put32(ptr, ofs, src_zone.col_end); ofs++;
298 put32(ptr, ofs, dst_unit_bits); ofs++;
299 put32(ptr, ofs, 0); /* pad */
300
301 _region_init(r, ptr, _CITRUS_MAPPER_STD_ROWCOL_INFO_SIZE);
302 }
303
304 #define CHKERR(ret, func, a) \
305 do { \
306 ret = func a; \
307 if (ret) \
308 errx(EXIT_FAILURE, "%s: %s", #func, strerror(ret)); \
309 } while (/*CONSTCOND*/0)
310
311 static void
312 dump_file(void)
313 {
314 FILE *fp;
315 int ret;
316 struct _db_factory *df;
317 struct _region data;
318 void *serialized;
319 size_t size;
320
321 /*
322 * build database
323 */
324 CHKERR(ret, _db_factory_create, (&df, _db_hash_std, NULL));
325
326 /* store type */
327 CHKERR(ret, _db_factory_addstr_by_s,
328 (df, _CITRUS_MAPPER_STD_SYM_TYPE,
329 _CITRUS_MAPPER_STD_TYPE_ROWCOL));
330
331 /* store info */
332 create_rowcol_info(&data);
333 CHKERR(ret, _db_factory_add_by_s,
334 (df, _CITRUS_MAPPER_STD_SYM_INFO, &data, 1));
335
336 /* store table */
337 _region_init(&data, table, table_size*dst_unit_bits/8);
338 CHKERR(ret, _db_factory_add_by_s,
339 (df, _CITRUS_MAPPER_STD_SYM_TABLE, &data, 1));
340
341 /*
342 * dump database to file
343 */
344 if (output)
345 fp = fopen(output, "wb");
346 else
347 fp = stdout;
348
349 if (fp == NULL) {
350 perror("fopen");
351 exit(1);
352 }
353
354 /* dump database body */
355 size = _db_factory_calc_size(df);
356 serialized = malloc(size);
357 _region_init(&data, serialized, size);
358 CHKERR(ret, _db_factory_serialize,
359 (df, _CITRUS_MAPPER_STD_MAGIC, &data));
360 if (fwrite(serialized, size, 1, fp) != 1)
361 err(EXIT_FAILURE, "fwrite");
362
363 fclose(fp);
364 }
365
366 static void
367 /*ARGSUSED*/
368 set_type(int type)
369 {
370
371 if (done_flag & DF_TYPE) {
372 warning("TYPE is duplicated. ignored this one");
373 return;
374 }
375
376 map_type = type;
377
378 done_flag |= DF_TYPE;
379 }
380 static void
381 /*ARGSUSED*/
382 set_name(char *str)
383 {
384
385 if (done_flag & DF_NAME) {
386 warning("NAME is duplicated. ignored this one");
387 return;
388 }
389
390 map_name = str;
391
392 done_flag |= DF_NAME;
393 }
394 static void
395 set_src_zone(const zone_t *zone)
396 {
397
398 if (done_flag & DF_SRC_ZONE) {
399 warning("SRC_ZONE is duplicated. ignored this one");
400 return;
401 }
402
403 /* sanity check */
404 if (zone->col_bits<1 || zone->col_bits>32) {
405 goto bad;
406 }
407
408 if (zone->col_bits!=32)
409 colmask = (1 << zone->col_bits)-1;
410 else
411 colmask = ~0;
412 rowmask = ~colmask;
413 if (zone->col_begin > zone->col_end ||
414 zone->row_begin > zone->row_end ||
415 (zone->col_begin & rowmask)!=0 ||
416 (zone->col_end & rowmask)!=0 ||
417 ((zone->row_begin << zone->col_bits) & colmask)!=0 ||
418 ((zone->row_end << zone->col_bits) & colmask)!=0) {
419 bad:
420 yyerror("Illegal argument for SRC_ZONE");
421 }
422
423 src_zone = *zone;
424
425 done_flag |= DF_SRC_ZONE;
426
427 return;
428 }
429 static void
430 set_dst_invalid(u_int32_t val)
431 {
432
433 if (done_flag & DF_DST_INVALID) {
434 warning("DST_INVALID is duplicated. ignored this one");
435 return;
436 }
437
438 dst_invalid = val;
439
440 done_flag |= DF_DST_INVALID;
441 }
442 static void
443 set_dst_unit_bits(u_int32_t val)
444 {
445
446 if (done_flag & DF_DST_UNIT_BITS) {
447 warning("DST_UNIT_BITS is duplicated. ignored this one");
448 return;
449 }
450
451 switch (val) {
452 case 8:
453 putfunc = &put8;
454 dst_unit_bits = val;
455 break;
456 case 16:
457 putfunc = &put16;
458 dst_unit_bits = val;
459 break;
460 case 32:
461 putfunc = &put32;
462 dst_unit_bits = val;
463 break;
464 default:
465 yyerror("Illegal argument for DST_UNIT_BITS");
466 }
467 done_flag |= DF_DST_UNIT_BITS;
468 }
469 static void
470 calc_next(void)
471 {
472 src_next++;
473 if (check_src(src_next, src_next))
474 next_valid = 0;
475 else
476 next_valid = 1;
477 }
478 static int
479 check_src(u_int32_t begin, u_int32_t end)
480 {
481 u_int32_t b_row = 0, e_row = 0, b_col, e_col;
482
483 b_col = begin & colmask;
484 e_col = end & colmask;
485 if (src_zone.col_bits != 32) {
486 b_row = begin >> src_zone.col_bits;
487 e_row = end >> src_zone.col_bits;
488 }
489
490 if (b_row != e_row ||
491 b_row < src_zone.row_begin ||
492 b_row > src_zone.row_end ||
493 e_row < src_zone.row_begin ||
494 e_row > src_zone.row_end ||
495 b_col < src_zone.col_begin ||
496 b_col > src_zone.col_end ||
497 e_col < src_zone.col_begin ||
498 e_col > src_zone.col_end ||
499 b_col>e_col) {
500 return (-1);
501 }
502 return (0);
503 }
504 static void
505 store(const linear_zone_t *lz, u_int32_t dst, int inc)
506 {
507 u_int32_t row=0, col, ofs, i;
508
509 if (src_zone.col_bits != 32)
510 row = lz->begin >> src_zone.col_bits;
511 col = lz->begin & colmask;
512 ofs =
513 (row-src_zone.row_begin)*(src_zone.col_end-src_zone.col_begin+1) +
514 (col-src_zone.col_begin);
515 for (i=lz->end-lz->begin+1; i>0; i--) {
516 (*putfunc)(table, ofs++, dst);
517 if (inc)
518 dst++;
519 }
520 }
521
522 static void
523 do_mkdb(FILE *in)
524 {
525 int ret;
526 FILE *out;
527
528 /* dump DB to file */
529 if (output)
530 out = fopen(output, "wb");
531 else
532 out = stdout;
533
534 if (out==NULL)
535 err(EXIT_FAILURE, "fopen");
536
537 ret = _lookup_factory_convert(out, in);
538 fclose(out);
539 if (ret && output)
540 unlink(output); /* dump failure */
541 }
542
543 static void
544 do_mkpv(FILE *in)
545 {
546 int ret;
547 FILE *out;
548
549 /* dump pivot to file */
550 if (output)
551 out = fopen(output, "wb");
552 else
553 out = stdout;
554
555 if (out==NULL)
556 err(EXIT_FAILURE, "fopen");
557
558 ret = _pivot_factory_convert(out, in);
559 fclose(out);
560 if (ret && output)
561 unlink(output); /* dump failure */
562 if (ret)
563 errx(EXIT_FAILURE, "%s\n", strerror(ret));
564 }
565
566 static void
567 usage(void)
568 {
569 warnx("usage: \n"
570 "\t%s [-d] [-o outfile] [infile]\n"
571 "\t%s -m [-d] [-o outfile] [infile]\n"
572 "\t%s -p [-d] [-o outfile] [infile]\n",
573 getprogname(), getprogname(), getprogname());
574 exit(1);
575 }
576
577 int
578 main(int argc, char **argv)
579 {
580 int ch;
581 extern char *optarg;
582 extern int optind;
583 FILE *in;
584 int mkdb = 0, mkpv = 0;
585
586 while ((ch=getopt(argc, argv, "do:mp")) != EOF) {
587 switch (ch) {
588 case 'd':
589 debug=1;
590 break;
591 case 'o':
592 output = strdup(optarg);
593 break;
594 case 'm':
595 mkdb = 1;
596 break;
597 case 'p':
598 mkpv = 1;
599 break;
600 default:
601 usage();
602 }
603 }
604
605 argc-=optind;
606 argv+=optind;
607 switch (argc) {
608 case 0:
609 in = stdin;
610 break;
611 case 1:
612 in = fopen(argv[0], "r");
613 if (!in)
614 err(EXIT_FAILURE, argv[0]);
615 break;
616 default:
617 usage();
618 }
619
620 if (mkdb)
621 do_mkdb(in);
622 else if (mkpv)
623 do_mkpv(in);
624 else {
625 yyin = in;
626 yyparse();
627 }
628
629 return (0);
630 }
631