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