The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/scripts/tkparse.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * tkparse.c
    3  *
    4  * Eric Youngdale was the original author of xconfig.
    5  * Michael Elizabeth Chastain (mec@shout.net) is the current maintainer.
    6  *
    7  * Parse a config.in file and translate it to a wish script.
    8  * This task has three parts:
    9  *
   10  *   tkparse.c  tokenize the input
   11  *   tkcond.c   transform 'if ...' statements
   12  *   tkgen.c    generate output
   13  *
   14  * Change History
   15  *
   16  * 7 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
   17  * - Teach dep_tristate about a few literals, such as:
   18  *     dep_tristate 'foo' CONFIG_FOO m
   19  *   Also have it print an error message and exit on some parse failures.
   20  *
   21  * 14 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
   22  * - Don't fclose stdin.  Thanks to Tony Hoyle for nailing this one.
   23  *
   24  * 14 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
   25  * - Steam-clean this file.  I tested this by generating kconfig.tk for
   26  *   every architecture and comparing it character-for-character against
   27  *   the output of the old tkparse.
   28  *
   29  * 23 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
   30  * - Remove bug-compatible code.
   31  *
   32  * 07 July 1999, Andrzej M. Krzysztofowicz, <ankry@mif.pg.gda.pl>
   33  * - Submenus implemented,
   34  * - plenty of option updating/displaying fixes,
   35  * - dep_bool, define_hex, define_int, define_string, define_tristate and
   36  *   undef implemented,
   37  * - dep_tristate fixed to support multiple dependencies,
   38  * - handling of variables with an empty value implemented,
   39  * - value checking for int and hex fields,
   40  * - more checking during condition parsing; choice variables are treated as
   41  *   all others now,
   42  *
   43  * TO DO:
   44  * - xconfig is at the end of its life cycle.  Contact <mec@shout.net> if
   45  *   you are interested in working on the replacement.
   46  */
   47 
   48 #include <stdio.h>
   49 #include <stdlib.h>
   50 #include <string.h>
   51 
   52 #include "tkparse.h"
   53 
   54 static struct kconfig * config_list = NULL;
   55 static struct kconfig * config_last = NULL;
   56 static const char * current_file = "<unknown file>";
   57 static int lineno = 0;
   58 
   59 static void do_source( const char * );
   60 
   61 #undef strcmp
   62 int my_strcmp( const char * s1, const char * s2 ) { return strcmp( s1, s2 ); }
   63 #define strcmp my_strcmp
   64 
   65 /*
   66  * Report a syntax error.
   67  */
   68 static void syntax_error( const char * msg )
   69 {
   70     fprintf( stderr, "%s: %d: %s\n", current_file, lineno, msg );
   71     exit( 1 );
   72 }
   73 
   74 
   75 
   76 /*
   77  * Find index of a specific variable in the symbol table.
   78  * Create a new entry if it does not exist yet.
   79  */
   80 struct variable *vartable;
   81 int max_varnum = 0;
   82 static int vartable_size = 0;
   83 
   84 int get_varnum( char * name )
   85 {
   86     int i;
   87     
   88     for ( i = 1; i <= max_varnum; i++ )
   89         if ( strcmp( vartable[i].name, name ) == 0 )
   90             return i;
   91     while (max_varnum+1 >= vartable_size) {
   92         vartable = realloc(vartable, (vartable_size += 1000)*sizeof(*vartable));
   93         if (!vartable) {
   94             fprintf(stderr, "tkparse realloc vartable failed\n");
   95             exit(1);
   96         }
   97     }
   98     vartable[++max_varnum].name = malloc( strlen( name )+1 );
   99     strcpy( vartable[max_varnum].name, name );
  100     return max_varnum;
  101 }
  102 
  103 
  104 
  105 /*
  106  * Get a string.
  107  */
  108 static const char * get_string( const char * pnt, char ** label )
  109 {
  110     const char * word;
  111 
  112     word = pnt;
  113     for ( ; ; )
  114     {
  115         if ( *pnt == '\0' || *pnt == ' ' || *pnt == '\t' )
  116             break;
  117         pnt++;
  118     }
  119 
  120     *label = malloc( pnt - word + 1 );
  121     memcpy( *label, word, pnt - word );
  122     (*label)[pnt - word] = '\0';
  123 
  124     if ( *pnt != '\0' )
  125         pnt++;
  126     return pnt;
  127 }
  128 
  129 
  130 
  131 /*
  132  * Get a quoted string.
  133  * Insert a '\' before any characters that need quoting.
  134  */
  135 static const char * get_qstring( const char * pnt, char ** label )
  136 {
  137     char quote_char;
  138     char newlabel [2048];
  139     char * pnt1;
  140 
  141     /* advance to the open quote */
  142     for ( ; ; )
  143     {
  144         if ( *pnt == '\0' )
  145             return pnt;
  146         quote_char = *pnt++;
  147         if ( quote_char == '"' || quote_char == '\'' )
  148             break;
  149     }
  150 
  151     /* copy into an intermediate buffer */
  152     pnt1 = newlabel;
  153     for ( ; ; )
  154     {
  155         if ( *pnt == '\0' )
  156             syntax_error( "unterminated quoted string" );
  157         if ( *pnt == quote_char && pnt[-1] != '\\' )
  158             break;
  159 
  160         /* copy the character, quoting if needed */
  161         if ( *pnt == '"' || *pnt == '\'' || *pnt == '[' || *pnt == ']' )
  162             *pnt1++ = '\\';
  163         *pnt1++ = *pnt++;
  164     }
  165 
  166     /* copy the label into a permanent location */
  167     *pnt1++ = '\0';
  168     *label = (char *) malloc( pnt1 - newlabel );
  169     memcpy( *label, newlabel, pnt1 - newlabel );
  170 
  171     /* skip over last quote and next whitespace */
  172     pnt++;
  173     while ( *pnt == ' ' || *pnt == '\t' )
  174         pnt++;
  175     return pnt;
  176 }
  177 
  178 
  179 
  180 /*
  181  * Get a quoted or unquoted string. It is recognized by the first 
  182  * non-white character. '"' and '"' are not allowed inside the string.
  183  */
  184 static const char * get_qnqstring( const char * pnt, char ** label )
  185 {
  186     char quote_char;
  187 
  188     while ( *pnt == ' ' || *pnt == '\t' )
  189         pnt++;
  190 
  191     if ( *pnt == '\0' )
  192         return pnt;
  193     quote_char = *pnt;
  194     if ( quote_char == '"' || quote_char == '\'' )
  195         return get_qstring( pnt, label );
  196     else
  197         return get_string( pnt, label );
  198 }
  199 
  200 
  201 
  202 /*
  203  * Tokenize an 'if' statement condition.
  204  */
  205 static struct condition * tokenize_if( const char * pnt )
  206 {
  207     struct condition * list;
  208     struct condition * last;
  209     struct condition * prev;
  210 
  211     /* eat the open bracket */
  212     while ( *pnt == ' ' || *pnt == '\t' )
  213         pnt++;
  214     if ( *pnt != '[' )
  215         syntax_error( "bad 'if' condition" );
  216     pnt++;
  217 
  218     list = last = NULL;
  219     for ( ; ; )
  220     {
  221         struct condition * cond;
  222 
  223         /* advance to the next token */
  224         while ( *pnt == ' ' || *pnt == '\t' )
  225             pnt++;
  226         if ( *pnt == '\0' )
  227             syntax_error( "unterminated 'if' condition" );
  228         if ( *pnt == ']' )
  229             return list;
  230 
  231         /* allocate a new token */
  232         cond = malloc( sizeof(*cond) );
  233         memset( cond, 0, sizeof(*cond) );
  234         if ( last == NULL )
  235             { list = last = cond; prev = NULL; }
  236         else
  237             { prev = last; last->next = cond; last = cond; }
  238 
  239         /* determine the token value */
  240         if ( *pnt == '-' && pnt[1] == 'a' )
  241         {
  242             if ( ! prev || ( prev->op != op_variable && prev->op != op_constant ) )
  243                 syntax_error( "incorrect argument" );
  244             cond->op = op_and;  pnt += 2; continue;
  245         }
  246 
  247         if ( *pnt == '-' && pnt[1] == 'o' )
  248         {
  249             if ( ! prev || ( prev->op != op_variable && prev->op != op_constant ) )
  250                 syntax_error( "incorrect argument" );
  251             cond->op = op_or;   pnt += 2; continue;
  252         }
  253 
  254         if ( *pnt == '!' && pnt[1] == '=' )
  255         {
  256             if ( ! prev || ( prev->op != op_variable && prev->op != op_constant ) )
  257                 syntax_error( "incorrect argument" );
  258             cond->op = op_neq;  pnt += 2; continue;
  259         }
  260 
  261         if ( *pnt == '=' )
  262         {
  263             if ( ! prev || ( prev->op != op_variable && prev->op != op_constant ) )
  264                 syntax_error( "incorrect argument" );
  265             cond->op = op_eq;   pnt += 1; continue;
  266         }
  267 
  268         if ( *pnt == '!' )
  269         {
  270             if ( prev && ( prev->op != op_and && prev->op != op_or
  271                       && prev->op != op_bang ) )
  272                 syntax_error( "incorrect argument" );
  273             cond->op = op_bang; pnt += 1; continue;
  274         }
  275 
  276         if ( *pnt == '"' )
  277         {
  278             const char * word;
  279 
  280             if ( prev && ( prev->op == op_variable || prev->op == op_constant ) )
  281                 syntax_error( "incorrect argument" );
  282             /* advance to the word */
  283             pnt++;
  284             if ( *pnt == '$' )
  285                 { cond->op = op_variable; pnt++; }
  286             else
  287                 { cond->op = op_constant; }
  288 
  289             /* find the end of the word */
  290             word = pnt;
  291             for ( ; ; )
  292             {
  293                 if ( *pnt == '\0' )
  294                     syntax_error( "unterminated double quote" );
  295                 if ( *pnt == '"' )
  296                     break;
  297                 pnt++;
  298             }
  299 
  300             /* store a copy of this word */
  301             {
  302                 char * str = malloc( pnt - word + 1 );
  303                 memcpy( str, word, pnt - word );
  304                 str [pnt - word] = '\0';
  305                 if ( cond->op == op_variable )
  306                 {
  307                     cond->nameindex = get_varnum( str );
  308                     free( str );
  309                 }
  310                 else /* op_constant */
  311                 {
  312                     cond->str = str;
  313                 }
  314             }
  315 
  316             pnt++;
  317             continue;
  318         }
  319 
  320         /* unknown token */
  321         syntax_error( "bad if condition" );
  322     }
  323 }
  324 
  325 
  326 
  327 /*
  328  * Tokenize a choice list.  Choices appear as pairs of strings;
  329  * note that I am parsing *inside* the double quotes.  Ugh.
  330  */
  331 static const char * tokenize_choices( struct kconfig * cfg_choose,
  332     const char * pnt )
  333 {
  334     int default_checked = 0;
  335     for ( ; ; )
  336     {
  337         struct kconfig * cfg;
  338         char * buffer = malloc( 64 );
  339 
  340         /* skip whitespace */
  341         while ( *pnt == ' ' || *pnt == '\t' )
  342             pnt++;
  343         if ( *pnt == '\0' )
  344             return pnt;
  345 
  346         /* allocate a new kconfig line */
  347         cfg = malloc( sizeof(*cfg) );
  348         memset( cfg, 0, sizeof(*cfg) );
  349         if ( config_last == NULL )
  350             { config_last = config_list = cfg; }
  351         else
  352             { config_last->next = cfg; config_last = cfg; }
  353 
  354         /* fill out the line */
  355         cfg->token      = token_choice_item;
  356         cfg->cfg_parent = cfg_choose;
  357         pnt = get_string( pnt, &cfg->label );
  358         if ( ! default_checked &&
  359              ! strncmp( cfg->label, cfg_choose->value, strlen( cfg_choose->value ) ) )
  360         {
  361             default_checked = 1;
  362             free( cfg_choose->value );
  363             cfg_choose->value = cfg->label;
  364         }
  365         while ( *pnt == ' ' || *pnt == '\t' )
  366             pnt++;
  367         pnt = get_string( pnt, &buffer );
  368         cfg->nameindex = get_varnum( buffer );
  369     }
  370     if ( ! default_checked )
  371         syntax_error( "bad 'choice' default value" );
  372     return pnt;
  373 }
  374 
  375 
  376 
  377 /*
  378  * Tokenize one line.
  379  */
  380 static void tokenize_line( const char * pnt )
  381 {
  382     static struct kconfig * last_menuoption = NULL;
  383     enum e_token token;
  384     struct kconfig * cfg;
  385     struct dependency ** dep_ptr;
  386     char * buffer = malloc( 64 );
  387 
  388     /* skip white space */
  389     while ( *pnt == ' ' || *pnt == '\t' )
  390         pnt++;
  391 
  392     /*
  393      * categorize the next token
  394      */
  395 
  396 #define match_token(t, s) \
  397     if (strncmp(pnt, s, strlen(s)) == 0) { token = t; pnt += strlen(s); break; }
  398 
  399     token = token_UNKNOWN;
  400     switch ( *pnt )
  401     {
  402     default:
  403         break;
  404 
  405     case '#':
  406     case '\0':
  407         return;
  408 
  409     case 'b':
  410         match_token( token_bool, "bool" );
  411         break;
  412 
  413     case 'c':
  414         match_token( token_choice_header, "choice"  );
  415         match_token( token_comment, "comment" );
  416         break;
  417 
  418     case 'd':
  419         match_token( token_define_bool, "define_bool" );
  420         match_token( token_define_hex, "define_hex" );
  421         match_token( token_define_int, "define_int" );
  422         match_token( token_define_string, "define_string" );
  423         match_token( token_define_tristate, "define_tristate" );
  424         match_token( token_dep_bool, "dep_bool" );
  425         match_token( token_dep_mbool, "dep_mbool" );
  426         match_token( token_dep_tristate, "dep_tristate" );
  427         break;
  428 
  429     case 'e':
  430         match_token( token_else, "else" );
  431         match_token( token_endmenu, "endmenu" );
  432         break;
  433 
  434     case 'f':
  435         match_token( token_fi, "fi" );
  436         break;
  437 
  438     case 'h':
  439         match_token( token_hex, "hex" );
  440         break;
  441 
  442     case 'i':
  443         match_token( token_if, "if" );
  444         match_token( token_int, "int" );
  445         break;
  446 
  447     case 'm':
  448         match_token( token_mainmenu_name, "mainmenu_name" );
  449         match_token( token_mainmenu_option, "mainmenu_option" );
  450         break;
  451 
  452     case 's':
  453         match_token( token_source, "source" );
  454         match_token( token_string, "string" );
  455         break;
  456 
  457     case 't':
  458         match_token( token_then, "then" );
  459         match_token( token_tristate, "tristate" );
  460         break;
  461 
  462     case 'u':
  463         match_token( token_unset, "unset" );
  464         break;
  465     }
  466 
  467 #undef match_token
  468 
  469     if ( token == token_source )
  470     {
  471         while ( *pnt == ' ' || *pnt == '\t' )
  472             pnt++;
  473         do_source( pnt );
  474         return;
  475     }
  476 
  477     if ( token == token_then )
  478     {
  479         if ( config_last != NULL && config_last->token == token_if )
  480             return;
  481         syntax_error( "bogus 'then'" );
  482     }
  483 
  484 #if 0
  485     if ( token == token_unset )
  486     {
  487         fprintf( stderr, "Ignoring 'unset' command\n" );
  488         return;
  489     }
  490 #endif
  491 
  492     if ( token == token_UNKNOWN )
  493         syntax_error( "unknown command" );
  494 
  495     /*
  496      * Allocate an item.
  497      */
  498     cfg = malloc( sizeof(*cfg) );
  499     memset( cfg, 0, sizeof(*cfg) );
  500     if ( config_last == NULL )
  501         { config_last = config_list = cfg; }
  502     else
  503         { config_last->next = cfg; config_last = cfg; }
  504 
  505     /*
  506      * Tokenize the arguments.
  507      */
  508     while ( *pnt == ' ' || *pnt == '\t' )
  509         pnt++;
  510 
  511     cfg->token = token;
  512     switch ( token )
  513     {
  514     default:
  515         syntax_error( "unknown token" );
  516 
  517     case token_bool:
  518     case token_tristate:
  519         pnt = get_qstring ( pnt, &cfg->label );
  520         pnt = get_string  ( pnt, &buffer );
  521         cfg->nameindex = get_varnum( buffer );
  522         break;
  523 
  524     case token_choice_header:
  525         {
  526             static int choose_number = 0;
  527             char * choice_list;
  528 
  529             pnt = get_qstring ( pnt, &cfg->label  );
  530             pnt = get_qstring ( pnt, &choice_list );
  531             pnt = get_string  ( pnt, &cfg->value  );
  532             cfg->nameindex = -(choose_number++);
  533             tokenize_choices( cfg, choice_list );
  534             free( choice_list );
  535         }
  536         break;
  537 
  538     case token_comment:
  539         pnt = get_qstring(pnt, &cfg->label);
  540         if ( last_menuoption != NULL )
  541         {
  542             pnt = get_qstring(pnt, &cfg->label);
  543             if (cfg->label == NULL)
  544                 syntax_error( "missing comment text" );
  545             last_menuoption->label = cfg->label;
  546             last_menuoption = NULL;
  547         }
  548         break;
  549 
  550     case token_define_bool:
  551     case token_define_tristate:
  552         pnt = get_string( pnt, &buffer );
  553         cfg->nameindex = get_varnum( buffer );
  554         while ( *pnt == ' ' || *pnt == '\t' )
  555             pnt++;
  556         if ( ( pnt[0] == 'Y'  || pnt[0] == 'M' || pnt[0] == 'N'
  557         ||     pnt[0] == 'y'  || pnt[0] == 'm' || pnt[0] == 'n' )
  558         &&   ( pnt[1] == '\0' || pnt[1] == ' ' || pnt[1] == '\t' ) )
  559         {
  560             if      ( *pnt == 'n' || *pnt == 'N' ) cfg->value = strdup( "CONSTANT_N" );
  561             else if ( *pnt == 'y' || *pnt == 'Y' ) cfg->value = strdup( "CONSTANT_Y" );
  562             else if ( *pnt == 'm' || *pnt == 'M' ) cfg->value = strdup( "CONSTANT_M" );
  563         }
  564         else if ( *pnt == '$' )
  565         {
  566             pnt++;
  567             pnt = get_string( pnt, &cfg->value );
  568         }
  569         else
  570         {
  571             syntax_error( "unknown define_bool value" );
  572         }
  573         get_varnum( cfg->value );
  574         break;
  575 
  576     case token_define_hex:
  577     case token_define_int:
  578         pnt = get_string( pnt, &buffer );
  579         cfg->nameindex = get_varnum( buffer );
  580         pnt = get_string( pnt, &cfg->value );
  581         break;
  582 
  583     case token_define_string:
  584         pnt = get_string( pnt, &buffer );
  585         cfg->nameindex = get_varnum( buffer );
  586         pnt = get_qnqstring( pnt, &cfg->value );
  587         if (cfg->value == NULL)
  588             syntax_error( "missing value" );
  589         break;
  590 
  591     case token_dep_bool:
  592     case token_dep_mbool:
  593     case token_dep_tristate:
  594         pnt = get_qstring ( pnt, &cfg->label );
  595         pnt = get_string  ( pnt, &buffer );
  596         cfg->nameindex = get_varnum( buffer );
  597 
  598         while ( *pnt == ' ' || *pnt == '\t' )
  599             pnt++;
  600 
  601         dep_ptr = &(cfg->depend);
  602 
  603         do {
  604             *dep_ptr = (struct dependency *) malloc( sizeof( struct dependency ) );
  605             (*dep_ptr)->next = NULL;
  606 
  607             if ( ( pnt[0] == 'Y'  || pnt[0] == 'M' || pnt[0] == 'N'
  608             ||     pnt[0] == 'y'  || pnt[0] == 'm' || pnt[0] == 'n' )
  609             &&   ( pnt[1] == '\0' || pnt[1] == ' ' || pnt[1] == '\t' ) )
  610             {
  611                 /* dep_tristate 'foo' CONFIG_FOO m */
  612                 if      ( pnt[0] == 'Y' || pnt[0] == 'y' )
  613                     (*dep_ptr)->name = strdup( "CONSTANT_Y" );
  614                 else if ( pnt[0] == 'N' || pnt[0] == 'n' )
  615                     (*dep_ptr)->name = strdup( "CONSTANT_N" );
  616                 else
  617                     (*dep_ptr)->name = strdup( "CONSTANT_M" );
  618                 pnt++;
  619                 get_varnum( (*dep_ptr)->name );
  620             }
  621             else if ( *pnt == '$' )
  622             {
  623                 pnt++;
  624                 pnt = get_string( pnt, &(*dep_ptr)->name );
  625                 get_varnum( (*dep_ptr)->name );
  626             }
  627             else
  628             {
  629                 syntax_error( "can't handle dep_bool/dep_mbool/dep_tristate condition" );
  630             }
  631             dep_ptr = &(*dep_ptr)->next;
  632             while ( *pnt == ' ' || *pnt == '\t' )
  633                 pnt++;
  634         } while ( *pnt );
  635 
  636         /*
  637          * Create a conditional for this object's dependencies.
  638          */
  639         {
  640             char fake_if [1024];
  641             struct dependency * dep;
  642             struct condition ** cond_ptr;
  643             int first = 1;
  644 
  645             cond_ptr = &(cfg->cond);
  646             for ( dep = cfg->depend; dep; dep = dep->next )
  647             {
  648                 if ( token == token_dep_tristate
  649                 && ! strcmp( dep->name, "CONSTANT_M" ) )
  650                 {
  651                     continue;
  652                 }
  653                 if ( first )
  654                 {
  655                     first = 0;
  656                 }
  657                 else
  658                 {
  659                     *cond_ptr = malloc( sizeof(struct condition) );
  660                     memset( *cond_ptr, 0, sizeof(struct condition) );
  661                     (*cond_ptr)->op = op_and;
  662                     cond_ptr = &(*cond_ptr)->next;
  663                 }
  664                 *cond_ptr = malloc( sizeof(struct condition) );
  665                 memset( *cond_ptr, 0, sizeof(struct condition) );
  666                 (*cond_ptr)->op = op_lparen;
  667                 if ( token == token_dep_bool )
  668                     sprintf( fake_if, "[ \"$%s\" = \"y\" -o \"$%s\" = \"\" ]; then",
  669                         dep->name, dep->name );
  670                 else
  671                     sprintf( fake_if, "[ \"$%s\" = \"y\" -o \"$%s\" = \"m\" -o \"$%s\" = \"\" ]; then",
  672                         dep->name, dep->name, dep->name );
  673                 (*cond_ptr)->next = tokenize_if( fake_if );
  674                 while ( *cond_ptr )
  675                     cond_ptr = &(*cond_ptr)->next;
  676                 *cond_ptr = malloc( sizeof(struct condition) );
  677                 memset( *cond_ptr, 0, sizeof(struct condition) );
  678                 (*cond_ptr)->op = op_rparen;
  679                 cond_ptr = &(*cond_ptr)->next;
  680             }
  681         }
  682         break;
  683 
  684     case token_else:
  685     case token_endmenu:
  686     case token_fi:
  687         break;
  688 
  689     case token_hex:
  690     case token_int:
  691         pnt = get_qstring ( pnt, &cfg->label );
  692         pnt = get_string  ( pnt, &buffer );
  693         cfg->nameindex = get_varnum( buffer );
  694         pnt = get_string  ( pnt, &cfg->value );
  695         break;
  696 
  697     case token_string:
  698         pnt = get_qstring ( pnt, &cfg->label );
  699         pnt = get_string  ( pnt, &buffer );
  700         cfg->nameindex = get_varnum( buffer );
  701         pnt = get_qnqstring  ( pnt, &cfg->value );
  702         if (cfg->value == NULL)
  703             syntax_error( "missing initial value" );
  704         break;
  705 
  706     case token_if:
  707         cfg->cond = tokenize_if( pnt );
  708         break;
  709 
  710     case token_mainmenu_name:
  711         pnt = get_qstring( pnt, &cfg->label );
  712         break;
  713 
  714     case token_mainmenu_option:
  715         if ( strncmp( pnt, "next_comment", 12 ) == 0 )
  716             last_menuoption = cfg;
  717         else
  718             pnt = get_qstring( pnt, &cfg->label );
  719         break;
  720 
  721     case token_unset:
  722         pnt = get_string( pnt, &buffer );
  723         cfg->nameindex = get_varnum( buffer );
  724         while ( *pnt == ' ' || *pnt == '\t' )
  725             pnt++;
  726         while (*pnt)
  727         {
  728             cfg->next = (struct kconfig *) malloc( sizeof(struct kconfig) );
  729             memset( cfg->next, 0, sizeof(struct kconfig) );
  730             cfg = cfg->next;
  731             cfg->token = token_unset;
  732             pnt = get_string( pnt, &buffer );
  733             cfg->nameindex = get_varnum( buffer );
  734             while ( *pnt == ' ' || *pnt == '\t' )
  735                 pnt++;
  736         }
  737         break;
  738     }
  739     return;
  740 }
  741 
  742 
  743 
  744 /*
  745  * Implement the "source" command.
  746  */
  747 static void do_source( const char * filename )
  748 {
  749     char buffer [2048];
  750     FILE * infile;
  751     const char * old_file;
  752     int old_lineno;
  753     int offset;
  754 
  755     /* open the file */
  756     if ( strcmp( filename, "-" ) == 0 )
  757         infile = stdin;
  758     else
  759         infile = fopen( filename, "r" );
  760 
  761     /* if that failed, try ../filename */
  762     if ( infile == NULL )
  763     {
  764         sprintf( buffer, "../%s", filename );
  765         infile = fopen( buffer, "r" );
  766     }
  767 
  768     if ( infile == NULL )
  769     {
  770         sprintf( buffer, "unable to open %s", filename );
  771         syntax_error( buffer );
  772     }
  773 
  774     /* push the new file name and line number */
  775     old_file     = current_file;
  776     old_lineno   = lineno;
  777     current_file = filename;
  778     lineno       = 0;
  779 
  780     /* read and process lines */
  781     for ( offset = 0; ; )
  782     {
  783         char * pnt;
  784 
  785         /* read a line */
  786         fgets( buffer + offset, sizeof(buffer) - offset, infile );
  787         if ( feof( infile ) )
  788             break;
  789         lineno++;
  790 
  791         /* strip the trailing return character */
  792         pnt = buffer + strlen(buffer) - 1;
  793         if ( *pnt == '\n' )
  794             *pnt-- = '\0';
  795 
  796         /* eat \ NL pairs */
  797         if ( *pnt == '\\' )
  798         {
  799             offset = pnt - buffer;
  800             continue;
  801         }
  802 
  803         /* tokenize this line */
  804         tokenize_line( buffer );
  805         offset = 0;
  806     }
  807 
  808     /* that's all, folks */
  809     if ( infile != stdin )
  810         fclose( infile );
  811     current_file = old_file;
  812     lineno       = old_lineno;
  813     return;
  814 }
  815 
  816 
  817 
  818 /*
  819  * Main program.
  820  */
  821 int main( int argc, const char * argv [] )
  822 {
  823     do_source        ( "-"         );
  824     fix_conditionals ( config_list );
  825     dump_tk_script   ( config_list );
  826     free(vartable);
  827     return 0;
  828 }

Cache object: 7a4a9451cd2458652722e5f75fb59978


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.