1178825Sdfr%{ 2178825Sdfr/* 3233294Sstas * Copyright (c) 2004-2006 Kungliga Tekniska H��gskolan 4233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 5233294Sstas * All rights reserved. 6178825Sdfr * 7233294Sstas * Redistribution and use in source and binary forms, with or without 8233294Sstas * modification, are permitted provided that the following conditions 9233294Sstas * are met: 10178825Sdfr * 11233294Sstas * 1. Redistributions of source code must retain the above copyright 12233294Sstas * notice, this list of conditions and the following disclaimer. 13178825Sdfr * 14233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 15233294Sstas * notice, this list of conditions and the following disclaimer in the 16233294Sstas * documentation and/or other materials provided with the distribution. 17178825Sdfr * 18233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 19233294Sstas * may be used to endorse or promote products derived from this software 20233294Sstas * without specific prior written permission. 21178825Sdfr * 22233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 23233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 26233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32233294Sstas * SUCH DAMAGE. 33178825Sdfr */ 34178825Sdfr 35178825Sdfr#include <config.h> 36178825Sdfr 37178825Sdfr#include <stdio.h> 38178825Sdfr#include <stdlib.h> 39178825Sdfr#include <err.h> 40178825Sdfr#include <ctype.h> 41178825Sdfr#include <limits.h> 42178825Sdfr#include <getarg.h> 43178825Sdfr#include <vers.h> 44178825Sdfr#include <roken.h> 45178825Sdfr 46178825Sdfr#include "slc.h" 47178825Sdfrextern FILE *yyin; 48178825Sdfrextern struct assignment *assignment; 49222081Sbenlextern int yyparse(void); 50233294Sstas 51233294Sstas/* Declarations for Bison: 52233294Sstas */ 53233294Sstas#define YYMALLOC malloc 54233294Sstas#define YYFREE free 55233294Sstas 56178825Sdfr%} 57178825Sdfr 58178825Sdfr%union { 59178825Sdfr char *string; 60178825Sdfr struct assignment *assignment; 61178825Sdfr} 62178825Sdfr 63178825Sdfr%token <string> LITERAL 64178825Sdfr%token <string> STRING 65178825Sdfr%type <assignment> assignment assignments 66178825Sdfr 67178825Sdfr%start start 68178825Sdfr 69178825Sdfr%% 70178825Sdfr 71178825Sdfrstart : assignments 72178825Sdfr { 73178825Sdfr assignment = $1; 74178825Sdfr } 75178825Sdfr ; 76178825Sdfr 77178825Sdfrassignments : assignment assignments 78178825Sdfr { 79178825Sdfr $1->next = $2; 80178825Sdfr $$ = $1; 81178825Sdfr } 82178825Sdfr | assignment 83178825Sdfr ; 84178825Sdfr 85178825Sdfrassignment : LITERAL '=' STRING 86178825Sdfr { 87178825Sdfr $$ = malloc(sizeof(*$$)); 88178825Sdfr $$->name = $1; 89178825Sdfr $$->type = a_value; 90178825Sdfr $$->lineno = lineno; 91178825Sdfr $$->u.value = $3; 92178825Sdfr $$->next = NULL; 93178825Sdfr } 94178825Sdfr | LITERAL '=' '{' assignments '}' 95178825Sdfr { 96178825Sdfr $$ = malloc(sizeof(*$$)); 97178825Sdfr $$->name = $1; 98178825Sdfr $$->type = a_assignment; 99178825Sdfr $$->lineno = lineno; 100178825Sdfr $$->u.assignment = $4; 101178825Sdfr $$->next = NULL; 102178825Sdfr } 103178825Sdfr ; 104178825Sdfr 105178825Sdfr%% 106178825Sdfrchar *filename; 107178825SdfrFILE *cfile, *hfile; 108178825Sdfrint error_flag; 109178825Sdfrstruct assignment *assignment; 110178825Sdfr 111178825Sdfr 112178825Sdfrstatic void 113178825Sdfrex(struct assignment *a, const char *fmt, ...) 114178825Sdfr{ 115178825Sdfr va_list ap; 116178825Sdfr fprintf(stderr, "%s:%d: ", a->name, a->lineno); 117178825Sdfr va_start(ap, fmt); 118178825Sdfr vfprintf(stderr, fmt, ap); 119178825Sdfr va_end(ap); 120178825Sdfr fprintf(stderr, "\n"); 121178825Sdfr} 122178825Sdfr 123178825Sdfr 124178825Sdfr 125178825Sdfrstatic int 126178825Sdfrcheck_option(struct assignment *as) 127178825Sdfr{ 128178825Sdfr struct assignment *a; 129178825Sdfr int seen_long = 0; 130233294Sstas int seen_name = 0; 131178825Sdfr int seen_short = 0; 132178825Sdfr int seen_type = 0; 133178825Sdfr int seen_argument = 0; 134178825Sdfr int seen_help = 0; 135178825Sdfr int seen_default = 0; 136178825Sdfr int ret = 0; 137178825Sdfr 138178825Sdfr for(a = as; a != NULL; a = a->next) { 139178825Sdfr if(strcmp(a->name, "long") == 0) 140178825Sdfr seen_long++; 141178825Sdfr else if(strcmp(a->name, "short") == 0) 142178825Sdfr seen_short++; 143233294Sstas else if(strcmp(a->name, "name") == 0) 144233294Sstas seen_name++; 145178825Sdfr else if(strcmp(a->name, "type") == 0) 146178825Sdfr seen_type++; 147178825Sdfr else if(strcmp(a->name, "argument") == 0) 148178825Sdfr seen_argument++; 149178825Sdfr else if(strcmp(a->name, "help") == 0) 150178825Sdfr seen_help++; 151178825Sdfr else if(strcmp(a->name, "default") == 0) 152178825Sdfr seen_default++; 153178825Sdfr else { 154233294Sstas ex(a, "unknown name %s", a->name); 155178825Sdfr ret++; 156178825Sdfr } 157178825Sdfr } 158178825Sdfr if(seen_long == 0 && seen_short == 0) { 159178825Sdfr ex(as, "neither long nor short option"); 160178825Sdfr ret++; 161178825Sdfr } 162233294Sstas if (seen_long == 0 && seen_name == 0) { 163233294Sstas ex(as, "either of long or name option must be used"); 164233294Sstas ret++; 165233294Sstas } 166178825Sdfr if(seen_long > 1) { 167178825Sdfr ex(as, "multiple long options"); 168178825Sdfr ret++; 169178825Sdfr } 170178825Sdfr if(seen_short > 1) { 171178825Sdfr ex(as, "multiple short options"); 172178825Sdfr ret++; 173178825Sdfr } 174178825Sdfr if(seen_type > 1) { 175178825Sdfr ex(as, "multiple types"); 176178825Sdfr ret++; 177178825Sdfr } 178178825Sdfr if(seen_argument > 1) { 179178825Sdfr ex(as, "multiple arguments"); 180178825Sdfr ret++; 181178825Sdfr } 182178825Sdfr if(seen_help > 1) { 183178825Sdfr ex(as, "multiple help strings"); 184178825Sdfr ret++; 185178825Sdfr } 186178825Sdfr if(seen_default > 1) { 187178825Sdfr ex(as, "multiple default values"); 188178825Sdfr ret++; 189178825Sdfr } 190178825Sdfr return ret; 191178825Sdfr} 192178825Sdfr 193178825Sdfrstatic int 194178825Sdfrcheck_command(struct assignment *as) 195178825Sdfr{ 196178825Sdfr struct assignment *a; 197178825Sdfr int seen_name = 0; 198178825Sdfr int seen_function = 0; 199178825Sdfr int seen_help = 0; 200178825Sdfr int seen_argument = 0; 201178825Sdfr int seen_minargs = 0; 202178825Sdfr int seen_maxargs = 0; 203178825Sdfr int ret = 0; 204178825Sdfr for(a = as; a != NULL; a = a->next) { 205178825Sdfr if(strcmp(a->name, "name") == 0) 206178825Sdfr seen_name++; 207178825Sdfr else if(strcmp(a->name, "function") == 0) { 208178825Sdfr seen_function++; 209178825Sdfr } else if(strcmp(a->name, "option") == 0) 210178825Sdfr ret += check_option(a->u.assignment); 211178825Sdfr else if(strcmp(a->name, "help") == 0) { 212178825Sdfr seen_help++; 213178825Sdfr } else if(strcmp(a->name, "argument") == 0) { 214178825Sdfr seen_argument++; 215178825Sdfr } else if(strcmp(a->name, "min_args") == 0) { 216178825Sdfr seen_minargs++; 217178825Sdfr } else if(strcmp(a->name, "max_args") == 0) { 218178825Sdfr seen_maxargs++; 219178825Sdfr } else { 220233294Sstas ex(a, "unknown name: %s", a->name); 221178825Sdfr ret++; 222178825Sdfr } 223178825Sdfr } 224178825Sdfr if(seen_name == 0) { 225178825Sdfr ex(as, "no command name"); 226178825Sdfr ret++; 227178825Sdfr } 228178825Sdfr if(seen_function > 1) { 229178825Sdfr ex(as, "multiple function names"); 230178825Sdfr ret++; 231178825Sdfr } 232178825Sdfr if(seen_help > 1) { 233178825Sdfr ex(as, "multiple help strings"); 234178825Sdfr ret++; 235178825Sdfr } 236178825Sdfr if(seen_argument > 1) { 237178825Sdfr ex(as, "multiple argument strings"); 238178825Sdfr ret++; 239178825Sdfr } 240178825Sdfr if(seen_minargs > 1) { 241178825Sdfr ex(as, "multiple min_args strings"); 242178825Sdfr ret++; 243178825Sdfr } 244178825Sdfr if(seen_maxargs > 1) { 245178825Sdfr ex(as, "multiple max_args strings"); 246178825Sdfr ret++; 247178825Sdfr } 248233294Sstas 249178825Sdfr return ret; 250178825Sdfr} 251178825Sdfr 252178825Sdfrstatic int 253178825Sdfrcheck(struct assignment *as) 254178825Sdfr{ 255178825Sdfr struct assignment *a; 256178825Sdfr int ret = 0; 257178825Sdfr for(a = as; a != NULL; a = a->next) { 258178825Sdfr if(strcmp(a->name, "command")) { 259178825Sdfr fprintf(stderr, "unknown type %s line %d\n", a->name, a->lineno); 260178825Sdfr ret++; 261178825Sdfr continue; 262178825Sdfr } 263178825Sdfr if(a->type != a_assignment) { 264178825Sdfr fprintf(stderr, "bad command definition %s line %d\n", a->name, a->lineno); 265178825Sdfr ret++; 266178825Sdfr continue; 267178825Sdfr } 268178825Sdfr ret += check_command(a->u.assignment); 269178825Sdfr } 270178825Sdfr return ret; 271178825Sdfr} 272178825Sdfr 273178825Sdfrstatic struct assignment * 274178825Sdfrfind_next(struct assignment *as, const char *name) 275178825Sdfr{ 276178825Sdfr for(as = as->next; as != NULL; as = as->next) { 277178825Sdfr if(strcmp(as->name, name) == 0) 278178825Sdfr return as; 279178825Sdfr } 280178825Sdfr return NULL; 281178825Sdfr} 282178825Sdfr 283178825Sdfrstatic struct assignment * 284178825Sdfrfind(struct assignment *as, const char *name) 285178825Sdfr{ 286178825Sdfr for(; as != NULL; as = as->next) { 287178825Sdfr if(strcmp(as->name, name) == 0) 288178825Sdfr return as; 289178825Sdfr } 290178825Sdfr return NULL; 291178825Sdfr} 292178825Sdfr 293178825Sdfrstatic void 294178825Sdfrspace(FILE *f, int level) 295178825Sdfr{ 296178825Sdfr fprintf(f, "%*.*s", level * 4, level * 4, " "); 297178825Sdfr} 298178825Sdfr 299178825Sdfrstatic void 300178825Sdfrcprint(int level, const char *fmt, ...) 301178825Sdfr{ 302178825Sdfr va_list ap; 303178825Sdfr va_start(ap, fmt); 304178825Sdfr space(cfile, level); 305178825Sdfr vfprintf(cfile, fmt, ap); 306178825Sdfr va_end(ap); 307178825Sdfr} 308178825Sdfr 309178825Sdfrstatic void 310178825Sdfrhprint(int level, const char *fmt, ...) 311178825Sdfr{ 312178825Sdfr va_list ap; 313178825Sdfr va_start(ap, fmt); 314178825Sdfr space(hfile, level); 315178825Sdfr vfprintf(hfile, fmt, ap); 316178825Sdfr va_end(ap); 317178825Sdfr} 318178825Sdfr 319178825Sdfrstatic void gen_name(char *str); 320178825Sdfr 321178825Sdfrstatic void 322178825Sdfrgen_command(struct assignment *as) 323178825Sdfr{ 324178825Sdfr struct assignment *a, *b; 325178825Sdfr char *f; 326178825Sdfr a = find(as, "name"); 327178825Sdfr f = strdup(a->u.value); 328178825Sdfr gen_name(f); 329178825Sdfr cprint(1, " { "); 330178825Sdfr fprintf(cfile, "\"%s\", ", a->u.value); 331178825Sdfr fprintf(cfile, "%s_wrap, ", f); 332178825Sdfr b = find(as, "argument"); 333178825Sdfr if(b) 334178825Sdfr fprintf(cfile, "\"%s %s\", ", a->u.value, b->u.value); 335178825Sdfr else 336178825Sdfr fprintf(cfile, "\"%s\", ", a->u.value); 337178825Sdfr b = find(as, "help"); 338178825Sdfr if(b) 339178825Sdfr fprintf(cfile, "\"%s\"", b->u.value); 340178825Sdfr else 341178825Sdfr fprintf(cfile, "NULL"); 342178825Sdfr fprintf(cfile, " },\n"); 343178825Sdfr for(a = a->next; a != NULL; a = a->next) 344178825Sdfr if(strcmp(a->name, "name") == 0) 345178825Sdfr cprint(1, " { \"%s\" },\n", a->u.value); 346178825Sdfr cprint(0, "\n"); 347178825Sdfr} 348178825Sdfr 349178825Sdfrstatic void 350178825Sdfrgen_name(char *str) 351178825Sdfr{ 352178825Sdfr char *p; 353178825Sdfr for(p = str; *p != '\0'; p++) 354178825Sdfr if(!isalnum((unsigned char)*p)) 355178825Sdfr *p = '_'; 356178825Sdfr} 357178825Sdfr 358178825Sdfrstatic char * 359178825Sdfrmake_name(struct assignment *as) 360178825Sdfr{ 361178825Sdfr struct assignment *lopt; 362178825Sdfr struct assignment *type; 363178825Sdfr char *s; 364178825Sdfr 365178825Sdfr lopt = find(as, "long"); 366178825Sdfr if(lopt == NULL) 367178825Sdfr lopt = find(as, "name"); 368178825Sdfr if(lopt == NULL) 369178825Sdfr return NULL; 370233294Sstas 371178825Sdfr type = find(as, "type"); 372178825Sdfr if(strcmp(type->u.value, "-flag") == 0) 373178825Sdfr asprintf(&s, "%s_flag", lopt->u.value); 374178825Sdfr else 375178825Sdfr asprintf(&s, "%s_%s", lopt->u.value, type->u.value); 376178825Sdfr gen_name(s); 377178825Sdfr return s; 378178825Sdfr} 379178825Sdfr 380178825Sdfr 381178825Sdfrstatic void defval_int(const char *name, struct assignment *defval) 382178825Sdfr{ 383178825Sdfr if(defval != NULL) 384178825Sdfr cprint(1, "opt.%s = %s;\n", name, defval->u.value); 385178825Sdfr else 386178825Sdfr cprint(1, "opt.%s = 0;\n", name); 387178825Sdfr} 388233294Sstasstatic void defval_neg_flag(const char *name, struct assignment *defval) 389178825Sdfr{ 390178825Sdfr if(defval != NULL) 391233294Sstas cprint(1, "opt.%s = %s;\n", name, defval->u.value); 392178825Sdfr else 393233294Sstas cprint(1, "opt.%s = 1;\n", name); 394233294Sstas} 395233294Sstasstatic void defval_string(const char *name, struct assignment *defval) 396233294Sstas{ 397233294Sstas if(defval != NULL) 398233294Sstas cprint(1, "opt.%s = (char *)(unsigned long)\"%s\";\n", name, defval->u.value); 399233294Sstas else 400178825Sdfr cprint(1, "opt.%s = NULL;\n", name); 401178825Sdfr} 402178825Sdfrstatic void defval_strings(const char *name, struct assignment *defval) 403178825Sdfr{ 404178825Sdfr cprint(1, "opt.%s.num_strings = 0;\n", name); 405178825Sdfr cprint(1, "opt.%s.strings = NULL;\n", name); 406178825Sdfr} 407178825Sdfr 408178825Sdfrstatic void free_strings(const char *name) 409178825Sdfr{ 410178825Sdfr cprint(1, "free_getarg_strings (&opt.%s);\n", name); 411178825Sdfr} 412178825Sdfr 413178825Sdfrstruct type_handler { 414178825Sdfr const char *typename; 415178825Sdfr const char *c_type; 416178825Sdfr const char *getarg_type; 417178825Sdfr void (*defval)(const char*, struct assignment*); 418178825Sdfr void (*free)(const char*); 419178825Sdfr} type_handlers[] = { 420178825Sdfr { "integer", 421178825Sdfr "int", 422178825Sdfr "arg_integer", 423178825Sdfr defval_int, 424178825Sdfr NULL 425178825Sdfr }, 426178825Sdfr { "string", 427178825Sdfr "char*", 428178825Sdfr "arg_string", 429178825Sdfr defval_string, 430178825Sdfr NULL 431178825Sdfr }, 432178825Sdfr { "strings", 433178825Sdfr "struct getarg_strings", 434178825Sdfr "arg_strings", 435178825Sdfr defval_strings, 436178825Sdfr free_strings 437178825Sdfr }, 438178825Sdfr { "flag", 439178825Sdfr "int", 440178825Sdfr "arg_flag", 441178825Sdfr defval_int, 442178825Sdfr NULL 443178825Sdfr }, 444178825Sdfr { "-flag", 445178825Sdfr "int", 446178825Sdfr "arg_negative_flag", 447233294Sstas defval_neg_flag, 448178825Sdfr NULL 449178825Sdfr }, 450178825Sdfr { NULL } 451178825Sdfr}; 452178825Sdfr 453178825Sdfrstatic struct type_handler *find_handler(struct assignment *type) 454178825Sdfr{ 455178825Sdfr struct type_handler *th; 456178825Sdfr for(th = type_handlers; th->typename != NULL; th++) 457178825Sdfr if(strcmp(type->u.value, th->typename) == 0) 458178825Sdfr return th; 459178825Sdfr ex(type, "unknown type \"%s\"", type->u.value); 460178825Sdfr exit(1); 461178825Sdfr} 462178825Sdfr 463178825Sdfrstatic void 464178825Sdfrgen_options(struct assignment *opt1, const char *name) 465178825Sdfr{ 466178825Sdfr struct assignment *tmp; 467178825Sdfr 468178825Sdfr hprint(0, "struct %s_options {\n", name); 469178825Sdfr 470233294Sstas for(tmp = opt1; 471233294Sstas tmp != NULL; 472178825Sdfr tmp = find_next(tmp, "option")) { 473178825Sdfr struct assignment *type; 474178825Sdfr struct type_handler *th; 475178825Sdfr char *s; 476233294Sstas 477178825Sdfr s = make_name(tmp->u.assignment); 478178825Sdfr type = find(tmp->u.assignment, "type"); 479178825Sdfr th = find_handler(type); 480178825Sdfr hprint(1, "%s %s;\n", th->c_type, s); 481178825Sdfr free(s); 482178825Sdfr } 483178825Sdfr hprint(0, "};\n"); 484178825Sdfr} 485178825Sdfr 486178825Sdfrstatic void 487178825Sdfrgen_wrapper(struct assignment *as) 488178825Sdfr{ 489178825Sdfr struct assignment *name; 490178825Sdfr struct assignment *arg; 491178825Sdfr struct assignment *opt1; 492178825Sdfr struct assignment *function; 493178825Sdfr struct assignment *tmp; 494178825Sdfr char *n, *f; 495178825Sdfr int nargs = 0; 496233294Sstas int narguments = 0; 497178825Sdfr 498178825Sdfr name = find(as, "name"); 499178825Sdfr n = strdup(name->u.value); 500178825Sdfr gen_name(n); 501178825Sdfr arg = find(as, "argument"); 502233294Sstas if (arg) 503233294Sstas narguments++; 504178825Sdfr opt1 = find(as, "option"); 505178825Sdfr function = find(as, "function"); 506178825Sdfr if(function) 507178825Sdfr f = function->u.value; 508178825Sdfr else 509178825Sdfr f = n; 510233294Sstas 511233294Sstas 512178825Sdfr if(opt1 != NULL) { 513178825Sdfr gen_options(opt1, n); 514178825Sdfr hprint(0, "int %s(struct %s_options*, int, char **);\n", f, n); 515178825Sdfr } else { 516178825Sdfr hprint(0, "int %s(void*, int, char **);\n", f); 517178825Sdfr } 518178825Sdfr 519178825Sdfr fprintf(cfile, "static int\n"); 520178825Sdfr fprintf(cfile, "%s_wrap(int argc, char **argv)\n", n); 521178825Sdfr fprintf(cfile, "{\n"); 522178825Sdfr if(opt1 != NULL) 523178825Sdfr cprint(1, "struct %s_options opt;\n", n); 524178825Sdfr cprint(1, "int ret;\n"); 525178825Sdfr cprint(1, "int optidx = 0;\n"); 526178825Sdfr cprint(1, "struct getargs args[] = {\n"); 527233294Sstas for(tmp = find(as, "option"); 528233294Sstas tmp != NULL; 529178825Sdfr tmp = find_next(tmp, "option")) { 530178825Sdfr struct assignment *type = find(tmp->u.assignment, "type"); 531178825Sdfr struct assignment *lopt = find(tmp->u.assignment, "long"); 532178825Sdfr struct assignment *sopt = find(tmp->u.assignment, "short"); 533178825Sdfr struct assignment *aarg = find(tmp->u.assignment, "argument"); 534178825Sdfr struct assignment *help = find(tmp->u.assignment, "help"); 535178825Sdfr 536178825Sdfr struct type_handler *th; 537233294Sstas 538178825Sdfr cprint(2, "{ "); 539178825Sdfr if(lopt) 540178825Sdfr fprintf(cfile, "\"%s\", ", lopt->u.value); 541178825Sdfr else 542178825Sdfr fprintf(cfile, "NULL, "); 543178825Sdfr if(sopt) 544178825Sdfr fprintf(cfile, "'%c', ", *sopt->u.value); 545178825Sdfr else 546178825Sdfr fprintf(cfile, "0, "); 547178825Sdfr th = find_handler(type); 548178825Sdfr fprintf(cfile, "%s, ", th->getarg_type); 549178825Sdfr fprintf(cfile, "NULL, "); 550178825Sdfr if(help) 551178825Sdfr fprintf(cfile, "\"%s\", ", help->u.value); 552178825Sdfr else 553178825Sdfr fprintf(cfile, "NULL, "); 554233294Sstas if(aarg) { 555178825Sdfr fprintf(cfile, "\"%s\"", aarg->u.value); 556233294Sstas narguments++; 557233294Sstas } else 558178825Sdfr fprintf(cfile, "NULL"); 559178825Sdfr fprintf(cfile, " },\n"); 560178825Sdfr } 561178825Sdfr cprint(2, "{ \"help\", 'h', arg_flag, NULL, NULL, NULL }\n"); 562178825Sdfr cprint(1, "};\n"); 563178825Sdfr cprint(1, "int help_flag = 0;\n"); 564178825Sdfr 565233294Sstas for(tmp = find(as, "option"); 566233294Sstas tmp != NULL; 567178825Sdfr tmp = find_next(tmp, "option")) { 568178825Sdfr char *s; 569178825Sdfr struct assignment *type = find(tmp->u.assignment, "type"); 570178825Sdfr 571178825Sdfr struct assignment *defval = find(tmp->u.assignment, "default"); 572178825Sdfr 573178825Sdfr struct type_handler *th; 574233294Sstas 575178825Sdfr s = make_name(tmp->u.assignment); 576178825Sdfr th = find_handler(type); 577178825Sdfr (*th->defval)(s, defval); 578178825Sdfr free(s); 579178825Sdfr } 580178825Sdfr 581233294Sstas for(tmp = find(as, "option"); 582233294Sstas tmp != NULL; 583178825Sdfr tmp = find_next(tmp, "option")) { 584178825Sdfr char *s; 585178825Sdfr s = make_name(tmp->u.assignment); 586178825Sdfr cprint(1, "args[%d].value = &opt.%s;\n", nargs++, s); 587178825Sdfr free(s); 588178825Sdfr } 589178825Sdfr cprint(1, "args[%d].value = &help_flag;\n", nargs++); 590178825Sdfr cprint(1, "if(getarg(args, %d, argc, argv, &optidx))\n", nargs); 591178825Sdfr cprint(2, "goto usage;\n"); 592178825Sdfr 593178825Sdfr { 594178825Sdfr int min_args = -1; 595178825Sdfr int max_args = -1; 596178825Sdfr char *end; 597233294Sstas if(narguments == 0) { 598178825Sdfr max_args = 0; 599178825Sdfr } else { 600178825Sdfr if((tmp = find(as, "min_args")) != NULL) { 601178825Sdfr min_args = strtol(tmp->u.value, &end, 0); 602178825Sdfr if(*end != '\0') { 603178825Sdfr ex(tmp, "min_args is not numeric"); 604178825Sdfr exit(1); 605178825Sdfr } 606178825Sdfr if(min_args < 0) { 607178825Sdfr ex(tmp, "min_args must be non-negative"); 608178825Sdfr exit(1); 609178825Sdfr } 610178825Sdfr } 611178825Sdfr if((tmp = find(as, "max_args")) != NULL) { 612178825Sdfr max_args = strtol(tmp->u.value, &end, 0); 613178825Sdfr if(*end != '\0') { 614178825Sdfr ex(tmp, "max_args is not numeric"); 615178825Sdfr exit(1); 616178825Sdfr } 617178825Sdfr if(max_args < 0) { 618178825Sdfr ex(tmp, "max_args must be non-negative"); 619178825Sdfr exit(1); 620178825Sdfr } 621178825Sdfr } 622178825Sdfr } 623178825Sdfr if(min_args != -1 || max_args != -1) { 624178825Sdfr if(min_args == max_args) { 625233294Sstas cprint(1, "if(argc - optidx != %d) {\n", 626178825Sdfr min_args); 627178825Sdfr cprint(2, "fprintf(stderr, \"Need exactly %u parameters (%%u given).\\n\\n\", argc - optidx);\n", min_args); 628178825Sdfr cprint(2, "goto usage;\n"); 629178825Sdfr cprint(1, "}\n"); 630178825Sdfr } else { 631178825Sdfr if(max_args != -1) { 632178825Sdfr cprint(1, "if(argc - optidx > %d) {\n", max_args); 633178825Sdfr cprint(2, "fprintf(stderr, \"Arguments given (%%u) are more than expected (%u).\\n\\n\", argc - optidx);\n", max_args); 634178825Sdfr cprint(2, "goto usage;\n"); 635178825Sdfr cprint(1, "}\n"); 636178825Sdfr } 637178825Sdfr if(min_args != -1) { 638178825Sdfr cprint(1, "if(argc - optidx < %d) {\n", min_args); 639178825Sdfr cprint(2, "fprintf(stderr, \"Arguments given (%%u) are less than expected (%u).\\n\\n\", argc - optidx);\n", min_args); 640178825Sdfr cprint(2, "goto usage;\n"); 641178825Sdfr cprint(1, "}\n"); 642178825Sdfr } 643178825Sdfr } 644178825Sdfr } 645178825Sdfr } 646233294Sstas 647178825Sdfr cprint(1, "if(help_flag)\n"); 648178825Sdfr cprint(2, "goto usage;\n"); 649178825Sdfr 650233294Sstas cprint(1, "ret = %s(%s, argc - optidx, argv + optidx);\n", 651178825Sdfr f, opt1 ? "&opt": "NULL"); 652233294Sstas 653178825Sdfr /* free allocated data */ 654233294Sstas for(tmp = find(as, "option"); 655233294Sstas tmp != NULL; 656178825Sdfr tmp = find_next(tmp, "option")) { 657178825Sdfr char *s; 658178825Sdfr struct assignment *type = find(tmp->u.assignment, "type"); 659178825Sdfr struct type_handler *th; 660178825Sdfr th = find_handler(type); 661178825Sdfr if(th->free == NULL) 662178825Sdfr continue; 663178825Sdfr s = make_name(tmp->u.assignment); 664178825Sdfr (*th->free)(s); 665178825Sdfr free(s); 666178825Sdfr } 667178825Sdfr cprint(1, "return ret;\n"); 668178825Sdfr 669178825Sdfr cprint(0, "usage:\n"); 670233294Sstas cprint(1, "arg_printusage (args, %d, \"%s\", \"%s\");\n", nargs, 671178825Sdfr name->u.value, arg ? arg->u.value : ""); 672178825Sdfr /* free allocated data */ 673233294Sstas for(tmp = find(as, "option"); 674233294Sstas tmp != NULL; 675178825Sdfr tmp = find_next(tmp, "option")) { 676178825Sdfr char *s; 677178825Sdfr struct assignment *type = find(tmp->u.assignment, "type"); 678178825Sdfr struct type_handler *th; 679178825Sdfr th = find_handler(type); 680178825Sdfr if(th->free == NULL) 681178825Sdfr continue; 682178825Sdfr s = make_name(tmp->u.assignment); 683178825Sdfr (*th->free)(s); 684178825Sdfr free(s); 685178825Sdfr } 686178825Sdfr cprint(1, "return 0;\n"); 687178825Sdfr cprint(0, "}\n"); 688178825Sdfr cprint(0, "\n"); 689178825Sdfr} 690178825Sdfr 691178825Sdfrchar cname[PATH_MAX]; 692178825Sdfrchar hname[PATH_MAX]; 693178825Sdfr 694178825Sdfrstatic void 695178825Sdfrgen(struct assignment *as) 696178825Sdfr{ 697178825Sdfr struct assignment *a; 698178825Sdfr cprint(0, "#include <stdio.h>\n"); 699178825Sdfr cprint(0, "#include <getarg.h>\n"); 700178825Sdfr cprint(0, "#include <sl.h>\n"); 701178825Sdfr cprint(0, "#include \"%s\"\n\n", hname); 702178825Sdfr 703178825Sdfr hprint(0, "#include <stdio.h>\n"); 704178825Sdfr hprint(0, "#include <sl.h>\n"); 705178825Sdfr hprint(0, "\n"); 706178825Sdfr 707178825Sdfr 708178825Sdfr for(a = as; a != NULL; a = a->next) 709178825Sdfr gen_wrapper(a->u.assignment); 710178825Sdfr 711178825Sdfr cprint(0, "SL_cmd commands[] = {\n"); 712178825Sdfr for(a = as; a != NULL; a = a->next) 713178825Sdfr gen_command(a->u.assignment); 714178825Sdfr cprint(1, "{ NULL }\n"); 715178825Sdfr cprint(0, "};\n"); 716178825Sdfr 717178825Sdfr hprint(0, "extern SL_cmd commands[];\n"); 718178825Sdfr} 719178825Sdfr 720178825Sdfrint version_flag; 721178825Sdfrint help_flag; 722178825Sdfrstruct getargs args[] = { 723178825Sdfr { "version", 0, arg_flag, &version_flag }, 724178825Sdfr { "help", 0, arg_flag, &help_flag } 725178825Sdfr}; 726178825Sdfrint num_args = sizeof(args) / sizeof(args[0]); 727178825Sdfr 728178825Sdfrstatic void 729178825Sdfrusage(int code) 730178825Sdfr{ 731178825Sdfr arg_printusage(args, num_args, NULL, "command-table"); 732178825Sdfr exit(code); 733178825Sdfr} 734178825Sdfr 735178825Sdfrint 736178825Sdfrmain(int argc, char **argv) 737178825Sdfr{ 738178825Sdfr char *p; 739178825Sdfr 740178825Sdfr int optidx = 0; 741178825Sdfr 742178825Sdfr setprogname(argv[0]); 743178825Sdfr if(getarg(args, num_args, argc, argv, &optidx)) 744178825Sdfr usage(1); 745178825Sdfr if(help_flag) 746178825Sdfr usage(0); 747178825Sdfr if(version_flag) { 748178825Sdfr print_version(NULL); 749178825Sdfr exit(0); 750178825Sdfr } 751233294Sstas 752178825Sdfr if(argc == optidx) 753178825Sdfr usage(1); 754178825Sdfr 755178825Sdfr filename = argv[optidx]; 756178825Sdfr yyin = fopen(filename, "r"); 757178825Sdfr if(yyin == NULL) 758178825Sdfr err(1, "%s", filename); 759178825Sdfr p = strrchr(filename, '/'); 760178825Sdfr if(p) 761178825Sdfr strlcpy(cname, p + 1, sizeof(cname)); 762178825Sdfr else 763178825Sdfr strlcpy(cname, filename, sizeof(cname)); 764178825Sdfr p = strrchr(cname, '.'); 765178825Sdfr if(p) 766178825Sdfr *p = '\0'; 767178825Sdfr strlcpy(hname, cname, sizeof(hname)); 768178825Sdfr strlcat(cname, ".c", sizeof(cname)); 769178825Sdfr strlcat(hname, ".h", sizeof(hname)); 770178825Sdfr yyparse(); 771178825Sdfr if(error_flag) 772178825Sdfr exit(1); 773178825Sdfr if(check(assignment) == 0) { 774178825Sdfr cfile = fopen(cname, "w"); 775178825Sdfr if(cfile == NULL) 776178825Sdfr err(1, "%s", cname); 777178825Sdfr hfile = fopen(hname, "w"); 778178825Sdfr if(hfile == NULL) 779178825Sdfr err(1, "%s", hname); 780178825Sdfr gen(assignment); 781178825Sdfr fclose(cfile); 782178825Sdfr fclose(hfile); 783178825Sdfr } 784178825Sdfr fclose(yyin); 785178825Sdfr return 0; 786178825Sdfr} 787