xref: /minix3/crypto/external/bsd/heimdal/dist/lib/sl/slc-gram.y (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1 /*	$NetBSD: slc-gram.y,v 1.1.1.2 2014/04/24 12:45:53 pettai 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
ex(struct assignment * a,const char * fmt,...)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
check_option(struct assignment * as)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
check_command(struct assignment * as)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
check(struct assignment * as)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 *
find_next(struct assignment * as,const char * name)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 *
find(struct assignment * as,const char * name)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
space(FILE * f,int level)295 space(FILE *f, int level)
296 {
297     fprintf(f, "%*.*s", level * 4, level * 4, " ");
298 }
299 
300 static void
cprint(int level,const char * fmt,...)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
hprint(int level,const char * fmt,...)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
gen_command(struct assignment * as)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
gen_name(char * str)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 *
make_name(struct assignment * as)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 
defval_int(const char * name,struct assignment * defval)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 }
defval_neg_flag(const char * name,struct assignment * defval)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 }
defval_string(const char * name,struct assignment * defval)396 static void defval_string(const char *name, struct assignment *defval)
397 {
398     if(defval != NULL)
399 	cprint(1, "opt.%s = (char *)(unsigned long)\"%s\";\n", name, defval->u.value);
400     else
401 	cprint(1, "opt.%s = NULL;\n", name);
402 }
defval_strings(const char * name,struct assignment * defval)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 
free_strings(const char * name)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 
find_handler(struct assignment * type)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
gen_options(struct assignment * opt1,const char * name)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
gen_wrapper(struct assignment * as)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     int narguments = 0;
498 
499     name = find(as, "name");
500     n = strdup(name->u.value);
501     gen_name(n);
502     arg = find(as, "argument");
503     if (arg)
504         narguments++;
505     opt1 = find(as, "option");
506     function = find(as, "function");
507     if(function)
508 	f = function->u.value;
509     else
510 	f = n;
511 
512 
513     if(opt1 != NULL) {
514 	gen_options(opt1, n);
515 	hprint(0, "int %s(struct %s_options*, int, char **);\n", f, n);
516     } else {
517 	hprint(0, "int %s(void*, int, char **);\n", f);
518     }
519 
520     fprintf(cfile, "static int\n");
521     fprintf(cfile, "%s_wrap(int argc, char **argv)\n", n);
522     fprintf(cfile, "{\n");
523     if(opt1 != NULL)
524 	cprint(1, "struct %s_options opt;\n", n);
525     cprint(1, "int ret;\n");
526     cprint(1, "int optidx = 0;\n");
527     cprint(1, "struct getargs args[] = {\n");
528     for(tmp = find(as, "option");
529 	tmp != NULL;
530 	tmp = find_next(tmp, "option")) {
531 	struct assignment *type = find(tmp->u.assignment, "type");
532 	struct assignment *lopt = find(tmp->u.assignment, "long");
533 	struct assignment *sopt = find(tmp->u.assignment, "short");
534 	struct assignment *aarg = find(tmp->u.assignment, "argument");
535 	struct assignment *help = find(tmp->u.assignment, "help");
536 
537 	struct type_handler *th;
538 
539 	cprint(2, "{ ");
540 	if(lopt)
541 	    fprintf(cfile, "\"%s\", ", lopt->u.value);
542 	else
543 	    fprintf(cfile, "NULL, ");
544 	if(sopt)
545 	    fprintf(cfile, "'%c', ", *sopt->u.value);
546 	else
547 	    fprintf(cfile, "0, ");
548 	th = find_handler(type);
549 	fprintf(cfile, "%s, ", th->getarg_type);
550 	fprintf(cfile, "NULL, ");
551 	if(help)
552 	    fprintf(cfile, "\"%s\", ", help->u.value);
553 	else
554 	    fprintf(cfile, "NULL, ");
555 	if(aarg) {
556 	    fprintf(cfile, "\"%s\"", aarg->u.value);
557             narguments++;
558 	} else
559 	    fprintf(cfile, "NULL");
560 	fprintf(cfile, " },\n");
561     }
562     cprint(2, "{ \"help\", 'h', arg_flag, NULL, NULL, NULL }\n");
563     cprint(1, "};\n");
564     cprint(1, "int help_flag = 0;\n");
565 
566     for(tmp = find(as, "option");
567 	tmp != NULL;
568 	tmp = find_next(tmp, "option")) {
569 	char *s;
570 	struct assignment *type = find(tmp->u.assignment, "type");
571 
572 	struct assignment *defval = find(tmp->u.assignment, "default");
573 
574 	struct type_handler *th;
575 
576 	s = make_name(tmp->u.assignment);
577 	th = find_handler(type);
578 	(*th->defval)(s, defval);
579 	free(s);
580     }
581 
582     for(tmp = find(as, "option");
583 	tmp != NULL;
584 	tmp = find_next(tmp, "option")) {
585 	char *s;
586 	s = make_name(tmp->u.assignment);
587 	cprint(1, "args[%d].value = &opt.%s;\n", nargs++, s);
588 	free(s);
589     }
590     cprint(1, "args[%d].value = &help_flag;\n", nargs++);
591     cprint(1, "if(getarg(args, %d, argc, argv, &optidx))\n", nargs);
592     cprint(2, "goto usage;\n");
593 
594     {
595 	int min_args = -1;
596 	int max_args = -1;
597 	char *end;
598 	if(narguments == 0) {
599 	    max_args = 0;
600 	} else {
601 	    if((tmp = find(as, "min_args")) != NULL) {
602 		min_args = strtol(tmp->u.value, &end, 0);
603 		if(*end != '\0') {
604 		    ex(tmp, "min_args is not numeric");
605 		    exit(1);
606 		}
607 		if(min_args < 0) {
608 		    ex(tmp, "min_args must be non-negative");
609 		    exit(1);
610 		}
611 	    }
612 	    if((tmp = find(as, "max_args")) != NULL) {
613 		max_args = strtol(tmp->u.value, &end, 0);
614 		if(*end != '\0') {
615 		    ex(tmp, "max_args is not numeric");
616 		    exit(1);
617 		}
618 		if(max_args < 0) {
619 		    ex(tmp, "max_args must be non-negative");
620 		    exit(1);
621 		}
622 	    }
623 	}
624 	if(min_args != -1 || max_args != -1) {
625 	    if(min_args == max_args) {
626 		cprint(1, "if(argc - optidx != %d) {\n",
627 		       min_args);
628 		cprint(2, "fprintf(stderr, \"Need exactly %u parameters (%%u given).\\n\\n\", argc - optidx);\n", min_args);
629 		cprint(2, "goto usage;\n");
630 		cprint(1, "}\n");
631 	    } else {
632 		if(max_args != -1) {
633 		    cprint(1, "if(argc - optidx > %d) {\n", max_args);
634 		    cprint(2, "fprintf(stderr, \"Arguments given (%%u) are more than expected (%u).\\n\\n\", argc - optidx);\n", max_args);
635 		    cprint(2, "goto usage;\n");
636 		    cprint(1, "}\n");
637 		}
638 		if(min_args != -1) {
639 		    cprint(1, "if(argc - optidx < %d) {\n", min_args);
640 		    cprint(2, "fprintf(stderr, \"Arguments given (%%u) are less than expected (%u).\\n\\n\", argc - optidx);\n", min_args);
641 		    cprint(2, "goto usage;\n");
642 		    cprint(1, "}\n");
643 		}
644 	    }
645 	}
646     }
647 
648     cprint(1, "if(help_flag)\n");
649     cprint(2, "goto usage;\n");
650 
651     cprint(1, "ret = %s(%s, argc - optidx, argv + optidx);\n",
652 	   f, opt1 ? "&opt": "NULL");
653 
654     /* free allocated data */
655     for(tmp = find(as, "option");
656 	tmp != NULL;
657 	tmp = find_next(tmp, "option")) {
658 	char *s;
659 	struct assignment *type = find(tmp->u.assignment, "type");
660 	struct type_handler *th;
661 	th = find_handler(type);
662 	if(th->free == NULL)
663 	    continue;
664 	s = make_name(tmp->u.assignment);
665 	(*th->free)(s);
666 	free(s);
667     }
668     cprint(1, "return ret;\n");
669 
670     cprint(0, "usage:\n");
671     cprint(1, "arg_printusage (args, %d, \"%s\", \"%s\");\n", nargs,
672 	   name->u.value, arg ? arg->u.value : "");
673     /* free allocated data */
674     for(tmp = find(as, "option");
675 	tmp != NULL;
676 	tmp = find_next(tmp, "option")) {
677 	char *s;
678 	struct assignment *type = find(tmp->u.assignment, "type");
679 	struct type_handler *th;
680 	th = find_handler(type);
681 	if(th->free == NULL)
682 	    continue;
683 	s = make_name(tmp->u.assignment);
684 	(*th->free)(s);
685 	free(s);
686     }
687     cprint(1, "return 0;\n");
688     cprint(0, "}\n");
689     cprint(0, "\n");
690 }
691 
692 char cname[PATH_MAX];
693 char hname[PATH_MAX];
694 
695 static void
gen(struct assignment * as)696 gen(struct assignment *as)
697 {
698     struct assignment *a;
699     cprint(0, "#include <stdio.h>\n");
700     cprint(0, "#include <krb5/getarg.h>\n");
701     cprint(0, "#include <krb5/sl.h>\n");
702     cprint(0, "#include \"%s\"\n\n", hname);
703 
704     hprint(0, "#include <stdio.h>\n");
705     hprint(0, "#include <krb5/sl.h>\n");
706     hprint(0, "\n");
707 
708 
709     for(a = as; a != NULL; a = a->next)
710 	gen_wrapper(a->u.assignment);
711 
712     cprint(0, "SL_cmd commands[] = {\n");
713     for(a = as; a != NULL; a = a->next)
714 	gen_command(a->u.assignment);
715     cprint(1, "{ NULL }\n");
716     cprint(0, "};\n");
717 
718     hprint(0, "extern SL_cmd commands[];\n");
719 }
720 
721 int version_flag;
722 int help_flag;
723 struct getargs args[] = {
724     { "version", 0, arg_flag, &version_flag },
725     { "help", 0, arg_flag, &help_flag }
726 };
727 int num_args = sizeof(args) / sizeof(args[0]);
728 
729 static void
usage(int code)730 usage(int code)
731 {
732     arg_printusage(args, num_args, NULL, "command-table");
733     exit(code);
734 }
735 
736 int
main(int argc,char ** argv)737 main(int argc, char **argv)
738 {
739     char *p;
740 
741     int optidx = 0;
742 
743     setprogname(argv[0]);
744     if(getarg(args, num_args, argc, argv, &optidx))
745 	usage(1);
746     if(help_flag)
747 	usage(0);
748     if(version_flag) {
749 	print_version(NULL);
750 	exit(0);
751     }
752 
753     if(argc == optidx)
754 	usage(1);
755 
756     filename = argv[optidx];
757     yyin = fopen(filename, "r");
758     if(yyin == NULL)
759 	err(1, "%s", filename);
760     p = strrchr(filename, '/');
761     if(p)
762 	strlcpy(cname, p + 1, sizeof(cname));
763     else
764 	strlcpy(cname, filename, sizeof(cname));
765     p = strrchr(cname, '.');
766     if(p)
767 	*p = '\0';
768     strlcpy(hname, cname, sizeof(hname));
769     strlcat(cname, ".c", sizeof(cname));
770     strlcat(hname, ".h", sizeof(hname));
771     yyparse();
772     if(error_flag)
773 	exit(1);
774     if(check(assignment) == 0) {
775 	cfile = fopen(cname, "w");
776 	if(cfile == NULL)
777 	  err(1, "%s", cname);
778 	hfile = fopen(hname, "w");
779 	if(hfile == NULL)
780 	  err(1, "%s", hname);
781 	gen(assignment);
782 	fclose(cfile);
783 	fclose(hfile);
784     }
785     fclose(yyin);
786     return 0;
787 }
788