dhcpcd: update README.DRAGONFLY
[dragonfly.git] / usr.bin / mkcsmapper / yacc.y
blob9af02cc16a2ab6f90f5bc1ea972c520fe8b7439c
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 $ */
4 %{
5 /*-
6 * Copyright (c)2003, 2006 Citrus Project,
7 * All rights reserved.
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.
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.
31 #include <sys/cdefs.h>
32 #include <sys/types.h>
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>
44 #include "ldef.h"
46 #ifndef __packed
47 #define __packed
48 #endif
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"
59 extern FILE *yyin;
61 int debug = 0;
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;
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
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);
101 #if YYPATCH < 20180510
102 int yylex(void);
103 #endif
106 %union {
107 u_int32_t i_value;
108 char *s_value;
109 linear_zone_t lz_value;
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
120 %type <lz_value> src
121 %type <i_value> dst types oob_mode_sel zone
125 file : property mapping lns
126 { dump_file(); }
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
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); }
143 ranges : /* empty */
144 | ranges range '/'
146 src_zone : R_SRC_ZONE zone { set_src_zone($2); }
147 zone : range {
148 $$ = 32;
150 | range '/' range '/' ranges L_IMM {
151 $$ = $6;
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); }
159 oob_mode_sel : R_INVALID { $$ = _CITRUS_MAPPER_STD_OOB_NONIDENTICAL; }
160 | R_ILSEQ { $$ = _CITRUS_MAPPER_STD_OOB_ILSEQ; }
162 mapping : begin_map map_elems R_END_MAP
163 begin_map : R_BEGIN_MAP lns { setup_map(); }
165 map_elems : /* empty */
166 | map_elems map_elem lns
168 map_elem : src '=' dst
169 { store(&$1, $3, 0); }
170 | src '=' L_IMM '-'
171 { store(&$1, $3, 1); }
172 dst : L_IMM
174 $$ = $1;
176 | R_INVALID
178 $$ = dst_invalid;
180 | R_ILSEQ
182 $$ = dst_ilseq;
185 src : /* empty */
187 set_src(&$$, src_next, src_next);
189 | L_IMM
191 set_src(&$$, $1, $1);
193 | L_IMM '-' L_IMM
195 set_src(&$$, $1, $3);
197 | '-' L_IMM
199 set_src(&$$, src_next, $2);
201 lns : R_LN
202 | lns R_LN
206 static void
207 warning(const char *s)
210 fprintf(stderr, "%s in %d\n", s, linenumber);
214 yyerror(const char *s)
217 warning(s);
218 exit(1);
221 void
222 put8(void *ptr, size_t ofs, u_int32_t val)
225 *((u_int8_t *)ptr + ofs) = val;
228 void
229 put16(void *ptr, size_t ofs, u_int32_t val)
232 u_int16_t oval = htons(val);
233 memcpy((u_int16_t *)ptr + ofs, &oval, 2);
236 void
237 put32(void *ptr, size_t ofs, u_int32_t val)
240 u_int32_t oval = htonl(val);
241 memcpy((u_int32_t *)ptr + ofs, &oval, 4);
244 static void
245 alloc_table(void)
247 linear_zone_t *p;
248 size_t i;
249 uint32_t val = 0;
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;
258 table = (void *)malloc(table_size * dst_unit_bits / 8);
259 if (table == NULL) {
260 perror("malloc");
261 exit(1);
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;
274 for (i = 0; i < table_size; i++)
275 (*putfunc)(table, i, val);
278 static void
279 setup_map(void)
282 if ((done_flag & DF_SRC_ZONE)==0) {
283 fprintf(stderr, "SRC_ZONE is mandatory.\n");
284 exit(1);
286 if ((done_flag & DF_DST_UNIT_BITS)==0) {
287 fprintf(stderr, "DST_UNIT_BITS is mandatory.\n");
288 exit(1);
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;
298 alloc_table();
301 static void
302 create_rowcol_info(struct _region *r)
304 void *ptr;
305 size_t i, len, ofs;
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++;
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;
326 for (i = 0; i < rowcol_len; ++i) {
327 put32(ptr, ofs, rowcol[i].begin); ofs++;
328 put32(ptr, ofs, rowcol[i].end); ofs++;
330 put32(ptr, ofs, dst_unit_bits); ofs++;
331 put32(ptr, ofs, len); ofs++;
333 _region_init(r, ptr, ofs * 4);
337 static void
338 create_rowcol_ext_ilseq_info(struct _region *r)
340 void *ptr;
341 size_t ofs;
343 ofs = 0;
344 ptr = malloc(_CITRUS_MAPPER_STD_ROWCOL_EXT_ILSEQ_SIZE);
345 if (ptr == NULL)
346 err(EXIT_FAILURE, "malloc");
348 put32(ptr, ofs, oob_mode); ofs++;
349 put32(ptr, ofs, dst_ilseq); ofs++;
351 _region_init(r, ptr, _CITRUS_MAPPER_STD_ROWCOL_EXT_ILSEQ_SIZE);
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)
361 static void
362 dump_file(void)
364 struct _db_factory *df;
365 struct _region data;
366 void *serialized;
367 FILE *fp;
368 size_t size;
369 int ret;
372 * build database
374 CHKERR(ret, _db_factory_create, (&df, _db_hash_std, NULL));
376 /* store type */
377 CHKERR(ret, _db_factory_addstr_by_s,
378 (df, _CITRUS_MAPPER_STD_SYM_TYPE, _CITRUS_MAPPER_STD_TYPE_ROWCOL));
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));
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));
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));
396 * dump database to file
398 fp = output ? fopen(output, "wb") : stdout;
400 if (fp == NULL) {
401 perror("fopen");
402 exit(1);
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");
414 fclose(fp);
417 static void
418 /*ARGSUSED*/
419 set_type(int type)
422 if (done_flag & DF_TYPE) {
423 warning("TYPE is duplicated. ignored this one");
424 return;
427 map_type = type;
429 done_flag |= DF_TYPE;
432 static void
433 /*ARGSUSED*/
434 set_name(char *str)
437 if (done_flag & DF_NAME) {
438 warning("NAME is duplicated. ignored this one");
439 return;
442 map_name = str;
444 done_flag |= DF_NAME;
447 static void
448 set_src_zone(u_int32_t val)
450 linear_zone_t *p;
451 size_t i;
453 if (done_flag & DF_SRC_ZONE) {
454 warning("SRC_ZONE is duplicated. ignored this one");
455 return;
457 rowcol_bits = val;
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;
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;
475 done_flag |= DF_SRC_ZONE;
476 return;
478 bad:
479 yyerror("Illegal argument for SRC_ZONE");
482 static void
483 set_dst_invalid(u_int32_t val)
486 if (done_flag & DF_DST_INVALID) {
487 warning("DST_INVALID is duplicated. ignored this one");
488 return;
491 dst_invalid = val;
493 done_flag |= DF_DST_INVALID;
496 static void
497 set_dst_ilseq(u_int32_t val)
500 if (done_flag & DF_DST_ILSEQ) {
501 warning("DST_ILSEQ is duplicated. ignored this one");
502 return;
505 dst_ilseq = val;
507 done_flag |= DF_DST_ILSEQ;
510 static void
511 set_oob_mode(u_int32_t val)
514 if (done_flag & DF_OOB_MODE) {
515 warning("OOB_MODE is duplicated. ignored this one");
516 return;
519 oob_mode = val;
521 done_flag |= DF_OOB_MODE;
524 static void
525 set_dst_unit_bits(u_int32_t val)
528 if (done_flag & DF_DST_UNIT_BITS) {
529 warning("DST_UNIT_BITS is duplicated. ignored this one");
530 return;
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");
549 done_flag |= DF_DST_UNIT_BITS;
552 static int
553 check_src(u_int32_t begin, u_int32_t end)
555 linear_zone_t *p;
556 size_t i;
557 u_int32_t m, n;
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);
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);
573 if (begin < end) {
574 n = end & rowcol_mask;
575 --p;
576 if (n < p->begin || n > p->end)
577 return (1);
579 return (0);
582 static void
583 store(const linear_zone_t *lz, u_int32_t dst, int inc)
585 linear_zone_t *p;
586 size_t i, ofs;
587 u_int32_t n;
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;
595 n = lz->width;
596 while (n-- > 0) {
597 (*putfunc)(table, ofs++, dst);
598 if (inc)
599 dst++;
603 static void
604 set_range(u_int32_t begin, u_int32_t end)
606 linear_zone_t *p;
608 if (rowcol_len >= _CITRUS_MAPPER_STD_ROWCOL_MAX)
609 goto bad;
610 p = &rowcol[rowcol_len++];
612 if (begin > end)
613 goto bad;
614 p->begin = begin, p->end = end;
615 p->width = end - begin + 1;
617 return;
619 bad:
620 yyerror("Illegal argument for SRC_ZONE");
623 static void
624 set_src(linear_zone_t *lz, u_int32_t begin, u_int32_t end)
627 if (check_src(begin, end) != 0)
628 yyerror("illegal zone");
630 lz->begin = begin, lz->end = end;
631 lz->width = end - begin + 1;
633 src_next = end + 1;
636 static void
637 do_mkdb(FILE *in)
639 FILE *out;
640 int ret;
642 /* dump DB to file */
643 out = output ? fopen(output, "wb") : stdout;
645 if (out == NULL)
646 err(EXIT_FAILURE, "fopen");
648 ret = _lookup_factory_convert(out, in);
649 fclose(out);
650 if (ret && output)
651 unlink(output); /* dump failure */
654 static void
655 do_mkpv(FILE *in)
657 FILE *out;
658 int ret;
660 /* dump pivot to file */
661 out = output ? fopen(output, "wb") : stdout;
663 if (out == NULL)
664 err(EXIT_FAILURE, "fopen");
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));
674 static void
675 usage(void)
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);
686 main(int argc, char **argv)
688 FILE *in = NULL;
689 int ch, mkdb = 0, mkpv = 0;
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();
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();
725 if (mkdb)
726 do_mkdb(in);
727 else if (mkpv)
728 do_mkpv(in);
729 else {
730 yyin = in;
731 yyparse();
734 return (0);