Changeset 51 for trunk/src/kmk/cond.c


Ignore:
Timestamp:
Apr 7, 2003, 3:30:32 AM (22 years ago)
Author:
bird
Message:

kMk and porting to kLib.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kmk/cond.c

    r45 r51  
    1818 * 3. All advertising materials mentioning features or use of this software
    1919 *    must display the following acknowledgement:
    20  *      This product includes software developed by the University of
    21  *      California, Berkeley and its contributors.
     20 *      This product includes software developed by the University of
     21 *      California, Berkeley and its contributors.
    2222 * 4. Neither the name of the University nor the names of its contributors
    2323 *    may be used to endorse or promote products derived from this software
     
    3939#ifndef lint
    4040#if 0
    41 static char sccsid[] = "@(#)cond.c      8.2 (Berkeley) 1/2/94";
     41static char sccsid[] = "@(#)cond.c      8.2 (Berkeley) 1/2/94";
    4242#else
    4343static const char rcsid[] =
    4444  "$FreeBSD: src/usr.bin/make/cond.c,v 1.12 1999/09/11 13:08:01 hoek Exp $";
    4545#endif
     46#define KLIBFILEDEF rcsid
    4647#endif /* not lint */
    4748
    4849/*-
    4950 * cond.c --
    50  *      Functions to handle conditionals in a makefile.
     51 *      Functions to handle conditionals in a makefile.
    5152 *
    5253 * Interface:
    53  *      Cond_Eval       Evaluate the conditional in the passed line.
     54 *      Cond_Eval       Evaluate the conditional in the passed line.
    5455 *
    5556 */
     
    6465/*
    6566 * The parsing of conditional expressions is based on this grammar:
    66  *      E -> F || E
    67  *      E -> F
    68  *      F -> T && F
    69  *      F -> T
    70  *      T -> defined(variable)
    71  *      T -> make(target)
    72  *      T -> exists(file)
    73  *      T -> empty(varspec)
    74  *      T -> target(name)
    75  *      T -> symbol
    76  *      T -> $(varspec) op value
    77  *      T -> $(varspec) == "string"
    78  *      T -> $(varspec) != "string"
    79  *      T -> ( E )
    80  *      T -> ! T
    81  *      op -> == | != | > | < | >= | <=
     67 *      E -> F || E
     68 *      E -> F
     69 *      F -> T && F
     70 *      F -> T
     71 *      T -> defined(variable)
     72 *      T -> make(target)
     73 *      T -> exists(file)
     74 *      T -> empty(varspec)
     75 *      T -> target(name)
     76 *      T -> symbol
     77 *      T -> $(varspec) op value
     78 *      T -> $(varspec) == "string"
     79 *      T -> $(varspec) != "string"
     80 *      T -> ( E )
     81 *      T -> ! T
     82 *      op -> == | != | > | < | >= | <=
    8283 *
    8384 * 'symbol' is some other symbol to which the default function (condDefProc)
     
    114115
    115116static struct If {
    116     char        *form;        /* Form of if */
    117     int         formlen;      /* Length of form */
    118     Boolean     doNot;        /* TRUE if default function should be negated */
    119     Boolean     (*defProc) __P((int, char *)); /* Default function to apply */
     117    char        *form;        /* Form of if */
     118    int         formlen;      /* Length of form */
     119    Boolean     doNot;        /* TRUE if default function should be negated */
     120    Boolean     (*defProc) __P((int, char *)); /* Default function to apply */
    120121} ifs[] = {
    121     { "ifdef",    5,      FALSE,  CondDoDefined },
    122     { "ifndef",   6,      TRUE,   CondDoDefined },
    123     { "ifmake",   6,      FALSE,  CondDoMake },
    124     { "ifnmake",  7,      TRUE,   CondDoMake },
    125     { "if",       2,      FALSE,  CondDoDefined },
    126     { NULL,       0,      FALSE,  NULL }
     122    { "ifdef",    5,      FALSE,  CondDoDefined },
     123    { "ifndef",   6,      TRUE,   CondDoDefined },
     124    { "ifmake",   6,      FALSE,  CondDoMake },
     125    { "ifnmake",  7,      TRUE,   CondDoMake },
     126    { "if",       2,      FALSE,  CondDoDefined },
     127    { NULL,       0,      FALSE,  NULL }
    127128};
    128129
    129 static Boolean    condInvert;           /* Invert the default function */
    130 static Boolean    (*condDefProc)        /* Default function to apply */
    131                     __P((int, char *));
    132 static char       *condExpr;            /* The expression to parse */
    133 static Token      condPushBack=None;    /* Single push-back token used in
    134                                         * parsing */
    135 
    136 #define MAXIF           30        /* greatest depth of #if'ing */
    137 
    138 static Boolean    condStack[MAXIF];     /* Stack of conditionals's values */
    139 static int        condTop = MAXIF;      /* Top-most conditional */
    140 static int        skipIfLevel=0;        /* Depth of skipped conditionals */
    141 static Boolean    skipLine = FALSE;     /* Whether the parse module is skipping
    142                                         * lines */
     130static Boolean    condInvert;           /* Invert the default function */
     131static Boolean    (*condDefProc)        /* Default function to apply */
     132                    __P((int, char *));
     133static char       *condExpr;            /* The expression to parse */
     134static Token      condPushBack=None;    /* Single push-back token used in
     135                                        * parsing */
     136
     137#define MAXIF           30        /* greatest depth of #if'ing */
     138
     139static Boolean    condStack[MAXIF];     /* Stack of conditionals's values */
     140static int        condTop = MAXIF;      /* Top-most conditional */
     141static int        skipIfLevel=0;        /* Depth of skipped conditionals */
     142static Boolean    skipLine = FALSE;     /* Whether the parse module is skipping
     143                                        * lines */
    143144
    144145/*-
    145146 *-----------------------------------------------------------------------
    146147 * CondPushBack --
    147  *      Push back the most recent token read. We only need one level of
    148  *      this, so the thing is just stored in 'condPushback'.
     148 *      Push back the most recent token read. We only need one level of
     149 *      this, so the thing is just stored in 'condPushback'.
    149150 *
    150151 * Results:
    151  *      None.
     152 *      None.
    152153 *
    153154 * Side Effects:
    154  *      condPushback is overwritten.
     155 *      condPushback is overwritten.
    155156 *
    156157 *-----------------------------------------------------------------------
     
    158159static void
    159160CondPushBack (t)
    160     Token         t;    /* Token to push back into the "stream" */
     161    Token         t;    /* Token to push back into the "stream" */
    161162{
    162163    condPushBack = t;
     
    167168 *-----------------------------------------------------------------------
    168169 * CondGetArg --
    169  *      Find the argument of a built-in function.
     170 *      Find the argument of a built-in function.
    170171 *
    171172 * Results:
    172  *      The length of the argument and the address of the argument.
     173 *      The length of the argument and the address of the argument.
    173174 *
    174175 * Side Effects:
    175  *      The pointer is set to point to the closing parenthesis of the
    176  *      function call.
     176 *      The pointer is set to point to the closing parenthesis of the
     177 *      function call.
    177178 *
    178179 *-----------------------------------------------------------------------
     
    180181static int
    181182CondGetArg (linePtr, argPtr, func, parens)
    182     char          **linePtr;
    183     char          **argPtr;
    184     char          *func;
    185     Boolean       parens;       /* TRUE if arg should be bounded by parens */
     183    char          **linePtr;
     184    char          **argPtr;
     185    char          *func;
     186    Boolean       parens;       /* TRUE if arg should be bounded by parens */
    186187{
    187188    register char *cp;
    188     int           argLen;
     189    int           argLen;
    189190    register Buffer buf;
    190191
    191192    cp = *linePtr;
    192193    if (parens) {
    193         while (*cp != '(' && *cp != '\0') {
    194             cp++;
    195         }
    196         if (*cp == '(') {
    197             cp++;
    198         }
     194        while (*cp != '(' && *cp != '\0') {
     195            cp++;
     196        }
     197        if (*cp == '(') {
     198            cp++;
     199        }
    199200    }
    200201
    201202    if (*cp == '\0') {
    202         /*
    203         * No arguments whatsoever. Because 'make' and 'defined' aren't really
    204         * "reserved words", we don't print a message. I think this is better
    205         * than hitting the user with a warning message every time s/he uses
    206         * the word 'make' or 'defined' at the beginning of a symbol...
    207         */
    208         *argPtr = cp;
    209         return (0);
     203        /*
     204        * No arguments whatsoever. Because 'make' and 'defined' aren't really
     205        * "reserved words", we don't print a message. I think this is better
     206        * than hitting the user with a warning message every time s/he uses
     207        * the word 'make' or 'defined' at the beginning of a symbol...
     208        */
     209        *argPtr = cp;
     210        return (0);
    210211    }
    211212
    212213    while (*cp == ' ' || *cp == '\t') {
    213         cp++;
     214        cp++;
    214215    }
    215216
     
    221222
    222223    while ((strchr(" \t)&|", *cp) == (char *)NULL) && (*cp != '\0')) {
    223         if (*cp == '$') {
    224             /*
    225              * Parse the variable spec and install it as part of the argument
    226              * if it's valid. We tell Var_Parse to complain on an undefined
    227              * variable, so we don't do it too. Nor do we return an error,
    228              * though perhaps we should...
    229              */
    230             char        *cp2;
    231             int         len;
    232             Boolean     doFree;
    233 
    234             cp2 = Var_Parse(cp, VAR_CMD, TRUE, &len, &doFree);
    235 
    236             Buf_AddBytes(buf, strlen(cp2), (Byte *)cp2);
    237             if (doFree) {
    238                 efree(cp2);
    239             }
    240             cp += len;
    241         } else {
    242             Buf_AddByte(buf, (Byte)*cp);
    243             cp++;
    244         }
     224        if (*cp == '$') {
     225            /*
     226             * Parse the variable spec and install it as part of the argument
     227             * if it's valid. We tell Var_Parse to complain on an undefined
     228             * variable, so we don't do it too. Nor do we return an error,
     229             * though perhaps we should...
     230             */
     231            char        *cp2;
     232            int         len;
     233            Boolean     doFree;
     234
     235            cp2 = Var_Parse(cp, VAR_CMD, TRUE, &len, &doFree);
     236
     237            Buf_AddBytes(buf, strlen(cp2), (Byte *)cp2);
     238            if (doFree) {
     239                efree(cp2);
     240            }
     241            cp += len;
     242        } else {
     243            Buf_AddByte(buf, (Byte)*cp);
     244            cp++;
     245        }
    245246    }
    246247
     
    250251
    251252    while (*cp == ' ' || *cp == '\t') {
    252         cp++;
     253        cp++;
    253254    }
    254255    if (parens && *cp != ')') {
    255         Parse_Error (PARSE_WARNING, "Missing closing parenthesis for %s()",
    256                      func);
    257         return (0);
     256        Parse_Error (PARSE_WARNING, "Missing closing parenthesis for %s()",
     257                     func);
     258        return (0);
    258259    } else if (parens) {
    259         /*
    260         * Advance pointer past close parenthesis.
    261         */
    262         cp++;
     260        /*
     261        * Advance pointer past close parenthesis.
     262        */
     263        cp++;
    263264    }
    264265
     
    271272 *-----------------------------------------------------------------------
    272273 * CondDoDefined --
    273  *      Handle the 'defined' function for conditionals.
     274 *      Handle the 'defined' function for conditionals.
    274275 *
    275276 * Results:
    276  *      TRUE if the given variable is defined.
     277 *      TRUE if the given variable is defined.
    277278 *
    278279 * Side Effects:
    279  *      None.
     280 *      None.
    280281 *
    281282 *-----------------------------------------------------------------------
     
    283284static Boolean
    284285CondDoDefined (argLen, arg)
    285     int     argLen;
     286    int     argLen;
    286287    char    *arg;
    287288{
     
    292293    arg[argLen] = '\0';
    293294    if (Var_Value (arg, VAR_CMD, &p1) != (char *)NULL) {
    294         result = TRUE;
     295        result = TRUE;
    295296    } else {
    296         result = FALSE;
     297        result = FALSE;
    297298    }
    298299    efree(p1);
     
    305306 *-----------------------------------------------------------------------
    306307 * CondStrMatch --
    307  *      Front-end for Str_Match so it returns 0 on match and non-zero
    308  *      on mismatch. Callback function for CondDoMake via Lst_Find
     308 *      Front-end for Str_Match so it returns 0 on match and non-zero
     309 *      on mismatch. Callback function for CondDoMake via Lst_Find
    309310 *
    310311 * Results:
    311  *      0 if string matches pattern
     312 *      0 if string matches pattern
    312313 *
    313314 * Side Effects:
    314  *      None
     315 *      None
    315316 *
    316317 *-----------------------------------------------------------------------
     
    328329 *-----------------------------------------------------------------------
    329330 * CondDoMake --
    330  *      Handle the 'make' function for conditionals.
     331 *      Handle the 'make' function for conditionals.
    331332 *
    332333 * Results:
    333  *      TRUE if the given target is being made.
     334 *      TRUE if the given target is being made.
    334335 *
    335336 * Side Effects:
    336  *      None.
     337 *      None.
    337338 *
    338339 *-----------------------------------------------------------------------
     
    340341static Boolean
    341342CondDoMake (argLen, arg)
    342     int     argLen;
     343    int     argLen;
    343344    char    *arg;
    344345{
     
    348349    arg[argLen] = '\0';
    349350    if (Lst_Find (create, (ClientData)arg, CondStrMatch) == NILLNODE) {
    350         result = FALSE;
     351        result = FALSE;
    351352    } else {
    352         result = TRUE;
     353        result = TRUE;
    353354    }
    354355    arg[argLen] = savec;
     
    360361 *-----------------------------------------------------------------------
    361362 * CondDoExists --
    362  *      See if the given file exists.
     363 *      See if the given file exists.
    363364 *
    364365 * Results:
    365  *      TRUE if the file exists and FALSE if it does not.
     366 *      TRUE if the file exists and FALSE if it does not.
    366367 *
    367368 * Side Effects:
    368  *      None.
     369 *      None.
    369370 *
    370371 *-----------------------------------------------------------------------
     
    372373static Boolean
    373374CondDoExists (argLen, arg)
    374     int     argLen;
     375    int     argLen;
    375376    char    *arg;
    376377{
     
    382383    path = Dir_FindFile(arg, dirSearchPath);
    383384    if (path != (char *)NULL) {
    384         result = TRUE;
    385         efree(path);
     385        result = TRUE;
     386        efree(path);
    386387    } else {
    387         result = FALSE;
     388        result = FALSE;
    388389    }
    389390    arg[argLen] = savec;
     
    395396 *-----------------------------------------------------------------------
    396397 * CondDoTarget --
    397  *      See if the given node exists and is an actual target.
     398 *      See if the given node exists and is an actual target.
    398399 *
    399400 * Results:
    400  *      TRUE if the node exists as a target and FALSE if it does not.
     401 *      TRUE if the node exists as a target and FALSE if it does not.
    401402 *
    402403 * Side Effects:
    403  *      None.
     404 *      None.
    404405 *
    405406 *-----------------------------------------------------------------------
     
    407408static Boolean
    408409CondDoTarget (argLen, arg)
    409     int     argLen;
     410    int     argLen;
    410411    char    *arg;
    411412{
     
    417418    gn = Targ_FindNode(arg, TARG_NOCREATE);
    418419    if ((gn != NILGNODE) && !OP_NOP(gn->type)) {
    419         result = TRUE;
     420        result = TRUE;
    420421    } else {
    421         result = FALSE;
     422        result = FALSE;
    422423    }
    423424    arg[argLen] = savec;
     
    430431 *-----------------------------------------------------------------------
    431432 * CondCvtArg --
    432  *      Convert the given number into a double. If the number begins
    433  *      with 0x, it is interpreted as a hexadecimal integer
    434  *      and converted to a double from there. All other strings just have
    435  *      strtod called on them.
     433 *      Convert the given number into a double. If the number begins
     434 *      with 0x, it is interpreted as a hexadecimal integer
     435 *      and converted to a double from there. All other strings just have
     436 *      strtod called on them.
    436437 *
    437438 * Results:
    438  *      Sets 'value' to double value of string.
    439  *      Returns address of the first character after the last valid
    440  *      character of the converted number.
     439 *      Sets 'value' to double value of string.
     440 *      Returns address of the first character after the last valid
     441 *      character of the converted number.
    441442 *
    442443 * Side Effects:
    443  *      Can change 'value' even if string is not a valid number.
     444 *      Can change 'value' even if string is not a valid number.
    444445 *
    445446 *
     
    448449static char *
    449450CondCvtArg(str, value)
    450     register char       *str;
    451     double              *value;
     451    register char       *str;
     452    double              *value;
    452453{
    453454    if ((*str == '0') && (str[1] == 'x')) {
    454         register long i;
    455 
    456         for (str += 2, i = 0; ; str++) {
    457             int x;
    458             if (isdigit((unsigned char) *str))
    459                 x  = *str - '0';
    460             else if (isxdigit((unsigned char) *str))
    461                 x = 10 + *str - isupper((unsigned char) *str) ? 'A' : 'a';
    462             else {
    463                 *value = (double) i;
    464                 return str;
    465             }
    466             i = (i << 4) + x;
    467         }
     455        register long i;
     456
     457        for (str += 2, i = 0; ; str++) {
     458            int x;
     459            if (isdigit((unsigned char) *str))
     460                x  = *str - '0';
     461            else if (isxdigit((unsigned char) *str))
     462                x = 10 + *str - isupper((unsigned char) *str) ? 'A' : 'a';
     463            else {
     464                *value = (double) i;
     465                return str;
     466            }
     467            i = (i << 4) + x;
     468        }
    468469    }
    469470    else {
    470         char *eptr;
    471         *value = strtod(str, &eptr);
    472         return eptr;
     471        char *eptr;
     472        *value = strtod(str, &eptr);
     473        return eptr;
    473474    }
    474475}
     
    478479 *-----------------------------------------------------------------------
    479480 * CondToken --
    480  *      Return the next token from the input.
     481 *      Return the next token from the input.
    481482 *
    482483 * Results:
    483  *      A Token for the next lexical token in the stream.
     484 *      A Token for the next lexical token in the stream.
    484485 *
    485486 * Side Effects:
    486  *      condPushback will be set back to None if it is used.
     487 *      condPushback will be set back to None if it is used.
    487488 *
    488489 *-----------------------------------------------------------------------
     
    492493    Boolean doEval;
    493494{
    494     Token         t;
     495    Token         t;
    495496
    496497    if (condPushBack == None) {
    497         while (*condExpr == ' ' || *condExpr == '\t') {
    498             condExpr++;
    499         }
    500         switch (*condExpr) {
    501             case '(':
    502                 t = LParen;
    503                 condExpr++;
    504                 break;
    505             case ')':
    506                 t = RParen;
    507                 condExpr++;
    508                 break;
    509             case '|':
    510                 if (condExpr[1] == '|') {
    511                     condExpr++;
    512                 }
    513                 condExpr++;
    514                 t = Or;
    515                 break;
    516             case '&':
    517                 if (condExpr[1] == '&') {
    518                     condExpr++;
    519                 }
    520                 condExpr++;
    521                 t = And;
    522                 break;
    523             case '!':
    524                 t = Not;
    525                 condExpr++;
    526                 break;
    527             case '\n':
    528             case '\0':
    529                 t = EndOfFile;
    530                 break;
     498        while (*condExpr == ' ' || *condExpr == '\t') {
     499            condExpr++;
     500        }
     501        switch (*condExpr) {
     502            case '(':
     503                t = LParen;
     504                condExpr++;
     505                break;
     506            case ')':
     507                t = RParen;
     508                condExpr++;
     509                break;
     510            case '|':
     511                if (condExpr[1] == '|') {
     512                    condExpr++;
     513                }
     514                condExpr++;
     515                t = Or;
     516                break;
     517            case '&':
     518                if (condExpr[1] == '&') {
     519                    condExpr++;
     520                }
     521                condExpr++;
     522                t = And;
     523                break;
     524            case '!':
     525                t = Not;
     526                condExpr++;
     527                break;
     528            case '\n':
     529            case '\0':
     530                t = EndOfFile;
     531                break;
    531532
    532533            #ifdef NMAKE
    533534            case '[':
    534535                /* @todo execute this command!!! */
    535                 Parse_Error(PARSE_WARNING, "Unsupported NMAKE construct ([])");
     536                Parse_Error(PARSE_WARNING, "Unsupported NMAKE construct ([])");
    536537                t = False;
    537538                condExpr += strlen(condExpr);
     
    543544            case '"':
    544545            #endif
    545             case '$': {
    546                 char    *lhs;
    547                 char    *rhs;
    548                 char    *op;
    549                 int     varSpecLen;
    550                 Boolean doFree;
     546            case '$': {
     547                char    *lhs;
     548                char    *rhs;
     549                char    *op;
     550                int     varSpecLen;
     551                Boolean doFree;
    551552                #ifdef NMAKE
    552553                Boolean fQuoted = (*condExpr == '"');
     
    555556                #endif
    556557
    557                 /*
    558                 * Parse the variable spec and skip over it, saving its
    559                 * value in lhs.
    560                 */
    561                 t = Err;
    562                 lhs = Var_Parse(condExpr, VAR_CMD, doEval,&varSpecLen,&doFree);
     558                /*
     559                * Parse the variable spec and skip over it, saving its
     560                * value in lhs.
     561                */
     562                t = Err;
     563                lhs = Var_Parse(condExpr, VAR_CMD, doEval,&varSpecLen,&doFree);
    563564                #ifdef NMAKE
    564565                if (lhs == var_Error)
     
    568569                }
    569570                #else
    570                 if (lhs == var_Error) {
    571                     /*
    572                      * Even if !doEval, we still report syntax errors, which
    573                      * is what getting var_Error back with !doEval means.
    574                      */
    575                     return(Err);
    576                 }
     571                if (lhs == var_Error) {
     572                    /*
     573                     * Even if !doEval, we still report syntax errors, which
     574                     * is what getting var_Error back with !doEval means.
     575                     */
     576                    return(Err);
     577                }
    577578                #endif
    578                 condExpr += varSpecLen;
     579                condExpr += varSpecLen;
    579580
    580581                #ifdef NMAKE
     
    583584                    )
    584585                #else
    585                 if (!isspace((unsigned char) *condExpr) &&
    586                     strchr("!=><", *condExpr) == NULL)
     586                if (!isspace((unsigned char) *condExpr) &&
     587                    strchr("!=><", *condExpr) == NULL)
    587588                #endif
    588589                {
    589                     Buffer buf;
    590                     char *cp;
    591 
    592                     buf = Buf_Init(0);
    593 
    594                     for (cp = lhs; *cp; cp++)
    595                         Buf_AddByte(buf, (Byte)*cp);
    596 
    597                     if (doFree)
    598                         efree(lhs);
     590                    Buffer buf;
     591                    char *cp;
     592
     593                    buf = Buf_Init(0);
     594
     595                    for (cp = lhs; *cp; cp++)
     596                        Buf_AddByte(buf, (Byte)*cp);
     597
     598                    if (doFree)
     599                        efree(lhs);
    599600
    600601                    #ifdef NMAKE
    601602                    //@todo entirely support escaped quotes and such nitty pick.
    602                     for (;*condExpr && (fQuoted ? *condExpr != '"' : !isspace((unsigned char) *condExpr)); condExpr++)
    603                         Buf_AddByte(buf, (Byte)*condExpr);
     603                    for (;*condExpr && (fQuoted ? *condExpr != '"' : !isspace((unsigned char) *condExpr)); condExpr++)
     604                        Buf_AddByte(buf, (Byte)*condExpr);
    604605                    if (fQuoted && *condExpr == '"')
    605606                        condExpr++;
    606607                    #else
    607                     for (;*condExpr && !isspace((unsigned char) *condExpr); condExpr++)
    608                         Buf_AddByte(buf, (Byte)*condExpr);
     608                    for (;*condExpr && !isspace((unsigned char) *condExpr); condExpr++)
     609                        Buf_AddByte(buf, (Byte)*condExpr);
    609610                    #endif
    610611
    611                     Buf_AddByte(buf, (Byte)'\0');
    612                     lhs = (char *)Buf_GetAll(buf, &varSpecLen);
    613                     Buf_Destroy(buf, FALSE);
    614 
    615                     doFree = TRUE;
    616                 }
    617 
    618                 /*
    619                 * Skip whitespace to get to the operator
    620                 */
     612                    Buf_AddByte(buf, (Byte)'\0');
     613                    lhs = (char *)Buf_GetAll(buf, &varSpecLen);
     614                    Buf_Destroy(buf, FALSE);
     615
     616                    doFree = TRUE;
     617                }
     618
     619                /*
     620                * Skip whitespace to get to the operator
     621                */
    621622                #ifdef NMAKE
    622623                if (fQuoted && *condExpr == '"')
    623624                    condExpr++;
    624625                #endif
    625                 while (isspace((unsigned char) *condExpr))
    626                     condExpr++;
    627 
    628                 /*
    629                 * Make sure the operator is a valid one. If it isn't a
    630                 * known relational operator, pretend we got a
    631                 * != 0 comparison.
    632                 */
    633                 op = condExpr;
    634                 switch (*condExpr) {
    635                     case '!':
    636                     case '=':
    637                     case '<':
    638                     case '>':
    639                         if (condExpr[1] == '=') {
    640                             condExpr += 2;
    641                         } else {
    642                             condExpr += 1;
    643                         }
    644                         break;
    645                     default:
    646                         op = "!=";
    647                         rhs = "0";
    648 
    649                         goto do_compare;
    650                 }
    651                 while (isspace((unsigned char) *condExpr)) {
    652                     condExpr++;
    653                 }
    654                 if (*condExpr == '\0') {
    655                     Parse_Error(PARSE_WARNING,
    656                                 "Missing right-hand-side of operator");
    657                     goto error;
    658                 }
    659                 rhs = condExpr;
     626                while (isspace((unsigned char) *condExpr))
     627                    condExpr++;
     628
     629                /*
     630                * Make sure the operator is a valid one. If it isn't a
     631                * known relational operator, pretend we got a
     632                * != 0 comparison.
     633                */
     634                op = condExpr;
     635                switch (*condExpr) {
     636                    case '!':
     637                    case '=':
     638                    case '<':
     639                    case '>':
     640                        if (condExpr[1] == '=') {
     641                            condExpr += 2;
     642                        } else {
     643                            condExpr += 1;
     644                        }
     645                        break;
     646                    default:
     647                        op = "!=";
     648                        rhs = "0";
     649
     650                        goto do_compare;
     651                }
     652                while (isspace((unsigned char) *condExpr)) {
     653                    condExpr++;
     654                }
     655                if (*condExpr == '\0') {
     656                    Parse_Error(PARSE_WARNING,
     657                                "Missing right-hand-side of operator");
     658                    goto error;
     659                }
     660                rhs = condExpr;
    660661do_compare:
    661                 if (*rhs == '"') {
    662                     /*
    663                      * Doing a string comparison. Only allow == and != for
    664                      * operators.
    665                      */
    666                     char    *string;
    667                     char    *cp, *cp2;
    668                     int     qt;
    669                     Buffer  buf;
     662                if (*rhs == '"') {
     663                    /*
     664                     * Doing a string comparison. Only allow == and != for
     665                     * operators.
     666                     */
     667                    char    *string;
     668                    char    *cp, *cp2;
     669                    int     qt;
     670                    Buffer  buf;
    670671
    671672do_string_compare:
    672                     if (((*op != '!') && (*op != '=')) || (op[1] != '=')) {
    673                         Parse_Error(PARSE_WARNING,
    674                 "String comparison operator should be either == or !=");
    675                         goto error;
    676                     }
    677 
    678                     buf = Buf_Init(0);
    679                     qt = *rhs == '"' ? 1 : 0;
    680 
    681                     for (cp = &rhs[qt];
    682                         ((qt && (*cp != '"')) ||
    683                           (!qt && strchr(" \t)", *cp) == NULL)) &&
    684                         (*cp != '\0'); cp++) {
    685                         if ((*cp == '\\') && (cp[1] != '\0')) {
    686                             /*
    687                              * Backslash escapes things -- skip over next
    688                              * character, if it exists.
    689                              */
    690                             cp++;
    691                             Buf_AddByte(buf, (Byte)*cp);
    692                         } else if (*cp == '$') {
    693                             int len;
    694                             Boolean freeIt;
    695 
    696                             cp2 = Var_Parse(cp, VAR_CMD, doEval,&len, &freeIt);
    697                             if (cp2 != var_Error) {
    698                                 Buf_AddBytes(buf, strlen(cp2), (Byte *)cp2);
    699                                 if (freeIt) {
    700                                     efree(cp2);
    701                                 }
    702                                 cp += len - 1;
    703                             } else {
    704                                 Buf_AddByte(buf, (Byte)*cp);
    705                             }
    706                         } else {
    707                             Buf_AddByte(buf, (Byte)*cp);
    708                         }
    709                     }
    710 
    711                     Buf_AddByte(buf, (Byte)0);
    712 
    713                     string = (char *)Buf_GetAll(buf, (int *)0);
    714                     Buf_Destroy(buf, FALSE);
    715 
    716                     if (DEBUG(COND)) {
    717                         printf("lhs = \"%s\", rhs = \"%s\", op = %.2s\n",
    718                                lhs, string, op);
    719                     }
    720                     /*
    721                      * Null-terminate rhs and perform the comparison.
    722                      * t is set to the result.
    723                      */
    724                     if (*op == '=') {
    725                         t = strcmp(lhs, string) ? False : True;
    726                     } else {
    727                         t = strcmp(lhs, string) ? True : False;
    728                     }
    729                     efree(string);
    730                     if (rhs == condExpr) {
    731                         if (!qt && *cp == ')')
    732                             condExpr = cp;
    733                         else
    734                             condExpr = cp + 1;
    735                     }
    736                 } else {
    737                     /*
    738                      * rhs is either a float or an integer. Convert both the
    739                      * lhs and the rhs to a double and compare the two.
    740                      */
    741                     double      left, right;
    742                     char        *string;
    743 
    744                     if (*CondCvtArg(lhs, &left) != '\0')
    745                         goto do_string_compare;
    746                     if (*rhs == '$') {
    747                         int     len;
    748                         Boolean freeIt;
    749 
    750                         string = Var_Parse(rhs, VAR_CMD, doEval,&len,&freeIt);
    751                         if (string == var_Error) {
    752                             right = 0.0;
    753                         } else {
    754                             if (*CondCvtArg(string, &right) != '\0') {
    755                                 if (freeIt)
    756                                     efree(string);
    757                                 goto do_string_compare;
    758                             }
    759                             if (freeIt)
    760                                 efree(string);
    761                             if (rhs == condExpr)
    762                                 condExpr += len;
    763                         }
    764                     } else {
    765                         char *c = CondCvtArg(rhs, &right);
    766                         if (*c != '\0' && !isspace(*c))
    767                             goto do_string_compare;
    768                         if (rhs == condExpr) {
    769                             /*
    770                              * Skip over the right-hand side
    771                              */
    772                             while(!isspace((unsigned char) *condExpr) &&
    773                                   (*condExpr != '\0')) {
    774                                 condExpr++;
    775                             }
    776                         }
    777                     }
    778 
    779                     if (DEBUG(COND)) {
    780                         printf("left = %f, right = %f, op = %.2s\n", left,
    781                                right, op);
    782                     }
    783                     switch(op[0]) {
    784                     case '!':
    785                         if (op[1] != '=') {
    786                             Parse_Error(PARSE_WARNING,
    787                                         "Unknown operator");
    788                             goto error;
    789                         }
    790                         t = (left != right ? True : False);
    791                         break;
    792                     case '=':
    793                         if (op[1] != '=') {
    794                             Parse_Error(PARSE_WARNING,
    795                                         "Unknown operator");
    796                             goto error;
    797                         }
    798                         t = (left == right ? True : False);
    799                         break;
    800                     case '<':
    801                         if (op[1] == '=') {
    802                             t = (left <= right ? True : False);
    803                         } else {
    804                             t = (left < right ? True : False);
    805                         }
    806                         break;
    807                     case '>':
    808                         if (op[1] == '=') {
    809                             t = (left >= right ? True : False);
    810                         } else {
    811                             t = (left > right ? True : False);
    812                         }
    813                         break;
    814                     }
    815                 }
     673                    if (((*op != '!') && (*op != '=')) || (op[1] != '=')) {
     674                        Parse_Error(PARSE_WARNING,
     675                "String comparison operator should be either == or !=");
     676                        goto error;
     677                    }
     678
     679                    buf = Buf_Init(0);
     680                    qt = *rhs == '"' ? 1 : 0;
     681
     682                    for (cp = &rhs[qt];
     683                        ((qt && (*cp != '"')) ||
     684                          (!qt && strchr(" \t)", *cp) == NULL)) &&
     685                        (*cp != '\0'); cp++) {
     686                        if ((*cp == '\\') && (cp[1] != '\0')) {
     687                            /*
     688                             * Backslash escapes things -- skip over next
     689                             * character, if it exists.
     690                             */
     691                            cp++;
     692                            Buf_AddByte(buf, (Byte)*cp);
     693                        } else if (*cp == '$') {
     694                            int len;
     695                            Boolean freeIt;
     696
     697                            cp2 = Var_Parse(cp, VAR_CMD, doEval,&len, &freeIt);
     698                            if (cp2 != var_Error) {
     699                                Buf_AddBytes(buf, strlen(cp2), (Byte *)cp2);
     700                                if (freeIt) {
     701                                    efree(cp2);
     702                                }
     703                                cp += len - 1;
     704                            } else {
     705                                Buf_AddByte(buf, (Byte)*cp);
     706                            }
     707                        } else {
     708                            Buf_AddByte(buf, (Byte)*cp);
     709                        }
     710                    }
     711
     712                    Buf_AddByte(buf, (Byte)0);
     713
     714                    string = (char *)Buf_GetAll(buf, (int *)0);
     715                    Buf_Destroy(buf, FALSE);
     716
     717                    if (DEBUG(COND)) {
     718                        printf("lhs = \"%s\", rhs = \"%s\", op = %.2s\n",
     719                               lhs, string, op);
     720                    }
     721                    /*
     722                     * Null-terminate rhs and perform the comparison.
     723                     * t is set to the result.
     724                     */
     725                    if (*op == '=') {
     726                        t = strcmp(lhs, string) ? False : True;
     727                    } else {
     728                        t = strcmp(lhs, string) ? True : False;
     729                    }
     730                    efree(string);
     731                    if (rhs == condExpr) {
     732                        if (!qt && *cp == ')')
     733                            condExpr = cp;
     734                        else
     735                            condExpr = cp + 1;
     736                    }
     737                } else {
     738                    /*
     739                     * rhs is either a float or an integer. Convert both the
     740                     * lhs and the rhs to a double and compare the two.
     741                     */
     742                    double      left, right;
     743                    char        *string;
     744
     745                    if (*CondCvtArg(lhs, &left) != '\0')
     746                        goto do_string_compare;
     747                    if (*rhs == '$') {
     748                        int     len;
     749                        Boolean freeIt;
     750
     751                        string = Var_Parse(rhs, VAR_CMD, doEval,&len,&freeIt);
     752                        if (string == var_Error) {
     753                            right = 0.0;
     754                        } else {
     755                            if (*CondCvtArg(string, &right) != '\0') {
     756                                if (freeIt)
     757                                    efree(string);
     758                                goto do_string_compare;
     759                            }
     760                            if (freeIt)
     761                                efree(string);
     762                            if (rhs == condExpr)
     763                                condExpr += len;
     764                        }
     765                    } else {
     766                        char *c = CondCvtArg(rhs, &right);
     767                        if (*c != '\0' && !isspace(*c))
     768                            goto do_string_compare;
     769                        if (rhs == condExpr) {
     770                            /*
     771                             * Skip over the right-hand side
     772                             */
     773                            while(!isspace((unsigned char) *condExpr) &&
     774                                  (*condExpr != '\0')) {
     775                                condExpr++;
     776                            }
     777                        }
     778                    }
     779
     780                    if (DEBUG(COND)) {
     781                        printf("left = %f, right = %f, op = %.2s\n", left,
     782                               right, op);
     783                    }
     784                    switch(op[0]) {
     785                    case '!':
     786                        if (op[1] != '=') {
     787                            Parse_Error(PARSE_WARNING,
     788                                        "Unknown operator");
     789                            goto error;
     790                        }
     791                        t = (left != right ? True : False);
     792                        break;
     793                    case '=':
     794                        if (op[1] != '=') {
     795                            Parse_Error(PARSE_WARNING,
     796                                        "Unknown operator");
     797                            goto error;
     798                        }
     799                        t = (left == right ? True : False);
     800                        break;
     801                    case '<':
     802                        if (op[1] == '=') {
     803                            t = (left <= right ? True : False);
     804                        } else {
     805                            t = (left < right ? True : False);
     806                        }
     807                        break;
     808                    case '>':
     809                        if (op[1] == '=') {
     810                            t = (left >= right ? True : False);
     811                        } else {
     812                            t = (left > right ? True : False);
     813                        }
     814                        break;
     815                    }
     816                }
    816817error:
    817                 if (doFree)
    818                     efree(lhs);
    819                 break;
    820             }
    821             default: {
    822                 Boolean (*evalProc) __P((int, char *));
    823                 Boolean invert = FALSE;
    824                 char    *arg;
    825                 int     arglen;
    826 
    827                 if (strncmp (condExpr, "defined", 7) == 0) {
    828                     /*
    829                      * Use CondDoDefined to evaluate the argument and
    830                      * CondGetArg to extract the argument from the 'function
    831                      * call'.
    832                      */
    833                     evalProc = CondDoDefined;
    834                     condExpr += 7;
    835                     arglen = CondGetArg (&condExpr, &arg, "defined", TRUE);
    836                     if (arglen == 0) {
    837                         condExpr -= 7;
    838                         goto use_default;
    839                     }
    840                 } else if (strncmp (condExpr, "make", 4) == 0) {
    841                     /*
    842                      * Use CondDoMake to evaluate the argument and
    843                      * CondGetArg to extract the argument from the 'function
    844                      * call'.
    845                      */
    846                     evalProc = CondDoMake;
    847                     condExpr += 4;
    848                     arglen = CondGetArg (&condExpr, &arg, "make", TRUE);
    849                     if (arglen == 0) {
    850                         condExpr -= 4;
    851                         goto use_default;
    852                     }
    853                 } else if (strncmp (condExpr, "exists", 6) == 0) {
    854                     /*
    855                      * Use CondDoExists to evaluate the argument and
    856                      * CondGetArg to extract the argument from the
    857                      * 'function call'.
    858                      */
    859                     evalProc = CondDoExists;
    860                     condExpr += 6;
    861                     arglen = CondGetArg(&condExpr, &arg, "exists", TRUE);
    862                     if (arglen == 0) {
    863                         condExpr -= 6;
    864                         goto use_default;
    865                     }
    866                 } else if (strncmp(condExpr, "empty", 5) == 0) {
    867                     /*
    868                      * Use Var_Parse to parse the spec in parens and return
    869                      * True if the resulting string is empty.
    870                      */
    871                     int     length;
    872                     Boolean doFree;
    873                     char    *val;
    874 
    875                     condExpr += 5;
    876 
    877                     for (arglen = 0;
    878                         condExpr[arglen] != '(' && condExpr[arglen] != '\0';
    879                         arglen += 1)
    880                         continue;
    881 
    882                     if (condExpr[arglen] != '\0') {
    883                         val = Var_Parse(&condExpr[arglen - 1], VAR_CMD,
    884                                         doEval, &length, &doFree);
    885                         if (val == var_Error) {
    886                             t = Err;
    887                         } else {
    888                             /*
    889                              * A variable is empty when it just contains
    890                              * spaces... 4/15/92, christos
    891                              */
    892                             char *p;
    893                             for (p = val; *p && isspace((unsigned char)*p); p++)
    894                                 continue;
    895                             t = (*p == '\0') ? True : False;
    896                         }
    897                         if (doFree) {
    898                             efree(val);
    899                         }
    900                         /*
    901                         * Advance condExpr to beyond the closing ). Note that
    902                         * we subtract one from arglen + length b/c length
    903                         * is calculated from condExpr[arglen - 1].
    904                         */
    905                         condExpr += arglen + length - 1;
    906                     } else {
    907                         condExpr -= 5;
    908                         goto use_default;
    909                     }
    910                     break;
    911                 } else if (strncmp (condExpr, "target", 6) == 0) {
    912                     /*
    913                      * Use CondDoTarget to evaluate the argument and
    914                      * CondGetArg to extract the argument from the
    915                      * 'function call'.
    916                      */
    917                     evalProc = CondDoTarget;
    918                     condExpr += 6;
    919                     arglen = CondGetArg(&condExpr, &arg, "target", TRUE);
    920                     if (arglen == 0) {
    921                         condExpr -= 6;
    922                         goto use_default;
    923                     }
    924                 } else {
    925                     /*
    926                      * The symbol is itself the argument to the default
    927                      * function. We advance condExpr to the end of the symbol
    928                      * by hand (the next whitespace, closing paren or
    929                      * binary operator) and set to invert the evaluation
    930                      * function if condInvert is TRUE.
    931                      */
    932                 use_default:
    933                     invert = condInvert;
    934                     evalProc = condDefProc;
    935                     arglen = CondGetArg(&condExpr, &arg, "", FALSE);
    936                 }
    937 
    938                 /*
    939                 * Evaluate the argument using the set function. If invert
    940                 * is TRUE, we invert the sense of the function.
    941                 */
    942                 t = (!doEval || (* evalProc) (arglen, arg) ?
    943                      (invert ? False : True) :
    944                      (invert ? True : False));
    945                 efree(arg);
    946                 break;
    947             }
    948         }
     818                if (doFree)
     819                    efree(lhs);
     820                break;
     821            }
     822            default: {
     823                Boolean (*evalProc) __P((int, char *));
     824                Boolean invert = FALSE;
     825                char    *arg;
     826                int     arglen;
     827
     828                if (strncmp (condExpr, "defined", 7) == 0) {
     829                    /*
     830                     * Use CondDoDefined to evaluate the argument and
     831                     * CondGetArg to extract the argument from the 'function
     832                     * call'.
     833                     */
     834                    evalProc = CondDoDefined;
     835                    condExpr += 7;
     836                    arglen = CondGetArg (&condExpr, &arg, "defined", TRUE);
     837                    if (arglen == 0) {
     838                        condExpr -= 7;
     839                        goto use_default;
     840                    }
     841                } else if (strncmp (condExpr, "make", 4) == 0) {
     842                    /*
     843                     * Use CondDoMake to evaluate the argument and
     844                     * CondGetArg to extract the argument from the 'function
     845                     * call'.
     846                     */
     847                    evalProc = CondDoMake;
     848                    condExpr += 4;
     849                    arglen = CondGetArg (&condExpr, &arg, "make", TRUE);
     850                    if (arglen == 0) {
     851                        condExpr -= 4;
     852                        goto use_default;
     853                    }
     854                } else if (strncmp (condExpr, "exists", 6) == 0) {
     855                    /*
     856                     * Use CondDoExists to evaluate the argument and
     857                     * CondGetArg to extract the argument from the
     858                     * 'function call'.
     859                     */
     860                    evalProc = CondDoExists;
     861                    condExpr += 6;
     862                    arglen = CondGetArg(&condExpr, &arg, "exists", TRUE);
     863                    if (arglen == 0) {
     864                        condExpr -= 6;
     865                        goto use_default;
     866                    }
     867                } else if (strncmp(condExpr, "empty", 5) == 0) {
     868                    /*
     869                     * Use Var_Parse to parse the spec in parens and return
     870                     * True if the resulting string is empty.
     871                     */
     872                    int     length;
     873                    Boolean doFree;
     874                    char    *val;
     875
     876                    condExpr += 5;
     877
     878                    for (arglen = 0;
     879                        condExpr[arglen] != '(' && condExpr[arglen] != '\0';
     880                        arglen += 1)
     881                        continue;
     882
     883                    if (condExpr[arglen] != '\0') {
     884                        val = Var_Parse(&condExpr[arglen - 1], VAR_CMD,
     885                                        doEval, &length, &doFree);
     886                        if (val == var_Error) {
     887                            t = Err;
     888                        } else {
     889                            /*
     890                             * A variable is empty when it just contains
     891                             * spaces... 4/15/92, christos
     892                             */
     893                            char *p;
     894                            for (p = val; *p && isspace((unsigned char)*p); p++)
     895                                continue;
     896                            t = (*p == '\0') ? True : False;
     897                        }
     898                        if (doFree) {
     899                            efree(val);
     900                        }
     901                        /*
     902                        * Advance condExpr to beyond the closing ). Note that
     903                        * we subtract one from arglen + length b/c length
     904                        * is calculated from condExpr[arglen - 1].
     905                        */
     906                        condExpr += arglen + length - 1;
     907                    } else {
     908                        condExpr -= 5;
     909                        goto use_default;
     910                    }
     911                    break;
     912                } else if (strncmp (condExpr, "target", 6) == 0) {
     913                    /*
     914                     * Use CondDoTarget to evaluate the argument and
     915                     * CondGetArg to extract the argument from the
     916                     * 'function call'.
     917                     */
     918                    evalProc = CondDoTarget;
     919                    condExpr += 6;
     920                    arglen = CondGetArg(&condExpr, &arg, "target", TRUE);
     921                    if (arglen == 0) {
     922                        condExpr -= 6;
     923                        goto use_default;
     924                    }
     925                } else {
     926                    /*
     927                     * The symbol is itself the argument to the default
     928                     * function. We advance condExpr to the end of the symbol
     929                     * by hand (the next whitespace, closing paren or
     930                     * binary operator) and set to invert the evaluation
     931                     * function if condInvert is TRUE.
     932                     */
     933                use_default:
     934                    invert = condInvert;
     935                    evalProc = condDefProc;
     936                    arglen = CondGetArg(&condExpr, &arg, "", FALSE);
     937                }
     938
     939                /*
     940                * Evaluate the argument using the set function. If invert
     941                * is TRUE, we invert the sense of the function.
     942                */
     943                t = (!doEval || (* evalProc) (arglen, arg) ?
     944                     (invert ? False : True) :
     945                     (invert ? True : False));
     946                efree(arg);
     947                break;
     948            }
     949        }
    949950    } else {
    950         t = condPushBack;
    951         condPushBack = None;
     951        t = condPushBack;
     952        condPushBack = None;
    952953    }
    953954    return (t);
     
    958959 *-----------------------------------------------------------------------
    959960 * CondT --
    960  *      Parse a single term in the expression. This consists of a terminal
    961  *      symbol or Not and a terminal symbol (not including the binary
    962  *      operators):
    963  *          T -> defined(variable) | make(target) | exists(file) | symbol
    964  *          T -> ! T | ( E )
     961 *      Parse a single term in the expression. This consists of a terminal
     962 *      symbol or Not and a terminal symbol (not including the binary
     963 *      operators):
     964 *          T -> defined(variable) | make(target) | exists(file) | symbol
     965 *          T -> ! T | ( E )
    965966 *
    966967 * Results:
    967  *      True, False or Err.
     968 *      True, False or Err.
    968969 *
    969970 * Side Effects:
    970  *      Tokens are consumed.
     971 *      Tokens are consumed.
    971972 *
    972973 *-----------------------------------------------------------------------
     
    981982
    982983    if (t == EndOfFile) {
    983         /*
    984         * If we reached the end of the expression, the expression
    985         * is malformed...
    986         */
    987         t = Err;
     984        /*
     985        * If we reached the end of the expression, the expression
     986        * is malformed...
     987        */
     988        t = Err;
    988989    } else if (t == LParen) {
    989         /*
    990         * T -> ( E )
    991         */
    992         t = CondE(doEval);
    993         if (t != Err) {
    994             if (CondToken(doEval) != RParen) {
    995                 t = Err;
    996             }
    997         }
     990        /*
     991        * T -> ( E )
     992        */
     993        t = CondE(doEval);
     994        if (t != Err) {
     995            if (CondToken(doEval) != RParen) {
     996                t = Err;
     997            }
     998        }
    998999    } else if (t == Not) {
    999         t = CondT(doEval);
    1000         if (t == True) {
    1001             t = False;
    1002         } else if (t == False) {
    1003             t = True;
    1004         }
     1000        t = CondT(doEval);
     1001        if (t == True) {
     1002            t = False;
     1003        } else if (t == False) {
     1004            t = True;
     1005        }
    10051006    }
    10061007    return (t);
     
    10111012 *-----------------------------------------------------------------------
    10121013 * CondF --
    1013  *      Parse a conjunctive factor (nice name, wot?)
    1014  *          F -> T && F | T
     1014 *      Parse a conjunctive factor (nice name, wot?)
     1015 *          F -> T && F | T
    10151016 *
    10161017 * Results:
    1017  *      True, False or Err
     1018 *      True, False or Err
    10181019 *
    10191020 * Side Effects:
    1020  *      Tokens are consumed.
     1021 *      Tokens are consumed.
    10211022 *
    10221023 *-----------------------------------------------------------------------
     
    10301031    l = CondT(doEval);
    10311032    if (l != Err) {
    1032         o = CondToken(doEval);
    1033 
    1034         if (o == And) {
    1035             /*
    1036              * F -> T && F
    1037              *
    1038              * If T is False, the whole thing will be False, but we have to
    1039              * parse the r.h.s. anyway (to throw it away).
    1040              * If T is True, the result is the r.h.s., be it an Err or no.
    1041              */
    1042             if (l == True) {
    1043                 l = CondF(doEval);
    1044             } else {
    1045                 (void) CondF(FALSE);
    1046             }
    1047         } else {
    1048             /*
    1049              * F -> T
    1050              */
    1051             CondPushBack (o);
    1052         }
     1033        o = CondToken(doEval);
     1034
     1035        if (o == And) {
     1036            /*
     1037             * F -> T && F
     1038             *
     1039             * If T is False, the whole thing will be False, but we have to
     1040             * parse the r.h.s. anyway (to throw it away).
     1041             * If T is True, the result is the r.h.s., be it an Err or no.
     1042             */
     1043            if (l == True) {
     1044                l = CondF(doEval);
     1045            } else {
     1046                (void) CondF(FALSE);
     1047            }
     1048        } else {
     1049            /*
     1050             * F -> T
     1051             */
     1052            CondPushBack (o);
     1053        }
    10531054    }
    10541055    return (l);
     
    10591060 *-----------------------------------------------------------------------
    10601061 * CondE --
    1061  *      Main expression production.
    1062  *          E -> F || E | F
     1062 *      Main expression production.
     1063 *          E -> F || E | F
    10631064 *
    10641065 * Results:
    1065  *      True, False or Err.
     1066 *      True, False or Err.
    10661067 *
    10671068 * Side Effects:
    1068  *      Tokens are, of course, consumed.
     1069 *      Tokens are, of course, consumed.
    10691070 *
    10701071 *-----------------------------------------------------------------------
     
    10781079    l = CondF(doEval);
    10791080    if (l != Err) {
    1080         o = CondToken(doEval);
    1081 
    1082         if (o == Or) {
    1083             /*
    1084              * E -> F || E
    1085              *
    1086              * A similar thing occurs for ||, except that here we make sure
    1087              * the l.h.s. is False before we bother to evaluate the r.h.s.
    1088              * Once again, if l is False, the result is the r.h.s. and once
    1089              * again if l is True, we parse the r.h.s. to throw it away.
    1090              */
    1091             if (l == False) {
    1092                 l = CondE(doEval);
    1093             } else {
    1094                 (void) CondE(FALSE);
    1095             }
    1096         } else {
    1097             /*
    1098              * E -> F
    1099              */
    1100             CondPushBack (o);
    1101         }
     1081        o = CondToken(doEval);
     1082
     1083        if (o == Or) {
     1084            /*
     1085             * E -> F || E
     1086             *
     1087             * A similar thing occurs for ||, except that here we make sure
     1088             * the l.h.s. is False before we bother to evaluate the r.h.s.
     1089             * Once again, if l is False, the result is the r.h.s. and once
     1090             * again if l is True, we parse the r.h.s. to throw it away.
     1091             */
     1092            if (l == False) {
     1093                l = CondE(doEval);
     1094            } else {
     1095                (void) CondE(FALSE);
     1096            }
     1097        } else {
     1098            /*
     1099             * E -> F
     1100             */
     1101            CondPushBack (o);
     1102        }
    11021103    }
    11031104    return (l);
     
    11081109 *-----------------------------------------------------------------------
    11091110 * Cond_Eval --
    1110  *      Evaluate the conditional in the passed line. The line
    1111  *      looks like this:
    1112  *          #<cond-type> <expr>
    1113  *      where <cond-type> is any of if, ifmake, ifnmake, ifdef,
    1114  *      ifndef, elif, elifmake, elifnmake, elifdef, elifndef
    1115  *      and <expr> consists of &&, ||, !, make(target), defined(variable)
    1116  *      and parenthetical groupings thereof.
     1111 *      Evaluate the conditional in the passed line. The line
     1112 *      looks like this:
     1113 *          #<cond-type> <expr>
     1114 *      where <cond-type> is any of if, ifmake, ifnmake, ifdef,
     1115 *      ifndef, elif, elifmake, elifnmake, elifdef, elifndef
     1116 *      and <expr> consists of &&, ||, !, make(target), defined(variable)
     1117 *      and parenthetical groupings thereof.
    11171118 *
    11181119 * Results:
    1119  *      COND_PARSE      if should parse lines after the conditional
    1120  *      COND_SKIP       if should skip lines after the conditional
    1121  *      COND_INVALID    if not a valid conditional.
     1120 *      COND_PARSE      if should parse lines after the conditional
     1121 *      COND_SKIP       if should skip lines after the conditional
     1122 *      COND_INVALID    if not a valid conditional.
    11221123 *
    11231124 * Side Effects:
    1124  *      None.
     1125 *      None.
    11251126 *
    11261127 *-----------------------------------------------------------------------
     
    11281129int
    11291130Cond_Eval (line)
    1130     char            *line;    /* Line to parse */
     1131    char            *line;    /* Line to parse */
    11311132{
    1132     struct If       *ifp;
    1133     Boolean         isElse;
    1134     Boolean         value = FALSE;
    1135     int             level;      /* Level at which to report errors. */
     1133    struct If       *ifp;
     1134    Boolean         isElse;
     1135    Boolean         value = FALSE;
     1136    int             level;      /* Level at which to report errors. */
    11361137
    11371138    level = PARSE_FATAL;
    11381139
    11391140    for (line++; *line == ' ' || *line == '\t'; line++) {
    1140         continue;
     1141        continue;
    11411142    }
    11421143
     
    11461147     */
    11471148    if (line[0] == 'e' && line[1] == 'l') {
    1148         line += 2;
    1149         isElse = TRUE;
     1149        line += 2;
     1150        isElse = TRUE;
    11501151    } else if (strncmp (line, "endif", 5) == 0) {
    1151         /*
    1152         * End of a conditional section. If skipIfLevel is non-zero, that
    1153         * conditional was skipped, so lines following it should also be
    1154         * skipped. Hence, we return COND_SKIP. Otherwise, the conditional
    1155         * was read so succeeding lines should be parsed (think about it...)
    1156         * so we return COND_PARSE, unless this endif isn't paired with
    1157         * a decent if.
    1158         */
    1159         if (skipIfLevel != 0) {
    1160             skipIfLevel -= 1;
    1161             return (COND_SKIP);
    1162         } else {
    1163             if (condTop == MAXIF) {
    1164                 Parse_Error (level, "if-less endif");
    1165                 return (COND_INVALID);
    1166             } else {
    1167                 skipLine = FALSE;
    1168                 condTop += 1;
    1169                 return (COND_PARSE);
    1170             }
    1171         }
     1152        /*
     1153        * End of a conditional section. If skipIfLevel is non-zero, that
     1154        * conditional was skipped, so lines following it should also be
     1155        * skipped. Hence, we return COND_SKIP. Otherwise, the conditional
     1156        * was read so succeeding lines should be parsed (think about it...)
     1157        * so we return COND_PARSE, unless this endif isn't paired with
     1158        * a decent if.
     1159        */
     1160        if (skipIfLevel != 0) {
     1161            skipIfLevel -= 1;
     1162            return (COND_SKIP);
     1163        } else {
     1164            if (condTop == MAXIF) {
     1165                Parse_Error (level, "if-less endif");
     1166                return (COND_INVALID);
     1167            } else {
     1168                skipLine = FALSE;
     1169                condTop += 1;
     1170                return (COND_PARSE);
     1171            }
     1172        }
    11721173    } else {
    1173         isElse = FALSE;
     1174        isElse = FALSE;
    11741175    }
    11751176
     
    11791180     */
    11801181    for (ifp = ifs; ifp->form != (char *)0; ifp++) {
    1181         if (strncmp (ifp->form, line, ifp->formlen) == 0) {
    1182             break;
    1183         }
     1182        if (strncmp (ifp->form, line, ifp->formlen) == 0) {
     1183            break;
     1184        }
    11841185    }
    11851186
    11861187    if (ifp->form == (char *) 0) {
    1187         /*
    1188         * Nothing fit. If the first word on the line is actually
    1189         * "else", it's a valid conditional whose value is the inverse
    1190         * of the previous if we parsed.
    1191         */
    1192         if (isElse && (line[0] == 's') && (line[1] == 'e')) {
    1193             if (condTop == MAXIF) {
    1194                 Parse_Error (level, "if-less else");
    1195                 return (COND_INVALID);
    1196             } else if (skipIfLevel == 0) {
    1197                 value = !condStack[condTop];
    1198             } else {
    1199                 return (COND_SKIP);
    1200             }
    1201         } else {
    1202             /*
    1203              * Not a valid conditional type. No error...
    1204              */
    1205             return (COND_INVALID);
    1206         }
     1188        /*
     1189        * Nothing fit. If the first word on the line is actually
     1190        * "else", it's a valid conditional whose value is the inverse
     1191        * of the previous if we parsed.
     1192        */
     1193        if (isElse && (line[0] == 's') && (line[1] == 'e')) {
     1194            if (condTop == MAXIF) {
     1195                Parse_Error (level, "if-less else");
     1196                return (COND_INVALID);
     1197            } else if (skipIfLevel == 0) {
     1198                value = !condStack[condTop];
     1199            } else {
     1200                return (COND_SKIP);
     1201            }
     1202        } else {
     1203            /*
     1204             * Not a valid conditional type. No error...
     1205             */
     1206            return (COND_INVALID);
     1207        }
    12071208    } else {
    1208         if (isElse) {
    1209             if (condTop == MAXIF) {
    1210                 Parse_Error (level, "if-less elif");
    1211                 return (COND_INVALID);
    1212             } else if (skipIfLevel != 0) {
    1213                 /*
    1214                 * If skipping this conditional, just ignore the whole thing.
    1215                 * If we don't, the user might be employing a variable that's
    1216                 * undefined, for which there's an enclosing ifdef that
    1217                 * we're skipping...
    1218                 */
    1219                 return(COND_SKIP);
    1220             }
    1221         } else if (skipLine) {
    1222             /*
    1223              * Don't even try to evaluate a conditional that's not an else if
    1224              * we're skipping things...
    1225              */
    1226             skipIfLevel += 1;
    1227             return(COND_SKIP);
    1228         }
    1229 
    1230         /*
    1231         * Initialize file-global variables for parsing
    1232         */
    1233         condDefProc = ifp->defProc;
    1234         condInvert = ifp->doNot;
    1235 
    1236         line += ifp->formlen;
    1237 
    1238         while (*line == ' ' || *line == '\t') {
    1239             line++;
    1240         }
    1241 
    1242         condExpr = line;
    1243         condPushBack = None;
    1244 
    1245         switch (CondE(TRUE)) {
    1246             case True:
    1247                 if (CondToken(TRUE) == EndOfFile) {
    1248                     value = TRUE;
    1249                     break;
    1250                 }
    1251                 goto err;
    1252                 /*FALLTHRU*/
    1253             case False:
    1254                 if (CondToken(TRUE) == EndOfFile) {
    1255                     value = FALSE;
    1256                     break;
    1257                 }
    1258                 /*FALLTHRU*/
    1259             case Err:
    1260             err:
    1261                 Parse_Error (level, "Malformed conditional (%s)",
    1262                              line);
    1263                 return (COND_INVALID);
    1264             default:
    1265                 break;
    1266         }
     1209        if (isElse) {
     1210            if (condTop == MAXIF) {
     1211                Parse_Error (level, "if-less elif");
     1212                return (COND_INVALID);
     1213            } else if (skipIfLevel != 0) {
     1214                /*
     1215                * If skipping this conditional, just ignore the whole thing.
     1216                * If we don't, the user might be employing a variable that's
     1217                * undefined, for which there's an enclosing ifdef that
     1218                * we're skipping...
     1219                */
     1220                return(COND_SKIP);
     1221            }
     1222        } else if (skipLine) {
     1223            /*
     1224             * Don't even try to evaluate a conditional that's not an else if
     1225             * we're skipping things...
     1226             */
     1227            skipIfLevel += 1;
     1228            return(COND_SKIP);
     1229        }
     1230
     1231        /*
     1232        * Initialize file-global variables for parsing
     1233        */
     1234        condDefProc = ifp->defProc;
     1235        condInvert = ifp->doNot;
     1236
     1237        line += ifp->formlen;
     1238
     1239        while (*line == ' ' || *line == '\t') {
     1240            line++;
     1241        }
     1242
     1243        condExpr = line;
     1244        condPushBack = None;
     1245
     1246        switch (CondE(TRUE)) {
     1247            case True:
     1248                if (CondToken(TRUE) == EndOfFile) {
     1249                    value = TRUE;
     1250                    break;
     1251                }
     1252                goto err;
     1253                /*FALLTHRU*/
     1254            case False:
     1255                if (CondToken(TRUE) == EndOfFile) {
     1256                    value = FALSE;
     1257                    break;
     1258                }
     1259                /*FALLTHRU*/
     1260            case Err:
     1261            err:
     1262                Parse_Error (level, "Malformed conditional (%s)",
     1263                             line);
     1264                return (COND_INVALID);
     1265            default:
     1266                break;
     1267        }
    12671268    }
    12681269    if (!isElse) {
    1269         condTop -= 1;
     1270        condTop -= 1;
    12701271    } else if ((skipIfLevel != 0) || condStack[condTop]) {
    1271         /*
    1272         * If this is an else-type conditional, it should only take effect
    1273         * if its corresponding if was evaluated and FALSE. If its if was
    1274         * TRUE or skipped, we return COND_SKIP (and start skipping in case
    1275         * we weren't already), leaving the stack unmolested so later elif's
    1276         * don't screw up...
    1277         */
    1278         skipLine = TRUE;
    1279         return (COND_SKIP);
     1272        /*
     1273        * If this is an else-type conditional, it should only take effect
     1274        * if its corresponding if was evaluated and FALSE. If its if was
     1275        * TRUE or skipped, we return COND_SKIP (and start skipping in case
     1276        * we weren't already), leaving the stack unmolested so later elif's
     1277        * don't screw up...
     1278        */
     1279        skipLine = TRUE;
     1280        return (COND_SKIP);
    12801281    }
    12811282
    12821283    if (condTop < 0) {
    1283         /*
    1284         * This is the one case where we can definitely proclaim a fatal
    1285         * error. If we don't, we're hosed.
    1286         */
    1287         Parse_Error (PARSE_FATAL, "Too many nested if's. %d max.", MAXIF);
    1288         return (COND_INVALID);
     1284        /*
     1285        * This is the one case where we can definitely proclaim a fatal
     1286        * error. If we don't, we're hosed.
     1287        */
     1288        Parse_Error (PARSE_FATAL, "Too many nested if's. %d max.", MAXIF);
     1289        return (COND_INVALID);
    12891290    } else {
    1290         condStack[condTop] = value;
    1291         skipLine = !value;
    1292         return (value ? COND_PARSE : COND_SKIP);
     1291        condStack[condTop] = value;
     1292        skipLine = !value;
     1293        return (value ? COND_PARSE : COND_SKIP);
    12931294    }
    12941295}
     
    12981299 *-----------------------------------------------------------------------
    12991300 * Cond_End --
    1300  *      Make sure everything's clean at the end of a makefile.
     1301 *      Make sure everything's clean at the end of a makefile.
    13011302 *
    13021303 * Results:
    1303  *      None.
     1304 *      None.
    13041305 *
    13051306 * Side Effects:
    1306  *      Parse_Error will be called if open conditionals are around.
     1307 *      Parse_Error will be called if open conditionals are around.
    13071308 *
    13081309 *-----------------------------------------------------------------------
     
    13121313{
    13131314    if (condTop != MAXIF) {
    1314         Parse_Error(PARSE_FATAL, "%d open conditional%s", MAXIF-condTop,
    1315                     MAXIF-condTop == 1 ? "" : "s");
     1315        Parse_Error(PARSE_FATAL, "%d open conditional%s", MAXIF-condTop,
     1316                    MAXIF-condTop == 1 ? "" : "s");
    13161317    }
    13171318    condTop = MAXIF;
Note: See TracChangeset for help on using the changeset viewer.