linux-old/scripts/tkparse.c
<<
>>
Prefs
   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
  54static struct kconfig * config_list = NULL;
  55static struct kconfig * config_last = NULL;
  56static const char * current_file = "<unknown file>";
  57static int lineno = 0;
  58
  59static void do_source( const char * );
  60
  61#undef strcmp
  62int 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 */
  68static 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 */
  80struct variable *vartable;
  81int max_varnum = 0;
  82static int vartable_size = 0;
  83
  84int 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 */
 108static 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 */
 135static 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 */
 184static 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 */
 205static 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 */
 331static 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 */
 380static 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 */
 747static 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 */
 821int 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}
 829
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.