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