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