yacc.y revision 1.3 1 /* $NetBSD: yacc.y,v 1.3 2003/10/27 00:12:43 lukem 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 #if HAVE_NBTOOL_CONFIG_H
31 #include "nbtool_config.h"
32 #endif
33
34 #include <sys/cdefs.h>
35 #if !defined(lint)
36 __RCSID("$NetBSD: yacc.y,v 1.3 2003/10/27 00:12:43 lukem Exp $");
37 #endif /* 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_ilseq, oob_mode, 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_ILSEQ 0x00000010
84 #define DF_DST_UNIT_BITS 0x00000020
85 #define DF_OOB_MODE 0x00000040
86
87 static void dump_file(void);
88 static void setup_map(void);
89 static void set_type(int);
90 static void set_name(char *);
91 static void set_src_zone(const zone_t *);
92 static void set_dst_invalid(u_int32_t);
93 static void set_dst_ilseq(u_int32_t);
94 static void set_dst_unit_bits(u_int32_t);
95 static void set_oob_mode(u_int32_t);
96 static void calc_next(void);
97 static int check_src(u_int32_t, u_int32_t);
98 static void store(const linear_zone_t *, u_int32_t, int);
99 static void put8(void *, size_t, u_int32_t);
100 static void put16(void *, size_t, u_int32_t);
101 static void put32(void *, size_t, u_int32_t);
102 %}
103
104 %union {
105 u_int32_t i_value;
106 char *s_value;
107 zone_t z_value;
108 linear_zone_t lz_value;
109 }
110
111 %token R_TYPE R_NAME R_SRC_ZONE R_DST_UNIT_BITS
112 %token R_DST_INVALID R_DST_ILSEQ
113 %token R_BEGIN_MAP R_END_MAP R_INVALID R_ROWCOL
114 %token R_ILSEQ R_OOB_MODE
115 %token R_LN
116 %token <i_value> L_IMM
117 %token <s_value> L_STRING
118
119 %type <z_value> zone
120 %type <lz_value> src
121 %type <i_value> dst types oob_mode_sel
122
123 %%
124
125 file : property mapping lns
126 { dump_file(); }
127
128 property : /* empty */
129 | property R_LN
130 | property name
131 | property type
132 | property src_zone
133 | property dst_invalid
134 | property dst_ilseq
135 | property dst_unit_bits
136 | property oob_mode
137
138 name : R_NAME L_STRING { set_name($2); $2 = NULL; }
139 type : R_TYPE types { set_type($2); }
140 types : R_ROWCOL { $$ = R_ROWCOL; }
141 src_zone : R_SRC_ZONE zone { set_src_zone(&$2); }
142 zone : L_IMM '-' L_IMM {
143 $$.row_begin = $$.row_end = 0;
144 $$.col_begin = $1; $$.col_end = $3;
145 $$.col_bits = 32;
146 }
147 | L_IMM '-' L_IMM '/' L_IMM '-' L_IMM '/' L_IMM {
148 $$.row_begin = $1; $$.row_end = $3;
149 $$.col_begin = $5; $$.col_end = $7;
150 $$.col_bits = $9;
151 }
152
153 dst_invalid : R_DST_INVALID L_IMM { set_dst_invalid($2); }
154 dst_ilseq : R_DST_ILSEQ L_IMM { set_dst_ilseq($2); }
155 dst_unit_bits : R_DST_UNIT_BITS L_IMM { set_dst_unit_bits($2); }
156 oob_mode : R_OOB_MODE oob_mode_sel { set_oob_mode($2); }
157
158 oob_mode_sel : R_INVALID { $$ = _CITRUS_MAPPER_STD_OOB_NONIDENTICAL; }
159 | R_ILSEQ { $$ = _CITRUS_MAPPER_STD_OOB_ILSEQ; }
160
161 mapping : begin_map map_elems R_END_MAP
162 begin_map : R_BEGIN_MAP lns { setup_map(); }
163
164 map_elems : /* empty */
165 | map_elems map_elem lns
166
167 map_elem : src '=' dst
168 { store(&$1, $3, 0); }
169 | src '=' L_IMM '-'
170 { store(&$1, $3, 1); }
171 dst : L_IMM
172 {
173 $$ = $1;
174 }
175 | R_INVALID
176 {
177 $$ = dst_invalid;
178 }
179 | R_ILSEQ
180 {
181 $$ = dst_ilseq;
182 }
183
184 src : /* empty */
185 {
186 if (!next_valid) {
187 yyerror("cannot omit src");
188 }
189 $$.begin = $$.end = src_next;
190 calc_next();
191 }
192 | L_IMM
193 {
194 if (check_src($1, $1)) {
195 yyerror("illegal zone");
196 }
197 $$.begin = $$.end = $1;
198 src_next = $1;
199 calc_next();
200 }
201 | L_IMM '-' L_IMM
202 {
203 if (check_src($1, $3)) {
204 yyerror("illegal zone");
205 }
206 $$.begin = $1; $$.end = $3;
207 src_next = $3;
208 calc_next();
209 }
210 | '-' L_IMM
211 {
212 if (!next_valid) {
213 yyerror("cannot omit src");
214 }
215 if (check_src(src_next, $2)) {
216 yyerror("illegal zone");
217 }
218 $$.begin = src_next; $$.end = $2;
219 src_next = $2;
220 calc_next();
221 }
222 lns : R_LN
223 | lns R_LN
224
225 %%
226
227 static void
228 warning(const char *s)
229 {
230 fprintf(stderr, "%s in %d\n", s, line_number);
231 }
232
233 int
234 yyerror(const char *s)
235 {
236 warning(s);
237 exit(1);
238 }
239
240 void
241 put8(void *ptr, size_t ofs, u_int32_t val)
242 {
243 *((u_int8_t *)ptr + ofs) = val;
244 }
245
246 void
247 put16(void *ptr, size_t ofs, u_int32_t val)
248 {
249 u_int16_t oval = htons(val);
250 memcpy((u_int16_t *)ptr + ofs, &oval, 2);
251 }
252
253 void
254 put32(void *ptr, size_t ofs, u_int32_t val)
255 {
256 u_int32_t oval = htonl(val);
257 memcpy((u_int32_t *)ptr + ofs, &oval, 4);
258 }
259
260 static void
261 alloc_table(void)
262 {
263 size_t i;
264 u_int32_t val;
265
266 table_size =
267 (src_zone.row_end-src_zone.row_begin+1)*
268 (src_zone.col_end-src_zone.col_begin+1);
269 table = malloc(table_size*dst_unit_bits/8);
270 if (!table) {
271 perror("malloc");
272 exit(1);
273 }
274
275 switch (oob_mode) {
276 case _CITRUS_MAPPER_STD_OOB_NONIDENTICAL:
277 val = dst_invalid;
278 break;
279 case _CITRUS_MAPPER_STD_OOB_ILSEQ:
280 val = dst_ilseq;
281 break;
282 default:
283 _DIAGASSERT(0);
284 }
285 for (i=0; i<table_size; i++)
286 (*putfunc)(table, i, val);
287 }
288
289 static void
290 setup_map(void)
291 {
292
293 if ((done_flag & DF_SRC_ZONE)==0) {
294 fprintf(stderr, "SRC_ZONE is mandatory.\n");
295 exit(1);
296 }
297 if ((done_flag & DF_DST_UNIT_BITS)==0) {
298 fprintf(stderr, "DST_UNIT_BITS is mandatory.\n");
299 exit(1);
300 }
301
302 if ((done_flag & DF_DST_INVALID) == 0)
303 dst_invalid = 0xFFFFFFFF;
304 if ((done_flag & DF_DST_ILSEQ) == 0)
305 dst_ilseq = 0xFFFFFFFE;
306 if ((done_flag & DF_OOB_MODE) == 0)
307 oob_mode = _CITRUS_MAPPER_STD_OOB_NONIDENTICAL;
308
309 alloc_table();
310 }
311
312 static void
313 create_rowcol_info(struct _region *r)
314 {
315 void *ptr;
316 size_t ofs;
317
318 ofs = 0;
319 ptr = malloc(_CITRUS_MAPPER_STD_ROWCOL_INFO_SIZE);
320 if (ptr==NULL)
321 err(EXIT_FAILURE, "malloc");
322
323 put32(ptr, ofs, src_zone.col_bits); ofs++;
324 put32(ptr, ofs, dst_invalid); ofs++;
325 put32(ptr, ofs, src_zone.row_begin); ofs++;
326 put32(ptr, ofs, src_zone.row_end); ofs++;
327 put32(ptr, ofs, src_zone.col_begin); ofs++;
328 put32(ptr, ofs, src_zone.col_end); ofs++;
329 put32(ptr, ofs, dst_unit_bits); ofs++;
330 put32(ptr, ofs, 0); /* pad */
331
332 _region_init(r, ptr, _CITRUS_MAPPER_STD_ROWCOL_INFO_SIZE);
333 }
334
335 static void
336 create_rowcol_ext_ilseq_info(struct _region *r)
337 {
338 void *ptr;
339 size_t ofs;
340
341 ofs = 0;
342 ptr = malloc(_CITRUS_MAPPER_STD_ROWCOL_EXT_ILSEQ_SIZE);
343 if (ptr==NULL)
344 err(EXIT_FAILURE, "malloc");
345
346 put32(ptr, ofs, oob_mode); ofs++;
347 put32(ptr, ofs, dst_ilseq); ofs++;
348
349 _region_init(r, ptr, _CITRUS_MAPPER_STD_ROWCOL_EXT_ILSEQ_SIZE);
350 }
351
352 #define CHKERR(ret, func, a) \
353 do { \
354 ret = func a; \
355 if (ret) \
356 errx(EXIT_FAILURE, "%s: %s", #func, strerror(ret)); \
357 } while (/*CONSTCOND*/0)
358
359 static void
360 dump_file(void)
361 {
362 FILE *fp;
363 int ret;
364 struct _db_factory *df;
365 struct _region data;
366 void *serialized;
367 size_t size;
368
369 /*
370 * build database
371 */
372 CHKERR(ret, _db_factory_create, (&df, _db_hash_std, NULL));
373
374 /* store type */
375 CHKERR(ret, _db_factory_addstr_by_s,
376 (df, _CITRUS_MAPPER_STD_SYM_TYPE,
377 _CITRUS_MAPPER_STD_TYPE_ROWCOL));
378
379 /* store info */
380 create_rowcol_info(&data);
381 CHKERR(ret, _db_factory_add_by_s,
382 (df, _CITRUS_MAPPER_STD_SYM_INFO, &data, 1));
383
384 /* ilseq extension */
385 create_rowcol_ext_ilseq_info(&data);
386 CHKERR(ret, _db_factory_add_by_s,
387 (df, _CITRUS_MAPPER_STD_SYM_ROWCOL_EXT_ILSEQ, &data, 1));
388
389 /* store table */
390 _region_init(&data, table, table_size*dst_unit_bits/8);
391 CHKERR(ret, _db_factory_add_by_s,
392 (df, _CITRUS_MAPPER_STD_SYM_TABLE, &data, 1));
393
394 /*
395 * dump database to file
396 */
397 if (output)
398 fp = fopen(output, "wb");
399 else
400 fp = stdout;
401
402 if (fp == NULL) {
403 perror("fopen");
404 exit(1);
405 }
406
407 /* dump database body */
408 size = _db_factory_calc_size(df);
409 serialized = malloc(size);
410 _region_init(&data, serialized, size);
411 CHKERR(ret, _db_factory_serialize,
412 (df, _CITRUS_MAPPER_STD_MAGIC, &data));
413 if (fwrite(serialized, size, 1, fp) != 1)
414 err(EXIT_FAILURE, "fwrite");
415
416 fclose(fp);
417 }
418
419 static void
420 /*ARGSUSED*/
421 set_type(int type)
422 {
423
424 if (done_flag & DF_TYPE) {
425 warning("TYPE is duplicated. ignored this one");
426 return;
427 }
428
429 map_type = type;
430
431 done_flag |= DF_TYPE;
432 }
433 static void
434 /*ARGSUSED*/
435 set_name(char *str)
436 {
437
438 if (done_flag & DF_NAME) {
439 warning("NAME is duplicated. ignored this one");
440 return;
441 }
442
443 map_name = str;
444
445 done_flag |= DF_NAME;
446 }
447 static void
448 set_src_zone(const zone_t *zone)
449 {
450
451 if (done_flag & DF_SRC_ZONE) {
452 warning("SRC_ZONE is duplicated. ignored this one");
453 return;
454 }
455
456 /* sanity check */
457 if (zone->col_bits<1 || zone->col_bits>32) {
458 goto bad;
459 }
460
461 if (zone->col_bits!=32)
462 colmask = (1 << zone->col_bits)-1;
463 else
464 colmask = ~0;
465 rowmask = ~colmask;
466 if (zone->col_begin > zone->col_end ||
467 zone->row_begin > zone->row_end ||
468 (zone->col_begin & rowmask)!=0 ||
469 (zone->col_end & rowmask)!=0 ||
470 ((zone->row_begin << zone->col_bits) & colmask)!=0 ||
471 ((zone->row_end << zone->col_bits) & colmask)!=0) {
472 bad:
473 yyerror("Illegal argument for SRC_ZONE");
474 }
475
476 src_zone = *zone;
477
478 done_flag |= DF_SRC_ZONE;
479
480 return;
481 }
482 static void
483 set_dst_invalid(u_int32_t val)
484 {
485
486 if (done_flag & DF_DST_INVALID) {
487 warning("DST_INVALID is duplicated. ignored this one");
488 return;
489 }
490
491 dst_invalid = val;
492
493 done_flag |= DF_DST_INVALID;
494 }
495 static void
496 set_dst_ilseq(u_int32_t val)
497 {
498
499 if (done_flag & DF_DST_ILSEQ) {
500 warning("DST_ILSEQ is duplicated. ignored this one");
501 return;
502 }
503
504 dst_ilseq = val;
505
506 done_flag |= DF_DST_ILSEQ;
507 }
508 static void
509 set_oob_mode(u_int32_t val)
510 {
511
512 if (done_flag & DF_OOB_MODE) {
513 warning("OOB_MODE is duplicated. ignored this one");
514 return;
515 }
516
517 oob_mode = val;
518
519 done_flag |= DF_OOB_MODE;
520 }
521 static void
522 set_dst_unit_bits(u_int32_t val)
523 {
524
525 if (done_flag & DF_DST_UNIT_BITS) {
526 warning("DST_UNIT_BITS is duplicated. ignored this one");
527 return;
528 }
529
530 switch (val) {
531 case 8:
532 putfunc = &put8;
533 dst_unit_bits = val;
534 break;
535 case 16:
536 putfunc = &put16;
537 dst_unit_bits = val;
538 break;
539 case 32:
540 putfunc = &put32;
541 dst_unit_bits = val;
542 break;
543 default:
544 yyerror("Illegal argument for DST_UNIT_BITS");
545 }
546 done_flag |= DF_DST_UNIT_BITS;
547 }
548 static void
549 calc_next(void)
550 {
551 src_next++;
552 if (check_src(src_next, src_next))
553 next_valid = 0;
554 else
555 next_valid = 1;
556 }
557 static int
558 check_src(u_int32_t begin, u_int32_t end)
559 {
560 u_int32_t b_row = 0, e_row = 0, b_col, e_col;
561
562 b_col = begin & colmask;
563 e_col = end & colmask;
564 if (src_zone.col_bits != 32) {
565 b_row = begin >> src_zone.col_bits;
566 e_row = end >> src_zone.col_bits;
567 }
568
569 if (b_row != e_row ||
570 b_row < src_zone.row_begin ||
571 b_row > src_zone.row_end ||
572 e_row < src_zone.row_begin ||
573 e_row > src_zone.row_end ||
574 b_col < src_zone.col_begin ||
575 b_col > src_zone.col_end ||
576 e_col < src_zone.col_begin ||
577 e_col > src_zone.col_end ||
578 b_col>e_col) {
579 return (-1);
580 }
581 return (0);
582 }
583 static void
584 store(const linear_zone_t *lz, u_int32_t dst, int inc)
585 {
586 u_int32_t row=0, col, ofs, i;
587
588 if (src_zone.col_bits != 32)
589 row = lz->begin >> src_zone.col_bits;
590 col = lz->begin & colmask;
591 ofs =
592 (row-src_zone.row_begin)*(src_zone.col_end-src_zone.col_begin+1) +
593 (col-src_zone.col_begin);
594 for (i=lz->end-lz->begin+1; i>0; i--) {
595 (*putfunc)(table, ofs++, dst);
596 if (inc)
597 dst++;
598 }
599 }
600
601 static void
602 do_mkdb(FILE *in)
603 {
604 int ret;
605 FILE *out;
606
607 /* dump DB to file */
608 if (output)
609 out = fopen(output, "wb");
610 else
611 out = stdout;
612
613 if (out==NULL)
614 err(EXIT_FAILURE, "fopen");
615
616 ret = _lookup_factory_convert(out, in);
617 fclose(out);
618 if (ret && output)
619 unlink(output); /* dump failure */
620 }
621
622 static void
623 do_mkpv(FILE *in)
624 {
625 int ret;
626 FILE *out;
627
628 /* dump pivot to file */
629 if (output)
630 out = fopen(output, "wb");
631 else
632 out = stdout;
633
634 if (out==NULL)
635 err(EXIT_FAILURE, "fopen");
636
637 ret = _pivot_factory_convert(out, in);
638 fclose(out);
639 if (ret && output)
640 unlink(output); /* dump failure */
641 if (ret)
642 errx(EXIT_FAILURE, "%s\n", strerror(ret));
643 }
644
645 static void
646 usage(void)
647 {
648 warnx("usage: \n"
649 "\t%s [-d] [-o outfile] [infile]\n"
650 "\t%s -m [-d] [-o outfile] [infile]\n"
651 "\t%s -p [-d] [-o outfile] [infile]\n",
652 getprogname(), getprogname(), getprogname());
653 exit(1);
654 }
655
656 int
657 main(int argc, char **argv)
658 {
659 int ch;
660 extern char *optarg;
661 extern int optind;
662 FILE *in;
663 int mkdb = 0, mkpv = 0;
664
665 while ((ch=getopt(argc, argv, "do:mp")) != EOF) {
666 switch (ch) {
667 case 'd':
668 debug=1;
669 break;
670 case 'o':
671 output = strdup(optarg);
672 break;
673 case 'm':
674 mkdb = 1;
675 break;
676 case 'p':
677 mkpv = 1;
678 break;
679 default:
680 usage();
681 }
682 }
683
684 argc-=optind;
685 argv+=optind;
686 switch (argc) {
687 case 0:
688 in = stdin;
689 break;
690 case 1:
691 in = fopen(argv[0], "r");
692 if (!in)
693 err(EXIT_FAILURE, argv[0]);
694 break;
695 default:
696 usage();
697 }
698
699 if (mkdb)
700 do_mkdb(in);
701 else if (mkpv)
702 do_mkpv(in);
703 else {
704 yyin = in;
705 yyparse();
706 }
707
708 return (0);
709 }
710