1 /* $NetBSD: slc-gram.y,v 1.1.1.2 2014/04/24 12:45:53 pettai Exp $ */
5 * Copyright (c) 2004-2006 Kungliga Tekniska Högskolan
6 * (Royal Institute of Technology, Stockholm, Sweden).
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
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.
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.
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
50 extern
struct assignment
*assignment
;
52 /* Declarations for Bison:
54 #define YYMALLOC malloc
61 struct assignment
*assignment
;
64 %token
<string> LITERAL
65 %token
<string> STRING
66 %type
<assignment
> assignment assignments
78 assignments
: assignment assignments
86 assignment
: LITERAL
'=' STRING
88 $$
= malloc
(sizeof
(*$$
));
95 | LITERAL
'=' '{' assignments
'}'
97 $$
= malloc
(sizeof
(*$$
));
99 $$
->type
= a_assignment
;
101 $$
->u.assignment
= $4;
110 struct assignment
*assignment
;
114 ex
(struct assignment
*a
, const char *fmt
, ...
)
117 fprintf
(stderr
, "%s:%d: ", a
->name
, a
->lineno
);
119 vfprintf
(stderr
, fmt
, ap
);
121 fprintf
(stderr
, "\n");
127 check_option
(struct assignment
*as
)
129 struct assignment
*a
;
134 int seen_argument
= 0;
136 int seen_default
= 0;
139 for
(a
= as
; a
!= NULL
; a
= a
->next
) {
140 if
(strcmp
(a
->name
, "long") == 0)
142 else if
(strcmp
(a
->name
, "short") == 0)
144 else if
(strcmp
(a
->name
, "name") == 0)
146 else if
(strcmp
(a
->name
, "type") == 0)
148 else if
(strcmp
(a
->name
, "argument") == 0)
150 else if
(strcmp
(a
->name
, "help") == 0)
152 else if
(strcmp
(a
->name
, "default") == 0)
155 ex
(a
, "unknown name %s", a
->name
);
159 if
(seen_long
== 0 && seen_short
== 0) {
160 ex
(as
, "neither long nor short option");
163 if
(seen_long
== 0 && seen_name
== 0) {
164 ex
(as
, "either of long or name option must be used");
168 ex
(as
, "multiple long options");
172 ex
(as
, "multiple short options");
176 ex
(as
, "multiple types");
179 if
(seen_argument
> 1) {
180 ex
(as
, "multiple arguments");
184 ex
(as
, "multiple help strings");
187 if
(seen_default
> 1) {
188 ex
(as
, "multiple default values");
195 check_command
(struct assignment
*as
)
197 struct assignment
*a
;
199 int seen_function
= 0;
201 int seen_argument
= 0;
202 int seen_minargs
= 0;
203 int seen_maxargs
= 0;
205 for
(a
= as
; a
!= NULL
; a
= a
->next
) {
206 if
(strcmp
(a
->name
, "name") == 0)
208 else if
(strcmp
(a
->name
, "function") == 0) {
210 } else if
(strcmp
(a
->name
, "option") == 0)
211 ret
+= check_option
(a
->u.assignment
);
212 else if
(strcmp
(a
->name
, "help") == 0) {
214 } else if
(strcmp
(a
->name
, "argument") == 0) {
216 } else if
(strcmp
(a
->name
, "min_args") == 0) {
218 } else if
(strcmp
(a
->name
, "max_args") == 0) {
221 ex
(a
, "unknown name: %s", a
->name
);
226 ex
(as
, "no command name");
229 if
(seen_function
> 1) {
230 ex
(as
, "multiple function names");
234 ex
(as
, "multiple help strings");
237 if
(seen_argument
> 1) {
238 ex
(as
, "multiple argument strings");
241 if
(seen_minargs
> 1) {
242 ex
(as
, "multiple min_args strings");
245 if
(seen_maxargs
> 1) {
246 ex
(as
, "multiple max_args strings");
254 check
(struct assignment
*as
)
256 struct assignment
*a
;
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
);
264 if
(a
->type
!= a_assignment
) {
265 fprintf
(stderr
, "bad command definition %s line %d\n", a
->name
, a
->lineno
);
269 ret
+= check_command
(a
->u.assignment
);
274 static struct assignment
*
275 find_next
(struct assignment
*as
, const char *name
)
277 for
(as
= as
->next
; as
!= NULL
; as
= as
->next
) {
278 if
(strcmp
(as
->name
, name
) == 0)
284 static struct assignment
*
285 find
(struct assignment
*as
, const char *name
)
287 for
(; as
!= NULL
; as
= as
->next
) {
288 if
(strcmp
(as
->name
, name
) == 0)
295 space
(FILE *f
, int level
)
297 fprintf
(f
, "%*.*s", level
* 4, level
* 4, " ");
301 cprint
(int level
, const char *fmt
, ...
)
306 vfprintf
(cfile
, fmt
, ap
);
311 hprint
(int level
, const char *fmt
, ...
)
316 vfprintf
(hfile
, fmt
, ap
);
320 static void gen_name
(char *str
);
323 gen_command
(struct assignment
*as
)
325 struct assignment
*a
, *b
;
327 a
= find
(as
, "name");
328 f
= strdup
(a
->u.value
);
331 fprintf
(cfile
, "\"%s\", ", a
->u.value
);
332 fprintf
(cfile
, "%s_wrap, ", f
);
333 b
= find
(as
, "argument");
335 fprintf
(cfile
, "\"%s %s\", ", a
->u.value
, b
->u.value
);
337 fprintf
(cfile
, "\"%s\", ", a
->u.value
);
338 b
= find
(as
, "help");
340 fprintf
(cfile
, "\"%s\"", b
->u.value
);
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
);
354 for
(p
= str
; *p
!= '\0'; p
++)
355 if
(!isalnum
((unsigned char)*p
))
360 make_name
(struct assignment
*as
)
362 struct assignment
*lopt
;
363 struct assignment
*type
;
366 lopt
= find
(as
, "long");
368 lopt
= find
(as
, "name");
372 type
= find
(as
, "type");
373 if
(strcmp
(type
->u.value
, "-flag") == 0)
374 asprintf
(&s
, "%s_flag", lopt
->u.value
);
376 asprintf
(&s
, "%s_%s", lopt
->u.value
, type
->u.value
);
382 static void defval_int
(const char *name
, struct assignment
*defval
)
385 cprint
(1, "opt.%s = %s;\n", name
, defval
->u.value
);
387 cprint
(1, "opt.%s = 0;\n", name
);
389 static void defval_neg_flag
(const char *name
, struct assignment
*defval
)
392 cprint
(1, "opt.%s = %s;\n", name
, defval
->u.value
);
394 cprint
(1, "opt.%s = 1;\n", name
);
396 static void defval_string
(const char *name
, struct assignment
*defval
)
399 cprint
(1, "opt.%s = (char *)(unsigned long)\"%s\";\n", name
, defval
->u.value
);
401 cprint
(1, "opt.%s = NULL;\n", name
);
403 static void defval_strings
(const char *name
, struct assignment
*defval
)
405 cprint
(1, "opt.%s.num_strings = 0;\n", name
);
406 cprint
(1, "opt.%s.strings = NULL;\n", name
);
409 static void free_strings
(const char *name
)
411 cprint
(1, "free_getarg_strings (&opt.%s);\n", name
);
414 struct type_handler
{
415 const char *typename
;
417 const char *getarg_type
;
418 void (*defval
)(const char*, struct assignment
*);
419 void (*free
)(const char*);
420 } type_handlers
[] = {
434 "struct getarg_strings",
454 static struct type_handler
*find_handler
(struct assignment
*type
)
456 struct type_handler
*th
;
457 for
(th
= type_handlers
; th
->typename
!= NULL
; th
++)
458 if
(strcmp
(type
->u.value
, th
->typename
) == 0)
460 ex
(type
, "unknown type \"%s\"", type
->u.value
);
465 gen_options
(struct assignment
*opt1
, const char *name
)
467 struct assignment
*tmp
;
469 hprint
(0, "struct %s_options {\n", name
);
473 tmp
= find_next
(tmp
, "option")) {
474 struct assignment
*type
;
475 struct type_handler
*th
;
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
);
488 gen_wrapper
(struct assignment
*as
)
490 struct assignment
*name
;
491 struct assignment
*arg
;
492 struct assignment
*opt1
;
493 struct assignment
*function
;
494 struct assignment
*tmp
;
499 name
= find
(as
, "name");
500 n
= strdup
(name
->u.value
);
502 arg
= find
(as
, "argument");
505 opt1
= find
(as
, "option");
506 function
= find
(as
, "function");
508 f
= function
->u.value
;
514 gen_options
(opt1
, n
);
515 hprint
(0, "int %s(struct %s_options*, int, char **);\n", f
, n
);
517 hprint
(0, "int %s(void*, int, char **);\n", f
);
520 fprintf
(cfile
, "static int\n");
521 fprintf
(cfile
, "%s_wrap(int argc, char **argv)\n", n
);
522 fprintf
(cfile
, "{\n");
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");
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");
537 struct type_handler
*th
;
541 fprintf
(cfile
, "\"%s\", ", lopt
->u.value
);
543 fprintf
(cfile
, "NULL, ");
545 fprintf
(cfile
, "'%c', ", *sopt
->u.value
);
547 fprintf
(cfile
, "0, ");
548 th
= find_handler
(type
);
549 fprintf
(cfile
, "%s, ", th
->getarg_type
);
550 fprintf
(cfile
, "NULL, ");
552 fprintf
(cfile
, "\"%s\", ", help
->u.value
);
554 fprintf
(cfile
, "NULL, ");
556 fprintf
(cfile
, "\"%s\"", aarg
->u.value
);
559 fprintf
(cfile
, "NULL");
560 fprintf
(cfile
, " },\n");
562 cprint
(2, "{ \"help\", 'h', arg_flag, NULL, NULL, NULL }\n");
564 cprint
(1, "int help_flag = 0;\n");
566 for
(tmp
= find
(as
, "option");
568 tmp
= find_next
(tmp
, "option")) {
570 struct assignment
*type
= find
(tmp
->u.assignment
, "type");
572 struct assignment
*defval
= find
(tmp
->u.assignment
, "default");
574 struct type_handler
*th
;
576 s
= make_name
(tmp
->u.assignment
);
577 th
= find_handler
(type
);
578 (*th
->defval
)(s
, defval
);
582 for
(tmp
= find
(as
, "option");
584 tmp
= find_next
(tmp
, "option")) {
586 s
= make_name
(tmp
->u.assignment
);
587 cprint
(1, "args[%d].value = &opt.%s;\n", nargs
++, s
);
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");
598 if
(narguments
== 0) {
601 if
((tmp
= find
(as
, "min_args")) != NULL
) {
602 min_args
= strtol
(tmp
->u.value
, &end
, 0);
604 ex
(tmp
, "min_args is not numeric");
608 ex
(tmp
, "min_args must be non-negative");
612 if
((tmp
= find
(as
, "max_args")) != NULL
) {
613 max_args
= strtol
(tmp
->u.value
, &end
, 0);
615 ex
(tmp
, "max_args is not numeric");
619 ex
(tmp
, "max_args must be non-negative");
624 if
(min_args
!= -1 || max_args
!= -1) {
625 if
(min_args
== max_args
) {
626 cprint
(1, "if(argc - optidx != %d) {\n",
628 cprint
(2, "fprintf(stderr, \"Need exactly %u parameters (%%u given).\\n\\n\", argc - optidx);\n", min_args
);
629 cprint
(2, "goto usage;\n");
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");
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");
648 cprint
(1, "if(help_flag)\n");
649 cprint
(2, "goto usage;\n");
651 cprint
(1, "ret = %s(%s, argc - optidx, argv + optidx);\n",
652 f
, opt1 ?
"&opt": "NULL");
654 /* free allocated data */
655 for
(tmp
= find
(as
, "option");
657 tmp
= find_next
(tmp
, "option")) {
659 struct assignment
*type
= find
(tmp
->u.assignment
, "type");
660 struct type_handler
*th
;
661 th
= find_handler
(type
);
664 s
= make_name
(tmp
->u.assignment
);
668 cprint
(1, "return ret;\n");
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");
676 tmp
= find_next
(tmp
, "option")) {
678 struct assignment
*type
= find
(tmp
->u.assignment
, "type");
679 struct type_handler
*th
;
680 th
= find_handler
(type
);
683 s
= make_name
(tmp
->u.assignment
);
687 cprint
(1, "return 0;\n");
692 char cname
[PATH_MAX
];
693 char hname
[PATH_MAX
];
696 gen
(struct assignment
*as
)
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
);
704 hprint
(0, "#include <stdio.h>\n");
705 hprint
(0, "#include <krb5/sl.h>\n");
709 for
(a
= as
; a
!= NULL
; a
= a
->next
)
710 gen_wrapper
(a
->u.assignment
);
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");
718 hprint
(0, "extern SL_cmd commands[];\n");
723 struct getargs args
[] = {
724 { "version", 0, arg_flag
, &version_flag
},
725 { "help", 0, arg_flag
, &help_flag
}
727 int num_args
= sizeof
(args
) / sizeof
(args
[0]);
732 arg_printusage
(args
, num_args
, NULL
, "command-table");
737 main
(int argc
, char **argv
)
743 setprogname
(argv
[0]);
744 if
(getarg
(args
, num_args
, argc
, argv
, &optidx
))
756 filename
= argv
[optidx
];
757 yyin
= fopen
(filename
, "r");
759 err
(1, "%s", filename
);
760 p
= strrchr
(filename
, '/');
762 strlcpy
(cname
, p
+ 1, sizeof
(cname
));
764 strlcpy
(cname
, filename
, sizeof
(cname
));
765 p
= strrchr
(cname
, '.');
768 strlcpy
(hname
, cname
, sizeof
(hname
));
769 strlcat
(cname
, ".c", sizeof
(cname
));
770 strlcat
(hname
, ".h", sizeof
(hname
));
774 if
(check
(assignment
) == 0) {
775 cfile
= fopen
(cname
, "w");
778 hfile
= fopen
(hname
, "w");