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