VirtualBox

Changeset 51 in kBuild for trunk/src/kmk/parse.c


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

kMk and porting to kLib.

File:
1 edited

Legend:

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

    r46 r51  
    11/*
    22 * Copyright (c) 1988, 1989, 1990, 1993
    3  *      The Regents of the University of California.  All rights reserved.
     3 *      The Regents of the University of California.  All rights reserved.
    44 * Copyright (c) 1989 by Berkeley Softworks
    55 * All rights reserved.
     
    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[] = "@(#)parse.c     8.3 (Berkeley) 3/19/94";
     41static char sccsid[] = "@(#)parse.c     8.3 (Berkeley) 3/19/94";
    4242#else
    4343static const char rcsid[] =
    4444  "$FreeBSD: src/usr.bin/make/parse.c,v 1.22 1999/08/28 01:03:35 peter Exp $";
    4545#endif
     46#define KLIBFILEDEF rcsid
    4647#endif /* not lint */
    4748
    4849/*-
    4950 * parse.c --
    50  *      Functions to parse a makefile.
    51  *
    52  *      One function, Parse_Init, must be called before any functions
    53  *      in this module are used. After that, the function Parse_File is the
    54  *      main entry point and controls most of the other functions in this
    55  *      module.
    56  *
    57  *      Most important structures are kept in Lsts. Directories for
    58  *      the #include "..." function are kept in the 'parseIncPath' Lst, while
    59  *      those for the #include <...> are kept in the 'sysIncPath' Lst. The
    60  *      targets currently being defined are kept in the 'targets' Lst.
    61  *
    62  *      The variables 'fname' and 'lineno' are used to track the name
    63  *      of the current file and the line number in that file so that error
    64  *      messages can be more meaningful.
     51 *      Functions to parse a makefile.
     52 *
     53 *      One function, Parse_Init, must be called before any functions
     54 *      in this module are used. After that, the function Parse_File is the
     55 *      main entry point and controls most of the other functions in this
     56 *      module.
     57 *
     58 *      Most important structures are kept in Lsts. Directories for
     59 *      the #include "..." function are kept in the 'parseIncPath' Lst, while
     60 *      those for the #include <...> are kept in the 'sysIncPath' Lst. The
     61 *      targets currently being defined are kept in the 'targets' Lst.
     62 *
     63 *      The variables 'fname' and 'lineno' are used to track the name
     64 *      of the current file and the line number in that file so that error
     65 *      messages can be more meaningful.
    6566 *
    6667 * Interface:
    67  *      Parse_Init                  Initialization function which must be
    68  *                                  called before anything else in this module
    69  *                                  is used.
    70  *
    71  *      Parse_End                   Cleanup the module
    72  *
    73  *      Parse_File                  Function used to parse a makefile. It must
    74  *                                  be given the name of the file, which should
    75  *                                  already have been opened, and a function
    76  *                                  to call to read a character from the file.
    77  *
    78  *      Parse_IsVar                 Returns TRUE if the given line is a
    79  *                                  variable assignment. Used by MainParseArgs
    80  *                                  to determine if an argument is a target
    81  *                                  or a variable assignment. Used internally
    82  *                                  for pretty much the same thing...
    83  *
    84  *      Parse_Error                 Function called when an error occurs in
    85  *                                  parsing. Used by the variable and
    86  *                                  conditional modules.
    87  *      Parse_MainName              Returns a Lst of the main target to create.
    88  */
    89 
    90 #if defined(__STDC__) || defined(__IBMC__)
     68 *      Parse_Init                  Initialization function which must be
     69 *                                  called before anything else in this module
     70 *                                  is used.
     71 *
     72 *      Parse_End                   Cleanup the module
     73 *
     74 *      Parse_File                  Function used to parse a makefile. It must
     75 *                                  be given the name of the file, which should
     76 *                                  already have been opened, and a function
     77 *                                  to call to read a character from the file.
     78 *
     79 *      Parse_IsVar                 Returns TRUE if the given line is a
     80 *                                  variable assignment. Used by MainParseArgs
     81 *                                  to determine if an argument is a target
     82 *                                  or a variable assignment. Used internally
     83 *                                  for pretty much the same thing...
     84 *
     85 *      Parse_Error                 Function called when an error occurs in
     86 *                                  parsing. Used by the variable and
     87 *                                  conditional modules.
     88 *      Parse_MainName              Returns a Lst of the main target to create.
     89 */
     90
     91#ifdef __STDC__
    9192#include <stdarg.h>
    9293#else
     
    109110 * or if it's DONE.
    110111 */
    111 #define CONTINUE        1
    112 #define DONE            0
    113 static Lst          targets;    /* targets we're working on */
    114 /*static Lst                targCmds; */        /* command lines for targets */
    115 static Boolean      inLine;     /* true if currently in a dependency
    116                                 * line or its commands */
     112#define CONTINUE        1
     113#define DONE            0
     114static Lst          targets;    /* targets we're working on */
     115/*static Lst                targCmds; */        /* command lines for targets */
     116static Boolean      inLine;     /* true if currently in a dependency
     117                                * line or its commands */
    117118#if defined(USE_INLINEFILES)
    118119static Boolean      inInlineFile; /* true if currently in a inline file.*/
     
    123124} PTR;
    124125
    125 static char         *fname;     /* name of current file (for errors) */
    126 static int          lineno;     /* line number in current file */
    127 static FILE         *curFILE = NULL;    /* current makefile */
    128 
    129 static PTR          *curPTR = NULL;     /* current makefile */
    130 
    131 static int          fatals = 0;
    132 
    133 static GNode        *mainNode;  /* The main target to create. This is the
    134                                 * first target on the first dependency
    135                                 * line in the first makefile */
     126static char         *fname;     /* name of current file (for errors) */
     127static int          lineno;     /* line number in current file */
     128static FILE         *curFILE = NULL;    /* current makefile */
     129
     130static PTR          *curPTR = NULL;     /* current makefile */
     131
     132static int          fatals = 0;
     133
     134static GNode        *mainNode;  /* The main target to create. This is the
     135                                * first target on the first dependency
     136                                * line in the first makefile */
    136137/*
    137138 * Definitions for handling #include specifications
    138139 */
    139140typedef struct IFile {
    140     char           *fname;          /* name of previous file */
    141     int             lineno;         /* saved line number */
    142     FILE *          F;              /* the open stream */
    143     PTR *           p;              /* the char pointer */
     141    char           *fname;          /* name of previous file */
     142    int             lineno;         /* saved line number */
     143    FILE *          F;              /* the open stream */
     144    PTR *           p;              /* the char pointer */
    144145} IFile;
    145146
    146 static Lst      includes;       /* stack of IFiles generated by
    147                                 * #includes */
    148 Lst             parseIncPath;   /* list of directories for "..." includes */
    149 Lst             sysIncPath;     /* list of directories for <...> includes */
     147static Lst      includes;       /* stack of IFiles generated by
     148                                * #includes */
     149Lst             parseIncPath;   /* list of directories for "..." includes */
     150Lst             sysIncPath;     /* list of directories for <...> includes */
    150151
    151152/*-
     
    156157 */
    157158typedef enum {
    158     Begin,          /* .BEGIN */
    159     Default,        /* .DEFAULT */
    160     End,            /* .END */
    161     Ignore,         /* .IGNORE */
    162     Includes,       /* .INCLUDES */
    163     Interrupt,      /* .INTERRUPT */
     159    Begin,          /* .BEGIN */
     160    Default,        /* .DEFAULT */
     161    End,            /* .END */
     162    Ignore,         /* .IGNORE */
     163    Includes,       /* .INCLUDES */
     164    Interrupt,      /* .INTERRUPT */
    164165#ifdef USE_ARCHIVES
    165     Libs,           /* .LIBS */
    166 #endif
    167     MFlags,         /* .MFLAGS or .MAKEFLAGS */
    168     Main,           /* .MAIN and we don't have anything user-specified to
    169                      * make */
    170     NoExport,       /* .NOEXPORT */
    171     Not,            /* Not special */
     166    Libs,           /* .LIBS */
     167#endif
     168    MFlags,         /* .MFLAGS or .MAKEFLAGS */
     169    Main,           /* .MAIN and we don't have anything user-specified to
     170                     * make */
     171    NoExport,       /* .NOEXPORT */
     172    Not,            /* Not special */
    172173    NotParallel,    /* .NOTPARALELL */
    173     Null,           /* .NULL */
    174     Order,          /* .ORDER */
    175     Parallel,       /* .PARALLEL */
    176     ExPath,         /* .PATH */
    177     Phony,          /* .PHONY */
     174    Null,           /* .NULL */
     175    Order,          /* .ORDER */
     176    Parallel,       /* .PARALLEL */
     177    ExPath,         /* .PATH */
     178    Phony,          /* .PHONY */
    178179#ifdef POSIX
    179     Posix,          /* .POSIX */
    180 #endif
    181     Precious,       /* .PRECIOUS */
    182     ExShell,        /* .SHELL */
    183     Silent,         /* .SILENT */
     180    Posix,          /* .POSIX */
     181#endif
     182    Precious,       /* .PRECIOUS */
     183    ExShell,        /* .SHELL */
     184    Silent,         /* .SILENT */
    184185    SingleShell,    /* .SINGLESHELL */
    185     Suffixes,       /* .SUFFIXES */
    186     Wait,           /* .WAIT */
    187     Attribute       /* Generic attribute */
     186    Suffixes,       /* .SUFFIXES */
     187    Wait,           /* .WAIT */
     188    Attribute       /* Generic attribute */
    188189} ParseSpecial;
    189190
     
    195196 * seen, then set to each successive source on the line.
    196197 */
    197 static GNode    *predecessor;
     198static GNode    *predecessor;
    198199
    199200/*
     
    205206 */
    206207static struct {
    207     char          *name;        /* Name of keyword */
    208     ParseSpecial  spec;         /* Type when used as a target */
    209     int           op;           /* Operator when used as a source */
     208    char          *name;        /* Name of keyword */
     209    ParseSpecial  spec;         /* Type when used as a target */
     210    int           op;           /* Operator when used as a source */
    210211} parseKeywords[] = {
    211 { ".BEGIN",       Begin,        0 },
    212 { ".DEFAULT",     Default,      0 },
    213 { ".END",         End,          0 },
    214 { ".EXEC",        Attribute,    OP_EXEC },
    215 { ".IGNORE",      Ignore,       OP_IGNORE },
    216 { ".INCLUDES",    Includes,     0 },
    217 { ".INTERRUPT",   Interrupt,    0 },
    218 { ".INVISIBLE",   Attribute,    OP_INVISIBLE },
    219 { ".JOIN",        Attribute,    OP_JOIN },
     212{ ".BEGIN",       Begin,        0 },
     213{ ".DEFAULT",     Default,      0 },
     214{ ".END",         End,          0 },
     215{ ".EXEC",        Attribute,    OP_EXEC },
     216{ ".IGNORE",      Ignore,       OP_IGNORE },
     217{ ".INCLUDES",    Includes,     0 },
     218{ ".INTERRUPT",   Interrupt,    0 },
     219{ ".INVISIBLE",   Attribute,    OP_INVISIBLE },
     220{ ".JOIN",        Attribute,    OP_JOIN },
    220221#ifdef USE_ARCHIVES
    221 { ".LIBS",        Libs,         0 },
    222 #endif
    223 { ".MAIN",        Main,         0 },
    224 { ".MAKE",        Attribute,    OP_MAKE },
    225 { ".MAKEFLAGS",   MFlags,       0 },
    226 { ".MFLAGS",      MFlags,       0 },
    227 { ".NOTMAIN",     Attribute,    OP_NOTMAIN },
    228 { ".NOTPARALLEL", NotParallel,  0 },
    229 { ".NO_PARALLEL", NotParallel,  0 },
    230 { ".NULL",        Null,         0 },
    231 { ".OPTIONAL",    Attribute,    OP_OPTIONAL },
    232 { ".ORDER",       Order,        0 },
    233 { ".PARALLEL",    Parallel,     0 },
    234 { ".PATH",        ExPath,       0 },
    235 { ".PHONY",       Phony,        OP_PHONY },
     222{ ".LIBS",        Libs,         0 },
     223#endif
     224{ ".MAIN",        Main,         0 },
     225{ ".MAKE",        Attribute,    OP_MAKE },
     226{ ".MAKEFLAGS",   MFlags,       0 },
     227{ ".MFLAGS",      MFlags,       0 },
     228{ ".NOTMAIN",     Attribute,    OP_NOTMAIN },
     229{ ".NOTPARALLEL", NotParallel,  0 },
     230{ ".NO_PARALLEL", NotParallel,  0 },
     231{ ".NULL",        Null,         0 },
     232{ ".OPTIONAL",    Attribute,    OP_OPTIONAL },
     233{ ".ORDER",       Order,        0 },
     234{ ".PARALLEL",    Parallel,     0 },
     235{ ".PATH",        ExPath,       0 },
     236{ ".PHONY",       Phony,        OP_PHONY },
    236237#ifdef POSIX
    237 { ".POSIX",       Posix,        0 },
    238 #endif
    239 { ".PRECIOUS",    Precious,     OP_PRECIOUS },
    240 { ".RECURSIVE",   Attribute,    OP_MAKE },
    241 { ".SHELL",       ExShell,      0 },
    242 { ".SILENT",      Silent,       OP_SILENT },
    243 { ".SINGLESHELL", SingleShell,  0 },
    244 { ".SUFFIXES",    Suffixes,     0 },
    245 { ".USE",         Attribute,    OP_USE },
    246 { ".WAIT",        Wait,         0 },
     238{ ".POSIX",       Posix,        0 },
     239#endif
     240{ ".PRECIOUS",    Precious,     OP_PRECIOUS },
     241{ ".RECURSIVE",   Attribute,    OP_MAKE },
     242{ ".SHELL",       ExShell,      0 },
     243{ ".SILENT",      Silent,       OP_SILENT },
     244{ ".SINGLESHELL", SingleShell,  0 },
     245{ ".SUFFIXES",    Suffixes,     0 },
     246{ ".USE",         Attribute,    OP_USE },
     247{ ".WAIT",        Wait,         0 },
    247248};
    248249
     
    277278 *----------------------------------------------------------------------
    278279 * ParseFindKeyword --
    279  *      Look in the table of keywords for one matching the given string.
     280 *      Look in the table of keywords for one matching the given string.
    280281 *
    281282 * Results:
    282  *      The index of the keyword, or -1 if it isn't there.
     283 *      The index of the keyword, or -1 if it isn't there.
    283284 *
    284285 * Side Effects:
    285  *      None
     286 *      None
    286287 *----------------------------------------------------------------------
    287288 */
    288289static int
    289290ParseFindKeyword (str)
    290     char            *str;               /* String to find */
     291    char            *str;               /* String to find */
    291292{
    292293    register int    start,
    293                     end,
    294                     cur;
     294                    end,
     295                    cur;
    295296    register int    diff;
    296297
     
    299300
    300301    do {
    301         cur = start + ((end - start) / 2);
    302         diff = strcmp (str, parseKeywords[cur].name);
    303 
    304         if (diff == 0) {
    305             return (cur);
    306         } else if (diff < 0) {
    307             end = cur - 1;
    308         } else {
    309             start = cur + 1;
    310         }
     302        cur = start + ((end - start) / 2);
     303        diff = strcmp (str, parseKeywords[cur].name);
     304
     305        if (diff == 0) {
     306            return (cur);
     307        } else if (diff < 0) {
     308            end = cur - 1;
     309        } else {
     310            start = cur + 1;
     311        }
    311312    } while (start <= end);
    312313    return (-1);
     
    315316/*-
    316317 * Parse_Error  --
    317  *      Error message abort function for parsing. Prints out the context
    318  *      of the error (line number and file) as well as the message with
    319  *      two optional arguments.
     318 *      Error message abort function for parsing. Prints out the context
     319 *      of the error (line number and file) as well as the message with
     320 *      two optional arguments.
    320321 *
    321322 * Results:
    322  *      None
     323 *      None
    323324 *
    324325 * Side Effects:
    325  *      "fatals" is incremented if the level is PARSE_FATAL.
     326 *      "fatals" is incremented if the level is PARSE_FATAL.
    326327 */
    327328/* VARARGS */
     
    331332#else
    332333Parse_Error(va_alist)
    333         va_dcl
    334 #endif
    335 {
    336         va_list ap;
     334        va_dcl
     335#endif
     336{
     337        va_list ap;
    337338#if defined(__STDC__) || defined(__IBMC__)
    338         va_start(ap, fmt);
     339        va_start(ap, fmt);
    339340#else
    340         int type;               /* Error type (PARSE_WARNING, PARSE_FATAL) */
    341         char *fmt;
    342 
    343         va_start(ap);
    344         type = va_arg(ap, int);
    345         fmt = va_arg(ap, char *);
    346 #endif
    347 
    348         (void)fprintf(stderr, "\"%s\", line %d: ", fname, lineno);
    349         if (type == PARSE_WARNING)
    350                 (void)fprintf(stderr, "warning: ");
    351         (void)vfprintf(stderr, fmt, ap);
    352         va_end(ap);
    353         (void)fprintf(stderr, "\n");
    354         (void)fflush(stderr);
    355         if (type == PARSE_FATAL)
    356                 fatals += 1;
     341        int type;               /* Error type (PARSE_WARNING, PARSE_FATAL) */
     342        char *fmt;
     343
     344        va_start(ap);
     345        type = va_arg(ap, int);
     346        fmt = va_arg(ap, char *);
     347#endif
     348
     349        (void)fprintf(stderr, "\"%s\", line %d: ", fname, lineno);
     350        if (type == PARSE_WARNING)
     351                (void)fprintf(stderr, "warning: ");
     352        (void)vfprintf(stderr, fmt, ap);
     353        va_end(ap);
     354        (void)fprintf(stderr, "\n");
     355        (void)fflush(stderr);
     356        if (type == PARSE_FATAL)
     357                fatals += 1;
    357358}
    358359
     
    360361 *---------------------------------------------------------------------
    361362 * ParseLinkSrc  --
    362  *      Link the parent node to its new child. Used in a Lst_ForEach by
    363  *      ParseDoDependency. If the specType isn't 'Not', the parent
    364  *      isn't linked as a parent of the child.
     363 *      Link the parent node to its new child. Used in a Lst_ForEach by
     364 *      ParseDoDependency. If the specType isn't 'Not', the parent
     365 *      isn't linked as a parent of the child.
    365366 *
    366367 * Results:
    367  *      Always = 0
     368 *      Always = 0
    368369 *
    369370 * Side Effects:
    370  *      New elements are added to the parents list of cgn and the
    371  *      children list of cgn. the unmade field of pgn is updated
    372  *      to reflect the additional child.
     371 *      New elements are added to the parents list of cgn and the
     372 *      children list of cgn. the unmade field of pgn is updated
     373 *      to reflect the additional child.
    373374 *---------------------------------------------------------------------
    374375 */
    375376static int
    376377ParseLinkSrc (pgnp, cgnp)
    377     ClientData     pgnp;        /* The parent node */
    378     ClientData     cgnp;        /* The child node */
     378    ClientData     pgnp;        /* The parent node */
     379    ClientData     cgnp;        /* The child node */
    379380{
    380381    GNode          *pgn = (GNode *) pgnp;
    381382    GNode          *cgn = (GNode *) cgnp;
    382383    if (Lst_Member (pgn->children, (ClientData)cgn) == NILLNODE) {
    383         (void)Lst_AtEnd (pgn->children, (ClientData)cgn);
    384         if (specType == Not) {
    385             (void)Lst_AtEnd (cgn->parents, (ClientData)pgn);
    386         }
    387         pgn->unmade += 1;
     384        (void)Lst_AtEnd (pgn->children, (ClientData)cgn);
     385        if (specType == Not) {
     386            (void)Lst_AtEnd (cgn->parents, (ClientData)pgn);
     387        }
     388        pgn->unmade += 1;
    388389    }
    389390    return (0);
     
    393394 *---------------------------------------------------------------------
    394395 * ParseDoOp  --
    395  *      Apply the parsed operator to the given target node. Used in a
    396  *      Lst_ForEach call by ParseDoDependency once all targets have
    397  *      been found and their operator parsed. If the previous and new
    398  *      operators are incompatible, a major error is taken.
     396 *      Apply the parsed operator to the given target node. Used in a
     397 *      Lst_ForEach call by ParseDoDependency once all targets have
     398 *      been found and their operator parsed. If the previous and new
     399 *      operators are incompatible, a major error is taken.
    399400 *
    400401 * Results:
    401  *      Always 0
     402 *      Always 0
    402403 *
    403404 * Side Effects:
    404  *      The type field of the node is altered to reflect any new bits in
    405  *      the op.
     405 *      The type field of the node is altered to reflect any new bits in
     406 *      the op.
    406407 *---------------------------------------------------------------------
    407408 */
    408409static int
    409410ParseDoOp (gnp, opp)
    410     ClientData     gnp;         /* The node to which the operator is to be
    411                                 * applied */
    412     ClientData     opp;         /* The operator to apply */
     411    ClientData     gnp;         /* The node to which the operator is to be
     412                                * applied */
     413    ClientData     opp;         /* The operator to apply */
    413414{
    414415    GNode          *gn = (GNode *) gnp;
     
    420421     */
    421422    if (((op & OP_OPMASK) != (gn->type & OP_OPMASK)) &&
    422         !OP_NOP(gn->type) && !OP_NOP(op))
     423        !OP_NOP(gn->type) && !OP_NOP(op))
    423424    {
    424         Parse_Error (PARSE_FATAL, "Inconsistent operator for %s", gn->name);
    425         return (1);
     425        Parse_Error (PARSE_FATAL, "Inconsistent operator for %s", gn->name);
     426        return (1);
    426427    }
    427428
    428429    if ((op == OP_DOUBLEDEP) && ((gn->type & OP_OPMASK) == OP_DOUBLEDEP)) {
    429         /*
    430         * If the node was the object of a :: operator, we need to create a
    431         * new instance of it for the children and commands on this dependency
    432         * line. The new instance is placed on the 'cohorts' list of the
    433         * initial one (note the initial one is not on its own cohorts list)
    434         * and the new instance is linked to all parents of the initial
    435         * instance.
    436         */
    437         register GNode  *cohort;
    438         LstNode         ln;
    439 
    440         cohort = Targ_NewGN(gn->name);
    441         /*
    442         * Duplicate links to parents so graph traversal is simple. Perhaps
    443         * some type bits should be duplicated?
    444         *
    445         * Make the cohort invisible as well to avoid duplicating it into
    446         * other variables. True, parents of this target won't tend to do
    447         * anything with their local variables, but better safe than
    448         * sorry.
    449         */
    450         Lst_ForEach(gn->parents, ParseLinkSrc, (ClientData)cohort);
    451         cohort->type = OP_DOUBLEDEP|OP_INVISIBLE;
    452         (void)Lst_AtEnd(gn->cohorts, (ClientData)cohort);
    453 
    454         /*
    455         * Replace the node in the targets list with the new copy
    456         */
    457         ln = Lst_Member(targets, (ClientData)gn);
    458         Lst_Replace(ln, (ClientData)cohort);
    459         gn = cohort;
     430        /*
     431        * If the node was the object of a :: operator, we need to create a
     432        * new instance of it for the children and commands on this dependency
     433        * line. The new instance is placed on the 'cohorts' list of the
     434        * initial one (note the initial one is not on its own cohorts list)
     435        * and the new instance is linked to all parents of the initial
     436        * instance.
     437        */
     438        register GNode  *cohort;
     439        LstNode         ln;
     440
     441        cohort = Targ_NewGN(gn->name);
     442        /*
     443        * Duplicate links to parents so graph traversal is simple. Perhaps
     444        * some type bits should be duplicated?
     445        *
     446        * Make the cohort invisible as well to avoid duplicating it into
     447        * other variables. True, parents of this target won't tend to do
     448        * anything with their local variables, but better safe than
     449        * sorry.
     450        */
     451        Lst_ForEach(gn->parents, ParseLinkSrc, (ClientData)cohort);
     452        cohort->type = OP_DOUBLEDEP|OP_INVISIBLE;
     453        (void)Lst_AtEnd(gn->cohorts, (ClientData)cohort);
     454
     455        /*
     456        * Replace the node in the targets list with the new copy
     457        */
     458        ln = Lst_Member(targets, (ClientData)gn);
     459        Lst_Replace(ln, (ClientData)cohort);
     460        gn = cohort;
    460461    }
    461462    /*
     
    471472 *---------------------------------------------------------------------
    472473 * ParseAddDep  --
    473  *      Check if the pair of GNodes given needs to be synchronized.
    474  *      This has to be when two nodes are on different sides of a
    475  *      .WAIT directive.
     474 *      Check if the pair of GNodes given needs to be synchronized.
     475 *      This has to be when two nodes are on different sides of a
     476 *      .WAIT directive.
    476477 *
    477478 * Results:
    478  *      Returns 1 if the two targets need to be ordered, 0 otherwise.
    479  *      If it returns 1, the search can stop
     479 *      Returns 1 if the two targets need to be ordered, 0 otherwise.
     480 *      If it returns 1, the search can stop
    480481 *
    481482 * Side Effects:
    482  *      A dependency can be added between the two nodes.
     483 *      A dependency can be added between the two nodes.
    483484 *
    484485 *---------------------------------------------------------------------
     
    493494
    494495    if (p->order < s->order) {
    495         /*
    496         * XXX: This can cause loops, and loops can cause unmade targets,
    497         * but checking is tedious, and the debugging output can show the
    498         * problem
    499         */
    500         (void)Lst_AtEnd(p->successors, (ClientData)s);
    501         (void)Lst_AtEnd(s->preds, (ClientData)p);
    502         return 0;
     496        /*
     497        * XXX: This can cause loops, and loops can cause unmade targets,
     498        * but checking is tedious, and the debugging output can show the
     499        * problem
     500        */
     501        (void)Lst_AtEnd(p->successors, (ClientData)s);
     502        (void)Lst_AtEnd(s->preds, (ClientData)p);
     503        return 0;
    503504    }
    504505    else
    505         return 1;
     506        return 1;
    506507}
    507508
     
    510511 *---------------------------------------------------------------------
    511512 * ParseDoSrc  --
    512  *      Given the name of a source, figure out if it is an attribute
    513  *      and apply it to the targets if it is. Else decide if there is
    514  *      some attribute which should be applied *to* the source because
    515  *      of some special target and apply it if so. Otherwise, make the
    516  *      source be a child of the targets in the list 'targets'
     513 *      Given the name of a source, figure out if it is an attribute
     514 *      and apply it to the targets if it is. Else decide if there is
     515 *      some attribute which should be applied *to* the source because
     516 *      of some special target and apply it if so. Otherwise, make the
     517 *      source be a child of the targets in the list 'targets'
    517518 *
    518519 * Results:
    519  *      None
     520 *      None
    520521 *
    521522 * Side Effects:
    522  *      Operator bits may be added to the list of targets or to the source.
    523  *      The targets may have a new source added to their lists of children.
     523 *      Operator bits may be added to the list of targets or to the source.
     524 *      The targets may have a new source added to their lists of children.
    524525 *---------------------------------------------------------------------
    525526 */
    526527static void
    527528ParseDoSrc (tOp, src, allsrc)
    528     int         tOp;    /* operator (if any) from special targets */
    529     char        *src;   /* name of the source to handle */
    530     Lst         allsrc; /* List of all sources to wait for */
    531 {
    532     GNode       *gn = NULL;
     529    int         tOp;    /* operator (if any) from special targets */
     530    char        *src;   /* name of the source to handle */
     531    Lst         allsrc; /* List of all sources to wait for */
     532{
     533    GNode       *gn = NULL;
    533534
    534535    if (*src == '.' && isupper (src[1])) {
    535         int keywd = ParseFindKeyword(src);
    536         if (keywd != -1) {
    537             int op = parseKeywords[keywd].op;
    538             if (op != 0) {
    539                 Lst_ForEach (targets, ParseDoOp, (ClientData)&op);
    540                 return;
    541             }
    542             if (parseKeywords[keywd].spec == Wait) {
    543                 waiting++;
    544                 return;
    545             }
    546         }
     536        int keywd = ParseFindKeyword(src);
     537        if (keywd != -1) {
     538            int op = parseKeywords[keywd].op;
     539            if (op != 0) {
     540                Lst_ForEach (targets, ParseDoOp, (ClientData)&op);
     541                return;
     542            }
     543            if (parseKeywords[keywd].spec == Wait) {
     544                waiting++;
     545                return;
     546            }
     547        }
    547548    }
    548549
    549550    switch (specType) {
    550551    case Main:
    551         /*
    552         * If we have noted the existence of a .MAIN, it means we need
    553         * to add the sources of said target to the list of things
    554         * to create. The string 'src' is likely to be efree, so we
    555         * must make a new copy of it. Note that this will only be
    556         * invoked if the user didn't specify a target on the command
    557         * line. This is to allow #ifmake's to succeed, or something...
    558         */
    559         (void) Lst_AtEnd (create, (ClientData)estrdup(src));
    560         /*
    561         * Add the name to the .TARGETS variable as well, so the user cna
    562         * employ that, if desired.
    563         */
    564         Var_Append(".TARGETS", src, VAR_GLOBAL);
    565         return;
     552        /*
     553        * If we have noted the existence of a .MAIN, it means we need
     554        * to add the sources of said target to the list of things
     555        * to create. The string 'src' is likely to be efree, so we
     556        * must make a new copy of it. Note that this will only be
     557        * invoked if the user didn't specify a target on the command
     558        * line. This is to allow #ifmake's to succeed, or something...
     559        */
     560        (void) Lst_AtEnd (create, (ClientData)estrdup(src));
     561        /*
     562        * Add the name to the .TARGETS variable as well, so the user cna
     563        * employ that, if desired.
     564        */
     565        Var_Append(".TARGETS", src, VAR_GLOBAL);
     566        return;
    566567
    567568    case Order:
    568         /*
    569         * Create proper predecessor/successor links between the previous
    570         * source and the current one.
    571         */
    572         gn = Targ_FindNode(src, TARG_CREATE);
    573         if (predecessor != NILGNODE) {
    574             (void)Lst_AtEnd(predecessor->successors, (ClientData)gn);
    575             (void)Lst_AtEnd(gn->preds, (ClientData)predecessor);
    576         }
    577         /*
    578         * The current source now becomes the predecessor for the next one.
    579         */
    580         predecessor = gn;
    581         break;
     569        /*
     570        * Create proper predecessor/successor links between the previous
     571        * source and the current one.
     572        */
     573        gn = Targ_FindNode(src, TARG_CREATE);
     574        if (predecessor != NILGNODE) {
     575            (void)Lst_AtEnd(predecessor->successors, (ClientData)gn);
     576            (void)Lst_AtEnd(gn->preds, (ClientData)predecessor);
     577        }
     578        /*
     579        * The current source now becomes the predecessor for the next one.
     580        */
     581        predecessor = gn;
     582        break;
    582583
    583584    default:
    584         /*
    585         * If the source is not an attribute, we need to find/create
    586         * a node for it. After that we can apply any operator to it
    587         * from a special target or link it to its parents, as
    588         * appropriate.
    589         *
    590         * In the case of a source that was the object of a :: operator,
    591         * the attribute is applied to all of its instances (as kept in
    592         * the 'cohorts' list of the node) or all the cohorts are linked
    593         * to all the targets.
    594         */
    595         gn = Targ_FindNode (src, TARG_CREATE);
    596         if (tOp) {
    597             gn->type |= tOp;
    598         } else {
    599             Lst_ForEach (targets, ParseLinkSrc, (ClientData)gn);
    600         }
    601         if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) {
    602             register GNode      *cohort;
    603             register LstNode    ln;
    604 
    605             for (ln=Lst_First(gn->cohorts); ln != NILLNODE; ln = Lst_Succ(ln)){
    606                 cohort = (GNode *)Lst_Datum(ln);
    607                 if (tOp) {
    608                     cohort->type |= tOp;
    609                 } else {
    610                     Lst_ForEach(targets, ParseLinkSrc, (ClientData)cohort);
    611                 }
    612             }
    613         }
    614         break;
     585        /*
     586        * If the source is not an attribute, we need to find/create
     587        * a node for it. After that we can apply any operator to it
     588        * from a special target or link it to its parents, as
     589        * appropriate.
     590        *
     591        * In the case of a source that was the object of a :: operator,
     592        * the attribute is applied to all of its instances (as kept in
     593        * the 'cohorts' list of the node) or all the cohorts are linked
     594        * to all the targets.
     595        */
     596        gn = Targ_FindNode (src, TARG_CREATE);
     597        if (tOp) {
     598            gn->type |= tOp;
     599        } else {
     600            Lst_ForEach (targets, ParseLinkSrc, (ClientData)gn);
     601        }
     602        if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) {
     603            register GNode      *cohort;
     604            register LstNode    ln;
     605
     606            for (ln=Lst_First(gn->cohorts); ln != NILLNODE; ln = Lst_Succ(ln)){
     607                cohort = (GNode *)Lst_Datum(ln);
     608                if (tOp) {
     609                    cohort->type |= tOp;
     610                } else {
     611                    Lst_ForEach(targets, ParseLinkSrc, (ClientData)cohort);
     612                }
     613            }
     614        }
     615        break;
    615616    }
    616617
     
    618619    (void)Lst_AtEnd(allsrc, (ClientData)gn);
    619620    if (waiting) {
    620         Lst_ForEach(allsrc, ParseAddDep, (ClientData)gn);
     621        Lst_ForEach(allsrc, ParseAddDep, (ClientData)gn);
    621622    }
    622623}
     
    625626 *-----------------------------------------------------------------------
    626627 * ParseFindMain --
    627  *      Find a real target in the list and set it to be the main one.
    628  *      Called by ParseDoDependency when a main target hasn't been found
    629  *      yet.
     628 *      Find a real target in the list and set it to be the main one.
     629 *      Called by ParseDoDependency when a main target hasn't been found
     630 *      yet.
    630631 *
    631632 * Results:
    632  *      0 if main not found yet, 1 if it is.
     633 *      0 if main not found yet, 1 if it is.
    633634 *
    634635 * Side Effects:
    635  *      mainNode is changed and Targ_SetMain is called.
     636 *      mainNode is changed and Targ_SetMain is called.
    636637 *
    637638 *-----------------------------------------------------------------------
     
    639640static int
    640641ParseFindMain(gnp, dummy)
    641     ClientData    gnp;      /* Node to examine */
     642    ClientData    gnp;      /* Node to examine */
    642643    ClientData    dummy;
    643644{
    644     GNode         *gn = (GNode *) gnp;
     645    GNode         *gn = (GNode *) gnp;
    645646    if ((gn->type & (OP_NOTMAIN|OP_USE|OP_EXEC|OP_TRANSFORM)) == 0) {
    646         mainNode = gn;
    647         Targ_SetMain(gn);
    648         return (dummy ? 1 : 1);
     647        mainNode = gn;
     648        Targ_SetMain(gn);
     649        return (dummy ? 1 : 1);
    649650    } else {
    650         return (dummy ? 0 : 0);
     651        return (dummy ? 0 : 0);
    651652    }
    652653}
     
    655656 *-----------------------------------------------------------------------
    656657 * ParseAddDir --
    657  *      Front-end for Dir_AddDir to make sure Lst_ForEach keeps going
     658 *      Front-end for Dir_AddDir to make sure Lst_ForEach keeps going
    658659 *
    659660 * Results:
    660  *      === 0
     661 *      === 0
    661662 *
    662663 * Side Effects:
    663  *      See Dir_AddDir.
     664 *      See Dir_AddDir.
    664665 *
    665666 *-----------------------------------------------------------------------
     
    667668static int
    668669ParseAddDir(path, name)
    669     ClientData    path;
     670    ClientData    path;
    670671    ClientData    name;
    671672{
     
    677678 *-----------------------------------------------------------------------
    678679 * ParseClearPath --
    679  *      Front-end for Dir_ClearPath to make sure Lst_ForEach keeps going
     680 *      Front-end for Dir_ClearPath to make sure Lst_ForEach keeps going
    680681 *
    681682 * Results:
    682  *      === 0
     683 *      === 0
    683684 *
    684685 * Side Effects:
    685  *      See Dir_ClearPath
     686 *      See Dir_ClearPath
    686687 *
    687688 *-----------------------------------------------------------------------
     
    699700 *---------------------------------------------------------------------
    700701 * ParseDoDependency  --
    701  *      Parse the dependency line in line.
     702 *      Parse the dependency line in line.
    702703 *
    703704 * Results:
    704  *      None
     705 *      None
    705706 *
    706707 * Side Effects:
    707  *      The nodes of the sources are linked as children to the nodes of the
    708  *      targets. Some nodes may be created.
    709  *
    710  *      We parse a dependency line by first extracting words from the line and
     708 *      The nodes of the sources are linked as children to the nodes of the
     709 *      targets. Some nodes may be created.
     710 *
     711 *      We parse a dependency line by first extracting words from the line and
    711712 * finding nodes in the list of all targets with that name. This is done
    712713 * until a character is encountered which is an operator character. Currently
    713714 * these are only ! and :. At this point the operator is parsed and the
    714715 * pointer into the line advanced until the first source is encountered.
    715  *      The parsed operator is applied to each node in the 'targets' list,
     716 *      The parsed operator is applied to each node in the 'targets' list,
    716717 * which is where the nodes found for the targets are kept, by means of
    717718 * the ParseDoOp function.
    718  *      The sources are read in much the same way as the targets were except
     719 *      The sources are read in much the same way as the targets were except
    719720 * that now they are expanded using the wildcarding scheme of the C-Shell
    720721 * and all instances of the resulting words in the list of all targets
    721722 * are found. Each of the resulting nodes is then linked to each of the
    722723 * targets as one of its children.
    723  *      Certain targets are handled specially. These are the ones detailed
     724 *      Certain targets are handled specially. These are the ones detailed
    724725 * by the specType variable.
    725  *      The storing of transformation rules is also taken care of here.
     726 *      The storing of transformation rules is also taken care of here.
    726727 * A target is recognized as a transformation rule by calling
    727728 * Suff_IsTransform. If it is a transformation rule, its node is gotten
     
    732733static void
    733734ParseDoDependency (line)
    734     char           *line;       /* the line to parse */
    735 {
    736     char           *cp;         /* our current position */
    737     GNode          *gn;         /* a general purpose temporary node */
    738     int             op;         /* the operator on the line */
    739     char            savec;      /* a place to save a character */
    740     Lst             paths;      /* List of search paths to alter when parsing
    741                                 * a list of .PATH targets */
    742     int             tOp;        /* operator from special target */
     735    char           *line;       /* the line to parse */
     736{
     737    char           *cp;         /* our current position */
     738    GNode          *gn;         /* a general purpose temporary node */
     739    int             op;         /* the operator on the line */
     740    char            savec;      /* a place to save a character */
     741    Lst             paths;      /* List of search paths to alter when parsing
     742                                * a list of .PATH targets */
     743    int             tOp;        /* operator from special target */
    743744#ifdef USE_ARCHIVES
    744     Lst             sources;    /* list of archive source names after
    745                                 * expansion */
    746 #endif
    747     Lst             curTargs;   /* list of target names to be found and added
    748                                 * to the targets list */
    749     Lst             curSrcs;    /* list of sources in order */
     745    Lst             sources;    /* list of archive source names after
     746                                * expansion */
     747#endif
     748    Lst             curTargs;   /* list of target names to be found and added
     749                                * to the targets list */
     750    Lst             curSrcs;    /* list of sources in order */
    750751
    751752    tOp = 0;
     
    759760
    760761    do {
    761         for (cp = line;
    762              *cp && !isspace (*cp) &&
    763              (*cp != '!') && (*cp != ':') && (*cp != '(');
    764              cp++)
    765         {
    766             if (*cp == '$') {
    767                 /*
    768                 * Must be a dynamic source (would have been expanded
    769                 * otherwise), so call the Var module to parse the puppy
    770                 * so we can safely advance beyond it...There should be
    771                 * no errors in this, as they would have been discovered
    772                 * in the initial Var_Subst and we wouldn't be here.
    773                 */
    774                 int     length;
    775                 Boolean freeIt;
    776                 char    *result;
    777 
    778                 result=Var_Parse(cp, VAR_CMD, TRUE, &length, &freeIt);
    779 
    780                 if (freeIt) {
    781                     efree(result);
    782                 }
    783                 cp += length-1;
    784             }
    785             continue;
    786         }
    787         if (*cp == '(') {
     762        for (cp = line;
     763             *cp && !isspace (*cp) &&
     764             (*cp != '!') && (*cp != ':') && (*cp != '(');
     765             cp++)
     766        {
     767            if (*cp == '$') {
     768                /*
     769                * Must be a dynamic source (would have been expanded
     770                * otherwise), so call the Var module to parse the puppy
     771                * so we can safely advance beyond it...There should be
     772                * no errors in this, as they would have been discovered
     773                * in the initial Var_Subst and we wouldn't be here.
     774                */
     775                int     length;
     776                Boolean freeIt;
     777                char    *result;
     778
     779                result=Var_Parse(cp, VAR_CMD, TRUE, &length, &freeIt);
     780
     781                if (freeIt) {
     782                    efree(result);
     783                }
     784                cp += length-1;
     785            }
     786            continue;
     787        }
     788        if (*cp == '(') {
    788789#ifdef USE_ARCHIVES
    789             /*
    790              * Archives must be handled specially to make sure the OP_ARCHV
    791              * flag is set in their 'type' field, for one thing, and because
    792              * things like "archive(file1.o file2.o file3.o)" are permissible.
    793              * Arch_ParseArchive will set 'line' to be the first non-blank
    794              * after the archive-spec. It creates/finds nodes for the members
    795              * and places them on the given list, returning SUCCESS if all
    796              * went well and FAILURE if there was an error in the
    797              * specification. On error, line should remain untouched.
    798              */
    799             if (Arch_ParseArchive (&line, targets, VAR_CMD) != SUCCESS) {
    800                 Parse_Error (PARSE_FATAL,
    801                              "Error in archive specification: \"%s\"", line);
    802                 return;
    803             } else
    804                 continue;
     790            /*
     791             * Archives must be handled specially to make sure the OP_ARCHV
     792             * flag is set in their 'type' field, for one thing, and because
     793             * things like "archive(file1.o file2.o file3.o)" are permissible.
     794             * Arch_ParseArchive will set 'line' to be the first non-blank
     795             * after the archive-spec. It creates/finds nodes for the members
     796             * and places them on the given list, returning SUCCESS if all
     797             * went well and FAILURE if there was an error in the
     798             * specification. On error, line should remain untouched.
     799             */
     800            if (Arch_ParseArchive (&line, targets, VAR_CMD) != SUCCESS) {
     801                Parse_Error (PARSE_FATAL,
     802                             "Error in archive specification: \"%s\"", line);
     803                return;
     804            } else
     805                continue;
    805806#else
    806807            Parse_Error(PARSE_FATAL, "Archives are not supported!", line);
    807808            return;
    808809#endif /* USE_ARCHIVES */
    809         }
    810         savec = *cp;
    811 
    812         if (!*cp) {
    813             /*
    814              * Ending a dependency line without an operator is a Bozo
    815              * no-no
    816              */
    817             Parse_Error (PARSE_FATAL, "Need an operator");
    818             return;
    819         }
    820         *cp = '\0';
    821         /*
    822         * Have a word in line. See if it's a special target and set
    823         * specType to match it.
    824         */
    825         if (*line == '.' && isupper (line[1])) {
    826             /*
    827              * See if the target is a special target that must have it
    828              * or its sources handled specially.
    829              */
    830             int keywd = ParseFindKeyword(line);
    831             if (keywd != -1) {
    832                 if (specType == ExPath && parseKeywords[keywd].spec != ExPath) {
    833                     Parse_Error(PARSE_FATAL, "Mismatched special targets");
    834                     return;
    835                 }
    836 
    837                 specType = parseKeywords[keywd].spec;
    838                 tOp = parseKeywords[keywd].op;
    839 
    840                 /*
    841                 * Certain special targets have special semantics:
    842                  *      .PATH           Have to set the dirSearchPath
    843                  *                      variable too
    844                  *      .MAIN           Its sources are only used if
    845                  *                      nothing has been specified to
    846                  *                      create.
    847                  *      .DEFAULT        Need to create a node to hang
    848                  *                      commands on, but we don't want
    849                  *                      it in the graph, nor do we want
    850                  *                      it to be the Main Target, so we
    851                  *                      create it, set OP_NOTMAIN and
    852                  *                      add it to the list, setting
    853                  *                      DEFAULT to the new node for
    854                  *                      later use. We claim the node is
    855                  *                      A transformation rule to make
    856                  *                      life easier later, when we'll
    857                  *                      use Make_HandleUse to actually
    858                  *                      apply the .DEFAULT commands.
    859                  *      .PHONY          The list of targets
    860                  *      .BEGIN
    861                  *      .END
    862                  *      .INTERRUPT      Are not to be considered the
    863                  *                      main target.
    864                  *      .NOTPARALLEL    Make only one target at a time.
    865                  *      .SINGLESHELL    Create a shell for each command.
    866                  *      .ORDER          Must set initial predecessor to NIL
    867                 */
    868                 switch (specType) {
    869                     case ExPath:
    870                         if (paths == NULL) {
    871                             paths = Lst_Init(FALSE);
    872                         }
    873                         (void)Lst_AtEnd(paths, (ClientData)dirSearchPath);
    874                         break;
    875                     case Main:
    876                         if (!Lst_IsEmpty(create)) {
    877                             specType = Not;
    878                         }
    879                         break;
    880                     case Begin:
    881                     case End:
    882                     case Interrupt:
    883                         gn = Targ_FindNode(line, TARG_CREATE);
    884                         gn->type |= OP_NOTMAIN;
    885                         (void)Lst_AtEnd(targets, (ClientData)gn);
    886                         break;
    887                     case Default:
    888                         gn = Targ_NewGN(".DEFAULT");
    889                         gn->type |= (OP_NOTMAIN|OP_TRANSFORM);
    890                         (void)Lst_AtEnd(targets, (ClientData)gn);
    891                         DEFAULT = gn;
    892                         break;
    893                     case NotParallel:
    894                     {
    895                         extern int  maxJobs;
    896 
    897                         maxJobs = 1;
    898                         break;
    899                     }
    900                     case SingleShell:
    901                         compatMake = 1;
    902                         break;
    903                     case Order:
    904                         predecessor = NILGNODE;
    905                         break;
    906                     default:
    907                         break;
    908                 }
    909             } else if (strncmp (line, ".PATH", 5) == 0) {
    910                 /*
    911                 * .PATH<suffix> has to be handled specially.
    912                 * Call on the suffix module to give us a path to
    913                 * modify.
    914                 */
    915                 Lst     path;
    916 
    917                 specType = ExPath;
    918                 path = Suff_GetPath (&line[5]);
    919                 if (path == NILLST) {
    920                     Parse_Error (PARSE_FATAL,
    921                                 "Suffix '%s' not defined (yet)",
    922                                 &line[5]);
    923                     return;
    924                 } else {
    925                     if (paths == (Lst)NULL) {
    926                         paths = Lst_Init(FALSE);
    927                     }
    928                     (void)Lst_AtEnd(paths, (ClientData)path);
    929                 }
    930             }
    931         }
    932 
    933         /*
    934         * Have word in line. Get or create its node and stick it at
    935         * the end of the targets list
    936         */
    937         if ((specType == Not) && (*line != '\0')) {
    938             if (Dir_HasWildcards(line)) {
    939                 /*
    940                 * Targets are to be sought only in the current directory,
    941                 * so create an empty path for the thing. Note we need to
    942                 * use Dir_Destroy in the destruction of the path as the
    943                 * Dir module could have added a directory to the path...
    944                 */
    945                 Lst         emptyPath = Lst_Init(FALSE);
    946 
    947                 Dir_Expand(line, emptyPath, curTargs);
    948 
    949                 Lst_Destroy(emptyPath, Dir_Destroy);
    950             } else {
    951                 /*
    952                 * No wildcards, but we want to avoid code duplication,
    953                 * so create a list with the word on it.
    954                 */
    955                 (void)Lst_AtEnd(curTargs, (ClientData)line);
    956             }
    957 
    958             while(!Lst_IsEmpty(curTargs)) {
    959                 char    *targName = (char *)Lst_DeQueue(curTargs);
    960 
    961                 if (!Suff_IsTransform (targName)) {
    962                     gn = Targ_FindNode (targName, TARG_CREATE);
    963                 } else {
    964                     gn = Suff_AddTransform (targName);
    965                 }
    966 
    967                 (void)Lst_AtEnd (targets, (ClientData)gn);
    968             }
    969         } else if (specType == ExPath && *line != '.' && *line != '\0') {
    970             Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line);
    971         }
    972 
    973         *cp = savec;
    974         /*
    975         * If it is a special type and not .PATH, it's the only target we
    976         * allow on this line...
    977         */
    978         if (specType != Not && specType != ExPath) {
    979             Boolean warn = FALSE;
    980 
    981             while ((*cp != '!') && (*cp != ':') && *cp) {
    982                 if (*cp != ' ' && *cp != '\t') {
    983                     warn = TRUE;
    984                 }
    985                 cp++;
    986             }
    987             if (warn) {
    988                 Parse_Error(PARSE_WARNING, "Extra target ignored");
    989             }
    990         } else {
    991             while (*cp && isspace (*cp)) {
    992                 cp++;
    993             }
    994         }
    995         line = cp;
     810        }
     811        savec = *cp;
     812
     813        if (!*cp) {
     814            /*
     815             * Ending a dependency line without an operator is a Bozo
     816             * no-no
     817             */
     818            Parse_Error (PARSE_FATAL, "Need an operator");
     819            return;
     820        }
     821        *cp = '\0';
     822        /*
     823        * Have a word in line. See if it's a special target and set
     824        * specType to match it.
     825        */
     826        if (*line == '.' && isupper (line[1])) {
     827            /*
     828             * See if the target is a special target that must have it
     829             * or its sources handled specially.
     830             */
     831            int keywd = ParseFindKeyword(line);
     832            if (keywd != -1) {
     833                if (specType == ExPath && parseKeywords[keywd].spec != ExPath) {
     834                    Parse_Error(PARSE_FATAL, "Mismatched special targets");
     835                    return;
     836                }
     837
     838                specType = parseKeywords[keywd].spec;
     839                tOp = parseKeywords[keywd].op;
     840
     841                /*
     842                * Certain special targets have special semantics:
     843                 *      .PATH           Have to set the dirSearchPath
     844                 *                      variable too
     845                 *      .MAIN           Its sources are only used if
     846                 *                      nothing has been specified to
     847                 *                      create.
     848                 *      .DEFAULT        Need to create a node to hang
     849                 *                      commands on, but we don't want
     850                 *                      it in the graph, nor do we want
     851                 *                      it to be the Main Target, so we
     852                 *                      create it, set OP_NOTMAIN and
     853                 *                      add it to the list, setting
     854                 *                      DEFAULT to the new node for
     855                 *                      later use. We claim the node is
     856                 *                      A transformation rule to make
     857                 *                      life easier later, when we'll
     858                 *                      use Make_HandleUse to actually
     859                 *                      apply the .DEFAULT commands.
     860                 *      .PHONY          The list of targets
     861                 *      .BEGIN
     862                 *      .END
     863                 *      .INTERRUPT      Are not to be considered the
     864                 *                      main target.
     865                 *      .NOTPARALLEL    Make only one target at a time.
     866                 *      .SINGLESHELL    Create a shell for each command.
     867                 *      .ORDER          Must set initial predecessor to NIL
     868                */
     869                switch (specType) {
     870                    case ExPath:
     871                        if (paths == NULL) {
     872                            paths = Lst_Init(FALSE);
     873                        }
     874                        (void)Lst_AtEnd(paths, (ClientData)dirSearchPath);
     875                        break;
     876                    case Main:
     877                        if (!Lst_IsEmpty(create)) {
     878                            specType = Not;
     879                        }
     880                        break;
     881                    case Begin:
     882                    case End:
     883                    case Interrupt:
     884                        gn = Targ_FindNode(line, TARG_CREATE);
     885                        gn->type |= OP_NOTMAIN;
     886                        (void)Lst_AtEnd(targets, (ClientData)gn);
     887                        break;
     888                    case Default:
     889                        gn = Targ_NewGN(".DEFAULT");
     890                        gn->type |= (OP_NOTMAIN|OP_TRANSFORM);
     891                        (void)Lst_AtEnd(targets, (ClientData)gn);
     892                        DEFAULT = gn;
     893                        break;
     894                    case NotParallel:
     895                    {
     896                        extern int  maxJobs;
     897
     898                        maxJobs = 1;
     899                        break;
     900                    }
     901                    case SingleShell:
     902                        compatMake = 1;
     903                        break;
     904                    case Order:
     905                        predecessor = NILGNODE;
     906                        break;
     907                    default:
     908                        break;
     909                }
     910            } else if (strncmp (line, ".PATH", 5) == 0) {
     911                /*
     912                * .PATH<suffix> has to be handled specially.
     913                * Call on the suffix module to give us a path to
     914                * modify.
     915                */
     916                Lst     path;
     917
     918                specType = ExPath;
     919                path = Suff_GetPath (&line[5]);
     920                if (path == NILLST) {
     921                    Parse_Error (PARSE_FATAL,
     922                                "Suffix '%s' not defined (yet)",
     923                                &line[5]);
     924                    return;
     925                } else {
     926                    if (paths == (Lst)NULL) {
     927                        paths = Lst_Init(FALSE);
     928                    }
     929                    (void)Lst_AtEnd(paths, (ClientData)path);
     930                }
     931            }
     932        }
     933
     934        /*
     935        * Have word in line. Get or create its node and stick it at
     936        * the end of the targets list
     937        */
     938        if ((specType == Not) && (*line != '\0')) {
     939            if (Dir_HasWildcards(line)) {
     940                /*
     941                * Targets are to be sought only in the current directory,
     942                * so create an empty path for the thing. Note we need to
     943                * use Dir_Destroy in the destruction of the path as the
     944                * Dir module could have added a directory to the path...
     945                */
     946                Lst         emptyPath = Lst_Init(FALSE);
     947
     948                Dir_Expand(line, emptyPath, curTargs);
     949
     950                Lst_Destroy(emptyPath, Dir_Destroy);
     951            } else {
     952                /*
     953                * No wildcards, but we want to avoid code duplication,
     954                * so create a list with the word on it.
     955                */
     956                (void)Lst_AtEnd(curTargs, (ClientData)line);
     957            }
     958
     959            while(!Lst_IsEmpty(curTargs)) {
     960                char    *targName = (char *)Lst_DeQueue(curTargs);
     961
     962                if (!Suff_IsTransform (targName)) {
     963                    gn = Targ_FindNode (targName, TARG_CREATE);
     964                } else {
     965                    gn = Suff_AddTransform (targName);
     966                }
     967
     968                (void)Lst_AtEnd (targets, (ClientData)gn);
     969            }
     970        } else if (specType == ExPath && *line != '.' && *line != '\0') {
     971            Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line);
     972        }
     973
     974        *cp = savec;
     975        /*
     976        * If it is a special type and not .PATH, it's the only target we
     977        * allow on this line...
     978        */
     979        if (specType != Not && specType != ExPath) {
     980            Boolean warn = FALSE;
     981
     982            while ((*cp != '!') && (*cp != ':') && *cp) {
     983                if (*cp != ' ' && *cp != '\t') {
     984                    warn = TRUE;
     985                }
     986                cp++;
     987            }
     988            if (warn) {
     989                Parse_Error(PARSE_WARNING, "Extra target ignored");
     990            }
     991        } else {
     992            while (*cp && isspace (*cp)) {
     993                cp++;
     994            }
     995        }
     996        line = cp;
    996997    } while ((*line != '!') && (*line != ':') && *line);
    997998
     
    10021003
    10031004    if (!Lst_IsEmpty(targets)) {
    1004         switch(specType) {
    1005             default:
    1006                 Parse_Error(PARSE_WARNING, "Special and mundane targets don't mix. Mundane ones ignored");
    1007                 break;
    1008             case Default:
    1009             case Begin:
    1010             case End:
    1011             case Interrupt:
    1012                 /*
    1013                 * These four create nodes on which to hang commands, so
    1014                 * targets shouldn't be empty...
    1015                 */
    1016             case Not:
    1017                 /*
    1018                 * Nothing special here -- targets can be empty if it wants.
    1019                 */
    1020                 break;
    1021         }
     1005        switch(specType) {
     1006            default:
     1007                Parse_Error(PARSE_WARNING, "Special and mundane targets don't mix. Mundane ones ignored");
     1008                break;
     1009            case Default:
     1010            case Begin:
     1011            case End:
     1012            case Interrupt:
     1013                /*
     1014                * These four create nodes on which to hang commands, so
     1015                * targets shouldn't be empty...
     1016                */
     1017            case Not:
     1018                /*
     1019                * Nothing special here -- targets can be empty if it wants.
     1020                */
     1021                break;
     1022        }
    10221023    }
    10231024
     
    10271028     */
    10281029    if (*cp == '!') {
    1029         op = OP_FORCE;
     1030        op = OP_FORCE;
    10301031    } else if (*cp == ':') {
    1031         if (cp[1] == ':') {
    1032             op = OP_DOUBLEDEP;
    1033             cp++;
    1034         } else {
    1035             op = OP_DEPENDS;
    1036         }
     1032        if (cp[1] == ':') {
     1033            op = OP_DOUBLEDEP;
     1034            cp++;
     1035        } else {
     1036            op = OP_DEPENDS;
     1037        }
    10371038    } else {
    1038         Parse_Error (PARSE_FATAL, "Missing dependency operator");
    1039         return;
    1040     }
    1041 
    1042     cp++;                       /* Advance beyond operator */
     1039        Parse_Error (PARSE_FATAL, "Missing dependency operator");
     1040        return;
     1041    }
     1042
     1043    cp++;                       /* Advance beyond operator */
    10431044
    10441045    Lst_ForEach (targets, ParseDoOp, (ClientData)&op);
     
    10481049     */
    10491050    while (*cp && isspace (*cp)) {
    1050         cp++;
     1051        cp++;
    10511052    }
    10521053    line = cp;
     
    10551056     * Several special targets take different actions if present with no
    10561057     * sources:
    1057      *  a .SUFFIXES line with no sources clears out all old suffixes
    1058      *  a .PRECIOUS line makes all targets precious
    1059      *  a .IGNORE line ignores errors for all targets
    1060      *  a .SILENT line creates silence when making all targets
    1061      *  a .PATH removes all directories from the search path(s).
     1058     *  a .SUFFIXES line with no sources clears out all old suffixes
     1059     *  a .PRECIOUS line makes all targets precious
     1060     *  a .IGNORE line ignores errors for all targets
     1061     *  a .SILENT line creates silence when making all targets
     1062     *  a .PATH removes all directories from the search path(s).
    10621063     */
    10631064    if (!*line) {
    1064         switch (specType) {
    1065             case Suffixes:
    1066                 Suff_ClearSuffixes ();
    1067                 break;
    1068             case Precious:
    1069                 allPrecious = TRUE;
    1070                 break;
    1071             case Ignore:
    1072                 ignoreErrors = TRUE;
    1073                 break;
    1074             case Silent:
    1075                 beSilent = TRUE;
    1076                 break;
    1077             case ExPath:
    1078                 Lst_ForEach(paths, ParseClearPath, (ClientData)NULL);
    1079                 break;
     1065        switch (specType) {
     1066            case Suffixes:
     1067                Suff_ClearSuffixes ();
     1068                break;
     1069            case Precious:
     1070                allPrecious = TRUE;
     1071                break;
     1072            case Ignore:
     1073                ignoreErrors = TRUE;
     1074                break;
     1075            case Silent:
     1076                beSilent = TRUE;
     1077                break;
     1078            case ExPath:
     1079                Lst_ForEach(paths, ParseClearPath, (ClientData)NULL);
     1080                break;
    10801081#ifdef POSIX
    1081             case Posix:
    1082                 Var_Set("%POSIX", "1003.2", VAR_GLOBAL);
    1083                 break;
    1084 #endif
    1085             default:
    1086                 break;
    1087         }
     1082            case Posix:
     1083                Var_Set("%POSIX", "1003.2", VAR_GLOBAL);
     1084                break;
     1085#endif
     1086            default:
     1087                break;
     1088        }
    10881089    } else if (specType == MFlags) {
    1089         /*
    1090         * Call on functions in main.c to deal with these arguments and
    1091         * set the initial character to a null-character so the loop to
    1092         * get sources won't get anything
    1093         */
    1094         Main_ParseArgLine (line);
    1095         *line = '\0';
     1090        /*
     1091        * Call on functions in main.c to deal with these arguments and
     1092        * set the initial character to a null-character so the loop to
     1093        * get sources won't get anything
     1094        */
     1095        Main_ParseArgLine (line);
     1096        *line = '\0';
    10961097    } else if (specType == ExShell) {
    10971098    #ifdef KMK
     
    10991100        return;
    11001101    #else
    1101         if (Job_ParseShell (line) != SUCCESS) {
    1102             Parse_Error (PARSE_FATAL, "improper shell specification");
    1103             return;
    1104         }
     1102        if (Job_ParseShell (line) != SUCCESS) {
     1103            Parse_Error (PARSE_FATAL, "improper shell specification");
     1104            return;
     1105        }
    11051106    #endif
    1106         *line = '\0';
     1107        *line = '\0';
    11071108    } else if ((specType == NotParallel) || (specType == SingleShell)) {
    1108         *line = '\0';
     1109        *line = '\0';
    11091110    }
    11101111
     
    11131114     */
    11141115    if ((specType == Suffixes) || (specType == ExPath) ||
    1115         (specType == Includes) ||
     1116        (specType == Includes) ||
    11161117#ifdef USE_ARCHIVES
    11171118        (specType == Libs) ||
    11181119#endif
    1119         (specType == Null))
     1120        (specType == Null))
    11201121    {
    1121         while (*line) {
    1122             /*
    1123              * If the target was one that doesn't take files as its sources
    1124              * but takes something like suffixes, we take each
    1125              * space-separated word on the line as a something and deal
    1126              * with it accordingly.
    1127              *
    1128              * If the target was .SUFFIXES, we take each source as a
    1129              * suffix and add it to the list of suffixes maintained by the
    1130              * Suff module.
    1131              *
    1132              * If the target was a .PATH, we add the source as a directory
    1133              * to search on the search path.
    1134              *
    1135              * If it was .INCLUDES, the source is taken to be the suffix of
    1136              * files which will be #included and whose search path should
    1137              * be present in the .INCLUDES variable.
    1138              *
    1139              * If it was .LIBS, the source is taken to be the suffix of
    1140              * files which are considered libraries and whose search path
    1141              * should be present in the .LIBS variable.
    1142              *
    1143              * If it was .NULL, the source is the suffix to use when a file
    1144              * has no valid suffix.
    1145              */
    1146             char  savec;
    1147             while (*cp && !isspace (*cp)) {
    1148                 cp++;
    1149             }
    1150             savec = *cp;
    1151             *cp = '\0';
    1152             switch (specType) {
    1153                 case Suffixes:
    1154                     Suff_AddSuffix (line);
    1155                     break;
    1156                 case ExPath:
    1157                     Lst_ForEach(paths, ParseAddDir, (ClientData)line);
    1158                     break;
    1159                 case Includes:
    1160                     Suff_AddInclude (line);
    1161                     break;
     1122        while (*line) {
     1123            /*
     1124             * If the target was one that doesn't take files as its sources
     1125             * but takes something like suffixes, we take each
     1126             * space-separated word on the line as a something and deal
     1127             * with it accordingly.
     1128             *
     1129             * If the target was .SUFFIXES, we take each source as a
     1130             * suffix and add it to the list of suffixes maintained by the
     1131             * Suff module.
     1132             *
     1133             * If the target was a .PATH, we add the source as a directory
     1134             * to search on the search path.
     1135             *
     1136             * If it was .INCLUDES, the source is taken to be the suffix of
     1137             * files which will be #included and whose search path should
     1138             * be present in the .INCLUDES variable.
     1139             *
     1140             * If it was .LIBS, the source is taken to be the suffix of
     1141             * files which are considered libraries and whose search path
     1142             * should be present in the .LIBS variable.
     1143             *
     1144             * If it was .NULL, the source is the suffix to use when a file
     1145             * has no valid suffix.
     1146             */
     1147            char  savec;
     1148            while (*cp && !isspace (*cp)) {
     1149                cp++;
     1150            }
     1151            savec = *cp;
     1152            *cp = '\0';
     1153            switch (specType) {
     1154                case Suffixes:
     1155                    Suff_AddSuffix (line);
     1156                    break;
     1157                case ExPath:
     1158                    Lst_ForEach(paths, ParseAddDir, (ClientData)line);
     1159                    break;
     1160                case Includes:
     1161                    Suff_AddInclude (line);
     1162                    break;
    11621163#ifdef USE_ARCHIVES
    1163                 case Libs:
    1164                     Suff_AddLib (line);
    1165                     break;
    1166 #endif
    1167                 case Null:
    1168                     Suff_SetNull (line);
    1169                     break;
    1170                 default:
    1171                     break;
    1172             }
    1173             *cp = savec;
    1174             if (savec != '\0') {
    1175                 cp++;
    1176             }
    1177             while (*cp && isspace (*cp)) {
    1178                 cp++;
    1179             }
    1180             line = cp;
    1181         }
    1182         if (paths) {
    1183             Lst_Destroy(paths, NOFREE);
    1184         }
     1164                case Libs:
     1165                    Suff_AddLib (line);
     1166                    break;
     1167#endif
     1168                case Null:
     1169                    Suff_SetNull (line);
     1170                    break;
     1171                default:
     1172                    break;
     1173            }
     1174            *cp = savec;
     1175            if (savec != '\0') {
     1176                cp++;
     1177            }
     1178            while (*cp && isspace (*cp)) {
     1179                cp++;
     1180            }
     1181            line = cp;
     1182        }
     1183        if (paths) {
     1184            Lst_Destroy(paths, NOFREE);
     1185        }
    11851186    } else {
    1186         while (*line) {
    1187             /*
    1188              * The targets take real sources, so we must beware of archive
    1189              * specifications (i.e. things with left parentheses in them)
    1190              * and handle them accordingly.
    1191              */
    1192             while (*cp && !isspace (*cp)) {
    1193                 if ((*cp == '(') && (cp > line) && (cp[-1] != '$')) {
    1194                     /*
    1195                      * Only stop for a left parenthesis if it isn't at the
    1196                      * start of a word (that'll be for variable changes
    1197                      * later) and isn't preceded by a dollar sign (a dynamic
    1198                      * source).
    1199                      */
    1200                     break;
    1201                 } else {
    1202                     cp++;
    1203                 }
    1204             }
    1205 
    1206             if (*cp == '(') {
     1187        while (*line) {
     1188            /*
     1189             * The targets take real sources, so we must beware of archive
     1190             * specifications (i.e. things with left parentheses in them)
     1191             * and handle them accordingly.
     1192             */
     1193            while (*cp && !isspace (*cp)) {
     1194                if ((*cp == '(') && (cp > line) && (cp[-1] != '$')) {
     1195                    /*
     1196                     * Only stop for a left parenthesis if it isn't at the
     1197                     * start of a word (that'll be for variable changes
     1198                     * later) and isn't preceded by a dollar sign (a dynamic
     1199                     * source).
     1200                     */
     1201                    break;
     1202                } else {
     1203                    cp++;
     1204                }
     1205            }
     1206
     1207            if (*cp == '(') {
    12071208#ifdef USE_ARCHIVES
    1208                 GNode     *gn;
    1209 
    1210                 sources = Lst_Init (FALSE);
    1211                 if (Arch_ParseArchive (&line, sources, VAR_CMD) != SUCCESS) {
    1212                     Parse_Error (PARSE_FATAL,
    1213                                 "Error in source archive spec \"%s\"", line);
    1214                     return;
    1215                 }
    1216 
    1217                 while (!Lst_IsEmpty (sources)) {
    1218                     gn = (GNode *) Lst_DeQueue (sources);
    1219                     ParseDoSrc (tOp, gn->name, curSrcs);
    1220                 }
    1221                 Lst_Destroy (sources, NOFREE);
    1222                 cp = line;
     1209                GNode     *gn;
     1210
     1211                sources = Lst_Init (FALSE);
     1212                if (Arch_ParseArchive (&line, sources, VAR_CMD) != SUCCESS) {
     1213                    Parse_Error (PARSE_FATAL,
     1214                                "Error in source archive spec \"%s\"", line);
     1215                    return;
     1216                }
     1217
     1218                while (!Lst_IsEmpty (sources)) {
     1219                    gn = (GNode *) Lst_DeQueue (sources);
     1220                    ParseDoSrc (tOp, gn->name, curSrcs);
     1221                }
     1222                Lst_Destroy (sources, NOFREE);
     1223                cp = line;
    12231224#else
    12241225                Parse_Error(PARSE_FATAL, "Archives are not supported!", line);
    12251226                return;
    12261227#endif /* USE_ARCHIVES */
    1227             } else {
    1228                 if (*cp) {
    1229                     *cp = '\0';
    1230                     cp += 1;
    1231                 }
    1232 
    1233                 ParseDoSrc (tOp, line, curSrcs);
    1234             }
    1235             while (*cp && isspace (*cp)) {
    1236                 cp++;
    1237             }
    1238             line = cp;
    1239         }
     1228            } else {
     1229                if (*cp) {
     1230                    *cp = '\0';
     1231                    cp += 1;
     1232                }
     1233
     1234                ParseDoSrc (tOp, line, curSrcs);
     1235            }
     1236            while (*cp && isspace (*cp)) {
     1237                cp++;
     1238            }
     1239            line = cp;
     1240        }
    12401241    }
    12411242
    12421243    if (mainNode == NILGNODE) {
    1243         /*
    1244         * If we have yet to decide on a main target to make, in the
    1245         * absence of any user input, we want the first target on
    1246         * the first dependency line that is actually a real target
    1247         * (i.e. isn't a .USE or .EXEC rule) to be made.
    1248         */
    1249         Lst_ForEach (targets, ParseFindMain, (ClientData)0);
     1244        /*
     1245        * If we have yet to decide on a main target to make, in the
     1246        * absence of any user input, we want the first target on
     1247        * the first dependency line that is actually a real target
     1248        * (i.e. isn't a .USE or .EXEC rule) to be made.
     1249        */
     1250        Lst_ForEach (targets, ParseFindMain, (ClientData)0);
    12501251    }
    12511252
     
    12591260 *---------------------------------------------------------------------
    12601261 * Parse_IsVar  --
    1261  *      Return TRUE if the passed line is a variable assignment. A variable
    1262  *      assignment consists of a single word followed by optional whitespace
    1263  *      followed by either a += or an = operator.
    1264  *      This function is used both by the Parse_File function and main when
    1265  *      parsing the command-line arguments.
     1262 *      Return TRUE if the passed line is a variable assignment. A variable
     1263 *      assignment consists of a single word followed by optional whitespace
     1264 *      followed by either a += or an = operator.
     1265 *      This function is used both by the Parse_File function and main when
     1266 *      parsing the command-line arguments.
    12661267 *
    12671268 * Results:
    1268  *      TRUE if it is. FALSE if it ain't
     1269 *      TRUE if it is. FALSE if it ain't
    12691270 *
    12701271 * Side Effects:
    1271  *      none
     1272 *      none
    12721273 *---------------------------------------------------------------------
    12731274 */
    12741275Boolean
    12751276Parse_IsVar (line)
    1276     register char  *line;       /* the line to check */
    1277 {
    1278     register Boolean wasSpace = FALSE;  /* set TRUE if found a space */
    1279     register Boolean haveName = FALSE;  /* Set TRUE if have a variable name */
     1277    register char  *line;       /* the line to check */
     1278{
     1279    register Boolean wasSpace = FALSE;  /* set TRUE if found a space */
     1280    register Boolean haveName = FALSE;  /* Set TRUE if have a variable name */
    12801281    int level = 0;
    12811282#define ISEQOPERATOR(c) \
    1282         (((c) == '+') || ((c) == ':') || ((c) == '?') || ((c) == '!'))
     1283        (((c) == '+') || ((c) == ':') || ((c) == '?') || ((c) == '!'))
    12831284
    12841285    /*
     
    12861287     */
    12871288    for (;(*line == ' ') || (*line == '\t'); line++)
    1288         continue;
     1289        continue;
    12891290
    12901291    for (; *line != '=' || level != 0; line++)
    1291         switch (*line) {
    1292         case '\0':
    1293             /*
    1294              * end-of-line -- can't be a variable assignment.
    1295              */
    1296             return FALSE;
    1297 
    1298         case ' ':
    1299         case '\t':
    1300             /*
    1301              * there can be as much white space as desired so long as there is
    1302              * only one word before the operator
    1303              */
    1304             wasSpace = TRUE;
    1305             break;
    1306 
    1307         case '(':
    1308         case '{':
    1309             level++;
    1310             break;
    1311 
    1312         case '}':
    1313         case ')':
    1314             level--;
    1315             break;
    1316 
    1317         default:
    1318             if (wasSpace && haveName) {
    1319                     if (ISEQOPERATOR(*line)) {
    1320                         /*
    1321                         * We must have a finished word
    1322                         */
    1323                         if (level != 0)
    1324                             return FALSE;
    1325 
    1326                         /*
    1327                         * When an = operator [+?!:] is found, the next
    1328                         * character must be an = or it ain't a valid
    1329                         * assignment.
    1330                         */
    1331                         if (line[1] == '=')
    1332                             return haveName;
     1292        switch (*line) {
     1293        case '\0':
     1294            /*
     1295             * end-of-line -- can't be a variable assignment.
     1296             */
     1297            return FALSE;
     1298
     1299        case ' ':
     1300        case '\t':
     1301            /*
     1302             * there can be as much white space as desired so long as there is
     1303             * only one word before the operator
     1304             */
     1305            wasSpace = TRUE;
     1306            break;
     1307
     1308        case '(':
     1309        case '{':
     1310            level++;
     1311            break;
     1312
     1313        case '}':
     1314        case ')':
     1315            level--;
     1316            break;
     1317
     1318        default:
     1319            if (wasSpace && haveName) {
     1320                    if (ISEQOPERATOR(*line)) {
     1321                        /*
     1322                        * We must have a finished word
     1323                        */
     1324                        if (level != 0)
     1325                            return FALSE;
     1326
     1327                        /*
     1328                        * When an = operator [+?!:] is found, the next
     1329                        * character must be an = or it ain't a valid
     1330                        * assignment.
     1331                        */
     1332                        if (line[1] == '=')
     1333                            return haveName;
    13331334#ifdef SUNSHCMD
    1334                         /*
    1335                         * This is a shell command
    1336                         */
    1337                         if (strncmp(line, ":sh", 3) == 0)
    1338                             return haveName;
    1339 #endif
    1340                     }
    1341                     /*
    1342                      * This is the start of another word, so not assignment.
    1343                      */
    1344                     return FALSE;
    1345             }
    1346             else {
    1347                 haveName = TRUE;
    1348                 wasSpace = FALSE;
    1349             }
    1350             break;
    1351         }
     1335                        /*
     1336                        * This is a shell command
     1337                        */
     1338                        if (strncmp(line, ":sh", 3) == 0)
     1339                            return haveName;
     1340#endif
     1341                    }
     1342                    /*
     1343                     * This is the start of another word, so not assignment.
     1344                     */
     1345                    return FALSE;
     1346            }
     1347            else {
     1348                haveName = TRUE;
     1349                wasSpace = FALSE;
     1350            }
     1351            break;
     1352        }
    13521353
    13531354    return haveName;
     
    13571358 *---------------------------------------------------------------------
    13581359 * Parse_DoVar  --
    1359  *      Take the variable assignment in the passed line and do it in the
    1360  *      global context.
    1361  *
    1362  *      Note: There is a lexical ambiguity with assignment modifier characters
    1363  *      in variable names. This routine interprets the character before the =
    1364  *      as a modifier. Therefore, an assignment like
    1365  *          C++=/usr/bin/CC
    1366  *      is interpreted as "C+ +=" instead of "C++ =".
     1360 *      Take the variable assignment in the passed line and do it in the
     1361 *      global context.
     1362 *
     1363 *      Note: There is a lexical ambiguity with assignment modifier characters
     1364 *      in variable names. This routine interprets the character before the =
     1365 *      as a modifier. Therefore, an assignment like
     1366 *          C++=/usr/bin/CC
     1367 *      is interpreted as "C+ +=" instead of "C++ =".
    13671368 *
    13681369 * Results:
    1369  *      none
     1370 *      none
    13701371 *
    13711372 * Side Effects:
    1372  *      the variable structure of the given variable name is altered in the
    1373  *      global context.
     1373 *      the variable structure of the given variable name is altered in the
     1374 *      global context.
    13741375 *---------------------------------------------------------------------
    13751376 */
    13761377void
    13771378Parse_DoVar (line, ctxt)
    1378     char            *line;      /* a line guaranteed to be a variable
    1379                                 * assignment. This reduces error checks */
    1380     GNode           *ctxt;      /* Context in which to do the assignment */
    1381 {
    1382     char           *cp; /* pointer into line */
     1379    char            *line;      /* a line guaranteed to be a variable
     1380                                * assignment. This reduces error checks */
     1381    GNode           *ctxt;      /* Context in which to do the assignment */
     1382{
     1383    char           *cp; /* pointer into line */
    13831384    enum {
    1384         VAR_SUBST, VAR_APPEND, VAR_SHELL, VAR_NORMAL
    1385     }               type;       /* Type of assignment */
    1386     char            *opc;       /* ptr to operator character to
    1387                                 * null-terminate the variable name */
     1385        VAR_SUBST, VAR_APPEND, VAR_SHELL, VAR_NORMAL
     1386    }               type;       /* Type of assignment */
     1387    char            *opc;       /* ptr to operator character to
     1388                                * null-terminate the variable name */
    13881389    /*
    13891390     * Avoid clobbered variable warnings by forcing the compiler
     
    13991400     */
    14001401    while ((*line == ' ') || (*line == '\t')) {
    1401         line++;
     1402        line++;
    14021403    }
    14031404
     
    14061407     */
    14071408    for (cp = line + 1; *cp != '='; cp++) {
    1408         if (isspace (*cp)) {
    1409             *cp = '\0';
    1410         }
    1411     }
    1412     opc = cp-1;         /* operator is the previous character */
    1413     *cp++ = '\0';       /* nuke the = */
     1409        if (isspace (*cp)) {
     1410            *cp = '\0';
     1411        }
     1412    }
     1413    opc = cp-1;         /* operator is the previous character */
     1414    *cp++ = '\0';       /* nuke the = */
    14141415
    14151416    /*
     
    14171418     */
    14181419    switch (*opc) {
    1419         case '+':
    1420             type = VAR_APPEND;
    1421             *opc = '\0';
    1422             break;
    1423 
    1424         case '?':
    1425             /*
    1426              * If the variable already has a value, we don't do anything.
    1427              */
    1428             *opc = '\0';
    1429             if (Var_Exists(line, ctxt)) {
    1430                 return;
    1431             } else {
    1432                 type = VAR_NORMAL;
    1433             }
    1434             break;
    1435 
    1436         case ':':
    1437             type = VAR_SUBST;
    1438             *opc = '\0';
    1439             break;
    1440 
    1441         case '!':
    1442             type = VAR_SHELL;
    1443             *opc = '\0';
    1444             break;
    1445 
    1446         default:
     1420        case '+':
     1421            type = VAR_APPEND;
     1422            *opc = '\0';
     1423            break;
     1424
     1425        case '?':
     1426            /*
     1427             * If the variable already has a value, we don't do anything.
     1428             */
     1429            *opc = '\0';
     1430            if (Var_Exists(line, ctxt)) {
     1431                return;
     1432            } else {
     1433                type = VAR_NORMAL;
     1434            }
     1435            break;
     1436
     1437        case ':':
     1438            type = VAR_SUBST;
     1439            *opc = '\0';
     1440            break;
     1441
     1442        case '!':
     1443            type = VAR_SHELL;
     1444            *opc = '\0';
     1445            break;
     1446
     1447        default:
    14471448#ifdef SUNSHCMD
    1448             while (*opc != ':')
    1449                 if (opc == line)
    1450                     break;
    1451                 else
    1452                     --opc;
    1453 
    1454             if (strncmp(opc, ":sh", 3) == 0) {
    1455                 type = VAR_SHELL;
    1456                 *opc = '\0';
    1457                 break;
    1458             }
    1459 #endif
    1460             type = VAR_NORMAL;
    1461             break;
     1449            while (*opc != ':')
     1450                if (opc == line)
     1451                    break;
     1452                else
     1453                    --opc;
     1454
     1455            if (strncmp(opc, ":sh", 3) == 0) {
     1456                type = VAR_SHELL;
     1457                *opc = '\0';
     1458                break;
     1459            }
     1460#endif
     1461            type = VAR_NORMAL;
     1462            break;
    14621463    }
    14631464
    14641465    while (isspace (*cp)) {
    1465         cp++;
     1466        cp++;
    14661467    }
    14671468
    14681469    if (type == VAR_APPEND) {
    1469         Var_Append (line, cp, ctxt);
     1470        Var_Append (line, cp, ctxt);
    14701471    } else if (type == VAR_SUBST) {
    1471         /*
    1472         * Allow variables in the old value to be undefined, but leave their
    1473         * invocation alone -- this is done by forcing oldVars to be false.
    1474         * XXX: This can cause recursive variables, but that's not hard to do,
    1475         * and this allows someone to do something like
    1476         *
    1477         *  CFLAGS = $(.INCLUDES)
    1478         *  CFLAGS := -I.. $(CFLAGS)
    1479         *
    1480         * And not get an error.
    1481         */
    1482         Boolean   oldOldVars = oldVars;
    1483 
    1484         oldVars = FALSE;
    1485         cp = Var_Subst(NULL, cp, ctxt, FALSE);
    1486         oldVars = oldOldVars;
    1487 
    1488         Var_Set(line, cp, ctxt);
    1489         efree(cp);
     1472        /*
     1473        * Allow variables in the old value to be undefined, but leave their
     1474        * invocation alone -- this is done by forcing oldVars to be false.
     1475        * XXX: This can cause recursive variables, but that's not hard to do,
     1476        * and this allows someone to do something like
     1477        *
     1478        *  CFLAGS = $(.INCLUDES)
     1479        *  CFLAGS := -I.. $(CFLAGS)
     1480        *
     1481        * And not get an error.
     1482        */
     1483        Boolean   oldOldVars = oldVars;
     1484
     1485        oldVars = FALSE;
     1486        cp = Var_Subst(NULL, cp, ctxt, FALSE);
     1487        oldVars = oldOldVars;
     1488
     1489        Var_Set(line, cp, ctxt);
     1490        efree(cp);
    14901491    } else if (type == VAR_SHELL) {
    1491         Boolean freeCmd = FALSE; /* TRUE if the command needs to be freed, i.e.
    1492                                   * if any variable expansion was performed */
    1493         char *res, *err;
    1494 
    1495         if (strchr(cp, '$') != NULL) {
    1496             /*
    1497              * There's a dollar sign in the command, so perform variable
    1498              * expansion on the whole thing. The resulting string will need
    1499              * freeing when we're done, so set freeCmd to TRUE.
    1500              */
    1501             cp = Var_Subst(NULL, cp, VAR_CMD, TRUE);
    1502             freeCmd = TRUE;
    1503         }
    1504 
    1505         res = Cmd_Exec(cp, &err);
    1506         Var_Set(line, res, ctxt);
    1507         efree(res);
    1508 
    1509         if (err)
    1510             Parse_Error(PARSE_WARNING, err, cp);
    1511 
    1512         if (freeCmd)
    1513             efree(cp);
     1492        Boolean freeCmd = FALSE; /* TRUE if the command needs to be freed, i.e.
     1493                                  * if any variable expansion was performed */
     1494        char *res, *err;
     1495
     1496        if (strchr(cp, '$') != NULL) {
     1497            /*
     1498             * There's a dollar sign in the command, so perform variable
     1499             * expansion on the whole thing. The resulting string will need
     1500             * freeing when we're done, so set freeCmd to TRUE.
     1501             */
     1502            cp = Var_Subst(NULL, cp, VAR_CMD, TRUE);
     1503            freeCmd = TRUE;
     1504        }
     1505
     1506        res = Cmd_Exec(cp, &err);
     1507        Var_Set(line, res, ctxt);
     1508        efree(res);
     1509
     1510        if (err)
     1511            Parse_Error(PARSE_WARNING, err, cp);
     1512
     1513        if (freeCmd)
     1514            efree(cp);
    15141515    } else {
    1515         /*
    1516         * Normal assignment -- just do it.
    1517         */
    1518         Var_Set(line, cp, ctxt);
     1516        /*
     1517        * Normal assignment -- just do it.
     1518        */
     1519        Var_Set(line, cp, ctxt);
    15191520    }
    15201521}
     
    15231524/*-
    15241525 * ParseAddCmd  --
    1525  *      Lst_ForEach function to add a command line to all targets
     1526 *      Lst_ForEach function to add a command line to all targets
    15261527 *
    15271528 * Results:
    1528  *      Always 0
     1529 *      Always 0
    15291530 *
    15301531 * Side Effects:
    1531  *      A new element is added to the commands list of the node.
     1532 *      A new element is added to the commands list of the node.
    15321533 */
    15331534static int
    15341535ParseAddCmd(gnp, cmd)
    1535     ClientData gnp;     /* the node to which the command is to be added */
    1536     ClientData cmd;     /* the command to add */
     1536    ClientData gnp;     /* the node to which the command is to be added */
     1537    ClientData cmd;     /* the command to add */
    15371538{
    15381539    GNode *gn = (GNode *) gnp;
    15391540    /* if target already supplied, ignore commands */
    15401541    if (!(gn->type & OP_HAS_COMMANDS))
    1541         (void)Lst_AtEnd(gn->commands, cmd);
     1542        (void)Lst_AtEnd(gn->commands, cmd);
    15421543    return(0);
    15431544}
     
    15481549/*-
    15491550 * ParseAppendInline  --
    1550  *      Lst_ForEach function to append the line to the last command
     1551 *      Lst_ForEach function to append the line to the last command
    15511552 *
    15521553 * Results:
    1553  *      Always 0
     1554 *      Always 0
    15541555 *
    15551556 * Side Effects:
    1556  *      A new element is added to the last commands list of the node.
     1557 *      A new element is added to the last commands list of the node.
    15571558 */
    15581559static int
    15591560ParseAppendInline(gnp, line)
    1560     ClientData gnp;     /* the node to which the command is to be added */
    1561     ClientData line;    /* the command to add */
     1561    ClientData gnp;     /* the node to which the command is to be added */
     1562    ClientData line;    /* the command to add */
    15621563{
    15631564    GNode *gn = (GNode *)gnp;
     
    15851586 *
    15861587 * Results:
    1587  *      returns TRUE if it is, FALSE if not.
     1588 *      returns TRUE if it is, FALSE if not.
    15881589 *
    15891590 * Side Effects:
    1590  *      OP_HAS_COMMANDS may be set for the target.
     1591 *      OP_HAS_COMMANDS may be set for the target.
    15911592 *
    15921593 *-----------------------------------------------------------------------
     
    16411642 *-----------------------------------------------------------------------
    16421643 * ParseHasCommands --
    1643  *      Callback procedure for Parse_File when destroying the list of
    1644  *      targets on the last dependency line. Marks a target as already
    1645  *      having commands if it does, to keep from having shell commands
    1646  *      on multiple dependency lines.
     1644 *      Callback procedure for Parse_File when destroying the list of
     1645 *      targets on the last dependency line. Marks a target as already
     1646 *      having commands if it does, to keep from having shell commands
     1647 *      on multiple dependency lines.
    16471648 *
    16481649 * Results:
    1649  *      None
     1650 *      None
    16501651 *
    16511652 * Side Effects:
    1652  *      OP_HAS_COMMANDS may be set for the target.
     1653 *      OP_HAS_COMMANDS may be set for the target.
    16531654 *
    16541655 *-----------------------------------------------------------------------
     
    16561657static void
    16571658ParseHasCommands(gnp)
    1658     ClientData    gnp;      /* Node to examine */
     1659    ClientData    gnp;      /* Node to examine */
    16591660{
    16601661    GNode *gn = (GNode *) gnp;
    16611662    if (!Lst_IsEmpty(gn->commands)) {
    1662         gn->type |= OP_HAS_COMMANDS;
     1663        gn->type |= OP_HAS_COMMANDS;
    16631664    }
    16641665}
     
    16671668 *-----------------------------------------------------------------------
    16681669 * Parse_AddIncludeDir --
    1669  *      Add a directory to the path searched for included makefiles
    1670  *      bracketed by double-quotes. Used by functions in main.c
     1670 *      Add a directory to the path searched for included makefiles
     1671 *      bracketed by double-quotes. Used by functions in main.c
    16711672 *
    16721673 * Results:
    1673  *      None.
     1674 *      None.
    16741675 *
    16751676 * Side Effects:
    1676  *      The directory is appended to the list.
     1677 *      The directory is appended to the list.
    16771678 *
    16781679 *-----------------------------------------------------------------------
     
    16801681void
    16811682Parse_AddIncludeDir (dir)
    1682     char          *dir;     /* The name of the directory to add */
     1683    char          *dir;     /* The name of the directory to add */
    16831684{
    16841685    Dir_AddDir (parseIncPath, dir);
     
    16871688/*---------------------------------------------------------------------
    16881689 * ParseDoError  --
    1689  *      Handle error directive
    1690  *
    1691  *      The input is the line minus the ".error".  We substitute variables,
    1692  *      print the message and exit(1) or just print a warning if the ".error"
    1693  *      directive is malformed.
     1690 *      Handle error directive
     1691 *
     1692 *      The input is the line minus the ".error".  We substitute variables,
     1693 *      print the message and exit(1) or just print a warning if the ".error"
     1694 *      directive is malformed.
    16941695 *
    16951696 *---------------------------------------------------------------------
     
    16971698static void
    16981699ParseDoError(errmsg)
    1699     char          *errmsg;      /* error message */
    1700 {
    1701         if (!isspace(*errmsg)) {
    1702                 Parse_Error(PARSE_WARNING, "invalid syntax: .error%s", errmsg);
    1703                 return;
    1704         }
    1705        
    1706         while (isspace(*errmsg))
    1707                 errmsg++;
    1708        
    1709         errmsg = Var_Subst(NULL, errmsg, VAR_GLOBAL, FALSE);
    1710 
    1711         /* use fprintf/exit instead of Parse_Error to terminate immediately */
    1712         fprintf(stderr, "\"%s\", line %d: %s\n", fname, lineno, errmsg);
    1713         exit(1);
     1700    char          *errmsg;      /* error message */
     1701{
     1702        if (!isspace(*errmsg)) {
     1703                Parse_Error(PARSE_WARNING, "invalid syntax: .error%s", errmsg);
     1704                return;
     1705        }
     1706
     1707        while (isspace(*errmsg))
     1708                errmsg++;
     1709
     1710        errmsg = Var_Subst(NULL, errmsg, VAR_GLOBAL, FALSE);
     1711
     1712        /* use fprintf/exit instead of Parse_Error to terminate immediately */
     1713        fprintf(stderr, "\"%s\", line %d: %s\n", fname, lineno, errmsg);
     1714        exit(1);
    17141715}
    17151716
     
    17171718 *---------------------------------------------------------------------
    17181719 * ParseDoInclude  --
    1719  *      Push to another file.
    1720  *
    1721  *      The input is the line minus the #include. A file spec is a string
    1722  *      enclosed in <> or "". The former is looked for only in sysIncPath.
    1723  *      The latter in . and the directories specified by -I command line
    1724  *      options
     1720 *      Push to another file.
     1721 *
     1722 *      The input is the line minus the #include. A file spec is a string
     1723 *      enclosed in <> or "". The former is looked for only in sysIncPath.
     1724 *      The latter in . and the directories specified by -I command line
     1725 *      options
    17251726 *
    17261727 * Results:
    1727  *      None
     1728 *      None
    17281729 *
    17291730 * Side Effects:
    1730  *      A structure is added to the includes Lst and readProc, lineno,
    1731  *      fname and curFILE are altered for the new file
     1731 *      A structure is added to the includes Lst and readProc, lineno,
     1732 *      fname and curFILE are altered for the new file
    17321733 *---------------------------------------------------------------------
    17331734 */
    17341735static void
    17351736ParseDoInclude (file, chPre)
    1736     char          *file;        /* file specification */
     1737    char          *file;        /* file specification */
    17371738    char           chPre;       /* Preprocessor char */
    17381739{
    1739     char          *fullname;    /* full pathname of file */
    1740     IFile         *oldFile;     /* state associated with current file */
    1741     char          endc;         /* the character which ends the file spec */
    1742     char          *cp;          /* current position in file spec */
    1743     Boolean       isSystem;     /* TRUE if makefile is a system makefile */
     1740    char          *fullname;    /* full pathname of file */
     1741    IFile         *oldFile;     /* state associated with current file */
     1742    char          endc;         /* the character which ends the file spec */
     1743    char          *cp;          /* current position in file spec */
     1744    Boolean       isSystem;     /* TRUE if makefile is a system makefile */
    17441745
    17451746    /*
     
    17471748     */
    17481749    while ((*file == ' ') || (*file == '\t')) {
    1749         file++;
     1750        file++;
    17501751    }
    17511752
    17521753    #ifndef NMAKE
    17531754    if ((*file != '"') && (*file != '<')) {
    1754         Parse_Error (PARSE_FATAL,
    1755             "%cinclude filename must be delimited by '\"' or '<'", chPre);
    1756         return;
     1755        Parse_Error (PARSE_FATAL,
     1756            "%cinclude filename must be delimited by '\"' or '<'", chPre);
     1757        return;
    17571758    }
    17581759    #endif
     
    17641765     */
    17651766    if (*file == '<') {
    1766         isSystem = TRUE;
    1767         endc = '>';
     1767        isSystem = TRUE;
     1768        endc = '>';
    17681769    } else {
    1769         isSystem = FALSE;
     1770        isSystem = FALSE;
    17701771        #ifdef NMAKE
    17711772        if (*file == '"')
    1772             endc = '"';
     1773            endc = '"';
    17731774        else
    17741775        {
     
    17771778        }
    17781779        #else
    1779         endc = '"';
     1780        endc = '"';
    17801781        #endif
    17811782    }
     
    17851786     */
    17861787    for (cp = ++file; *cp && *cp != endc; cp++) {
    1787         continue;
     1788        continue;
    17881789    }
    17891790
     
    17931794    if (*cp != endc) {
    17941795    #endif
    1795         Parse_Error (PARSE_FATAL,
    1796                      "Unclosed %cinclude filename. '%c' expected",
    1797                      chPre, endc);
    1798         return;
     1796        Parse_Error (PARSE_FATAL,
     1797                     "Unclosed %cinclude filename. '%c' expected",
     1798                     chPre, endc);
     1799        return;
    17991800    }
    18001801    *cp = '\0';
     
    18121813     */
    18131814    if (!isSystem) {
    1814         /*
    1815         * Include files contained in double-quotes are first searched for
    1816         * relative to the including file's location. We don't want to
    1817         * cd there, of course, so we just tack on the old file's
    1818         * leading path components and call Dir_FindFile to see if
    1819         * we can locate the beast.
    1820         */
    1821         char      *prefEnd, *Fname;
    1822 
    1823         /* Make a temporary copy of this, to be safe. */
    1824         Fname = estrdup(fname);
    1825 
    1826         prefEnd = strrchr (Fname, '/');
    1827         if (prefEnd != (char *)NULL) {
    1828             char        *newName;
    1829 
    1830             *prefEnd = '\0';
    1831             if (file[0] == '/')
    1832                 newName = estrdup(file);
    1833             else
    1834                 newName = str_concat (Fname, file, STR_ADDSLASH);
    1835             fullname = Dir_FindFile (newName, parseIncPath);
    1836             if (fullname == (char *)NULL) {
    1837                 fullname = Dir_FindFile(newName, dirSearchPath);
    1838             }
    1839             efree (newName);
    1840             *prefEnd = '/';
    1841         } else {
    1842             fullname = (char *)NULL;
    1843         }
    1844         efree (Fname);
     1815        /*
     1816        * Include files contained in double-quotes are first searched for
     1817        * relative to the including file's location. We don't want to
     1818        * cd there, of course, so we just tack on the old file's
     1819        * leading path components and call Dir_FindFile to see if
     1820        * we can locate the beast.
     1821        */
     1822        char      *prefEnd, *Fname;
     1823
     1824        /* Make a temporary copy of this, to be safe. */
     1825        Fname = estrdup(fname);
     1826
     1827        prefEnd = strrchr (Fname, '/');
     1828        if (prefEnd != (char *)NULL) {
     1829            char        *newName;
     1830
     1831            *prefEnd = '\0';
     1832            if (file[0] == '/')
     1833                newName = estrdup(file);
     1834            else
     1835                newName = str_concat (Fname, file, STR_ADDSLASH);
     1836            fullname = Dir_FindFile (newName, parseIncPath);
     1837            if (fullname == (char *)NULL) {
     1838                fullname = Dir_FindFile(newName, dirSearchPath);
     1839            }
     1840            efree (newName);
     1841            *prefEnd = '/';
     1842        } else {
     1843            fullname = (char *)NULL;
     1844        }
     1845        efree (Fname);
    18451846    } else {
    1846         fullname = (char *)NULL;
     1847        fullname = (char *)NULL;
    18471848    }
    18481849
    18491850    if (fullname == (char *)NULL) {
    1850         /*
    1851         * System makefile or makefile wasn't found in same directory as
    1852         * included makefile. Search for it first on the -I search path,
    1853         * then on the .PATH search path, if not found in a -I directory.
    1854         * XXX: Suffix specific?
    1855         */
    1856         fullname = Dir_FindFile (file, parseIncPath);
    1857         if (fullname == (char *)NULL) {
    1858             fullname = Dir_FindFile(file, dirSearchPath);
    1859         }
     1851        /*
     1852        * System makefile or makefile wasn't found in same directory as
     1853        * included makefile. Search for it first on the -I search path,
     1854        * then on the .PATH search path, if not found in a -I directory.
     1855        * XXX: Suffix specific?
     1856        */
     1857        fullname = Dir_FindFile (file, parseIncPath);
     1858        if (fullname == (char *)NULL) {
     1859            fullname = Dir_FindFile(file, dirSearchPath);
     1860        }
    18601861    }
    18611862
    18621863    if (fullname == (char *)NULL) {
    1863         /*
    1864         * Still haven't found the makefile. Look for it on the system
    1865         * path as a last resort.
    1866         */
    1867         fullname = Dir_FindFile(file, sysIncPath);
     1864        /*
     1865        * Still haven't found the makefile. Look for it on the system
     1866        * path as a last resort.
     1867        */
     1868        fullname = Dir_FindFile(file, sysIncPath);
    18681869    }
    18691870
    18701871    if (fullname == (char *) NULL) {
    1871         *cp = endc;
    1872         Parse_Error (PARSE_FATAL, "Could not find '%s'", file);
    1873         return;
     1872        *cp = endc;
     1873        Parse_Error (PARSE_FATAL, "Could not find '%s'", file);
     1874        return;
    18741875    }
    18751876
     
    19041905    curPTR = NULL;
    19051906    if (curFILE == (FILE * ) NULL) {
    1906         Parse_Error (PARSE_FATAL, "Cannot open %s", fullname);
    1907         /*
    1908         * Pop to previous file
    1909         */
    1910         (void) ParseEOF(0);
     1907        Parse_Error (PARSE_FATAL, "Cannot open %s", fullname);
     1908        /*
     1909        * Pop to previous file
     1910        */
     1911        (void) ParseEOF(0);
    19111912    }
    19121913}
     
    19171918 *---------------------------------------------------------------------
    19181919 * Parse_FromString  --
    1919  *      Start Parsing from the given string
     1920 *      Start Parsing from the given string
    19201921 *
    19211922 * Results:
    1922  *      None
     1923 *      None
    19231924 *
    19241925 * Side Effects:
    1925  *      A structure is added to the includes Lst and readProc, lineno,
    1926  *      fname and curFILE are altered for the new file
     1926 *      A structure is added to the includes Lst and readProc, lineno,
     1927 *      fname and curFILE are altered for the new file
    19271928 *---------------------------------------------------------------------
    19281929 */
     
    19311932    char *str;
    19321933{
    1933     IFile         *oldFile;     /* state associated with this file */
     1934    IFile         *oldFile;     /* state associated with this file */
    19341935
    19351936    if (DEBUG(FOR))
    1936         (void) fprintf(stderr, "%s\n----\n", str);
     1937        (void) fprintf(stderr, "%s\n----\n", str);
    19371938
    19381939    oldFile = (IFile *) emalloc (sizeof (IFile));
     
    19561957 *---------------------------------------------------------------------
    19571958 * ParseTraditionalInclude  --
    1958  *      Push to another file.
    1959  *
    1960  *      The input is the line minus the "include".  The file name is
    1961  *      the string following the "include".
     1959 *      Push to another file.
     1960 *
     1961 *      The input is the line minus the "include".  The file name is
     1962 *      the string following the "include".
    19621963 *
    19631964 * Results:
    1964  *      None
     1965 *      None
    19651966 *
    19661967 * Side Effects:
    1967  *      A structure is added to the includes Lst and readProc, lineno,
    1968  *      fname and curFILE are altered for the new file
     1968 *      A structure is added to the includes Lst and readProc, lineno,
     1969 *      fname and curFILE are altered for the new file
    19691970 *---------------------------------------------------------------------
    19701971 */
    19711972static void
    19721973ParseTraditionalInclude (file)
    1973     char          *file;        /* file specification */
    1974 {
    1975     char          *fullname;    /* full pathname of file */
    1976     IFile         *oldFile;     /* state associated with current file */
    1977     char          *cp;          /* current position in file spec */
    1978     char          *prefEnd;
     1974    char          *file;        /* file specification */
     1975{
     1976    char          *fullname;    /* full pathname of file */
     1977    IFile         *oldFile;     /* state associated with current file */
     1978    char          *cp;          /* current position in file spec */
     1979    char          *prefEnd;
    19791980
    19801981    /*
     
    19821983     */
    19831984    while ((*file == ' ') || (*file == '\t')) {
    1984         file++;
     1985        file++;
    19851986    }
    19861987
    19871988    if (*file == '\0') {
    1988         Parse_Error (PARSE_FATAL,
    1989                      "Filename missing from \"include\"");
    1990         return;
     1989        Parse_Error (PARSE_FATAL,
     1990                     "Filename missing from \"include\"");
     1991        return;
    19911992    }
    19921993
     
    19951996     */
    19961997    for (cp = file; *cp && *cp != '\n' && *cp != '\t' && *cp != ' '; cp++) {
    1997         continue;
     1998        continue;
    19981999    }
    19992000
     
    20192020    prefEnd = strrchr (fname, '/');
    20202021    if (prefEnd != (char *)NULL) {
    2021         char    *newName;
    2022 
    2023         *prefEnd = '\0';
    2024         newName = str_concat (fname, file, STR_ADDSLASH);
    2025         fullname = Dir_FindFile (newName, parseIncPath);
    2026         if (fullname == (char *)NULL) {
    2027             fullname = Dir_FindFile(newName, dirSearchPath);
    2028         }
    2029         efree (newName);
    2030         *prefEnd = '/';
     2022        char    *newName;
     2023
     2024        *prefEnd = '\0';
     2025        newName = str_concat (fname, file, STR_ADDSLASH);
     2026        fullname = Dir_FindFile (newName, parseIncPath);
     2027        if (fullname == (char *)NULL) {
     2028            fullname = Dir_FindFile(newName, dirSearchPath);
     2029        }
     2030        efree (newName);
     2031        *prefEnd = '/';
    20312032    } else {
    2032         fullname = (char *)NULL;
     2033        fullname = (char *)NULL;
    20332034    }
    20342035
    20352036    if (fullname == (char *)NULL) {
    2036         /*
    2037         * System makefile or makefile wasn't found in same directory as
    2038         * included makefile. Search for it first on the -I search path,
    2039         * then on the .PATH search path, if not found in a -I directory.
    2040         * XXX: Suffix specific?
    2041         */
    2042         fullname = Dir_FindFile (file, parseIncPath);
    2043         if (fullname == (char *)NULL) {
    2044             fullname = Dir_FindFile(file, dirSearchPath);
    2045         }
     2037        /*
     2038        * System makefile or makefile wasn't found in same directory as
     2039        * included makefile. Search for it first on the -I search path,
     2040        * then on the .PATH search path, if not found in a -I directory.
     2041        * XXX: Suffix specific?
     2042        */
     2043        fullname = Dir_FindFile (file, parseIncPath);
     2044        if (fullname == (char *)NULL) {
     2045            fullname = Dir_FindFile(file, dirSearchPath);
     2046        }
    20462047    }
    20472048
    20482049    if (fullname == (char *)NULL) {
    2049         /*
    2050         * Still haven't found the makefile. Look for it on the system
    2051         * path as a last resort.
    2052         */
    2053         fullname = Dir_FindFile(file, sysIncPath);
     2050        /*
     2051        * Still haven't found the makefile. Look for it on the system
     2052        * path as a last resort.
     2053        */
     2054        fullname = Dir_FindFile(file, sysIncPath);
    20542055    }
    20552056
    20562057    if (fullname == (char *) NULL) {
    2057         Parse_Error (PARSE_FATAL, "Could not find %s", file);
    2058         return;
     2058        Parse_Error (PARSE_FATAL, "Could not find %s", file);
     2059        return;
    20592060    }
    20602061
     
    20872088    curPTR = NULL;
    20882089    if (curFILE == (FILE * ) NULL) {
    2089         Parse_Error (PARSE_FATAL, "Cannot open %s", fullname);
    2090         /*
    2091         * Pop to previous file
    2092         */
    2093         (void) ParseEOF(1);
     2090        Parse_Error (PARSE_FATAL, "Cannot open %s", fullname);
     2091        /*
     2092        * Pop to previous file
     2093        */
     2094        (void) ParseEOF(1);
    20942095    }
    20952096}
     
    20992100 *---------------------------------------------------------------------
    21002101 * ParseEOF  --
    2101  *      Called when EOF is reached in the current file. If we were reading
    2102  *      an include file, the includes stack is popped and things set up
    2103  *      to go back to reading the previous file at the previous location.
     2102 *      Called when EOF is reached in the current file. If we were reading
     2103 *      an include file, the includes stack is popped and things set up
     2104 *      to go back to reading the previous file at the previous location.
    21042105 *
    21052106 * Results:
    2106  *      CONTINUE if there's more to do. DONE if not.
     2107 *      CONTINUE if there's more to do. DONE if not.
    21072108 *
    21082109 * Side Effects:
    2109  *      The old curFILE, is closed. The includes list is shortened.
    2110  *      lineno, curFILE, and fname are changed if CONTINUE is returned.
     2110 *      The old curFILE, is closed. The includes list is shortened.
     2111 *      lineno, curFILE, and fname are changed if CONTINUE is returned.
    21112112 *---------------------------------------------------------------------
    21122113 */
     
    21152116    int opened;
    21162117{
    2117     IFile     *ifile;   /* the state on the top of the includes stack */
     2118    IFile     *ifile;   /* the state on the top of the includes stack */
    21182119
    21192120    if (Lst_IsEmpty (includes)) {
    2120         return (DONE);
     2121        return (DONE);
    21212122    }
    21222123
     
    21262127    lineno = ifile->lineno;
    21272128    if (opened && curFILE)
    2128         (void) fclose (curFILE);
     2129        (void) fclose (curFILE);
    21292130    if (curPTR) {
    2130         efree((Address) curPTR->str);
    2131         efree((Address) curPTR);
     2131        efree((Address) curPTR->str);
     2132        efree((Address) curPTR);
    21322133    }
    21332134    curFILE = ifile->F;
     
    21402141 *---------------------------------------------------------------------
    21412142 * ParseReadc  --
    2142  *      Read a character from the current file
     2143 *      Read a character from the current file
    21432144 *
    21442145 * Results:
    2145  *      The character that was read
     2146 *      The character that was read
    21462147 *
    21472148 * Side Effects:
     
    21522153{
    21532154    if (curFILE)
    2154         return fgetc(curFILE);
     2155        return fgetc(curFILE);
    21552156
    21562157    if (curPTR && *curPTR->ptr)
    2157         return *curPTR->ptr++;
     2158        return *curPTR->ptr++;
    21582159    return EOF;
    21592160}
     
    21632164 *---------------------------------------------------------------------
    21642165 * ParseUnreadc  --
    2165  *      Put back a character to the current file
     2166 *      Put back a character to the current file
    21662167 *
    21672168 * Results:
    2168  *      None.
     2169 *      None.
    21692170 *
    21702171 * Side Effects:
     
    21762177{
    21772178    if (curFILE) {
    2178         ungetc(c, curFILE);
    2179         return;
     2179        ungetc(c, curFILE);
     2180        return;
    21802181    }
    21812182    if (curPTR) {
    2182         *--(curPTR->ptr) = c;
    2183         return;
     2183        *--(curPTR->ptr) = c;
     2184        return;
    21842185    }
    21852186}
     
    21872188
    21882189/* ParseSkipLine():
    2189  *      Grab the next line
     2190 *      Grab the next line
    21902191 */
    21912192static char *
    21922193ParseSkipLine(skip)
    2193     int skip;           /* Skip lines that don't start with . */
     2194    int skip;           /* Skip lines that don't start with . */
    21942195{
    21952196    char *line;
     
    22422243 *---------------------------------------------------------------------
    22432244 * ParseReadLine --
    2244  *      Read an entire line from the input file. Called only by Parse_File.
    2245  *      To facilitate escaped newlines and what have you, a character is
    2246  *      buffered in 'lastc', which is '\0' when no characters have been
    2247  *      read. When we break out of the loop, c holds the terminating
    2248  *      character and lastc holds a character that should be added to
    2249  *      the line (unless we don't read anything but a terminator).
     2245 *      Read an entire line from the input file. Called only by Parse_File.
     2246 *      To facilitate escaped newlines and what have you, a character is
     2247 *      buffered in 'lastc', which is '\0' when no characters have been
     2248 *      read. When we break out of the loop, c holds the terminating
     2249 *      character and lastc holds a character that should be added to
     2250 *      the line (unless we don't read anything but a terminator).
    22502251 *
    22512252 * Results:
    2252  *      A line w/o its newline
     2253 *      A line w/o its newline
    22532254 *
    22542255 * Side Effects:
    2255  *      Only those associated with reading a character
     2256 *      Only those associated with reading a character
    22562257 *---------------------------------------------------------------------
    22572258 */
     
    22592260ParseReadLine ()
    22602261{
    2261     Buffer        buf;          /* Buffer for current line */
    2262     register int  c;            /* the current character */
    2263     register int  lastc;        /* The most-recent character */
    2264     Boolean       semiNL;       /* treat semi-colons as newlines */
    2265     Boolean       ignDepOp;     /* TRUE if should ignore dependency operators
    2266                                 * for the purposes of setting semiNL */
    2267     Boolean       ignComment;   /* TRUE if should ignore comments (in a
    2268                                 * shell command */
    2269     char          *line;        /* Result */
    2270     char          *ep;          /* to strip trailing blanks */
    2271     int           lineLength;   /* Length of result */
     2262    Buffer        buf;          /* Buffer for current line */
     2263    register int  c;            /* the current character */
     2264    register int  lastc;        /* The most-recent character */
     2265    Boolean       semiNL;       /* treat semi-colons as newlines */
     2266    Boolean       ignDepOp;     /* TRUE if should ignore dependency operators
     2267                                * for the purposes of setting semiNL */
     2268    Boolean       ignComment;   /* TRUE if should ignore comments (in a
     2269                                * shell command */
     2270    char          *line;        /* Result */
     2271    char          *ep;          /* to strip trailing blanks */
     2272    int           lineLength;   /* Length of result */
    22722273
    22732274    semiNL = FALSE;
     
    22872288     */
    22882289    for (;;) {
    2289         c = ParseReadc();
     2290        c = ParseReadc();
    22902291        #ifdef USE_INLINEFILES
    22912292        if (inInlineFile)
     
    22932294        #endif
    22942295
    2295         if (c == '\t') {
    2296             ignComment = ignDepOp = TRUE;
    2297             break;
    2298         } else if (c == '\n') {
    2299             lineno++;
    2300         } else if (c == '#') {
    2301             ParseUnreadc(c);
    2302             break;
    2303         } else {
    2304             /*
    2305              * Anything else breaks out without doing anything
    2306              */
    2307             break;
    2308         }
     2296        if (c == '\t') {
     2297            ignComment = ignDepOp = TRUE;
     2298            break;
     2299        } else if (c == '\n') {
     2300            lineno++;
     2301        } else if (c == '#') {
     2302            ParseUnreadc(c);
     2303            break;
     2304        } else {
     2305            /*
     2306             * Anything else breaks out without doing anything
     2307             */
     2308            break;
     2309        }
    23092310    }
    23102311
    23112312    if (c != EOF) {
    2312         lastc = c;
    2313         buf = Buf_Init(MAKE_BSIZE);
     2313        lastc = c;
     2314        buf = Buf_Init(MAKE_BSIZE);
    23142315
    23152316        /* @todo any inline changes here? */
    23162317        #ifdef NMAKE
    2317         while (((c = ParseReadc ()) != '\n' || (lastc == '\\') || (lastc == '^')) && (c != EOF))
     2318        while (((c = ParseReadc ()) != '\n' || (lastc == '\\') || (lastc == '^')) && (c != EOF))
    23182319        #else
    2319         while (((c = ParseReadc ()) != '\n' || (lastc == '\\')) && (c != EOF))
     2320        while (((c = ParseReadc ()) != '\n' || (lastc == '\\')) && (c != EOF))
    23202321        #endif
    2321         {
     2322        {
    23222323test_char:
    2323             switch(c) {
    2324             case '\n':
     2324            switch(c) {
     2325            case '\n':
    23252326                #ifdef USE_INLINEFILES
    23262327                /* No newline escaping in inline files, unless it's a directive. */
     
    23362337                }
    23372338                #endif
    2338                
     2339
    23392340                /*
    2340                 * Escaped newline: read characters until a non-space or an
    2341                 * unescaped newline and replace them all by a single space.
    2342                 * This is done by storing the space over the backslash and
    2343                 * dropping through with the next nonspace. If it is a
    2344                 * semi-colon and semiNL is TRUE, it will be recognized as a
    2345                 * newline in the code below this...
    2346                 */
    2347                 lineno++;
    2348                 lastc = ' ';
     2341                * Escaped newline: read characters until a non-space or an
     2342                * unescaped newline and replace them all by a single space.
     2343                * This is done by storing the space over the backslash and
     2344                * dropping through with the next nonspace. If it is a
     2345                * semi-colon and semiNL is TRUE, it will be recognized as a
     2346                * newline in the code below this...
     2347                */
     2348                lineno++;
     2349                lastc = ' ';
    23492350#ifdef NMAKE
    23502351                if (lastc == '^')
    2351                     lastc = '\n';
     2352                    lastc = '\n';
    23522353
    23532354                do {
    23542355                        while ((c = ParseReadc ()) == ' ' || c == '\t') {
    2355                             continue;
    2356                         }
     2356                            continue;
     2357                        }
    23572358                        if (c != '#')
    23582359                            break;
    23592360                        /* comment - skip line */
    23602361                        while ((c = ParseReadc ()) != '\n' && c != EOF) {
    2361                             continue;
    2362                         }
     2362                            continue;
     2363                        }
    23632364                        if (c == EOF)
    23642365                            break;
    23652366                } while (1);
    23662367#else
    2367                 while ((c = ParseReadc ()) == ' ' || c == '\t') {
    2368                     continue;
    2369                 }
    2370 #endif
    2371                 if (c == EOF || c == '\n') {
    2372                     goto line_read;
    2373                 } else {
    2374                     /*
    2375                      * Check for comments, semiNL's, etc. -- easier than
    2376                      * ParseUnreadc(c); continue;
    2377                      */
    2378                     goto test_char;
    2379                 }
    2380                 /*NOTREACHED*/
    2381                 break;
     2368                while ((c = ParseReadc ()) == ' ' || c == '\t') {
     2369                    continue;
     2370                }
     2371#endif
     2372                if (c == EOF || c == '\n') {
     2373                    goto line_read;
     2374                } else {
     2375                    /*
     2376                     * Check for comments, semiNL's, etc. -- easier than
     2377                     * ParseUnreadc(c); continue;
     2378                     */
     2379                    goto test_char;
     2380                }
     2381                /*NOTREACHED*/
     2382                break;
    23822383
    23832384/* We don't need this, and don't want it! */
    23842385#ifndef KMK
    2385             case ';':
     2386            case ';':
    23862387                #ifdef USE_INLINEFILES
    23872388                if (inInlineFile)
    23882389                    break;
    23892390                #endif
    2390                 /*
    2391                 * Semi-colon: Need to see if it should be interpreted as a
    2392                 * newline
    2393                 */
    2394                 if (semiNL) {
    2395                     /*
    2396                      * To make sure the command that may be following this
    2397                      * semi-colon begins with a tab, we push one back into the
    2398                      * input stream. This will overwrite the semi-colon in the
    2399                      * buffer. If there is no command following, this does no
    2400                      * harm, since the newline remains in the buffer and the
    2401                      * whole line is ignored.
    2402                      */
    2403                     ParseUnreadc('\t');
    2404                     goto line_read;
    2405                 }
    2406                 break;
    2407             case '=':
     2391                /*
     2392                * Semi-colon: Need to see if it should be interpreted as a
     2393                * newline
     2394                */
     2395                if (semiNL) {
     2396                    /*
     2397                     * To make sure the command that may be following this
     2398                     * semi-colon begins with a tab, we push one back into the
     2399                     * input stream. This will overwrite the semi-colon in the
     2400                     * buffer. If there is no command following, this does no
     2401                     * harm, since the newline remains in the buffer and the
     2402                     * whole line is ignored.
     2403                     */
     2404                    ParseUnreadc('\t');
     2405                    goto line_read;
     2406                }
     2407                break;
     2408            case '=':
    24082409                #ifdef USE_INLINEFILES
    24092410                if (inInlineFile)
     
    24112412                #endif
    24122413                if (!semiNL) {
    2413                     /*
    2414                      * Haven't seen a dependency operator before this, so this
    2415                      * must be a variable assignment -- don't pay attention to
    2416                      * dependency operators after this.
    2417                      */
    2418                     ignDepOp = TRUE;
    2419                 } else if (lastc == ':' || lastc == '!') {
    2420                     /*
    2421                      * Well, we've seen a dependency operator already, but it
    2422                      * was the previous character, so this is really just an
    2423                      * expanded variable assignment. Revert semi-colons to
    2424                      * being just semi-colons again and ignore any more
    2425                      * dependency operators.
    2426                      *
    2427                      * XXX: Note that a line like "foo : a:=b" will blow up,
    2428                      * but who'd write a line like that anyway?
    2429                      */
    2430                     ignDepOp = TRUE; semiNL = FALSE;
    2431                 }
    2432                 break;
    2433             case '#':
    2434                 if (!ignComment) {
    2435                     if (
     2414                    /*
     2415                     * Haven't seen a dependency operator before this, so this
     2416                     * must be a variable assignment -- don't pay attention to
     2417                     * dependency operators after this.
     2418                     */
     2419                    ignDepOp = TRUE;
     2420                } else if (lastc == ':' || lastc == '!') {
     2421                    /*
     2422                     * Well, we've seen a dependency operator already, but it
     2423                     * was the previous character, so this is really just an
     2424                     * expanded variable assignment. Revert semi-colons to
     2425                     * being just semi-colons again and ignore any more
     2426                     * dependency operators.
     2427                     *
     2428                     * XXX: Note that a line like "foo : a:=b" will blow up,
     2429                     * but who'd write a line like that anyway?
     2430                     */
     2431                    ignDepOp = TRUE; semiNL = FALSE;
     2432                }
     2433                break;
     2434            case '#':
     2435                if (!ignComment) {
     2436                    if (
    24362437#if 0
    2437                     compatMake &&
    2438 #endif
    2439                     (lastc != '\\')) {
    2440                         /*
    2441                         * If the character is a hash mark and it isn't escaped
    2442                         * (or we're being compatible), the thing is a comment.
    2443                         * Skip to the end of the line.
    2444                         */
    2445                         do {
    2446                             c = ParseReadc();
    2447                         } while ((c != '\n') && (c != EOF));
    2448                         goto line_read;
    2449                     } else {
    2450                         /*
    2451                         * Don't add the backslash. Just let the # get copied
    2452                         * over.
    2453                         */
    2454                         lastc = c;
    2455                         continue;
    2456                     }
    2457                 }
    2458                 break;
    2459             case ':':
    2460             case '!':
     2438                    compatMake &&
     2439#endif
     2440                    (lastc != '\\')) {
     2441                        /*
     2442                        * If the character is a hash mark and it isn't escaped
     2443                        * (or we're being compatible), the thing is a comment.
     2444                        * Skip to the end of the line.
     2445                        */
     2446                        do {
     2447                            c = ParseReadc();
     2448                        } while ((c != '\n') && (c != EOF));
     2449                        goto line_read;
     2450                    } else {
     2451                        /*
     2452                        * Don't add the backslash. Just let the # get copied
     2453                        * over.
     2454                        */
     2455                        lastc = c;
     2456                        continue;
     2457                    }
     2458                }
     2459                break;
     2460            case ':':
     2461            case '!':
    24612462                #ifdef USE_INLINEFILES
    24622463                if (inInlineFile)
    24632464                    break;
    24642465                #endif
    2465                 if (!ignDepOp && (c == ':' || c == '!')) {
    2466                     /*
    2467                      * A semi-colon is recognized as a newline only on
    2468                      * dependency lines. Dependency lines are lines with a
    2469                      * colon or an exclamation point. Ergo...
    2470                      */
    2471                     semiNL = TRUE;
    2472                 }
    2473                 break;
     2466                if (!ignDepOp && (c == ':' || c == '!')) {
     2467                    /*
     2468                     * A semi-colon is recognized as a newline only on
     2469                     * dependency lines. Dependency lines are lines with a
     2470                     * colon or an exclamation point. Ergo...
     2471                     */
     2472                    semiNL = TRUE;
     2473                }
     2474                break;
    24742475#endif /* !KMK */
    2475             }
    2476             /*
    2477              * Copy in the previous character and save this one in lastc.
    2478              */
    2479             Buf_AddByte (buf, (Byte)lastc);
    2480             lastc = c;
    2481 
    2482         }
     2476            }
     2477            /*
     2478             * Copy in the previous character and save this one in lastc.
     2479             */
     2480            Buf_AddByte (buf, (Byte)lastc);
     2481            lastc = c;
     2482
     2483        }
    24832484    line_read:
    2484         lineno++;
    2485 
    2486         if (lastc != '\0') {
    2487             Buf_AddByte (buf, (Byte)lastc);
    2488         }
    2489         Buf_AddByte (buf, (Byte)'\0');
    2490         line = (char *)Buf_GetAll (buf, &lineLength);
    2491         Buf_Destroy (buf, FALSE);
    2492 
    2493         /*
    2494         * Strip trailing blanks and tabs from the line.
    2495         * Do not strip a blank or tab that is preceeded by
    2496         * a '\'
    2497         */
     2485        lineno++;
     2486
     2487        if (lastc != '\0') {
     2488            Buf_AddByte (buf, (Byte)lastc);
     2489        }
     2490        Buf_AddByte (buf, (Byte)'\0');
     2491        line = (char *)Buf_GetAll (buf, &lineLength);
     2492        Buf_Destroy (buf, FALSE);
     2493
     2494        /*
     2495        * Strip trailing blanks and tabs from the line.
     2496        * Do not strip a blank or tab that is preceeded by
     2497        * a '\'
     2498        */
    24982499#ifdef USE_INLINEFILES
    24992500      if (!inInlineFile) {
    25002501#endif
    2501         ep = line;
    2502         while (*ep)
    2503             ++ep;
    2504         while (ep > line + 1 && (ep[-1] == ' ' || ep[-1] == '\t')) {
    2505             if (ep > line + 1 && ep[-2] == '\\')
    2506                 break;
    2507             --ep;
    2508         }
    2509         *ep = 0;
     2502        ep = line;
     2503        while (*ep)
     2504            ++ep;
     2505        while (ep > line + 1 && (ep[-1] == ' ' || ep[-1] == '\t')) {
     2506            if (ep > line + 1 && ep[-2] == '\\')
     2507                break;
     2508            --ep;
     2509        }
     2510        *ep = 0;
    25102511#ifdef USE_INLINEFILES
    25112512      }
     
    25132514
    25142515#ifdef NMAKE
    2515         if (line[0] == '.' || line[0] == '!') {
     2516        if (line[0] == '.' || line[0] == '!') {
    25162517#else
    2517         if (line[0] == '.') {
    2518 #endif
    2519             /*
    2520              * The line might be a conditional. Ask the conditional module
    2521              * about it and act accordingly
    2522              */
    2523             switch (Cond_Eval (line)) {
    2524             case COND_SKIP:
    2525                 /*
    2526                 * Skip to next conditional that evaluates to COND_PARSE.
    2527                 */
    2528                 do {
    2529                     efree (line);
    2530                     line = ParseSkipLine(1);
    2531                 } while (line && Cond_Eval(line) != COND_PARSE);
    2532                 if (line == NULL)
    2533                     break;
    2534                 /*FALLTHRU*/
    2535             case COND_PARSE:
    2536                 efree ((Address) line);
    2537                 line = ParseReadLine();
    2538                 break;
    2539             case COND_INVALID:
    2540                 if (For_Eval(line)) {
    2541                     int ok;
    2542                     efree(line);
    2543                     do {
    2544                         /*
    2545                         * Skip after the matching end
    2546                         */
    2547                         line = ParseSkipLine(0);
    2548                         if (line == NULL) {
    2549                             Parse_Error (PARSE_FATAL,
    2550                                      "Unexpected end of file in for loop.\n");
    2551                             break;
    2552                         }
    2553                         ok = For_Eval(line);
    2554                         efree(line);
    2555                     }
    2556                     while (ok);
    2557                     if (line != NULL)
    2558                         For_Run();
    2559                     line = ParseReadLine();
    2560                 }
    2561                 break;
    2562             }
    2563         }
    2564         return (line);
     2518        if (line[0] == '.') {
     2519#endif
     2520            /*
     2521             * The line might be a conditional. Ask the conditional module
     2522             * about it and act accordingly
     2523             */
     2524            switch (Cond_Eval (line)) {
     2525            case COND_SKIP:
     2526                /*
     2527                * Skip to next conditional that evaluates to COND_PARSE.
     2528                */
     2529                do {
     2530                    efree (line);
     2531                    line = ParseSkipLine(1);
     2532                } while (line && Cond_Eval(line) != COND_PARSE);
     2533                if (line == NULL)
     2534                    break;
     2535                /*FALLTHRU*/
     2536            case COND_PARSE:
     2537                efree ((Address) line);
     2538                line = ParseReadLine();
     2539                break;
     2540            case COND_INVALID:
     2541                if (For_Eval(line)) {
     2542                    int ok;
     2543                    efree(line);
     2544                    do {
     2545                        /*
     2546                        * Skip after the matching end
     2547                        */
     2548                        line = ParseSkipLine(0);
     2549                        if (line == NULL) {
     2550                            Parse_Error (PARSE_FATAL,
     2551                                     "Unexpected end of file in for loop.\n");
     2552                            break;
     2553                        }
     2554                        ok = For_Eval(line);
     2555                        efree(line);
     2556                    }
     2557                    while (ok);
     2558                    if (line != NULL)
     2559                        For_Run();
     2560                    line = ParseReadLine();
     2561                }
     2562                break;
     2563            }
     2564        }
     2565        return (line);
    25652566
    25662567    } else {
    2567         /*
    2568         * Hit end-of-file, so return a NULL line to indicate this.
    2569         */
    2570         return((char *)NULL);
     2568        /*
     2569        * Hit end-of-file, so return a NULL line to indicate this.
     2570        */
     2571        return((char *)NULL);
    25712572    }
    25722573}
     
    25752576 *-----------------------------------------------------------------------
    25762577 * ParseFinishLine --
    2577  *      Handle the end of a dependency group.
     2578 *      Handle the end of a dependency group.
    25782579 *
    25792580 * Results:
    2580  *      Nothing.
     2581 *      Nothing.
    25812582 *
    25822583 * Side Effects:
    2583  *      inLine set FALSE. 'targets' list destroyed.
     2584 *      inLine set FALSE. 'targets' list destroyed.
    25842585 *
    25852586 *-----------------------------------------------------------------------
     
    25892590{
    25902591    if (inLine) {
    2591         Lst_ForEach(targets, Suff_EndTransform, (ClientData)NULL);
    2592         Lst_Destroy (targets, ParseHasCommands);
    2593         targets = NULL;
    2594         inLine = FALSE;
     2592        Lst_ForEach(targets, Suff_EndTransform, (ClientData)NULL);
     2593        Lst_Destroy (targets, ParseHasCommands);
     2594        targets = NULL;
     2595        inLine = FALSE;
    25952596    }
    25962597}
     
    26002601 *---------------------------------------------------------------------
    26012602 * Parse_File --
    2602  *      Parse a file into its component parts, incorporating it into the
    2603  *      current dependency graph. This is the main function and controls
    2604  *      almost every other function in this module
     2603 *      Parse a file into its component parts, incorporating it into the
     2604 *      current dependency graph. This is the main function and controls
     2605 *      almost every other function in this module
    26052606 *
    26062607 * Results:
    2607  *      None
     2608 *      None
    26082609 *
    26092610 * Side Effects:
    2610  *      Loads. Nodes are added to the list of all targets, nodes and links
    2611  *      are added to the dependency graph. etc. etc. etc.
     2611 *      Loads. Nodes are added to the list of all targets, nodes and links
     2612 *      are added to the dependency graph. etc. etc. etc.
    26122613 *---------------------------------------------------------------------
    26132614 */
    26142615void
    26152616Parse_File(name, stream)
    2616     char          *name;        /* the name of the file being read */
    2617     FILE *        stream;       /* Stream open to makefile to parse */
    2618 {
    2619     register char *cp,          /* pointer into the line */
    2620                   *line;        /* the line we're working on */
     2617    char          *name;        /* the name of the file being read */
     2618    FILE *        stream;       /* Stream open to makefile to parse */
     2619{
     2620    register char *cp,          /* pointer into the line */
     2621                  *line;        /* the line we're working on */
    26212622
    26222623    inLine = FALSE;
     
    26302631
    26312632    do {
    2632         while ((line = ParseReadLine ()) != NULL) {
     2633        while ((line = ParseReadLine ()) != NULL) {
    26332634            if (DEBUG(PARSE))
    26342635                printf("%s(%d): inLine=%d inInlineFile=%d\n%s\n", fname, lineno, inLine, inInlineFile, line);
    26352636            #ifdef NMAKE
    2636             if (*line == '.' || *line == '!') {
     2637            if (*line == '.' || *line == '!') {
    26372638            #else
    2638             if (*line == '.') {
     2639            if (*line == '.') {
    26392640            #endif
    2640                 /*
    2641                 * Lines that begin with the special character are either
    2642                 * include or undef directives.
    2643                 */
    2644                 for (cp = line + 1; isspace (*cp); cp++) {
    2645                     continue;
    2646                 }
    2647                 if (strncmp (cp, "include", 7) == 0) {
    2648                     ParseDoInclude (cp + 7, *line);
    2649                     goto nextLine;
    2650                 } else if (strncmp (cp, "error", 5) == 0) {
    2651                     ParseDoError(cp + 5);
    2652                     goto nextLine;     
    2653                 } else if (strncmp(cp, "undef", 5) == 0) {
    2654                     char *cp2;
    2655                     for (cp += 5; isspace((unsigned char) *cp); cp++) {
    2656                         continue;
    2657                     }
    2658 
    2659                     for (cp2 = cp; !isspace((unsigned char) *cp2) &&
    2660                                    (*cp2 != '\0'); cp2++) {
    2661                         continue;
    2662                     }
    2663 
    2664                     *cp2 = '\0';
    2665 
    2666                     Var_Delete(cp, VAR_GLOBAL);
    2667                     goto nextLine;
    2668                 }
    2669             }
     2641                /*
     2642                * Lines that begin with the special character are either
     2643                * include or undef directives.
     2644                */
     2645                for (cp = line + 1; isspace (*cp); cp++) {
     2646                    continue;
     2647                }
     2648                if (strncmp (cp, "include", 7) == 0) {
     2649                    ParseDoInclude (cp + 7, *line);
     2650                    goto nextLine;
     2651                } else if (strncmp (cp, "error", 5) == 0) {
     2652                    ParseDoError(cp + 5);
     2653                    goto nextLine;
     2654                } else if (strncmp(cp, "undef", 5) == 0) {
     2655                    char *cp2;
     2656                    for (cp += 5; isspace((unsigned char) *cp); cp++) {
     2657                        continue;
     2658                    }
     2659
     2660                    for (cp2 = cp; !isspace((unsigned char) *cp2) &&
     2661                                   (*cp2 != '\0'); cp2++) {
     2662                        continue;
     2663                    }
     2664
     2665                    *cp2 = '\0';
     2666
     2667                    Var_Delete(cp, VAR_GLOBAL);
     2668                    goto nextLine;
     2669                }
     2670            }
    26702671
    26712672            #ifdef USE_INLINEFILES
     
    27052706                    /*Lst_AtEnd(targCmds, (ClientData) line); */
    27062707                }
    2707                 goto nextLine;
     2708                goto nextLine;
    27082709            }
    27092710            #endif
    27102711
    2711             if (*line == '#') {
    2712                 /* If we're this far, the line must be a comment. */
    2713                 goto nextLine;
    2714             }
    2715 
    2716             if (*line == '\t') {
    2717                 /*
    2718                 * If a line starts with a tab, it can only hope to be
    2719                 * a creation command.
    2720                 */
     2712            if (*line == '#') {
     2713                /* If we're this far, the line must be a comment. */
     2714                goto nextLine;
     2715            }
     2716
     2717            if (*line == '\t') {
     2718                /*
     2719                * If a line starts with a tab, it can only hope to be
     2720                * a creation command.
     2721                */
    27212722#if !defined(POSIX) || defined(USE_NO_STUPID_TABS)
    2722             shellCommand:
    2723 #endif
    2724                 for (cp = line + 1; isspace (*cp); cp++) {
    2725                     continue;
    2726                 }
    2727                 if (*cp) {
    2728                     if (inLine) {
     2723            shellCommand:
     2724#endif
     2725                for (cp = line + 1; isspace (*cp); cp++) {
     2726                    continue;
     2727                }
     2728                if (*cp) {
     2729                    if (inLine) {
    27292730                        #ifdef USE_INLINEFILES
    27302731                        if (ParseCmdIsComponent(cp, "<<"))
     
    27362737                        }
    27372738                        #endif
    2738                         /*
    2739                         * So long as it's not a blank line and we're actually
    2740                         * in a dependency spec, add the command to the list of
    2741                         * commands of all targets in the dependency spec
    2742                         */
    2743                         Lst_ForEach (targets, ParseAddCmd, cp);
    2744                         /*Lst_AtEnd(targCmds, (ClientData) line);*/
    2745                         continue;
    2746                     } else {
    2747                         Parse_Error (PARSE_FATAL,
    2748                                      "Unassociated shell command \"%s\"",
    2749                                      cp);
    2750                     }
    2751                 }
     2739                        /*
     2740                        * So long as it's not a blank line and we're actually
     2741                        * in a dependency spec, add the command to the list of
     2742                        * commands of all targets in the dependency spec
     2743                        */
     2744                        Lst_ForEach (targets, ParseAddCmd, cp);
     2745                        /*Lst_AtEnd(targCmds, (ClientData) line);*/
     2746                        continue;
     2747                    } else {
     2748                        Parse_Error (PARSE_FATAL,
     2749                                     "Unassociated shell command \"%s\"",
     2750                                     cp);
     2751                    }
     2752                }
    27522753#ifdef SYSVINCLUDE
    2753             } else if (strncmp (line, "include", 7) == 0 &&
    2754                        isspace((unsigned char) line[7]) &&
    2755                        strchr(line, ':') == NULL) {
    2756                 /*
    2757                 * It's an S3/S5-style "include".
    2758                 */
    2759                 ParseTraditionalInclude (line + 7);
    2760                 goto nextLine;
    2761 #endif
    2762             } else if (Parse_IsVar (line)) {
    2763                 ParseFinishLine();
    2764                 Parse_DoVar (line, VAR_GLOBAL);
    2765             } else {
    2766                 /*
    2767                 * We now know it's a dependency line so it needs to have all
    2768                 * variables expanded before being parsed. Tell the variable
    2769                 * module to complain if some variable is undefined...
    2770                 * To make life easier on novices, if the line is indented we
    2771                 * first make sure the line has a dependency operator in it.
    2772                 * If it doesn't have an operator and we're in a dependency
    2773                 * line's script, we assume it's actually a shell command
    2774                 * and add it to the current list of targets.
    2775                 */
     2754            } else if (strncmp (line, "include", 7) == 0 &&
     2755                       isspace((unsigned char) line[7]) &&
     2756                       strchr(line, ':') == NULL) {
     2757                /*
     2758                * It's an S3/S5-style "include".
     2759                */
     2760                ParseTraditionalInclude (line + 7);
     2761                goto nextLine;
     2762#endif
     2763            } else if (Parse_IsVar (line)) {
     2764                ParseFinishLine();
     2765                Parse_DoVar (line, VAR_GLOBAL);
     2766            } else {
     2767                /*
     2768                * We now know it's a dependency line so it needs to have all
     2769                * variables expanded before being parsed. Tell the variable
     2770                * module to complain if some variable is undefined...
     2771                * To make life easier on novices, if the line is indented we
     2772                * first make sure the line has a dependency operator in it.
     2773                * If it doesn't have an operator and we're in a dependency
     2774                * line's script, we assume it's actually a shell command
     2775                * and add it to the current list of targets.
     2776                */
    27762777#if !defined(POSIX) || defined(USE_NO_STUPID_TABS)
    2777                 Boolean nonSpace = FALSE;
    2778 #endif
    2779 
    2780                 cp = line;
    2781                 if (isspace((unsigned char) line[0])) {
    2782                     while ((*cp != '\0') && isspace((unsigned char) *cp)) {
    2783                         cp++;
    2784                     }
    2785                     if (*cp == '\0') {
    2786                         goto nextLine;
    2787                     }
     2778                Boolean nonSpace = FALSE;
     2779#endif
     2780
     2781                cp = line;
     2782                if (isspace((unsigned char) line[0])) {
     2783                    while ((*cp != '\0') && isspace((unsigned char) *cp)) {
     2784                        cp++;
     2785                    }
     2786                    if (*cp == '\0') {
     2787                        goto nextLine;
     2788                    }
    27882789#if !defined(POSIX) || defined(USE_NO_STUPID_TABS)
    2789                     while ((*cp != ':') && (*cp != '!') && (*cp != '\0')) {
    2790                         nonSpace = TRUE;
    2791                         cp++;
    2792                     }
    2793 #endif
    2794                 }
     2790                    while ((*cp != ':') && (*cp != '!') && (*cp != '\0')) {
     2791                        nonSpace = TRUE;
     2792                        cp++;
     2793                    }
     2794#endif
     2795                }
    27952796
    27962797#if !defined(POSIX) || defined(USE_NO_STUPID_TABS)
    2797                 if (*cp == '\0') {
    2798                     if (inLine) {
     2798                if (*cp == '\0') {
     2799                    if (inLine) {
    27992800#if !defined(USE_NO_STUPID_TABS)
    2800                         Parse_Error (PARSE_WARNING,
    2801                                      "Shell command needs a leading tab");
    2802 #endif
    2803                         goto shellCommand;
    2804                     } else if (nonSpace) {
    2805                         Parse_Error (PARSE_FATAL, "Missing operator");
    2806                     }
    2807                 } else {
    2808 #endif
    2809                     ParseFinishLine();
    2810 
    2811                     cp = Var_Subst (NULL, line, VAR_CMD, TRUE);
    2812                     efree (line);
    2813                     line = cp;
    2814 
    2815                     /*
    2816                      * Need a non-circular list for the target nodes
    2817                      */
    2818                     if (targets)
    2819                         Lst_Destroy(targets, NOFREE);
    2820 
    2821                     targets = Lst_Init (FALSE);
    2822                     inLine = TRUE;
    2823 
    2824                     ParseDoDependency (line);
     2801                        Parse_Error (PARSE_WARNING,
     2802                                     "Shell command needs a leading tab");
     2803#endif
     2804                        goto shellCommand;
     2805                    } else if (nonSpace) {
     2806                        Parse_Error (PARSE_FATAL, "Missing operator");
     2807                    }
     2808                } else {
     2809#endif
     2810                    ParseFinishLine();
     2811
     2812                    cp = Var_Subst (NULL, line, VAR_CMD, TRUE);
     2813                    efree (line);
     2814                    line = cp;
     2815
     2816                    /*
     2817                     * Need a non-circular list for the target nodes
     2818                     */
     2819                    if (targets)
     2820                        Lst_Destroy(targets, NOFREE);
     2821
     2822                    targets = Lst_Init (FALSE);
     2823                    inLine = TRUE;
     2824
     2825                    ParseDoDependency (line);
    28252826#if !defined(POSIX) || defined(USE_NO_STUPID_TABS)
    2826                 }
    2827 #endif
    2828             }
    2829 
    2830             nextLine:
    2831 
    2832             efree (line);
    2833         }
    2834         /*
    2835         * Reached EOF, but it may be just EOF of an include file...
    2836         */
     2827                }
     2828#endif
     2829            }
     2830
     2831            nextLine:
     2832
     2833            efree (line);
     2834        }
     2835        /*
     2836        * Reached EOF, but it may be just EOF of an include file...
     2837        */
    28372838    } while (ParseEOF(1) == CONTINUE);
    28382839
     
    28432844
    28442845    if (fatals)
    2845         errx(1, "fatal errors encountered -- cannot continue");
     2846        errx(1, "fatal errors encountered -- cannot continue");
    28462847}
    28472848
     
    28492850 *---------------------------------------------------------------------
    28502851 * Parse_Init --
    2851  *      initialize the parsing module
     2852 *      initialize the parsing module
    28522853 *
    28532854 * Results:
    2854  *      none
     2855 *      none
    28552856 *
    28562857 * Side Effects:
    2857  *      the parseIncPath list is initialized...
     2858 *      the parseIncPath list is initialized...
    28582859 *---------------------------------------------------------------------
    28592860 */
     
    28732874    /*Lst_Destroy(targCmds, (void (*) __P((ClientData))) efree);*/
    28742875    if (targets)
    2875         Lst_Destroy(targets, NOFREE);
     2876        Lst_Destroy(targets, NOFREE);
    28762877    Lst_Destroy(sysIncPath, Dir_Destroy);
    28772878    Lst_Destroy(parseIncPath, Dir_Destroy);
    2878     Lst_Destroy(includes, NOFREE);      /* Should be empty now */
     2879    Lst_Destroy(includes, NOFREE);      /* Should be empty now */
    28792880}
    28802881
     
    28832884 *-----------------------------------------------------------------------
    28842885 * Parse_MainName --
    2885  *      Return a Lst of the main target to create for main()'s sake. If
    2886  *      no such target exists, we Punt with an obnoxious error message.
     2886 *      Return a Lst of the main target to create for main()'s sake. If
     2887 *      no such target exists, we Punt with an obnoxious error message.
    28872888 *
    28882889 * Results:
    2889  *      A Lst of the single node to create.
     2890 *      A Lst of the single node to create.
    28902891 *
    28912892 * Side Effects:
    2892  *      None.
     2893 *      None.
    28932894 *
    28942895 *-----------------------------------------------------------------------
     
    28972898Parse_MainName()
    28982899{
    2899     Lst           listmain;     /* result list */
     2900    Lst           listmain;     /* result list */
    29002901
    29012902    listmain = Lst_Init (FALSE);
    29022903
    29032904    if (mainNode == NILGNODE) {
    2904         Punt ("no target to make.");
    2905         /*NOTREACHED*/
     2905        Punt ("no target to make.");
     2906        /*NOTREACHED*/
    29062907    } else if (mainNode->type & OP_DOUBLEDEP) {
    2907         (void) Lst_AtEnd (listmain, (ClientData)mainNode);
    2908         Lst_Concat(listmain, mainNode->cohorts, LST_CONCNEW);
     2908        (void) Lst_AtEnd (listmain, (ClientData)mainNode);
     2909        Lst_Concat(listmain, mainNode->cohorts, LST_CONCNEW);
    29092910    }
    29102911    else
    2911         (void) Lst_AtEnd (listmain, (ClientData)mainNode);
     2912        (void) Lst_AtEnd (listmain, (ClientData)mainNode);
    29122913    return (listmain);
    29132914}
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette