home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / make / parse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-18  |  59.0 KB  |  2,213 lines

  1. /*
  2.  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
  3.  * Copyright (c) 1988, 1989 by Adam de Boor
  4.  * Copyright (c) 1989 by Berkeley Softworks
  5.  * All rights reserved.
  6.  *
  7.  * This code is derived from software contributed to Berkeley by
  8.  * Adam de Boor.
  9.  *
  10.  * Redistribution and use in source and binary forms, with or without
  11.  * modification, are permitted provided that the following conditions
  12.  * are met:
  13.  * 1. Redistributions of source code must retain the above copyright
  14.  *    notice, this list of conditions and the following disclaimer.
  15.  * 2. Redistributions in binary form must reproduce the above copyright
  16.  *    notice, this list of conditions and the following disclaimer in the
  17.  *    documentation and/or other materials provided with the distribution.
  18.  * 3. All advertising materials mentioning features or use of this software
  19.  *    must display the following acknowledgement:
  20.  *    This product includes software developed by the University of
  21.  *    California, Berkeley and its contributors.
  22.  * 4. Neither the name of the University nor the names of its contributors
  23.  *    may be used to endorse or promote products derived from this software
  24.  *    without specific prior written permission.
  25.  *
  26.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  27.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  30.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  31.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  32.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  33.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  34.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  35.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  36.  * SUCH DAMAGE.
  37.  */
  38.  
  39. #ifndef lint
  40. static char sccsid[] = "@(#)parse.c    5.18 (Berkeley) 2/19/91";
  41. #endif /* not lint */
  42.  
  43. /*-
  44.  * parse.c --
  45.  *    Functions to parse a makefile.
  46.  *
  47.  *    One function, Parse_Init, must be called before any functions
  48.  *    in this module are used. After that, the function Parse_File is the
  49.  *    main entry point and controls most of the other functions in this
  50.  *    module.
  51.  *
  52.  *    Most important structures are kept in Lsts. Directories for
  53.  *    the #include "..." function are kept in the 'parseIncPath' Lst, while
  54.  *    those for the #include <...> are kept in the 'sysIncPath' Lst. The
  55.  *    targets currently being defined are kept in the 'targets' Lst.
  56.  *
  57.  *    The variables 'fname' and 'lineno' are used to track the name
  58.  *    of the current file and the line number in that file so that error
  59.  *    messages can be more meaningful.
  60.  *
  61.  * Interface:
  62.  *    Parse_Init                Initialization function which must be
  63.  *                              called before anything else in this module
  64.  *                              is used.
  65.  *
  66.  *    Parse_File                Function used to parse a makefile. It must
  67.  *                              be given the name of the file, which should
  68.  *                              already have been opened, and a function
  69.  *                              to call to read a character from the file.
  70.  *
  71.  *    Parse_IsVar                Returns TRUE if the given line is a
  72.  *                              variable assignment. Used by MainParseArgs
  73.  *                              to determine if an argument is a target
  74.  *                              or a variable assignment. Used internally
  75.  *                              for pretty much the same thing...
  76.  *
  77.  *    Parse_Error                Function called when an error occurs in
  78.  *                              parsing. Used by the variable and
  79.  *                              conditional modules.
  80.  *    Parse_MainName                Returns a Lst of the main target to create.
  81.  */
  82.  
  83. #include <varargs.h>
  84. #include <stdio.h>
  85. #include <ctype.h>
  86. #include "make.h"
  87. #include "buf.h"
  88. #include "pathnames.h"
  89.  
  90. /*
  91.  * These values are returned by ParseEOF to tell Parse_File whether to
  92.  * CONTINUE parsing, i.e. it had only reached the end of an include file,
  93.  * or if it's DONE.
  94.  */
  95. #define    CONTINUE    1
  96. #define    DONE        0
  97. static int         ParseEOF();
  98.  
  99. static Lst             targets;    /* targets we're working on */
  100. static Boolean        inLine;    /* true if currently in a dependency
  101.                  * line or its commands */
  102.  
  103. static char            *fname;    /* name of current file (for errors) */
  104. static int          lineno;    /* line number in current file */
  105. static FILE           *curFILE;     /* current makefile */
  106.  
  107. static int        fatals = 0;
  108.  
  109. static GNode        *mainNode;    /* The main target to create. This is the
  110.                  * first target on the first dependency
  111.                  * line in the first makefile */
  112. /*
  113.  * Definitions for handling #include specifications
  114.  */
  115. typedef struct IFile {
  116.     char           *fname;        /* name of previous file */
  117.     int             lineno;        /* saved line number */
  118.     FILE *       F;            /* the open stream */
  119. }                    IFile;
  120.  
  121. static Lst      includes;      /* stack of IFiles generated by
  122.                  * #includes */
  123. Lst             parseIncPath;    /* list of directories for "..." includes */
  124. Lst             sysIncPath;    /* list of directories for <...> includes */
  125.  
  126. /*-
  127.  * specType contains the SPECial TYPE of the current target. It is
  128.  * Not if the target is unspecial. If it *is* special, however, the children
  129.  * are linked as children of the parent but not vice versa. This variable is
  130.  * set in ParseDoDependency
  131.  */
  132. typedef enum {
  133.     Begin,          /* .BEGIN */
  134.     Default,        /* .DEFAULT */
  135.     End,            /* .END */
  136.     Ignore,        /* .IGNORE */
  137.     Includes,        /* .INCLUDES */
  138.     Interrupt,        /* .INTERRUPT */
  139.     Libs,        /* .LIBS */
  140.     MFlags,        /* .MFLAGS or .MAKEFLAGS */
  141.     Main,        /* .MAIN and we don't have anything user-specified to
  142.              * make */
  143.     Not,        /* Not special */
  144.     NotParallel,    /* .NOTPARALELL */
  145.     Null,           /* .NULL */
  146.     Order,          /* .ORDER */
  147.     Path,        /* .PATH */
  148.     Precious,        /* .PRECIOUS */
  149.     Shell,        /* .SHELL */
  150.     Silent,        /* .SILENT */
  151.     SingleShell,    /* .SINGLESHELL */
  152.     Suffixes,        /* .SUFFIXES */
  153.     Attribute,        /* Generic attribute */
  154. } ParseSpecial;
  155.  
  156. ParseSpecial specType;
  157.  
  158. /*
  159.  * Predecessor node for handling .ORDER. Initialized to NILGNODE when .ORDER
  160.  * seen, then set to each successive source on the line.
  161.  */
  162. static GNode    *predecessor;
  163.  
  164. /*
  165.  * The parseKeywords table is searched using binary search when deciding
  166.  * if a target or source is special. The 'spec' field is the ParseSpecial
  167.  * type of the keyword ("Not" if the keyword isn't special as a target) while
  168.  * the 'op' field is the operator to apply to the list of targets if the
  169.  * keyword is used as a source ("0" if the keyword isn't special as a source)
  170.  */
  171. static struct {
  172.     char          *name;        /* Name of keyword */
  173.     ParseSpecial  spec;            /* Type when used as a target */
  174.     int              op;            /* Operator when used as a source */
  175. } parseKeywords[] = {
  176. { ".BEGIN",       Begin,        0 },
  177. { ".DEFAULT",      Default,      0 },
  178. { ".OPTIONAL",      Attribute,       OP_OPTIONAL },
  179. { ".END",         End,            0 },
  180. { ".EXEC",      Attribute,       OP_EXEC },
  181. { ".IGNORE",      Ignore,       OP_IGNORE },
  182. { ".INCLUDES",      Includes,     0 },
  183. { ".INTERRUPT",      Interrupt,    0 },
  184. { ".INVISIBLE",      Attribute,       OP_INVISIBLE },
  185. { ".JOIN",        Attribute,       OP_JOIN },
  186. { ".LIBS",        Libs,            0 },
  187. { ".MAIN",      Main,        0 },
  188. { ".MAKE",        Attribute,       OP_MAKE },
  189. { ".MAKEFLAGS",      MFlags,       0 },
  190. { ".MFLAGS",      MFlags,       0 },
  191. { ".NOTMAIN",      Attribute,       OP_NOTMAIN },
  192. { ".NOTPARALLEL", NotParallel,    0 },
  193. { ".NULL",        Null,            0 },
  194. { ".ORDER",       Order,        0 },
  195. { ".PATH",      Path,        0 },
  196. { ".PRECIOUS",      Precious,     OP_PRECIOUS },
  197. { ".RECURSIVE",      Attribute,    OP_MAKE },
  198. { ".SHELL",       Shell,        0 },
  199. { ".SILENT",      Silent,       OP_SILENT },
  200. { ".SINGLESHELL", SingleShell,    0 },
  201. { ".SUFFIXES",      Suffixes,     0 },
  202. { ".USE",         Attribute,       OP_USE },
  203. };
  204.  
  205. /*-
  206.  *----------------------------------------------------------------------
  207.  * ParseFindKeyword --
  208.  *    Look in the table of keywords for one matching the given string.
  209.  *
  210.  * Results:
  211.  *    The index of the keyword, or -1 if it isn't there.
  212.  *
  213.  * Side Effects:
  214.  *    None
  215.  *----------------------------------------------------------------------
  216.  */
  217. static int
  218. ParseFindKeyword (str)
  219.     char        *str;        /* String to find */
  220. {
  221.     register int    start,
  222.             end,
  223.             cur;
  224.     register int    diff;
  225.     
  226.     start = 0;
  227.     end = (sizeof(parseKeywords)/sizeof(parseKeywords[0])) - 1;
  228.  
  229.     do {
  230.     cur = start + ((end - start) / 2);
  231.     diff = strcmp (str, parseKeywords[cur].name);
  232.  
  233.     if (diff == 0) {
  234.         return (cur);
  235.     } else if (diff < 0) {
  236.         end = cur - 1;
  237.     } else {
  238.         start = cur + 1;
  239.     }
  240.     } while (start <= end);
  241.     return (-1);
  242. }
  243.  
  244. /*-
  245.  * Parse_Error  --
  246.  *    Error message abort function for parsing. Prints out the context
  247.  *    of the error (line number and file) as well as the message with
  248.  *    two optional arguments.
  249.  *
  250.  * Results:
  251.  *    None
  252.  *
  253.  * Side Effects:
  254.  *    "fatals" is incremented if the level is PARSE_FATAL.
  255.  */
  256. /* VARARGS */
  257. void
  258. Parse_Error(type, va_alist)
  259.     int type;        /* Error type (PARSE_WARNING, PARSE_FATAL) */
  260.     va_dcl
  261. {
  262.     va_list ap;
  263.     char *fmt;
  264.  
  265.     (void)fprintf(stderr, "\"%s\", line %d: ", fname, lineno);
  266.     if (type == PARSE_WARNING)
  267.         (void)fprintf(stderr, "warning: ");
  268.     va_start(ap);
  269.     fmt = va_arg(ap, char *);
  270.     (void)vfprintf(stderr, fmt, ap);
  271.     va_end(ap);
  272.     (void)fprintf(stderr, "\n");
  273.     (void)fflush(stderr);
  274.     if (type == PARSE_FATAL)
  275.         fatals += 1;
  276. }
  277.  
  278. /*-
  279.  *---------------------------------------------------------------------
  280.  * ParseLinkSrc  --
  281.  *    Link the parent node to its new child. Used in a Lst_ForEach by
  282.  *    ParseDoDependency. If the specType isn't 'Not', the parent
  283.  *    isn't linked as a parent of the child.
  284.  *
  285.  * Results:
  286.  *    Always = 0
  287.  *
  288.  * Side Effects:
  289.  *    New elements are added to the parents list of cgn and the
  290.  *    children list of cgn. the unmade field of pgn is updated
  291.  *    to reflect the additional child.
  292.  *---------------------------------------------------------------------
  293.  */
  294. static int
  295. ParseLinkSrc (pgn, cgn)
  296.     GNode          *pgn;    /* The parent node */
  297.     GNode          *cgn;    /* The child node */
  298. {
  299.     if (Lst_Member (pgn->children, (ClientData)cgn) == NILLNODE) {
  300.     (void)Lst_AtEnd (pgn->children, (ClientData)cgn);
  301.     if (specType == Not) {
  302.         (void)Lst_AtEnd (cgn->parents, (ClientData)pgn);
  303.     }
  304.     pgn->unmade += 1;
  305.     }
  306.     return (0);
  307. }
  308.  
  309. /*-
  310.  *---------------------------------------------------------------------
  311.  * ParseDoOp  --
  312.  *    Apply the parsed operator to the given target node. Used in a
  313.  *    Lst_ForEach call by ParseDoDependency once all targets have
  314.  *    been found and their operator parsed. If the previous and new
  315.  *    operators are incompatible, a major error is taken.
  316.  *
  317.  * Results:
  318.  *    Always 0
  319.  *
  320.  * Side Effects:
  321.  *    The type field of the node is altered to reflect any new bits in
  322.  *    the op.
  323.  *---------------------------------------------------------------------
  324.  */
  325. static int
  326. ParseDoOp (gn, op)
  327.     GNode          *gn;        /* The node to which the operator is to be
  328.                  * applied */
  329.     int             op;        /* The operator to apply */
  330. {
  331.     /*
  332.      * If the dependency mask of the operator and the node don't match and
  333.      * the node has actually had an operator applied to it before, and
  334.      * the operator actually has some dependency information in it, complain. 
  335.      */
  336.     if (((op & OP_OPMASK) != (gn->type & OP_OPMASK)) &&
  337.     !OP_NOP(gn->type) && !OP_NOP(op))
  338.     {
  339.     Parse_Error (PARSE_FATAL, "Inconsistent operator for %s", gn->name);
  340.     return (1);
  341.     }
  342.  
  343.     if ((op == OP_DOUBLEDEP) && ((gn->type & OP_OPMASK) == OP_DOUBLEDEP)) {
  344.     /*
  345.      * If the node was the object of a :: operator, we need to create a
  346.      * new instance of it for the children and commands on this dependency
  347.      * line. The new instance is placed on the 'cohorts' list of the
  348.      * initial one (note the initial one is not on its own cohorts list)
  349.      * and the new instance is linked to all parents of the initial
  350.      * instance.
  351.      */
  352.     register GNode    *cohort;
  353.     LstNode            ln;
  354.             
  355.     cohort = Targ_NewGN(gn->name);
  356.     /*
  357.      * Duplicate links to parents so graph traversal is simple. Perhaps
  358.      * some type bits should be duplicated?
  359.      *
  360.      * Make the cohort invisible as well to avoid duplicating it into
  361.      * other variables. True, parents of this target won't tend to do
  362.      * anything with their local variables, but better safe than
  363.      * sorry.
  364.      */
  365.     Lst_ForEach(gn->parents, ParseLinkSrc, (ClientData)cohort);
  366.     cohort->type = OP_DOUBLEDEP|OP_INVISIBLE;
  367.     (void)Lst_AtEnd(gn->cohorts, (ClientData)cohort);
  368.  
  369.     /*
  370.      * Replace the node in the targets list with the new copy
  371.      */
  372.     ln = Lst_Member(targets, (ClientData)gn);
  373.     Lst_Replace(ln, (ClientData)cohort);
  374.     gn = cohort;
  375.     }
  376.     /*
  377.      * We don't want to nuke any previous flags (whatever they were) so we
  378.      * just OR the new operator into the old 
  379.      */
  380.     gn->type |= op;
  381.  
  382.     return (0);
  383. }
  384.  
  385. /*-
  386.  *---------------------------------------------------------------------
  387.  * ParseDoSrc  --
  388.  *    Given the name of a source, figure out if it is an attribute
  389.  *    and apply it to the targets if it is. Else decide if there is
  390.  *    some attribute which should be applied *to* the source because
  391.  *    of some special target and apply it if so. Otherwise, make the
  392.  *    source be a child of the targets in the list 'targets'
  393.  *
  394.  * Results:
  395.  *    None
  396.  *
  397.  * Side Effects:
  398.  *    Operator bits may be added to the list of targets or to the source.
  399.  *    The targets may have a new source added to their lists of children.
  400.  *---------------------------------------------------------------------
  401.  */
  402. static void
  403. ParseDoSrc (tOp, src)
  404.     int        tOp;    /* operator (if any) from special targets */
  405.     char    *src;    /* name of the source to handle */
  406. {
  407.     int        op;    /* operator (if any) from special source */
  408.     GNode    *gn;
  409.  
  410.     op = 0;
  411.     if (*src == '.' && isupper (src[1])) {
  412.     int keywd = ParseFindKeyword(src);
  413.     if (keywd != -1) {
  414.         op = parseKeywords[keywd].op;
  415.     }
  416.     }
  417.     if (op != 0) {
  418.     Lst_ForEach (targets, ParseDoOp, (ClientData)op);
  419.     } else if (specType == Main) {
  420.     /*
  421.      * If we have noted the existence of a .MAIN, it means we need
  422.      * to add the sources of said target to the list of things
  423.      * to create. The string 'src' is likely to be free, so we
  424.      * must make a new copy of it. Note that this will only be
  425.      * invoked if the user didn't specify a target on the command
  426.      * line. This is to allow #ifmake's to succeed, or something...
  427.      */
  428.     (void) Lst_AtEnd (create, (ClientData)strdup(src));
  429.     /*
  430.      * Add the name to the .TARGETS variable as well, so the user cna
  431.      * employ that, if desired.
  432.      */
  433.     Var_Append(".TARGETS", src, VAR_GLOBAL);
  434.     } else if (specType == Order) {
  435.     /*
  436.      * Create proper predecessor/successor links between the previous
  437.      * source and the current one.
  438.      */
  439.     gn = Targ_FindNode(src, TARG_CREATE);
  440.     if (predecessor != NILGNODE) {
  441.         (void)Lst_AtEnd(predecessor->successors, (ClientData)gn);
  442.         (void)Lst_AtEnd(gn->preds, (ClientData)predecessor);
  443.     }
  444.     /*
  445.      * The current source now becomes the predecessor for the next one.
  446.      */
  447.     predecessor = gn;
  448.     } else {
  449.     /*
  450.      * If the source is not an attribute, we need to find/create
  451.      * a node for it. After that we can apply any operator to it
  452.      * from a special target or link it to its parents, as
  453.      * appropriate.
  454.      *
  455.      * In the case of a source that was the object of a :: operator,
  456.      * the attribute is applied to all of its instances (as kept in
  457.      * the 'cohorts' list of the node) or all the cohorts are linked
  458.      * to all the targets.
  459.      */
  460.     gn = Targ_FindNode (src, TARG_CREATE);
  461.     if (tOp) {
  462.         gn->type |= tOp;
  463.     } else {
  464.         Lst_ForEach (targets, ParseLinkSrc, (ClientData)gn);
  465.     }
  466.     if ((gn->type & OP_OPMASK) == OP_DOUBLEDEP) {
  467.         register GNode      *cohort;
  468.         register LstNode    ln;
  469.  
  470.         for (ln=Lst_First(gn->cohorts); ln != NILLNODE; ln = Lst_Succ(ln)){
  471.         cohort = (GNode *)Lst_Datum(ln);
  472.         if (tOp) {
  473.             cohort->type |= tOp;
  474.         } else {
  475.             Lst_ForEach(targets, ParseLinkSrc, (ClientData)cohort);
  476.         }
  477.         }
  478.     }
  479.     }
  480. }
  481.  
  482. /*-
  483.  *-----------------------------------------------------------------------
  484.  * ParseFindMain --
  485.  *    Find a real target in the list and set it to be the main one.
  486.  *    Called by ParseDoDependency when a main target hasn't been found
  487.  *    yet.
  488.  *
  489.  * Results:
  490.  *    0 if main not found yet, 1 if it is.
  491.  *
  492.  * Side Effects:
  493.  *    mainNode is changed and Targ_SetMain is called.
  494.  *
  495.  *-----------------------------------------------------------------------
  496.  */
  497. static int
  498. ParseFindMain(gn)
  499.     GNode         *gn;        /* Node to examine */
  500. {
  501.     if ((gn->type & (OP_NOTMAIN|OP_USE|OP_EXEC|OP_TRANSFORM)) == 0) {
  502.     mainNode = gn;
  503.     Targ_SetMain(gn);
  504.     return (1);
  505.     } else {
  506.     return (0);
  507.     }
  508. }
  509.  
  510. /*-
  511.  *-----------------------------------------------------------------------
  512.  * ParseAddDir --
  513.  *    Front-end for Dir_AddDir to make sure Lst_ForEach keeps going
  514.  *
  515.  * Results:
  516.  *    === 0
  517.  *
  518.  * Side Effects:
  519.  *    See Dir_AddDir.
  520.  *
  521.  *-----------------------------------------------------------------------
  522.  */
  523. static int
  524. ParseAddDir(path, name)
  525.     Lst        path;
  526.     char    *name;
  527. {
  528.     Dir_AddDir(path, name);
  529.     return(0);
  530. }
  531.  
  532. /*-
  533.  *-----------------------------------------------------------------------
  534.  * ParseClearPath --
  535.  *    Front-end for Dir_ClearPath to make sure Lst_ForEach keeps going
  536.  *
  537.  * Results:
  538.  *    === 0
  539.  *
  540.  * Side Effects:
  541.  *    See Dir_ClearPath
  542.  *
  543.  *-----------------------------------------------------------------------
  544.  */
  545. static int
  546. ParseClearPath(path)
  547.     Lst        path;
  548. {
  549.     Dir_ClearPath(path);
  550.     return(0);
  551. }
  552.  
  553. /*-
  554.  *---------------------------------------------------------------------
  555.  * ParseDoDependency  --
  556.  *    Parse the dependency line in line.
  557.  *
  558.  * Results:
  559.  *    None
  560.  *
  561.  * Side Effects:
  562.  *    The nodes of the sources are linked as children to the nodes of the
  563.  *    targets. Some nodes may be created.
  564.  *
  565.  *    We parse a dependency line by first extracting words from the line and
  566.  * finding nodes in the list of all targets with that name. This is done
  567.  * until a character is encountered which is an operator character. Currently
  568.  * these are only ! and :. At this point the operator is parsed and the
  569.  * pointer into the line advanced until the first source is encountered.
  570.  *     The parsed operator is applied to each node in the 'targets' list,
  571.  * which is where the nodes found for the targets are kept, by means of
  572.  * the ParseDoOp function.
  573.  *    The sources are read in much the same way as the targets were except
  574.  * that now they are expanded using the wildcarding scheme of the C-Shell
  575.  * and all instances of the resulting words in the list of all targets
  576.  * are found. Each of the resulting nodes is then linked to each of the
  577.  * targets as one of its children.
  578.  *    Certain targets are handled specially. These are the ones detailed
  579.  * by the specType variable.
  580.  *    The storing of transformation rules is also taken care of here.
  581.  * A target is recognized as a transformation rule by calling
  582.  * Suff_IsTransform. If it is a transformation rule, its node is gotten
  583.  * from the suffix module via Suff_AddTransform rather than the standard
  584.  * Targ_FindNode in the target module.
  585.  *---------------------------------------------------------------------
  586.  */
  587. static void
  588. ParseDoDependency (line)
  589.     char           *line;    /* the line to parse */
  590. {
  591.     register char  *cp;        /* our current position */
  592.     register GNode *gn;        /* a general purpose temporary node */
  593.     register int    op;        /* the operator on the line */
  594.     char            savec;    /* a place to save a character */
  595.     Lst            paths;       /* List of search paths to alter when parsing
  596.                  * a list of .PATH targets */
  597.     int                tOp;        /* operator from special target */
  598.     Lst                sources;    /* list of source names after expansion */
  599.     Lst         curTargs;    /* list of target names to be found and added
  600.                  * to the targets list */
  601.  
  602.     tOp = 0;
  603.  
  604.     specType = Not;
  605.     paths = (Lst)NULL;
  606.  
  607.     curTargs = Lst_Init(FALSE);
  608.     
  609.     do {
  610.     for (cp = line;
  611.          *cp && !isspace (*cp) &&
  612.          (*cp != '!') && (*cp != ':') && (*cp != '(');
  613.          cp++)
  614.     {
  615.         if (*cp == '$') {
  616.         /*
  617.          * Must be a dynamic source (would have been expanded
  618.          * otherwise), so call the Var module to parse the puppy
  619.          * so we can safely advance beyond it...There should be
  620.          * no errors in this, as they would have been discovered
  621.          * in the initial Var_Subst and we wouldn't be here.
  622.          */
  623.         int     length;
  624.         Boolean    freeIt;
  625.         char    *result;
  626.  
  627.         result=Var_Parse(cp, VAR_CMD, TRUE, &length, &freeIt);
  628.  
  629.         if (freeIt) {
  630.             free(result);
  631.         }
  632.         cp += length-1;
  633.         }
  634.         continue;
  635.     }
  636.     if (*cp == '(') {
  637.         /*
  638.          * Archives must be handled specially to make sure the OP_ARCHV
  639.          * flag is set in their 'type' field, for one thing, and because
  640.          * things like "archive(file1.o file2.o file3.o)" are permissible.
  641.          * Arch_ParseArchive will set 'line' to be the first non-blank
  642.          * after the archive-spec. It creates/finds nodes for the members
  643.          * and places them on the given list, returning SUCCESS if all
  644.          * went well and FAILURE if there was an error in the
  645.          * specification. On error, line should remain untouched.
  646.          */
  647.         if (Arch_ParseArchive (&line, targets, VAR_CMD) != SUCCESS) {
  648.         Parse_Error (PARSE_FATAL,
  649.                  "Error in archive specification: \"%s\"", line);
  650.         return;
  651.         } else {
  652.         continue;
  653.         }
  654.     }
  655.     savec = *cp;
  656.     
  657.     if (!*cp) {
  658.         /*
  659.          * Ending a dependency line without an operator is a Bozo
  660.          * no-no 
  661.          */
  662.         Parse_Error (PARSE_FATAL, "Need an operator");
  663.         return;
  664.     }
  665.     *cp = '\0';
  666.     /*
  667.      * Have a word in line. See if it's a special target and set
  668.      * specType to match it.
  669.      */
  670.     if (*line == '.' && isupper (line[1])) {
  671.         /*
  672.          * See if the target is a special target that must have it
  673.          * or its sources handled specially. 
  674.          */
  675.         int keywd = ParseFindKeyword(line);
  676.         if (keywd != -1) {
  677.         if (specType == Path && parseKeywords[keywd].spec != Path) {
  678.             Parse_Error(PARSE_FATAL, "Mismatched special targets");
  679.             return;
  680.         }
  681.         
  682.         specType = parseKeywords[keywd].spec;
  683.         tOp = parseKeywords[keywd].op;
  684.  
  685.         /*
  686.          * Certain special targets have special semantics:
  687.          *    .PATH        Have to set the dirSearchPath
  688.          *            variable too
  689.          *    .MAIN        Its sources are only used if
  690.          *            nothing has been specified to
  691.          *            create.
  692.          *    .DEFAULT        Need to create a node to hang
  693.          *            commands on, but we don't want
  694.          *            it in the graph, nor do we want
  695.          *            it to be the Main Target, so we
  696.          *            create it, set OP_NOTMAIN and
  697.          *            add it to the list, setting
  698.          *            DEFAULT to the new node for
  699.          *            later use. We claim the node is
  700.          *                    A transformation rule to make
  701.          *                    life easier later, when we'll
  702.          *                    use Make_HandleUse to actually
  703.          *                    apply the .DEFAULT commands.
  704.          *    .BEGIN
  705.          *    .END
  706.          *    .INTERRUPT      Are not to be considered the
  707.          *            main target.
  708.          *      .NOTPARALLEL    Make only one target at a time.
  709.          *      .SINGLESHELL    Create a shell for each command.
  710.          *      .ORDER            Must set initial predecessor to NIL
  711.          */
  712.         switch (specType) {
  713.             case Path:
  714.             if (paths == NULL) {
  715.                 paths = Lst_Init(FALSE);
  716.             }
  717.             (void)Lst_AtEnd(paths, (ClientData)dirSearchPath);
  718.             break;
  719.             case Main:
  720.             if (!Lst_IsEmpty(create)) {
  721.                 specType = Not;
  722.             }
  723.             break;
  724.             case Begin:
  725.             case End:
  726.             case Interrupt:
  727.             gn = Targ_FindNode(line, TARG_CREATE);
  728.             gn->type |= OP_NOTMAIN;
  729.             (void)Lst_AtEnd(targets, (ClientData)gn);
  730.             break;
  731.             case Default:
  732.             gn = Targ_NewGN(".DEFAULT");
  733.             gn->type |= (OP_NOTMAIN|OP_TRANSFORM);
  734.             (void)Lst_AtEnd(targets, (ClientData)gn);
  735.             DEFAULT = gn;
  736.             break;
  737.             case NotParallel:
  738.             {
  739.             extern int  maxJobs;
  740.             
  741.             maxJobs = 1;
  742.             break;
  743.             }
  744.             case SingleShell:
  745.             /* backwards = 1; */
  746.             break;
  747.             case Order:
  748.             predecessor = NILGNODE;
  749.             break;
  750.         }
  751.         } else if (strncmp (line, ".PATH", 5) == 0) {
  752.         /*
  753.          * .PATH<suffix> has to be handled specially.
  754.          * Call on the suffix module to give us a path to
  755.          * modify.
  756.          */
  757.         Lst     path;
  758.         
  759.         specType = Path;
  760.         path = Suff_GetPath (&line[5]);
  761.         if (path == NILLST) {
  762.             Parse_Error (PARSE_FATAL,
  763.                  "Suffix '%s' not defined (yet)",
  764.                  &line[5]);
  765.             return;
  766.         } else {
  767.             if (paths == (Lst)NULL) {
  768.             paths = Lst_Init(FALSE);
  769.             }
  770.             (void)Lst_AtEnd(paths, (ClientData)path);
  771.         }
  772.         }
  773.     }
  774.     
  775.     /*
  776.      * Have word in line. Get or create its node and stick it at
  777.      * the end of the targets list 
  778.      */
  779.     if ((specType == Not) && (*line != '\0')) {
  780.         if (Dir_HasWildcards(line)) {
  781.         /*
  782.          * Targets are to be sought only in the current directory,
  783.          * so create an empty path for the thing. Note we need to
  784.          * use Dir_Destroy in the destruction of the path as the
  785.          * Dir module could have added a directory to the path...
  786.          */
  787.         Lst        emptyPath = Lst_Init(FALSE);
  788.         
  789.         Dir_Expand(line, emptyPath, curTargs);
  790.         
  791.         Lst_Destroy(emptyPath, Dir_Destroy);
  792.         } else {
  793.         /*
  794.          * No wildcards, but we want to avoid code duplication,
  795.          * so create a list with the word on it.
  796.          */
  797.         (void)Lst_AtEnd(curTargs, (ClientData)line);
  798.         }
  799.         
  800.         while(!Lst_IsEmpty(curTargs)) {
  801.         char    *targName = (char *)Lst_DeQueue(curTargs);
  802.         
  803.         if (!Suff_IsTransform (targName)) {
  804.             gn = Targ_FindNode (targName, TARG_CREATE);
  805.         } else {
  806.             gn = Suff_AddTransform (targName);
  807.         }
  808.         
  809.         (void)Lst_AtEnd (targets, (ClientData)gn);
  810.         }
  811.     } else if (specType == Path && *line != '.' && *line != '\0') {
  812.         Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line);
  813.     }
  814.     
  815.     *cp = savec;
  816.     /*
  817.      * If it is a special type and not .PATH, it's the only target we
  818.      * allow on this line...
  819.      */
  820.     if (specType != Not && specType != Path) {
  821.         Boolean warn = FALSE;
  822.         
  823.         while ((*cp != '!') && (*cp != ':') && *cp) {
  824.         if (*cp != ' ' && *cp != '\t') {
  825.             warn = TRUE;
  826.         }
  827.         cp++;
  828.         }
  829.         if (warn) {
  830.         Parse_Error(PARSE_WARNING, "Extra target ignored");
  831.         }
  832.     } else {
  833.         while (*cp && isspace (*cp)) {
  834.         cp++;
  835.         }
  836.     }
  837.     line = cp;
  838.     } while ((*line != '!') && (*line != ':') && *line);
  839.  
  840.     /*
  841.      * Don't need the list of target names anymore...
  842.      */
  843.     Lst_Destroy(curTargs, NOFREE);
  844.  
  845.     if (!Lst_IsEmpty(targets)) {
  846.     switch(specType) {
  847.         default:
  848.         Parse_Error(PARSE_WARNING, "Special and mundane targets don't mix. Mundane ones ignored");
  849.         break;
  850.         case Default:
  851.         case Begin:
  852.         case End:
  853.         case Interrupt:
  854.         /*
  855.          * These four create nodes on which to hang commands, so
  856.          * targets shouldn't be empty...
  857.          */
  858.         case Not:
  859.         /*
  860.          * Nothing special here -- targets can be empty if it wants.
  861.          */
  862.         break;
  863.     }
  864.     }
  865.  
  866.     /*
  867.      * Have now parsed all the target names. Must parse the operator next. The
  868.      * result is left in  op .
  869.      */
  870.     if (*cp == '!') {
  871.     op = OP_FORCE;
  872.     } else if (*cp == ':') {
  873.     if (cp[1] == ':') {
  874.         op = OP_DOUBLEDEP;
  875.         cp++;
  876.     } else {
  877.         op = OP_DEPENDS;
  878.     }
  879.     } else {
  880.     Parse_Error (PARSE_FATAL, "Missing dependency operator");
  881.     return;
  882.     }
  883.  
  884.     cp++;            /* Advance beyond operator */
  885.  
  886.     Lst_ForEach (targets, ParseDoOp, (ClientData)op);
  887.  
  888.     /*
  889.      * Get to the first source 
  890.      */
  891.     while (*cp && isspace (*cp)) {
  892.     cp++;
  893.     }
  894.     line = cp;
  895.  
  896.     /*
  897.      * Several special targets take different actions if present with no
  898.      * sources:
  899.      *    a .SUFFIXES line with no sources clears out all old suffixes
  900.      *    a .PRECIOUS line makes all targets precious
  901.      *    a .IGNORE line ignores errors for all targets
  902.      *    a .SILENT line creates silence when making all targets
  903.      *    a .PATH removes all directories from the search path(s).
  904.      */
  905.     if (!*line) {
  906.     switch (specType) {
  907.         case Suffixes:
  908.         Suff_ClearSuffixes ();
  909.         break;
  910.         case Precious:
  911.         allPrecious = TRUE;
  912.         break;
  913.         case Ignore:
  914.         ignoreErrors = TRUE;
  915.         break;
  916.         case Silent:
  917.         beSilent = TRUE;
  918.         break;
  919.         case Path:
  920.         Lst_ForEach(paths, ParseClearPath, (ClientData)NULL);
  921.         break;
  922.     }
  923.     } else if (specType == MFlags) {
  924.     /*
  925.      * Call on functions in main.c to deal with these arguments and
  926.      * set the initial character to a null-character so the loop to
  927.      * get sources won't get anything
  928.      */
  929.     Main_ParseArgLine (line);
  930.     *line = '\0';
  931.     } else if (specType == Shell) {
  932.     if (Job_ParseShell (line) != SUCCESS) {
  933.         Parse_Error (PARSE_FATAL, "improper shell specification");
  934.         return;
  935.     }
  936.     *line = '\0';
  937.     } else if ((specType == NotParallel) || (specType == SingleShell)) {
  938.     *line = '\0';
  939.     }
  940.     
  941.     /*
  942.      * NOW GO FOR THE SOURCES 
  943.      */
  944.     if ((specType == Suffixes) || (specType == Path) ||
  945.     (specType == Includes) || (specType == Libs) ||
  946.     (specType == Null))
  947.     {
  948.     while (*line) {
  949.         /*
  950.          * If the target was one that doesn't take files as its sources
  951.          * but takes something like suffixes, we take each
  952.          * space-separated word on the line as a something and deal
  953.          * with it accordingly.
  954.          *
  955.          * If the target was .SUFFIXES, we take each source as a
  956.          * suffix and add it to the list of suffixes maintained by the
  957.          * Suff module.
  958.          *
  959.          * If the target was a .PATH, we add the source as a directory
  960.          * to search on the search path.
  961.          *
  962.          * If it was .INCLUDES, the source is taken to be the suffix of
  963.          * files which will be #included and whose search path should
  964.          * be present in the .INCLUDES variable.
  965.          *
  966.          * If it was .LIBS, the source is taken to be the suffix of
  967.          * files which are considered libraries and whose search path
  968.          * should be present in the .LIBS variable.
  969.          *
  970.          * If it was .NULL, the source is the suffix to use when a file
  971.          * has no valid suffix.
  972.          */
  973.         char  savec;
  974.         while (*cp && !isspace (*cp)) {
  975.         cp++;
  976.         }
  977.         savec = *cp;
  978.         *cp = '\0';
  979.         switch (specType) {
  980.         case Suffixes:
  981.             Suff_AddSuffix (line);
  982.             break;
  983.         case Path:
  984.             Lst_ForEach(paths, ParseAddDir, (ClientData)line);
  985.             break;
  986.         case Includes:
  987.             Suff_AddInclude (line);
  988.             break;
  989.         case Libs:
  990.             Suff_AddLib (line);
  991.             break;
  992.         case Null:
  993.             Suff_SetNull (line);
  994.             break;
  995.         }
  996.         *cp = savec;
  997.         if (savec != '\0') {
  998.         cp++;
  999.         }
  1000.         while (*cp && isspace (*cp)) {
  1001.         cp++;
  1002.         }
  1003.         line = cp;
  1004.     }
  1005.     if (paths) {
  1006.         Lst_Destroy(paths, NOFREE);
  1007.     }
  1008.     } else {
  1009.     while (*line) {
  1010.         /*
  1011.          * The targets take real sources, so we must beware of archive
  1012.          * specifications (i.e. things with left parentheses in them)
  1013.          * and handle them accordingly.
  1014.          */
  1015.         while (*cp && !isspace (*cp)) {
  1016.         if ((*cp == '(') && (cp > line) && (cp[-1] != '$')) {
  1017.             /*
  1018.              * Only stop for a left parenthesis if it isn't at the
  1019.              * start of a word (that'll be for variable changes
  1020.              * later) and isn't preceded by a dollar sign (a dynamic
  1021.              * source).
  1022.              */
  1023.             break;
  1024.         } else {
  1025.             cp++;
  1026.         }
  1027.         }
  1028.  
  1029.         if (*cp == '(') {
  1030.         GNode      *gn;
  1031.  
  1032.         sources = Lst_Init (FALSE);
  1033.         if (Arch_ParseArchive (&line, sources, VAR_CMD) != SUCCESS) {
  1034.             Parse_Error (PARSE_FATAL,
  1035.                  "Error in source archive spec \"%s\"", line);
  1036.             return;
  1037.         }
  1038.  
  1039.         while (!Lst_IsEmpty (sources)) {
  1040.             gn = (GNode *) Lst_DeQueue (sources);
  1041.             ParseDoSrc (tOp, gn->name);
  1042.         }
  1043.         Lst_Destroy (sources, NOFREE);
  1044.         cp = line;
  1045.         } else {
  1046.         if (*cp) {
  1047.             *cp = '\0';
  1048.             cp += 1;
  1049.         }
  1050.  
  1051.         ParseDoSrc (tOp, line);
  1052.         }
  1053.         while (*cp && isspace (*cp)) {
  1054.         cp++;
  1055.         }
  1056.         line = cp;
  1057.     }
  1058.     }
  1059.     
  1060.     if (mainNode == NILGNODE) {
  1061.     /*
  1062.      * If we have yet to decide on a main target to make, in the
  1063.      * absence of any user input, we want the first target on
  1064.      * the first dependency line that is actually a real target
  1065.      * (i.e. isn't a .USE or .EXEC rule) to be made.
  1066.      */
  1067.     Lst_ForEach (targets, ParseFindMain, (ClientData)0);
  1068.     }
  1069.  
  1070. }
  1071.  
  1072. /*-
  1073.  *---------------------------------------------------------------------
  1074.  * Parse_IsVar  --
  1075.  *    Return TRUE if the passed line is a variable assignment. A variable
  1076.  *    assignment consists of a single word followed by optional whitespace
  1077.  *    followed by either a += or an = operator.
  1078.  *    This function is used both by the Parse_File function and main when
  1079.  *    parsing the command-line arguments.
  1080.  *
  1081.  * Results:
  1082.  *    TRUE if it is. FALSE if it ain't
  1083.  *
  1084.  * Side Effects:
  1085.  *    none
  1086.  *---------------------------------------------------------------------
  1087.  */
  1088. Boolean
  1089. Parse_IsVar (line)
  1090.     register char  *line;    /* the line to check */
  1091. {
  1092.     register Boolean wasSpace = FALSE;    /* set TRUE if found a space */
  1093.     register Boolean haveName = FALSE;    /* Set TRUE if have a variable name */
  1094.  
  1095.     /*
  1096.      * Skip to variable name
  1097.      */
  1098.     while ((*line == ' ') || (*line == '\t')) {
  1099.     line++;
  1100.     }
  1101.  
  1102.     while (*line != '=') {
  1103.     if (*line == '\0') {
  1104.         /*
  1105.          * end-of-line -- can't be a variable assignment.
  1106.          */
  1107.         return (FALSE);
  1108.     } else if ((*line == ' ') || (*line == '\t')) {
  1109.         /*
  1110.          * there can be as much white space as desired so long as there is
  1111.          * only one word before the operator 
  1112.          */
  1113.         wasSpace = TRUE;
  1114.     } else if (wasSpace && haveName) {
  1115.         /*
  1116.          * Stop when an = operator is found.
  1117.          */
  1118.         if ((*line == '+') || (*line == ':') || (*line == '?') || 
  1119.         (*line == '!')) {
  1120.         break;    
  1121.         }
  1122.  
  1123.         /*
  1124.          * This is the start of another word, so not assignment.
  1125.          */
  1126.         return (FALSE);
  1127.     } else {
  1128.         haveName = TRUE; 
  1129.         wasSpace = FALSE;
  1130.     }
  1131.     line++;
  1132.     }
  1133.  
  1134.     /*
  1135.      * A final check: if we stopped on a +, ?, ! or :, the next character must
  1136.      * be an = or it ain't a valid assignment 
  1137.      */
  1138.     if (((*line == '+') ||
  1139.      (*line == '?') ||
  1140.      (*line == ':') ||
  1141.      (*line == '!')) &&
  1142.     (line[1] != '='))
  1143.     {
  1144.     return (FALSE);
  1145.     } else {
  1146.     return (haveName);
  1147.     }
  1148. }
  1149.  
  1150. /*-
  1151.  *---------------------------------------------------------------------
  1152.  * Parse_DoVar  --
  1153.  *    Take the variable assignment in the passed line and do it in the
  1154.  *    global context.
  1155.  *
  1156.  *    Note: There is a lexical ambiguity with assignment modifier characters
  1157.  *    in variable names. This routine interprets the character before the =
  1158.  *    as a modifier. Therefore, an assignment like
  1159.  *        C++=/usr/bin/CC
  1160.  *    is interpreted as "C+ +=" instead of "C++ =".
  1161.  *
  1162.  * Results:
  1163.  *    none
  1164.  *
  1165.  * Side Effects:
  1166.  *    the variable structure of the given variable name is altered in the
  1167.  *    global context.
  1168.  *---------------------------------------------------------------------
  1169.  */
  1170. void
  1171. Parse_DoVar (line, ctxt)
  1172.     char            *line;    /* a line guaranteed to be a variable
  1173.                  * assignment. This reduces error checks */
  1174.     GNode           *ctxt;        /* Context in which to do the assignment */
  1175. {
  1176.     register char   *cp;    /* pointer into line */
  1177.     enum {
  1178.     VAR_SUBST, VAR_APPEND, VAR_SHELL, VAR_NORMAL
  1179.     }                type;       /* Type of assignment */
  1180.     char            *opc;    /* ptr to operator character to 
  1181.                  * null-terminate the variable name */
  1182.  
  1183.     /*
  1184.      * Skip to variable name
  1185.      */
  1186.     while ((*line == ' ') || (*line == '\t')) {
  1187.     line++;
  1188.     }
  1189.  
  1190.     /*
  1191.      * Skip to operator character, nulling out whitespace as we go
  1192.      */
  1193.     for (cp = line + 1; *cp != '='; cp++) {
  1194.     if (isspace (*cp)) {
  1195.         *cp = '\0';
  1196.     }
  1197.     }
  1198.     opc = cp-1;        /* operator is the previous character */
  1199.     *cp++ = '\0';    /* nuke the = */
  1200.  
  1201.     /*
  1202.      * Check operator type
  1203.      */
  1204.     switch (*opc) {
  1205.     case '+':
  1206.         type = VAR_APPEND;
  1207.         *opc = '\0';
  1208.         break;
  1209.  
  1210.     case '?':
  1211.         /*
  1212.          * If the variable already has a value, we don't do anything.
  1213.          */
  1214.         *opc = '\0';
  1215.         if (Var_Exists(line, ctxt)) {
  1216.         return;
  1217.         } else {
  1218.         type = VAR_NORMAL;
  1219.         }
  1220.         break;
  1221.  
  1222.     case ':':
  1223.         type = VAR_SUBST;
  1224.         *opc = '\0';
  1225.         break;
  1226.  
  1227.     case '!':
  1228.         type = VAR_SHELL;
  1229.         *opc = '\0';
  1230.         break;
  1231.  
  1232.     default:
  1233.         type = VAR_NORMAL;
  1234.         break;
  1235.     }
  1236.  
  1237.     while (isspace (*cp)) {
  1238.     cp++;
  1239.     }
  1240.  
  1241.     if (type == VAR_APPEND) {
  1242.     Var_Append (line, cp, ctxt);
  1243.     } else if (type == VAR_SUBST) {
  1244.     /*
  1245.      * Allow variables in the old value to be undefined, but leave their
  1246.      * invocation alone -- this is done by forcing oldVars to be false.
  1247.      * XXX: This can cause recursive variables, but that's not hard to do,
  1248.      * and this allows someone to do something like
  1249.      *
  1250.      *  CFLAGS = $(.INCLUDES)
  1251.      *  CFLAGS := -I.. $(CFLAGS)
  1252.      *
  1253.      * And not get an error.
  1254.      */
  1255.     Boolean      oldOldVars = oldVars;
  1256.  
  1257.     oldVars = FALSE;
  1258.     cp = Var_Subst(cp, ctxt, FALSE);
  1259.     oldVars = oldOldVars;
  1260.  
  1261.     Var_Set(line, cp, ctxt);
  1262.     free(cp);
  1263.     } else if (type == VAR_SHELL) {
  1264.     char    result[BUFSIZ];    /* Result of command */
  1265.     char    *args[4];       /* Args for invoking the shell */
  1266.     int     fds[2];            /* Pipe streams */
  1267.     int     cpid;            /* Child PID */
  1268.     int     pid;            /* PID from wait() */
  1269.     Boolean    freeCmd;        /* TRUE if the command needs to be freed, i.e.
  1270.                  * if any variable expansion was performed */
  1271.  
  1272.     /*
  1273.      * Set up arguments for shell
  1274.      */
  1275.     args[0] = "sh";
  1276.     args[1] = "-c";
  1277.     if (index(cp, '$') != (char *)NULL) {
  1278.         /*
  1279.          * There's a dollar sign in the command, so perform variable
  1280.          * expansion on the whole thing. The resulting string will need
  1281.          * freeing when we're done, so set freeCmd to TRUE.
  1282.          */
  1283.         args[2] = Var_Subst(cp, VAR_CMD, TRUE);
  1284.         freeCmd = TRUE;
  1285.     } else {
  1286.         args[2] = cp;
  1287.         freeCmd = FALSE;
  1288.     }
  1289.     args[3] = (char *)NULL;
  1290.  
  1291.     /*
  1292.      * Open a pipe for fetching its output
  1293.      */
  1294.     pipe(fds);
  1295.  
  1296.     /*
  1297.      * Fork
  1298.      */
  1299.     cpid = vfork();
  1300.     if (cpid == 0) {
  1301.         /*
  1302.          * Close input side of pipe
  1303.          */
  1304.         close(fds[0]);
  1305.  
  1306.         /*
  1307.          * Duplicate the output stream to the shell's output, then
  1308.          * shut the extra thing down. Note we don't fetch the error
  1309.          * stream...why not? Why?
  1310.          */
  1311.         dup2(fds[1], 1);
  1312.         close(fds[1]);
  1313.         
  1314.         execv("/bin/sh", args);
  1315.         _exit(1);
  1316.     } else if (cpid < 0) {
  1317.         /*
  1318.          * Couldn't fork -- tell the user and make the variable null
  1319.          */
  1320.         Parse_Error(PARSE_WARNING, "Couldn't exec \"%s\"", cp);
  1321.         Var_Set(line, "", ctxt);
  1322.     } else {
  1323.         int    status;
  1324.         int cc;
  1325.  
  1326.         /*
  1327.          * No need for the writing half
  1328.          */
  1329.         close(fds[1]);
  1330.         
  1331.         /*
  1332.          * Wait for the process to exit.
  1333.          *
  1334.          * XXX: If the child writes more than a pipe's worth, we will
  1335.          * deadlock.
  1336.          */
  1337.         while(((pid = wait(&status)) != cpid) && (pid >= 0)) {
  1338.         ;
  1339.         }
  1340.  
  1341.         /*
  1342.          * Read all the characters the child wrote.
  1343.          */
  1344.         cc = read(fds[0], result, sizeof(result));
  1345.  
  1346.         if (cc < 0) {
  1347.         /*
  1348.          * Couldn't read the child's output -- tell the user and
  1349.          * set the variable to null
  1350.          */
  1351.         Parse_Error(PARSE_WARNING, "Couldn't read shell's output");
  1352.         cc = 0;
  1353.         }
  1354.  
  1355.         if (status) {
  1356.         /*
  1357.          * Child returned an error -- tell the user but still use
  1358.          * the result.
  1359.          */
  1360.         Parse_Error(PARSE_WARNING, "\"%s\" returned non-zero", cp);
  1361.         }
  1362.         /*
  1363.          * Null-terminate the result, convert newlines to spaces and
  1364.          * install it in the variable.
  1365.          */
  1366.         result[cc] = '\0';
  1367.         cp = &result[cc] - 1;
  1368.  
  1369.         if (*cp == '\n') {
  1370.         /*
  1371.          * A final newline is just stripped
  1372.          */
  1373.         *cp-- = '\0';
  1374.         }
  1375.         while (cp >= result) {
  1376.         if (*cp == '\n') {
  1377.             *cp = ' ';
  1378.         }
  1379.         cp--;
  1380.         }
  1381.         Var_Set(line, result, ctxt);
  1382.  
  1383.         /*
  1384.          * Close the input side of the pipe.
  1385.          */
  1386.         close(fds[0]);
  1387.     }
  1388.     if (freeCmd) {
  1389.         free(args[2]);
  1390.     }
  1391.     } else {
  1392.     /*
  1393.      * Normal assignment -- just do it.
  1394.      */
  1395.     Var_Set (line, cp, ctxt);
  1396.     }
  1397. }
  1398.  
  1399. /*-
  1400.  * ParseAddCmd  --
  1401.  *    Lst_ForEach function to add a command line to all targets
  1402.  *
  1403.  * Results:
  1404.  *    Always 0
  1405.  *
  1406.  * Side Effects:
  1407.  *    A new element is added to the commands list of the node.
  1408.  */
  1409. static
  1410. ParseAddCmd(gn, cmd)
  1411.     GNode *gn;    /* the node to which the command is to be added */
  1412.     char *cmd;    /* the command to add */
  1413. {
  1414.     /* if target already supplied, ignore commands */
  1415.     if (!(gn->type & OP_HAS_COMMANDS))
  1416.         (void)Lst_AtEnd(gn->commands, (ClientData)cmd);
  1417.     return(0);
  1418. }
  1419.  
  1420. /*-
  1421.  *-----------------------------------------------------------------------
  1422.  * ParseHasCommands --
  1423.  *    Callback procedure for Parse_File when destroying the list of
  1424.  *    targets on the last dependency line. Marks a target as already
  1425.  *    having commands if it does, to keep from having shell commands
  1426.  *    on multiple dependency lines.
  1427.  *
  1428.  * Results:
  1429.  *    Always 0.
  1430.  *
  1431.  * Side Effects:
  1432.  *    OP_HAS_COMMANDS may be set for the target.
  1433.  *
  1434.  *-----------------------------------------------------------------------
  1435.  */
  1436. static int
  1437. ParseHasCommands(gn)
  1438.     GNode         *gn;        /* Node to examine */
  1439. {
  1440.     if (!Lst_IsEmpty(gn->commands)) {
  1441.     gn->type |= OP_HAS_COMMANDS;
  1442.     }
  1443.     return(0);
  1444. }
  1445.  
  1446. /*-
  1447.  *-----------------------------------------------------------------------
  1448.  * Parse_AddIncludeDir --
  1449.  *    Add a directory to the path searched for included makefiles
  1450.  *    bracketed by double-quotes. Used by functions in main.c
  1451.  *
  1452.  * Results:
  1453.  *    None.
  1454.  *
  1455.  * Side Effects:
  1456.  *    The directory is appended to the list.
  1457.  *
  1458.  *-----------------------------------------------------------------------
  1459.  */
  1460. void
  1461. Parse_AddIncludeDir (dir)
  1462.     char          *dir;        /* The name of the directory to add */
  1463. {
  1464.     Dir_AddDir (parseIncPath, dir);
  1465. }
  1466.  
  1467. /*-
  1468.  *---------------------------------------------------------------------
  1469.  * ParseDoInclude  --
  1470.  *    Push to another file.
  1471.  *    
  1472.  *    The input is the line minus the #include. A file spec is a string
  1473.  *    enclosed in <> or "". The former is looked for only in sysIncPath.
  1474.  *    The latter in . and the directories specified by -I command line
  1475.  *    options
  1476.  *
  1477.  * Results:
  1478.  *    None
  1479.  *
  1480.  * Side Effects:
  1481.  *    A structure is added to the includes Lst and readProc, lineno,
  1482.  *    fname and curFILE are altered for the new file
  1483.  *---------------------------------------------------------------------
  1484.  */
  1485. static void
  1486. ParseDoInclude (file)
  1487.     char          *file;    /* file specification */
  1488. {
  1489.     char          *fullname;    /* full pathname of file */
  1490.     IFile         *oldFile;    /* state associated with current file */
  1491.     Lst           path;            /* the path to use to find the file */
  1492.     char          endc;            /* the character which ends the file spec */
  1493.     char          *cp;        /* current position in file spec */
  1494.     Boolean       isSystem;     /* TRUE if makefile is a system makefile */
  1495.  
  1496.     /*
  1497.      * Skip to delimiter character so we know where to look
  1498.      */
  1499.     while ((*file == ' ') || (*file == '\t')) {
  1500.     file++;
  1501.     }
  1502.  
  1503.     if ((*file != '"') && (*file != '<')) {
  1504.     Parse_Error (PARSE_FATAL,
  1505.         ".include filename must be delimited by '\"' or '<'");
  1506.     return;
  1507.     }
  1508.  
  1509.     /*
  1510.      * Set the search path on which to find the include file based on the
  1511.      * characters which bracket its name. Angle-brackets imply it's
  1512.      * a system Makefile while double-quotes imply it's a user makefile
  1513.      */
  1514.     if (*file == '<') {
  1515.     isSystem = TRUE;
  1516.     endc = '>';
  1517.     } else {
  1518.     isSystem = FALSE;
  1519.     endc = '"';
  1520.     }
  1521.  
  1522.     /*
  1523.      * Skip to matching delimiter
  1524.      */
  1525.     for (cp = ++file; *cp && *cp != endc; cp++) {
  1526.     continue;
  1527.     }
  1528.  
  1529.     if (*cp != endc) {
  1530.     Parse_Error (PARSE_FATAL,
  1531.              "Unclosed .include filename. '%c' expected", endc);
  1532.     return;
  1533.     }
  1534.     *cp = '\0';
  1535.  
  1536.     /*
  1537.      * Substitute for any variables in the file name before trying to
  1538.      * find the thing.
  1539.      */
  1540.     file = Var_Subst (file, VAR_CMD, FALSE);
  1541.  
  1542.     /*
  1543.      * Now we know the file's name and its search path, we attempt to
  1544.      * find the durn thing. A return of NULL indicates the file don't
  1545.      * exist.
  1546.      */
  1547.     if (!isSystem) {
  1548.     /*
  1549.      * Include files contained in double-quotes are first searched for
  1550.      * relative to the including file's location. We don't want to
  1551.      * cd there, of course, so we just tack on the old file's
  1552.      * leading path components and call Dir_FindFile to see if
  1553.      * we can locate the beast.
  1554.      */
  1555.     char      *prefEnd;
  1556.  
  1557.     prefEnd = rindex (fname, '/');
  1558.     if (prefEnd != (char *)NULL) {
  1559.         char      *newName;
  1560.         
  1561.         *prefEnd = '\0';
  1562.         newName = str_concat (fname, file, STR_ADDSLASH);
  1563.         fullname = Dir_FindFile (newName, parseIncPath);
  1564.         if (fullname == (char *)NULL) {
  1565.         fullname = Dir_FindFile(newName, dirSearchPath);
  1566.         }
  1567.         free (newName);
  1568.         *prefEnd = '/';
  1569.     } else {
  1570.         fullname = (char *)NULL;
  1571.     }
  1572.     } else {
  1573.     fullname = (char *)NULL;
  1574.     }
  1575.  
  1576.     if (fullname == (char *)NULL) {
  1577.     /*
  1578.      * System makefile or makefile wasn't found in same directory as
  1579.      * included makefile. Search for it first on the -I search path,
  1580.      * then on the .PATH search path, if not found in a -I directory.
  1581.      * XXX: Suffix specific?
  1582.      */
  1583.     fullname = Dir_FindFile (file, parseIncPath);
  1584.     if (fullname == (char *)NULL) {
  1585.         fullname = Dir_FindFile(file, dirSearchPath);
  1586.     }
  1587.     }
  1588.  
  1589.     if (fullname == (char *)NULL) {
  1590.     /*
  1591.      * Still haven't found the makefile. Look for it on the system
  1592.      * path as a last resort.
  1593.      */
  1594.     fullname = Dir_FindFile(file, sysIncPath);
  1595.     }
  1596.  
  1597.     if (fullname == (char *) NULL) {
  1598.     *cp = endc;
  1599.     Parse_Error (PARSE_FATAL, "Could not find %s", file);
  1600.     return;
  1601.     }
  1602.  
  1603.     /*
  1604.      * Once we find the absolute path to the file, we get to save all the
  1605.      * state from the current file before we can start reading this
  1606.      * include file. The state is stored in an IFile structure which
  1607.      * is placed on a list with other IFile structures. The list makes
  1608.      * a very nice stack to track how we got here...
  1609.      */
  1610.     oldFile = (IFile *) emalloc (sizeof (IFile));
  1611.     oldFile->fname = fname;
  1612.  
  1613.     oldFile->F = curFILE;
  1614.     oldFile->lineno = lineno;
  1615.  
  1616.     (void) Lst_AtFront (includes, (ClientData)oldFile);
  1617.  
  1618.     /*
  1619.      * Once the previous state has been saved, we can get down to reading
  1620.      * the new file. We set up the name of the file to be the absolute
  1621.      * name of the include file so error messages refer to the right
  1622.      * place. Naturally enough, we start reading at line number 0.
  1623.      */
  1624.     fname = fullname;
  1625.     lineno = 0;
  1626.  
  1627.     curFILE = fopen (fullname, "r");
  1628.     if (curFILE == (FILE * ) NULL) {
  1629.     Parse_Error (PARSE_FATAL, "Cannot open %s", fullname);
  1630.     /*
  1631.      * Pop to previous file
  1632.      */
  1633.     (void) ParseEOF(0);
  1634.     }
  1635. }
  1636.  
  1637. /*-
  1638.  *---------------------------------------------------------------------
  1639.  * ParseEOF  --
  1640.  *    Called when EOF is reached in the current file. If we were reading
  1641.  *    an include file, the includes stack is popped and things set up
  1642.  *    to go back to reading the previous file at the previous location.
  1643.  *
  1644.  * Results:
  1645.  *    CONTINUE if there's more to do. DONE if not.
  1646.  *
  1647.  * Side Effects:
  1648.  *    The old curFILE, is closed. The includes list is shortened.
  1649.  *    lineno, curFILE, and fname are changed if CONTINUE is returned.
  1650.  *---------------------------------------------------------------------
  1651.  */
  1652. static int
  1653. ParseEOF (opened)
  1654.     int opened;
  1655. {
  1656.     IFile     *ifile;    /* the state on the top of the includes stack */
  1657.  
  1658.     if (Lst_IsEmpty (includes)) {
  1659.     return (DONE);
  1660.     }
  1661.  
  1662.     ifile = (IFile *) Lst_DeQueue (includes);
  1663.     free (fname);
  1664.     fname = ifile->fname;
  1665.     lineno = ifile->lineno;
  1666.     if (opened)
  1667.     (void) fclose (curFILE);
  1668.     curFILE = ifile->F;
  1669.     free ((Address)ifile);
  1670.     return (CONTINUE);
  1671. }
  1672.  
  1673. /*-
  1674.  *---------------------------------------------------------------------
  1675.  * ParseReadc  --
  1676.  *    Read a character from the current file and update the line number
  1677.  *    counter as necessary
  1678.  *
  1679.  * Results:
  1680.  *    The character that was read
  1681.  *
  1682.  * Side Effects:
  1683.  *    The lineno counter is incremented if the character is a newline
  1684.  *---------------------------------------------------------------------
  1685.  */
  1686. #ifdef notdef
  1687. static int parseReadChar;
  1688.  
  1689. #define ParseReadc() (((parseReadChar = getc(curFILE)) == '\n') ? \
  1690.               (lineno++, '\n') : parseReadChar)
  1691. #else
  1692. #define ParseReadc() (getc(curFILE))
  1693. #endif /* notdef */
  1694.  
  1695.  
  1696. /*-
  1697.  *---------------------------------------------------------------------
  1698.  * ParseReadLine --
  1699.  *    Read an entire line from the input file. Called only by Parse_File.
  1700.  *    To facilitate escaped newlines and what have you, a character is
  1701.  *    buffered in 'lastc', which is '\0' when no characters have been
  1702.  *    read. When we break out of the loop, c holds the terminating
  1703.  *    character and lastc holds a character that should be added to
  1704.  *    the line (unless we don't read anything but a terminator).
  1705.  *
  1706.  * Results:
  1707.  *    A line w/o its newline
  1708.  *
  1709.  * Side Effects:
  1710.  *    Only those associated with reading a character
  1711.  *---------------------------------------------------------------------
  1712.  */
  1713. static char *
  1714. ParseReadLine ()
  1715. {
  1716.     Buffer        buf;            /* Buffer for current line */
  1717.     register int  c;              /* the current character */
  1718.     register int  lastc;        /* The most-recent character */
  1719.     Boolean      semiNL;         /* treat semi-colons as newlines */
  1720.     Boolean      ignDepOp;       /* TRUE if should ignore dependency operators
  1721.                  * for the purposes of setting semiNL */
  1722.     Boolean       ignComment;    /* TRUE if should ignore comments (in a
  1723.                  * shell command */
  1724.     char          *line;        /* Result */
  1725.     int              lineLength;    /* Length of result */
  1726.  
  1727.     semiNL = FALSE;
  1728.     ignDepOp = FALSE;
  1729.     ignComment = FALSE;
  1730.  
  1731.     /*
  1732.      * Handle special-characters at the beginning of the line. Either a
  1733.      * leading tab (shell command) or pound-sign (possible conditional)
  1734.      * forces us to ignore comments and dependency operators and treat
  1735.      * semi-colons as semi-colons (by leaving semiNL FALSE). This also
  1736.      * discards completely blank lines.
  1737.      */
  1738.     while(1) {
  1739.     c = ParseReadc();
  1740.  
  1741.     if (c == '\t') {
  1742.         ignComment = ignDepOp = TRUE;
  1743.         break;
  1744.     } else if (c == '.') {
  1745.         ignComment = TRUE;
  1746.         break;
  1747.     } else if (c == '\n') {
  1748.         lineno++;
  1749.     } else if (c == '#') {
  1750.         ungetc(c, curFILE); 
  1751.         break;
  1752.     } else {
  1753.         /*
  1754.          * Anything else breaks out without doing anything
  1755.          */
  1756.         break;
  1757.     }
  1758.     }
  1759.     
  1760.     if (c != EOF) {
  1761.     lastc = c;
  1762.     buf = Buf_Init(BSIZE);
  1763.     
  1764.     while (((c = ParseReadc ()) != '\n' || (lastc == '\\')) &&
  1765.            (c != EOF))
  1766.     {
  1767. test_char:
  1768.         switch(c) {
  1769.         case '\n':
  1770.         /*
  1771.          * Escaped newline: read characters until a non-space or an
  1772.          * unescaped newline and replace them all by a single space.
  1773.          * This is done by storing the space over the backslash and
  1774.          * dropping through with the next nonspace. If it is a
  1775.          * semi-colon and semiNL is TRUE, it will be recognized as a
  1776.          * newline in the code below this...
  1777.          */
  1778.         lineno++;
  1779.         lastc = ' ';
  1780.         while ((c = ParseReadc ()) == ' ' || c == '\t') {
  1781.             continue;
  1782.         }
  1783.         if (c == EOF || c == '\n') {
  1784.             goto line_read;
  1785.         } else {
  1786.             /*
  1787.              * Check for comments, semiNL's, etc. -- easier than
  1788.              * ungetc(c, curFILE); continue;
  1789.              */
  1790.             goto test_char;
  1791.         }
  1792.         break;
  1793.         case ';':
  1794.         /*
  1795.          * Semi-colon: Need to see if it should be interpreted as a
  1796.          * newline
  1797.          */
  1798.         if (semiNL) {
  1799.             /*
  1800.              * To make sure the command that may be following this
  1801.              * semi-colon begins with a tab, we push one back into the
  1802.              * input stream. This will overwrite the semi-colon in the
  1803.              * buffer. If there is no command following, this does no
  1804.              * harm, since the newline remains in the buffer and the
  1805.              * whole line is ignored.
  1806.              */
  1807.             ungetc('\t', curFILE);
  1808.             goto line_read;
  1809.         } 
  1810.         break;
  1811.         case '=':
  1812.         if (!semiNL) {
  1813.             /*
  1814.              * Haven't seen a dependency operator before this, so this
  1815.              * must be a variable assignment -- don't pay attention to
  1816.              * dependency operators after this.
  1817.              */
  1818.             ignDepOp = TRUE;
  1819.         } else if (lastc == ':' || lastc == '!') {
  1820.             /*
  1821.              * Well, we've seen a dependency operator already, but it
  1822.              * was the previous character, so this is really just an
  1823.              * expanded variable assignment. Revert semi-colons to
  1824.              * being just semi-colons again and ignore any more
  1825.              * dependency operators.
  1826.              *
  1827.              * XXX: Note that a line like "foo : a:=b" will blow up,
  1828.              * but who'd write a line like that anyway?
  1829.              */
  1830.             ignDepOp = TRUE; semiNL = FALSE;
  1831.         }
  1832.         break;
  1833.         case '#':
  1834.         if (!ignComment) {
  1835.             /*
  1836.              * If the character is a hash mark and it isn't escaped
  1837.              * (or we're being compatible), the thing is a comment.
  1838.              * Skip to the end of the line.
  1839.              */
  1840.             do {
  1841.                 c = ParseReadc();
  1842.             } while ((c != '\n') && (c != EOF));
  1843.             goto line_read;
  1844.         }
  1845.         break;
  1846.         case ':':
  1847.         case '!':
  1848.         if (!ignDepOp && (c == ':' || c == '!')) {
  1849.             /*
  1850.              * A semi-colon is recognized as a newline only on
  1851.              * dependency lines. Dependency lines are lines with a
  1852.              * colon or an exclamation point. Ergo...
  1853.              */
  1854.             semiNL = TRUE;
  1855.         }
  1856.         break;
  1857.         }
  1858.         /*
  1859.          * Copy in the previous character and save this one in lastc.
  1860.          */
  1861.         Buf_AddByte (buf, (Byte)lastc);
  1862.         lastc = c;
  1863.         
  1864.     }
  1865.     line_read:
  1866.     lineno++;
  1867.     
  1868.     if (lastc != '\0') {
  1869.         Buf_AddByte (buf, (Byte)lastc);
  1870.     }
  1871.     Buf_AddByte (buf, (Byte)'\0');
  1872.     line = (char *)Buf_GetAll (buf, &lineLength);
  1873.     Buf_Destroy (buf, FALSE);
  1874.     
  1875.     if (line[0] == '.') {
  1876.         /*
  1877.          * The line might be a conditional. Ask the conditional module
  1878.          * about it and act accordingly
  1879.          */
  1880.         switch (Cond_Eval (line)) {
  1881.         case COND_SKIP:
  1882.         do {
  1883.             /*
  1884.              * Skip to next conditional that evaluates to COND_PARSE.
  1885.              */
  1886.             free (line);
  1887.             c = ParseReadc();
  1888.             /*
  1889.              * Skip lines until get to one that begins with a
  1890.              * special char.
  1891.              */
  1892.             while ((c != '.') && (c != EOF)) {
  1893.             while (((c != '\n') || (lastc == '\\')) &&
  1894.                    (c != EOF))
  1895.             {
  1896.                 /*
  1897.                  * Advance to next unescaped newline
  1898.                  */
  1899.                 if ((lastc = c) == '\n') {
  1900.                 lineno++;
  1901.                 }
  1902.                 c = ParseReadc();
  1903.             }
  1904.             lineno++;
  1905.             
  1906.             lastc = c;
  1907.             c = ParseReadc ();
  1908.             }
  1909.             
  1910.             if (c == EOF) {
  1911.             Parse_Error (PARSE_FATAL, "Unclosed conditional");
  1912.             return ((char *)NULL);
  1913.             }
  1914.             
  1915.             /*
  1916.              * Read the entire line into buf
  1917.              */
  1918.             buf = Buf_Init (BSIZE);
  1919.             do {
  1920.             Buf_AddByte (buf, (Byte)c);
  1921.             c = ParseReadc();
  1922.             } while ((c != '\n') && (c != EOF));
  1923.             lineno++;
  1924.             
  1925.             Buf_AddByte (buf, (Byte)'\0');
  1926.             line = (char *)Buf_GetAll (buf, &lineLength);
  1927.             Buf_Destroy (buf, FALSE);
  1928.         } while (Cond_Eval(line) != COND_PARSE);
  1929.         /*FALLTHRU*/
  1930.         case COND_PARSE:
  1931.         free (line);
  1932.         line = ParseReadLine();
  1933.         break;
  1934.         }
  1935.     }
  1936.     
  1937.     return (line);
  1938.     } else {
  1939.     /*
  1940.      * Hit end-of-file, so return a NULL line to indicate this.
  1941.      */
  1942.     return((char *)NULL);
  1943.     }
  1944. }
  1945.  
  1946. /*-
  1947.  *-----------------------------------------------------------------------
  1948.  * ParseFinishLine --
  1949.  *    Handle the end of a dependency group.
  1950.  *
  1951.  * Results:
  1952.  *    Nothing.
  1953.  *
  1954.  * Side Effects:
  1955.  *    inLine set FALSE. 'targets' list destroyed.
  1956.  *
  1957.  *-----------------------------------------------------------------------
  1958.  */
  1959. static void
  1960. ParseFinishLine()
  1961. {
  1962.     extern int Suff_EndTransform();
  1963.  
  1964.     if (inLine) {
  1965.     Lst_ForEach(targets, Suff_EndTransform, (ClientData)NULL);
  1966.     Lst_Destroy (targets, ParseHasCommands);
  1967.     inLine = FALSE;
  1968.     }
  1969. }
  1970.             
  1971.  
  1972. /*-
  1973.  *---------------------------------------------------------------------
  1974.  * Parse_File --
  1975.  *    Parse a file into its component parts, incorporating it into the
  1976.  *    current dependency graph. This is the main function and controls
  1977.  *    almost every other function in this module
  1978.  *
  1979.  * Results:
  1980.  *    None
  1981.  *
  1982.  * Side Effects:
  1983.  *    Loads. Nodes are added to the list of all targets, nodes and links
  1984.  *    are added to the dependency graph. etc. etc. etc.
  1985.  *---------------------------------------------------------------------
  1986.  */
  1987. void
  1988. Parse_File(name, stream)
  1989.     char          *name;    /* the name of the file being read */
  1990.     FILE *      stream;       /* Stream open to makefile to parse */
  1991. {
  1992.     register char *cp,        /* pointer into the line */
  1993.                   *line;    /* the line we're working on */
  1994.  
  1995.     inLine = FALSE;
  1996.     fname = name;
  1997.     curFILE = stream;
  1998.     lineno = 0;
  1999.     fatals = 0;
  2000.  
  2001.     do {
  2002.     while (line = ParseReadLine ()) {
  2003.         if (*line == '.') {
  2004.         /*
  2005.          * Lines that begin with the special character are either
  2006.          * include or undef directives.
  2007.          */
  2008.         for (cp = line + 1; isspace (*cp); cp++) {
  2009.             continue;
  2010.         }
  2011.         if (strncmp (cp, "include", 7) == 0) {
  2012.             ParseDoInclude (cp + 7);
  2013.             goto nextLine;
  2014.         } else if (strncmp(cp, "undef", 5) == 0) {
  2015.             char *cp2;
  2016.             for (cp += 5; isspace(*cp); cp++) {
  2017.             continue;
  2018.             }
  2019.  
  2020.             for (cp2 = cp; !isspace(*cp2) && (*cp2 != '\0'); cp2++) {
  2021.             continue;
  2022.             }
  2023.  
  2024.             *cp2 = '\0';
  2025.  
  2026.             Var_Delete(cp, VAR_GLOBAL);
  2027.             goto nextLine;
  2028.         }
  2029.         }
  2030.         if (*line == '#') {
  2031.         /* If we're this far, the line must be a comment. */
  2032.         goto nextLine;
  2033.         }
  2034.         
  2035.         if (*line == '\t'
  2036. #ifdef POSIX
  2037.                || *line == ' '
  2038. #endif
  2039.                )
  2040.         {
  2041.         /*
  2042.          * If a line starts with a tab (or space in POSIX-land), it
  2043.          * can only hope to be a creation command.
  2044.          */
  2045.         shellCommand:
  2046.         for (cp = line + 1; isspace (*cp); cp++) {
  2047.             continue;
  2048.         }
  2049.         if (*cp) {
  2050.             if (inLine) {
  2051.             /*
  2052.              * So long as it's not a blank line and we're actually
  2053.              * in a dependency spec, add the command to the list of
  2054.              * commands of all targets in the dependency spec 
  2055.              */
  2056.             Lst_ForEach (targets, ParseAddCmd, (ClientData)cp);
  2057.             continue;
  2058.             } else {
  2059.             Parse_Error (PARSE_FATAL,
  2060.                      "Unassociated shell command \"%.20s\"",
  2061.                      cp);
  2062.             }
  2063.         }
  2064.         } else if (Parse_IsVar (line)) {
  2065.         ParseFinishLine();
  2066.         Parse_DoVar (line, VAR_GLOBAL);
  2067.         } else {
  2068.         /*
  2069.          * We now know it's a dependency line so it needs to have all
  2070.          * variables expanded before being parsed. Tell the variable
  2071.          * module to complain if some variable is undefined...
  2072.          * To make life easier on novices, if the line is indented we
  2073.          * first make sure the line has a dependency operator in it.
  2074.          * If it doesn't have an operator and we're in a dependency
  2075.          * line's script, we assume it's actually a shell command
  2076.          * and add it to the current list of targets.
  2077.          *
  2078.          * Note that POSIX declares all lines that start with
  2079.          * whitespace are shell commands, so there's no need to check
  2080.          * here...
  2081.          */
  2082.         Boolean    nonSpace = FALSE;
  2083.         
  2084.         cp = line;
  2085. #ifndef POSIX
  2086.         if (line[0] == ' ') {
  2087.             while ((*cp != ':') && (*cp != '!') && (*cp != '\0')) {
  2088.             if (!isspace(*cp)) {
  2089.                 nonSpace = TRUE;
  2090.             }
  2091.             cp++;
  2092.             }
  2093.         }
  2094.             
  2095.         if (*cp == '\0') {
  2096.             if (inLine) {
  2097.             Parse_Error (PARSE_WARNING,
  2098.                      "Shell command needs a leading tab");
  2099.             goto shellCommand;
  2100.             } else if (nonSpace) {
  2101.             Parse_Error (PARSE_FATAL, "Missing operator");
  2102.             }
  2103.         } else {
  2104. #endif
  2105.             ParseFinishLine();
  2106.  
  2107.             cp = Var_Subst (line, VAR_CMD, TRUE);
  2108.             free (line);
  2109.             line = cp;
  2110.             
  2111.             /*
  2112.              * Need a non-circular list for the target nodes 
  2113.              */
  2114.             targets = Lst_Init (FALSE);
  2115.             inLine = TRUE;
  2116.             
  2117.             ParseDoDependency (line);
  2118. #ifndef POSIX
  2119.         }
  2120. #endif
  2121.         }
  2122.  
  2123.         nextLine:
  2124.  
  2125.         free (line);
  2126.     }
  2127.     /*
  2128.      * Reached EOF, but it may be just EOF of an include file... 
  2129.      */
  2130.     } while (ParseEOF(1) == CONTINUE);
  2131.  
  2132.     /*
  2133.      * Make sure conditionals are clean
  2134.      */
  2135.     Cond_End();
  2136.  
  2137.     if (fatals) {
  2138.     fprintf (stderr, "Fatal errors encountered -- cannot continue\n");
  2139.     exit (1);
  2140.     }
  2141. }
  2142.  
  2143. /*-
  2144.  *---------------------------------------------------------------------
  2145.  * Parse_Init --
  2146.  *    initialize the parsing module
  2147.  *
  2148.  * Results:
  2149.  *    none
  2150.  *
  2151.  * Side Effects:
  2152.  *    the parseIncPath list is initialized...
  2153.  *---------------------------------------------------------------------
  2154.  */
  2155. Parse_Init ()
  2156. {
  2157.     char *cp, *start;
  2158.                     /* avoid faults on read-only strings */
  2159.     static char syspath[] = _PATH_DEFSYSPATH;
  2160.     
  2161.     mainNode = NILGNODE;
  2162.     parseIncPath = Lst_Init (FALSE);
  2163.     sysIncPath = Lst_Init (FALSE);
  2164.     includes = Lst_Init (FALSE);
  2165.  
  2166.     /*
  2167.      * Add the directories from the DEFSYSPATH (more than one may be given
  2168.      * as dir1:...:dirn) to the system include path.
  2169.      */
  2170.     for (start = syspath; *start != '\0'; start = cp) {
  2171.     for (cp = start; *cp != '\0' && *cp != ':'; cp++) {
  2172.         ;
  2173.     }
  2174.     if (*cp == '\0') {
  2175.         Dir_AddDir(sysIncPath, start);
  2176.     } else {
  2177.         *cp++ = '\0';
  2178.         Dir_AddDir(sysIncPath, start);
  2179.     }
  2180.     }
  2181. }
  2182.  
  2183. /*-
  2184.  *-----------------------------------------------------------------------
  2185.  * Parse_MainName --
  2186.  *    Return a Lst of the main target to create for main()'s sake. If
  2187.  *    no such target exists, we Punt with an obnoxious error message.
  2188.  *
  2189.  * Results:
  2190.  *    A Lst of the single node to create.
  2191.  *
  2192.  * Side Effects:
  2193.  *    None.
  2194.  *
  2195.  *-----------------------------------------------------------------------
  2196.  */
  2197. Lst
  2198. Parse_MainName()
  2199. {
  2200.     Lst           main;    /* result list */
  2201.  
  2202.     main = Lst_Init (FALSE);
  2203.  
  2204.     if (mainNode == NILGNODE) {
  2205.     Punt ("make: no target to make.\n");
  2206.         /*NOTREACHED*/
  2207.     } else if (mainNode->type & OP_DOUBLEDEP) {
  2208.     Lst_Concat(main, mainNode->cohorts, LST_CONCNEW);
  2209.     }
  2210.     (void) Lst_AtEnd (main, (ClientData)mainNode);
  2211.     return (main);
  2212. }
  2213.