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