]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - usr.bin/mkcsmapper/yacc.y
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / usr.bin / mkcsmapper / yacc.y
1 /* $FreeBSD$ */
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
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, line_number);
207 }
208
209 int
210 yyerror(const char *s)
211 {
212
213         warning(s);
214         exit(1);
215 }
216
217 void
218 put8(void *ptr, size_t ofs, u_int32_t val)
219 {
220
221         *((u_int8_t *)ptr + ofs) = val;
222 }
223
224 void
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
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
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
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
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
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
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*/
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*/
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
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 = 1 << (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
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
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
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
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
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
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
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
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
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
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
671 usage(void)
672 {
673         warnx("usage: \n"
674             "\t%s [-d] [-o outfile] [infile]\n"
675             "\t%s -m [-d] [-o outfile] [infile]\n"
676             "\t%s -p [-d] [-o outfile] [infile]\n",
677             getprogname(), getprogname(), getprogname());
678         exit(1);
679 }
680
681 int
682 main(int argc, char **argv)
683 {
684         FILE *in = NULL;
685         int ch, mkdb = 0, mkpv = 0;
686
687         while ((ch = getopt(argc, argv, "do:mp")) != EOF) {
688                 switch (ch) {
689                 case 'd':
690                         debug = 1;
691                         break;
692                 case 'o':
693                         output = strdup(optarg);
694                         break;
695                 case 'm':
696                         mkdb = 1;
697                         break;
698                 case 'p':
699                         mkpv = 1;
700                         break;
701                 default:
702                         usage();
703                 }
704         }
705
706         argc -= optind;
707         argv += optind;
708         switch (argc) {
709         case 0:
710                 in = stdin;
711                 break;
712         case 1:
713                 in = fopen(argv[0], "r");
714                 if (!in)
715                         err(EXIT_FAILURE, "%s", argv[0]);
716                 break;
717         default:
718                 usage();
719         }
720
721         if (mkdb)
722                 do_mkdb(in);
723         else if (mkpv)
724                 do_mkpv(in);
725         else {
726                 yyin = in;
727                 yyparse();
728         }
729
730         return (0);
731 }