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