[15] | 1 | /* parser config.in |
---|
| 2 | * $Id$ |
---|
| 3 | * Version 1.0 |
---|
| 4 | * Eric Youngdale |
---|
| 5 | * 10/95 |
---|
| 6 | * |
---|
| 7 | * The general idea here is that we want to parse a config.in file and |
---|
| 8 | * from this, we generate a wish script which gives us effectively the |
---|
| 9 | * same functionality that the original config.in script provided. |
---|
| 10 | * |
---|
| 11 | * This task is split roughly into 3 parts. The first parse is the parse |
---|
| 12 | * of the input file itself. The second part is where we analyze the |
---|
| 13 | * #ifdef clauses, and attach a linked list of tokens to each of the |
---|
| 14 | * menu items. In this way, each menu item has a complete list of |
---|
| 15 | * dependencies that are used to enable/disable the options. |
---|
| 16 | * The third part is to take the configuration database we have build, |
---|
| 17 | * and build the actual wish script. |
---|
| 18 | * |
---|
| 19 | * This file contains the code to do the first parse of config.in. |
---|
| 20 | */ |
---|
| 21 | #include <stdlib.h> |
---|
| 22 | #include <stdio.h> |
---|
| 23 | #include <string.h> |
---|
| 24 | #include "tkparse.h" |
---|
| 25 | |
---|
| 26 | struct kconfig * config = NULL; |
---|
| 27 | struct kconfig * clast = NULL; |
---|
| 28 | struct kconfig * koption = NULL; |
---|
| 29 | static int lineno = 0; |
---|
| 30 | static int menus_seen = 0; |
---|
| 31 | static char * current_file = NULL; |
---|
| 32 | static int do_source(char * filename); |
---|
| 33 | static char * get_string(char *pnt, char ** labl); |
---|
| 34 | static int choose_number = 0; |
---|
| 35 | |
---|
| 36 | |
---|
| 37 | /* |
---|
| 38 | * Simple function just to skip over spaces and tabs in config.in. |
---|
| 39 | */ |
---|
| 40 | static char * skip_whitespace(char * pnt) |
---|
| 41 | { |
---|
| 42 | while( *pnt && (*pnt == ' ' || *pnt == '\t')) pnt++; |
---|
| 43 | return pnt; |
---|
| 44 | } |
---|
| 45 | |
---|
| 46 | /* |
---|
| 47 | * This function parses a conditional from a config.in (i.e. from an ifdef) |
---|
| 48 | * and generates a linked list of tokens that describes the conditional. |
---|
| 49 | */ |
---|
| 50 | static struct condition * parse_if(char * pnt) |
---|
| 51 | { |
---|
| 52 | char * opnt; |
---|
| 53 | struct condition *list; |
---|
| 54 | struct condition *last; |
---|
| 55 | struct condition *cpnt; |
---|
| 56 | char varname[64]; |
---|
| 57 | char * pnt1; |
---|
| 58 | |
---|
| 59 | opnt = pnt; |
---|
| 60 | |
---|
| 61 | /* |
---|
| 62 | * We need to find the various tokens, and build the linked list. |
---|
| 63 | */ |
---|
| 64 | pnt = skip_whitespace(pnt); |
---|
| 65 | if( *pnt != '[' ) return NULL; |
---|
| 66 | pnt++; |
---|
| 67 | pnt = skip_whitespace(pnt); |
---|
| 68 | |
---|
| 69 | list = last = NULL; |
---|
| 70 | while(*pnt && *pnt != ']') { |
---|
| 71 | |
---|
| 72 | pnt = skip_whitespace(pnt); |
---|
| 73 | if(*pnt== '\0' || *pnt == ']') break; |
---|
| 74 | |
---|
| 75 | /* |
---|
| 76 | * Allocate memory for the token we are about to parse, and insert |
---|
| 77 | * it in the linked list. |
---|
| 78 | */ |
---|
| 79 | cpnt = (struct condition *) malloc(sizeof(struct condition)); |
---|
| 80 | memset(cpnt, 0, sizeof(struct condition)); |
---|
| 81 | if( last == NULL ) |
---|
| 82 | { |
---|
| 83 | list = last = cpnt; |
---|
| 84 | } |
---|
| 85 | else |
---|
| 86 | { |
---|
| 87 | last->next = cpnt; |
---|
| 88 | last = cpnt; |
---|
| 89 | } |
---|
| 90 | |
---|
| 91 | /* |
---|
| 92 | * Determine what type of operation this token represents. |
---|
| 93 | */ |
---|
| 94 | if( *pnt == '-' && pnt[1] == 'a' ) |
---|
| 95 | { |
---|
| 96 | cpnt->op = op_and; |
---|
| 97 | pnt += 2; |
---|
| 98 | continue; |
---|
| 99 | } |
---|
| 100 | |
---|
| 101 | if( *pnt == '-' && pnt[1] == 'o' ) |
---|
| 102 | { |
---|
| 103 | cpnt->op = op_or; |
---|
| 104 | pnt += 2; |
---|
| 105 | continue; |
---|
| 106 | } |
---|
| 107 | |
---|
| 108 | if( *pnt == '!' && pnt[1] == '=' ) |
---|
| 109 | { |
---|
| 110 | cpnt->op = op_neq; |
---|
| 111 | pnt += 2; |
---|
| 112 | continue; |
---|
| 113 | } |
---|
| 114 | |
---|
| 115 | if( *pnt == '=') |
---|
| 116 | { |
---|
| 117 | cpnt->op = op_eq; |
---|
| 118 | pnt += 1; |
---|
| 119 | continue; |
---|
| 120 | } |
---|
| 121 | |
---|
| 122 | if( *pnt == '!') |
---|
| 123 | { |
---|
| 124 | cpnt->op = op_bang; |
---|
| 125 | pnt += 1; |
---|
| 126 | continue; |
---|
| 127 | } |
---|
| 128 | |
---|
| 129 | if( *pnt != '"' ) goto error; /* This cannot be right. */ |
---|
| 130 | pnt++; |
---|
| 131 | if( *pnt == '`' ) |
---|
| 132 | { |
---|
| 133 | cpnt->op = op_shellcmd; |
---|
| 134 | pnt1 = varname; |
---|
| 135 | pnt++; |
---|
| 136 | while(*pnt && *pnt != '`') *pnt1++ = *pnt++; |
---|
| 137 | *pnt1++ = '\0'; |
---|
| 138 | cpnt->variable.str = strdup(varname); |
---|
| 139 | if( *pnt == '`' ) pnt++; |
---|
| 140 | if( *pnt == '"' ) pnt++; |
---|
| 141 | continue; |
---|
| 142 | } |
---|
| 143 | if( *pnt == '$' ) |
---|
| 144 | { |
---|
| 145 | cpnt->op = op_variable; |
---|
| 146 | pnt1 = varname; |
---|
| 147 | pnt++; |
---|
| 148 | while(*pnt && *pnt != '"') *pnt1++ = *pnt++; |
---|
| 149 | *pnt1++ = '\0'; |
---|
| 150 | cpnt->variable.str = strdup(varname); |
---|
| 151 | if( *pnt == '"' ) pnt++; |
---|
| 152 | continue; |
---|
| 153 | } |
---|
| 154 | |
---|
| 155 | cpnt->op = op_constant; |
---|
| 156 | pnt1 = varname; |
---|
| 157 | while(*pnt && *pnt != '"') *pnt1++ = *pnt++; |
---|
| 158 | *pnt1++ = '\0'; |
---|
| 159 | cpnt->variable.str = strdup(varname); |
---|
| 160 | if( *pnt == '"' ) pnt++; |
---|
| 161 | continue; |
---|
| 162 | } |
---|
| 163 | |
---|
| 164 | return list; |
---|
| 165 | |
---|
| 166 | error: |
---|
| 167 | if(current_file != NULL) |
---|
| 168 | fprintf(stderr, |
---|
| 169 | "Bad if clause at line %d(%s):%s\n", lineno, current_file, opnt); |
---|
| 170 | else |
---|
| 171 | fprintf(stderr, |
---|
| 172 | "Bad if clause at line %d:%s\n", lineno, opnt); |
---|
| 173 | return NULL; |
---|
| 174 | } |
---|
| 175 | |
---|
| 176 | /* |
---|
| 177 | * This function looks for a quoted string, from the input buffer, and |
---|
| 178 | * returns a pointer to a copy of this string. Any characters in |
---|
| 179 | * the string that need to be "quoted" have a '\' character inserted |
---|
| 180 | * in front - this way we can directly write these strings into |
---|
| 181 | * wish scripts. |
---|
| 182 | */ |
---|
| 183 | static char * get_qstring(char *pnt, char ** labl) |
---|
| 184 | { |
---|
| 185 | char quotechar; |
---|
| 186 | char newlabel[1024]; |
---|
| 187 | char * pnt1; |
---|
| 188 | char * pnt2; |
---|
| 189 | |
---|
| 190 | while( *pnt && *pnt != '"' && *pnt != '\'') pnt++; |
---|
| 191 | if (*pnt == '\0') return pnt; |
---|
| 192 | |
---|
| 193 | quotechar = *pnt++; |
---|
| 194 | pnt1 = newlabel; |
---|
| 195 | while(*pnt && *pnt != quotechar && pnt[-1] != '\\') |
---|
| 196 | { |
---|
| 197 | /* |
---|
| 198 | * Quote the character if we need to. |
---|
| 199 | */ |
---|
| 200 | if( *pnt == '"' || *pnt == '\'' || *pnt == '[' || *pnt == ']') |
---|
| 201 | *pnt1++ = '\\'; |
---|
| 202 | |
---|
| 203 | *pnt1++ = *pnt++; |
---|
| 204 | } |
---|
| 205 | *pnt1++ = '\0'; |
---|
| 206 | |
---|
| 207 | pnt2 = (char *) malloc(strlen(newlabel) + 1); |
---|
| 208 | strcpy(pnt2, newlabel); |
---|
| 209 | *labl = pnt2; |
---|
| 210 | |
---|
| 211 | /* |
---|
| 212 | * Skip over last quote, and whitespace. |
---|
| 213 | */ |
---|
| 214 | pnt++; |
---|
| 215 | pnt = skip_whitespace(pnt); |
---|
| 216 | return pnt; |
---|
| 217 | } |
---|
| 218 | |
---|
| 219 | static char * parse_choices(struct kconfig * choice_kcfg, char * pnt) |
---|
| 220 | { |
---|
| 221 | struct kconfig * kcfg; |
---|
| 222 | int index = 1; |
---|
| 223 | |
---|
| 224 | /* |
---|
| 225 | * Choices appear in pairs of strings. The parse is fairly trivial. |
---|
| 226 | */ |
---|
| 227 | while(1) |
---|
| 228 | { |
---|
| 229 | pnt = skip_whitespace(pnt); |
---|
| 230 | if(*pnt == '\0') break; |
---|
| 231 | |
---|
| 232 | kcfg = (struct kconfig *) malloc(sizeof(struct kconfig)); |
---|
| 233 | memset(kcfg, 0, sizeof(struct kconfig)); |
---|
| 234 | kcfg->tok = tok_choice; |
---|
| 235 | if( clast != NULL ) |
---|
| 236 | { |
---|
| 237 | clast->next = kcfg; |
---|
| 238 | clast = kcfg; |
---|
| 239 | } |
---|
| 240 | else |
---|
| 241 | { |
---|
| 242 | clast = config = kcfg; |
---|
| 243 | } |
---|
| 244 | |
---|
| 245 | pnt = get_string(pnt, &kcfg->label); |
---|
| 246 | pnt = skip_whitespace(pnt); |
---|
| 247 | pnt = get_string(pnt, &kcfg->optionname); |
---|
| 248 | kcfg->choice_label = choice_kcfg; |
---|
| 249 | kcfg->choice_value = index++; |
---|
| 250 | if( strcmp(kcfg->label, choice_kcfg->value) == 0 ) |
---|
| 251 | choice_kcfg->choice_value = kcfg->choice_value; |
---|
| 252 | } |
---|
| 253 | |
---|
| 254 | return pnt; |
---|
| 255 | } |
---|
| 256 | |
---|
| 257 | |
---|
| 258 | /* |
---|
| 259 | * This function grabs one text token from the input buffer |
---|
| 260 | * and returns a pointer to a copy of just the identifier. |
---|
| 261 | * This can be either a variable name (i.e. CONFIG_NET), |
---|
| 262 | * or it could be the default value for the option. |
---|
| 263 | */ |
---|
| 264 | static char * get_string(char *pnt, char ** labl) |
---|
| 265 | { |
---|
| 266 | char newlabel[1024]; |
---|
| 267 | char * pnt1; |
---|
| 268 | char * pnt2; |
---|
| 269 | |
---|
| 270 | if (*pnt == '\0') return pnt; |
---|
| 271 | |
---|
| 272 | pnt1 = newlabel; |
---|
| 273 | while(*pnt && *pnt != ' ' && *pnt != '\t') |
---|
| 274 | { |
---|
| 275 | *pnt1++ = *pnt++; |
---|
| 276 | } |
---|
| 277 | *pnt1++ = '\0'; |
---|
| 278 | |
---|
| 279 | pnt2 = (char *) malloc(strlen(newlabel) + 1); |
---|
| 280 | strcpy(pnt2, newlabel); |
---|
| 281 | *labl = pnt2; |
---|
| 282 | |
---|
| 283 | if( *pnt ) pnt++; |
---|
| 284 | return pnt; |
---|
| 285 | } |
---|
| 286 | |
---|
| 287 | |
---|
| 288 | /* |
---|
| 289 | * Top level parse function. Input pointer is one complete line from config.in |
---|
| 290 | * and the result is that we create a token that describes this line |
---|
| 291 | * and insert it into our linked list. |
---|
| 292 | */ |
---|
| 293 | void parse(char * pnt) { |
---|
| 294 | enum token tok; |
---|
| 295 | struct kconfig * kcfg; |
---|
| 296 | char tmpbuf[24],fake_if[1024]; |
---|
| 297 | |
---|
| 298 | /* |
---|
| 299 | * Ignore comments and leading whitespace. |
---|
| 300 | */ |
---|
| 301 | |
---|
| 302 | pnt = skip_whitespace(pnt); |
---|
| 303 | while( *pnt && (*pnt == ' ' || *pnt == '\t')) pnt++; |
---|
| 304 | if(! *pnt ) return; |
---|
| 305 | if( *pnt == '#' ) return; |
---|
| 306 | |
---|
| 307 | /* |
---|
| 308 | * Now categorize the next token. |
---|
| 309 | */ |
---|
| 310 | tok = tok_unknown; |
---|
| 311 | if (strncmp(pnt, "mainmenu_name", 13) == 0) |
---|
| 312 | { |
---|
| 313 | tok = tok_menuname; |
---|
| 314 | pnt += 13; |
---|
| 315 | } |
---|
| 316 | else if (strncmp(pnt, "source", 6) == 0) |
---|
| 317 | { |
---|
| 318 | pnt += 7; |
---|
| 319 | pnt = skip_whitespace(pnt); |
---|
| 320 | do_source(pnt); |
---|
| 321 | return; |
---|
| 322 | } |
---|
| 323 | else if (strncmp(pnt, "mainmenu_option", 15) == 0) |
---|
| 324 | { |
---|
| 325 | menus_seen++; |
---|
| 326 | tok = tok_menuoption; |
---|
| 327 | pnt += 15; |
---|
| 328 | } |
---|
| 329 | else if (strncmp(pnt, "$MAKE ", 6) == 0) |
---|
| 330 | { |
---|
| 331 | tok = tok_make; |
---|
| 332 | } |
---|
| 333 | else if (strncmp(pnt, "comment", 7) == 0) |
---|
| 334 | { |
---|
| 335 | tok = tok_comment; |
---|
| 336 | pnt += 7; |
---|
| 337 | } |
---|
| 338 | else if (strncmp(pnt, "choice", 6) == 0) |
---|
| 339 | { |
---|
| 340 | tok = tok_choose; |
---|
| 341 | pnt += 6; |
---|
| 342 | } |
---|
| 343 | else if (strncmp(pnt, "define_bool", 11) == 0) |
---|
| 344 | { |
---|
| 345 | tok = tok_define; |
---|
| 346 | pnt += 11; |
---|
| 347 | } |
---|
| 348 | else if (strncmp(pnt, "bool", 4) == 0) |
---|
| 349 | { |
---|
| 350 | tok = tok_bool; |
---|
| 351 | pnt += 4; |
---|
| 352 | } |
---|
| 353 | else if (strncmp(pnt, "tristate", 8) == 0) |
---|
| 354 | { |
---|
| 355 | tok = tok_tristate; |
---|
| 356 | pnt += 8; |
---|
| 357 | } |
---|
| 358 | else if (strncmp(pnt, "dep_tristate", 12) == 0) |
---|
| 359 | { |
---|
| 360 | tok = tok_dep_tristate; |
---|
| 361 | pnt += 12; |
---|
| 362 | } |
---|
| 363 | else if (strncmp(pnt, "int", 3) == 0) |
---|
| 364 | { |
---|
| 365 | tok = tok_int; |
---|
| 366 | pnt += 3; |
---|
| 367 | } |
---|
| 368 | else if (strncmp(pnt, "hex", 3) == 0) |
---|
| 369 | { |
---|
| 370 | tok = tok_hex; |
---|
| 371 | pnt += 3; |
---|
| 372 | } |
---|
| 373 | else if (strncmp(pnt, "if", 2) == 0) |
---|
| 374 | { |
---|
| 375 | tok = tok_if; |
---|
| 376 | pnt += 2; |
---|
| 377 | } |
---|
| 378 | else if (strncmp(pnt, "else", 4) == 0) |
---|
| 379 | { |
---|
| 380 | tok = tok_else; |
---|
| 381 | pnt += 4; |
---|
| 382 | } |
---|
| 383 | else if (strncmp(pnt, "fi", 2) == 0) |
---|
| 384 | { |
---|
| 385 | tok = tok_fi; |
---|
| 386 | pnt += 2; |
---|
| 387 | } |
---|
| 388 | else if (strncmp(pnt, "endmenu", 7) == 0) |
---|
| 389 | { |
---|
| 390 | tok = tok_endmenu; |
---|
| 391 | pnt += 7; |
---|
| 392 | } |
---|
| 393 | |
---|
| 394 | if( tok == tok_unknown) |
---|
| 395 | { |
---|
| 396 | if( clast != NULL && clast->tok == tok_if |
---|
| 397 | && strcmp(pnt,"then") == 0) return; |
---|
| 398 | if( current_file != NULL ) |
---|
| 399 | fprintf(stderr, "unknown command=%s(%s %d)\n", pnt, |
---|
| 400 | current_file, lineno); |
---|
| 401 | else |
---|
| 402 | fprintf(stderr, "unknown command=%s(%d)\n", pnt,lineno); |
---|
| 403 | return; |
---|
| 404 | } |
---|
| 405 | |
---|
| 406 | /* |
---|
| 407 | * Allocate memory for this item, and attach it to the end of the linked |
---|
| 408 | * list. |
---|
| 409 | */ |
---|
| 410 | kcfg = (struct kconfig *) malloc(sizeof(struct kconfig)); |
---|
| 411 | memset(kcfg, 0, sizeof(struct kconfig)); |
---|
| 412 | kcfg->tok = tok; |
---|
| 413 | if( clast != NULL ) |
---|
| 414 | { |
---|
| 415 | clast->next = kcfg; |
---|
| 416 | clast = kcfg; |
---|
| 417 | } |
---|
| 418 | else |
---|
| 419 | { |
---|
| 420 | clast = config = kcfg; |
---|
| 421 | } |
---|
| 422 | |
---|
| 423 | pnt = skip_whitespace(pnt); |
---|
| 424 | |
---|
| 425 | /* |
---|
| 426 | * Now parse the remaining parts of the option, and attach the results |
---|
| 427 | * to the structure. |
---|
| 428 | */ |
---|
| 429 | switch (tok) |
---|
| 430 | { |
---|
| 431 | case tok_choose: |
---|
| 432 | pnt = get_qstring(pnt, &kcfg->label); |
---|
| 433 | pnt = get_qstring(pnt, &kcfg->optionname); |
---|
| 434 | pnt = get_string(pnt, &kcfg->value); |
---|
| 435 | /* |
---|
| 436 | * Now we need to break apart the individual options into their |
---|
| 437 | * own configuration structures. |
---|
| 438 | */ |
---|
| 439 | parse_choices(kcfg, kcfg->optionname); |
---|
| 440 | free(kcfg->optionname); |
---|
| 441 | sprintf(tmpbuf, "tmpvar_%d", choose_number++); |
---|
| 442 | kcfg->optionname = strdup(tmpbuf); |
---|
| 443 | break; |
---|
| 444 | case tok_define: |
---|
| 445 | pnt = get_string(pnt, &kcfg->optionname); |
---|
| 446 | if(*pnt == 'y' || *pnt == 'Y' ) kcfg->value = "1"; |
---|
| 447 | if(*pnt == 'n' || *pnt == 'N' ) kcfg->value = "0"; |
---|
| 448 | if(*pnt == 'm' || *pnt == 'M' ) kcfg->value = "2"; |
---|
| 449 | break; |
---|
| 450 | case tok_menuname: |
---|
| 451 | pnt = get_qstring(pnt, &kcfg->label); |
---|
| 452 | break; |
---|
| 453 | case tok_bool: |
---|
| 454 | case tok_tristate: |
---|
| 455 | pnt = get_qstring(pnt, &kcfg->label); |
---|
| 456 | pnt = get_string(pnt, &kcfg->optionname); |
---|
| 457 | break; |
---|
| 458 | case tok_int: |
---|
| 459 | case tok_hex: |
---|
| 460 | pnt = get_qstring(pnt, &kcfg->label); |
---|
| 461 | pnt = get_string(pnt, &kcfg->optionname); |
---|
| 462 | pnt = get_string(pnt, &kcfg->value); |
---|
| 463 | break; |
---|
| 464 | case tok_dep_tristate: |
---|
| 465 | pnt = get_qstring(pnt, &kcfg->label); |
---|
| 466 | pnt = get_string(pnt, &kcfg->optionname); |
---|
| 467 | pnt = skip_whitespace(pnt); |
---|
| 468 | if( *pnt == '$') pnt++; |
---|
| 469 | pnt = get_string(pnt, &kcfg->depend.str); |
---|
| 470 | |
---|
| 471 | /* |
---|
| 472 | * Create a conditional for this object's dependency. |
---|
| 473 | * |
---|
| 474 | * We can't use "!= n" because this is internally converted to "!= 0" |
---|
| 475 | * and if UMSDOS depends on MSDOS which depends on FAT, then when FAT |
---|
| 476 | * is disabled MSDOS has 16 added to its value, making UMSDOS fully |
---|
| 477 | * available. Whew. |
---|
| 478 | * |
---|
| 479 | * This is more of a hack than a fix. Nested "if" conditionals are |
---|
| 480 | * probably affected too - that +/- 16 affects things in too many |
---|
| 481 | * places. But this should do for now. |
---|
| 482 | */ |
---|
| 483 | sprintf(fake_if,"[ \"$%s\" = \"y\" -o \"$%s\" = \"m\" ]; then", |
---|
| 484 | kcfg->depend.str,kcfg->depend.str); |
---|
| 485 | kcfg->cond = parse_if(fake_if); |
---|
| 486 | if(kcfg->cond == NULL ) |
---|
| 487 | { |
---|
| 488 | exit(1); |
---|
| 489 | } |
---|
| 490 | break; |
---|
| 491 | case tok_comment: |
---|
| 492 | pnt = get_qstring(pnt, &kcfg->label); |
---|
| 493 | if( koption != NULL ) |
---|
| 494 | { |
---|
| 495 | pnt = get_qstring(pnt, &kcfg->label); |
---|
| 496 | koption->label = kcfg->label; |
---|
| 497 | koption = NULL; |
---|
| 498 | } |
---|
| 499 | break; |
---|
| 500 | case tok_menuoption: |
---|
| 501 | if( strncmp(pnt, "next_comment", 12) == 0) |
---|
| 502 | { |
---|
| 503 | koption = kcfg; |
---|
| 504 | } |
---|
| 505 | else |
---|
| 506 | { |
---|
| 507 | pnt = get_qstring(pnt, &kcfg->label); |
---|
| 508 | } |
---|
| 509 | break; |
---|
| 510 | case tok_make: |
---|
| 511 | kcfg->value=strdup(pnt); |
---|
| 512 | break; |
---|
| 513 | case tok_else: |
---|
| 514 | case tok_fi: |
---|
| 515 | case tok_endmenu: |
---|
| 516 | break; |
---|
| 517 | case tok_if: |
---|
| 518 | /* |
---|
| 519 | * Conditionals are different. For the first level parse, only |
---|
| 520 | * tok_if and tok_dep_tristate items have a ->cond chain attached. |
---|
| 521 | */ |
---|
| 522 | kcfg->cond = parse_if(pnt); |
---|
| 523 | if(kcfg->cond == NULL ) |
---|
| 524 | { |
---|
| 525 | exit(1); |
---|
| 526 | } |
---|
| 527 | break; |
---|
| 528 | default: |
---|
| 529 | exit(0); |
---|
| 530 | } |
---|
| 531 | |
---|
| 532 | return; |
---|
| 533 | } |
---|
| 534 | |
---|
| 535 | /* |
---|
| 536 | * Simple function to dump to the screen what the condition chain looks like. |
---|
| 537 | */ |
---|
| 538 | void dump_if(struct condition * cond) |
---|
| 539 | { |
---|
| 540 | printf(" "); |
---|
| 541 | while(cond != NULL ) |
---|
| 542 | { |
---|
| 543 | switch(cond->op){ |
---|
| 544 | case op_eq: |
---|
| 545 | printf(" = "); |
---|
| 546 | break; |
---|
| 547 | case op_bang: |
---|
| 548 | printf(" ! "); |
---|
| 549 | break; |
---|
| 550 | case op_neq: |
---|
| 551 | printf(" != "); |
---|
| 552 | break; |
---|
| 553 | case op_and: |
---|
| 554 | printf(" -a "); |
---|
| 555 | break; |
---|
| 556 | case op_lparen: |
---|
| 557 | printf("("); |
---|
| 558 | break; |
---|
| 559 | case op_rparen: |
---|
| 560 | printf(")"); |
---|
| 561 | break; |
---|
| 562 | case op_variable: |
---|
| 563 | printf("$%s", cond->variable.str); |
---|
| 564 | break; |
---|
| 565 | case op_constant: |
---|
| 566 | printf("'%s'", cond->variable.str); |
---|
| 567 | break; |
---|
| 568 | default: |
---|
| 569 | break; |
---|
| 570 | } |
---|
| 571 | cond = cond->next; |
---|
| 572 | } |
---|
| 573 | |
---|
| 574 | printf("\n"); |
---|
| 575 | } |
---|
| 576 | |
---|
| 577 | static int do_source(char * filename) |
---|
| 578 | { |
---|
| 579 | char buffer[1024]; |
---|
| 580 | int offset; |
---|
| 581 | int old_lineno; |
---|
| 582 | char * old_file; |
---|
| 583 | char * pnt; |
---|
| 584 | FILE * infile; |
---|
| 585 | |
---|
| 586 | if( strcmp(filename, "-") == 0 ) |
---|
| 587 | infile = stdin; |
---|
| 588 | else |
---|
| 589 | infile = fopen(filename,"r"); |
---|
| 590 | |
---|
| 591 | /* |
---|
| 592 | * If our cwd was in the scripts directory, we might have to go up one |
---|
| 593 | * to find the sourced file. |
---|
| 594 | */ |
---|
| 595 | if(!infile) { |
---|
| 596 | strcpy (buffer, "../"); |
---|
| 597 | strcat (buffer, filename); |
---|
| 598 | infile = fopen(buffer,"r"); |
---|
| 599 | } |
---|
| 600 | |
---|
| 601 | if(!infile) { |
---|
| 602 | fprintf(stderr,"Unable to open file %s\n", filename); |
---|
| 603 | return 1; |
---|
| 604 | } |
---|
| 605 | old_lineno = lineno; |
---|
| 606 | lineno = 0; |
---|
| 607 | if( infile != stdin ) { |
---|
| 608 | old_file = current_file; |
---|
| 609 | current_file = filename; |
---|
| 610 | } |
---|
| 611 | offset = 0; |
---|
| 612 | while(1) |
---|
| 613 | { |
---|
| 614 | fgets(&buffer[offset], sizeof(buffer) - offset, infile); |
---|
| 615 | if(feof(infile)) break; |
---|
| 616 | |
---|
| 617 | /* |
---|
| 618 | * Strip the trailing return character. |
---|
| 619 | */ |
---|
| 620 | pnt = buffer + strlen(buffer) - 1; |
---|
| 621 | if( *pnt == '\n') *pnt-- = 0; |
---|
| 622 | lineno++; |
---|
| 623 | if( *pnt == '\\' ) |
---|
| 624 | { |
---|
| 625 | offset = pnt - buffer; |
---|
| 626 | } |
---|
| 627 | else |
---|
| 628 | { |
---|
| 629 | parse(buffer); |
---|
| 630 | offset = 0; |
---|
| 631 | } |
---|
| 632 | } |
---|
| 633 | fclose(infile); |
---|
| 634 | if( infile != stdin ) { |
---|
| 635 | current_file = old_file; |
---|
| 636 | } |
---|
| 637 | lineno = old_lineno; |
---|
| 638 | return 0; |
---|
| 639 | } |
---|
| 640 | |
---|
| 641 | int main(int argc, char * argv[]) |
---|
| 642 | { |
---|
| 643 | #if 0 |
---|
| 644 | char buffer[1024]; |
---|
| 645 | char * pnt; |
---|
| 646 | struct kconfig * cfg; |
---|
| 647 | int i; |
---|
| 648 | #endif |
---|
| 649 | |
---|
| 650 | /* |
---|
| 651 | * Read stdin to get the top level script. |
---|
| 652 | */ |
---|
| 653 | do_source("-"); |
---|
| 654 | |
---|
| 655 | if( menus_seen == 0 ) |
---|
| 656 | { |
---|
| 657 | fprintf(stderr,"The config.in file for this platform does not support\n"); |
---|
| 658 | fprintf(stderr,"menus.\n"); |
---|
| 659 | exit(1); |
---|
| 660 | } |
---|
| 661 | /* |
---|
| 662 | * Input file is now parsed. Next we need to go through and attach |
---|
| 663 | * the correct conditions to each of the actual menu items and kill |
---|
| 664 | * the if/else/endif tokens from the list. We also flag the menu items |
---|
| 665 | * that have other things that depend upon its setting. |
---|
| 666 | */ |
---|
| 667 | fix_conditionals(config); |
---|
| 668 | |
---|
| 669 | /* |
---|
| 670 | * Finally, we generate the wish script. |
---|
| 671 | */ |
---|
| 672 | dump_tk_script(config); |
---|
| 673 | |
---|
| 674 | #if 0 |
---|
| 675 | /* |
---|
| 676 | * Now dump what we have so far. This is only for debugging so that |
---|
| 677 | * we can display what we think we have in the list. |
---|
| 678 | */ |
---|
| 679 | for(cfg = config; cfg; cfg = cfg->next) |
---|
| 680 | { |
---|
| 681 | |
---|
| 682 | if(cfg->cond != NULL && cfg->tok != tok_if) |
---|
| 683 | dump_if(cfg->cond); |
---|
| 684 | |
---|
| 685 | switch(cfg->tok) |
---|
| 686 | { |
---|
| 687 | case tok_menuname: |
---|
| 688 | printf("main_menuname "); |
---|
| 689 | break; |
---|
| 690 | case tok_bool: |
---|
| 691 | printf("bool "); |
---|
| 692 | break; |
---|
| 693 | case tok_tristate: |
---|
| 694 | printf("tristate "); |
---|
| 695 | break; |
---|
| 696 | case tok_dep_tristate: |
---|
| 697 | printf("dep_tristate "); |
---|
| 698 | break; |
---|
| 699 | case tok_int: |
---|
| 700 | printf("int "); |
---|
| 701 | break; |
---|
| 702 | case tok_hex: |
---|
| 703 | printf("hex "); |
---|
| 704 | break; |
---|
| 705 | case tok_comment: |
---|
| 706 | printf("comment "); |
---|
| 707 | break; |
---|
| 708 | case tok_menuoption: |
---|
| 709 | printf("menuoption "); |
---|
| 710 | break; |
---|
| 711 | case tok_else: |
---|
| 712 | printf("else"); |
---|
| 713 | break; |
---|
| 714 | case tok_fi: |
---|
| 715 | printf("fi"); |
---|
| 716 | break; |
---|
| 717 | case tok_if: |
---|
| 718 | printf("if"); |
---|
| 719 | break; |
---|
| 720 | default: |
---|
| 721 | } |
---|
| 722 | |
---|
| 723 | switch(cfg->tok) |
---|
| 724 | { |
---|
| 725 | case tok_menuoption: |
---|
| 726 | case tok_comment: |
---|
| 727 | case tok_menuname: |
---|
| 728 | printf("%s\n", cfg->label); |
---|
| 729 | break; |
---|
| 730 | case tok_bool: |
---|
| 731 | case tok_tristate: |
---|
| 732 | case tok_dep_tristate: |
---|
| 733 | case tok_int: |
---|
| 734 | case tok_hex: |
---|
| 735 | printf("%s %s\n", cfg->label, cfg->optionname); |
---|
| 736 | break; |
---|
| 737 | case tok_if: |
---|
| 738 | dump_if(cfg->cond); |
---|
| 739 | break; |
---|
| 740 | case tok_nop: |
---|
| 741 | case tok_endmenu: |
---|
| 742 | break; |
---|
| 743 | default: |
---|
| 744 | printf("\n"); |
---|
| 745 | } |
---|
| 746 | } |
---|
| 747 | #endif |
---|
| 748 | |
---|
| 749 | return 0; |
---|
| 750 | |
---|
| 751 | } |
---|