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