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