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