xref: /netbsd-src/crypto/external/bsd/heimdal/dist/lib/sl/slc-gram.y (revision 48fb7bfab72acd4281a53bbee5ccf3f809019e75)
1 /*	$NetBSD: slc-gram.y,v 1.1.1.1 2011/04/13 18:15:44 elric Exp $	*/
2 
3 %{
4 /*
5  * Copyright (c) 2004-2006 Kungliga Tekniska Högskolan
6  * (Royal Institute of Technology, Stockholm, Sweden).
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  *
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  *
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  * 3. Neither the name of the Institute nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  */
36 
37 #include <config.h>
38 
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <err.h>
42 #include <ctype.h>
43 #include <limits.h>
44 #include <getarg.h>
45 #include <vers.h>
46 #include <roken.h>
47 
48 #include "slc.h"
49 extern FILE *yyin;
50 extern struct assignment *assignment;
51 
52 /* Declarations for Bison:
53  */
54 #define YYMALLOC        malloc
55 #define YYFREE          free
56 
57 %}
58 
59 %union {
60 	char *string;
61 	struct assignment *assignment;
62 }
63 
64 %token <string> LITERAL
65 %token <string> STRING
66 %type <assignment> assignment assignments
67 
68 %start start
69 
70 %%
71 
72 start		: assignments
73 		{
74 			assignment = $1;
75 		}
76 		;
77 
78 assignments	: assignment assignments
79 		{
80 			$1->next = $2;
81 			$$ = $1;
82 		}
83 		| assignment
84 		;
85 
86 assignment	: LITERAL '=' STRING
87 		{
88 			$$ = malloc(sizeof(*$$));
89 			$$->name = $1;
90 			$$->type = a_value;
91 			$$->lineno = lineno;
92 			$$->u.value = $3;
93 			$$->next = NULL;
94 		}
95 		| LITERAL '=' '{' assignments '}'
96 		{
97 			$$ = malloc(sizeof(*$$));
98 			$$->name = $1;
99 			$$->type = a_assignment;
100 			$$->lineno = lineno;
101 			$$->u.assignment = $4;
102 			$$->next = NULL;
103 		}
104 		;
105 
106 %%
107 char *filename;
108 FILE *cfile, *hfile;
109 int error_flag;
110 struct assignment *assignment;
111 
112 
113 static void
114 ex(struct assignment *a, const char *fmt, ...)
115 {
116     va_list ap;
117     fprintf(stderr, "%s:%d: ", a->name, a->lineno);
118     va_start(ap, fmt);
119     vfprintf(stderr, fmt, ap);
120     va_end(ap);
121     fprintf(stderr, "\n");
122 }
123 
124 
125 
126 static int
127 check_option(struct assignment *as)
128 {
129     struct assignment *a;
130     int seen_long = 0;
131     int seen_name = 0;
132     int seen_short = 0;
133     int seen_type = 0;
134     int seen_argument = 0;
135     int seen_help = 0;
136     int seen_default = 0;
137     int ret = 0;
138 
139     for(a = as; a != NULL; a = a->next) {
140 	if(strcmp(a->name, "long") == 0)
141 	    seen_long++;
142 	else if(strcmp(a->name, "short") == 0)
143 	    seen_short++;
144 	else if(strcmp(a->name, "name") == 0)
145 	    seen_name++;
146 	else if(strcmp(a->name, "type") == 0)
147 	    seen_type++;
148 	else if(strcmp(a->name, "argument") == 0)
149 	    seen_argument++;
150 	else if(strcmp(a->name, "help") == 0)
151 	    seen_help++;
152 	else if(strcmp(a->name, "default") == 0)
153 	    seen_default++;
154 	else {
155 	    ex(a, "unknown name %s", a->name);
156 	    ret++;
157 	}
158     }
159     if(seen_long == 0 && seen_short == 0) {
160 	ex(as, "neither long nor short option");
161 	ret++;
162     }
163     if (seen_long == 0 && seen_name == 0) {
164 	ex(as, "either of long or name option must be used");
165 	ret++;
166     }
167     if(seen_long > 1) {
168 	ex(as, "multiple long options");
169 	ret++;
170     }
171     if(seen_short > 1) {
172 	ex(as, "multiple short options");
173 	ret++;
174     }
175     if(seen_type > 1) {
176 	ex(as, "multiple types");
177 	ret++;
178     }
179     if(seen_argument > 1) {
180 	ex(as, "multiple arguments");
181 	ret++;
182     }
183     if(seen_help > 1) {
184 	ex(as, "multiple help strings");
185 	ret++;
186     }
187     if(seen_default > 1) {
188 	ex(as, "multiple default values");
189 	ret++;
190     }
191     return ret;
192 }
193 
194 static int
195 check_command(struct assignment *as)
196 {
197 	struct assignment *a;
198 	int seen_name = 0;
199 	int seen_function = 0;
200 	int seen_help = 0;
201 	int seen_argument = 0;
202 	int seen_minargs = 0;
203 	int seen_maxargs = 0;
204 	int ret = 0;
205 	for(a = as; a != NULL; a = a->next) {
206 		if(strcmp(a->name, "name") == 0)
207 			seen_name++;
208 		else if(strcmp(a->name, "function") == 0) {
209 			seen_function++;
210 		} else if(strcmp(a->name, "option") == 0)
211 			ret += check_option(a->u.assignment);
212 		else if(strcmp(a->name, "help") == 0) {
213 			seen_help++;
214 		} else if(strcmp(a->name, "argument") == 0) {
215 			seen_argument++;
216 		} else if(strcmp(a->name, "min_args") == 0) {
217 			seen_minargs++;
218 		} else if(strcmp(a->name, "max_args") == 0) {
219 			seen_maxargs++;
220 		} else {
221 			ex(a, "unknown name: %s", a->name);
222 			ret++;
223 		}
224 	}
225 	if(seen_name == 0) {
226 		ex(as, "no command name");
227 		ret++;
228 	}
229 	if(seen_function > 1) {
230 		ex(as, "multiple function names");
231 		ret++;
232 	}
233 	if(seen_help > 1) {
234 		ex(as, "multiple help strings");
235 		ret++;
236 	}
237 	if(seen_argument > 1) {
238 		ex(as, "multiple argument strings");
239 		ret++;
240 	}
241 	if(seen_minargs > 1) {
242 		ex(as, "multiple min_args strings");
243 		ret++;
244 	}
245 	if(seen_maxargs > 1) {
246 		ex(as, "multiple max_args strings");
247 		ret++;
248 	}
249 
250 	return ret;
251 }
252 
253 static int
254 check(struct assignment *as)
255 {
256     struct assignment *a;
257     int ret = 0;
258     for(a = as; a != NULL; a = a->next) {
259 	if(strcmp(a->name, "command")) {
260 	    fprintf(stderr, "unknown type %s line %d\n", a->name, a->lineno);
261 	    ret++;
262 	    continue;
263 	}
264 	if(a->type != a_assignment) {
265 	    fprintf(stderr, "bad command definition %s line %d\n", a->name, a->lineno);
266 	    ret++;
267 	    continue;
268 	}
269 	ret += check_command(a->u.assignment);
270     }
271     return ret;
272 }
273 
274 static struct assignment *
275 find_next(struct assignment *as, const char *name)
276 {
277     for(as = as->next; as != NULL; as = as->next) {
278 	if(strcmp(as->name, name) == 0)
279 	    return as;
280     }
281     return NULL;
282 }
283 
284 static struct assignment *
285 find(struct assignment *as, const char *name)
286 {
287     for(; as != NULL; as = as->next) {
288 	if(strcmp(as->name, name) == 0)
289 	    return as;
290     }
291     return NULL;
292 }
293 
294 static void
295 space(FILE *f, int level)
296 {
297     fprintf(f, "%*.*s", level * 4, level * 4, " ");
298 }
299 
300 static void
301 cprint(int level, const char *fmt, ...)
302 {
303     va_list ap;
304     va_start(ap, fmt);
305     space(cfile, level);
306     vfprintf(cfile, fmt, ap);
307     va_end(ap);
308 }
309 
310 static void
311 hprint(int level, const char *fmt, ...)
312 {
313     va_list ap;
314     va_start(ap, fmt);
315     space(hfile, level);
316     vfprintf(hfile, fmt, ap);
317     va_end(ap);
318 }
319 
320 static void gen_name(char *str);
321 
322 static void
323 gen_command(struct assignment *as)
324 {
325     struct assignment *a, *b;
326     char *f;
327     a = find(as, "name");
328     f = strdup(a->u.value);
329     gen_name(f);
330     cprint(1, "    { ");
331     fprintf(cfile, "\"%s\", ", a->u.value);
332     fprintf(cfile, "%s_wrap, ", f);
333     b = find(as, "argument");
334     if(b)
335 	fprintf(cfile, "\"%s %s\", ", a->u.value, b->u.value);
336     else
337 	fprintf(cfile, "\"%s\", ", a->u.value);
338     b = find(as, "help");
339     if(b)
340 	fprintf(cfile, "\"%s\"", b->u.value);
341     else
342 	fprintf(cfile, "NULL");
343     fprintf(cfile, " },\n");
344     for(a = a->next; a != NULL; a = a->next)
345 	if(strcmp(a->name, "name") == 0)
346 	    cprint(1, "    { \"%s\" },\n", a->u.value);
347     cprint(0, "\n");
348 }
349 
350 static void
351 gen_name(char *str)
352 {
353     char *p;
354     for(p = str; *p != '\0'; p++)
355 	if(!isalnum((unsigned char)*p))
356 	    *p = '_';
357 }
358 
359 static char *
360 make_name(struct assignment *as)
361 {
362     struct assignment *lopt;
363     struct assignment *type;
364     char *s;
365 
366     lopt = find(as, "long");
367     if(lopt == NULL)
368 	lopt = find(as, "name");
369     if(lopt == NULL)
370 	return NULL;
371 
372     type = find(as, "type");
373     if(strcmp(type->u.value, "-flag") == 0)
374 	asprintf(&s, "%s_flag", lopt->u.value);
375     else
376 	asprintf(&s, "%s_%s", lopt->u.value, type->u.value);
377     gen_name(s);
378     return s;
379 }
380 
381 
382 static void defval_int(const char *name, struct assignment *defval)
383 {
384     if(defval != NULL)
385 	cprint(1, "opt.%s = %s;\n", name, defval->u.value);
386     else
387 	cprint(1, "opt.%s = 0;\n", name);
388 }
389 static void defval_neg_flag(const char *name, struct assignment *defval)
390 {
391     if(defval != NULL)
392 	cprint(1, "opt.%s = %s;\n", name, defval->u.value);
393     else
394 	cprint(1, "opt.%s = 1;\n", name);
395 }
396 static void defval_string(const char *name, struct assignment *defval)
397 {
398     if(defval != NULL)
399 	cprint(1, "opt.%s = \"%s\";\n", name, defval->u.value);
400     else
401 	cprint(1, "opt.%s = NULL;\n", name);
402 }
403 static void defval_strings(const char *name, struct assignment *defval)
404 {
405     cprint(1, "opt.%s.num_strings = 0;\n", name);
406     cprint(1, "opt.%s.strings = NULL;\n", name);
407 }
408 
409 static void free_strings(const char *name)
410 {
411     cprint(1, "free_getarg_strings (&opt.%s);\n", name);
412 }
413 
414 struct type_handler {
415     const char *typename;
416     const char *c_type;
417     const char *getarg_type;
418     void (*defval)(const char*, struct assignment*);
419     void (*free)(const char*);
420 } type_handlers[] = {
421 	{ "integer",
422 	  "int",
423 	  "arg_integer",
424 	  defval_int,
425 	  NULL
426 	},
427 	{ "string",
428 	  "char*",
429 	  "arg_string",
430 	  defval_string,
431 	  NULL
432 	},
433 	{ "strings",
434 	  "struct getarg_strings",
435 	  "arg_strings",
436 	  defval_strings,
437 	  free_strings
438 	},
439 	{ "flag",
440 	  "int",
441 	  "arg_flag",
442 	  defval_int,
443 	  NULL
444 	},
445 	{ "-flag",
446 	  "int",
447 	  "arg_negative_flag",
448 	  defval_neg_flag,
449 	  NULL
450 	},
451 	{ NULL }
452 };
453 
454 static struct type_handler *find_handler(struct assignment *type)
455 {
456     struct type_handler *th;
457     for(th = type_handlers; th->typename != NULL; th++)
458 	if(strcmp(type->u.value, th->typename) == 0)
459 	    return th;
460     ex(type, "unknown type \"%s\"", type->u.value);
461     exit(1);
462 }
463 
464 static void
465 gen_options(struct assignment *opt1, const char *name)
466 {
467     struct assignment *tmp;
468 
469     hprint(0, "struct %s_options {\n", name);
470 
471     for(tmp = opt1;
472 	tmp != NULL;
473 	tmp = find_next(tmp, "option")) {
474 	struct assignment *type;
475 	struct type_handler *th;
476 	char *s;
477 
478 	s = make_name(tmp->u.assignment);
479 	type = find(tmp->u.assignment, "type");
480 	th = find_handler(type);
481 	hprint(1, "%s %s;\n", th->c_type, s);
482 	free(s);
483     }
484     hprint(0, "};\n");
485 }
486 
487 static void
488 gen_wrapper(struct assignment *as)
489 {
490     struct assignment *name;
491     struct assignment *arg;
492     struct assignment *opt1;
493     struct assignment *function;
494     struct assignment *tmp;
495     char *n, *f;
496     int nargs = 0;
497 
498     name = find(as, "name");
499     n = strdup(name->u.value);
500     gen_name(n);
501     arg = find(as, "argument");
502     opt1 = find(as, "option");
503     function = find(as, "function");
504     if(function)
505 	f = function->u.value;
506     else
507 	f = n;
508 
509 
510     if(opt1 != NULL) {
511 	gen_options(opt1, n);
512 	hprint(0, "int %s(struct %s_options*, int, char **);\n", f, n);
513     } else {
514 	hprint(0, "int %s(void*, int, char **);\n", f);
515     }
516 
517     fprintf(cfile, "static int\n");
518     fprintf(cfile, "%s_wrap(int argc, char **argv)\n", n);
519     fprintf(cfile, "{\n");
520     if(opt1 != NULL)
521 	cprint(1, "struct %s_options opt;\n", n);
522     cprint(1, "int ret;\n");
523     cprint(1, "int optidx = 0;\n");
524     cprint(1, "struct getargs args[] = {\n");
525     for(tmp = find(as, "option");
526 	tmp != NULL;
527 	tmp = find_next(tmp, "option")) {
528 	struct assignment *type = find(tmp->u.assignment, "type");
529 	struct assignment *lopt = find(tmp->u.assignment, "long");
530 	struct assignment *sopt = find(tmp->u.assignment, "short");
531 	struct assignment *aarg = find(tmp->u.assignment, "argument");
532 	struct assignment *help = find(tmp->u.assignment, "help");
533 
534 	struct type_handler *th;
535 
536 	cprint(2, "{ ");
537 	if(lopt)
538 	    fprintf(cfile, "\"%s\", ", lopt->u.value);
539 	else
540 	    fprintf(cfile, "NULL, ");
541 	if(sopt)
542 	    fprintf(cfile, "'%c', ", *sopt->u.value);
543 	else
544 	    fprintf(cfile, "0, ");
545 	th = find_handler(type);
546 	fprintf(cfile, "%s, ", th->getarg_type);
547 	fprintf(cfile, "NULL, ");
548 	if(help)
549 	    fprintf(cfile, "\"%s\", ", help->u.value);
550 	else
551 	    fprintf(cfile, "NULL, ");
552 	if(aarg)
553 	    fprintf(cfile, "\"%s\"", aarg->u.value);
554 	else
555 	    fprintf(cfile, "NULL");
556 	fprintf(cfile, " },\n");
557     }
558     cprint(2, "{ \"help\", 'h', arg_flag, NULL, NULL, NULL }\n");
559     cprint(1, "};\n");
560     cprint(1, "int help_flag = 0;\n");
561 
562     for(tmp = find(as, "option");
563 	tmp != NULL;
564 	tmp = find_next(tmp, "option")) {
565 	char *s;
566 	struct assignment *type = find(tmp->u.assignment, "type");
567 
568 	struct assignment *defval = find(tmp->u.assignment, "default");
569 
570 	struct type_handler *th;
571 
572 	s = make_name(tmp->u.assignment);
573 	th = find_handler(type);
574 	(*th->defval)(s, defval);
575 	free(s);
576     }
577 
578     for(tmp = find(as, "option");
579 	tmp != NULL;
580 	tmp = find_next(tmp, "option")) {
581 	char *s;
582 	s = make_name(tmp->u.assignment);
583 	cprint(1, "args[%d].value = &opt.%s;\n", nargs++, s);
584 	free(s);
585     }
586     cprint(1, "args[%d].value = &help_flag;\n", nargs++);
587     cprint(1, "if(getarg(args, %d, argc, argv, &optidx))\n", nargs);
588     cprint(2, "goto usage;\n");
589 
590     {
591 	int min_args = -1;
592 	int max_args = -1;
593 	char *end;
594 	if(arg == NULL) {
595 	    max_args = 0;
596 	} else {
597 	    if((tmp = find(as, "min_args")) != NULL) {
598 		min_args = strtol(tmp->u.value, &end, 0);
599 		if(*end != '\0') {
600 		    ex(tmp, "min_args is not numeric");
601 		    exit(1);
602 		}
603 		if(min_args < 0) {
604 		    ex(tmp, "min_args must be non-negative");
605 		    exit(1);
606 		}
607 	    }
608 	    if((tmp = find(as, "max_args")) != NULL) {
609 		max_args = strtol(tmp->u.value, &end, 0);
610 		if(*end != '\0') {
611 		    ex(tmp, "max_args is not numeric");
612 		    exit(1);
613 		}
614 		if(max_args < 0) {
615 		    ex(tmp, "max_args must be non-negative");
616 		    exit(1);
617 		}
618 	    }
619 	}
620 	if(min_args != -1 || max_args != -1) {
621 	    if(min_args == max_args) {
622 		cprint(1, "if(argc - optidx != %d) {\n",
623 		       min_args);
624 		cprint(2, "fprintf(stderr, \"Need exactly %u parameters (%%u given).\\n\\n\", argc - optidx);\n", min_args);
625 		cprint(2, "goto usage;\n");
626 		cprint(1, "}\n");
627 	    } else {
628 		if(max_args != -1) {
629 		    cprint(1, "if(argc - optidx > %d) {\n", max_args);
630 		    cprint(2, "fprintf(stderr, \"Arguments given (%%u) are more than expected (%u).\\n\\n\", argc - optidx);\n", max_args);
631 		    cprint(2, "goto usage;\n");
632 		    cprint(1, "}\n");
633 		}
634 		if(min_args != -1) {
635 		    cprint(1, "if(argc - optidx < %d) {\n", min_args);
636 		    cprint(2, "fprintf(stderr, \"Arguments given (%%u) are less than expected (%u).\\n\\n\", argc - optidx);\n", min_args);
637 		    cprint(2, "goto usage;\n");
638 		    cprint(1, "}\n");
639 		}
640 	    }
641 	}
642     }
643 
644     cprint(1, "if(help_flag)\n");
645     cprint(2, "goto usage;\n");
646 
647     cprint(1, "ret = %s(%s, argc - optidx, argv + optidx);\n",
648 	   f, opt1 ? "&opt": "NULL");
649 
650     /* free allocated data */
651     for(tmp = find(as, "option");
652 	tmp != NULL;
653 	tmp = find_next(tmp, "option")) {
654 	char *s;
655 	struct assignment *type = find(tmp->u.assignment, "type");
656 	struct type_handler *th;
657 	th = find_handler(type);
658 	if(th->free == NULL)
659 	    continue;
660 	s = make_name(tmp->u.assignment);
661 	(*th->free)(s);
662 	free(s);
663     }
664     cprint(1, "return ret;\n");
665 
666     cprint(0, "usage:\n");
667     cprint(1, "arg_printusage (args, %d, \"%s\", \"%s\");\n", nargs,
668 	   name->u.value, arg ? arg->u.value : "");
669     /* free allocated data */
670     for(tmp = find(as, "option");
671 	tmp != NULL;
672 	tmp = find_next(tmp, "option")) {
673 	char *s;
674 	struct assignment *type = find(tmp->u.assignment, "type");
675 	struct type_handler *th;
676 	th = find_handler(type);
677 	if(th->free == NULL)
678 	    continue;
679 	s = make_name(tmp->u.assignment);
680 	(*th->free)(s);
681 	free(s);
682     }
683     cprint(1, "return 0;\n");
684     cprint(0, "}\n");
685     cprint(0, "\n");
686 }
687 
688 char cname[PATH_MAX];
689 char hname[PATH_MAX];
690 
691 static void
692 gen(struct assignment *as)
693 {
694     struct assignment *a;
695     cprint(0, "#include <stdio.h>\n");
696     cprint(0, "#include <krb5/getarg.h>\n");
697     cprint(0, "#include <krb5/sl.h>\n");
698     cprint(0, "#include \"%s\"\n\n", hname);
699 
700     hprint(0, "#include <stdio.h>\n");
701     hprint(0, "#include <krb5/sl.h>\n");
702     hprint(0, "\n");
703 
704 
705     for(a = as; a != NULL; a = a->next)
706 	gen_wrapper(a->u.assignment);
707 
708     cprint(0, "SL_cmd commands[] = {\n");
709     for(a = as; a != NULL; a = a->next)
710 	gen_command(a->u.assignment);
711     cprint(1, "{ NULL }\n");
712     cprint(0, "};\n");
713 
714     hprint(0, "extern SL_cmd commands[];\n");
715 }
716 
717 int version_flag;
718 int help_flag;
719 struct getargs args[] = {
720     { "version", 0, arg_flag, &version_flag },
721     { "help", 0, arg_flag, &help_flag }
722 };
723 int num_args = sizeof(args) / sizeof(args[0]);
724 
725 static void
726 usage(int code)
727 {
728     arg_printusage(args, num_args, NULL, "command-table");
729     exit(code);
730 }
731 
732 int
733 main(int argc, char **argv)
734 {
735     char *p;
736 
737     int optidx = 0;
738 
739     setprogname(argv[0]);
740     if(getarg(args, num_args, argc, argv, &optidx))
741 	usage(1);
742     if(help_flag)
743 	usage(0);
744     if(version_flag) {
745 	print_version(NULL);
746 	exit(0);
747     }
748 
749     if(argc == optidx)
750 	usage(1);
751 
752     filename = argv[optidx];
753     yyin = fopen(filename, "r");
754     if(yyin == NULL)
755 	err(1, "%s", filename);
756     p = strrchr(filename, '/');
757     if(p)
758 	strlcpy(cname, p + 1, sizeof(cname));
759     else
760 	strlcpy(cname, filename, sizeof(cname));
761     p = strrchr(cname, '.');
762     if(p)
763 	*p = '\0';
764     strlcpy(hname, cname, sizeof(hname));
765     strlcat(cname, ".c", sizeof(cname));
766     strlcat(hname, ".h", sizeof(hname));
767     yyparse();
768     if(error_flag)
769 	exit(1);
770     if(check(assignment) == 0) {
771 	cfile = fopen(cname, "w");
772 	if(cfile == NULL)
773 	  err(1, "%s", cname);
774 	hfile = fopen(hname, "w");
775 	if(hfile == NULL)
776 	  err(1, "%s", hname);
777 	gen(assignment);
778 	fclose(cfile);
779 	fclose(hfile);
780     }
781     fclose(yyin);
782     return 0;
783 }
784