3 * Copyright (c) 2004-2006 Kungliga Tekniska Högskolan
4 * (Royal Institute of Technology, Stockholm, Sweden).
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * 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.
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.
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
48 extern
struct assignment
*assignment
;
50 /* Declarations for Bison:
52 #define YYMALLOC malloc
59 struct assignment
*assignment
;
62 %token
<string> LITERAL
63 %token
<string> STRING
64 %type
<assignment
> assignment assignments
76 assignments
: assignment assignments
84 assignment
: LITERAL
'=' STRING
86 $$
= malloc
(sizeof
(*$$
));
93 | LITERAL
'=' '{' assignments
'}'
95 $$
= malloc
(sizeof
(*$$
));
97 $$
->type
= a_assignment
;
99 $$
->u.assignment
= $4;
108 struct assignment
*assignment
;
112 ex
(struct assignment
*a
, const char *fmt
, ...
)
115 fprintf
(stderr
, "%s:%d: ", a
->name
, a
->lineno
);
117 vfprintf
(stderr
, fmt
, ap
);
119 fprintf
(stderr
, "\n");
125 check_option
(struct assignment
*as
)
127 struct assignment
*a
;
132 int seen_argument
= 0;
134 int seen_default
= 0;
137 for
(a
= as
; a
!= NULL
; a
= a
->next
) {
138 if
(strcmp
(a
->name
, "long") == 0)
140 else if
(strcmp
(a
->name
, "short") == 0)
142 else if
(strcmp
(a
->name
, "name") == 0)
144 else if
(strcmp
(a
->name
, "type") == 0)
146 else if
(strcmp
(a
->name
, "argument") == 0)
148 else if
(strcmp
(a
->name
, "help") == 0)
150 else if
(strcmp
(a
->name
, "default") == 0)
153 ex
(a
, "unknown name %s", a
->name
);
157 if
(seen_long
== 0 && seen_short
== 0) {
158 ex
(as
, "neither long nor short option");
161 if
(seen_long
== 0 && seen_name
== 0) {
162 ex
(as
, "either of long or name option must be used");
166 ex
(as
, "multiple long options");
170 ex
(as
, "multiple short options");
174 ex
(as
, "multiple types");
177 if
(seen_argument
> 1) {
178 ex
(as
, "multiple arguments");
182 ex
(as
, "multiple help strings");
185 if
(seen_default
> 1) {
186 ex
(as
, "multiple default values");
193 check_command
(struct assignment
*as
)
195 struct assignment
*a
;
197 int seen_function
= 0;
199 int seen_argument
= 0;
200 int seen_minargs
= 0;
201 int seen_maxargs
= 0;
203 for
(a
= as
; a
!= NULL
; a
= a
->next
) {
204 if
(strcmp
(a
->name
, "name") == 0)
206 else if
(strcmp
(a
->name
, "function") == 0) {
208 } else if
(strcmp
(a
->name
, "option") == 0)
209 ret
+= check_option
(a
->u.assignment
);
210 else if
(strcmp
(a
->name
, "help") == 0) {
212 } else if
(strcmp
(a
->name
, "argument") == 0) {
214 } else if
(strcmp
(a
->name
, "min_args") == 0) {
216 } else if
(strcmp
(a
->name
, "max_args") == 0) {
219 ex
(a
, "unknown name: %s", a
->name
);
224 ex
(as
, "no command name");
227 if
(seen_function
> 1) {
228 ex
(as
, "multiple function names");
232 ex
(as
, "multiple help strings");
235 if
(seen_argument
> 1) {
236 ex
(as
, "multiple argument strings");
239 if
(seen_minargs
> 1) {
240 ex
(as
, "multiple min_args strings");
243 if
(seen_maxargs
> 1) {
244 ex
(as
, "multiple max_args strings");
252 check
(struct assignment
*as
)
254 struct assignment
*a
;
256 for
(a
= as
; a
!= NULL
; a
= a
->next
) {
257 if
(strcmp
(a
->name
, "command") != 0) {
258 fprintf
(stderr
, "unknown type %s line %d\n", a
->name
, a
->lineno
);
262 if
(a
->type
!= a_assignment
) {
263 fprintf
(stderr
, "bad command definition %s line %d\n", a
->name
, a
->lineno
);
267 ret
+= check_command
(a
->u.assignment
);
272 static struct assignment
*
273 find_next
(struct assignment
*as
, const char *name
)
275 for
(as
= as
->next
; as
!= NULL
; as
= as
->next
) {
276 if
(strcmp
(as
->name
, name
) == 0)
282 static struct assignment
*
283 find
(struct assignment
*as
, const char *name
)
285 for
(; as
!= NULL
; as
= as
->next
) {
286 if
(strcmp
(as
->name
, name
) == 0)
293 space
(FILE *f
, int level
)
295 fprintf
(f
, "%*.*s", level
* 4, level
* 4, " ");
299 cprint
(int level
, const char *fmt
, ...
)
304 vfprintf
(cfile
, fmt
, ap
);
309 hprint
(int level
, const char *fmt
, ...
)
314 vfprintf
(hfile
, fmt
, ap
);
318 static void gen_name
(char *str
);
321 gen_command
(struct assignment
*as
)
323 struct assignment
*a
, *b
;
325 a
= find
(as
, "name");
326 f
= strdup
(a
->u.value
);
329 fprintf
(cfile
, "\"%s\", ", a
->u.value
);
330 fprintf
(cfile
, "%s_wrap, ", f
);
332 b
= find
(as
, "argument");
334 fprintf
(cfile
, "\"%s %s\", ", a
->u.value
, b
->u.value
);
336 fprintf
(cfile
, "\"%s\", ", a
->u.value
);
337 b
= find
(as
, "help");
339 fprintf
(cfile
, "\"%s\"", b
->u.value
);
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\", NULL, NULL, NULL },\n", a
->u.value
);
353 for
(p
= str
; *p
!= '\0'; p
++)
354 if
(!isalnum
((unsigned char)*p
))
359 make_name
(struct assignment
*as
)
361 struct assignment
*lopt
;
362 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 ret
= asprintf
(&s
, "%s_flag", lopt
->u.value
);
376 ret
= asprintf
(&s
, "%s_%s", lopt
->u.value
, type
->u.value
);
384 static void defval_int
(const char *name
, struct assignment
*defval
)
387 cprint
(1, "opt.%s = %s;\n", name
, defval
->u.value
);
389 cprint
(1, "opt.%s = 0;\n", name
);
391 static void defval_neg_flag
(const char *name
, struct assignment
*defval
)
394 cprint
(1, "opt.%s = %s;\n", name
, defval
->u.value
);
396 cprint
(1, "opt.%s = 1;\n", name
);
398 static void defval_string
(const char *name
, struct assignment
*defval
)
401 cprint
(1, "opt.%s = (char *)(uintptr_t)\"%s\";\n", name
, defval
->u.value
);
403 cprint
(1, "opt.%s = NULL;\n", name
);
405 static void defval_strings
(const char *name
, struct assignment
*defval
)
407 cprint
(1, "opt.%s.num_strings = 0;\n", name
);
408 cprint
(1, "opt.%s.strings = NULL;\n", name
);
411 static void free_strings
(const char *name
)
413 cprint
(1, "free_getarg_strings (&opt.%s);\n", name
);
416 struct type_handler
{
417 const char *typename
;
419 const char *getarg_type
;
420 void (*defval
)(const char*, struct assignment
*);
421 void (*free
)(const char*);
422 } type_handlers
[] = {
436 "struct getarg_strings",
453 { NULL
, NULL
, NULL
, NULL
, NULL
}
456 static struct type_handler
*find_handler
(struct assignment
*type
)
458 struct type_handler
*th
;
459 for
(th
= type_handlers
; th
->typename
!= NULL
; th
++)
460 if
(strcmp
(type
->u.value
, th
->typename
) == 0)
462 ex
(type
, "unknown type \"%s\"", type
->u.value
);
467 gen_options
(struct assignment
*opt1
, const char *name
)
469 struct assignment
*tmp
;
471 hprint
(0, "struct %s_options {\n", name
);
475 tmp
= find_next
(tmp
, "option")) {
476 struct assignment
*type
;
477 struct type_handler
*th
;
480 s
= make_name
(tmp
->u.assignment
);
481 type
= find
(tmp
->u.assignment
, "type");
482 th
= find_handler
(type
);
483 hprint
(1, "%s %s;\n", th
->c_type
, s
);
490 gen_wrapper
(struct assignment
*as
)
492 struct assignment
*name
;
493 struct assignment
*arg
;
494 struct assignment
*opt1
;
495 struct assignment
*function
;
496 struct assignment
*tmp
;
501 name
= find
(as
, "name");
502 n
= strdup
(name
->u.value
);
504 arg
= find
(as
, "argument");
507 opt1
= find
(as
, "option");
508 function
= find
(as
, "function");
510 f
= function
->u.value
;
516 gen_options
(opt1
, n
);
517 hprint
(0, "int %s(struct %s_options*, int, char **);\n", f
, n
);
519 hprint
(0, "int %s(void*, int, char **);\n", f
);
522 fprintf
(cfile
, "static int\n");
523 fprintf
(cfile
, "%s_wrap(int argc, char **argv)\n", n
);
524 fprintf
(cfile
, "{\n");
526 cprint
(1, "struct %s_options opt;\n", n
);
527 cprint
(1, "int ret;\n");
528 cprint
(1, "int optidx = 0;\n");
529 cprint
(1, "struct getargs args[] = {\n");
530 for
(tmp
= find
(as
, "option");
532 tmp
= find_next
(tmp
, "option")) {
533 struct assignment
*type
= find
(tmp
->u.assignment
, "type");
534 struct assignment
*lopt
= find
(tmp
->u.assignment
, "long");
535 struct assignment
*sopt
= find
(tmp
->u.assignment
, "short");
536 struct assignment
*aarg
= find
(tmp
->u.assignment
, "argument");
537 struct assignment
*help
= find
(tmp
->u.assignment
, "help");
539 struct type_handler
*th
;
543 fprintf
(cfile
, "\"%s\", ", lopt
->u.value
);
545 fprintf
(cfile
, "NULL, ");
547 fprintf
(cfile
, "'%c', ", *sopt
->u.value
);
549 fprintf
(cfile
, "0, ");
550 th
= find_handler
(type
);
551 fprintf
(cfile
, "%s, ", th
->getarg_type
);
552 fprintf
(cfile
, "NULL, ");
554 fprintf
(cfile
, "\"%s\", ", help
->u.value
);
556 fprintf
(cfile
, "NULL, ");
558 fprintf
(cfile
, "\"%s\"", aarg
->u.value
);
561 fprintf
(cfile
, "NULL");
562 fprintf
(cfile
, " },\n");
564 cprint
(2, "{ \"help\", 'h', arg_flag, NULL, NULL, NULL }\n");
566 cprint
(1, "int help_flag = 0;\n");
568 for
(tmp
= find
(as
, "option");
570 tmp
= find_next
(tmp
, "option")) {
572 struct assignment
*type
= find
(tmp
->u.assignment
, "type");
574 struct assignment
*defval
= find
(tmp
->u.assignment
, "default");
576 struct type_handler
*th
;
578 s
= make_name
(tmp
->u.assignment
);
579 th
= find_handler
(type
);
580 (*th
->defval
)(s
, defval
);
584 for
(tmp
= find
(as
, "option");
586 tmp
= find_next
(tmp
, "option")) {
588 s
= make_name
(tmp
->u.assignment
);
589 cprint
(1, "args[%d].value = &opt.%s;\n", nargs
++, s
);
592 cprint
(1, "args[%d].value = &help_flag;\n", nargs
++);
593 cprint
(1, "if(getarg(args, %d, argc, argv, &optidx))\n", nargs
);
594 cprint
(2, "goto usage;\n");
600 if
(narguments
== 0) {
603 if
((tmp
= find
(as
, "min_args")) != NULL
) {
604 min_args
= strtol
(tmp
->u.value
, &end
, 0);
606 ex
(tmp
, "min_args is not numeric");
610 ex
(tmp
, "min_args must be non-negative");
614 if
((tmp
= find
(as
, "max_args")) != NULL
) {
615 max_args
= strtol
(tmp
->u.value
, &end
, 0);
617 ex
(tmp
, "max_args is not numeric");
621 ex
(tmp
, "max_args must be non-negative");
626 if
(min_args
!= -1 || max_args
!= -1) {
627 if
(min_args
== max_args
) {
628 cprint
(1, "if(argc - optidx != %d) {\n",
630 cprint
(2, "fprintf(stderr, \"Need exactly %u parameters (%%u given).\\n\\n\", argc - optidx);\n", min_args
);
631 cprint
(2, "goto usage;\n");
635 cprint
(1, "if(argc - optidx > %d) {\n", max_args
);
636 cprint
(2, "fprintf(stderr, \"Arguments given (%%u) are more than expected (%u).\\n\\n\", argc - optidx);\n", max_args
);
637 cprint
(2, "goto usage;\n");
641 cprint
(1, "if(argc - optidx < %d) {\n", min_args
);
642 cprint
(2, "fprintf(stderr, \"Arguments given (%%u) are less than expected (%u).\\n\\n\", argc - optidx);\n", min_args
);
643 cprint
(2, "goto usage;\n");
650 cprint
(1, "if(help_flag)\n");
651 cprint
(2, "goto usage;\n");
653 cprint
(1, "ret = %s(%s, argc - optidx, argv + optidx);\n",
654 f
, opt1 ?
"&opt": "NULL");
656 /* free allocated data */
657 for
(tmp
= find
(as
, "option");
659 tmp
= find_next
(tmp
, "option")) {
661 struct assignment
*type
= find
(tmp
->u.assignment
, "type");
662 struct type_handler
*th
;
663 th
= find_handler
(type
);
666 s
= make_name
(tmp
->u.assignment
);
670 cprint
(1, "return ret;\n");
672 cprint
(0, "usage:\n");
673 cprint
(1, "arg_printusage (args, %d, \"%s\", \"%s\");\n", nargs
,
674 name
->u.value
, arg ? arg
->u.value
: "");
675 /* free allocated data */
676 for
(tmp
= find
(as
, "option");
678 tmp
= find_next
(tmp
, "option")) {
680 struct assignment
*type
= find
(tmp
->u.assignment
, "type");
681 struct type_handler
*th
;
682 th
= find_handler
(type
);
685 s
= make_name
(tmp
->u.assignment
);
689 cprint
(1, "return 1;\n");
695 char cname
[PATH_MAX
];
696 char hname
[PATH_MAX
];
699 gen
(struct assignment
*as
)
701 struct assignment
*a
;
702 cprint
(0, "#include <stdio.h>\n");
703 cprint
(0, "#include <stdint.h>\n");
704 cprint
(0, "#include <getarg.h>\n");
705 cprint
(0, "#include <sl.h>\n");
706 cprint
(0, "#include \"%s\"\n\n", hname
);
708 hprint
(0, "#include <stdio.h>\n");
709 hprint
(0, "#include <sl.h>\n");
713 for
(a
= as
; a
!= NULL
; a
= a
->next
)
714 gen_wrapper
(a
->u.assignment
);
716 cprint
(0, "SL_cmd commands[] = {\n");
717 for
(a
= as
; a
!= NULL
; a
= a
->next
)
718 gen_command
(a
->u.assignment
);
719 cprint
(1, "{ NULL, NULL, NULL, NULL }\n");
722 hprint
(0, "extern SL_cmd commands[];\n");
727 struct getargs args
[] = {
728 { "version", 0, arg_flag
, &version_flag
, NULL
, NULL
},
729 { "help", 0, arg_flag
, &help_flag
, NULL
, NULL
}
731 int num_args
= sizeof
(args
) / sizeof
(args
[0]);
736 arg_printusage
(args
, num_args
, NULL
, "command-table");
741 main
(int argc
, char **argv
)
747 setprogname
(argv
[0]);
748 if
(getarg
(args
, num_args
, argc
, argv
, &optidx
))
760 filename
= argv
[optidx
];
761 yyin
= fopen
(filename
, "r");
763 err
(1, "%s", filename
);
764 p
= strrchr
(filename
, '/');
766 strlcpy
(cname
, p
+ 1, sizeof
(cname
));
768 strlcpy
(cname
, filename
, sizeof
(cname
));
769 p
= strrchr
(cname
, '.');
772 strlcpy
(hname
, cname
, sizeof
(hname
));
773 strlcat
(cname
, ".c", sizeof
(cname
));
774 strlcat
(hname
, ".h", sizeof
(hname
));
778 if
(check
(assignment
) == 0) {
779 cfile
= fopen
(cname
, "w");
782 hfile
= fopen
(hname
, "w");