VirtualBox

Changeset 51 in kBuild


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

kMk and porting to kLib.

Location:
trunk/src
Files:
21 edited

Legend:

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

    r35 r51  
    1818 * 3. All advertising materials mentioning features or use of this software
    1919 *    must display the following acknowledgement:
    20  *      This product includes software developed by the University of
    21  *      California, Berkeley and its contributors.
     20 *      This product includes software developed by the University of
     21 *      California, Berkeley and its contributors.
    2222 * 4. Neither the name of the University nor the names of its contributors
    2323 *    may be used to endorse or promote products derived from this software
     
    3939#ifndef lint
    4040#if 0
    41 static char sccsid[] = "@(#)buf.c       8.1 (Berkeley) 6/6/93";
     41static char sccsid[] = "@(#)buf.c       8.1 (Berkeley) 6/6/93";
    4242#else
    4343static const char rcsid[] =
    4444  "$FreeBSD: src/usr.bin/make/buf.c,v 1.11 1999/09/11 13:08:01 hoek Exp $";
    4545#endif
     46#define KLIBFILEDEF rcsid
    4647#endif /* not lint */
    4748
    4849/*-
    4950 * buf.c --
    50  *      Functions for automatically-expanded buffers.
     51 *      Functions for automatically-expanded buffers.
    5152 */
    5253
     
    6162/*
    6263 * BufExpand --
    63  *      Expand the given buffer to hold the given number of additional
    64  *      bytes.
    65  *      Makes sure there's room for an extra NULL byte at the end of the
    66  *      buffer in case it holds a string.
     64 *      Expand the given buffer to hold the given number of additional
     65 *      bytes.
     66 *      Makes sure there's room for an extra NULL byte at the end of the
     67 *      buffer in case it holds a string.
    6768 */
    6869#define BufExpand(bp,nb) \
    69         if (bp->left < (nb)+1) {\
    70             int newSize = (bp)->size + max((nb)+1,BUF_ADD_INC); \
    71             Byte  *newBuf = (Byte *) erealloc((bp)->buffer, newSize); \
    72             \
    73             (bp)->inPtr = newBuf + ((bp)->inPtr - (bp)->buffer); \
    74             (bp)->outPtr = newBuf + ((bp)->outPtr - (bp)->buffer);\
    75             (bp)->buffer = newBuf;\
    76             (bp)->size = newSize;\
    77             (bp)->left = newSize - ((bp)->inPtr - (bp)->buffer);\
    78         }
    79 
    80 #define BUF_DEF_SIZE    256     /* Default buffer size */
    81 #define BUF_ADD_INC     256     /* Expansion increment when Adding */
    82 #define BUF_UNGET_INC   16      /* Expansion increment when Ungetting */
     70        if (bp->left < (nb)+1) {\
     71            int newSize = (bp)->size + max((nb)+1,BUF_ADD_INC); \
     72            Byte  *newBuf = (Byte *) erealloc((bp)->buffer, newSize); \
     73            \
     74            (bp)->inPtr = newBuf + ((bp)->inPtr - (bp)->buffer); \
     75            (bp)->outPtr = newBuf + ((bp)->outPtr - (bp)->buffer);\
     76            (bp)->buffer = newBuf;\
     77            (bp)->size = newSize;\
     78            (bp)->left = newSize - ((bp)->inPtr - (bp)->buffer);\
     79        }
     80
     81#define BUF_DEF_SIZE    256     /* Default buffer size */
     82#define BUF_ADD_INC     256     /* Expansion increment when Adding */
     83#define BUF_UNGET_INC   16      /* Expansion increment when Ungetting */
    8384
    8485/*-
    8586 *-----------------------------------------------------------------------
    8687 * Buf_OvAddByte --
    87  *      Add a single byte to the buffer.  left is zero or negative.
    88  *
    89  * Results:
    90  *      None.
    91  *
    92  * Side Effects:
    93  *      The buffer may be expanded.
     88 *      Add a single byte to the buffer.  left is zero or negative.
     89 *
     90 * Results:
     91 *      None.
     92 *
     93 * Side Effects:
     94 *      The buffer may be expanded.
    9495 *
    9596 *-----------------------------------------------------------------------
     
    117118 *-----------------------------------------------------------------------
    118119 * Buf_AddBytes --
    119  *      Add a number of bytes to the buffer.
    120  *
    121  * Results:
    122  *      None.
    123  *
    124  * Side Effects:
    125  *      Guess what?
     120 *      Add a number of bytes to the buffer.
     121 *
     122 * Results:
     123 *      None.
     124 *
     125 * Side Effects:
     126 *      Guess what?
    126127 *
    127128 *-----------------------------------------------------------------------
     
    130131Buf_AddBytes (bp, numBytes, bytesPtr)
    131132    register Buffer bp;
    132     int     numBytes;
     133    int     numBytes;
    133134    const Byte *bytesPtr;
    134135{
     
    150151 *-----------------------------------------------------------------------
    151152 * Buf_UngetByte --
    152  *      Place the byte back at the beginning of the buffer.
    153  *
    154  * Results:
    155  *      SUCCESS if the byte was added ok. FAILURE if not.
    156  *
    157  * Side Effects:
    158  *      The byte is stuffed in the buffer and outPtr is decremented.
     153 *      Place the byte back at the beginning of the buffer.
     154 *
     155 * Results:
     156 *      SUCCESS if the byte was added ok. FAILURE if not.
     157 *
     158 * Side Effects:
     159 *      The byte is stuffed in the buffer and outPtr is decremented.
    159160 *
    160161 *-----------------------------------------------------------------------
     
    167168
    168169    if (bp->outPtr != bp->buffer) {
    169         bp->outPtr--;
    170         *bp->outPtr = byte;
     170        bp->outPtr--;
     171        *bp->outPtr = byte;
    171172    } else if (bp->outPtr == bp->inPtr) {
    172         *bp->inPtr = byte;
    173         bp->inPtr++;
    174         bp->left--;
    175         *bp->inPtr = 0;
     173        *bp->inPtr = byte;
     174        bp->inPtr++;
     175        bp->left--;
     176        *bp->inPtr = 0;
    176177    } else {
    177         /*
    178         * Yech. have to expand the buffer to stuff this thing in.
    179         * We use a different expansion constant because people don't
    180         * usually push back many bytes when they're doing it a byte at
    181         * a time...
    182         */
    183         int       numBytes = bp->inPtr - bp->outPtr;
    184         Byte      *newBuf;
    185 
    186         newBuf = (Byte *)emalloc(bp->size + BUF_UNGET_INC);
    187         memcpy ((char *)(newBuf+BUF_UNGET_INC), (char *)bp->outPtr, numBytes+1);
    188         bp->outPtr = newBuf + BUF_UNGET_INC;
    189         bp->inPtr = bp->outPtr + numBytes;
    190         efree ((char *)bp->buffer);
    191         bp->buffer = newBuf;
    192         bp->size += BUF_UNGET_INC;
    193         bp->left = bp->size - (bp->inPtr - bp->buffer);
    194         bp->outPtr -= 1;
    195         *bp->outPtr = byte;
     178        /*
     179        * Yech. have to expand the buffer to stuff this thing in.
     180        * We use a different expansion constant because people don't
     181        * usually push back many bytes when they're doing it a byte at
     182        * a time...
     183        */
     184        int       numBytes = bp->inPtr - bp->outPtr;
     185        Byte      *newBuf;
     186
     187        newBuf = (Byte *)emalloc(bp->size + BUF_UNGET_INC);
     188        memcpy ((char *)(newBuf+BUF_UNGET_INC), (char *)bp->outPtr, numBytes+1);
     189        bp->outPtr = newBuf + BUF_UNGET_INC;
     190        bp->inPtr = bp->outPtr + numBytes;
     191        efree ((char *)bp->buffer);
     192        bp->buffer = newBuf;
     193        bp->size += BUF_UNGET_INC;
     194        bp->left = bp->size - (bp->inPtr - bp->buffer);
     195        bp->outPtr -= 1;
     196        *bp->outPtr = byte;
    196197    }
    197198}
     
    201202 *-----------------------------------------------------------------------
    202203 * Buf_UngetBytes --
    203  *      Push back a series of bytes at the beginning of the buffer.
    204  *
    205  * Results:
    206  *      None.
    207  *
    208  * Side Effects:
    209  *      outPtr is decremented and the bytes copied into the buffer.
     204 *      Push back a series of bytes at the beginning of the buffer.
     205 *
     206 * Results:
     207 *      None.
     208 *
     209 * Side Effects:
     210 *      outPtr is decremented and the bytes copied into the buffer.
    210211 *
    211212 *-----------------------------------------------------------------------
     
    214215Buf_UngetBytes (bp, numBytes, bytesPtr)
    215216    register Buffer bp;
    216     int     numBytes;
     217    int     numBytes;
    217218    Byte    *bytesPtr;
    218219{
    219220
    220221    if (bp->outPtr - bp->buffer >= numBytes) {
    221         bp->outPtr -= numBytes;
    222         memcpy (bp->outPtr, bytesPtr, numBytes);
     222        bp->outPtr -= numBytes;
     223        memcpy (bp->outPtr, bytesPtr, numBytes);
    223224    } else if (bp->outPtr == bp->inPtr) {
    224         Buf_AddBytes (bp, numBytes, bytesPtr);
     225        Buf_AddBytes (bp, numBytes, bytesPtr);
    225226    } else {
    226         int       curNumBytes = bp->inPtr - bp->outPtr;
    227         Byte      *newBuf;
    228         int       newBytes = max(numBytes,BUF_UNGET_INC);
    229 
    230         newBuf = (Byte *)emalloc (bp->size + newBytes);
    231         memcpy((char *)(newBuf+newBytes), (char *)bp->outPtr, curNumBytes+1);
    232         bp->outPtr = newBuf + newBytes;
    233         bp->inPtr = bp->outPtr + curNumBytes;
    234         efree ((char *)bp->buffer);
    235         bp->buffer = newBuf;
    236         bp->size += newBytes;
    237         bp->left = bp->size - (bp->inPtr - bp->buffer);
    238         bp->outPtr -= numBytes;
    239         memcpy ((char *)bp->outPtr, (char *)bytesPtr, numBytes);
     227        int       curNumBytes = bp->inPtr - bp->outPtr;
     228        Byte      *newBuf;
     229        int       newBytes = max(numBytes,BUF_UNGET_INC);
     230
     231        newBuf = (Byte *)emalloc (bp->size + newBytes);
     232        memcpy((char *)(newBuf+newBytes), (char *)bp->outPtr, curNumBytes+1);
     233        bp->outPtr = newBuf + newBytes;
     234        bp->inPtr = bp->outPtr + curNumBytes;
     235        efree ((char *)bp->buffer);
     236        bp->buffer = newBuf;
     237        bp->size += newBytes;
     238        bp->left = bp->size - (bp->inPtr - bp->buffer);
     239        bp->outPtr -= numBytes;
     240        memcpy ((char *)bp->outPtr, (char *)bytesPtr, numBytes);
    240241    }
    241242}
     
    245246 *-----------------------------------------------------------------------
    246247 * Buf_GetByte --
    247  *      Return the next byte from the buffer. Actually returns an integer.
    248  *
    249  * Results:
    250  *      Returns BUF_ERROR if there's no byte in the buffer, or the byte
    251  *      itself if there is one.
    252  *
    253  * Side Effects:
    254  *      outPtr is incremented and both outPtr and inPtr will be reset if
    255  *      the buffer is emptied.
     248 *      Return the next byte from the buffer. Actually returns an integer.
     249 *
     250 * Results:
     251 *      Returns BUF_ERROR if there's no byte in the buffer, or the byte
     252 *      itself if there is one.
     253 *
     254 * Side Effects:
     255 *      outPtr is incremented and both outPtr and inPtr will be reset if
     256 *      the buffer is emptied.
    256257 *
    257258 *-----------------------------------------------------------------------
     
    261262    register Buffer bp;
    262263{
    263     int     res;
     264    int     res;
    264265
    265266    if (bp->inPtr == bp->outPtr) {
    266         return (BUF_ERROR);
     267        return (BUF_ERROR);
    267268    } else {
    268         res = (int) *bp->outPtr;
    269         bp->outPtr += 1;
    270         if (bp->outPtr == bp->inPtr) {
    271             bp->outPtr = bp->inPtr = bp->buffer;
    272             bp->left = bp->size;
    273             *bp->inPtr = 0;
    274         }
    275         return (res);
     269        res = (int) *bp->outPtr;
     270        bp->outPtr += 1;
     271        if (bp->outPtr == bp->inPtr) {
     272            bp->outPtr = bp->inPtr = bp->buffer;
     273            bp->left = bp->size;
     274            *bp->inPtr = 0;
     275        }
     276        return (res);
    276277    }
    277278}
     
    281282 *-----------------------------------------------------------------------
    282283 * Buf_GetBytes --
    283  *      Extract a number of bytes from the buffer.
    284  *
    285  * Results:
    286  *      The number of bytes gotten.
    287  *
    288  * Side Effects:
    289  *      The passed array is overwritten.
     284 *      Extract a number of bytes from the buffer.
     285 *
     286 * Results:
     287 *      The number of bytes gotten.
     288 *
     289 * Side Effects:
     290 *      The passed array is overwritten.
    290291 *
    291292 *-----------------------------------------------------------------------
     
    294295Buf_GetBytes (bp, numBytes, bytesPtr)
    295296    register Buffer bp;
    296     int     numBytes;
     297    int     numBytes;
    297298    Byte    *bytesPtr;
    298299{
    299300
    300301    if (bp->inPtr - bp->outPtr < numBytes) {
    301         numBytes = bp->inPtr - bp->outPtr;
     302        numBytes = bp->inPtr - bp->outPtr;
    302303    }
    303304    memcpy (bytesPtr, bp->outPtr, numBytes);
     
    305306
    306307    if (bp->outPtr == bp->inPtr) {
    307         bp->outPtr = bp->inPtr = bp->buffer;
    308         bp->left = bp->size;
    309         *bp->inPtr = 0;
     308        bp->outPtr = bp->inPtr = bp->buffer;
     309        bp->left = bp->size;
     310        *bp->inPtr = 0;
    310311    }
    311312    return (numBytes);
     
    316317 *-----------------------------------------------------------------------
    317318 * Buf_GetAll --
    318  *      Get all the available data at once.
    319  *
    320  * Results:
    321  *      A pointer to the data and the number of bytes available.
    322  *
    323  * Side Effects:
    324  *      None.
     319 *      Get all the available data at once.
     320 *
     321 * Results:
     322 *      A pointer to the data and the number of bytes available.
     323 *
     324 * Side Effects:
     325 *      None.
    325326 *
    326327 *-----------------------------------------------------------------------
     
    329330Buf_GetAll (bp, numBytesPtr)
    330331    register Buffer bp;
    331     int     *numBytesPtr;
     332    int     *numBytesPtr;
    332333{
    333334
    334335    if (numBytesPtr != (int *)NULL) {
    335         *numBytesPtr = bp->inPtr - bp->outPtr;
     336        *numBytesPtr = bp->inPtr - bp->outPtr;
    336337    }
    337338
     
    343344 *-----------------------------------------------------------------------
    344345 * Buf_Discard --
    345  *      Throw away bytes in a buffer.
    346  *
    347  * Results:
    348  *      None.
    349  *
    350  * Side Effects:
    351  *      The bytes are discarded.
     346 *      Throw away bytes in a buffer.
     347 *
     348 * Results:
     349 *      None.
     350 *
     351 * Side Effects:
     352 *      The bytes are discarded.
    352353 *
    353354 *-----------------------------------------------------------------------
     
    356357Buf_Discard (bp, numBytes)
    357358    register Buffer bp;
    358     int     numBytes;
     359    int     numBytes;
    359360{
    360361
    361362    if (bp->inPtr - bp->outPtr <= numBytes) {
    362         bp->inPtr = bp->outPtr = bp->buffer;
    363         bp->left = bp->size;
    364         *bp->inPtr = 0;
     363        bp->inPtr = bp->outPtr = bp->buffer;
     364        bp->left = bp->size;
     365        *bp->inPtr = 0;
    365366    } else {
    366         bp->outPtr += numBytes;
     367        bp->outPtr += numBytes;
    367368    }
    368369}
     
    372373 *-----------------------------------------------------------------------
    373374 * Buf_Size --
    374  *      Returns the number of bytes in the given buffer. Doesn't include
    375  *      the null-terminating byte.
    376  *
    377  * Results:
    378  *      The number of bytes.
    379  *
    380  * Side Effects:
    381  *      None.
     375 *      Returns the number of bytes in the given buffer. Doesn't include
     376 *      the null-terminating byte.
     377 *
     378 * Results:
     379 *      The number of bytes.
     380 *
     381 * Side Effects:
     382 *      None.
    382383 *
    383384 *-----------------------------------------------------------------------
     
    394395 *-----------------------------------------------------------------------
    395396 * Buf_Init --
    396  *      Initialize a buffer. If no initial size is given, a reasonable
    397  *      default is used.
    398  *
    399  * Results:
    400  *      A buffer to be given to other functions in this library.
    401  *
    402  * Side Effects:
    403  *      The buffer is created, the space allocated and pointers
    404  *      initialized.
     397 *      Initialize a buffer. If no initial size is given, a reasonable
     398 *      default is used.
     399 *
     400 * Results:
     401 *      A buffer to be given to other functions in this library.
     402 *
     403 * Side Effects:
     404 *      The buffer is created, the space allocated and pointers
     405 *      initialized.
    405406 *
    406407 *-----------------------------------------------------------------------
     
    408409Buffer
    409410Buf_Init (size)
    410     int     size;       /* Initial size for the buffer */
    411 {
    412     Buffer bp;          /* New Buffer */
     411    int     size;       /* Initial size for the buffer */
     412{
     413    Buffer bp;          /* New Buffer */
    413414
    414415    bp = (Buffer)emalloc(sizeof(*bp));
    415416
    416417    if (size <= 0) {
    417         size = BUF_DEF_SIZE;
     418        size = BUF_DEF_SIZE;
    418419    }
    419420    bp->left = bp->size = size;
     
    429430 *-----------------------------------------------------------------------
    430431 * Buf_Destroy --
    431  *      Nuke a buffer and all its resources.
    432  *
    433  * Results:
    434  *      None.
    435  *
    436  * Side Effects:
    437  *      The buffer is freed.
     432 *      Nuke a buffer and all its resources.
     433 *
     434 * Results:
     435 *      None.
     436 *
     437 * Side Effects:
     438 *      The buffer is freed.
    438439 *
    439440 *-----------------------------------------------------------------------
     
    441442void
    442443Buf_Destroy (buf, freeData)
    443     Buffer  buf;        /* Buffer to destroy */
    444     Boolean freeData;   /* TRUE if the data should be destroyed as well */
     444    Buffer  buf;        /* Buffer to destroy */
     445    Boolean freeData;   /* TRUE if the data should be destroyed as well */
    445446{
    446447
    447448    if (freeData) {
    448         efree ((char *)buf->buffer);
     449        efree ((char *)buf->buffer);
    449450    }
    450451    efree ((char *)buf);
     
    468469void
    469470Buf_ReplaceLastByte (buf, byte)
    470     Buffer buf; /* buffer to augment */
    471     int byte;   /* byte to be written */
     471    Buffer buf; /* buffer to augment */
     472    int byte;   /* byte to be written */
    472473{
    473474    if (buf->inPtr == buf->outPtr)
  • trunk/src/kmk/compat.c

    r35 r51  
    1818 * 3. All advertising materials mentioning features or use of this software
    1919 *    must display the following acknowledgement:
    20  *      This product includes software developed by the University of
    21  *      California, Berkeley and its contributors.
     20 *      This product includes software developed by the University of
     21 *      California, Berkeley and its contributors.
    2222 * 4. Neither the name of the University nor the names of its contributors
    2323 *    may be used to endorse or promote products derived from this software
     
    3939#ifndef lint
    4040#if 0
    41 static char sccsid[] = "@(#)compat.c    8.2 (Berkeley) 3/19/94";
     41static char sccsid[] = "@(#)compat.c    8.2 (Berkeley) 3/19/94";
    4242#else
    4343static const char rcsid[] =
    4444  "$FreeBSD: src/usr.bin/make/compat.c,v 1.16.2.2 2000/07/01 12:24:21 ps Exp $";
    4545#endif
     46#define KLIBFILEDEF rcsid
    4647#endif /* not lint */
    4748
    4849/*-
    4950 * compat.c --
    50  *      The routines in this file implement the full-compatibility
    51  *      mode of PMake. Most of the special functionality of PMake
    52  *      is available in this mode. Things not supported:
    53  *          - different shells.
    54  *          - friendly variable substitution.
     51 *      The routines in this file implement the full-compatibility
     52 *      mode of PMake. Most of the special functionality of PMake
     53 *      is available in this mode. Things not supported:
     54 *          - different shells.
     55 *          - friendly variable substitution.
    5556 *
    5657 * Interface:
    57  *      Compat_Run          Initialize things for this module and recreate
    58  *                          thems as need creatin'
     58 *      Compat_Run          Initialize things for this module and recreate
     59 *                          thems as need creatin'
    5960 */
    6061
     
    8788 */
    8889
    89 static char         meta[256];
    90 
    91 static GNode        *curTarg = NILGNODE;
    92 static GNode        *ENDNode;
     90static char         meta[256];
     91
     92static GNode        *curTarg = NILGNODE;
     93static GNode        *ENDNode;
    9394static void CompatInterrupt __P((int));
    9495static int CompatRunCommand __P((ClientData, ClientData));
     
    9697
    9798static char *sh_builtin[] = {
    98         "alias", "cd", "eval", "exec", "exit", "read", "set", "ulimit",
    99         "unalias", "umask", "unset", "wait", ":", 0};
     99        "alias", "cd", "eval", "exec", "exit", "read", "set", "ulimit",
     100        "unalias", "umask", "unset", "wait", ":", 0};
    100101
    101102/*-
    102103 *-----------------------------------------------------------------------
    103104 * CompatInterrupt --
    104  *      Interrupt the creation of the current target and remove it if
    105  *      it ain't precious.
     105 *      Interrupt the creation of the current target and remove it if
     106 *      it ain't precious.
    106107 *
    107108 * Results:
    108  *      None.
     109 *      None.
    109110 *
    110111 * Side Effects:
    111  *      The target is removed and the process exits. If .INTERRUPT exists,
    112  *      its commands are run first WITH INTERRUPTS IGNORED..
     112 *      The target is removed and the process exits. If .INTERRUPT exists,
     113 *      its commands are run first WITH INTERRUPTS IGNORED..
    113114 *
    114115 *-----------------------------------------------------------------------
     
    116117static void
    117118CompatInterrupt (signo)
    118     int     signo;
     119    int     signo;
    119120{
    120121    GNode   *gn;
    121122
    122123    if ((curTarg != NILGNODE) && !Targ_Precious (curTarg)) {
    123         char      *p1;
    124         char      *file = Var_Value (TARGET, curTarg, &p1);
    125 
    126         if (!noExecute && eunlink(file) != -1) {
    127             printf ("*** %s removed\n", file);
    128         }
    129         efree(p1);
    130 
    131         /*
    132         * Run .INTERRUPT only if hit with interrupt signal
    133         */
    134         if (signo == SIGINT) {
    135             gn = Targ_FindNode(".INTERRUPT", TARG_NOCREATE);
    136             if (gn != NILGNODE) {
    137                 Lst_ForEach(gn->commands, CompatRunCommand, (ClientData)gn);
    138             }
    139         }
     124        char      *p1;
     125        char      *file = Var_Value (TARGET, curTarg, &p1);
     126
     127        if (!noExecute && eunlink(file) != -1) {
     128            printf ("*** %s removed\n", file);
     129        }
     130        efree(p1);
     131
     132        /*
     133        * Run .INTERRUPT only if hit with interrupt signal
     134        */
     135        if (signo == SIGINT) {
     136            gn = Targ_FindNode(".INTERRUPT", TARG_NOCREATE);
     137            if (gn != NILGNODE) {
     138                Lst_ForEach(gn->commands, CompatRunCommand, (ClientData)gn);
     139            }
     140        }
    140141
    141142    }
    142143    #if !(defined(OS2) && defined(__IBMC__))
    143144    if (signo == SIGQUIT)
    144         exit(signo);
     145        exit(signo);
    145146    #endif
    146147    (void) signal(signo, SIG_DFL);
     
    152153 *-----------------------------------------------------------------------
    153154 * shellneed --
    154  *     
     155 *
    155156 * Results:
    156  *      Returns 1 if a specified line must be executed by the shell,
    157  *      0 if it can be run via execve, and -1 if the command is a no-op.
     157 *      Returns 1 if a specified line must be executed by the shell,
     158 *      0 if it can be run via execve, and -1 if the command is a no-op.
    158159 *
    159160 * Side Effects:
    160  *      None.
    161  *     
     161 *      None.
     162 *
    162163 *-----------------------------------------------------------------------
    163164 */
    164165static int
    165166shellneed (cmd)
    166         char *cmd;
     167        char *cmd;
    167168{
    168         char **av, **p;
    169         int ac;
    170 
    171         av = brk_string(cmd, &ac, TRUE);
    172         for(p = sh_builtin; *p != 0; p++)
    173                 if (strcmp(av[1], *p) == 0)
    174                         return (1);
    175         return (0);
     169        char **av, **p;
     170        int ac;
     171
     172        av = brk_string(cmd, &ac, TRUE);
     173        for(p = sh_builtin; *p != 0; p++)
     174                if (strcmp(av[1], *p) == 0)
     175                        return (1);
     176        return (0);
    176177}
    177178
     
    180181 *-----------------------------------------------------------------------
    181182 * CompatRunCommand --
    182  *      Execute the next command for a target. If the command returns an
    183  *      error, the node's made field is set to ERROR and creation stops.
     183 *      Execute the next command for a target. If the command returns an
     184 *      error, the node's made field is set to ERROR and creation stops.
    184185 *
    185186 * Results:
    186  *      0 if the command succeeded, 1 if an error occurred.
     187 *      0 if the command succeeded, 1 if an error occurred.
    187188 *
    188189 * Side Effects:
    189  *      The node's 'made' field may be set to ERROR.
     190 *      The node's 'made' field may be set to ERROR.
    190191 *
    191192 *-----------------------------------------------------------------------
     
    193194static int
    194195CompatRunCommand (cmdp, gnp)
    195     ClientData    cmdp;         /* Command to execute */
    196     ClientData    gnp;          /* Node from which the command came */
     196    ClientData    cmdp;         /* Command to execute */
     197    ClientData    gnp;          /* Node from which the command came */
    197198{
    198     char          *cmdStart;    /* Start of expanded command */
     199    char          *cmdStart;    /* Start of expanded command */
    199200    register char *cp;
    200     Boolean       silent,       /* Don't print command */
    201                   errCheck;     /* Check errors */
    202     int           reason;       /* Reason for child's death */
    203     int           status;       /* Description of child's death */
    204     int           cpid;         /* Child actually found */
    205     ReturnStatus  stat;         /* Status of fork */
    206     LstNode       cmdNode;      /* Node where current command is located */
    207     char          **av;         /* Argument vector for thing to exec */
    208     int           argc;         /* Number of arguments in av or 0 if not
    209                                 * dynamically allocated */
    210     Boolean       local;        /* TRUE if command should be executed
    211                                 * locally */
    212     int           internal;     /* Various values.. */
    213     char          *cmd = (char *) cmdp;
    214     GNode         *gn = (GNode *) gnp;
     201    Boolean       silent,       /* Don't print command */
     202                  errCheck;     /* Check errors */
     203    int           reason;       /* Reason for child's death */
     204    int           status;       /* Description of child's death */
     205    int           cpid;         /* Child actually found */
     206    ReturnStatus  stat;         /* Status of fork */
     207    LstNode       cmdNode;      /* Node where current command is located */
     208    char          **av;         /* Argument vector for thing to exec */
     209    int           argc;         /* Number of arguments in av or 0 if not
     210                                * dynamically allocated */
     211    Boolean       local;        /* TRUE if command should be executed
     212                                * locally */
     213    int           internal;     /* Various values.. */
     214    char          *cmd = (char *) cmdp;
     215    GNode         *gn = (GNode *) gnp;
    215216
    216217    /*
     
    236237
    237238    if (*cmdStart == '\0') {
    238         efree(cmdStart);
    239         Error("%s expands to empty string", cmd);
    240         return(0);
     239        efree(cmdStart);
     240        Error("%s expands to empty string", cmd);
     241        return(0);
    241242    } else {
    242         cmd = cmdStart;
     243        cmd = cmdStart;
    243244    }
    244245    Lst_Replace (cmdNode, (ClientData)cmdStart);
    245246
    246247    if ((gn->type & OP_SAVE_CMDS) && (gn != ENDNode)) {
    247         (void)Lst_AtEnd(ENDNode->commands, (ClientData)cmdStart);
    248         return(0);
     248        (void)Lst_AtEnd(ENDNode->commands, (ClientData)cmdStart);
     249        return(0);
    249250    } else if (strcmp(cmdStart, "...") == 0) {
    250         gn->type |= OP_SAVE_CMDS;
    251         return(0);
     251        gn->type |= OP_SAVE_CMDS;
     252        return(0);
    252253    }
    253254
    254255    while ((*cmd == '@') || (*cmd == '-')) {
    255         if (*cmd == '@') {
    256             silent = DEBUG(LOUD) ? FALSE : TRUE;
    257         } else {
    258             errCheck = FALSE;
    259         }
    260         cmd++;
     256        if (*cmd == '@') {
     257            silent = DEBUG(LOUD) ? FALSE : TRUE;
     258        } else {
     259            errCheck = FALSE;
     260        }
     261        cmd++;
    261262    }
    262263
    263264    while (isspace((unsigned char)*cmd))
    264         cmd++;
     265        cmd++;
    265266
    266267    /*
     
    270271     */
    271272    for (cp = cmd; !meta[(unsigned char)*cp]; cp++) {
    272         continue;
     273        continue;
    273274    }
    274275
     
    278279     */
    279280    if (!silent || noExecute) {
    280         printf ("%s\n", cmd);
    281         fflush(stdout);
     281        printf ("%s\n", cmd);
     282        fflush(stdout);
    282283    }
    283284
     
    287288     */
    288289    if (noExecute) {
    289         return (0);
     290        return (0);
    290291    }
    291292
    292293    if (*cp != '\0') {
    293         /*
    294         * If *cp isn't the null character, we hit a "meta" character and
    295         * need to pass the command off to the shell. We give the shell the
    296         * -e flag as well as -c if it's supposed to exit when it hits an
    297         * error.
    298         */
    299         static char     *shargv[4] = { "/bin/sh" };
    300 
    301         shargv[1] = (errCheck ? "-ec" : "-c");
    302         shargv[2] = cmd;
    303         shargv[3] = (char *)NULL;
    304         av = shargv;
    305         argc = 0;
     294        /*
     295        * If *cp isn't the null character, we hit a "meta" character and
     296        * need to pass the command off to the shell. We give the shell the
     297        * -e flag as well as -c if it's supposed to exit when it hits an
     298        * error.
     299        */
     300        static char     *shargv[4] = { "/bin/sh" };
     301
     302        shargv[1] = (errCheck ? "-ec" : "-c");
     303        shargv[2] = cmd;
     304        shargv[3] = (char *)NULL;
     305        av = shargv;
     306        argc = 0;
    306307    } else if ((internal = shellneed(cmd))) {
    307         /*
    308         * This command must be passed by the shell for other reasons..
    309         * or.. possibly not at all.
    310         */
    311         static char     *shargv[4] = { "/bin/sh" };
    312 
    313         if (internal == -1) {
    314                 /* Command does not need to be executed */
    315                 return (0);
    316         }
    317 
    318         shargv[1] = (errCheck ? "-ec" : "-c");
    319         shargv[2] = cmd;
    320         shargv[3] = (char *)NULL;
    321         av = shargv;
    322         argc = 0;
     308        /*
     309        * This command must be passed by the shell for other reasons..
     310        * or.. possibly not at all.
     311        */
     312        static char     *shargv[4] = { "/bin/sh" };
     313
     314        if (internal == -1) {
     315                /* Command does not need to be executed */
     316                return (0);
     317        }
     318
     319        shargv[1] = (errCheck ? "-ec" : "-c");
     320        shargv[2] = cmd;
     321        shargv[3] = (char *)NULL;
     322        av = shargv;
     323        argc = 0;
    323324    } else {
    324         /*
    325         * No meta-characters, so no need to exec a shell. Break the command
    326         * into words to form an argument vector we can execute.
    327         * brk_string sticks our name in av[0], so we have to
    328         * skip over it...
    329         */
    330         av = brk_string(cmd, &argc, TRUE);
    331         av += 1;
     325        /*
     326        * No meta-characters, so no need to exec a shell. Break the command
     327        * into words to form an argument vector we can execute.
     328        * brk_string sticks our name in av[0], so we have to
     329        * skip over it...
     330        */
     331        av = brk_string(cmd, &argc, TRUE);
     332        av += 1;
    332333    }
    333334
     
    342343    cpid = vfork();
    343344    if (cpid < 0) {
    344         Fatal("Could not fork");
     345        Fatal("Could not fork");
    345346    }
    346347    if (cpid == 0) {
    347         if (local) {
    348             execvp(av[0], av);
    349             (void) write (2, av[0], strlen (av[0]));
    350             (void) write (2, ":", 1);
    351             (void) write (2, strerror(errno), strlen(strerror(errno)));
    352             (void) write (2, "\n", 1);
    353         } else {
    354             (void)execv(av[0], av);
    355         }
    356         exit(1);
     348        if (local) {
     349            execvp(av[0], av);
     350            (void) write (2, av[0], strlen (av[0]));
     351            (void) write (2, ":", 1);
     352            (void) write (2, strerror(errno), strlen(strerror(errno)));
     353            (void) write (2, "\n", 1);
     354        } else {
     355            (void)execv(av[0], av);
     356        }
     357        exit(1);
    357358    }
    358359#endif
     
    365366     */
    366367    if (!DEBUG(GRAPH2)) {
    367         efree(cmdStart);
    368         Lst_Replace (cmdNode, cmdp);
     368        efree(cmdStart);
     369        Lst_Replace (cmdNode, cmdp);
    369370    }
    370371
     
    374375    while (1) {
    375376
    376         while ((stat = wait(&reason)) != cpid) {
    377             if (stat == -1 && errno != EINTR) {
    378                 break;
    379             }
    380         }
    381 
    382         if (stat > -1) {
    383             if (WIFSTOPPED(reason)) {
    384                 status = WSTOPSIG(reason);              /* stopped */
    385             } else if (WIFEXITED(reason)) {
    386                 status = WEXITSTATUS(reason);           /* exited */
    387                 if (status != 0) {
    388                     printf ("*** Error code %d", status);
    389                 }
    390             } else {
    391                 status = WTERMSIG(reason);              /* signaled */
    392                 printf ("*** Signal %d", status);
    393             }
    394 
    395 
    396             if (!WIFEXITED(reason) || (status != 0)) {
    397                 if (errCheck) {
    398                     gn->made = ERROR;
    399                     if (keepgoing) {
    400                         /*
    401                         * Abort the current target, but let others
    402                         * continue.
    403                         */
    404                         printf (" (continuing)\n");
    405                     }
    406                 } else {
    407                     /*
    408                      * Continue executing commands for this target.
    409                      * If we return 0, this will happen...
    410                      */
    411                     printf (" (ignored)\n");
    412                     status = 0;
    413                 }
    414             }
    415             break;
    416         } else {
    417             Fatal ("error in wait: %d", stat);
    418             /*NOTREACHED*/
    419         }
     377        while ((stat = wait(&reason)) != cpid) {
     378            if (stat == -1 && errno != EINTR) {
     379                break;
     380            }
     381        }
     382
     383        if (stat > -1) {
     384            if (WIFSTOPPED(reason)) {
     385                status = WSTOPSIG(reason);              /* stopped */
     386            } else if (WIFEXITED(reason)) {
     387                status = WEXITSTATUS(reason);           /* exited */
     388                if (status != 0) {
     389                    printf ("*** Error code %d", status);
     390                }
     391            } else {
     392                status = WTERMSIG(reason);              /* signaled */
     393                printf ("*** Signal %d", status);
     394            }
     395
     396
     397            if (!WIFEXITED(reason) || (status != 0)) {
     398                if (errCheck) {
     399                    gn->made = ERROR;
     400                    if (keepgoing) {
     401                        /*
     402                        * Abort the current target, but let others
     403                        * continue.
     404                        */
     405                        printf (" (continuing)\n");
     406                    }
     407                } else {
     408                    /*
     409                     * Continue executing commands for this target.
     410                     * If we return 0, this will happen...
     411                     */
     412                    printf (" (ignored)\n");
     413                    status = 0;
     414                }
     415            }
     416            break;
     417        } else {
     418            Fatal ("error in wait: %d", stat);
     419            /*NOTREACHED*/
     420        }
    420421    }
    421422
     
    427428 *-----------------------------------------------------------------------
    428429 * CompatMake --
    429  *      Make a target.
     430 *      Make a target.
    430431 *
    431432 * Results:
    432  *      0
     433 *      0
    433434 *
    434435 * Side Effects:
    435  *      If an error is detected and not being ignored, the process exits.
     436 *      If an error is detected and not being ignored, the process exits.
    436437 *
    437438 *-----------------------------------------------------------------------
     
    439440static int
    440441CompatMake (gnp, pgnp)
    441     ClientData  gnp;        /* The node to make */
    442     ClientData  pgnp;       /* Parent to abort if necessary */
     442    ClientData  gnp;        /* The node to make */
     443    ClientData  pgnp;       /* Parent to abort if necessary */
    443444{
    444445    GNode *gn = (GNode *) gnp;
    445446    GNode *pgn = (GNode *) pgnp;
    446447    if (gn->type & OP_USE) {
    447         Make_HandleUse(gn, pgn);
     448        Make_HandleUse(gn, pgn);
    448449    } else if (gn->made == UNMADE) {
    449         /*
    450         * First mark ourselves to be made, then apply whatever transformations
    451         * the suffix module thinks are necessary. Once that's done, we can
    452         * descend and make all our children. If any of them has an error
    453         * but the -k flag was given, our 'make' field will be set FALSE again.
    454         * This is our signal to not attempt to do anything but abort our
    455         * parent as well.
    456         */
    457         gn->make = TRUE;
    458         gn->made = BEINGMADE;
    459         Suff_FindDeps (gn);
    460         Lst_ForEach (gn->children, CompatMake, (ClientData)gn);
    461         if (!gn->make) {
    462             gn->made = ABORTED;
    463             pgn->make = FALSE;
    464             return (0);
    465         }
    466 
    467         if (Lst_Member (gn->iParents, pgn) != NILLNODE) {
    468             char *p1;
    469             Var_Set (IMPSRC, Var_Value(TARGET, gn, &p1), pgn);
    470             efree(p1);
    471         }
    472 
    473         /*
    474         * All the children were made ok. Now cmtime contains the modification
    475         * time of the newest child, we need to find out if we exist and when
    476         * we were modified last. The criteria for datedness are defined by the
    477         * Make_OODate function.
    478         */
    479         if (DEBUG(MAKE)) {
    480             printf("Examining %s...", gn->name);
    481         }
    482         if (! Make_OODate(gn)) {
    483             gn->made = UPTODATE;
    484             if (DEBUG(MAKE)) {
    485                 printf("up-to-date.\n");
    486             }
    487             return (0);
    488         } else if (DEBUG(MAKE)) {
    489             printf("out-of-date.\n");
    490         }
    491 
    492         /*
    493         * If the user is just seeing if something is out-of-date, exit now
    494         * to tell him/her "yes".
    495         */
    496         if (queryFlag) {
    497             exit (-1);
    498         }
    499 
    500         /*
    501         * We need to be re-made. We also have to make sure we've got a $?
    502         * variable. To be nice, we also define the $> variable using
    503         * Make_DoAllVar().
    504         */
    505         Make_DoAllVar(gn);
    506 
    507         /*
    508         * Alter our type to tell if errors should be ignored or things
    509         * should not be printed so CompatRunCommand knows what to do.
    510         */
    511         if (Targ_Ignore (gn)) {
    512             gn->type |= OP_IGNORE;
    513         }
    514         if (Targ_Silent (gn)) {
    515             gn->type |= OP_SILENT;
    516         }
    517 
    518         if (Job_CheckCommands (gn, Fatal)) {
    519             /*
    520              * Our commands are ok, but we still have to worry about the -t
    521              * flag...
    522              */
    523             if (!touchFlag) {
    524                 curTarg = gn;
    525                 Lst_ForEach (gn->commands, CompatRunCommand, (ClientData)gn);
    526                 curTarg = NILGNODE;
    527             } else {
    528                 Job_Touch (gn, gn->type & OP_SILENT);
    529             }
    530         } else {
    531             gn->made = ERROR;
    532         }
    533 
    534         if (gn->made != ERROR) {
    535             /*
    536              * If the node was made successfully, mark it so, update
    537              * its modification time and timestamp all its parents. Note
    538              * that for .ZEROTIME targets, the timestamping isn't done.
    539              * This is to keep its state from affecting that of its parent.
    540              */
    541             gn->made = MADE;
     450        /*
     451        * First mark ourselves to be made, then apply whatever transformations
     452        * the suffix module thinks are necessary. Once that's done, we can
     453        * descend and make all our children. If any of them has an error
     454        * but the -k flag was given, our 'make' field will be set FALSE again.
     455        * This is our signal to not attempt to do anything but abort our
     456        * parent as well.
     457        */
     458        gn->make = TRUE;
     459        gn->made = BEINGMADE;
     460        Suff_FindDeps (gn);
     461        Lst_ForEach (gn->children, CompatMake, (ClientData)gn);
     462        if (!gn->make) {
     463            gn->made = ABORTED;
     464            pgn->make = FALSE;
     465            return (0);
     466        }
     467
     468        if (Lst_Member (gn->iParents, pgn) != NILLNODE) {
     469            char *p1;
     470            Var_Set (IMPSRC, Var_Value(TARGET, gn, &p1), pgn);
     471            efree(p1);
     472        }
     473
     474        /*
     475        * All the children were made ok. Now cmtime contains the modification
     476        * time of the newest child, we need to find out if we exist and when
     477        * we were modified last. The criteria for datedness are defined by the
     478        * Make_OODate function.
     479        */
     480        if (DEBUG(MAKE)) {
     481            printf("Examining %s...", gn->name);
     482        }
     483        if (! Make_OODate(gn)) {
     484            gn->made = UPTODATE;
     485            if (DEBUG(MAKE)) {
     486                printf("up-to-date.\n");
     487            }
     488            return (0);
     489        } else if (DEBUG(MAKE)) {
     490            printf("out-of-date.\n");
     491        }
     492
     493        /*
     494        * If the user is just seeing if something is out-of-date, exit now
     495        * to tell him/her "yes".
     496        */
     497        if (queryFlag) {
     498            exit (-1);
     499        }
     500
     501        /*
     502        * We need to be re-made. We also have to make sure we've got a $?
     503        * variable. To be nice, we also define the $> variable using
     504        * Make_DoAllVar().
     505        */
     506        Make_DoAllVar(gn);
     507
     508        /*
     509        * Alter our type to tell if errors should be ignored or things
     510        * should not be printed so CompatRunCommand knows what to do.
     511        */
     512        if (Targ_Ignore (gn)) {
     513            gn->type |= OP_IGNORE;
     514        }
     515        if (Targ_Silent (gn)) {
     516            gn->type |= OP_SILENT;
     517        }
     518
     519        if (Job_CheckCommands (gn, Fatal)) {
     520            /*
     521             * Our commands are ok, but we still have to worry about the -t
     522             * flag...
     523             */
     524            if (!touchFlag) {
     525                curTarg = gn;
     526                Lst_ForEach (gn->commands, CompatRunCommand, (ClientData)gn);
     527                curTarg = NILGNODE;
     528            } else {
     529                Job_Touch (gn, gn->type & OP_SILENT);
     530            }
     531        } else {
     532            gn->made = ERROR;
     533        }
     534
     535        if (gn->made != ERROR) {
     536            /*
     537             * If the node was made successfully, mark it so, update
     538             * its modification time and timestamp all its parents. Note
     539             * that for .ZEROTIME targets, the timestamping isn't done.
     540             * This is to keep its state from affecting that of its parent.
     541             */
     542            gn->made = MADE;
    542543#ifndef RECHECK
    543             /*
    544              * We can't re-stat the thing, but we can at least take care of
    545              * rules where a target depends on a source that actually creates
    546              * the target, but only if it has changed, e.g.
    547              *
    548              * parse.h : parse.o
    549              *
    550              * parse.o : parse.y
    551              *          yacc -d parse.y
    552              *          cc -c y.tab.c
    553              *          mv y.tab.o parse.o
    554              *          cmp -s y.tab.h parse.h || mv y.tab.h parse.h
    555              *
    556              * In this case, if the definitions produced by yacc haven't
    557              * changed from before, parse.h won't have been updated and
    558              * gn->mtime will reflect the current modification time for
    559              * parse.h. This is something of a kludge, I admit, but it's a
    560              * useful one..
    561              *
    562              * XXX: People like to use a rule like
    563              *
    564              * FRC:
    565              *
    566              * To force things that depend on FRC to be made, so we have to
    567              * check for gn->children being empty as well...
    568              */
    569             if (!Lst_IsEmpty(gn->commands) || Lst_IsEmpty(gn->children)) {
    570                 gn->mtime = now;
    571             }
     544            /*
     545             * We can't re-stat the thing, but we can at least take care of
     546             * rules where a target depends on a source that actually creates
     547             * the target, but only if it has changed, e.g.
     548             *
     549             * parse.h : parse.o
     550             *
     551             * parse.o : parse.y
     552             *          yacc -d parse.y
     553             *          cc -c y.tab.c
     554             *          mv y.tab.o parse.o
     555             *          cmp -s y.tab.h parse.h || mv y.tab.h parse.h
     556             *
     557             * In this case, if the definitions produced by yacc haven't
     558             * changed from before, parse.h won't have been updated and
     559             * gn->mtime will reflect the current modification time for
     560             * parse.h. This is something of a kludge, I admit, but it's a
     561             * useful one..
     562             *
     563             * XXX: People like to use a rule like
     564             *
     565             * FRC:
     566             *
     567             * To force things that depend on FRC to be made, so we have to
     568             * check for gn->children being empty as well...
     569             */
     570            if (!Lst_IsEmpty(gn->commands) || Lst_IsEmpty(gn->children)) {
     571                gn->mtime = now;
     572            }
    572573#else
    573             /*
    574              * This is what Make does and it's actually a good thing, as it
    575              * allows rules like
    576              *
    577              *  cmp -s y.tab.h parse.h || cp y.tab.h parse.h
    578              *
    579              * to function as intended. Unfortunately, thanks to the stateless
    580              * nature of NFS (and the speed of this program), there are times
    581              * when the modification time of a file created on a remote
    582              * machine will not be modified before the stat() implied by
    583              * the Dir_MTime occurs, thus leading us to believe that the file
    584              * is unchanged, wreaking havoc with files that depend on this one.
    585              *
    586              * I have decided it is better to make too much than to make too
    587              * little, so this stuff is commented out unless you're sure it's
    588              * ok.
    589              * -- ardeb 1/12/88
    590              */
    591             if (noExecute || Dir_MTime(gn) == 0) {
    592                 gn->mtime = now;
    593             }
    594             if (gn->cmtime > gn->mtime)
    595                 gn->mtime = gn->cmtime;
    596             if (DEBUG(MAKE)) {
    597                 printf("update time: %s\n", Targ_FmtTime(gn->mtime));
    598             }
     574            /*
     575             * This is what Make does and it's actually a good thing, as it
     576             * allows rules like
     577             *
     578             *  cmp -s y.tab.h parse.h || cp y.tab.h parse.h
     579             *
     580             * to function as intended. Unfortunately, thanks to the stateless
     581             * nature of NFS (and the speed of this program), there are times
     582             * when the modification time of a file created on a remote
     583             * machine will not be modified before the stat() implied by
     584             * the Dir_MTime occurs, thus leading us to believe that the file
     585             * is unchanged, wreaking havoc with files that depend on this one.
     586             *
     587             * I have decided it is better to make too much than to make too
     588             * little, so this stuff is commented out unless you're sure it's
     589             * ok.
     590             * -- ardeb 1/12/88
     591             */
     592            if (noExecute || Dir_MTime(gn) == 0) {
     593                gn->mtime = now;
     594            }
     595            if (gn->cmtime > gn->mtime)
     596                gn->mtime = gn->cmtime;
     597            if (DEBUG(MAKE)) {
     598                printf("update time: %s\n", Targ_FmtTime(gn->mtime));
     599            }
    599600#endif
    600             if (!(gn->type & OP_EXEC)) {
    601                 pgn->childMade = TRUE;
    602                 Make_TimeStamp(pgn, gn);
    603             }
    604         } else if (keepgoing) {
    605             pgn->make = FALSE;
    606         } else {
    607             char *p1;
    608 
    609             printf ("\n\nStop in %s.\n", Var_Value(".CURDIR", gn, &p1));
    610             efree(p1);
    611             exit (1);
    612         }
     601            if (!(gn->type & OP_EXEC)) {
     602                pgn->childMade = TRUE;
     603                Make_TimeStamp(pgn, gn);
     604            }
     605        } else if (keepgoing) {
     606            pgn->make = FALSE;
     607        } else {
     608            char *p1;
     609
     610            printf ("\n\nStop in %s.\n", Var_Value(".CURDIR", gn, &p1));
     611            efree(p1);
     612            exit (1);
     613        }
    613614    } else if (gn->made == ERROR) {
    614         /*
    615         * Already had an error when making this beastie. Tell the parent
    616         * to abort.
    617         */
    618         pgn->make = FALSE;
     615        /*
     616        * Already had an error when making this beastie. Tell the parent
     617        * to abort.
     618        */
     619        pgn->make = FALSE;
    619620    } else {
    620         if (Lst_Member (gn->iParents, pgn) != NILLNODE) {
    621             char *p1;
    622             Var_Set (IMPSRC, Var_Value(TARGET, gn, &p1), pgn);
    623             efree(p1);
    624         }
    625         switch(gn->made) {
    626             case BEINGMADE:
    627                 Error("Graph cycles through %s\n", gn->name);
    628                 gn->made = ERROR;
    629                 pgn->make = FALSE;
    630                 break;
    631             case MADE:
    632                 if ((gn->type & OP_EXEC) == 0) {
    633                     pgn->childMade = TRUE;
    634                     Make_TimeStamp(pgn, gn);
    635                 }
    636                 break;
    637             case UPTODATE:
    638                 if ((gn->type & OP_EXEC) == 0) {
    639                     Make_TimeStamp(pgn, gn);
    640                 }
    641                 break;
    642             default:
    643                 break;
    644         }
     621        if (Lst_Member (gn->iParents, pgn) != NILLNODE) {
     622            char *p1;
     623            Var_Set (IMPSRC, Var_Value(TARGET, gn, &p1), pgn);
     624            efree(p1);
     625        }
     626        switch(gn->made) {
     627            case BEINGMADE:
     628                Error("Graph cycles through %s\n", gn->name);
     629                gn->made = ERROR;
     630                pgn->make = FALSE;
     631                break;
     632            case MADE:
     633                if ((gn->type & OP_EXEC) == 0) {
     634                    pgn->childMade = TRUE;
     635                    Make_TimeStamp(pgn, gn);
     636                }
     637                break;
     638            case UPTODATE:
     639                if ((gn->type & OP_EXEC) == 0) {
     640                    Make_TimeStamp(pgn, gn);
     641                }
     642                break;
     643            default:
     644                break;
     645        }
    645646    }
    646647
     
    652653 *-----------------------------------------------------------------------
    653654 * Compat_Run --
    654  *      Initialize this mode and start making.
     655 *      Initialize this mode and start making.
    655656 *
    656657 * Results:
    657  *      None.
     658 *      None.
    658659 *
    659660 * Side Effects:
    660  *      Guess what?
     661 *      Guess what?
    661662 *
    662663 *-----------------------------------------------------------------------
     
    664665void
    665666Compat_Run(targs)
    666     Lst           targs;    /* List of target nodes to re-create */
     667    Lst           targs;    /* List of target nodes to re-create */
    667668{
    668     char          *cp;      /* Pointer to string of shell meta-characters */
    669     GNode         *gn = NULL;/* Current root target */
    670     int           errors;   /* Number of targets not remade due to errors */
     669    char          *cp;      /* Pointer to string of shell meta-characters */
     670    GNode         *gn = NULL;/* Current root target */
     671    int           errors;   /* Number of targets not remade due to errors */
    671672
    672673    if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
    673         signal(SIGINT, CompatInterrupt);
     674        signal(SIGINT, CompatInterrupt);
    674675    }
    675676    if (signal(SIGTERM, SIG_IGN) != SIG_IGN) {
    676         signal(SIGTERM, CompatInterrupt);
     677        signal(SIGTERM, CompatInterrupt);
    677678    }
    678679    #if !(defined(OS2) && defined(__IBMC__))
    679680    if (signal(SIGHUP, SIG_IGN) != SIG_IGN) {
    680         signal(SIGHUP, CompatInterrupt);
     681        signal(SIGHUP, CompatInterrupt);
    681682    }
    682683    #endif
    683684    #if !(defined(OS2) && defined(__IBMC__))
    684685    if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) {
    685         signal(SIGQUIT, CompatInterrupt);
     686        signal(SIGQUIT, CompatInterrupt);
    686687    }
    687688    #endif
    688689
    689690    for (cp = "#=|^(){};&<>*?[]:$`\\\n"; *cp != '\0'; cp++) {
    690         meta[(unsigned char) *cp] = 1;
     691        meta[(unsigned char) *cp] = 1;
    691692    }
    692693    /*
     
    701702     */
    702703    if (!queryFlag) {
    703         gn = Targ_FindNode(".BEGIN", TARG_NOCREATE);
    704         if (gn != NILGNODE) {
    705             Lst_ForEach(gn->commands, CompatRunCommand, (ClientData)gn);
     704        gn = Targ_FindNode(".BEGIN", TARG_NOCREATE);
     705        if (gn != NILGNODE) {
     706            Lst_ForEach(gn->commands, CompatRunCommand, (ClientData)gn);
    706707            if (gn->made == ERROR) {
    707708                printf("\n\nStop.\n");
    708709                exit(1);
    709710            }
    710         }
     711        }
    711712    }
    712713
     
    715716     * it to create the thing. CompatMake will leave the 'made' field of gn
    716717     * in one of several states:
    717      *      UPTODATE        gn was already up-to-date
    718      *      MADE            gn was recreated successfully
    719      *      ERROR           An error occurred while gn was being created
    720      *      ABORTED         gn was not remade because one of its inferiors
    721      *                      could not be made due to errors.
     718     *      UPTODATE        gn was already up-to-date
     719     *      MADE            gn was recreated successfully
     720     *      ERROR           An error occurred while gn was being created
     721     *      ABORTED         gn was not remade because one of its inferiors
     722     *                      could not be made due to errors.
    722723     */
    723724    errors = 0;
    724725    while (!Lst_IsEmpty (targs)) {
    725         gn = (GNode *) Lst_DeQueue (targs);
    726         CompatMake (gn, gn);
    727 
    728         if (gn->made == UPTODATE) {
    729             printf ("`%s' is up to date.\n", gn->name);
    730         } else if (gn->made == ABORTED) {
    731             printf ("`%s' not remade because of errors.\n", gn->name);
    732             errors += 1;
    733         }
     726        gn = (GNode *) Lst_DeQueue (targs);
     727        CompatMake (gn, gn);
     728
     729        if (gn->made == UPTODATE) {
     730            printf ("`%s' is up to date.\n", gn->name);
     731        } else if (gn->made == ABORTED) {
     732            printf ("`%s' not remade because of errors.\n", gn->name);
     733            errors += 1;
     734        }
    734735    }
    735736
     
    738739     */
    739740    if (errors == 0) {
    740         Lst_ForEach(ENDNode->commands, CompatRunCommand, (ClientData)gn);
     741        Lst_ForEach(ENDNode->commands, CompatRunCommand, (ClientData)gn);
    741742    }
    742743}
  • trunk/src/kmk/cond.c

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

    r47 r51  
    1818 * 3. All advertising materials mentioning features or use of this software
    1919 *    must display the following acknowledgement:
    20  *      This product includes software developed by the University of
    21  *      California, Berkeley and its contributors.
     20 *      This product includes software developed by the University of
     21 *      California, Berkeley and its contributors.
    2222 * 4. Neither the name of the University nor the names of its contributors
    2323 *    may be used to endorse or promote products derived from this software
     
    3636 * SUCH DAMAGE.
    3737 *
    38  *      from: @(#)config.h      8.1 (Berkeley) 6/6/93
     38 *      from: @(#)config.h      8.1 (Berkeley) 6/6/93
    3939 * $FreeBSD: src/usr.bin/make/config.h,v 1.9 1999/09/10 20:51:59 julian Exp $
    4040 */
    4141
    42 #define DEFSHELL        1                       /* Bourne shell */
     42#define DEFSHELL        1                       /* Bourne shell */
    4343
    4444/*
    4545 * DEFMAXJOBS
    4646 * DEFMAXLOCAL
    47  *      These control the default concurrency. On no occasion will more
    48  *      than DEFMAXJOBS targets be created at once (locally or remotely)
    49  *      DEFMAXLOCAL is the highest number of targets which will be
    50  *      created on the local machine at once. Note that if you set this
    51  *      to 0, nothing will ever happen...
     47 *      These control the default concurrency. On no occasion will more
     48 *      than DEFMAXJOBS targets be created at once (locally or remotely)
     49 *      DEFMAXLOCAL is the highest number of targets which will be
     50 *      created on the local machine at once. Note that if you set this
     51 *      to 0, nothing will ever happen...
    5252 */
    53 #define DEFMAXJOBS      4
    54 #define DEFMAXLOCAL     1
     53#define DEFMAXJOBS      4
     54#define DEFMAXLOCAL     1
    5555
    5656/*
    5757 * INCLUDES
    5858 * LIBRARIES
    59  *      These control the handling of the .INCLUDES and .LIBS variables.
    60  *      If INCLUDES is defined, the .INCLUDES variable will be filled
    61  *      from the search paths of those suffixes which are marked by
    62  *      .INCLUDES dependency lines. Similarly for LIBRARIES and .LIBS
    63  *      See suff.c for more details.
     59 *      These control the handling of the .INCLUDES and .LIBS variables.
     60 *      If INCLUDES is defined, the .INCLUDES variable will be filled
     61 *      from the search paths of those suffixes which are marked by
     62 *      .INCLUDES dependency lines. Similarly for LIBRARIES and .LIBS
     63 *      See suff.c for more details.
    6464 */
    6565#define INCLUDES
     
    6868/*
    6969 * LIBSUFF
    70  *      Is the suffix used to denote libraries and is used by the Suff module
    71  *      to find the search path on which to seek any -l<xx> targets.
     70 *      Is the suffix used to denote libraries and is used by the Suff module
     71 *      to find the search path on which to seek any -l<xx> targets.
    7272 *
    7373 * RECHECK
    74  *      If defined, Make_Update will check a target for its current
    75  *      modification time after it has been re-made, setting it to the
    76  *      starting time of the make only if the target still doesn't exist.
    77  *      Unfortunately, under NFS the modification time often doesn't
    78  *      get updated in time, so a target will appear to not have been
    79  *      re-made, causing later targets to appear up-to-date. On systems
    80  *      that don't have this problem, you should defined this. Under
    81  *      NFS you probably should not, unless you aren't exporting jobs.
     74 *      If defined, Make_Update will check a target for its current
     75 *      modification time after it has been re-made, setting it to the
     76 *      starting time of the make only if the target still doesn't exist.
     77 *      Unfortunately, under NFS the modification time often doesn't
     78 *      get updated in time, so a target will appear to not have been
     79 *      re-made, causing later targets to appear up-to-date. On systems
     80 *      that don't have this problem, you should defined this. Under
     81 *      NFS you probably should not, unless you aren't exporting jobs.
    8282 */
    83 #define LIBSUFF ".a"
    84 #define RECHECK
     83#define LIBSUFF ".a"
     84#define RECHECK
    8585
    8686/*
    8787 * POSIX
    88  *      Adhere to the POSIX 1003.2 draft for the make(1) program.
    89  *      - Use MAKEFLAGS instead of MAKE to pick arguments from the
    90  *        environment.
    91  *      - Allow empty command lines if starting with tab.
     88 *      Adhere to the POSIX 1003.2 draft for the make(1) program.
     89 *      - Use MAKEFLAGS instead of MAKE to pick arguments from the
     90 *        environment.
     91 *      - Allow empty command lines if starting with tab.
    9292 */
    9393#define POSIX
     
    9595/*
    9696 * SYSVINCLUDE
    97  *      Recognize system V like include directives [include "filename"]
     97 *      Recognize system V like include directives [include "filename"]
    9898 * SYSVVARSUB
    99  *      Recognize system V like ${VAR:x=y} variable substitutions
     99 *      Recognize system V like ${VAR:x=y} variable substitutions
    100100 */
    101101#define SYSVINCLUDE
     
    104104/*
    105105 * SUNSHCMD
    106  *      Recognize SunOS and Solaris:
    107  *              VAR :sh= CMD    # Assign VAR to the command substitution of CMD
    108  *              ${VAR:sh}       # Return the command substitution of the value
    109  *                              # of ${VAR}
     106 *      Recognize SunOS and Solaris:
     107 *              VAR :sh= CMD    # Assign VAR to the command substitution of CMD
     108 *              ${VAR:sh}       # Return the command substitution of the value
     109 *                              # of ${VAR}
    110110 */
    111111#define SUNSHCMD
     
    120120# endif
    121121#endif
    122 
    123 
    124 
    125122
    126123
     
    159156
    160157/*
     158 * USE_BASEANDROOT_MODIFIERS
     159 *      If defined two extra variable modifiers B and R are added.
     160 */
     161#if defined(NMAKE) || defined(KMK)
     162#define USE_BASEANDROOT_MODIFIERS 1
     163#endif
     164
     165
     166/*
    161167 * USE_ISODATES
    162168 *      If defined dates and times will be outputted in ISO format.
  • trunk/src/kmk/dir.c

    r46 r51  
    1818 * 3. All advertising materials mentioning features or use of this software
    1919 *    must display the following acknowledgement:
    20  *      This product includes software developed by the University of
    21  *      California, Berkeley and its contributors.
     20 *      This product includes software developed by the University of
     21 *      California, Berkeley and its contributors.
    2222 * 4. Neither the name of the University nor the names of its contributors
    2323 *    may be used to endorse or promote products derived from this software
     
    3939#ifndef lint
    4040#if 0
    41 static char sccsid[] = "@(#)dir.c       8.2 (Berkeley) 1/2/94";
     41static char sccsid[] = "@(#)dir.c       8.2 (Berkeley) 1/2/94";
    4242#else
    4343static const char rcsid[] =
    4444  "$FreeBSD: src/usr.bin/make/dir.c,v 1.10.2.1 2001/02/13 03:13:57 will Exp $";
    4545#endif
     46#define KLIBFILEDEF rcsid
    4647#endif /* not lint */
    4748
    4849/*-
    4950 * dir.c --
    50  *      Directory searching using wildcards and/or normal names...
    51  *      Used both for source wildcarding in the Makefile and for finding
    52  *      implicit sources.
     51 *      Directory searching using wildcards and/or normal names...
     52 *      Used both for source wildcarding in the Makefile and for finding
     53 *      implicit sources.
    5354 *
    5455 * The interface for this module is:
    55  *      Dir_Init            Initialize the module.
    56  *
    57  *      Dir_End             Cleanup the module.
    58  *
    59  *      Dir_HasWildcards    Returns TRUE if the name given it needs to
    60  *                          be wildcard-expanded.
    61  *
    62  *      Dir_Expand          Given a pattern and a path, return a Lst of names
    63  *                          which match the pattern on the search path.
    64  *
    65  *      Dir_FindFile        Searches for a file on a given search path.
    66  *                          If it exists, the entire path is returned.
    67  *                          Otherwise NULL is returned.
    68  *
    69  *      Dir_MTime           Return the modification time of a node. The file
    70  *                          is searched for along the default search path.
    71  *                          The path and mtime fields of the node are filled
    72  *                          in.
    73  *
    74  *      Dir_AddDir          Add a directory to a search path.
    75  *
    76  *      Dir_MakeFlags       Given a search path and a command flag, create
    77  *                          a string with each of the directories in the path
    78  *                          preceded by the command flag and all of them
    79  *                          separated by a space.
    80  *
    81  *      Dir_Destroy         Destroy an element of a search path. Frees up all
    82  *                          things that can be freed for the element as long
    83  *                          as the element is no longer referenced by any other
    84  *                          search path.
    85  *      Dir_ClearPath       Resets a search path to the empty list.
     56 *      Dir_Init            Initialize the module.
     57 *
     58 *      Dir_End             Cleanup the module.
     59 *
     60 *      Dir_HasWildcards    Returns TRUE if the name given it needs to
     61 *                          be wildcard-expanded.
     62 *
     63 *      Dir_Expand          Given a pattern and a path, return a Lst of names
     64 *                          which match the pattern on the search path.
     65 *
     66 *      Dir_FindFile        Searches for a file on a given search path.
     67 *                          If it exists, the entire path is returned.
     68 *                          Otherwise NULL is returned.
     69 *
     70 *      Dir_MTime           Return the modification time of a node. The file
     71 *                          is searched for along the default search path.
     72 *                          The path and mtime fields of the node are filled
     73 *                          in.
     74 *
     75 *      Dir_AddDir          Add a directory to a search path.
     76 *
     77 *      Dir_MakeFlags       Given a search path and a command flag, create
     78 *                          a string with each of the directories in the path
     79 *                          preceded by the command flag and all of them
     80 *                          separated by a space.
     81 *
     82 *      Dir_Destroy         Destroy an element of a search path. Frees up all
     83 *                          things that can be freed for the element as long
     84 *                          as the element is no longer referenced by any other
     85 *                          search path.
     86 *      Dir_ClearPath       Resets a search path to the empty list.
    8687 *
    8788 * For debugging:
    88  *      Dir_PrintDirectories    Print stats about the directory cache.
     89 *      Dir_PrintDirectories    Print stats about the directory cache.
    8990 */
    9091
     
    9899
    99100/*
    100  *      A search path consists of a Lst of Path structures. A Path structure
    101  *      has in it the name of the directory and a hash table of all the files
    102  *      in the directory. This is used to cut down on the number of system
    103  *      calls necessary to find implicit dependents and their like. Since
    104  *      these searches are made before any actions are taken, we need not
    105  *      worry about the directory changing due to creation commands. If this
    106  *      hampers the style of some makefiles, they must be changed.
    107  *
    108  *      A list of all previously-read directories is kept in the
    109  *      openDirectories Lst. This list is checked first before a directory
    110  *      is opened.
    111  *
    112  *      The need for the caching of whole directories is brought about by
    113  *      the multi-level transformation code in suff.c, which tends to search
    114  *      for far more files than regular make does. In the initial
    115  *      implementation, the amount of time spent performing "stat" calls was
    116  *      truly astronomical. The problem with hashing at the start is,
    117  *      of course, that pmake doesn't then detect changes to these directories
    118  *      during the course of the make. Three possibilities suggest themselves:
    119  *
    120  *          1) just use stat to test for a file's existence. As mentioned
    121  *             above, this is very inefficient due to the number of checks
    122  *             engendered by the multi-level transformation code.
    123  *          2) use readdir() and company to search the directories, keeping
    124  *             them open between checks. I have tried this and while it
    125  *             didn't slow down the process too much, it could severely
    126  *             affect the amount of parallelism available as each directory
    127  *             open would take another file descriptor out of play for
    128  *             handling I/O for another job. Given that it is only recently
    129  *             that UNIX OS's have taken to allowing more than 20 or 32
    130  *             file descriptors for a process, this doesn't seem acceptable
    131  *             to me.
    132  *          3) record the mtime of the directory in the Path structure and
    133  *             verify the directory hasn't changed since the contents were
    134  *             hashed. This will catch the creation or deletion of files,
    135  *             but not the updating of files. However, since it is the
    136  *             creation and deletion that is the problem, this could be
    137  *             a good thing to do. Unfortunately, if the directory (say ".")
    138  *             were fairly large and changed fairly frequently, the constant
    139  *             rehashing could seriously degrade performance. It might be
    140  *             good in such cases to keep track of the number of rehashes
    141  *             and if the number goes over a (small) limit, resort to using
    142  *             stat in its place.
    143  *
    144  *      An additional thing to consider is that pmake is used primarily
    145  *      to create C programs and until recently pcc-based compilers refused
    146  *      to allow you to specify where the resulting object file should be
    147  *      placed. This forced all objects to be created in the current
    148  *      directory. This isn't meant as a full excuse, just an explanation of
    149  *      some of the reasons for the caching used here.
    150  *
    151  *      One more note: the location of a target's file is only performed
    152  *      on the downward traversal of the graph and then only for terminal
    153  *      nodes in the graph. This could be construed as wrong in some cases,
    154  *      but prevents inadvertent modification of files when the "installed"
    155  *      directory for a file is provided in the search path.
    156  *
    157  *      Another data structure maintained by this module is an mtime
    158  *      cache used when the searching of cached directories fails to find
    159  *      a file. In the past, Dir_FindFile would simply perform an access()
    160  *      call in such a case to determine if the file could be found using
    161  *      just the name given. When this hit, however, all that was gained
    162  *      was the knowledge that the file existed. Given that an access() is
    163  *      essentially a stat() without the copyout() call, and that the same
    164  *      filesystem overhead would have to be incurred in Dir_MTime, it made
    165  *      sense to replace the access() with a stat() and record the mtime
    166  *      in a cache for when Dir_MTime was actually called.
    167  */
    168 
    169 Lst          dirSearchPath;     /* main search path */
    170 
    171 static Lst   openDirectories;   /* the list of all open directories */
     101 *      A search path consists of a Lst of Path structures. A Path structure
     102 *      has in it the name of the directory and a hash table of all the files
     103 *      in the directory. This is used to cut down on the number of system
     104 *      calls necessary to find implicit dependents and their like. Since
     105 *      these searches are made before any actions are taken, we need not
     106 *      worry about the directory changing due to creation commands. If this
     107 *      hampers the style of some makefiles, they must be changed.
     108 *
     109 *      A list of all previously-read directories is kept in the
     110 *      openDirectories Lst. This list is checked first before a directory
     111 *      is opened.
     112 *
     113 *      The need for the caching of whole directories is brought about by
     114 *      the multi-level transformation code in suff.c, which tends to search
     115 *      for far more files than regular make does. In the initial
     116 *      implementation, the amount of time spent performing "stat" calls was
     117 *      truly astronomical. The problem with hashing at the start is,
     118 *      of course, that pmake doesn't then detect changes to these directories
     119 *      during the course of the make. Three possibilities suggest themselves:
     120 *
     121 *          1) just use stat to test for a file's existence. As mentioned
     122 *             above, this is very inefficient due to the number of checks
     123 *             engendered by the multi-level transformation code.
     124 *          2) use readdir() and company to search the directories, keeping
     125 *             them open between checks. I have tried this and while it
     126 *             didn't slow down the process too much, it could severely
     127 *             affect the amount of parallelism available as each directory
     128 *             open would take another file descriptor out of play for
     129 *             handling I/O for another job. Given that it is only recently
     130 *             that UNIX OS's have taken to allowing more than 20 or 32
     131 *             file descriptors for a process, this doesn't seem acceptable
     132 *             to me.
     133 *          3) record the mtime of the directory in the Path structure and
     134 *             verify the directory hasn't changed since the contents were
     135 *             hashed. This will catch the creation or deletion of files,
     136 *             but not the updating of files. However, since it is the
     137 *             creation and deletion that is the problem, this could be
     138 *             a good thing to do. Unfortunately, if the directory (say ".")
     139 *             were fairly large and changed fairly frequently, the constant
     140 *             rehashing could seriously degrade performance. It might be
     141 *             good in such cases to keep track of the number of rehashes
     142 *             and if the number goes over a (small) limit, resort to using
     143 *             stat in its place.
     144 *
     145 *      An additional thing to consider is that pmake is used primarily
     146 *      to create C programs and until recently pcc-based compilers refused
     147 *      to allow you to specify where the resulting object file should be
     148 *      placed. This forced all objects to be created in the current
     149 *      directory. This isn't meant as a full excuse, just an explanation of
     150 *      some of the reasons for the caching used here.
     151 *
     152 *      One more note: the location of a target's file is only performed
     153 *      on the downward traversal of the graph and then only for terminal
     154 *      nodes in the graph. This could be construed as wrong in some cases,
     155 *      but prevents inadvertent modification of files when the "installed"
     156 *      directory for a file is provided in the search path.
     157 *
     158 *      Another data structure maintained by this module is an mtime
     159 *      cache used when the searching of cached directories fails to find
     160 *      a file. In the past, Dir_FindFile would simply perform an access()
     161 *      call in such a case to determine if the file could be found using
     162 *      just the name given. When this hit, however, all that was gained
     163 *      was the knowledge that the file existed. Given that an access() is
     164 *      essentially a stat() without the copyout() call, and that the same
     165 *      filesystem overhead would have to be incurred in Dir_MTime, it made
     166 *      sense to replace the access() with a stat() and record the mtime
     167 *      in a cache for when Dir_MTime was actually called.
     168 */
     169
     170Lst          dirSearchPath;     /* main search path */
     171
     172static Lst   openDirectories;   /* the list of all open directories */
    172173
    173174/*
     
    175176 * mechanism.
    176177 */
    177 static int    hits,           /* Found in directory cache */
    178               misses,         /* Sad, but not evil misses */
    179               nearmisses,     /* Found under search path */
    180               bigmisses;      /* Sought by itself */
    181 
    182 static Path       *dot;     /* contents of current directory */
     178static int    hits,           /* Found in directory cache */
     179              misses,         /* Sad, but not evil misses */
     180              nearmisses,     /* Found under search path */
     181              bigmisses;      /* Sought by itself */
     182
     183static Path       *dot;     /* contents of current directory */
    183184static Hash_Table mtimes;   /* Results of doing a last-resort stat in
    184                              * Dir_FindFile -- if we have to go to the
    185                              * system to find the file, we might as well
    186                              * have its mtime on record. XXX: If this is done
    187                              * way early, there's a chance other rules will
    188                              * have already updated the file, in which case
    189                              * we'll update it again. Generally, there won't
    190                              * be two rules to update a single file, so this
    191                              * should be ok, but... */
     185                             * Dir_FindFile -- if we have to go to the
     186                             * system to find the file, we might as well
     187                             * have its mtime on record. XXX: If this is done
     188                             * way early, there's a chance other rules will
     189                             * have already updated the file, in which case
     190                             * we'll update it again. Generally, there won't
     191                             * be two rules to update a single file, so this
     192                             * should be ok, but... */
    192193
    193194
     
    202203 *-----------------------------------------------------------------------
    203204 * Dir_Init --
    204  *      initialize things for this module
    205  *
    206  * Results:
    207  *      none
    208  *
    209  * Side Effects:
    210  *      some directories may be opened.
     205 *      initialize things for this module
     206 *
     207 * Results:
     208 *      none
     209 *
     210 * Side Effects:
     211 *      some directories may be opened.
    211212 *-----------------------------------------------------------------------
    212213 */
     
    227228    dot = (Path *) Lst_DeQueue (openDirectories);
    228229    if (dot == (Path *) NULL)
    229         err(1, "cannot open current directory");
     230        err(1, "cannot open current directory");
    230231
    231232    /*
     
    239240 *-----------------------------------------------------------------------
    240241 * Dir_End --
    241  *      cleanup things for this module
    242  *
    243  * Results:
    244  *      none
    245  *
    246  * Side Effects:
    247  *      none
     242 *      cleanup things for this module
     243 *
     244 * Results:
     245 *      none
     246 *
     247 * Side Effects:
     248 *      none
    248249 *-----------------------------------------------------------------------
    249250 */
     
    263264 *-----------------------------------------------------------------------
    264265 * DirFindName --
    265  *      See if the Path structure describes the same directory as the
    266  *      given one by comparing their names. Called from Dir_AddDir via
    267  *      Lst_Find when searching the list of open directories.
    268  *
    269  * Results:
    270  *      0 if it is the same. Non-zero otherwise
    271  *
    272  * Side Effects:
    273  *      None
     266 *      See if the Path structure describes the same directory as the
     267 *      given one by comparing their names. Called from Dir_AddDir via
     268 *      Lst_Find when searching the list of open directories.
     269 *
     270 * Results:
     271 *      0 if it is the same. Non-zero otherwise
     272 *
     273 * Side Effects:
     274 *      None
    274275 *-----------------------------------------------------------------------
    275276 */
    276277static int
    277278DirFindName (p, dname)
    278     ClientData    p;          /* Current name */
    279     ClientData    dname;      /* Desired name */
     279    ClientData    p;          /* Current name */
     280    ClientData    dname;      /* Desired name */
    280281{
    281282    return (strcmp (((Path *)p)->name, (char *) dname));
     
    285286 *-----------------------------------------------------------------------
    286287 * Dir_HasWildcards  --
    287  *      see if the given name has any wildcard characters in it
    288  *
    289  * Results:
    290  *      returns TRUE if the word should be expanded, FALSE otherwise
    291  *
    292  * Side Effects:
    293  *      none
     288 *      see if the given name has any wildcard characters in it
     289 *
     290 * Results:
     291 *      returns TRUE if the word should be expanded, FALSE otherwise
     292 *
     293 * Side Effects:
     294 *      none
    294295 *-----------------------------------------------------------------------
    295296 */
    296297Boolean
    297298Dir_HasWildcards (name)
    298     char          *name;        /* name to check */
     299    char          *name;        /* name to check */
    299300{
    300301    register char *cp;
    301302
    302303    for (cp = name; *cp; cp++) {
    303         switch(*cp) {
    304         case '{':
    305         case '[':
    306         case '?':
    307         case '*':
    308             return (TRUE);
    309         }
     304        switch(*cp) {
     305        case '{':
     306        case '[':
     307        case '?':
     308        case '*':
     309            return (TRUE);
     310        }
    310311    }
    311312    return (FALSE);
     
    315316 *-----------------------------------------------------------------------
    316317 * DirMatchFiles --
    317  *      Given a pattern and a Path structure, see if any files
    318  *      match the pattern and add their names to the 'expansions' list if
    319  *      any do. This is incomplete -- it doesn't take care of patterns like
    320  *      src / *src / *.c properly (just *.c on any of the directories), but it
    321  *      will do for now.
    322  *
    323  * Results:
    324  *      Always returns 0
    325  *
    326  * Side Effects:
    327  *      File names are added to the expansions lst. The directory will be
    328  *      fully hashed when this is done.
     318 *      Given a pattern and a Path structure, see if any files
     319 *      match the pattern and add their names to the 'expansions' list if
     320 *      any do. This is incomplete -- it doesn't take care of patterns like
     321 *      src / *src / *.c properly (just *.c on any of the directories), but it
     322 *      will do for now.
     323 *
     324 * Results:
     325 *      Always returns 0
     326 *
     327 * Side Effects:
     328 *      File names are added to the expansions lst. The directory will be
     329 *      fully hashed when this is done.
    329330 *-----------------------------------------------------------------------
    330331 */
    331332static int
    332333DirMatchFiles (pattern, p, expansions)
    333     char          *pattern;     /* Pattern to look for */
    334     Path          *p;           /* Directory to search */
    335     Lst           expansions;   /* Place to store the results */
    336 {
    337     Hash_Search   search;       /* Index into the directory's table */
    338     Hash_Entry    *entry;       /* Current entry in the table */
    339     Boolean       isDot;        /* TRUE if the directory being searched is . */
     334    char          *pattern;     /* Pattern to look for */
     335    Path          *p;           /* Directory to search */
     336    Lst           expansions;   /* Place to store the results */
     337{
     338    Hash_Search   search;       /* Index into the directory's table */
     339    Hash_Entry    *entry;       /* Current entry in the table */
     340    Boolean       isDot;        /* TRUE if the directory being searched is . */
    340341
    341342    isDot = (*p->name == '.' && p->name[1] == '\0');
    342343
    343344    for (entry = Hash_EnumFirst(&p->files, &search);
    344         entry != (Hash_Entry *)NULL;
    345         entry = Hash_EnumNext(&search))
     345        entry != (Hash_Entry *)NULL;
     346        entry = Hash_EnumNext(&search))
    346347    {
    347         /*
    348         * See if the file matches the given pattern. Note we follow the UNIX
    349         * convention that dot files will only be found if the pattern
    350         * begins with a dot (note also that as a side effect of the hashing
    351         * scheme, .* won't match . or .. since they aren't hashed).
    352         */
    353         if (Str_Match(entry->name, pattern) &&
    354             ((entry->name[0] != '.') ||
    355              (pattern[0] == '.')))
    356         {
    357             (void)Lst_AtEnd(expansions,
    358                             (isDot ? estrdup(entry->name) :
    359                              str_concat(p->name, entry->name,
    360                                         STR_ADDSLASH)));
    361         }
     348        /*
     349        * See if the file matches the given pattern. Note we follow the UNIX
     350        * convention that dot files will only be found if the pattern
     351        * begins with a dot (note also that as a side effect of the hashing
     352        * scheme, .* won't match . or .. since they aren't hashed).
     353        */
     354        if (Str_Match(entry->name, pattern) &&
     355            ((entry->name[0] != '.') ||
     356             (pattern[0] == '.')))
     357        {
     358            (void)Lst_AtEnd(expansions,
     359                            (isDot ? estrdup(entry->name) :
     360                             str_concat(p->name, entry->name,
     361                                        STR_ADDSLASH)));
     362        }
    362363    }
    363364    return (0);
     
    367368 *-----------------------------------------------------------------------
    368369 * DirExpandCurly --
    369  *      Expand curly braces like the C shell. Does this recursively.
    370  *      Note the special case: if after the piece of the curly brace is
    371  *      done there are no wildcard characters in the result, the result is
    372  *      placed on the list WITHOUT CHECKING FOR ITS EXISTENCE.
    373  *
    374  * Results:
    375  *      None.
    376  *
    377  * Side Effects:
    378  *      The given list is filled with the expansions...
     370 *      Expand curly braces like the C shell. Does this recursively.
     371 *      Note the special case: if after the piece of the curly brace is
     372 *      done there are no wildcard characters in the result, the result is
     373 *      placed on the list WITHOUT CHECKING FOR ITS EXISTENCE.
     374 *
     375 * Results:
     376 *      None.
     377 *
     378 * Side Effects:
     379 *      The given list is filled with the expansions...
    379380 *
    380381 *-----------------------------------------------------------------------
     
    382383static void
    383384DirExpandCurly(word, brace, path, expansions)
    384     char          *word;        /* Entire word to expand */
    385     char          *brace;       /* First curly brace in it */
    386     Lst           path;         /* Search path to use */
    387     Lst           expansions;   /* Place to store the expansions */
    388 {
    389     char          *end;         /* Character after the closing brace */
    390     char          *cp;          /* Current position in brace clause */
    391     char          *start;       /* Start of current piece of brace clause */
    392     int           bracelevel;   /* Number of braces we've seen. If we see a
    393                                 * right brace when this is 0, we've hit the
    394                                 * end of the clause. */
    395     char          *file;        /* Current expansion */
    396     int           otherLen;     /* The length of the other pieces of the
    397                                 * expansion (chars before and after the
    398                                 * clause in 'word') */
    399     char          *cp2;         /* Pointer for checking for wildcards in
    400                                 * expansion before calling Dir_Expand */
     385    char          *word;        /* Entire word to expand */
     386    char          *brace;       /* First curly brace in it */
     387    Lst           path;         /* Search path to use */
     388    Lst           expansions;   /* Place to store the expansions */
     389{
     390    char          *end;         /* Character after the closing brace */
     391    char          *cp;          /* Current position in brace clause */
     392    char          *start;       /* Start of current piece of brace clause */
     393    int           bracelevel;   /* Number of braces we've seen. If we see a
     394                                * right brace when this is 0, we've hit the
     395                                * end of the clause. */
     396    char          *file;        /* Current expansion */
     397    int           otherLen;     /* The length of the other pieces of the
     398                                * expansion (chars before and after the
     399                                * clause in 'word') */
     400    char          *cp2;         /* Pointer for checking for wildcards in
     401                                * expansion before calling Dir_Expand */
    401402
    402403    start = brace+1;
     
    407408     */
    408409    for (end = start, bracelevel = 0; *end != '\0'; end++) {
    409         if (*end == '{') {
    410             bracelevel++;
    411         } else if ((*end == '}') && (bracelevel-- == 0)) {
    412             break;
    413         }
     410        if (*end == '{') {
     411            bracelevel++;
     412        } else if ((*end == '}') && (bracelevel-- == 0)) {
     413            break;
     414        }
    414415    }
    415416    if (*end == '\0') {
    416         Error("Unterminated {} clause \"%s\"", start);
    417         return;
     417        Error("Unterminated {} clause \"%s\"", start);
     418        return;
    418419    } else {
    419         end++;
     420        end++;
    420421    }
    421422    otherLen = brace - word + strlen(end);
    422423
    423424    for (cp = start; cp < end; cp++) {
    424         /*
    425         * Find the end of this piece of the clause.
    426         */
    427         bracelevel = 0;
    428         while (*cp != ',') {
    429             if (*cp == '{') {
    430                 bracelevel++;
    431             } else if ((*cp == '}') && (bracelevel-- <= 0)) {
    432                 break;
    433             }
    434             cp++;
    435         }
    436         /*
    437         * Allocate room for the combination and install the three pieces.
    438         */
    439         file = emalloc(otherLen + cp - start + 1);
    440         if (brace != word) {
    441             strncpy(file, word, brace-word);
    442         }
    443         if (cp != start) {
    444             strncpy(&file[brace-word], start, cp-start);
    445         }
    446         strcpy(&file[(brace-word)+(cp-start)], end);
    447 
    448         /*
    449         * See if the result has any wildcards in it. If we find one, call
    450         * Dir_Expand right away, telling it to place the result on our list
    451         * of expansions.
    452         */
    453         for (cp2 = file; *cp2 != '\0'; cp2++) {
    454             switch(*cp2) {
    455             case '*':
    456             case '?':
    457             case '{':
    458             case '[':
    459                 Dir_Expand(file, path, expansions);
    460                 goto next;
    461             }
    462         }
    463         if (*cp2 == '\0') {
    464             /*
    465              * Hit the end w/o finding any wildcards, so stick the expansion
    466              * on the end of the list.
    467              */
    468             (void)Lst_AtEnd(expansions, file);
    469         } else {
    470         next:
    471             efree(file);
    472         }
    473         start = cp+1;
     425        /*
     426        * Find the end of this piece of the clause.
     427        */
     428        bracelevel = 0;
     429        while (*cp != ',') {
     430            if (*cp == '{') {
     431                bracelevel++;
     432            } else if ((*cp == '}') && (bracelevel-- <= 0)) {
     433                break;
     434            }
     435            cp++;
     436        }
     437        /*
     438        * Allocate room for the combination and install the three pieces.
     439        */
     440        file = emalloc(otherLen + cp - start + 1);
     441        if (brace != word) {
     442            strncpy(file, word, brace-word);
     443        }
     444        if (cp != start) {
     445            strncpy(&file[brace-word], start, cp-start);
     446        }
     447        strcpy(&file[(brace-word)+(cp-start)], end);
     448
     449        /*
     450        * See if the result has any wildcards in it. If we find one, call
     451        * Dir_Expand right away, telling it to place the result on our list
     452        * of expansions.
     453        */
     454        for (cp2 = file; *cp2 != '\0'; cp2++) {
     455            switch(*cp2) {
     456            case '*':
     457            case '?':
     458            case '{':
     459            case '[':
     460                Dir_Expand(file, path, expansions);
     461                goto next;
     462            }
     463        }
     464        if (*cp2 == '\0') {
     465            /*
     466             * Hit the end w/o finding any wildcards, so stick the expansion
     467             * on the end of the list.
     468             */
     469            (void)Lst_AtEnd(expansions, file);
     470        } else {
     471        next:
     472            efree(file);
     473        }
     474        start = cp+1;
    474475    }
    475476}
     
    479480 *-----------------------------------------------------------------------
    480481 * DirExpandInt --
    481  *      Internal expand routine. Passes through the directories in the
    482  *      path one by one, calling DirMatchFiles for each. NOTE: This still
    483  *      doesn't handle patterns in directories...
    484  *
    485  * Results:
    486  *      None.
    487  *
    488  * Side Effects:
    489  *      Things are added to the expansions list.
     482 *      Internal expand routine. Passes through the directories in the
     483 *      path one by one, calling DirMatchFiles for each. NOTE: This still
     484 *      doesn't handle patterns in directories...
     485 *
     486 * Results:
     487 *      None.
     488 *
     489 * Side Effects:
     490 *      Things are added to the expansions list.
    490491 *
    491492 *-----------------------------------------------------------------------
     
    493494static void
    494495DirExpandInt(word, path, expansions)
    495     char          *word;        /* Word to expand */
    496     Lst           path;         /* Path on which to look */
    497     Lst           expansions;   /* Place to store the result */
    498 {
    499     LstNode       ln;           /* Current node */
    500     Path          *p;           /* Directory in the node */
     496    char          *word;        /* Word to expand */
     497    Lst           path;         /* Path on which to look */
     498    Lst           expansions;   /* Place to store the result */
     499{
     500    LstNode       ln;           /* Current node */
     501    Path          *p;           /* Directory in the node */
    501502
    502503    if (Lst_Open(path) == SUCCESS) {
    503         while ((ln = Lst_Next(path)) != NILLNODE) {
    504             p = (Path *)Lst_Datum(ln);
    505             DirMatchFiles(word, p, expansions);
    506         }
    507         Lst_Close(path);
     504        while ((ln = Lst_Next(path)) != NILLNODE) {
     505            p = (Path *)Lst_Datum(ln);
     506            DirMatchFiles(word, p, expansions);
     507        }
     508        Lst_Close(path);
    508509    }
    509510}
     
    512513 *-----------------------------------------------------------------------
    513514 * DirPrintWord --
    514  *      Print a word in the list of expansions. Callback for Dir_Expand
    515  *      when DEBUG(DIR), via Lst_ForEach.
    516  *
    517  * Results:
    518  *      === 0
    519  *
    520  * Side Effects:
    521  *      The passed word is printed, followed by a space.
     515 *      Print a word in the list of expansions. Callback for Dir_Expand
     516 *      when DEBUG(DIR), via Lst_ForEach.
     517 *
     518 * Results:
     519 *      === 0
     520 *
     521 * Side Effects:
     522 *      The passed word is printed, followed by a space.
    522523 *
    523524 *-----------------------------------------------------------------------
     
    536537 *-----------------------------------------------------------------------
    537538 * Dir_Expand  --
    538  *      Expand the given word into a list of words by globbing it looking
    539  *      in the directories on the given search path.
    540  *
    541  * Results:
    542  *      A list of words consisting of the files which exist along the search
    543  *      path matching the given pattern.
    544  *
    545  * Side Effects:
    546  *      Directories may be opened. Who knows?
     539 *      Expand the given word into a list of words by globbing it looking
     540 *      in the directories on the given search path.
     541 *
     542 * Results:
     543 *      A list of words consisting of the files which exist along the search
     544 *      path matching the given pattern.
     545 *
     546 * Side Effects:
     547 *      Directories may be opened. Who knows?
    547548 *-----------------------------------------------------------------------
    548549 */
     
    550551Dir_Expand (word, path, expansions)
    551552    char    *word;      /* the word to expand */
    552     Lst     path;       /* the list of directories in which to find
    553                         * the resulting files */
    554     Lst     expansions; /* the list on which to place the results */
    555 {
    556     char          *cp;
     553    Lst     path;       /* the list of directories in which to find
     554                        * the resulting files */
     555    Lst     expansions; /* the list on which to place the results */
     556{
     557    char          *cp;
    557558
    558559    if (DEBUG(DIR)) {
    559         printf("expanding \"%s\"...", word);
     560        printf("expanding \"%s\"...", word);
    560561    }
    561562
    562563    cp = strchr(word, '{');
    563564    if (cp) {
    564         DirExpandCurly(word, cp, path, expansions);
     565        DirExpandCurly(word, cp, path, expansions);
    565566    } else {
    566         cp = strchr(word, '/');
    567         if (cp) {
    568             /*
    569              * The thing has a directory component -- find the first wildcard
    570              * in the string.
    571              */
    572             for (cp = word; *cp; cp++) {
    573                 if (*cp == '?' || *cp == '[' || *cp == '*' || *cp == '{') {
    574                     break;
    575                 }
    576             }
    577             if (*cp == '{') {
    578                 /*
    579                 * This one will be fun.
    580                 */
    581                 DirExpandCurly(word, cp, path, expansions);
    582                 return;
    583             } else if (*cp != '\0') {
    584                 /*
    585                 * Back up to the start of the component
    586                 */
    587                 char  *dirpath;
    588 
    589                 while (cp > word && *cp != '/') {
    590                     cp--;
    591                 }
    592                 if (cp != word) {
    593                     char sc;
    594                     /*
    595                      * If the glob isn't in the first component, try and find
    596                      * all the components up to the one with a wildcard.
    597                      */
    598                     sc = cp[1];
    599                     cp[1] = '\0';
    600                     dirpath = Dir_FindFile(word, path);
    601                     cp[1] = sc;
    602                     /*
    603                      * dirpath is null if can't find the leading component
    604                      * XXX: Dir_FindFile won't find internal components.
    605                      * i.e. if the path contains ../Etc/Object and we're
    606                      * looking for Etc, it won't be found. Ah well.
    607                      * Probably not important.
    608                      */
    609                     if (dirpath != (char *)NULL) {
    610                         char *dp = &dirpath[strlen(dirpath) - 1];
    611                         if (*dp == '/')
    612                             *dp = '\0';
    613                         path = Lst_Init(FALSE);
    614                         Dir_AddDir(path, dirpath);
    615                         DirExpandInt(cp+1, path, expansions);
    616                         Lst_Destroy(path, NOFREE);
    617                     }
    618                 } else {
    619                     /*
    620                      * Start the search from the local directory
    621                      */
    622                     DirExpandInt(word, path, expansions);
    623                 }
    624             } else {
    625                 /*
    626                 * Return the file -- this should never happen.
    627                 */
    628                 DirExpandInt(word, path, expansions);
    629             }
    630         } else {
    631             /*
    632              * First the files in dot
    633              */
    634             DirMatchFiles(word, dot, expansions);
    635 
    636             /*
    637              * Then the files in every other directory on the path.
    638              */
    639             DirExpandInt(word, path, expansions);
    640         }
     567        cp = strchr(word, '/');
     568        if (cp) {
     569            /*
     570             * The thing has a directory component -- find the first wildcard
     571             * in the string.
     572             */
     573            for (cp = word; *cp; cp++) {
     574                if (*cp == '?' || *cp == '[' || *cp == '*' || *cp == '{') {
     575                    break;
     576                }
     577            }
     578            if (*cp == '{') {
     579                /*
     580                * This one will be fun.
     581                */
     582                DirExpandCurly(word, cp, path, expansions);
     583                return;
     584            } else if (*cp != '\0') {
     585                /*
     586                * Back up to the start of the component
     587                */
     588                char  *dirpath;
     589
     590                while (cp > word && *cp != '/') {
     591                    cp--;
     592                }
     593                if (cp != word) {
     594                    char sc;
     595                    /*
     596                     * If the glob isn't in the first component, try and find
     597                     * all the components up to the one with a wildcard.
     598                     */
     599                    sc = cp[1];
     600                    cp[1] = '\0';
     601                    dirpath = Dir_FindFile(word, path);
     602                    cp[1] = sc;
     603                    /*
     604                     * dirpath is null if can't find the leading component
     605                     * XXX: Dir_FindFile won't find internal components.
     606                     * i.e. if the path contains ../Etc/Object and we're
     607                     * looking for Etc, it won't be found. Ah well.
     608                     * Probably not important.
     609                     */
     610                    if (dirpath != (char *)NULL) {
     611                        char *dp = &dirpath[strlen(dirpath) - 1];
     612                        if (*dp == '/')
     613                            *dp = '\0';
     614                        path = Lst_Init(FALSE);
     615                        Dir_AddDir(path, dirpath);
     616                        DirExpandInt(cp+1, path, expansions);
     617                        Lst_Destroy(path, NOFREE);
     618                    }
     619                } else {
     620                    /*
     621                     * Start the search from the local directory
     622                     */
     623                    DirExpandInt(word, path, expansions);
     624                }
     625            } else {
     626                /*
     627                * Return the file -- this should never happen.
     628                */
     629                DirExpandInt(word, path, expansions);
     630            }
     631        } else {
     632            /*
     633             * First the files in dot
     634             */
     635            DirMatchFiles(word, dot, expansions);
     636
     637            /*
     638             * Then the files in every other directory on the path.
     639             */
     640            DirExpandInt(word, path, expansions);
     641        }
    641642    }
    642643    if (DEBUG(DIR)) {
    643         Lst_ForEach(expansions, DirPrintWord, (ClientData) 0);
    644         fputc('\n', stdout);
     644        Lst_ForEach(expansions, DirPrintWord, (ClientData) 0);
     645        fputc('\n', stdout);
    645646    }
    646647}
     
    649650 *-----------------------------------------------------------------------
    650651 * Dir_FindFile  --
    651  *      Find the file with the given name along the given search path.
    652  *
    653  * Results:
    654  *      The path to the file or NULL. This path is guaranteed to be in a
    655  *      different part of memory than name and so may be safely efree'd.
    656  *
    657  * Side Effects:
    658  *      If the file is found in a directory which is not on the path
    659  *      already (either 'name' is absolute or it is a relative path
    660  *      [ dir1/.../dirn/file ] which exists below one of the directories
    661  *      already on the search path), its directory is added to the end
    662  *      of the path on the assumption that there will be more files in
    663  *      that directory later on. Sometimes this is true. Sometimes not.
     652 *      Find the file with the given name along the given search path.
     653 *
     654 * Results:
     655 *      The path to the file or NULL. This path is guaranteed to be in a
     656 *      different part of memory than name and so may be safely efree'd.
     657 *
     658 * Side Effects:
     659 *      If the file is found in a directory which is not on the path
     660 *      already (either 'name' is absolute or it is a relative path
     661 *      [ dir1/.../dirn/file ] which exists below one of the directories
     662 *      already on the search path), its directory is added to the end
     663 *      of the path on the assumption that there will be more files in
     664 *      that directory later on. Sometimes this is true. Sometimes not.
    664665 *-----------------------------------------------------------------------
    665666 */
    666667char *
    667668Dir_FindFile (name, path)
    668     char          *name;    /* the file to find */
    669     Lst           path;     /* the Lst of directories to search */
    670 {
    671     register char *p1;      /* pointer into p->name */
    672     register char *p2;      /* pointer into name */
    673     LstNode       ln;       /* a list element */
     669    char          *name;    /* the file to find */
     670    Lst           path;     /* the Lst of directories to search */
     671{
     672    register char *p1;      /* pointer into p->name */
     673    register char *p2;      /* pointer into name */
     674    LstNode       ln;       /* a list element */
    674675    register char *file;    /* the current filename to check */
    675     register Path *p;       /* current path member */
    676     register char *cp;      /* index of first slash, if any */
    677     Boolean       hasSlash; /* true if 'name' contains a / */
    678     struct stat   stb;      /* Buffer for stat, if necessary */
    679     Hash_Entry    *entry;   /* Entry for mtimes table */
     676    register Path *p;       /* current path member */
     677    register char *cp;      /* index of first slash, if any */
     678    Boolean       hasSlash; /* true if 'name' contains a / */
     679    struct stat   stb;      /* Buffer for stat, if necessary */
     680    Hash_Entry    *entry;   /* Entry for mtimes table */
    680681
    681682#ifdef NMAKE
     
    691692    cp = strrchr (name, '/');
    692693    if (cp) {
    693         hasSlash = TRUE;
    694         cp += 1;
     694        hasSlash = TRUE;
     695        cp += 1;
    695696    } else {
    696         hasSlash = FALSE;
    697         cp = name;
     697        hasSlash = FALSE;
     698        cp = name;
    698699    }
    699700
    700701    if (DEBUG(DIR)) {
    701         printf("Searching for %s...", name);
     702        printf("Searching for %s...", name);
    702703    }
    703704    /*
     
    708709     */
    709710    if ((!hasSlash || (cp - name == 2 && *name == '.')) &&
    710         (Hash_FindEntry (&dot->files, cp) != (Hash_Entry *)NULL)) {
    711             if (DEBUG(DIR)) {
    712                 printf("in '.'\n");
    713             }
    714             hits += 1;
    715             dot->hits += 1;
    716             return (estrdup (name));
     711        (Hash_FindEntry (&dot->files, cp) != (Hash_Entry *)NULL)) {
     712            if (DEBUG(DIR)) {
     713                printf("in '.'\n");
     714            }
     715            hits += 1;
     716            dot->hits += 1;
     717            return (estrdup (name));
    717718    }
    718719
    719720    if (Lst_Open (path) == FAILURE) {
    720         if (DEBUG(DIR)) {
    721             printf("couldn't open path, file not found\n");
    722         }
    723         misses += 1;
    724         return ((char *) NULL);
     721        if (DEBUG(DIR)) {
     722            printf("couldn't open path, file not found\n");
     723        }
     724        misses += 1;
     725        return ((char *) NULL);
    725726    }
    726727
     
    734735     */
    735736    while ((ln = Lst_Next (path)) != NILLNODE) {
    736         p = (Path *) Lst_Datum (ln);
    737         if (DEBUG(DIR)) {
    738             printf("%s...", p->name);
    739         }
    740         if (Hash_FindEntry (&p->files, cp) != (Hash_Entry *)NULL) {
    741             if (DEBUG(DIR)) {
    742                 printf("here...");
    743             }
    744             if (hasSlash) {
    745                 /*
    746                 * If the name had a slash, its initial components and p's
    747                 * final components must match. This is false if a mismatch
    748                 * is encountered before all of the initial components
    749                 * have been checked (p2 > name at the end of the loop), or
    750                 * we matched only part of one of the components of p
    751                 * along with all the rest of them (*p1 != '/').
    752                 */
    753                 p1 = p->name + strlen (p->name) - 1;
    754                 p2 = cp - 2;
    755                 while (p2 >= name && p1 >= p->name && *p1 == *p2) {
    756                     p1 -= 1; p2 -= 1;
    757                 }
    758                 if (p2 >= name || (p1 >= p->name && *p1 != '/')) {
    759                     if (DEBUG(DIR)) {
    760                         printf("component mismatch -- continuing...");
    761                     }
    762                     continue;
    763                 }
    764             }
    765             file = str_concat (p->name, cp, STR_ADDSLASH);
    766             if (DEBUG(DIR)) {
    767                 printf("returning %s\n", file);
    768             }
    769             Lst_Close (path);
    770             p->hits += 1;
    771             hits += 1;
    772             return (file);
    773         } else if (hasSlash) {
    774             /*
    775              * If the file has a leading path component and that component
    776              * exactly matches the entire name of the current search
    777              * directory, we assume the file doesn't exist and return NULL.
    778              */
    779             for (p1 = p->name, p2 = name; *p1 && *p1 == *p2; p1++, p2++) {
    780                 continue;
    781             }
    782             if (*p1 == '\0' && p2 == cp - 1) {
    783                 if (DEBUG(DIR)) {
    784                     printf("must be here but isn't -- returing NULL\n");
    785                 }
    786                 Lst_Close (path);
    787                 return ((char *) NULL);
    788             }
    789         }
     737        p = (Path *) Lst_Datum (ln);
     738        if (DEBUG(DIR)) {
     739            printf("%s...", p->name);
     740        }
     741        if (Hash_FindEntry (&p->files, cp) != (Hash_Entry *)NULL) {
     742            if (DEBUG(DIR)) {
     743                printf("here...");
     744            }
     745            if (hasSlash) {
     746                /*
     747                * If the name had a slash, its initial components and p's
     748                * final components must match. This is false if a mismatch
     749                * is encountered before all of the initial components
     750                * have been checked (p2 > name at the end of the loop), or
     751                * we matched only part of one of the components of p
     752                * along with all the rest of them (*p1 != '/').
     753                */
     754                p1 = p->name + strlen (p->name) - 1;
     755                p2 = cp - 2;
     756                while (p2 >= name && p1 >= p->name && *p1 == *p2) {
     757                    p1 -= 1; p2 -= 1;
     758                }
     759                if (p2 >= name || (p1 >= p->name && *p1 != '/')) {
     760                    if (DEBUG(DIR)) {
     761                        printf("component mismatch -- continuing...");
     762                    }
     763                    continue;
     764                }
     765            }
     766            file = str_concat (p->name, cp, STR_ADDSLASH);
     767            if (DEBUG(DIR)) {
     768                printf("returning %s\n", file);
     769            }
     770            Lst_Close (path);
     771            p->hits += 1;
     772            hits += 1;
     773            return (file);
     774        } else if (hasSlash) {
     775            /*
     776             * If the file has a leading path component and that component
     777             * exactly matches the entire name of the current search
     778             * directory, we assume the file doesn't exist and return NULL.
     779             */
     780            for (p1 = p->name, p2 = name; *p1 && *p1 == *p2; p1++, p2++) {
     781                continue;
     782            }
     783            if (*p1 == '\0' && p2 == cp - 1) {
     784                if (DEBUG(DIR)) {
     785                    printf("must be here but isn't -- returing NULL\n");
     786                }
     787                Lst_Close (path);
     788                return ((char *) NULL);
     789            }
     790        }
    790791    }
    791792
     
    803804     */
    804805    if (!hasSlash) {
    805         if (DEBUG(DIR)) {
    806             printf("failed.\n");
    807         }
    808         misses += 1;
    809         return ((char *) NULL);
     806        if (DEBUG(DIR)) {
     807            printf("failed.\n");
     808        }
     809        misses += 1;
     810        return ((char *) NULL);
    810811    }
    811812
    812813    if (*name != '/') {
    813         Boolean checkedDot = FALSE;
    814 
    815         if (DEBUG(DIR)) {
    816             printf("failed. Trying subdirectories...");
    817         }
    818         (void) Lst_Open (path);
    819         while ((ln = Lst_Next (path)) != NILLNODE) {
    820             p = (Path *) Lst_Datum (ln);
    821             if (p != dot) {
    822                 file = str_concat (p->name, name, STR_ADDSLASH);
    823             } else {
    824                 /*
    825                 * Checking in dot -- DON'T put a leading ./ on the thing.
    826                 */
    827                 file = estrdup(name);
    828                 checkedDot = TRUE;
    829             }
    830             if (DEBUG(DIR)) {
    831                 printf("checking %s...", file);
    832             }
    833 
    834 
    835             if (stat (file, &stb) == 0) {
    836                 if (DEBUG(DIR)) {
    837                     printf("got it.\n");
    838                 }
    839 
    840                 Lst_Close (path);
    841 
    842                 /*
    843                 * We've found another directory to search. We know there's
    844                 * a slash in 'file' because we put one there. We nuke it after
    845                 * finding it and call Dir_AddDir to add this new directory
    846                 * onto the existing search path. Once that's done, we restore
    847                 * the slash and triumphantly return the file name, knowing
    848                 * that should a file in this directory every be referenced
    849                 * again in such a manner, we will find it without having to do
    850                 * numerous numbers of access calls. Hurrah!
    851                 */
    852                 cp = strrchr (file, '/');
    853                 *cp = '\0';
    854                 Dir_AddDir (path, file);
    855                 *cp = '/';
    856 
    857                 /*
    858                 * Save the modification time so if it's needed, we don't have
    859                 * to fetch it again.
    860                 */
    861                 if (DEBUG(DIR)) {
    862                     printf("Caching %s for %s\n", Targ_FmtTime(stb.st_mtime),
    863                             file);
    864                 }
    865                 entry = Hash_CreateEntry(&mtimes, (char *) file,
    866                                         (Boolean *)NULL);
    867                 Hash_SetValue(entry, (long)stb.st_mtime);
    868                 nearmisses += 1;
    869                 return (file);
    870             } else {
    871                 efree (file);
    872             }
    873         }
    874 
    875         if (DEBUG(DIR)) {
    876             printf("failed. ");
    877         }
    878         Lst_Close (path);
    879 
    880         if (checkedDot) {
    881             /*
    882              * Already checked by the given name, since . was in the path,
    883              * so no point in proceeding...
    884              */
    885             if (DEBUG(DIR)) {
    886                 printf("Checked . already, returning NULL\n");
    887             }
    888             return(NULL);
    889         }
     814        Boolean checkedDot = FALSE;
     815
     816        if (DEBUG(DIR)) {
     817            printf("failed. Trying subdirectories...");
     818        }
     819        (void) Lst_Open (path);
     820        while ((ln = Lst_Next (path)) != NILLNODE) {
     821            p = (Path *) Lst_Datum (ln);
     822            if (p != dot) {
     823                file = str_concat (p->name, name, STR_ADDSLASH);
     824            } else {
     825                /*
     826                * Checking in dot -- DON'T put a leading ./ on the thing.
     827                */
     828                file = estrdup(name);
     829                checkedDot = TRUE;
     830            }
     831            if (DEBUG(DIR)) {
     832                printf("checking %s...", file);
     833            }
     834
     835
     836            if (stat (file, &stb) == 0) {
     837                if (DEBUG(DIR)) {
     838                    printf("got it.\n");
     839                }
     840
     841                Lst_Close (path);
     842
     843                /*
     844                * We've found another directory to search. We know there's
     845                * a slash in 'file' because we put one there. We nuke it after
     846                * finding it and call Dir_AddDir to add this new directory
     847                * onto the existing search path. Once that's done, we restore
     848                * the slash and triumphantly return the file name, knowing
     849                * that should a file in this directory every be referenced
     850                * again in such a manner, we will find it without having to do
     851                * numerous numbers of access calls. Hurrah!
     852                */
     853                cp = strrchr (file, '/');
     854                *cp = '\0';
     855                Dir_AddDir (path, file);
     856                *cp = '/';
     857
     858                /*
     859                * Save the modification time so if it's needed, we don't have
     860                * to fetch it again.
     861                */
     862                if (DEBUG(DIR)) {
     863                    printf("Caching %s for %s\n", Targ_FmtTime(stb.st_mtime),
     864                            file);
     865                }
     866                entry = Hash_CreateEntry(&mtimes, (char *) file,
     867                                        (Boolean *)NULL);
     868                Hash_SetValue(entry, (long)stb.st_mtime);
     869                nearmisses += 1;
     870                return (file);
     871            } else {
     872                efree (file);
     873            }
     874        }
     875
     876        if (DEBUG(DIR)) {
     877            printf("failed. ");
     878        }
     879        Lst_Close (path);
     880
     881        if (checkedDot) {
     882            /*
     883             * Already checked by the given name, since . was in the path,
     884             * so no point in proceeding...
     885             */
     886            if (DEBUG(DIR)) {
     887                printf("Checked . already, returning NULL\n");
     888            }
     889            return(NULL);
     890        }
    890891    }
    891892
     
    915916    ln = Lst_Last (path);
    916917    if (ln == NILLNODE) {
    917         return ((char *) NULL);
     918        return ((char *) NULL);
    918919    } else {
    919         p = (Path *) Lst_Datum (ln);
     920        p = (Path *) Lst_Datum (ln);
    920921    }
    921922
    922923    if (Hash_FindEntry (&p->files, cp) != (Hash_Entry *)NULL) {
    923         return (estrdup (name));
     924        return (estrdup (name));
    924925    } else {
    925         return ((char *) NULL);
     926        return ((char *) NULL);
    926927    }
    927928#else /* !notdef */
    928929    if (DEBUG(DIR)) {
    929         printf("Looking for \"%s\"...", name);
     930        printf("Looking for \"%s\"...", name);
    930931    }
    931932
     
    933934    entry = Hash_FindEntry(&mtimes, name);
    934935    if (entry != (Hash_Entry *)NULL) {
    935         if (DEBUG(DIR)) {
    936             printf("got it (in mtime cache)\n");
    937         }
    938         return(estrdup(name));
     936        if (DEBUG(DIR)) {
     937            printf("got it (in mtime cache)\n");
     938        }
     939        return(estrdup(name));
    939940    } else if (stat (name, &stb) == 0) {
    940         entry = Hash_CreateEntry(&mtimes, name, (Boolean *)NULL);
    941         if (DEBUG(DIR)) {
    942             printf("Caching %s for %s\n", Targ_FmtTime(stb.st_mtime),
    943                     name);
    944         }
    945         Hash_SetValue(entry, (long)stb.st_mtime);
    946         return (estrdup (name));
     941        entry = Hash_CreateEntry(&mtimes, name, (Boolean *)NULL);
     942        if (DEBUG(DIR)) {
     943            printf("Caching %s for %s\n", Targ_FmtTime(stb.st_mtime),
     944                    name);
     945        }
     946        Hash_SetValue(entry, (long)stb.st_mtime);
     947        return (estrdup (name));
    947948    } else {
    948         if (DEBUG(DIR)) {
    949             printf("failed. Returning NULL\n");
    950         }
    951         return ((char *)NULL);
     949        if (DEBUG(DIR)) {
     950            printf("failed. Returning NULL\n");
     951        }
     952        return ((char *)NULL);
    952953    }
    953954#endif /* notdef */
     
    957958 *-----------------------------------------------------------------------
    958959 * Dir_MTime  --
    959  *      Find the modification time of the file described by gn along the
    960  *      search path dirSearchPath.
    961  *
    962  * Results:
    963  *      The modification time or 0 if it doesn't exist
    964  *
    965  * Side Effects:
    966  *      The modification time is placed in the node's mtime slot.
    967  *      If the node didn't have a path entry before, and Dir_FindFile
    968  *      found one for it, the full name is placed in the path slot.
     960 *      Find the modification time of the file described by gn along the
     961 *      search path dirSearchPath.
     962 *
     963 * Results:
     964 *      The modification time or 0 if it doesn't exist
     965 *
     966 * Side Effects:
     967 *      The modification time is placed in the node's mtime slot.
     968 *      If the node didn't have a path entry before, and Dir_FindFile
     969 *      found one for it, the full name is placed in the path slot.
    969970 *-----------------------------------------------------------------------
    970971 */
    971972int
    972973Dir_MTime (gn)
    973     GNode         *gn;        /* the file whose modification time is
    974                                * desired */
     974    GNode         *gn;        /* the file whose modification time is
     975                               * desired */
    975976{
    976977    char          *fullName;  /* the full pathname of name */
    977     struct stat   stb;        /* buffer for finding the mod time */
    978     Hash_Entry    *entry;
     978    struct stat   stb;        /* buffer for finding the mod time */
     979    Hash_Entry    *entry;
    979980
    980981    #ifdef USE_ARCHIVES
    981982    if (gn->type & OP_ARCHV) {
    982         return Arch_MTime (gn);
     983        return Arch_MTime (gn);
    983984    } else
    984985    #endif
    985986        if (gn->path == (char *)NULL) {
    986         fullName = Dir_FindFile (gn->name, dirSearchPath);
     987        fullName = Dir_FindFile (gn->name, dirSearchPath);
    987988    } else {
    988         fullName = gn->path;
     989        fullName = gn->path;
    989990    }
    990991
    991992    if (fullName == (char *)NULL) {
    992         fullName = estrdup(gn->name);
     993        fullName = estrdup(gn->name);
    993994    }
    994995
    995996    entry = Hash_FindEntry(&mtimes, fullName);
    996997    if (entry != (Hash_Entry *)NULL) {
    997         /*
    998         * Only do this once -- the second time folks are checking to
    999         * see if the file was actually updated, so we need to actually go
    1000         * to the file system.
    1001         */
    1002         if (DEBUG(DIR)) {
    1003             printf("Using cached time %s for %s\n",
    1004                     Targ_FmtTime((time_t)(long)Hash_GetValue(entry)), fullName);
    1005         }
    1006         stb.st_mtime = (time_t)(long)Hash_GetValue(entry);
    1007         Hash_DeleteEntry(&mtimes, entry);
     998        /*
     999        * Only do this once -- the second time folks are checking to
     1000        * see if the file was actually updated, so we need to actually go
     1001        * to the file system.
     1002        */
     1003        if (DEBUG(DIR)) {
     1004            printf("Using cached time %s for %s\n",
     1005                    Targ_FmtTime((time_t)(long)Hash_GetValue(entry)), fullName);
     1006        }
     1007        stb.st_mtime = (time_t)(long)Hash_GetValue(entry);
     1008        Hash_DeleteEntry(&mtimes, entry);
    10081009    } else if (stat (fullName, &stb) < 0) {
    10091010        #ifdef USE_ARCHIVES
    1010         if (gn->type & OP_MEMBER) {
    1011             if (fullName != gn->path)
    1012                 efree(fullName);
    1013             return Arch_MemMTime (gn);
    1014         } else
     1011        if (gn->type & OP_MEMBER) {
     1012            if (fullName != gn->path)
     1013                efree(fullName);
     1014            return Arch_MemMTime (gn);
     1015        } else
    10151016        #endif
    1016             stb.st_mtime = 0;
     1017            stb.st_mtime = 0;
    10171018    }
    10181019    if (fullName && gn->path == (char *)NULL) {
    1019         gn->path = fullName;
     1020        gn->path = fullName;
    10201021    }
    10211022
     
    10271028 *-----------------------------------------------------------------------
    10281029 * Dir_AddDir --
    1029  *      Add the given name to the end of the given path. The order of
    1030  *      the arguments is backwards so ParseDoDependency can do a
    1031  *      Lst_ForEach of its list of paths...
    1032  *
    1033  * Results:
    1034  *      none
    1035  *
    1036  * Side Effects:
    1037  *      A structure is added to the list and the directory is
    1038  *      read and hashed.
     1030 *      Add the given name to the end of the given path. The order of
     1031 *      the arguments is backwards so ParseDoDependency can do a
     1032 *      Lst_ForEach of its list of paths...
     1033 *
     1034 * Results:
     1035 *      none
     1036 *
     1037 * Side Effects:
     1038 *      A structure is added to the list and the directory is
     1039 *      read and hashed.
    10391040 *-----------------------------------------------------------------------
    10401041 */
    10411042void
    10421043Dir_AddDir (path, name)
    1043     Lst           path;       /* the path to which the directory should be
    1044                                * added */
     1044    Lst           path;       /* the path to which the directory should be
     1045                               * added */
    10451046    char          *name;      /* the name of the directory to add */
    10461047{
    1047     LstNode       ln;         /* node in case Path structure is found */
    1048     register Path *p;         /* pointer to new Path structure */
    1049     DIR           *d;         /* for reading directory */
     1048    LstNode       ln;         /* node in case Path structure is found */
     1049    register Path *p;         /* pointer to new Path structure */
     1050    DIR           *d;         /* for reading directory */
    10501051    register struct dirent *dp; /* entry in directory */
    10511052
    10521053    ln = Lst_Find (openDirectories, (ClientData)name, DirFindName);
    10531054    if (ln != NILLNODE) {
    1054         p = (Path *)Lst_Datum (ln);
    1055         if (Lst_Member(path, (ClientData)p) == NILLNODE) {
    1056             p->refCount += 1;
    1057             (void)Lst_AtEnd (path, (ClientData)p);
    1058         }
     1055        p = (Path *)Lst_Datum (ln);
     1056        if (Lst_Member(path, (ClientData)p) == NILLNODE) {
     1057            p->refCount += 1;
     1058            (void)Lst_AtEnd (path, (ClientData)p);
     1059        }
    10591060    } else {
    1060         if (DEBUG(DIR)) {
    1061             printf("Caching %s...", name);
    1062             fflush(stdout);
    1063         }
    1064 
    1065         if ((d = opendir (name)) != (DIR *) NULL) {
    1066             p = (Path *) emalloc (sizeof (Path));
    1067             p->name = estrdup (name);
    1068             p->hits = 0;
    1069             p->refCount = 1;
    1070             Hash_InitTable (&p->files, -1);
    1071 
    1072             while ((dp = readdir (d)) != (struct dirent *) NULL) {
     1061        if (DEBUG(DIR)) {
     1062            printf("Caching %s...", name);
     1063            fflush(stdout);
     1064        }
     1065
     1066        if ((d = opendir (name)) != (DIR *) NULL) {
     1067            p = (Path *) emalloc (sizeof (Path));
     1068            p->name = estrdup (name);
     1069            p->hits = 0;
     1070            p->refCount = 1;
     1071            Hash_InitTable (&p->files, -1);
     1072
     1073            while ((dp = readdir (d)) != (struct dirent *) NULL) {
    10731074#if defined(sun) && defined(d_ino) /* d_ino is a sunos4 #define for d_fileno */
    1074                 /*
    1075                 * The sun directory library doesn't check for a 0 inode
    1076                 * (0-inode slots just take up space), so we have to do
    1077                 * it ourselves.
    1078                 */
    1079                 if (dp->d_fileno == 0) {
    1080                     continue;
    1081                 }
     1075                /*
     1076                * The sun directory library doesn't check for a 0 inode
     1077                * (0-inode slots just take up space), so we have to do
     1078                * it ourselves.
     1079                */
     1080                if (dp->d_fileno == 0) {
     1081                    continue;
     1082                }
    10821083#endif /* sun && d_ino */
    10831084
    1084                 /* Skip the '.' and '..' entries by checking for them
    1085                 * specifically instead of assuming readdir() reuturns them in
    1086                 * that order when first going through a directory.  This is
    1087                 * needed for XFS over NFS filesystems since SGI does not
    1088                 * guarantee that these are * the first two entries returned
    1089                 * from readdir().
    1090                 */
    1091                 if (ISDOT(dp->d_name) || ISDOTDOT(dp->d_name))
    1092                         continue;
    1093 
    1094                 (void)Hash_CreateEntry(&p->files, dp->d_name, (Boolean *)NULL);
    1095             }
    1096             (void) closedir (d);
    1097             (void)Lst_AtEnd (openDirectories, (ClientData)p);
    1098             (void)Lst_AtEnd (path, (ClientData)p);
    1099         }
    1100         if (DEBUG(DIR)) {
    1101             printf("done\n");
    1102         }
     1085                /* Skip the '.' and '..' entries by checking for them
     1086                * specifically instead of assuming readdir() reuturns them in
     1087                * that order when first going through a directory.  This is
     1088                * needed for XFS over NFS filesystems since SGI does not
     1089                * guarantee that these are * the first two entries returned
     1090                * from readdir().
     1091                */
     1092                if (ISDOT(dp->d_name) || ISDOTDOT(dp->d_name))
     1093                        continue;
     1094
     1095                (void)Hash_CreateEntry(&p->files, dp->d_name, (Boolean *)NULL);
     1096            }
     1097            (void) closedir (d);
     1098            (void)Lst_AtEnd (openDirectories, (ClientData)p);
     1099            (void)Lst_AtEnd (path, (ClientData)p);
     1100        }
     1101        if (DEBUG(DIR)) {
     1102            printf("done\n");
     1103        }
    11031104    }
    11041105}
     
    11071108 *-----------------------------------------------------------------------
    11081109 * Dir_CopyDir --
    1109  *      Callback function for duplicating a search path via Lst_Duplicate.
    1110  *      Ups the reference count for the directory.
    1111  *
    1112  * Results:
    1113  *      Returns the Path it was given.
    1114  *
    1115  * Side Effects:
    1116  *      The refCount of the path is incremented.
     1110 *      Callback function for duplicating a search path via Lst_Duplicate.
     1111 *      Ups the reference count for the directory.
     1112 *
     1113 * Results:
     1114 *      Returns the Path it was given.
     1115 *
     1116 * Side Effects:
     1117 *      The refCount of the path is incremented.
    11171118 *
    11181119 *-----------------------------------------------------------------------
     
    11301131 *-----------------------------------------------------------------------
    11311132 * Dir_MakeFlags --
    1132  *      Make a string by taking all the directories in the given search
    1133  *      path and preceding them by the given flag. Used by the suffix
    1134  *      module to create variables for compilers based on suffix search
    1135  *      paths.
    1136  *
    1137  * Results:
    1138  *      The string mentioned above. Note that there is no space between
    1139  *      the given flag and each directory. The empty string is returned if
    1140  *      Things don't go well.
    1141  *
    1142  * Side Effects:
    1143  *      None
     1133 *      Make a string by taking all the directories in the given search
     1134 *      path and preceding them by the given flag. Used by the suffix
     1135 *      module to create variables for compilers based on suffix search
     1136 *      paths.
     1137 *
     1138 * Results:
     1139 *      The string mentioned above. Note that there is no space between
     1140 *      the given flag and each directory. The empty string is returned if
     1141 *      Things don't go well.
     1142 *
     1143 * Side Effects:
     1144 *      None
    11441145 *-----------------------------------------------------------------------
    11451146 */
    11461147char *
    11471148Dir_MakeFlags (flag, path)
    1148     char          *flag;  /* flag which should precede each directory */
    1149     Lst           path;   /* list of directories */
    1150 {
    1151     char          *str;   /* the string which will be returned */
    1152     char          *tstr;  /* the current directory preceded by 'flag' */
    1153     LstNode       ln;     /* the node of the current directory */
    1154     Path          *p;     /* the structure describing the current directory */
     1149    char          *flag;  /* flag which should precede each directory */
     1150    Lst           path;   /* list of directories */
     1151{
     1152    char          *str;   /* the string which will be returned */
     1153    char          *tstr;  /* the current directory preceded by 'flag' */
     1154    LstNode       ln;     /* the node of the current directory */
     1155    Path          *p;     /* the structure describing the current directory */
    11551156
    11561157    str = estrdup ("");
    11571158
    11581159    if (Lst_Open (path) == SUCCESS) {
    1159         while ((ln = Lst_Next (path)) != NILLNODE) {
    1160             p = (Path *) Lst_Datum (ln);
    1161             tstr = str_concat (flag, p->name, 0);
    1162             str = str_concat (str, tstr, STR_ADDSPACE | STR_DOFREE);
    1163         }
    1164         Lst_Close (path);
     1160        while ((ln = Lst_Next (path)) != NILLNODE) {
     1161            p = (Path *) Lst_Datum (ln);
     1162            tstr = str_concat (flag, p->name, 0);
     1163            str = str_concat (str, tstr, STR_ADDSPACE | STR_DOFREE);
     1164        }
     1165        Lst_Close (path);
    11651166    }
    11661167
     
    11711172 *-----------------------------------------------------------------------
    11721173 * Dir_Destroy --
    1173  *      Nuke a directory descriptor, if possible. Callback procedure
    1174  *      for the suffixes module when destroying a search path.
    1175  *
    1176  * Results:
    1177  *      None.
    1178  *
    1179  * Side Effects:
    1180  *      If no other path references this directory (refCount == 0),
    1181  *      the Path and all its data are freed.
     1174 *      Nuke a directory descriptor, if possible. Callback procedure
     1175 *      for the suffixes module when destroying a search path.
     1176 *
     1177 * Results:
     1178 *      None.
     1179 *
     1180 * Side Effects:
     1181 *      If no other path references this directory (refCount == 0),
     1182 *      the Path and all its data are freed.
    11821183 *
    11831184 *-----------------------------------------------------------------------
     
    11851186void
    11861187Dir_Destroy (pp)
    1187     ClientData    pp;       /* The directory descriptor to nuke */
    1188 {
    1189     Path          *p = (Path *) pp;
     1188    ClientData    pp;       /* The directory descriptor to nuke */
     1189{
     1190    Path          *p = (Path *) pp;
    11901191    p->refCount -= 1;
    11911192
    11921193    if (p->refCount == 0) {
    1193         LstNode ln;
    1194 
    1195         ln = Lst_Member (openDirectories, (ClientData)p);
    1196         (void) Lst_Remove (openDirectories, ln);
    1197 
    1198         Hash_DeleteTable (&p->files);
    1199         efree((Address)p->name);
    1200         efree((Address)p);
     1194        LstNode ln;
     1195
     1196        ln = Lst_Member (openDirectories, (ClientData)p);
     1197        (void) Lst_Remove (openDirectories, ln);
     1198
     1199        Hash_DeleteTable (&p->files);
     1200        efree((Address)p->name);
     1201        efree((Address)p);
    12011202    }
    12021203}
     
    12051206 *-----------------------------------------------------------------------
    12061207 * Dir_ClearPath --
    1207  *      Clear out all elements of the given search path. This is different
    1208  *      from destroying the list, notice.
    1209  *
    1210  * Results:
    1211  *      None.
    1212  *
    1213  * Side Effects:
    1214  *      The path is set to the empty list.
     1208 *      Clear out all elements of the given search path. This is different
     1209 *      from destroying the list, notice.
     1210 *
     1211 * Results:
     1212 *      None.
     1213 *
     1214 * Side Effects:
     1215 *      The path is set to the empty list.
    12151216 *
    12161217 *-----------------------------------------------------------------------
     
    12181219void
    12191220Dir_ClearPath(path)
    1220     Lst     path;       /* Path to clear */
     1221    Lst     path;       /* Path to clear */
    12211222{
    12221223    Path    *p;
    12231224    while (!Lst_IsEmpty(path)) {
    1224         p = (Path *)Lst_DeQueue(path);
    1225         Dir_Destroy((ClientData) p);
     1225        p = (Path *)Lst_DeQueue(path);
     1226        Dir_Destroy((ClientData) p);
    12261227    }
    12271228}
     
    12311232 *-----------------------------------------------------------------------
    12321233 * Dir_Concat --
    1233  *      Concatenate two paths, adding the second to the end of the first.
    1234  *      Makes sure to avoid duplicates.
    1235  *
    1236  * Results:
    1237  *      None
    1238  *
    1239  * Side Effects:
    1240  *      Reference counts for added dirs are upped.
     1234 *      Concatenate two paths, adding the second to the end of the first.
     1235 *      Makes sure to avoid duplicates.
     1236 *
     1237 * Results:
     1238 *      None
     1239 *
     1240 * Side Effects:
     1241 *      Reference counts for added dirs are upped.
    12411242 *
    12421243 *-----------------------------------------------------------------------
     
    12441245void
    12451246Dir_Concat(path1, path2)
    1246     Lst     path1;      /* Dest */
    1247     Lst     path2;      /* Source */
     1247    Lst     path1;      /* Dest */
     1248    Lst     path2;      /* Source */
    12481249{
    12491250    LstNode ln;
     
    12511252
    12521253    for (ln = Lst_First(path2); ln != NILLNODE; ln = Lst_Succ(ln)) {
    1253         p = (Path *)Lst_Datum(ln);
    1254         if (Lst_Member(path1, (ClientData)p) == NILLNODE) {
    1255             p->refCount += 1;
    1256             (void)Lst_AtEnd(path1, (ClientData)p);
    1257         }
     1254        p = (Path *)Lst_Datum(ln);
     1255        if (Lst_Member(path1, (ClientData)p) == NILLNODE) {
     1256            p->refCount += 1;
     1257            (void)Lst_AtEnd(path1, (ClientData)p);
     1258        }
    12581259    }
    12591260}
     
    12631264Dir_PrintDirectories()
    12641265{
    1265     LstNode     ln;
    1266     Path        *p;
     1266    LstNode     ln;
     1267    Path        *p;
    12671268
    12681269    printf ("#*** Directory Cache:\n");
    12691270    printf ("# Stats: %d hits %d misses %d near misses %d losers (%d%%)\n",
    1270               hits, misses, nearmisses, bigmisses,
    1271               (hits+bigmisses+nearmisses ?
    1272                hits * 100 / (hits + bigmisses + nearmisses) : 0));
     1271              hits, misses, nearmisses, bigmisses,
     1272              (hits+bigmisses+nearmisses ?
     1273               hits * 100 / (hits + bigmisses + nearmisses) : 0));
    12731274    printf ("# %-20s referenced\thits\n", "directory");
    12741275    if (Lst_Open (openDirectories) == SUCCESS) {
    1275         while ((ln = Lst_Next (openDirectories)) != NILLNODE) {
    1276             p = (Path *) Lst_Datum (ln);
    1277             printf ("# %-20s %10d\t%4d\n", p->name, p->refCount, p->hits);
    1278         }
    1279         Lst_Close (openDirectories);
     1276        while ((ln = Lst_Next (openDirectories)) != NILLNODE) {
     1277            p = (Path *) Lst_Datum (ln);
     1278            printf ("# %-20s %10d\t%4d\n", p->name, p->refCount, p->hits);
     1279        }
     1280        Lst_Close (openDirectories);
    12801281    }
    12811282}
    12821283
    12831284static int DirPrintDir (p, dummy)
    1284     ClientData  p;
    1285     ClientData  dummy;
     1285    ClientData  p;
     1286    ClientData  dummy;
    12861287{
    12871288    printf ("%s ", ((Path *) p)->name);
     
    12911292void
    12921293Dir_PrintPath (path)
    1293     Lst path;
     1294    Lst path;
    12941295{
    12951296    Lst_ForEach (path, DirPrintDir, (ClientData)0);
  • trunk/src/kmk/for.c

    r35 r51  
    1313 * 3. All advertising materials mentioning features or use of this software
    1414 *    must display the following acknowledgement:
    15  *      This product includes software developed by the University of
    16  *      California, Berkeley and its contributors.
     15 *      This product includes software developed by the University of
     16 *      California, Berkeley and its contributors.
    1717 * 4. Neither the name of the University nor the names of its contributors
    1818 *    may be used to endorse or promote products derived from this software
     
    3434#ifndef lint
    3535#if 0
    36 static char sccsid[] = "@(#)for.c       8.1 (Berkeley) 6/6/93";
     36static char sccsid[] = "@(#)for.c       8.1 (Berkeley) 6/6/93";
    3737#else
    3838static const char rcsid[] =
    3939  "$FreeBSD: src/usr.bin/make/for.c,v 1.10 1999/09/11 13:08:01 hoek Exp $";
    4040#endif
     41#define KLIBFILEDEF rcsid
    4142#endif /* not lint */
    4243
    4344/*-
    4445 * for.c --
    45  *      Functions to handle loops in a makefile.
     46 *      Functions to handle loops in a makefile.
    4647 *
    4748 * Interface:
    48  *      For_Eval        Evaluate the loop in the passed line.
    49  *      For_Run         Run accumulated loop
     49 *      For_Eval        Evaluate the loop in the passed line.
     50 *      For_Run         Run accumulated loop
    5051 *
    5152 */
     
    7172 */
    7273
    73 static int        forLevel = 0;         /* Nesting level        */
    74 static char      *forVar;               /* Iteration variable   */
    75 static Buffer     forBuf;               /* Commands in loop     */
    76 static Lst        forLst;               /* List of items        */
     74static int        forLevel = 0;         /* Nesting level        */
     75static char      *forVar;               /* Iteration variable   */
     76static Buffer     forBuf;               /* Commands in loop     */
     77static Lst        forLst;               /* List of items        */
    7778
    7879/*
     
    8081 */
    8182typedef struct _For {
    82     Buffer        buf;                  /* Unexpanded buffer    */
    83     char*         var;                  /* Index name           */
    84     Lst           lst;                  /* List of variables    */
     83    Buffer        buf;                  /* Unexpanded buffer    */
     84    char*         var;                  /* Index name           */
     85    Lst           lst;                  /* List of variables    */
    8586} For;
    8687
    87 static int ForExec      __P((ClientData, ClientData));
     88static int ForExec      __P((ClientData, ClientData));
    8889
    8990
     
    9495 *-----------------------------------------------------------------------
    9596 * For_Eval --
    96  *      Evaluate the for loop in the passed line. The line
    97  *      looks like this:
    98  *          .for <variable> in <varlist>
     97 *      Evaluate the for loop in the passed line. The line
     98 *      looks like this:
     99 *          .for <variable> in <varlist>
    99100 *
    100101 * Results:
    101  *      TRUE: We found a for loop, or we are inside a for loop
    102  *      FALSE: We did not find a for loop, or we found the end of the for
    103  *             for loop.
     102 *      TRUE: We found a for loop, or we are inside a for loop
     103 *      FALSE: We did not find a for loop, or we found the end of the for
     104 *             for loop.
    104105 *
    105106 * Side Effects:
    106  *      None.
     107 *      None.
    107108 *
    108109 *-----------------------------------------------------------------------
     
    110111int
    111112For_Eval (line)
    112     char            *line;    /* Line to parse */
     113    char            *line;    /* Line to parse */
    113114{
    114     char            *ptr = line, *sub, *wrd;
    115     int             level;      /* Level at which to report errors. */
     115    char            *ptr = line, *sub, *wrd;
     116    int             level;      /* Level at which to report errors. */
    116117
    117118    level = PARSE_FATAL;
     
    119120
    120121    if (forLevel == 0) {
    121         Buffer      buf;
    122         int         varlen;
    123 
    124         for (ptr++; *ptr && isspace((unsigned char) *ptr); ptr++)
    125             continue;
    126         /*
    127         * If we are not in a for loop quickly determine if the statement is
    128         * a for.
    129         */
    130         if (ptr[0] != 'f' || ptr[1] != 'o' || ptr[2] != 'r' ||
    131             !isspace((unsigned char) ptr[3]))
    132             return FALSE;
    133         ptr += 3;
    134 
    135         /*
    136         * we found a for loop, and now we are going to parse it.
    137         */
    138         while (*ptr && isspace((unsigned char) *ptr))
    139             ptr++;
    140 
    141         /*
    142         * Grab the variable
    143         */
    144         buf = Buf_Init(0);
    145         for (wrd = ptr; *ptr && !isspace((unsigned char) *ptr); ptr++)
    146             continue;
    147         Buf_AddBytes(buf, ptr - wrd, (Byte *) wrd);
    148 
    149         forVar = (char *) Buf_GetAll(buf, &varlen);
    150         if (varlen == 0) {
    151             Parse_Error (level, "missing variable in for");
    152             return 0;
    153         }
    154         Buf_Destroy(buf, FALSE);
    155 
    156         while (*ptr && isspace((unsigned char) *ptr))
    157             ptr++;
    158 
    159         /*
    160         * Grab the `in'
    161         */
    162         if (ptr[0] != 'i' || ptr[1] != 'n' ||
    163             !isspace((unsigned char) ptr[2])) {
    164             Parse_Error (level, "missing `in' in for");
    165             printf("%s\n", ptr);
    166             return 0;
    167         }
    168         ptr += 3;
    169 
    170         while (*ptr && isspace((unsigned char) *ptr))
    171             ptr++;
    172 
    173         /*
    174         * Make a list with the remaining words
    175         */
    176         forLst = Lst_Init(FALSE);
    177         buf = Buf_Init(0);
    178         sub = Var_Subst(NULL, ptr, VAR_GLOBAL, FALSE);
     122        Buffer      buf;
     123        int         varlen;
     124
     125        for (ptr++; *ptr && isspace((unsigned char) *ptr); ptr++)
     126            continue;
     127        /*
     128        * If we are not in a for loop quickly determine if the statement is
     129        * a for.
     130        */
     131        if (ptr[0] != 'f' || ptr[1] != 'o' || ptr[2] != 'r' ||
     132            !isspace((unsigned char) ptr[3]))
     133            return FALSE;
     134        ptr += 3;
     135
     136        /*
     137        * we found a for loop, and now we are going to parse it.
     138        */
     139        while (*ptr && isspace((unsigned char) *ptr))
     140            ptr++;
     141
     142        /*
     143        * Grab the variable
     144        */
     145        buf = Buf_Init(0);
     146        for (wrd = ptr; *ptr && !isspace((unsigned char) *ptr); ptr++)
     147            continue;
     148        Buf_AddBytes(buf, ptr - wrd, (Byte *) wrd);
     149
     150        forVar = (char *) Buf_GetAll(buf, &varlen);
     151        if (varlen == 0) {
     152            Parse_Error (level, "missing variable in for");
     153            return 0;
     154        }
     155        Buf_Destroy(buf, FALSE);
     156
     157        while (*ptr && isspace((unsigned char) *ptr))
     158            ptr++;
     159
     160        /*
     161        * Grab the `in'
     162        */
     163        if (ptr[0] != 'i' || ptr[1] != 'n' ||
     164            !isspace((unsigned char) ptr[2])) {
     165            Parse_Error (level, "missing `in' in for");
     166            printf("%s\n", ptr);
     167            return 0;
     168        }
     169        ptr += 3;
     170
     171        while (*ptr && isspace((unsigned char) *ptr))
     172            ptr++;
     173
     174        /*
     175        * Make a list with the remaining words
     176        */
     177        forLst = Lst_Init(FALSE);
     178        buf = Buf_Init(0);
     179        sub = Var_Subst(NULL, ptr, VAR_GLOBAL, FALSE);
    179180
    180181#define ADDWORD() \
    181         Buf_AddBytes(buf, ptr - wrd, (Byte *) wrd), \
    182         Buf_AddByte(buf, (Byte) '\0'), \
    183         Lst_AtFront(forLst, (ClientData) Buf_GetAll(buf, &varlen)), \
    184         Buf_Destroy(buf, FALSE)
    185 
    186         for (ptr = sub; *ptr && isspace((unsigned char) *ptr); ptr++)
    187             continue;
    188 
    189         for (wrd = ptr; *ptr; ptr++)
    190             if (isspace((unsigned char) *ptr)) {
    191                 ADDWORD();
    192                 buf = Buf_Init(0);
    193                 while (*ptr && isspace((unsigned char) *ptr))
    194                     ptr++;
    195                 wrd = ptr--;
    196             }
    197         if (DEBUG(FOR))
    198             (void) fprintf(stderr, "For: Iterator %s List %s\n", forVar, sub);
    199         if (ptr - wrd > 0)
    200             ADDWORD();
    201         else
    202             Buf_Destroy(buf, TRUE);
    203         efree((Address) sub);
    204 
    205         forBuf = Buf_Init(0);
    206         forLevel++;
    207         return 1;
     182        Buf_AddBytes(buf, ptr - wrd, (Byte *) wrd), \
     183        Buf_AddByte(buf, (Byte) '\0'), \
     184        Lst_AtFront(forLst, (ClientData) Buf_GetAll(buf, &varlen)), \
     185        Buf_Destroy(buf, FALSE)
     186
     187        for (ptr = sub; *ptr && isspace((unsigned char) *ptr); ptr++)
     188            continue;
     189
     190        for (wrd = ptr; *ptr; ptr++)
     191            if (isspace((unsigned char) *ptr)) {
     192                ADDWORD();
     193                buf = Buf_Init(0);
     194                while (*ptr && isspace((unsigned char) *ptr))
     195                    ptr++;
     196                wrd = ptr--;
     197            }
     198        if (DEBUG(FOR))
     199            (void) fprintf(stderr, "For: Iterator %s List %s\n", forVar, sub);
     200        if (ptr - wrd > 0)
     201            ADDWORD();
     202        else
     203            Buf_Destroy(buf, TRUE);
     204        efree((Address) sub);
     205
     206        forBuf = Buf_Init(0);
     207        forLevel++;
     208        return 1;
    208209    }
    209210    else if (*ptr == '.') {
    210211
    211         for (ptr++; *ptr && isspace((unsigned char) *ptr); ptr++)
    212             continue;
    213 
    214         if (strncmp(ptr, "endfor", 6) == 0 &&
    215             (isspace((unsigned char) ptr[6]) || !ptr[6])) {
    216             if (DEBUG(FOR))
    217                 (void) fprintf(stderr, "For: end for %d\n", forLevel);
    218             if (--forLevel < 0) {
    219                 Parse_Error (level, "for-less endfor");
    220                 return 0;
    221             }
    222         }
    223         else if (strncmp(ptr, "for", 3) == 0 &&
    224                 isspace((unsigned char) ptr[3])) {
    225             forLevel++;
    226             if (DEBUG(FOR))
    227                 (void) fprintf(stderr, "For: new loop %d\n", forLevel);
    228         }
     212        for (ptr++; *ptr && isspace((unsigned char) *ptr); ptr++)
     213            continue;
     214
     215        if (strncmp(ptr, "endfor", 6) == 0 &&
     216            (isspace((unsigned char) ptr[6]) || !ptr[6])) {
     217            if (DEBUG(FOR))
     218                (void) fprintf(stderr, "For: end for %d\n", forLevel);
     219            if (--forLevel < 0) {
     220                Parse_Error (level, "for-less endfor");
     221                return 0;
     222            }
     223        }
     224        else if (strncmp(ptr, "for", 3) == 0 &&
     225                isspace((unsigned char) ptr[3])) {
     226            forLevel++;
     227            if (DEBUG(FOR))
     228                (void) fprintf(stderr, "For: new loop %d\n", forLevel);
     229        }
    229230    }
    230231
    231232    if (forLevel != 0) {
    232         Buf_AddBytes(forBuf, strlen(line), (Byte *) line);
    233         Buf_AddByte(forBuf, (Byte) '\n');
    234         return 1;
     233        Buf_AddBytes(forBuf, strlen(line), (Byte *) line);
     234        Buf_AddByte(forBuf, (Byte) '\n');
     235        return 1;
    235236    }
    236237    else {
    237         return 0;
     238        return 0;
    238239    }
    239240}
     
    242243 *-----------------------------------------------------------------------
    243244 * ForExec --
    244  *      Expand the for loop for this index and push it in the Makefile
     245 *      Expand the for loop for this index and push it in the Makefile
    245246 *
    246247 * Results:
    247  *      None.
     248 *      None.
    248249 *
    249250 * Side Effects:
    250  *      None.
     251 *      None.
    251252 *
    252253 *-----------------------------------------------------------------------
     
    262263    Var_Set(arg->var, name, VAR_GLOBAL);
    263264    if (DEBUG(FOR))
    264         (void) fprintf(stderr, "--- %s = %s\n", arg->var, name);
     265        (void) fprintf(stderr, "--- %s = %s\n", arg->var, name);
    265266    Parse_FromString(Var_Subst(arg->var, (char *) Buf_GetAll(arg->buf, &len),
    266                                VAR_GLOBAL, FALSE));
     267                               VAR_GLOBAL, FALSE));
    267268    Var_Delete(arg->var, VAR_GLOBAL);
    268269
     
    275276 *-----------------------------------------------------------------------
    276277 * For_Run --
    277  *      Run the for loop, immitating the actions of an include file
     278 *      Run the for loop, immitating the actions of an include file
    278279 *
    279280 * Results:
    280  *      None.
     281 *      None.
    281282 *
    282283 * Side Effects:
    283  *      None.
     284 *      None.
    284285 *
    285286 *-----------------------------------------------------------------------
     
    291292
    292293    if (forVar == NULL || forBuf == NULL || forLst == NULL)
    293         return;
     294        return;
    294295    arg.var = forVar;
    295296    arg.buf = forBuf;
  • trunk/src/kmk/hash.c

    r35 r51  
    1818 * 3. All advertising materials mentioning features or use of this software
    1919 *    must display the following acknowledgement:
    20  *      This product includes software developed by the University of
    21  *      California, Berkeley and its contributors.
     20 *      This product includes software developed by the University of
     21 *      California, Berkeley and its contributors.
    2222 * 4. Neither the name of the University nor the names of its contributors
    2323 *    may be used to endorse or promote products derived from this software
     
    3939#ifndef lint
    4040#if 0
    41 static char sccsid[] = "@(#)hash.c      8.1 (Berkeley) 6/6/93";
     41static char sccsid[] = "@(#)hash.c      8.1 (Berkeley) 6/6/93";
    4242#else
    4343static const char rcsid[] =
    4444  "$FreeBSD: src/usr.bin/make/hash.c,v 1.9 1999/09/11 13:08:01 hoek Exp $";
    4545#endif
     46#define KLIBFILEDEF rcsid
    4647#endif /* not lint */
    4748
    4849/* hash.c --
    4950 *
    50  *      This module contains routines to manipulate a hash table.
    51  *      See hash.h for a definition of the structure of the hash
    52  *      table.  Hash tables grow automatically as the amount of
    53  *      information increases.
     51 *      This module contains routines to manipulate a hash table.
     52 *      See hash.h for a definition of the structure of the hash
     53 *      table.  Hash tables grow automatically as the amount of
     54 *      information increases.
    5455 */
    5556#include "sprite.h"
     
    7677 * Hash_InitTable --
    7778 *
    78  *      This routine just sets up the hash table.
    79  *
    80  * Results:
    81  *      None.
    82  *
    83  * Side Effects:
    84  *      Memory is allocated for the initial bucket area.
     79 *      This routine just sets up the hash table.
     80 *
     81 * Results:
     82 *      None.
     83 *
     84 * Side Effects:
     85 *      Memory is allocated for the initial bucket area.
    8586 *
    8687 *---------------------------------------------------------
     
    8990void
    9091Hash_InitTable(t, numBuckets)
    91         register Hash_Table *t; /* Structure to use to hold table. */
    92         int numBuckets;         /* How many buckets to create for starters.
    93                                 * This number is rounded up to a power of
    94                                 * two.   If <= 0, a reasonable default is
    95                                 * chosen. The table will grow in size later
    96                                 * as needed. */
    97 {
    98         register int i;
    99         register struct Hash_Entry **hp;
    100 
    101         /*
    102         * Round up the size to a power of two.
    103         */
    104         if (numBuckets <= 0)
    105                 i = 16;
    106         else {
    107                 for (i = 2; i < numBuckets; i <<= 1)
    108                         continue;
    109         }
    110         t->numEntries = 0;
    111         t->size = i;
    112         t->mask = i - 1;
    113         t->bucketPtr = hp = (struct Hash_Entry **)emalloc(sizeof(*hp) * i);
    114         while (--i >= 0)
    115                 *hp++ = NULL;
     92        register Hash_Table *t; /* Structure to use to hold table. */
     93        int numBuckets;         /* How many buckets to create for starters.
     94                                * This number is rounded up to a power of
     95                                * two.   If <= 0, a reasonable default is
     96                                * chosen. The table will grow in size later
     97                                * as needed. */
     98{
     99        register int i;
     100        register struct Hash_Entry **hp;
     101
     102        /*
     103        * Round up the size to a power of two.
     104        */
     105        if (numBuckets <= 0)
     106                i = 16;
     107        else {
     108                for (i = 2; i < numBuckets; i <<= 1)
     109                        continue;
     110        }
     111        t->numEntries = 0;
     112        t->size = i;
     113        t->mask = i - 1;
     114        t->bucketPtr = hp = (struct Hash_Entry **)emalloc(sizeof(*hp) * i);
     115        while (--i >= 0)
     116                *hp++ = NULL;
    116117}
    117118
     
    121122 * Hash_DeleteTable --
    122123 *
    123  *      This routine removes everything from a hash table
    124  *      and frees up the memory space it occupied (except for
    125  *      the space in the Hash_Table structure).
    126  *
    127  * Results:
    128  *      None.
    129  *
    130  * Side Effects:
    131  *      Lots of memory is freed up.
     124 *      This routine removes everything from a hash table
     125 *      and frees up the memory space it occupied (except for
     126 *      the space in the Hash_Table structure).
     127 *
     128 * Results:
     129 *      None.
     130 *
     131 * Side Effects:
     132 *      Lots of memory is freed up.
    132133 *
    133134 *---------------------------------------------------------
     
    136137void
    137138Hash_DeleteTable(t)
    138         Hash_Table *t;
    139 {
    140         register struct Hash_Entry **hp, *h, *nexth = NULL;
    141         register int i;
    142 
    143         for (hp = t->bucketPtr, i = t->size; --i >= 0;) {
    144                 for (h = *hp++; h != NULL; h = nexth) {
    145                         nexth = h->next;
    146                         efree((char *)h);
    147                 }
    148         }
    149         efree((char *)t->bucketPtr);
    150 
    151         /*
    152         * Set up the hash table to cause memory faults on any future access
    153         * attempts until re-initialization.
    154         */
    155         t->bucketPtr = NULL;
     139        Hash_Table *t;
     140{
     141        register struct Hash_Entry **hp, *h, *nexth = NULL;
     142        register int i;
     143
     144        for (hp = t->bucketPtr, i = t->size; --i >= 0;) {
     145                for (h = *hp++; h != NULL; h = nexth) {
     146                        nexth = h->next;
     147                        efree((char *)h);
     148                }
     149        }
     150        efree((char *)t->bucketPtr);
     151
     152        /*
     153        * Set up the hash table to cause memory faults on any future access
     154        * attempts until re-initialization.
     155        */
     156        t->bucketPtr = NULL;
    156157}
    157158
     
    161162 * Hash_FindEntry --
    162163 *
    163  *      Searches a hash table for an entry corresponding to key.
    164  *
    165  * Results:
    166  *      The return value is a pointer to the entry for key,
    167  *      if key was present in the table.  If key was not
    168  *      present, NULL is returned.
    169  *
    170  * Side Effects:
    171  *      None.
     164 *      Searches a hash table for an entry corresponding to key.
     165 *
     166 * Results:
     167 *      The return value is a pointer to the entry for key,
     168 *      if key was present in the table.  If key was not
     169 *      present, NULL is returned.
     170 *
     171 * Side Effects:
     172 *      None.
    172173 *
    173174 *---------------------------------------------------------
     
    176177Hash_Entry *
    177178Hash_FindEntry(t, key)
    178         Hash_Table *t;          /* Hash table to search. */
    179         char *key;              /* A hash key. */
    180 {
    181         register Hash_Entry *e;
    182         register unsigned h;
    183         register char *p;
    184 
    185         for (h = 0, p = key; *p;)
    186                 h = (h << 5) - h + *p++;
    187         p = key;
    188         for (e = t->bucketPtr[h & t->mask]; e != NULL; e = e->next)
    189                 if (e->namehash == h && strcmp(e->name, p) == 0)
    190                         return (e);
    191         return (NULL);
     179        Hash_Table *t;          /* Hash table to search. */
     180        char *key;              /* A hash key. */
     181{
     182        register Hash_Entry *e;
     183        register unsigned h;
     184        register char *p;
     185
     186        for (h = 0, p = key; *p;)
     187                h = (h << 5) - h + *p++;
     188        p = key;
     189        for (e = t->bucketPtr[h & t->mask]; e != NULL; e = e->next)
     190                if (e->namehash == h && strcmp(e->name, p) == 0)
     191                        return (e);
     192        return (NULL);
    192193}
    193194
     
    197198 * Hash_CreateEntry --
    198199 *
    199  *      Searches a hash table for an entry corresponding to
    200  *      key.  If no entry is found, then one is created.
    201  *
    202  * Results:
    203  *      The return value is a pointer to the entry.  If *newPtr
    204  *      isn't NULL, then *newPtr is filled in with TRUE if a
    205  *      new entry was created, and FALSE if an entry already existed
    206  *      with the given key.
    207  *
    208  * Side Effects:
    209  *      Memory may be allocated, and the hash buckets may be modified.
     200 *      Searches a hash table for an entry corresponding to
     201 *      key.  If no entry is found, then one is created.
     202 *
     203 * Results:
     204 *      The return value is a pointer to the entry.  If *newPtr
     205 *      isn't NULL, then *newPtr is filled in with TRUE if a
     206 *      new entry was created, and FALSE if an entry already existed
     207 *      with the given key.
     208 *
     209 * Side Effects:
     210 *      Memory may be allocated, and the hash buckets may be modified.
    210211 *---------------------------------------------------------
    211212 */
     
    213214Hash_Entry *
    214215Hash_CreateEntry(t, key, newPtr)
    215         register Hash_Table *t; /* Hash table to search. */
    216         char *key;              /* A hash key. */
    217         Boolean *newPtr;        /* Filled in with TRUE if new entry created,
    218                                 * FALSE otherwise. */
    219 {
    220         register Hash_Entry *e;
    221         register unsigned h;
    222         register char *p;
    223         int keylen;
    224         struct Hash_Entry **hp;
    225 
    226         /*
    227         * Hash the key.  As a side effect, save the length (strlen) of the
    228         * key in case we need to create the entry.
    229         */
    230         for (h = 0, p = key; *p;)
    231                 h = (h << 5) - h + *p++;
    232         keylen = p - key;
    233         p = key;
    234         for (e = t->bucketPtr[h & t->mask]; e != NULL; e = e->next) {
    235                 if (e->namehash == h && strcmp(e->name, p) == 0) {
    236                         if (newPtr != NULL)
    237                                 *newPtr = FALSE;
    238                         return (e);
    239                 }
    240         }
    241 
    242         /*
    243         * The desired entry isn't there.  Before allocating a new entry,
    244         * expand the table if necessary (and this changes the resulting
    245         * bucket chain).
    246         */
    247         if (t->numEntries >= rebuildLimit * t->size)
    248                 RebuildTable(t);
    249         e = (Hash_Entry *) emalloc(sizeof(*e) + keylen);
    250         hp = &t->bucketPtr[h & t->mask];
    251         e->next = *hp;
    252         *hp = e;
    253         e->clientData = NULL;
    254         e->namehash = h;
    255         (void) strcpy(e->name, p);
    256         t->numEntries++;
    257 
    258         if (newPtr != NULL)
    259                 *newPtr = TRUE;
    260         return (e);
     216        register Hash_Table *t; /* Hash table to search. */
     217        char *key;              /* A hash key. */
     218        Boolean *newPtr;        /* Filled in with TRUE if new entry created,
     219                                * FALSE otherwise. */
     220{
     221        register Hash_Entry *e;
     222        register unsigned h;
     223        register char *p;
     224        int keylen;
     225        struct Hash_Entry **hp;
     226
     227        /*
     228        * Hash the key.  As a side effect, save the length (strlen) of the
     229        * key in case we need to create the entry.
     230        */
     231        for (h = 0, p = key; *p;)
     232                h = (h << 5) - h + *p++;
     233        keylen = p - key;
     234        p = key;
     235        for (e = t->bucketPtr[h & t->mask]; e != NULL; e = e->next) {
     236                if (e->namehash == h && strcmp(e->name, p) == 0) {
     237                        if (newPtr != NULL)
     238                                *newPtr = FALSE;
     239                        return (e);
     240                }
     241        }
     242
     243        /*
     244        * The desired entry isn't there.  Before allocating a new entry,
     245        * expand the table if necessary (and this changes the resulting
     246        * bucket chain).
     247        */
     248        if (t->numEntries >= rebuildLimit * t->size)
     249                RebuildTable(t);
     250        e = (Hash_Entry *) emalloc(sizeof(*e) + keylen);
     251        hp = &t->bucketPtr[h & t->mask];
     252        e->next = *hp;
     253        *hp = e;
     254        e->clientData = NULL;
     255        e->namehash = h;
     256        (void) strcpy(e->name, p);
     257        t->numEntries++;
     258
     259        if (newPtr != NULL)
     260                *newPtr = TRUE;
     261        return (e);
    261262}
    262263
     
    266267 * Hash_DeleteEntry --
    267268 *
    268  *      Delete the given hash table entry and efree memory associated with
    269  *      it.
    270  *
    271  * Results:
    272  *      None.
    273  *
    274  * Side Effects:
    275  *      Hash chain that entry lives in is modified and memory is freed.
     269 *      Delete the given hash table entry and efree memory associated with
     270 *      it.
     271 *
     272 * Results:
     273 *      None.
     274 *
     275 * Side Effects:
     276 *      Hash chain that entry lives in is modified and memory is freed.
    276277 *
    277278 *---------------------------------------------------------
     
    280281void
    281282Hash_DeleteEntry(t, e)
    282         Hash_Table *t;
    283         Hash_Entry *e;
    284 {
    285         register Hash_Entry **hp, *p;
    286 
    287         if (e == NULL)
    288                 return;
    289         for (hp = &t->bucketPtr[e->namehash & t->mask];
    290              (p = *hp) != NULL; hp = &p->next) {
    291                 if (p == e) {
    292                         *hp = p->next;
    293                         efree((char *)p);
    294                         t->numEntries--;
    295                         return;
    296                 }
    297         }
    298         (void) write(2, "bad call to Hash_DeleteEntry\n", 29);
    299         abort();
     283        Hash_Table *t;
     284        Hash_Entry *e;
     285{
     286        register Hash_Entry **hp, *p;
     287
     288        if (e == NULL)
     289                return;
     290        for (hp = &t->bucketPtr[e->namehash & t->mask];
     291             (p = *hp) != NULL; hp = &p->next) {
     292                if (p == e) {
     293                        *hp = p->next;
     294                        efree((char *)p);
     295                        t->numEntries--;
     296                        return;
     297                }
     298        }
     299        (void) write(STDERR_FILENO, "bad call to Hash_DeleteEntry\n", 29);
     300        abort();
    300301}
    301302
     
    304305 *
    305306 * Hash_EnumFirst --
    306  *      This procedure sets things up for a complete search
    307  *      of all entries recorded in the hash table.
    308  *
    309  * Results:
    310  *      The return value is the address of the first entry in
    311  *      the hash table, or NULL if the table is empty.
    312  *
    313  * Side Effects:
    314  *      The information in searchPtr is initialized so that successive
    315  *      calls to Hash_Next will return successive HashEntry's
    316  *      from the table.
     307 *      This procedure sets things up for a complete search
     308 *      of all entries recorded in the hash table.
     309 *
     310 * Results:
     311 *      The return value is the address of the first entry in
     312 *      the hash table, or NULL if the table is empty.
     313 *
     314 * Side Effects:
     315 *      The information in searchPtr is initialized so that successive
     316 *      calls to Hash_Next will return successive HashEntry's
     317 *      from the table.
    317318 *
    318319 *---------------------------------------------------------
     
    321322Hash_Entry *
    322323Hash_EnumFirst(t, searchPtr)
    323         Hash_Table *t;                  /* Table to be searched. */
    324         register Hash_Search *searchPtr;/* Area in which to keep state
    325                                         * about search.*/
    326 {
    327         searchPtr->tablePtr = t;
    328         searchPtr->nextIndex = 0;
    329         searchPtr->hashEntryPtr = NULL;
    330         return Hash_EnumNext(searchPtr);
     324        Hash_Table *t;                  /* Table to be searched. */
     325        register Hash_Search *searchPtr;/* Area in which to keep state
     326                                        * about search.*/
     327{
     328        searchPtr->tablePtr = t;
     329        searchPtr->nextIndex = 0;
     330        searchPtr->hashEntryPtr = NULL;
     331        return Hash_EnumNext(searchPtr);
    331332}
    332333
     
    351352Hash_Entry *
    352353Hash_EnumNext(searchPtr)
    353         register Hash_Search *searchPtr; /* Area used to keep state about
    354                                             search. */
    355 {
    356         register Hash_Entry *e;
    357         Hash_Table *t = searchPtr->tablePtr;
    358 
    359         /*
    360         * The hashEntryPtr field points to the most recently returned
    361         * entry, or is nil if we are starting up.  If not nil, we have
    362         * to start at the next one in the chain.
    363         */
    364         e = searchPtr->hashEntryPtr;
    365         if (e != NULL)
    366                 e = e->next;
    367         /*
    368         * If the chain ran out, or if we are starting up, we need to
    369         * find the next nonempty chain.
    370         */
    371         while (e == NULL) {
    372                 if (searchPtr->nextIndex >= t->size)
    373                         return (NULL);
    374                 e = t->bucketPtr[searchPtr->nextIndex++];
    375         }
    376         searchPtr->hashEntryPtr = e;
    377         return (e);
     354        register Hash_Search *searchPtr; /* Area used to keep state about
     355                                            search. */
     356{
     357        register Hash_Entry *e;
     358        Hash_Table *t = searchPtr->tablePtr;
     359
     360        /*
     361        * The hashEntryPtr field points to the most recently returned
     362        * entry, or is nil if we are starting up.  If not nil, we have
     363        * to start at the next one in the chain.
     364        */
     365        e = searchPtr->hashEntryPtr;
     366        if (e != NULL)
     367                e = e->next;
     368        /*
     369        * If the chain ran out, or if we are starting up, we need to
     370        * find the next nonempty chain.
     371        */
     372        while (e == NULL) {
     373                if (searchPtr->nextIndex >= t->size)
     374                        return (NULL);
     375                e = t->bucketPtr[searchPtr->nextIndex++];
     376        }
     377        searchPtr->hashEntryPtr = e;
     378        return (e);
    378379}
    379380
     
    382383 *
    383384 * RebuildTable --
    384  *      This local routine makes a new hash table that
    385  *      is larger than the old one.
    386  *
    387  * Results:
    388  *      None.
    389  *
    390  * Side Effects:
    391  *      The entire hash table is moved, so any bucket numbers
    392  *      from the old table are invalid.
     385 *      This local routine makes a new hash table that
     386 *      is larger than the old one.
     387 *
     388 * Results:
     389 *      None.
     390 *
     391 * Side Effects:
     392 *      The entire hash table is moved, so any bucket numbers
     393 *      from the old table are invalid.
    393394 *
    394395 *---------------------------------------------------------
     
    397398static void
    398399RebuildTable(t)
    399         register Hash_Table *t;
    400 {
    401         register Hash_Entry *e, *next = NULL, **hp, **xp;
    402         register int i, mask;
     400        register Hash_Table *t;
     401{
     402        register Hash_Entry *e, *next = NULL, **hp, **xp;
     403        register int i, mask;
    403404        register Hash_Entry **oldhp;
    404         int oldsize;
    405 
    406         oldhp = t->bucketPtr;
    407         oldsize = i = t->size;
    408         i <<= 1;
    409         t->size = i;
    410         t->mask = mask = i - 1;
    411         t->bucketPtr = hp = (struct Hash_Entry **) emalloc(sizeof(*hp) * i);
    412         while (--i >= 0)
    413                 *hp++ = NULL;
    414         for (hp = oldhp, i = oldsize; --i >= 0;) {
    415                 for (e = *hp++; e != NULL; e = next) {
    416                         next = e->next;
    417                         xp = &t->bucketPtr[e->namehash & mask];
    418                         e->next = *xp;
    419                         *xp = e;
    420                 }
    421         }
    422         efree((char *)oldhp);
    423 }
     405        int oldsize;
     406
     407        oldhp = t->bucketPtr;
     408        oldsize = i = t->size;
     409        i <<= 1;
     410        t->size = i;
     411        t->mask = mask = i - 1;
     412        t->bucketPtr = hp = (struct Hash_Entry **) emalloc(sizeof(*hp) * i);
     413        while (--i >= 0)
     414                *hp++ = NULL;
     415        for (hp = oldhp, i = oldsize; --i >= 0;) {
     416                for (e = *hp++; e != NULL; e = next) {
     417                        next = e->next;
     418                        xp = &t->bucketPtr[e->namehash & mask];
     419                        e->next = *xp;
     420                        *xp = e;
     421                }
     422        }
     423        efree((char *)oldhp);
     424}
  • trunk/src/kmk/helpers.c

    r35 r51  
    1818#include <sys/stat.h>
    1919#include <stdarg.h>
     20#include <stdio.h>
     21#include <err.h>
     22
    2023#ifdef OS2
    2124    #define INCL_BASE
    2225    #include <os2.h>
    2326#endif
    24 #include <stdio.h>
    25 #include <err.h>
    2627
    2728
     
    3435char *realpath(const char *pszFileName, char *pszResolvedName)
    3536{
    36     #if 0 //def USE_KLIB //@todo
     37    #ifdef USE_KLIB
    3738    if (kPathCanonifyEx(pszFileName, NULL, '/', '/', pszResolvedName, KFILE_LENGTH))
    3839        if (kPathExist(pszFileName))
     
    5152
    5253#ifdef OS2
    53 void    err(int flags, const char *pszFormat, ...)
     54void    err(int flags, const char *pszFormat, ...)
    5455{
    5556    va_list args;
     
    6061}
    6162
    62 void    errx(int flags, const char *pszFormat, ...)
     63void    errx(int flags, const char *pszFormat, ...)
    6364{
    6465    va_list args;
     
    6970}
    7071
    71 void    warnx(const char *pszFormat, ...)
     72void    warnx(const char *pszFormat, ...)
    7273{
    7374    va_list args;
     
    7879}
    7980
    80 void    warn(const char *pszFormat, ...)
     81void    warn(const char *pszFormat, ...)
    8182{
    8283    va_list args;
  • trunk/src/kmk/job.c

    r46 r51  
    1818 * 3. All advertising materials mentioning features or use of this software
    1919 *    must display the following acknowledgement:
    20  *      This product includes software developed by the University of
    21  *      California, Berkeley and its contributors.
     20 *      This product includes software developed by the University of
     21 *      California, Berkeley and its contributors.
    2222 * 4. Neither the name of the University nor the names of its contributors
    2323 *    may be used to endorse or promote products derived from this software
     
    3939#ifndef lint
    4040#if 0
    41 static char sccsid[] = "@(#)job.c       8.2 (Berkeley) 3/19/94";
     41static char sccsid[] = "@(#)job.c       8.2 (Berkeley) 3/19/94";
    4242#else
    4343static const char rcsid[] =
    4444  "$FreeBSD: src/usr.bin/make/job.c,v 1.17.2.2 2001/02/13 03:13:57 will Exp $";
    4545#endif
     46#define KLIBFILEDEF rcsid
    4647#endif /* not lint */
    4748
     
    5657/*-
    5758 * job.c --
    58  *      handle the creation etc. of our child processes.
     59 *      handle the creation etc. of our child processes.
    5960 *
    6061 * Interface:
    61  *      Job_Make                Start the creation of the given target.
    62  *
    63  *      Job_CatchChildren       Check for and handle the termination of any
    64  *                              children. This must be called reasonably
    65  *                              frequently to keep the whole make going at
    66  *                              a decent clip, since job table entries aren't
    67  *                              removed until their process is caught this way.
    68  *                              Its single argument is TRUE if the function
    69  *                              should block waiting for a child to terminate.
    70  *
    71  *      Job_CatchOutput         Print any output our children have produced.
    72  *                              Should also be called fairly frequently to
    73  *                              keep the user informed of what's going on.
    74  *                              If no output is waiting, it will block for
    75  *                              a time given by the SEL_* constants, below,
    76  *                              or until output is ready.
    77  *
    78  *      Job_Init                Called to intialize this module. in addition,
    79  *                              any commands attached to the .BEGIN target
    80  *                              are executed before this function returns.
    81  *                              Hence, the makefile must have been parsed
    82  *                              before this function is called.
    83  *
    84  *      Job_Full                Return TRUE if the job table is filled.
    85  *
    86  *      Job_Empty               Return TRUE if the job table is completely
    87  *                              empty.
    88  *
    89  *      Job_ParseShell          Given the line following a .SHELL target, parse
    90  *                              the line as a shell specification. Returns
    91  *                              FAILURE if the spec was incorrect.
    92  *
    93  *      Job_End                 Perform any final processing which needs doing.
    94  *                              This includes the execution of any commands
    95  *                              which have been/were attached to the .END
    96  *                              target. It should only be called when the
    97  *                              job table is empty.
    98  *
    99  *      Job_AbortAll            Abort all currently running jobs. It doesn't
    100  *                              handle output or do anything for the jobs,
    101  *                              just kills them. It should only be called in
    102  *                              an emergency, as it were.
    103  *
    104  *      Job_CheckCommands       Verify that the commands for a target are
    105  *                              ok. Provide them if necessary and possible.
    106  *
    107  *      Job_Touch               Update a target without really updating it.
    108  *
    109  *      Job_Wait                Wait for all currently-running jobs to finish.
     62 *      Job_Make                Start the creation of the given target.
     63 *
     64 *      Job_CatchChildren       Check for and handle the termination of any
     65 *                              children. This must be called reasonably
     66 *                              frequently to keep the whole make going at
     67 *                              a decent clip, since job table entries aren't
     68 *                              removed until their process is caught this way.
     69 *                              Its single argument is TRUE if the function
     70 *                              should block waiting for a child to terminate.
     71 *
     72 *      Job_CatchOutput         Print any output our children have produced.
     73 *                              Should also be called fairly frequently to
     74 *                              keep the user informed of what's going on.
     75 *                              If no output is waiting, it will block for
     76 *                              a time given by the SEL_* constants, below,
     77 *                              or until output is ready.
     78 *
     79 *      Job_Init                Called to intialize this module. in addition,
     80 *                              any commands attached to the .BEGIN target
     81 *                              are executed before this function returns.
     82 *                              Hence, the makefile must have been parsed
     83 *                              before this function is called.
     84 *
     85 *      Job_Full                Return TRUE if the job table is filled.
     86 *
     87 *      Job_Empty               Return TRUE if the job table is completely
     88 *                              empty.
     89 *
     90 *      Job_ParseShell          Given the line following a .SHELL target, parse
     91 *                              the line as a shell specification. Returns
     92 *                              FAILURE if the spec was incorrect.
     93 *
     94 *      Job_End                 Perform any final processing which needs doing.
     95 *                              This includes the execution of any commands
     96 *                              which have been/were attached to the .END
     97 *                              target. It should only be called when the
     98 *                              job table is empty.
     99 *
     100 *      Job_AbortAll            Abort all currently running jobs. It doesn't
     101 *                              handle output or do anything for the jobs,
     102 *                              just kills them. It should only be called in
     103 *                              an emergency, as it were.
     104 *
     105 *      Job_CheckCommands       Verify that the commands for a target are
     106 *                              ok. Provide them if necessary and possible.
     107 *
     108 *      Job_Touch               Update a target without really updating it.
     109 *
     110 *      Job_Wait                Wait for all currently-running jobs to finish.
    110111 */
    111112
     
    153154 * error handling variables
    154155 */
    155 static int      errors = 0;         /* number of errors reported */
    156 static int      aborting = 0;       /* why is the make aborting? */
    157 #define ABORT_ERROR     1           /* Because of an error */
    158 #define ABORT_INTERRUPT 2           /* Because it was interrupted */
    159 #define ABORT_WAIT      3           /* Waiting for jobs to finish */
     156static int      errors = 0;         /* number of errors reported */
     157static int      aborting = 0;       /* why is the make aborting? */
     158#define ABORT_ERROR     1           /* Because of an error */
     159#define ABORT_INTERRUPT 2           /* Because it was interrupted */
     160#define ABORT_WAIT      3           /* Waiting for jobs to finish */
    160161
    161162/*
     
    170171 * all the time.
    171172 */
    172 static GNode      *postCommands;    /* node containing commands to execute when
    173                                      * everything else is done */
    174 static int        numCommands;      /* The number of commands actually printed
    175                                      * for a target. Should this number be
    176                                      * 0, no shell will be executed. */
     173static GNode      *postCommands;    /* node containing commands to execute when
     174                                     * everything else is done */
     175static int        numCommands;      /* The number of commands actually printed
     176                                     * for a target. Should this number be
     177                                     * 0, no shell will be executed. */
    177178
    178179/*
    179180 * Return values from JobStart.
    180181 */
    181 #define JOB_RUNNING     0       /* Job is running */
    182 #define JOB_ERROR       1       /* Error in starting the job */
    183 #define JOB_FINISHED    2       /* The job is already finished */
    184 #define JOB_STOPPED     3       /* The job is stopped */
     182#define JOB_RUNNING     0       /* Job is running */
     183#define JOB_ERROR       1       /* Error in starting the job */
     184#define JOB_FINISHED    2       /* The job is already finished */
     185#define JOB_STOPPED     3       /* The job is stopped */
    185186
    186187/*
     
    229230}
    230231};
    231 static Shell    *commandShell = &shells[DEFSHELL];/* this is the shell to
    232                                                    * which we pass all
    233                                                    * commands in the Makefile.
    234                                                    * It is set by the
    235                                                    * Job_ParseShell function */
    236 static char     *shellPath = NULL,                /* full pathname of
    237                                                    * executable image */
    238                 *shellName;                       /* last component of shell */
     232static Shell    *commandShell = &shells[DEFSHELL];/* this is the shell to
     233                                                   * which we pass all
     234                                                   * commands in the Makefile.
     235                                                   * It is set by the
     236                                                   * Job_ParseShell function */
     237static char     *shellPath = NULL,                /* full pathname of
     238                                                   * executable image */
     239                *shellName;                       /* last component of shell */
    239240#endif /*!KMK*/
    240241
    241242
    242 static int      maxJobs;        /* The most children we can run at once */
    243 static int      maxLocal;       /* The most local ones we can have */
    244 STATIC int      nJobs;          /* The number of children currently running */
    245 STATIC int      nLocal;         /* The number of local children */
    246 STATIC Lst      jobs;           /* The structures that describe them */
    247 STATIC Boolean  jobFull;        /* Flag to tell when the job table is full. It
    248                                 * is set TRUE when (1) the total number of
    249                                 * running jobs equals the maximum allowed or
    250                                 * (2) a job can only be run locally, but
    251                                 * nLocal equals maxLocal */
     243static int      maxJobs;        /* The most children we can run at once */
     244static int      maxLocal;       /* The most local ones we can have */
     245STATIC int      nJobs;          /* The number of children currently running */
     246STATIC int      nLocal;         /* The number of local children */
     247STATIC Lst      jobs;           /* The structures that describe them */
     248STATIC Boolean  jobFull;        /* Flag to tell when the job table is full. It
     249                                * is set TRUE when (1) the total number of
     250                                * running jobs equals the maximum allowed or
     251                                * (2) a job can only be run locally, but
     252                                * nLocal equals maxLocal */
    252253#ifndef RMT_WILL_WATCH
    253 static fd_set   outputs;        /* Set of descriptors of pipes connected to
    254                                 * the output channels of children */
    255 #endif
    256 
    257 STATIC GNode    *lastNode;      /* The node for which output was most recently
    258                                 * produced. */
    259 STATIC char     *targFmt;       /* Format string to use to head output from a
    260                                 * job when it's not the most-recent job heard
    261                                 * from */
     254static fd_set   outputs;        /* Set of descriptors of pipes connected to
     255                                * the output channels of children */
     256#endif
     257
     258STATIC GNode    *lastNode;      /* The node for which output was most recently
     259                                * produced. */
     260STATIC char     *targFmt;       /* Format string to use to head output from a
     261                                * job when it's not the most-recent job heard
     262                                * from */
    262263
    263264#ifdef REMOTE
    264265# define TARG_FMT  "--- %s at %s ---\n" /* Default format */
    265266# define MESSAGE(fp, gn) \
    266         (void) fprintf(fp, targFmt, gn->name, gn->rem.hname);
     267        (void) fprintf(fp, targFmt, gn->name, gn->rem.hname);
    267268#else
    268269# define TARG_FMT  "--- %s ---\n" /* Default format */
    269270# define MESSAGE(fp, gn) \
    270         (void) fprintf(fp, targFmt, gn->name);
    271 #endif
    272 
     271        (void) fprintf(fp, targFmt, gn->name);
     272#endif
     273
     274#ifdef SIGCONT
    273275/*
    274276 * When JobStart attempts to run a job remotely but can't, and isn't allowed
     
    277279 * when the next job finishes.
    278280 */
    279 STATIC Lst      stoppedJobs;    /* Lst of Job structures describing
    280                                 * jobs that were stopped due to concurrency
    281                                 * limits or migration home */
    282 
     281STATIC Lst      stoppedJobs;    /* Lst of Job structures describing
     282                                * jobs that were stopped due to concurrency
     283                                * limits or migration home */
     284#endif /*SIGCONT*/
    283285
    284286#if defined(USE_PGRP) && defined(SYSV)
    285 # define KILL(pid, sig)         killpg(-(pid), (sig))
     287# define KILL(pid, sig)         killpg(-(pid), (sig))
    286288#else
    287289# if defined(USE_PGRP)
    288 #  define KILL(pid, sig)        killpg((pid), (sig))
     290#  define KILL(pid, sig)        killpg((pid), (sig))
    289291# else
    290 #  define KILL(pid, sig)        kill((pid), (sig))
     292#  define KILL(pid, sig)        kill((pid), (sig))
    291293# endif
    292294#endif
     
    298300 * really ugly, use dramamine sparingly. You have been warned.
    299301 */
    300 #define W_SETMASKED(st, val, fun)                               \
    301         {                                                       \
    302                 int sh = (int) ~0;                              \
    303                 int mask = fun(sh);                             \
    304                                                                 \
    305                 for (sh = 0; ((mask >> sh) & 1) == 0; sh++)     \
    306                         continue;                               \
    307                 *(st) = (*(st) & ~mask) | ((val) << sh);        \
    308         }
     302#define W_SETMASKED(st, val, fun)                               \
     303        {                                                       \
     304                int sh = (int) ~0;                              \
     305                int mask = fun(sh);                             \
     306                                                                \
     307                for (sh = 0; ((mask >> sh) & 1) == 0; sh++)     \
     308                        continue;                               \
     309                *(st) = (*(st) & ~mask) | ((val) << sh);        \
     310        }
    309311
    310312#define W_SETTERMSIG(st, val) W_SETMASKED(st, val, WTERMSIG)
     
    324326# endif
    325327#else
     328#ifdef USE_KLIB
     329static void JobFinish __P((Job *, KPROCRES *));
     330#else
    326331static void JobFinish __P((Job *, int *));
     332#endif
    327333static void JobExec __P((Job *, char **));
    328334#endif
    329 #ifndef KMK
    330335static void JobMakeArgv __P((Job *, char **));
    331 #endif
     336#ifdef SIGCONT
    332337static void JobRestart __P((Job *));
     338#endif
    333339static int JobStart __P((GNode *, int, Job *));
    334340static char *JobOutput __P((Job *, char *, char *, int));
     
    336342static Shell *JobMatchShell __P((char *));
    337343static void JobInterrupt __P((int, int));
     344#ifdef SIGCONT
    338345static void JobRestartJobs __P((void));
     346#endif
    339347
    340348/*-
    341349 *-----------------------------------------------------------------------
    342350 * JobCondPassSig --
    343  *      Pass a signal to a job if the job is remote or if USE_PGRP
    344  *      is defined.
     351 *      Pass a signal to a job if the job is remote or if USE_PGRP
     352 *      is defined.
    345353 *
    346354 * Results:
    347  *      === 0
     355 *      === 0
    348356 *
    349357 * Side Effects:
    350  *      None, except the job may bite it.
     358 *      None, except the job may bite it.
    351359 *
    352360 *-----------------------------------------------------------------------
     
    354362static int
    355363JobCondPassSig(jobp, signop)
    356     ClientData          jobp;       /* Job to biff */
    357     ClientData          signop;     /* Signal to send it */
     364    ClientData          jobp;       /* Job to biff */
     365    ClientData          signop;     /* Signal to send it */
    358366{
    359     Job *job = (Job *) jobp;
    360     int signo = *(int *) signop;
     367    Job *job = (Job *) jobp;
     368    int signo = *(int *) signop;
    361369#ifdef RMT_WANTS_SIGNALS
    362370    if (job->flags & JOB_REMOTE) {
    363         (void) Rmt_Signal(job, signo);
     371        (void) Rmt_Signal(job, signo);
    364372    } else {
    365         KILL(job->pid, signo);
     373        KILL(job->pid, signo);
    366374    }
    367375#else
     
    371379     */
    372380    if (DEBUG(JOB)) {
    373         (void) fprintf(stdout,
    374                        "JobCondPassSig passing signal %d to child %d.\n",
    375                        signo, job->pid);
    376         (void) fflush(stdout);
    377     }
     381        (void) fprintf(stdout,
     382                       "JobCondPassSig passing signal %d to child %d.\n",
     383                       signo, job->pid);
     384        (void) fflush(stdout);
     385    }
     386#if defined(USE_KLIB) && (defined(OS2) || defined(WIN32))
     387    switch (signo)
     388    {
     389        case SIGINT:
     390            kProcKill(job->pid, KPROCKILL_FLAGS_TREE | KPROCKILL_FLAGS_TYPE_INT);
     391            break;
     392        #ifdef SIGKILL
     393        case SIGKILL:
     394        #endif
     395        case SIGTERM:
     396            kProcKill(job->pid, KPROCKILL_FLAGS_TREE | KPROCKILL_FLAGS_TYPE_KILL);
     397            break;
     398    /* default: ignore signal as we don't really support it */
     399    }
     400#else
    378401    KILL(job->pid, signo);
     402#endif
    379403#endif
    380404    return 0;
     
    384408 *-----------------------------------------------------------------------
    385409 * JobPassSig --
    386  *      Pass a signal on to all remote jobs and to all local jobs if
    387  *      USE_PGRP is defined, then die ourselves.
     410 *      Pass a signal on to all remote jobs and to all local jobs if
     411 *      USE_PGRP is defined, then die ourselves.
    388412 *
    389413 * Results:
    390  *      None.
     414 *      None.
    391415 *
    392416 * Side Effects:
    393  *      We die by the same signal.
     417 *      We die by the same signal.
    394418 *
    395419 *-----------------------------------------------------------------------
     
    397421static void
    398422JobPassSig(signo)
    399     int     signo;      /* The signal number we've received */
     423    int     signo;      /* The signal number we've received */
    400424{
    401     sigset_t nmask, omask;
    402     struct sigaction act;
     425#if defined(USE_KLIB) && (defined(OS2) || defined(WIN32))
    403426
    404427    if (DEBUG(JOB)) {
    405         (void) fprintf(stdout, "JobPassSig(%d) called.\n", signo);
    406         (void) fflush(stdout);
     428        fprintf(stdout, "JobPassSig(%d) called.\n", signo);
     429        fflush(stdout);
    407430    }
    408431    Lst_ForEach(jobs, JobCondPassSig, (ClientData) &signo);
     
    414437     */
    415438    if (signo == SIGINT) {
    416         JobInterrupt(TRUE, signo);
    417     } else if ((signo == SIGHUP) || (signo == SIGTERM) || (signo == SIGQUIT)) {
    418         JobInterrupt(FALSE, signo);
    419     }
    420 
     439        JobInterrupt(TRUE, signo);
     440    } else if (signo == SIGTERM) {
     441        JobInterrupt(FALSE, signo);
     442    }
     443
     444
     445    if (DEBUG(JOB)) {
     446        fprintf(stdout,
     447                "JobPassSig passing signal to self, mask = %x.\n",
     448                ~0 & ~(1 << (signo-1)));
     449        fflush(stdout);
     450    }
     451    signal(signo, SIG_DFL);
     452    raise(signo);
     453
     454#ifdef SIGCONT
     455    signo = SIGCONT;
     456    Lst_ForEach(jobs, JobCondPassSig, (ClientData) &signo);
     457#endif
     458
     459
     460#else /* Not KLIB + OS2/Win32 */
     461    sigset_t nmask, omask;
     462    struct sigaction act;
     463
     464
     465    if (DEBUG(JOB)) {
     466        (void) fprintf(stdout, "JobPassSig(%d) called.\n", signo);
     467        (void) fflush(stdout);
     468    }
     469    Lst_ForEach(jobs, JobCondPassSig, (ClientData) &signo);
     470
     471    /*
     472     * Deal with proper cleanup based on the signal received. We only run
     473     * the .INTERRUPT target if the signal was in fact an interrupt. The other
     474     * three termination signals are more of a "get out *now*" command.
     475     */
     476    if (signo == SIGINT) {
     477        JobInterrupt(TRUE, signo);
     478    } else if ( 0
     479#ifdef SIGHUP  /* not all systems supports this signal */
     480               || (signo == SIGHUP)
     481#endif
     482               || (signo == SIGTERM)
     483#ifdef SIGQUIT /* not all systems supports this signal */
     484               || (signo == SIGQUIT)
     485#endif
     486               ) {
     487        JobInterrupt(FALSE, signo);
     488    }
     489
     490#ifdef SIGQUIT /* not all systems supports this signal */
    421491    /*
    422492     * Leave gracefully if SIGQUIT, rather than core dumping.
    423493     */
    424494    if (signo == SIGQUIT) {
    425         signo = SIGINT;
    426     }
    427 
     495        signo = SIGINT;
     496    }
     497#endif
     498
     499#if !defined(USE_KLIB) || !(defined(OS2) || defined(WIN32))
    428500    /*
    429501     * Send ourselves the signal now we've given the message to everyone else.
     
    439511    act.sa_flags = 0;
    440512    sigaction(signo, &act, NULL);
     513#endif
    441514
    442515    if (DEBUG(JOB)) {
    443         (void) fprintf(stdout,
    444                        "JobPassSig passing signal to self, mask = %x.\n",
    445                        ~0 & ~(1 << (signo-1)));
    446         (void) fflush(stdout);
     516        (void) fprintf(stdout,
     517                       "JobPassSig passing signal to self, mask = %x.\n",
     518                       ~0 & ~(1 << (signo-1)));
     519        (void) fflush(stdout);
    447520    }
    448521    (void) signal(signo, SIG_DFL);
     
    453526    Lst_ForEach(jobs, JobCondPassSig, (ClientData) &signo);
    454527
     528#if !defined(USE_KLIB) || !(defined(OS2) || defined(WIN32))
    455529    (void) sigprocmask(SIG_SETMASK, &omask, NULL);
    456530    sigprocmask(SIG_SETMASK, &omask, NULL);
    457531    act.sa_handler = JobPassSig;
    458532    sigaction(signo, &act, NULL);
     533#endif
     534#endif /* KLIB + OS2/Win32 */
    459535}
    460536
     
    462538 *-----------------------------------------------------------------------
    463539 * JobCmpPid  --
    464  *      Compare the pid of the job with the given pid and return 0 if they
    465  *      are equal. This function is called from Job_CatchChildren via
    466  *      Lst_Find to find the job descriptor of the finished job.
     540 *      Compare the pid of the job with the given pid and return 0 if they
     541 *      are equal. This function is called from Job_CatchChildren via
     542 *      Lst_Find to find the job descriptor of the finished job.
    467543 *
    468544 * Results:
    469  *      0 if the pid's match
     545 *      0 if the pid's match
    470546 *
    471547 * Side Effects:
    472  *      None
     548 *      None
    473549 *-----------------------------------------------------------------------
    474550 */
    475551static int
    476552JobCmpPid(job, pid)
    477     ClientData        job;      /* job to examine */
    478     ClientData        pid;      /* process id desired */
     553    ClientData        job;      /* job to examine */
     554    ClientData        pid;      /* process id desired */
    479555{
    480556    return *(int *) pid - ((Job *) job)->pid;
     
    485561 *-----------------------------------------------------------------------
    486562 * JobCmpRmtID  --
    487  *      Compare the rmtID of the job with the given rmtID and return 0 if they
    488  *      are equal.
     563 *      Compare the rmtID of the job with the given rmtID and return 0 if they
     564 *      are equal.
    489565 *
    490566 * Results:
    491  *      0 if the rmtID's match
     567 *      0 if the rmtID's match
    492568 *
    493569 * Side Effects:
    494  *      None.
     570 *      None.
    495571 *-----------------------------------------------------------------------
    496572 */
    497573static int
    498574JobCmpRmtID(job, rmtID)
    499     ClientData      job;        /* job to examine */
    500     ClientData      rmtID;      /* remote id desired */
     575    ClientData      job;        /* job to examine */
     576    ClientData      rmtID;      /* remote id desired */
    501577{
    502578    return(*(int *) rmtID - *(int *) job->rmtID);
     
    507583 *-----------------------------------------------------------------------
    508584 * JobPrintCommand  --
    509  *      Put out another command for the given job. If the command starts
    510  *      with an @ or a - we process it specially. In the former case,
    511  *      so long as the -s and -n flags weren't given to make, we stick
    512  *      a shell-specific echoOff command in the script. In the latter,
    513  *      we ignore errors for the entire job, unless the shell has error
    514  *      control.
    515  *      If the command is just "..." we take all future commands for this
    516  *      job to be commands to be executed once the entire graph has been
    517  *      made and return non-zero to signal that the end of the commands
    518  *      was reached. These commands are later attached to the postCommands
    519  *      node and executed by Job_End when all things are done.
    520  *      This function is called from JobStart via Lst_ForEach.
     585 *      Put out another command for the given job. If the command starts
     586 *      with an @ or a - we process it specially. In the former case,
     587 *      so long as the -s and -n flags weren't given to make, we stick
     588 *      a shell-specific echoOff command in the script. In the latter,
     589 *      we ignore errors for the entire job, unless the shell has error
     590 *      control.
     591 *      If the command is just "..." we take all future commands for this
     592 *      job to be commands to be executed once the entire graph has been
     593 *      made and return non-zero to signal that the end of the commands
     594 *      was reached. These commands are later attached to the postCommands
     595 *      node and executed by Job_End when all things are done.
     596 *      This function is called from JobStart via Lst_ForEach.
    521597 *
    522598 * Results:
    523  *      Always 0, unless the command was "..."
     599 *      Always 0, unless the command was "..."
    524600 *
    525601 * Side Effects:
    526  *      If the command begins with a '-' and the shell has no error control,
    527  *      the JOB_IGNERR flag is set in the job descriptor.
    528  *      If the command is "..." and we're not ignoring such things,
    529  *      tailCmds is set to the successor node of the cmd.
    530  *      numCommands is incremented if the command is actually printed.
     602 *      If the command begins with a '-' and the shell has no error control,
     603 *      the JOB_IGNERR flag is set in the job descriptor.
     604 *      If the command is "..." and we're not ignoring such things,
     605 *      tailCmds is set to the successor node of the cmd.
     606 *      numCommands is incremented if the command is actually printed.
    531607 *-----------------------------------------------------------------------
    532608 */
    533609static int
    534610JobPrintCommand(cmdp, jobp)
    535     ClientData    cmdp;             /* command string to print */
    536     ClientData    jobp;             /* job for which to print it */
     611    ClientData    cmdp;             /* command string to print */
     612    ClientData    jobp;             /* job for which to print it */
    537613{
    538     Boolean       noSpecials;       /* true if we shouldn't worry about
    539                                      * inserting special commands into
    540                                      * the input stream. */
     614    Boolean       noSpecials;       /* true if we shouldn't worry about
     615                                     * inserting special commands into
     616                                     * the input stream. */
    541617    Boolean       shutUp = FALSE;   /* true if we put a no echo command
    542                                      * into the command file */
    543     Boolean       errOff = FALSE;   /* true if we turned error checking
    544                                      * off before printing the command
    545                                      * and need to turn it back on */
    546     char          *cmdTemplate;     /* Template to use when printing the
    547                                      * command */
    548     char          *cmdStart;        /* Start of expanded command */
    549     LstNode       cmdNode;          /* Node for replacing the command */
    550     char          *cmd = (char *) cmdp;
     618                                     * into the command file */
     619    Boolean       errOff = FALSE;   /* true if we turned error checking
     620                                     * off before printing the command
     621                                     * and need to turn it back on */
     622    char          *cmdTemplate;     /* Template to use when printing the
     623                                     * command */
     624    char          *cmdStart;        /* Start of expanded command */
     625    LstNode       cmdNode;          /* Node for replacing the command */
     626    char          *cmd = (char *) cmdp;
    551627    Job           *job = (Job *) jobp;
    552628
     
    554630
    555631    if (strcmp(cmd, "...") == 0) {
    556         job->node->type |= OP_SAVE_CMDS;
    557         if ((job->flags & JOB_IGNDOTS) == 0) {
    558             job->tailCmds = Lst_Succ(Lst_Member(job->node->commands,
    559                                                 (ClientData)cmd));
    560             return 1;
    561         }
    562         return 0;
    563     }
    564 
    565 #define DBPRINTF(fmt, arg) if (DEBUG(JOB)) {    \
    566         (void) fprintf(stdout, fmt, arg);       \
    567         (void) fflush(stdout);                  \
    568     }                                           \
    569    (void) fprintf(job->cmdFILE, fmt, arg);      \
     632        job->node->type |= OP_SAVE_CMDS;
     633        if ((job->flags & JOB_IGNDOTS) == 0) {
     634            job->tailCmds = Lst_Succ(Lst_Member(job->node->commands,
     635                                                (ClientData)cmd));
     636            return 1;
     637        }
     638        return 0;
     639    }
     640
     641#define DBPRINTF(fmt, arg) if (DEBUG(JOB)) {    \
     642        (void) fprintf(stdout, fmt, arg);       \
     643        (void) fflush(stdout);                  \
     644    }                                           \
     645   (void) fprintf(job->cmdFILE, fmt, arg);      \
    570646   (void) fflush(job->cmdFILE);
    571647
     
    586662     */
    587663    while (*cmd == '@' || *cmd == '-') {
    588         if (*cmd == '@') {
    589             shutUp = DEBUG(LOUD) ? FALSE : TRUE;
    590         } else {
    591             errOff = TRUE;
    592         }
    593         cmd++;
     664        if (*cmd == '@') {
     665            shutUp = DEBUG(LOUD) ? FALSE : TRUE;
     666        } else {
     667            errOff = TRUE;
     668        }
     669        cmd++;
    594670    }
    595671
    596672    while (isspace((unsigned char) *cmd))
    597         cmd++;
     673        cmd++;
    598674
    599675    #ifndef KMK
    600676    if (shutUp) {
    601         if (!(job->flags & JOB_SILENT) && !noSpecials &&
    602             commandShell->hasEchoCtl) {
    603                 DBPRINTF("%s\n", commandShell->echoOff);
    604         } else {
    605             shutUp = FALSE;
    606         }
     677        if (!(job->flags & JOB_SILENT) && !noSpecials &&
     678            commandShell->hasEchoCtl) {
     679                DBPRINTF("%s\n", commandShell->echoOff);
     680        } else {
     681            shutUp = FALSE;
     682        }
    607683    }
    608684    #endif
    609685
    610686    if (errOff) {
    611         if ( !(job->flags & JOB_IGNERR) && !noSpecials) {
     687        if ( !(job->flags & JOB_IGNERR) && !noSpecials) {
    612688            #ifdef KMK
    613689            errOff = FALSE;
    614690            #else
    615             if (commandShell->hasErrCtl) {
    616                 /*
    617                 * we don't want the error-control commands showing
    618                 * up either, so we turn off echoing while executing
    619                 * them. We could put another field in the shell
    620                 * structure to tell JobDoOutput to look for this
    621                 * string too, but why make it any more complex than
    622                 * it already is?
    623                 */
    624                 if (!(job->flags & JOB_SILENT) && !shutUp &&
    625                     commandShell->hasEchoCtl) {
    626                         DBPRINTF("%s\n", commandShell->echoOff);
    627                         DBPRINTF("%s\n", commandShell->ignErr);
    628                         DBPRINTF("%s\n", commandShell->echoOn);
    629                 } else {
    630                     DBPRINTF("%s\n", commandShell->ignErr);
    631                 }
    632             } else if (commandShell->ignErr &&
    633                       (*commandShell->ignErr != '\0'))
    634             {
    635                 /*
    636                 * The shell has no error control, so we need to be
    637                 * weird to get it to ignore any errors from the command.
    638                 * If echoing is turned on, we turn it off and use the
    639                 * errCheck template to echo the command. Leave echoing
    640                 * off so the user doesn't see the weirdness we go through
    641                 * to ignore errors. Set cmdTemplate to use the weirdness
    642                 * instead of the simple "%s\n" template.
    643                 */
    644                 if (!(job->flags & JOB_SILENT) && !shutUp &&
    645                     commandShell->hasEchoCtl) {
    646                         DBPRINTF("%s\n", commandShell->echoOff);
    647                         DBPRINTF(commandShell->errCheck, cmd);
    648                         shutUp = TRUE;
    649                 }
    650                 cmdTemplate = commandShell->ignErr;
    651                 /*
    652                 * The error ignoration (hee hee) is already taken care
    653                 * of by the ignErr template, so pretend error checking
    654                 * is still on.
    655                 */
    656                 errOff = FALSE;
    657             } else {
    658                 errOff = FALSE;
    659             }
     691            if (commandShell->hasErrCtl) {
     692                /*
     693                * we don't want the error-control commands showing
     694                * up either, so we turn off echoing while executing
     695                * them. We could put another field in the shell
     696                * structure to tell JobDoOutput to look for this
     697                * string too, but why make it any more complex than
     698                * it already is?
     699                */
     700                if (!(job->flags & JOB_SILENT) && !shutUp &&
     701                    commandShell->hasEchoCtl) {
     702                        DBPRINTF("%s\n", commandShell->echoOff);
     703                        DBPRINTF("%s\n", commandShell->ignErr);
     704                        DBPRINTF("%s\n", commandShell->echoOn);
     705                } else {
     706                    DBPRINTF("%s\n", commandShell->ignErr);
     707                }
     708            } else if (commandShell->ignErr &&
     709                      (*commandShell->ignErr != '\0'))
     710            {
     711                /*
     712                * The shell has no error control, so we need to be
     713                * weird to get it to ignore any errors from the command.
     714                * If echoing is turned on, we turn it off and use the
     715                * errCheck template to echo the command. Leave echoing
     716                * off so the user doesn't see the weirdness we go through
     717                * to ignore errors. Set cmdTemplate to use the weirdness
     718                * instead of the simple "%s\n" template.
     719                */
     720                if (!(job->flags & JOB_SILENT) && !shutUp &&
     721                    commandShell->hasEchoCtl) {
     722                        DBPRINTF("%s\n", commandShell->echoOff);
     723                        DBPRINTF(commandShell->errCheck, cmd);
     724                        shutUp = TRUE;
     725                }
     726                cmdTemplate = commandShell->ignErr;
     727                /*
     728                * The error ignoration (hee hee) is already taken care
     729                * of by the ignErr template, so pretend error checking
     730                * is still on.
     731                */
     732                errOff = FALSE;
     733            } else {
     734                errOff = FALSE;
     735            }
    660736            #endif
    661         } else {
    662             errOff = FALSE;
    663         }
     737        } else {
     738            errOff = FALSE;
     739        }
    664740    }
    665741
     
    668744    #ifndef KMK /*todo*/
    669745    if (errOff) {
    670         /*
    671         * If echoing is already off, there's no point in issuing the
    672         * echoOff command. Otherwise we issue it and pretend it was on
    673         * for the whole command...
    674         */
    675         if (!shutUp && !(job->flags & JOB_SILENT) && commandShell->hasEchoCtl){
    676             DBPRINTF("%s\n", commandShell->echoOff);
    677             shutUp = TRUE;
    678         }
    679         DBPRINTF("%s\n", commandShell->errCheck);
     746        /*
     747        * If echoing is already off, there's no point in issuing the
     748        * echoOff command. Otherwise we issue it and pretend it was on
     749        * for the whole command...
     750        */
     751        if (!shutUp && !(job->flags & JOB_SILENT) && commandShell->hasEchoCtl){
     752            DBPRINTF("%s\n", commandShell->echoOff);
     753            shutUp = TRUE;
     754        }
     755        DBPRINTF("%s\n", commandShell->errCheck);
    680756    }
    681757    if (shutUp) {
    682         DBPRINTF("%s\n", commandShell->echoOn);
     758        DBPRINTF("%s\n", commandShell->echoOn);
    683759    }
    684760    #endif
     
    689765 *-----------------------------------------------------------------------
    690766 * JobSaveCommand --
    691  *      Save a command to be executed when everything else is done.
    692  *      Callback function for JobFinish...
     767 *      Save a command to be executed when everything else is done.
     768 *      Callback function for JobFinish...
    693769 *
    694770 * Results:
    695  *      Always returns 0
     771 *      Always returns 0
    696772 *
    697773 * Side Effects:
    698  *      The command is tacked onto the end of postCommands's commands list.
     774 *      The command is tacked onto the end of postCommands's commands list.
    699775 *
    700776 *-----------------------------------------------------------------------
     
    714790 *-----------------------------------------------------------------------
    715791 * JobClose --
    716  *      Called to close both input and output pipes when a job is finished.
     792 *      Called to close both input and output pipes when a job is finished.
    717793 *
    718794 * Results:
    719  *      Nada
     795 *      Nada
    720796 *
    721797 * Side Effects:
    722  *      The file descriptors associated with the job are closed.
     798 *      The file descriptors associated with the job are closed.
    723799 *
    724800 *-----------------------------------------------------------------------
     
    728804    Job *job;
    729805{
     806#ifdef USE_PIPES
    730807    if (usePipes) {
    731808#ifdef RMT_WILL_WATCH
    732         Rmt_Ignore(job->inPipe);
     809        Rmt_Ignore(job->inPipe);
    733810#else
    734         FD_CLR(job->inPipe, &outputs);
    735 #endif
    736         if (job->outPipe != job->inPipe) {
    737            (void) close(job->outPipe);
    738         }
    739         JobDoOutput(job, TRUE);
    740         (void) close(job->inPipe);
     811        FD_CLR(job->inPipe, &outputs);
     812#endif
     813        if (job->outPipe != job->inPipe) {
     814           (void) close(job->outPipe);
     815        }
     816        JobDoOutput(job, TRUE);
     817        (void) close(job->inPipe);
    741818    } else {
    742         (void) close(job->outFd);
    743         JobDoOutput(job, TRUE);
    744     }
     819        (void) close(job->outFd);
     820        JobDoOutput(job, TRUE);
     821    }
     822
     823#else  /* Don't use Pipes */
     824    close(job->outFd);
     825    JobDoOutput(job, TRUE);
     826#endif /* USE_PIPES */
    745827}
    746828
     
    748830 *-----------------------------------------------------------------------
    749831 * JobFinish  --
    750  *      Do final processing for the given job including updating
    751  *      parents and starting new jobs as available/necessary. Note
    752  *      that we pay no attention to the JOB_IGNERR flag here.
    753  *      This is because when we're called because of a noexecute flag
    754  *      or something, jstat.w_status is 0 and when called from
    755  *      Job_CatchChildren, the status is zeroed if it s/b ignored.
     832 *      Do final processing for the given job including updating
     833 *      parents and starting new jobs as available/necessary. Note
     834 *      that we pay no attention to the JOB_IGNERR flag here.
     835 *      This is because when we're called because of a noexecute flag
     836 *      or something, jstat.w_status is 0 and when called from
     837 *      Job_CatchChildren, the status is zeroed if it s/b ignored.
    756838 *
    757839 * Results:
    758  *      None
     840 *      None
    759841 *
    760842 * Side Effects:
    761  *      Some nodes may be put on the toBeMade queue.
    762  *      Final commands for the job are placed on postCommands.
    763  *
    764  *      If we got an error and are aborting (aborting == ABORT_ERROR) and
    765  *      the job list is now empty, we are done for the day.
    766  *      If we recognized an error (errors !=0), we set the aborting flag
    767  *      to ABORT_ERROR so no more jobs will be started.
     843 *      Some nodes may be put on the toBeMade queue.
     844 *      Final commands for the job are placed on postCommands.
     845 *
     846 *      If we got an error and are aborting (aborting == ABORT_ERROR) and
     847 *      the job list is now empty, we are done for the day.
     848 *      If we recognized an error (errors !=0), we set the aborting flag
     849 *      to ABORT_ERROR so no more jobs will be started.
    768850 *-----------------------------------------------------------------------
    769851 */
     
    771853static void
    772854JobFinish(job, status)
    773     Job         *job;             /* job to finish */
    774     int         *status;          /* sub-why job went away */
     855    Job         *job;             /* job to finish */
     856#ifdef USE_KLIB
     857    KPROCRES    *status;          /* sub-why job went away */
     858#else
     859    int         *status;          /* sub-why job went away */
     860#endif
    775861{
    776     Boolean      done;
     862#ifdef USE_KLIB
     863    Boolean      done;
     864
     865    if ( ( (status->fFlags & KPROCRES_FLAGS_NORMAL) && status->uExitCode != 0 && !(job->flags & JOB_IGNERR) )
     866        || !(status->fFlags & KPROCRES_FLAGS_NORMAL)
     867         )
     868    {
     869        /*
     870         * If it exited non-zero and either we're doing things our
     871         * way or we're not ignoring errors, the job is finished.
     872         * Similarly, if the shell died because of a signal
     873         * the job is also finished. In these
     874         * cases, finish out the job's output before printing the exit
     875         * status...
     876         */
     877        JobClose(job);
     878        if (job->cmdFILE != NULL && job->cmdFILE != stdout) {
     879           (void) fclose(job->cmdFILE);
     880           job->cmdFILE = NULL;
     881        }
     882        done = TRUE;
     883    } else if (status->fFlags & KPROCRES_FLAGS_NORMAL) {
     884        /*
     885         * Deal with ignored errors in -B mode. We need to print a message
     886         * telling of the ignored error as well as setting status.w_status
     887         * to 0 so the next command gets run. To do this, we set done to be
     888         * TRUE if in -B mode and the job exited non-zero.
     889         */
     890        done = status->uExitCode != 0;
     891        /*
     892         * Old comment said: "Note we don't
     893         * want to close down any of the streams until we know we're at the
     894         * end."
     895         * But we do. Otherwise when are we going to print the rest of the
     896         * stuff?
     897         */
     898        JobClose(job);
     899    } else {
     900        /*
     901         * No need to close things down or anything.
     902         */
     903        done = FALSE;
     904    }
     905
     906    if (    done
     907        || DEBUG(JOB))
     908    {
     909        FILE      *out = stdout;
     910        if (compatMake && !usePipes && (job->flags & JOB_IGNERR))
     911        {
     912            /*
     913             * If output is going to a file and this job is ignoring
     914             * errors, arrange to have the exit status sent to the
     915             * output file as well.
     916             */
     917            out = fdopen(job->outFd, "w");
     918        }
     919
     920        if (status->fFlags & KPROCRES_FLAGS_NORMAL)
     921        {
     922            if (DEBUG(JOB))
     923            {
     924                fprintf(stdout, "Process %d exited.\n", job->pid);
     925                fflush(stdout);
     926            }
     927            if (status->uExitCode != 0)
     928            {
     929#ifdef USE_PIPES
     930                if (usePipes && job->node != lastNode)
     931                {
     932                    MESSAGE(out, job->node);
     933                    lastNode = job->node;
     934                }
     935#endif
     936                fprintf(out, "*** Error code %d%s\n",
     937                        status->uExitCode,
     938                        (job->flags & JOB_IGNERR) ? "(ignored)" : "");
     939
     940                if (job->flags & JOB_IGNERR)
     941                    status->uExitCode = 0;
     942            }
     943            else if (DEBUG(JOB))
     944            {
     945#ifdef USE_PIPES
     946                if (usePipes && job->node != lastNode)
     947                {
     948                    MESSAGE(out, job->node);
     949                    lastNode = job->node;
     950                }
     951#endif
     952                fprintf(out, "*** Completed successfully\n");
     953            }
     954        }
     955        else
     956        {
     957#ifdef USE_PIPES
     958            if (usePipes && job->node != lastNode)
     959            {
     960                MESSAGE(out, job->node);
     961                lastNode = job->node;
     962            }
     963#endif
     964            fprintf(out, "*** Abnormal End\n");
     965        }
     966
     967        fflush(out);
     968    }
     969
     970    /*
     971     * Now handle the -B-mode stuff. If the beast still isn't finished,
     972     * try and restart the job on the next command. If JobStart says it's
     973     * ok, it's ok. If there's an error, this puppy is done.
     974     */
     975    if (    compatMake
     976        && (status->fFlags & KPROCRES_FLAGS_NORMAL)
     977        && !Lst_IsAtEnd(job->node->commands)
     978        )
     979    {
     980        switch (JobStart(job->node, job->flags & JOB_IGNDOTS, job))
     981        {
     982        case JOB_RUNNING:
     983            done = FALSE;
     984            break;
     985        case JOB_ERROR:
     986            done = TRUE;
     987            status->uExitCode = EXIT_FAILURE;
     988            break;
     989        case JOB_FINISHED:
     990            /*
     991             * If we got back a JOB_FINISHED code, JobStart has already
     992             * called Make_Update and freed the job descriptor. We set
     993             * done to false here to avoid fake cycles and double frees.
     994             * JobStart needs to do the update so we can proceed up the
     995             * graph when given the -n flag..
     996             */
     997            done = FALSE;
     998            break;
     999        }
     1000    } else {
     1001        done = TRUE;
     1002    }
     1003
     1004
     1005    if (   done
     1006        && aborting != ABORT_ERROR
     1007        && aborting != ABORT_INTERRUPT
     1008        && (status->fFlags & KPROCRES_FLAGS_NORMAL)
     1009        && status->uExitCode == 0
     1010        )
     1011    {
     1012        /*
     1013         * As long as we aren't aborting and the job didn't return a non-zero
     1014         * status that we shouldn't ignore, we call Make_Update to update
     1015         * the parents. In addition, any saved commands for the node are placed
     1016         * on the .END target.
     1017         */
     1018        if (job->tailCmds != NILLNODE) {
     1019            Lst_ForEachFrom(job->node->commands, job->tailCmds,
     1020                             JobSaveCommand,
     1021                            (ClientData)job->node);
     1022        }
     1023        job->node->made = MADE;
     1024        Make_Update(job->node);
     1025        efree((Address)job);
     1026    }
     1027    else if (!(status->fFlags & KPROCRES_FLAGS_NORMAL) || status->uExitCode != 0)
     1028    {
     1029        errors += 1;
     1030        efree((Address)job);
     1031    }
     1032
     1033    /*
     1034     * Set aborting if any error.
     1035     */
     1036    if (errors && !keepgoing && (aborting != ABORT_INTERRUPT))
     1037    {
     1038        /*
     1039         * If we found any errors in this batch of children and the -k flag
     1040         * wasn't given, we set the aborting flag so no more jobs get
     1041         * started.
     1042         */
     1043        aborting = ABORT_ERROR;
     1044    }
     1045
     1046    if ((aborting == ABORT_ERROR) && Job_Empty())
     1047    {
     1048        /*
     1049         * If we are aborting and the job table is now empty, we finish.
     1050         */
     1051        Finish(errors);
     1052    }
     1053
     1054
     1055#else /* Don't use kLib */
     1056    Boolean      done;
    7771057
    7781058    if ((WIFEXITED(*status) &&
    779         (((WEXITSTATUS(*status) != 0) && !(job->flags & JOB_IGNERR)))) ||
    780         (WIFSIGNALED(*status) && (WTERMSIG(*status) != SIGCONT)))
     1059        (((WEXITSTATUS(*status) != 0) && !(job->flags & JOB_IGNERR)))) ||
     1060        (WIFSIGNALED(*status) && (WTERMSIG(*status) != SIGCONT)))
    7811061    {
    782         /*
    783         * If it exited non-zero and either we're doing things our
    784         * way or we're not ignoring errors, the job is finished.
    785         * Similarly, if the shell died because of a signal
    786         * the job is also finished. In these
    787         * cases, finish out the job's output before printing the exit
    788         * status...
    789         */
     1062        /*
     1063        * If it exited non-zero and either we're doing things our
     1064        * way or we're not ignoring errors, the job is finished.
     1065        * Similarly, if the shell died because of a signal
     1066        * the job is also finished. In these
     1067        * cases, finish out the job's output before printing the exit
     1068        * status...
     1069        */
    7901070#ifdef REMOTE
    791         KILL(job->pid, SIGCONT);
    792 #endif
    793         JobClose(job);
    794         if (job->cmdFILE != NULL && job->cmdFILE != stdout) {
    795            (void) fclose(job->cmdFILE);
    796         }
    797         done = TRUE;
     1071        KILL(job->pid, SIGCONT);
     1072#endif
     1073        JobClose(job);
     1074        if (job->cmdFILE != NULL && job->cmdFILE != stdout) {
     1075           (void) fclose(job->cmdFILE);
     1076        }
     1077        done = TRUE;
    7981078#ifdef REMOTE
    799         if (job->flags & JOB_REMOTE)
    800             Rmt_Done(job->rmtID, job->node);
     1079        if (job->flags & JOB_REMOTE)
     1080            Rmt_Done(job->rmtID, job->node);
    8011081#endif
    8021082    } else if (WIFEXITED(*status)) {
    803         /*
    804         * Deal with ignored errors in -B mode. We need to print a message
    805         * telling of the ignored error as well as setting status.w_status
    806         * to 0 so the next command gets run. To do this, we set done to be
    807         * TRUE if in -B mode and the job exited non-zero.
    808         */
    809         done = WEXITSTATUS(*status) != 0;
    810         /*
    811         * Old comment said: "Note we don't
    812         * want to close down any of the streams until we know we're at the
    813         * end."
    814         * But we do. Otherwise when are we going to print the rest of the
    815         * stuff?
    816         */
    817         JobClose(job);
     1083        /*
     1084        * Deal with ignored errors in -B mode. We need to print a message
     1085        * telling of the ignored error as well as setting status.w_status
     1086        * to 0 so the next command gets run. To do this, we set done to be
     1087        * TRUE if in -B mode and the job exited non-zero.
     1088        */
     1089        done = WEXITSTATUS(*status) != 0;
     1090        /*
     1091        * Old comment said: "Note we don't
     1092        * want to close down any of the streams until we know we're at the
     1093        * end."
     1094        * But we do. Otherwise when are we going to print the rest of the
     1095        * stuff?
     1096        */
     1097        JobClose(job);
    8181098#ifdef REMOTE
    819         if (job->flags & JOB_REMOTE)
    820             Rmt_Done(job->rmtID, job->node);
     1099        if (job->flags & JOB_REMOTE)
     1100            Rmt_Done(job->rmtID, job->node);
    8211101#endif /* REMOTE */
    8221102    } else {
    823         /*
    824         * No need to close things down or anything.
    825         */
    826         done = FALSE;
     1103        /*
     1104        * No need to close things down or anything.
     1105        */
     1106        done = FALSE;
    8271107    }
    8281108
    8291109    if (done ||
    830         WIFSTOPPED(*status) ||
    831         (WIFSIGNALED(*status) && (WTERMSIG(*status) == SIGCONT)) ||
    832         DEBUG(JOB))
     1110        WIFSTOPPED(*status) ||
     1111        (WIFSIGNALED(*status) && (WTERMSIG(*status) == SIGCONT)) ||
     1112        DEBUG(JOB))
    8331113    {
    834         FILE      *out;
    835 
    836         if (compatMake && !usePipes && (job->flags & JOB_IGNERR)) {
    837             /*
    838              * If output is going to a file and this job is ignoring
    839              * errors, arrange to have the exit status sent to the
    840              * output file as well.
    841              */
    842             out = fdopen(job->outFd, "w");
    843         } else {
    844             out = stdout;
    845         }
    846 
    847         if (WIFEXITED(*status)) {
    848             if (DEBUG(JOB)) {
    849                 (void) fprintf(stdout, "Process %d exited.\n", job->pid);
    850                 (void) fflush(stdout);
    851             }
    852             if (WEXITSTATUS(*status) != 0) {
    853                 if (usePipes && job->node != lastNode) {
    854                     MESSAGE(out, job->node);
    855                     lastNode = job->node;
    856                 }
    857                 (void) fprintf(out, "*** Error code %d%s\n",
    858                                WEXITSTATUS(*status),
    859                                (job->flags & JOB_IGNERR) ? "(ignored)" : "");
    860 
    861                 if (job->flags & JOB_IGNERR) {
    862                     *status = 0;
    863                 }
    864             } else if (DEBUG(JOB)) {
    865                 if (usePipes && job->node != lastNode) {
    866                     MESSAGE(out, job->node);
    867                     lastNode = job->node;
    868                 }
    869                 (void) fprintf(out, "*** Completed successfully\n");
    870             }
    871         } else if (WIFSTOPPED(*status)) {
    872             if (DEBUG(JOB)) {
    873                 (void) fprintf(stdout, "Process %d stopped.\n", job->pid);
    874                 (void) fflush(stdout);
    875             }
    876             if (usePipes && job->node != lastNode) {
    877                 MESSAGE(out, job->node);
    878                 lastNode = job->node;
    879             }
    880             if (!(job->flags & JOB_REMIGRATE)) {
    881                 (void) fprintf(out, "*** Stopped -- signal %d\n",
    882                     WSTOPSIG(*status));
    883             }
    884             job->flags |= JOB_RESUME;
    885             (void)Lst_AtEnd(stoppedJobs, (ClientData)job);
    886 #ifdef REMOTE
    887             if (job->flags & JOB_REMIGRATE)
    888                 JobRestart(job);
    889 #endif
    890             (void) fflush(out);
    891             return;
    892         } else if (WTERMSIG(*status) == SIGCONT) {
    893             /*
    894              * If the beastie has continued, shift the Job from the stopped
    895              * list to the running one (or re-stop it if concurrency is
    896              * exceeded) and go and get another child.
    897              */
    898             if (job->flags & (JOB_RESUME|JOB_REMIGRATE|JOB_RESTART)) {
    899                 if (usePipes && job->node != lastNode) {
    900                     MESSAGE(out, job->node);
    901                     lastNode = job->node;
    902                 }
    903                 (void) fprintf(out, "*** Continued\n");
    904             }
    905             if (!(job->flags & JOB_CONTINUING)) {
    906                 if (DEBUG(JOB)) {
    907                     (void) fprintf(stdout,
    908                                    "Warning: process %d was not continuing.\n",
    909                                    job->pid);
    910                     (void) fflush(stdout);
    911                 }
     1114        FILE      *out;
     1115
     1116        if (compatMake && !usePipes && (job->flags & JOB_IGNERR)) {
     1117            /*
     1118             * If output is going to a file and this job is ignoring
     1119             * errors, arrange to have the exit status sent to the
     1120             * output file as well.
     1121             */
     1122            out = fdopen(job->outFd, "w");
     1123        } else {
     1124            out = stdout;
     1125        }
     1126
     1127        if (WIFEXITED(*status)) {
     1128            if (DEBUG(JOB)) {
     1129                (void) fprintf(stdout, "Process %d exited.\n", job->pid);
     1130                (void) fflush(stdout);
     1131            }
     1132            if (WEXITSTATUS(*status) != 0) {
     1133#ifdef USE_PIPES
     1134                if (usePipes && job->node != lastNode) {
     1135                    MESSAGE(out, job->node);
     1136                    lastNode = job->node;
     1137                }
     1138#endif
     1139                (void) fprintf(out, "*** Error code %d%s\n",
     1140                               WEXITSTATUS(*status),
     1141                               (job->flags & JOB_IGNERR) ? "(ignored)" : "");
     1142
     1143                if (job->flags & JOB_IGNERR) {
     1144                    *status = 0;
     1145                }
     1146            } else if (DEBUG(JOB)) {
     1147#ifdef USE_PIPES
     1148                if (usePipes && job->node != lastNode) {
     1149                    MESSAGE(out, job->node);
     1150                    lastNode = job->node;
     1151                }
     1152#endif
     1153                (void) fprintf(out, "*** Completed successfully\n");
     1154            }
     1155        } else if (WIFSTOPPED(*status)) {
     1156            if (DEBUG(JOB)) {
     1157                (void) fprintf(stdout, "Process %d stopped.\n", job->pid);
     1158                (void) fflush(stdout);
     1159            }
     1160#ifdef USE_PIPES
     1161            if (usePipes && job->node != lastNode) {
     1162                MESSAGE(out, job->node);
     1163                lastNode = job->node;
     1164            }
     1165#endif
     1166            if (!(job->flags & JOB_REMIGRATE)) {
     1167                (void) fprintf(out, "*** Stopped -- signal %d\n",
     1168                    WSTOPSIG(*status));
     1169            }
     1170            job->flags |= JOB_RESUME;
     1171            (void)Lst_AtEnd(stoppedJobs, (ClientData)job);
     1172#if defined(REMOTE) && defined(SIGCONT)
     1173            if (job->flags & JOB_REMIGRATE)
     1174                JobRestart(job);
     1175#endif
     1176            (void) fflush(out);
     1177            return;
     1178        } else if (WTERMSIG(*status) == SIGCONT) {
     1179            /*
     1180             * If the beastie has continued, shift the Job from the stopped
     1181             * list to the running one (or re-stop it if concurrency is
     1182             * exceeded) and go and get another child.
     1183             */
     1184            if (job->flags & (JOB_RESUME|JOB_REMIGRATE|JOB_RESTART)) {
     1185#ifdef USE_PIPES
     1186                if (usePipes && job->node != lastNode) {
     1187                    MESSAGE(out, job->node);
     1188                    lastNode = job->node;
     1189                }
     1190#endif
     1191                (void) fprintf(out, "*** Continued\n");
     1192            }
     1193            if (!(job->flags & JOB_CONTINUING)) {
     1194                if (DEBUG(JOB)) {
     1195                    (void) fprintf(stdout,
     1196                                   "Warning: process %d was not continuing.\n",
     1197                                   job->pid);
     1198                    (void) fflush(stdout);
     1199                }
     1200#ifdef SIGCONT
    9121201#ifdef notdef
    913                 /*
    914                  * We don't really want to restart a job from scratch just
    915                  * because it continued, especially not without killing the
    916                  * continuing process!  That's why this is ifdef'ed out.
    917                  * FD - 9/17/90
    918                  */
    919                 JobRestart(job);
    920 #endif
    921             }
    922             job->flags &= ~JOB_CONTINUING;
    923             Lst_AtEnd(jobs, (ClientData)job);
    924             nJobs += 1;
    925             if (!(job->flags & JOB_REMOTE)) {
    926                 if (DEBUG(JOB)) {
    927                     (void) fprintf(stdout,
    928                                    "Process %d is continuing locally.\n",
    929                                    job->pid);
    930                     (void) fflush(stdout);
    931                 }
    932                 nLocal += 1;
    933             }
    934             if (nJobs == maxJobs) {
    935                 jobFull = TRUE;
    936                 if (DEBUG(JOB)) {
    937                     (void) fprintf(stdout, "Job queue is full.\n");
    938                     (void) fflush(stdout);
    939                 }
    940             }
    941             (void) fflush(out);
    942             return;
    943         } else {
    944             if (usePipes && job->node != lastNode) {
    945                 MESSAGE(out, job->node);
    946                 lastNode = job->node;
    947             }
    948             (void) fprintf(out, "*** Signal %d\n", WTERMSIG(*status));
    949         }
    950 
    951         (void) fflush(out);
     1202                /*
     1203                 * We don't really want to restart a job from scratch just
     1204                 * because it continued, especially not without killing the
     1205                 * continuing process!  That's why this is ifdef'ed out.
     1206                 * FD - 9/17/90
     1207                 */
     1208                JobRestart(job);
     1209#endif
     1210#endif
     1211            }
     1212            job->flags &= ~JOB_CONTINUING;
     1213            Lst_AtEnd(jobs, (ClientData)job);
     1214            nJobs += 1;
     1215            if (!(job->flags & JOB_REMOTE)) {
     1216                if (DEBUG(JOB)) {
     1217                    (void) fprintf(stdout,
     1218                                   "Process %d is continuing locally.\n",
     1219                                   job->pid);
     1220                    (void) fflush(stdout);
     1221                }
     1222                nLocal += 1;
     1223            }
     1224            if (nJobs == maxJobs) {
     1225                jobFull = TRUE;
     1226                if (DEBUG(JOB)) {
     1227                    (void) fprintf(stdout, "Job queue is full.\n");
     1228                    (void) fflush(stdout);
     1229                }
     1230            }
     1231            (void) fflush(out);
     1232            return;
     1233        } else {
     1234#ifdef USE_PIPES
     1235            if (usePipes && job->node != lastNode) {
     1236                MESSAGE(out, job->node);
     1237                lastNode = job->node;
     1238            }
     1239#endif
     1240            (void) fprintf(out, "*** Signal %d\n", WTERMSIG(*status));
     1241        }
     1242
     1243        (void) fflush(out);
    9521244    }
    9531245
     
    9581250     */
    9591251    if (compatMake && (WIFEXITED(*status) &&
    960         !Lst_IsAtEnd(job->node->commands))) {
    961         switch (JobStart(job->node, job->flags & JOB_IGNDOTS, job)) {
    962         case JOB_RUNNING:
    963             done = FALSE;
    964             break;
    965         case JOB_ERROR:
    966             done = TRUE;
    967             W_SETEXITSTATUS(status, 1);
    968             break;
    969         case JOB_FINISHED:
    970             /*
    971              * If we got back a JOB_FINISHED code, JobStart has already
    972              * called Make_Update and freed the job descriptor. We set
    973              * done to false here to avoid fake cycles and double frees.
    974              * JobStart needs to do the update so we can proceed up the
    975              * graph when given the -n flag..
    976              */
    977             done = FALSE;
    978             break;
    979         }
     1252        !Lst_IsAtEnd(job->node->commands))) {
     1253        switch (JobStart(job->node, job->flags & JOB_IGNDOTS, job)) {
     1254        case JOB_RUNNING:
     1255            done = FALSE;
     1256            break;
     1257        case JOB_ERROR:
     1258            done = TRUE;
     1259            W_SETEXITSTATUS(status, 1);
     1260            break;
     1261        case JOB_FINISHED:
     1262            /*
     1263             * If we got back a JOB_FINISHED code, JobStart has already
     1264             * called Make_Update and freed the job descriptor. We set
     1265             * done to false here to avoid fake cycles and double frees.
     1266             * JobStart needs to do the update so we can proceed up the
     1267             * graph when given the -n flag..
     1268             */
     1269            done = FALSE;
     1270            break;
     1271        }
    9801272    } else {
    981         done = TRUE;
     1273        done = TRUE;
    9821274    }
    9831275
    9841276
    9851277    if (done &&
    986         (aborting != ABORT_ERROR) &&
    987         (aborting != ABORT_INTERRUPT) &&
    988         (*status == 0))
     1278        (aborting != ABORT_ERROR) &&
     1279        (aborting != ABORT_INTERRUPT) &&
     1280        (*status == 0))
    9891281    {
    990         /*
    991         * As long as we aren't aborting and the job didn't return a non-zero
    992         * status that we shouldn't ignore, we call Make_Update to update
    993         * the parents. In addition, any saved commands for the node are placed
    994         * on the .END target.
    995         */
    996         if (job->tailCmds != NILLNODE) {
    997             Lst_ForEachFrom(job->node->commands, job->tailCmds,
    998                              JobSaveCommand,
    999                             (ClientData)job->node);
    1000         }
    1001         job->node->made = MADE;
    1002         Make_Update(job->node);
    1003         efree((Address)job);
     1282        /*
     1283        * As long as we aren't aborting and the job didn't return a non-zero
     1284        * status that we shouldn't ignore, we call Make_Update to update
     1285        * the parents. In addition, any saved commands for the node are placed
     1286        * on the .END target.
     1287        */
     1288        if (job->tailCmds != NILLNODE) {
     1289            Lst_ForEachFrom(job->node->commands, job->tailCmds,
     1290                             JobSaveCommand,
     1291                            (ClientData)job->node);
     1292        }
     1293        job->node->made = MADE;
     1294        Make_Update(job->node);
     1295        efree((Address)job);
    10041296    } else if (*status != 0) {
    1005         errors += 1;
    1006         efree((Address)job);
    1007     }
    1008 
     1297        errors += 1;
     1298        efree((Address)job);
     1299    }
     1300
     1301#ifdef SIGCONT
    10091302    JobRestartJobs();
     1303#endif
    10101304
    10111305    /*
     
    10131307     */
    10141308    if (errors && !keepgoing && (aborting != ABORT_INTERRUPT)) {
    1015         /*
    1016         * If we found any errors in this batch of children and the -k flag
    1017         * wasn't given, we set the aborting flag so no more jobs get
    1018         * started.
    1019         */
    1020         aborting = ABORT_ERROR;
     1309        /*
     1310        * If we found any errors in this batch of children and the -k flag
     1311        * wasn't given, we set the aborting flag so no more jobs get
     1312        * started.
     1313        */
     1314        aborting = ABORT_ERROR;
    10211315    }
    10221316
    10231317    if ((aborting == ABORT_ERROR) && Job_Empty())
    1024         /*
    1025          * If we are aborting and the job table is now empty, we finish.
    1026          */
    1027         Finish(errors);
     1318        /*
     1319         * If we are aborting and the job table is now empty, we finish.
     1320         */
     1321        Finish(errors);
     1322#endif /* USE_KLIB */
    10281323}
    10291324
     
    10311326 *-----------------------------------------------------------------------
    10321327 * Job_Touch --
    1033  *      Touch the given target. Called by JobStart when the -t flag was
    1034  *      given
     1328 *      Touch the given target. Called by JobStart when the -t flag was
     1329 *      given
    10351330 *
    10361331 * Results:
    1037  *      None
     1332 *      None
    10381333 *
    10391334 * Side Effects:
    1040  *      The data modification of the file is changed. In addition, if the
    1041  *      file did not exist, it is created.
     1335 *      The data modification of the file is changed. In addition, if the
     1336 *      file did not exist, it is created.
    10421337 *-----------------------------------------------------------------------
    10431338 */
    10441339void
    10451340Job_Touch(gn, silent)
    1046     GNode         *gn;          /* the node of the file to touch */
    1047     Boolean       silent;       /* TRUE if should not print messages */
     1341    GNode         *gn;          /* the node of the file to touch */
     1342    Boolean       silent;       /* TRUE if should not print messages */
    10481343{
    1049     int           streamID;     /* ID of stream opened to do the touch */
    1050     struct utimbuf times;       /* Times for utime() call */
     1344    int           streamID;     /* ID of stream opened to do the touch */
     1345    struct utimbuf times;       /* Times for utime() call */
    10511346
    10521347    if (gn->type & (OP_JOIN|OP_USE|OP_EXEC|OP_OPTIONAL)) {
    1053         /*
    1054         * .JOIN, .USE, .ZEROTIME and .OPTIONAL targets are "virtual" targets
    1055         * and, as such, shouldn't really be created.
    1056         */
    1057         return;
     1348        /*
     1349        * .JOIN, .USE, .ZEROTIME and .OPTIONAL targets are "virtual" targets
     1350        * and, as such, shouldn't really be created.
     1351        */
     1352        return;
    10581353    }
    10591354
    10601355    if (!silent) {
    1061         (void) fprintf(stdout, "touch %s\n", gn->name);
    1062         (void) fflush(stdout);
     1356        (void) fprintf(stdout, "touch %s\n", gn->name);
     1357        (void) fflush(stdout);
    10631358    }
    10641359
    10651360    if (noExecute) {
    1066         return;
     1361        return;
    10671362    }
    10681363
    10691364#ifdef USE_ARCHIVES
    10701365    if (gn->type & OP_ARCHV) {
    1071         Arch_Touch(gn);
     1366        Arch_Touch(gn);
    10721367    } else if (gn->type & OP_LIB) {
    1073         Arch_TouchLib(gn);
     1368        Arch_TouchLib(gn);
    10741369    } else {
    10751370#else
     
    10771372#endif
    10781373
    1079         char    *file = gn->path ? gn->path : gn->name;
    1080 
    1081         times.actime = times.modtime = now;
    1082         if (utime(file, &times) < 0){
    1083             streamID = open(file, O_RDWR | O_CREAT, 0666);
    1084 
    1085             if (streamID >= 0) {
    1086                 char    c;
    1087 
    1088                 /*
    1089                 * Read and write a byte to the file to change the
    1090                 * modification time, then close the file.
    1091                 */
    1092                 if (read(streamID, &c, 1) == 1) {
    1093                     (void) lseek(streamID, 0L, SEEK_SET);
    1094                     (void) write(streamID, &c, 1);
    1095                 }
    1096 
    1097                 (void) close(streamID);
    1098             } else {
    1099                 (void) fprintf(stdout, "*** couldn't touch %s: %s",
    1100                                file, strerror(errno));
    1101                 (void) fflush(stdout);
    1102             }
    1103         }
     1374        char    *file = gn->path ? gn->path : gn->name;
     1375
     1376        times.actime = times.modtime = now;
     1377        if (utime(file, &times) < 0){
     1378            streamID = open(file, O_RDWR | O_CREAT, 0666);
     1379
     1380            if (streamID >= 0) {
     1381                char    c;
     1382
     1383                /*
     1384                * Read and write a byte to the file to change the
     1385                * modification time, then close the file.
     1386                */
     1387                if (read(streamID, &c, 1) == 1) {
     1388                    (void) lseek(streamID, 0L, SEEK_SET);
     1389                    (void) write(streamID, &c, 1);
     1390                }
     1391
     1392                (void) close(streamID);
     1393            } else {
     1394                (void) fprintf(stdout, "*** couldn't touch %s: %s",
     1395                               file, strerror(errno));
     1396                (void) fflush(stdout);
     1397            }
     1398        }
    11041399    }
    11051400}
     
    11081403 *-----------------------------------------------------------------------
    11091404 * Job_CheckCommands --
    1110  *      Make sure the given node has all the commands it needs.
     1405 *      Make sure the given node has all the commands it needs.
    11111406 *
    11121407 * Results:
    1113  *      TRUE if the commands list is/was ok.
     1408 *      TRUE if the commands list is/was ok.
    11141409 *
    11151410 * Side Effects:
    1116  *      The node will have commands from the .DEFAULT rule added to it
    1117  *      if it needs them.
     1411 *      The node will have commands from the .DEFAULT rule added to it
     1412 *      if it needs them.
    11181413 *-----------------------------------------------------------------------
    11191414 */
    11201415Boolean
    11211416Job_CheckCommands(gn, abortProc)
    1122     GNode          *gn;             /* The target whose commands need
    1123                                      * verifying */
    1124     void        (*abortProc) __P((char *, ...));
    1125                         /* Function to abort with message */
     1417    GNode          *gn;             /* The target whose commands need
     1418                                     * verifying */
     1419    void        (*abortProc) __P((char *, ...));
     1420                        /* Function to abort with message */
    11261421{
    11271422    if (OP_NOP(gn->type) && Lst_IsEmpty(gn->commands)
     
    11311426        )
    11321427    {
    1133         /*
    1134         * No commands. Look for .DEFAULT rule from which we might infer
    1135         * commands
    1136         */
    1137         if ((DEFAULT != NILGNODE) && !Lst_IsEmpty(DEFAULT->commands)) {
    1138             char *p1;
    1139             /*
    1140              * Make only looks for a .DEFAULT if the node was never the
    1141              * target of an operator, so that's what we do too. If
    1142              * a .DEFAULT was given, we substitute its commands for gn's
    1143              * commands and set the IMPSRC variable to be the target's name
    1144              * The DEFAULT node acts like a transformation rule, in that
    1145              * gn also inherits any attributes or sources attached to
    1146              * .DEFAULT itself.
    1147              */
    1148             Make_HandleUse(DEFAULT, gn);
    1149             Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), gn);
    1150             efree(p1);
    1151         } else if (Dir_MTime(gn) == 0) {
    1152             /*
    1153              * The node wasn't the target of an operator we have no .DEFAULT
    1154              * rule to go on and the target doesn't already exist. There's
    1155              * nothing more we can do for this branch. If the -k flag wasn't
    1156              * given, we stop in our tracks, otherwise we just don't update
    1157              * this node's parents so they never get examined.
    1158              */
    1159             static const char msg[] = MAKE_NAME ": don't know how to make";
    1160 
    1161             if (gn->type & OP_OPTIONAL) {
    1162                 (void) fprintf(stdout, "%s %s(ignored)\n", msg, gn->name);
    1163                 (void) fflush(stdout);
    1164             } else if (keepgoing) {
    1165                 (void) fprintf(stdout, "%s %s(continuing)\n", msg, gn->name);
    1166                 (void) fflush(stdout);
    1167                 return FALSE;
    1168             } else {
     1428        /*
     1429        * No commands. Look for .DEFAULT rule from which we might infer
     1430        * commands
     1431        */
     1432        if ((DEFAULT != NILGNODE) && !Lst_IsEmpty(DEFAULT->commands)) {
     1433            char *p1;
     1434            /*
     1435             * Make only looks for a .DEFAULT if the node was never the
     1436             * target of an operator, so that's what we do too. If
     1437             * a .DEFAULT was given, we substitute its commands for gn's
     1438             * commands and set the IMPSRC variable to be the target's name
     1439             * The DEFAULT node acts like a transformation rule, in that
     1440             * gn also inherits any attributes or sources attached to
     1441             * .DEFAULT itself.
     1442             */
     1443            Make_HandleUse(DEFAULT, gn);
     1444            Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), gn);
     1445            efree(p1);
     1446        } else if (Dir_MTime(gn) == 0) {
     1447            /*
     1448             * The node wasn't the target of an operator we have no .DEFAULT
     1449             * rule to go on and the target doesn't already exist. There's
     1450             * nothing more we can do for this branch. If the -k flag wasn't
     1451             * given, we stop in our tracks, otherwise we just don't update
     1452             * this node's parents so they never get examined.
     1453             */
     1454            static const char msg[] = MAKE_NAME ": don't know how to make";
     1455
     1456            if (gn->type & OP_OPTIONAL) {
     1457                (void) fprintf(stdout, "%s %s(ignored)\n", msg, gn->name);
     1458                (void) fflush(stdout);
     1459            } else if (keepgoing) {
     1460                (void) fprintf(stdout, "%s %s(continuing)\n", msg, gn->name);
     1461                (void) fflush(stdout);
     1462                return FALSE;
     1463            } else {
    11691464#if OLD_JOKE
    1170                 if (strcmp(gn->name,"love") == 0)
    1171                     (*abortProc)("Not war.");
     1465                if (strcmp(gn->name,"love") == 0)
     1466                    (*abortProc)("Not war.");
    11721467#if defined(NMAKE) || defined(KMK)
    11731468                else if (strcmp(gn->name,"fire") == 0)
    1174                     (*abortProc)("No match.");
     1469                    (*abortProc)("No match.");
    11751470#endif
    11761471                else
    11771472#endif
    1178                     (*abortProc)("%s %s. Stop", msg, gn->name);
    1179                 return FALSE;
    1180             }
    1181         }
     1473                    (*abortProc)("%s %s. Stop", msg, gn->name);
     1474                return FALSE;
     1475            }
     1476        }
    11821477    }
    11831478    return TRUE;
     
    11871482 *-----------------------------------------------------------------------
    11881483 * JobLocalInput --
    1189  *      Handle a pipe becoming readable. Callback function for Rmt_Watch
     1484 *      Handle a pipe becoming readable. Callback function for Rmt_Watch
    11901485 *
    11911486 * Results:
    1192  *      None
     1487 *      None
    11931488 *
    11941489 * Side Effects:
    1195  *      JobDoOutput is called.
     1490 *      JobDoOutput is called.
    11961491 *
    11971492 *-----------------------------------------------------------------------
     
    12001495static void
    12011496JobLocalInput(stream, job)
    1202     int     stream;     /* Stream that's ready (ignored) */
    1203     Job     *job;       /* Job to which the stream belongs */
     1497    int     stream;     /* Stream that's ready (ignored) */
     1498    Job     *job;       /* Job to which the stream belongs */
    12041499{
    12051500    JobDoOutput(job, FALSE);
     
    12101505 *-----------------------------------------------------------------------
    12111506 * JobExec --
    1212  *      Execute the shell for the given job. Called from JobStart and
    1213  *      JobRestart.
     1507 *      Execute the shell for the given job. Called from JobStart and
     1508 *      JobRestart.
    12141509 *
    12151510 * Results:
    1216  *      None.
     1511 *      None.
    12171512 *
    12181513 * Side Effects:
    1219  *      A shell is executed, outputs is altered and the Job structure added
    1220  *      to the job table.
     1514 *      A shell is executed, outputs is altered and the Job structure added
     1515 *      to the job table.
    12211516 *
    12221517 *-----------------------------------------------------------------------
     
    12241519static void
    12251520JobExec(job, argv)
    1226     Job           *job;         /* Job to execute */
    1227     char          **argv;
     1521    Job           *job;         /* Job to execute */
     1522    char          **argv;
    12281523{
    1229     int           cpid;         /* ID of new child */
     1524#ifdef USE_KLIB
     1525    int           cpid;         /* ID of new child */
     1526    int           rc;
     1527
     1528    if (DEBUG(JOB))
     1529    {
     1530        int       i;
     1531        fprintf(stdout, "Running %s %sly\n", job->node->name,
     1532                job->flags&JOB_REMOTE?"remote":"local");
     1533        fprintf(stdout, "\tCommand: ");
     1534        for (i = 0; argv[i] != NULL; i++)
     1535            fprintf(stdout, "%s ", argv[i]);
     1536        fprintf(stdout, "\n");
     1537        fflush(stdout);
     1538    }
     1539
     1540    /*
     1541     * Some jobs produce no output and it's disconcerting to have
     1542     * no feedback of their running (since they produce no output, the
     1543     * banner with their name in it never appears). This is an attempt to
     1544     * provide that feedback, even if nothing follows it.
     1545     */
     1546    if (    lastNode != job->node
     1547        &&  (job->flags & JOB_FIRST)
     1548        && !(job->flags & JOB_SILENT)
     1549         )
     1550    {
     1551        MESSAGE(stdout, job->node);
     1552        lastNode = job->node;
     1553    }
     1554
     1555    /*
     1556     * Create process with assigned output+stderr pipe.
     1557     */
     1558    if (job->cmdFILE)
     1559        fseek(job->cmdFILE, 0, SEEK_SET);
     1560    rc = kProcCreate(argv,
     1561                     NULL,
     1562                     NULL,
     1563                     NULL,
     1564                     KPROCCREATE_FLAGS_SPAWN,
     1565                     job->cmdFILE ? FILENO(job->cmdFILE) : KFILE_NULL,
     1566                     usePipes ? job->outPipe : job->outFd, /* stdout */
     1567                     usePipes ? job->outPipe : job->outFd, /* stderr */
     1568                     &cpid,
     1569                     NULL);
     1570    if (!rc)
     1571    {
     1572        job->pid = cpid;
     1573
     1574#ifdef USE_PIPES
     1575        if (usePipes && (job->flags & JOB_FIRST) )
     1576        {
     1577            /*
     1578             * The first time a job is run for a node, we set the current
     1579             * position in the buffer to the beginning and mark another
     1580             * stream to watch in the outputs mask
     1581             */
     1582            job->curPos = 0;
     1583            FD_SET(job->inPipe, &outputs);
     1584        }
     1585#endif /* USE_PIPES */
     1586
     1587        if (job->flags & JOB_REMOTE) {
     1588            job->rmtID = 0;
     1589        } else {
     1590            nLocal += 1;
     1591            /*
     1592             * XXX: Used to not happen if REMOTE. Why?
     1593             */
     1594            if (job->cmdFILE != NULL && job->cmdFILE != stdout) {
     1595                fclose(job->cmdFILE);
     1596                job->cmdFILE = NULL;
     1597            }
     1598        }
     1599
     1600        /*
     1601         * Now the job is actually running, add it to the table.
     1602         */
     1603        nJobs += 1;
     1604        (void) Lst_AtEnd(jobs, (ClientData)job);
     1605        if (nJobs == maxJobs)
     1606        {
     1607            jobFull = TRUE;
     1608        }
     1609    }
     1610    else
     1611        Punt("Cannot start child (%d)", rc);
     1612
     1613
     1614
     1615#else /* Don't use kLib */
     1616    int           cpid;         /* ID of new child */
    12301617
    12311618    if (DEBUG(JOB)) {
    1232         int       i;
    1233 
    1234         (void) fprintf(stdout, "Running %s %sly\n", job->node->name,
    1235                        job->flags&JOB_REMOTE?"remote":"local");
    1236         (void) fprintf(stdout, "\tCommand: ");
    1237         for (i = 0; argv[i] != NULL; i++) {
    1238             (void) fprintf(stdout, "%s ", argv[i]);
    1239         }
    1240         (void) fprintf(stdout, "\n");
    1241         (void) fflush(stdout);
     1619        int       i;
     1620
     1621        (void) fprintf(stdout, "Running %s %sly\n", job->node->name,
     1622                       job->flags&JOB_REMOTE?"remote":"local");
     1623        (void) fprintf(stdout, "\tCommand: ");
     1624        for (i = 0; argv[i] != NULL; i++) {
     1625            (void) fprintf(stdout, "%s ", argv[i]);
     1626        }
     1627        (void) fprintf(stdout, "\n");
     1628        (void) fflush(stdout);
    12421629    }
    12431630
     
    12491636     */
    12501637    if ((lastNode != job->node) && (job->flags & JOB_FIRST) &&
    1251         !(job->flags & JOB_SILENT)) {
    1252         MESSAGE(stdout, job->node);
    1253         lastNode = job->node;
     1638        !(job->flags & JOB_SILENT)) {
     1639        MESSAGE(stdout, job->node);
     1640        lastNode = job->node;
    12541641    }
    12551642
    12561643#ifdef RMT_NO_EXEC
    12571644    if (job->flags & JOB_REMOTE) {
    1258         goto jobExecFinish;
     1645        goto jobExecFinish;
    12591646    }
    12601647#endif /* RMT_NO_EXEC */
     
    12651652    if ((cpid = vfork()) == -1) {
    12661653#endif
    1267         Punt("Cannot fork");
     1654        Punt("Cannot fork");
    12681655    } else if (cpid == 0) {
    12691656
    1270         /*
    1271         * Must duplicate the input stream down to the child's input and
    1272         * reset it to the beginning (again). Since the stream was marked
    1273         * close-on-exec, we must clear that bit in the new input.
    1274         */
    1275         if (dup2(FILENO(job->cmdFILE), 0) == -1)
    1276             Punt("Cannot dup2: %s", strerror(errno));
    1277         (void) fcntl(0, F_SETFD, 0);
    1278         (void) lseek(0, 0, SEEK_SET);
    1279 
    1280         if (usePipes) {
    1281             /*
    1282              * Set up the child's output to be routed through the pipe
    1283              * we've created for it.
    1284              */
    1285             if (dup2(job->outPipe, 1) == -1)
    1286                 Punt("Cannot dup2: %s", strerror(errno));
    1287         } else {
    1288             /*
    1289              * We're capturing output in a file, so we duplicate the
    1290              * descriptor to the temporary file into the standard
    1291              * output.
    1292              */
    1293             if (dup2(job->outFd, 1) == -1)
    1294                 Punt("Cannot dup2: %s", strerror(errno));
    1295         }
    1296         /*
    1297         * The output channels are marked close on exec. This bit was
    1298         * duplicated by the dup2 (on some systems), so we have to clear
    1299         * it before routing the shell's error output to the same place as
    1300         * its standard output.
    1301         */
    1302         (void) fcntl(1, F_SETFD, 0);
    1303         if (dup2(1, 2) == -1)
    1304             Punt("Cannot dup2: %s", strerror(errno));
     1657        /*
     1658        * Must duplicate the input stream down to the child's input and
     1659        * reset it to the beginning (again). Since the stream was marked
     1660        * close-on-exec, we must clear that bit in the new input.
     1661        */
     1662        if (dup2(FILENO(job->cmdFILE), 0) == -1)
     1663            Punt("Cannot dup2: %s", strerror(errno));
     1664        (void) fcntl(0, F_SETFD, 0);
     1665        (void) lseek(0, 0, SEEK_SET);
     1666
     1667        if (usePipes) {
     1668            /*
     1669             * Set up the child's output to be routed through the pipe
     1670             * we've created for it.
     1671             */
     1672            if (dup2(job->outPipe, STDOUT_FILENO) == -1)
     1673                Punt("Cannot dup2: %s", strerror(errno));
     1674        } else {
     1675            /*
     1676             * We're capturing output in a file, so we duplicate the
     1677             * descriptor to the temporary file into the standard
     1678             * output.
     1679             */
     1680            if (dup2(job->outFd, STDOUT_FILENO) == -1)
     1681                Punt("Cannot dup2: %s", strerror(errno));
     1682        }
     1683        /*
     1684        * The output channels are marked close on exec. This bit was
     1685        * duplicated by the dup2 (on some systems), so we have to clear
     1686        * it before routing the shell's error output to the same place as
     1687        * its standard output.
     1688        */
     1689        (void) fcntl(1, F_SETFD, 0);
     1690        if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1)
     1691            Punt("Cannot dup2: %s", strerror(errno));
    13051692
    13061693#ifdef USE_PGRP
    1307         /*
    1308         * We want to switch the child into a different process family so
    1309         * we can kill it and all its descendants in one fell swoop,
    1310         * by killing its process family, but not commit suicide.
    1311         */
     1694        /*
     1695        * We want to switch the child into a different process family so
     1696        * we can kill it and all its descendants in one fell swoop,
     1697        * by killing its process family, but not commit suicide.
     1698        */
    13121699# if defined(SYSV)
    1313         (void) setsid();
     1700        (void) setsid();
    13141701# else
    1315         (void) setpgid(0, getpid());
     1702        (void) setpgid(0, getpid());
    13161703# endif
    13171704#endif /* USE_PGRP */
    13181705
    13191706#ifdef REMOTE
    1320         if (job->flags & JOB_REMOTE) {
    1321             Rmt_Exec(shellPath, argv, FALSE);
    1322         } else
     1707        if (job->flags & JOB_REMOTE) {
     1708            Rmt_Exec(shellPath, argv, FALSE);
     1709        } else
    13231710#endif /* REMOTE */
    13241711#ifdef KMK
    1325            (void) execv(argv[0], argv);
     1712           (void) execv(argv[0], argv);
    13261713#else
    1327            (void) execv(shellPath, argv);
    1328 #endif
    1329 
    1330         (void) write(2, "Could not execute shell\n",
    1331                      sizeof("Could not execute shell"));
    1332         _exit(1);
     1714           (void) execv(shellPath, argv);
     1715#endif
     1716
     1717        (void) write(2, "Could not execute shell\n",
     1718                     sizeof("Could not execute shell"));
     1719        _exit(1);
    13331720    } else {
    13341721#ifdef REMOTE
    1335         long omask = sigblock(sigmask(SIGCHLD));
    1336 #endif
    1337         job->pid = cpid;
    1338 
    1339         if (usePipes && (job->flags & JOB_FIRST) ) {
    1340             /*
    1341              * The first time a job is run for a node, we set the current
    1342              * position in the buffer to the beginning and mark another
    1343              * stream to watch in the outputs mask
    1344              */
    1345             job->curPos = 0;
     1722        long omask = sigblock(sigmask(SIGCHLD));
     1723#endif
     1724        job->pid = cpid;
     1725
     1726#ifdef USE_PIPES
     1727        if (usePipes && (job->flags & JOB_FIRST) ) {
     1728            /*
     1729             * The first time a job is run for a node, we set the current
     1730             * position in the buffer to the beginning and mark another
     1731             * stream to watch in the outputs mask
     1732             */
     1733            job->curPos = 0;
    13461734
    13471735#ifdef RMT_WILL_WATCH
    1348             Rmt_Watch(job->inPipe, JobLocalInput, job);
     1736            Rmt_Watch(job->inPipe, JobLocalInput, job);
    13491737#else
    1350             FD_SET(job->inPipe, &outputs);
     1738            FD_SET(job->inPipe, &outputs);
    13511739#endif /* RMT_WILL_WATCH */
    1352         }
    1353 
    1354         if (job->flags & JOB_REMOTE) {
     1740        }
     1741#endif /* USE_PIPES */
     1742
     1743        if (job->flags & JOB_REMOTE) {
    13551744#ifndef REMOTE
    1356             job->rmtID = 0;
     1745            job->rmtID = 0;
    13571746#else
    1358             job->rmtID = Rmt_LastID(job->pid);
     1747            job->rmtID = Rmt_LastID(job->pid);
    13591748#endif /* REMOTE */
    1360         } else {
    1361             nLocal += 1;
    1362             /*
    1363              * XXX: Used to not happen if REMOTE. Why?
    1364              */
    1365             if (job->cmdFILE != NULL && job->cmdFILE != stdout) {
    1366                 (void) fclose(job->cmdFILE);
    1367                 job->cmdFILE = NULL;
    1368             }
    1369         }
     1749        } else {
     1750            nLocal += 1;
     1751            /*
     1752             * XXX: Used to not happen if REMOTE. Why?
     1753             */
     1754            if (job->cmdFILE != NULL && job->cmdFILE != stdout) {
     1755                (void) fclose(job->cmdFILE);
     1756                job->cmdFILE = NULL;
     1757            }
     1758        }
    13701759#ifdef REMOTE
    1371         (void) sigsetmask(omask);
     1760        (void) sigsetmask(omask);
    13721761#endif
    13731762    }
     
    13821771    (void) Lst_AtEnd(jobs, (ClientData)job);
    13831772    if (nJobs == maxJobs) {
    1384         jobFull = TRUE;
    1385     }
     1773        jobFull = TRUE;
     1774    }
     1775#endif /* USE_KLIB */
    13861776}
    13871777
     
    13901780 *-----------------------------------------------------------------------
    13911781 * JobMakeArgv --
    1392  *      Create the argv needed to execute the shell for a given job.
     1782 *      Create the argv needed to execute the shell for a given job.
    13931783 *
    13941784 *
     
    14011791static void
    14021792JobMakeArgv(job, argv)
    1403     Job           *job;
    1404     char          **argv;
     1793    Job           *job;
     1794    char          **argv;
    14051795{
    1406     int           argc;
    1407     static char   args[10];     /* For merged arguments */
    1408 
    1409 #ifndef _PATH_DEFSHELLDIR
    1410     /* @todo! */
    1411     argv[0] = "c:\\os2\\cmd.exe";
    1412     argc = 1;
    1413 #else
     1796#ifdef KMK
     1797    int           argc;
     1798
     1799    argv[0] = argv0;
     1800    argv[1] = "--kShell";
     1801    argc = 2;
     1802    if (!(job->flags & JOB_IGNERR))
     1803        argv[argc++] = "-e";
     1804    if (!(job->flags & JOB_SILENT))
     1805        argv[argc++] = "-v";
     1806    argv[argc] = NULL;
     1807
     1808#else /* not kMk */
     1809    int           argc;
     1810    static char   args[10];     /* For merged arguments */
     1811
    14141812    argv[0] = shellName;
    14151813    argc = 1;
    14161814
    14171815    if ((commandShell->exit && (*commandShell->exit != '-')) ||
    1418         (commandShell->echo && (*commandShell->echo != '-')))
     1816        (commandShell->echo && (*commandShell->echo != '-')))
    14191817    {
    1420         /*
    1421         * At least one of the flags doesn't have a minus before it, so
    1422         * merge them together. Have to do this because the *(&(@*#*&#$#
    1423         * Bourne shell thinks its second argument is a file to source.
    1424         * Grrrr. Note the ten-character limitation on the combined arguments.
    1425         */
    1426         (void)sprintf(args, "-%s%s",
    1427                       ((job->flags & JOB_IGNERR) ? "" :
    1428                        (commandShell->exit ? commandShell->exit : "")),
    1429                       ((job->flags & JOB_SILENT) ? "" :
    1430                        (commandShell->echo ? commandShell->echo : "")));
    1431 
    1432         if (args[1]) {
    1433             argv[argc] = args;
    1434             argc++;
    1435         }
     1818        /*
     1819        * At least one of the flags doesn't have a minus before it, so
     1820        * merge them together. Have to do this because the *(&(@*#*&#$#
     1821        * Bourne shell thinks its second argument is a file to source.
     1822        * Grrrr. Note the ten-character limitation on the combined arguments.
     1823        */
     1824        (void)sprintf(args, "-%s%s",
     1825                      ((job->flags & JOB_IGNERR) ? "" :
     1826                       (commandShell->exit ? commandShell->exit : "")),
     1827                      ((job->flags & JOB_SILENT) ? "" :
     1828                       (commandShell->echo ? commandShell->echo : "")));
     1829
     1830        if (args[1]) {
     1831            argv[argc] = args;
     1832            argc++;
     1833        }
    14361834    } else {
    1437         if (!(job->flags & JOB_IGNERR) && commandShell->exit) {
    1438             argv[argc] = commandShell->exit;
    1439             argc++;
    1440         }
    1441         if (!(job->flags & JOB_SILENT) && commandShell->echo) {
    1442             argv[argc] = commandShell->echo;
    1443             argc++;
    1444         }
     1835        if (!(job->flags & JOB_IGNERR) && commandShell->exit) {
     1836            argv[argc] = commandShell->exit;
     1837            argc++;
     1838        }
     1839        if (!(job->flags & JOB_SILENT) && commandShell->echo) {
     1840            argv[argc] = commandShell->echo;
     1841            argc++;
     1842        }
    14451843    }
    14461844    argv[argc] = NULL;
    1447 #endif
     1845#endif /* KMK */
    14481846}
    14491847
    14501848
     1849#ifdef SIGCONT
    14511850/*-
    14521851 *-----------------------------------------------------------------------
    14531852 * JobRestart --
    1454  *      Restart a job that stopped for some reason.
     1853 *      Restart a job that stopped for some reason.
    14551854 *
    14561855 * Results:
    1457  *      None.
     1856 *      None.
    14581857 *
    14591858 * Side Effects:
    1460  *      jobFull will be set if the job couldn't be run.
     1859 *      jobFull will be set if the job couldn't be run.
    14611860 *
    14621861 *-----------------------------------------------------------------------
     
    14641863static void
    14651864JobRestart(job)
    1466     Job           *job;         /* Job to restart */
     1865    Job           *job;         /* Job to restart */
    14671866{
    14681867#ifdef REMOTE
     
    14711870
    14721871    if (job->flags & JOB_REMIGRATE) {
    1473         if (
     1872        if (
    14741873#ifdef REMOTE
    1475             verboseRemigrates ||
    1476 #endif
    1477             DEBUG(JOB)) {
    1478            (void) fprintf(stdout, "*** remigrating %x(%s)\n",
    1479                            job->pid, job->node->name);
    1480            (void) fflush(stdout);
    1481         }
     1874            verboseRemigrates ||
     1875#endif
     1876            DEBUG(JOB)) {
     1877           (void) fprintf(stdout, "*** remigrating %x(%s)\n",
     1878                           job->pid, job->node->name);
     1879           (void) fflush(stdout);
     1880        }
    14821881
    14831882#ifdef REMOTE
    1484         if (!Rmt_ReExport(job->pid, job->node, &host)) {
    1485             if (verboseRemigrates || DEBUG(JOB)) {
    1486                 (void) fprintf(stdout, "*** couldn't migrate...\n");
    1487                 (void) fflush(stdout);
    1488             }
    1489 #endif
    1490             if (nLocal != maxLocal) {
    1491                 /*
    1492                 * Job cannot be remigrated, but there's room on the local
    1493                 * machine, so resume the job and note that another
    1494                 * local job has started.
    1495                 */
    1496                 if (
     1883        if (!Rmt_ReExport(job->pid, job->node, &host)) {
     1884            if (verboseRemigrates || DEBUG(JOB)) {
     1885                (void) fprintf(stdout, "*** couldn't migrate...\n");
     1886                (void) fflush(stdout);
     1887            }
     1888#endif
     1889            if (nLocal != maxLocal) {
     1890                /*
     1891                * Job cannot be remigrated, but there's room on the local
     1892                * machine, so resume the job and note that another
     1893                * local job has started.
     1894                */
     1895                if (
    14971896#ifdef REMOTE
    1498                     verboseRemigrates ||
    1499 #endif
    1500                     DEBUG(JOB)) {
    1501                     (void) fprintf(stdout, "*** resuming on local machine\n");
    1502                     (void) fflush(stdout);
    1503                 }
    1504                 KILL(job->pid, SIGCONT);
    1505                 nLocal +=1;
     1897                    verboseRemigrates ||
     1898#endif
     1899                    DEBUG(JOB)) {
     1900                    (void) fprintf(stdout, "*** resuming on local machine\n");
     1901                    (void) fflush(stdout);
     1902                }
     1903                KILL(job->pid, SIGCONT);
     1904                nLocal +=1;
    15061905#ifdef REMOTE
    1507                 job->flags &= ~(JOB_REMIGRATE|JOB_RESUME|JOB_REMOTE);
    1508                 job->flags |= JOB_CONTINUING;
     1906                job->flags &= ~(JOB_REMIGRATE|JOB_RESUME|JOB_REMOTE);
     1907                job->flags |= JOB_CONTINUING;
    15091908#else
    1510                 job->flags &= ~(JOB_REMIGRATE|JOB_RESUME);
    1511 #endif
    1512         } else {
    1513                 /*
    1514                 * Job cannot be restarted. Mark the table as full and
    1515                 * place the job back on the list of stopped jobs.
    1516                 */
    1517                 if (
     1909                job->flags &= ~(JOB_REMIGRATE|JOB_RESUME);
     1910#endif
     1911        } else {
     1912                /*
     1913                * Job cannot be restarted. Mark the table as full and
     1914                * place the job back on the list of stopped jobs.
     1915                */
     1916                if (
    15181917#ifdef REMOTE
    1519                     verboseRemigrates ||
    1520 #endif
    1521                     DEBUG(JOB)) {
    1522                    (void) fprintf(stdout, "*** holding\n");
    1523                    (void) fflush(stdout);
    1524                 }
    1525                 (void)Lst_AtFront(stoppedJobs, (ClientData)job);
    1526                 jobFull = TRUE;
    1527                 if (DEBUG(JOB)) {
    1528                    (void) fprintf(stdout, "Job queue is full.\n");
    1529                    (void) fflush(stdout);
    1530                 }
    1531                 return;
    1532             }
     1918                    verboseRemigrates ||
     1919#endif
     1920                    DEBUG(JOB)) {
     1921                   (void) fprintf(stdout, "*** holding\n");
     1922                   (void) fflush(stdout);
     1923                }
     1924                (void)Lst_AtFront(stoppedJobs, (ClientData)job);
     1925                jobFull = TRUE;
     1926                if (DEBUG(JOB)) {
     1927                   (void) fprintf(stdout, "Job queue is full.\n");
     1928                   (void) fflush(stdout);
     1929                }
     1930                return;
     1931            }
    15331932#ifdef REMOTE
    1534         } else {
    1535             /*
    1536              * Clear out the remigrate and resume flags. Set the continuing
    1537              * flag so we know later on that the process isn't exiting just
    1538              * because of a signal.
    1539              */
    1540             job->flags &= ~(JOB_REMIGRATE|JOB_RESUME);
    1541             job->flags |= JOB_CONTINUING;
    1542             job->rmtID = host;
    1543         }
    1544 #endif
    1545 
    1546         (void)Lst_AtEnd(jobs, (ClientData)job);
    1547         nJobs += 1;
    1548         if (nJobs == maxJobs) {
    1549             jobFull = TRUE;
    1550             if (DEBUG(JOB)) {
    1551                 (void) fprintf(stdout, "Job queue is full.\n");
    1552                 (void) fflush(stdout);
    1553             }
    1554         }
     1933        } else {
     1934            /*
     1935             * Clear out the remigrate and resume flags. Set the continuing
     1936             * flag so we know later on that the process isn't exiting just
     1937             * because of a signal.
     1938             */
     1939            job->flags &= ~(JOB_REMIGRATE|JOB_RESUME);
     1940            job->flags |= JOB_CONTINUING;
     1941            job->rmtID = host;
     1942        }
     1943#endif
     1944
     1945        (void)Lst_AtEnd(jobs, (ClientData)job);
     1946        nJobs += 1;
     1947        if (nJobs == maxJobs) {
     1948            jobFull = TRUE;
     1949            if (DEBUG(JOB)) {
     1950                (void) fprintf(stdout, "Job queue is full.\n");
     1951                (void) fflush(stdout);
     1952            }
     1953        }
    15551954    } else if (job->flags & JOB_RESTART) {
    1556         /*
    1557         * Set up the control arguments to the shell. This is based on the
    1558         * flags set earlier for this job. If the JOB_IGNERR flag is clear,
    1559         * the 'exit' flag of the commandShell is used to cause it to exit
    1560         * upon receiving an error. If the JOB_SILENT flag is clear, the
    1561         * 'echo' flag of the commandShell is used to get it to start echoing
    1562         * as soon as it starts processing commands.
    1563         */
    1564         char      *argv[4];
    1565 
    1566         JobMakeArgv(job, argv);
    1567 
    1568         if (DEBUG(JOB)) {
    1569             (void) fprintf(stdout, "Restarting %s...", job->node->name);
    1570             (void) fflush(stdout);
    1571         }
     1955        /*
     1956        * Set up the control arguments to the shell. This is based on the
     1957        * flags set earlier for this job. If the JOB_IGNERR flag is clear,
     1958        * the 'exit' flag of the commandShell is used to cause it to exit
     1959        * upon receiving an error. If the JOB_SILENT flag is clear, the
     1960        * 'echo' flag of the commandShell is used to get it to start echoing
     1961        * as soon as it starts processing commands.
     1962        */
     1963        char      *argv[4];
     1964
     1965        JobMakeArgv(job, argv);
     1966
     1967        if (DEBUG(JOB)) {
     1968            (void) fprintf(stdout, "Restarting %s...", job->node->name);
     1969            (void) fflush(stdout);
     1970        }
    15721971#ifdef REMOTE
    1573         if ((job->node->type&OP_NOEXPORT) ||
    1574             (nLocal < maxLocal && runLocalFirst)
     1972        if ((job->node->type&OP_NOEXPORT) ||
     1973            (nLocal < maxLocal && runLocalFirst)
    15751974# ifdef RMT_NO_EXEC
    1576             || !Rmt_Export(shellPath, argv, job)
     1975            || !Rmt_Export(shellPath, argv, job)
    15771976# else
    1578             || !Rmt_Begin(shellPath, argv, job->node)
     1977            || !Rmt_Begin(shellPath, argv, job->node)
    15791978# endif
    15801979#endif
    1581         {
    1582             if (((nLocal >= maxLocal) && !(job->flags & JOB_SPECIAL))) {
    1583                 /*
    1584                 * Can't be exported and not allowed to run locally -- put it
    1585                 * back on the hold queue and mark the table full
    1586                 */
    1587                 if (DEBUG(JOB)) {
    1588                     (void) fprintf(stdout, "holding\n");
    1589                     (void) fflush(stdout);
    1590                 }
    1591                 (void)Lst_AtFront(stoppedJobs, (ClientData)job);
    1592                 jobFull = TRUE;
    1593                 if (DEBUG(JOB)) {
    1594                     (void) fprintf(stdout, "Job queue is full.\n");
    1595                     (void) fflush(stdout);
    1596                 }
    1597                 return;
    1598             } else {
    1599                 /*
    1600                 * Job may be run locally.
    1601                 */
    1602                 if (DEBUG(JOB)) {
    1603                     (void) fprintf(stdout, "running locally\n");
    1604                     (void) fflush(stdout);
    1605                 }
    1606                 job->flags &= ~JOB_REMOTE;
    1607             }
    1608         }
     1980        {
     1981            if (((nLocal >= maxLocal) && !(job->flags & JOB_SPECIAL))) {
     1982                /*
     1983                * Can't be exported and not allowed to run locally -- put it
     1984                * back on the hold queue and mark the table full
     1985                */
     1986                if (DEBUG(JOB)) {
     1987                    (void) fprintf(stdout, "holding\n");
     1988                    (void) fflush(stdout);
     1989                }
     1990                (void)Lst_AtFront(stoppedJobs, (ClientData)job);
     1991                jobFull = TRUE;
     1992                if (DEBUG(JOB)) {
     1993                    (void) fprintf(stdout, "Job queue is full.\n");
     1994                    (void) fflush(stdout);
     1995                }
     1996                return;
     1997            } else {
     1998                /*
     1999                * Job may be run locally.
     2000                */
     2001                if (DEBUG(JOB)) {
     2002                    (void) fprintf(stdout, "running locally\n");
     2003                    (void) fflush(stdout);
     2004                }
     2005                job->flags &= ~JOB_REMOTE;
     2006            }
     2007        }
    16092008#ifdef REMOTE
    1610         else {
    1611             /*
    1612              * Can be exported. Hooray!
    1613              */
    1614             if (DEBUG(JOB)) {
    1615                 (void) fprintf(stdout, "exporting\n");
    1616                 (void) fflush(stdout);
    1617             }
    1618             job->flags |= JOB_REMOTE;
    1619         }
    1620 #endif
    1621         JobExec(job, argv);
     2009        else {
     2010            /*
     2011             * Can be exported. Hooray!
     2012             */
     2013            if (DEBUG(JOB)) {
     2014                (void) fprintf(stdout, "exporting\n");
     2015                (void) fflush(stdout);
     2016            }
     2017            job->flags |= JOB_REMOTE;
     2018        }
     2019#endif
     2020        JobExec(job, argv);
    16222021    } else {
    1623         /*
    1624         * The job has stopped and needs to be restarted. Why it stopped,
    1625         * we don't know...
    1626         */
    1627         if (DEBUG(JOB)) {
    1628            (void) fprintf(stdout, "Resuming %s...", job->node->name);
    1629            (void) fflush(stdout);
    1630         }
    1631         if (((job->flags & JOB_REMOTE) ||
    1632             (nLocal < maxLocal) ||
     2022        /*
     2023        * The job has stopped and needs to be restarted. Why it stopped,
     2024        * we don't know...
     2025        */
     2026        if (DEBUG(JOB)) {
     2027           (void) fprintf(stdout, "Resuming %s...", job->node->name);
     2028           (void) fflush(stdout);
     2029        }
     2030        if (((job->flags & JOB_REMOTE) ||
     2031            (nLocal < maxLocal) ||
    16332032#ifdef REMOTE
    1634             (((job->flags & JOB_SPECIAL) &&
    1635               (job->node->type & OP_NOEXPORT)) &&
    1636              (maxLocal == 0))) &&
     2033            (((job->flags & JOB_SPECIAL) &&
     2034              (job->node->type & OP_NOEXPORT)) &&
     2035             (maxLocal == 0))) &&
    16372036#else
    1638             ((job->flags & JOB_SPECIAL) &&
    1639              (maxLocal == 0))) &&
    1640 #endif
    1641            (nJobs != maxJobs))
    1642         {
    1643             /*
    1644              * If the job is remote, it's ok to resume it as long as the
    1645              * maximum concurrency won't be exceeded. If it's local and
    1646              * we haven't reached the local concurrency limit already (or the
    1647              * job must be run locally and maxLocal is 0), it's also ok to
    1648              * resume it.
    1649              */
    1650             Boolean error;
    1651             int status;
     2037            ((job->flags & JOB_SPECIAL) &&
     2038             (maxLocal == 0))) &&
     2039#endif
     2040           (nJobs != maxJobs))
     2041        {
     2042            /*
     2043             * If the job is remote, it's ok to resume it as long as the
     2044             * maximum concurrency won't be exceeded. If it's local and
     2045             * we haven't reached the local concurrency limit already (or the
     2046             * job must be run locally and maxLocal is 0), it's also ok to
     2047             * resume it.
     2048             */
     2049            Boolean error;
     2050            int status;
    16522051
    16532052#ifdef RMT_WANTS_SIGNALS
    1654             if (job->flags & JOB_REMOTE) {
    1655                 error = !Rmt_Signal(job, SIGCONT);
    1656             } else
    1657 #endif  /* RMT_WANTS_SIGNALS */
    1658                 error = (KILL(job->pid, SIGCONT) != 0);
    1659 
    1660             if (!error) {
    1661                 /*
    1662                 * Make sure the user knows we've continued the beast and
    1663                 * actually put the thing in the job table.
    1664                 */
    1665                 job->flags |= JOB_CONTINUING;
    1666                 W_SETTERMSIG(&status, SIGCONT);
    1667                 JobFinish(job, &status);
    1668 
    1669                 job->flags &= ~(JOB_RESUME|JOB_CONTINUING);
    1670                 if (DEBUG(JOB)) {
    1671                    (void) fprintf(stdout, "done\n");
    1672                    (void) fflush(stdout);
    1673                 }
    1674             } else {
    1675                 Error("couldn't resume %s: %s",
    1676                     job->node->name, strerror(errno));
    1677                 status = 0;
    1678                 W_SETEXITSTATUS(&status, 1);
    1679                 JobFinish(job, &status);
    1680             }
    1681         } else {
    1682             /*
    1683              * Job cannot be restarted. Mark the table as full and
    1684              * place the job back on the list of stopped jobs.
    1685              */
    1686             if (DEBUG(JOB)) {
    1687                 (void) fprintf(stdout, "table full\n");
    1688                 (void) fflush(stdout);
    1689             }
    1690             (void) Lst_AtFront(stoppedJobs, (ClientData)job);
    1691             jobFull = TRUE;
    1692             if (DEBUG(JOB)) {
    1693                 (void) fprintf(stdout, "Job queue is full.\n");
    1694                 (void) fflush(stdout);
    1695             }
    1696         }
     2053            if (job->flags & JOB_REMOTE) {
     2054                error = !Rmt_Signal(job, SIGCONT);
     2055            } else
     2056#endif  /* RMT_WANTS_SIGNALS */
     2057                error = (KILL(job->pid, SIGCONT) != 0);
     2058
     2059            if (!error) {
     2060                /*
     2061                * Make sure the user knows we've continued the beast and
     2062                * actually put the thing in the job table.
     2063                */
     2064                job->flags |= JOB_CONTINUING;
     2065                W_SETTERMSIG(&status, SIGCONT);
     2066                JobFinish(job, &status);
     2067
     2068                job->flags &= ~(JOB_RESUME|JOB_CONTINUING);
     2069                if (DEBUG(JOB)) {
     2070                   (void) fprintf(stdout, "done\n");
     2071                   (void) fflush(stdout);
     2072                }
     2073            } else {
     2074                Error("couldn't resume %s: %s",
     2075                    job->node->name, strerror(errno));
     2076                status = 0;
     2077                W_SETEXITSTATUS(&status, 1);
     2078                JobFinish(job, &status);
     2079            }
     2080        } else {
     2081            /*
     2082             * Job cannot be restarted. Mark the table as full and
     2083             * place the job back on the list of stopped jobs.
     2084             */
     2085            if (DEBUG(JOB)) {
     2086                (void) fprintf(stdout, "table full\n");
     2087                (void) fflush(stdout);
     2088            }
     2089            (void) Lst_AtFront(stoppedJobs, (ClientData)job);
     2090            jobFull = TRUE;
     2091            if (DEBUG(JOB)) {
     2092                (void) fprintf(stdout, "Job queue is full.\n");
     2093                (void) fflush(stdout);
     2094            }
     2095        }
    16972096    }
    16982097}
     2098#endif
    16992099
    17002100/*-
    17012101 *-----------------------------------------------------------------------
    17022102 * JobStart  --
    1703  *      Start a target-creation process going for the target described
    1704  *      by the graph node gn.
     2103 *      Start a target-creation process going for the target described
     2104 *      by the graph node gn.
    17052105 *
    17062106 * Results:
    1707  *      JOB_ERROR if there was an error in the commands, JOB_FINISHED
    1708  *      if there isn't actually anything left to do for the job and
    1709  *      JOB_RUNNING if the job has been started.
     2107 *      JOB_ERROR if there was an error in the commands, JOB_FINISHED
     2108 *      if there isn't actually anything left to do for the job and
     2109 *      JOB_RUNNING if the job has been started.
    17102110 *
    17112111 * Side Effects:
    1712  *      A new Job node is created and added to the list of running
    1713  *      jobs. PMake is forked and a child shell created.
     2112 *      A new Job node is created and added to the list of running
     2113 *      jobs. PMake is forked and a child shell created.
    17142114 *-----------------------------------------------------------------------
    17152115 */
    17162116static int
    17172117JobStart(gn, flags, previous)
    1718     GNode         *gn;        /* target to create */
    1719     int            flags;      /* flags for the job to override normal ones.
    1720                                * e.g. JOB_SPECIAL or JOB_IGNDOTS */
    1721     Job           *previous;  /* The previous Job structure for this node,
    1722                                * if any. */
     2118    GNode         *gn;        /* target to create */
     2119    int            flags;      /* flags for the job to override normal ones.
     2120                               * e.g. JOB_SPECIAL or JOB_IGNDOTS */
     2121    Job           *previous;  /* The previous Job structure for this node,
     2122                               * if any. */
    17232123{
    17242124    register Job  *job;       /* new job descriptor */
    1725     char          *argv[4];   /* Argument vector to shell */
    1726     Boolean       cmdsOK;     /* true if the nodes commands were all right */
    1727     Boolean       local;      /* Set true if the job was run locally */
    1728     Boolean       noExec;     /* Set true if we decide not to run the job */
    1729     int           tfd;        /* File descriptor for temp file */
     2125    char          *argv[4];   /* Argument vector to shell */
     2126    Boolean       cmdsOK;     /* true if the nodes commands were all right */
     2127    Boolean       local;      /* Set true if the job was run locally */
     2128    Boolean       noExec;     /* Set true if we decide not to run the job */
     2129    int           tfd;        /* File descriptor for temp file */
    17302130
    17312131    if (previous != NULL) {
    1732         previous->flags &= ~(JOB_FIRST|JOB_IGNERR|JOB_SILENT|JOB_REMOTE);
    1733         job = previous;
     2132        previous->flags &= ~(JOB_FIRST|JOB_IGNERR|JOB_SILENT|JOB_REMOTE);
     2133        job = previous;
    17342134    } else {
    1735         job = (Job *) emalloc(sizeof(Job));
    1736         if (job == NULL) {
    1737             Punt("JobStart out of memory");
    1738         }
    1739         flags |= JOB_FIRST;
     2135        job = (Job *) emalloc(sizeof(Job));
     2136        if (job == NULL) {
     2137            Punt("JobStart out of memory");
     2138        }
     2139        flags |= JOB_FIRST;
    17402140    }
    17412141
     
    17502150    job->flags = 0;
    17512151    if (Targ_Ignore(gn)) {
    1752         job->flags |= JOB_IGNERR;
     2152        job->flags |= JOB_IGNERR;
    17532153    }
    17542154    if (Targ_Silent(gn)) {
    1755         job->flags |= JOB_SILENT;
     2155        job->flags |= JOB_SILENT;
    17562156    }
    17572157    job->flags |= flags;
     
    17622162     */
    17632163    if (!compatMake && job->flags & JOB_FIRST) {
    1764         cmdsOK = Job_CheckCommands(gn, Error);
     2164        cmdsOK = Job_CheckCommands(gn, Error);
    17652165    } else {
    1766         cmdsOK = TRUE;
     2166        cmdsOK = TRUE;
    17672167    }
    17682168
     
    17742174     */
    17752175    if ((gn->type & OP_MAKE) || (!noExecute && !touchFlag)) {
    1776         /*
    1777         * We're serious here, but if the commands were bogus, we're
    1778         * also dead...
    1779         */
    1780         if (!cmdsOK) {
    1781             DieHorribly();
    1782         }
    1783 
    1784         (void) strcpy(tfile, TMPPAT);
    1785         if ((tfd = mkstemp(tfile)) == -1)
    1786             Punt("Cannot create temp file: %s", strerror(errno));
    1787         job->cmdFILE = fdopen(tfd, "w+");
    1788         eunlink(tfile);
    1789         if (job->cmdFILE == NULL) {
    1790             close(tfd);
    1791             Punt("Could not open %s", tfile);
    1792         }
    1793         (void) fcntl(FILENO(job->cmdFILE), F_SETFD, 1);
    1794         /*
    1795         * Send the commands to the command file, flush all its buffers then
    1796         * rewind and remove the thing.
    1797         */
    1798         noExec = FALSE;
    1799 
    1800         /*
    1801         * used to be backwards; replace when start doing multiple commands
    1802         * per shell.
    1803         */
    1804         if (compatMake) {
    1805             /*
    1806              * Be compatible: If this is the first time for this node,
    1807              * verify its commands are ok and open the commands list for
    1808              * sequential access by later invocations of JobStart.
    1809              * Once that is done, we take the next command off the list
    1810              * and print it to the command file. If the command was an
    1811              * ellipsis, note that there's nothing more to execute.
    1812              */
    1813             if ((job->flags&JOB_FIRST) && (Lst_Open(gn->commands) != SUCCESS)){
    1814                 cmdsOK = FALSE;
    1815             } else {
    1816                 LstNode ln = Lst_Next(gn->commands);
    1817 
    1818                 if ((ln == NILLNODE) ||
    1819                     JobPrintCommand((ClientData) Lst_Datum(ln),
    1820                                     (ClientData) job))
    1821                 {
    1822                     noExec = TRUE;
    1823                     Lst_Close(gn->commands);
    1824                 }
    1825                 if (noExec && !(job->flags & JOB_FIRST)) {
    1826                     /*
    1827                      * If we're not going to execute anything, the job
    1828                      * is done and we need to close down the various
    1829                      * file descriptors we've opened for output, then
    1830                      * call JobDoOutput to catch the final characters or
    1831                      * send the file to the screen... Note that the i/o streams
    1832                      * are only open if this isn't the first job.
    1833                      * Note also that this could not be done in
    1834                      * Job_CatchChildren b/c it wasn't clear if there were
    1835                      * more commands to execute or not...
    1836                      */
    1837                     JobClose(job);
    1838                 }
    1839             }
    1840         } else {
    1841             /*
    1842              * We can do all the commands at once. hooray for sanity
    1843              */
    1844             numCommands = 0;
    1845             Lst_ForEach(gn->commands, JobPrintCommand, (ClientData)job);
    1846 
    1847             /*
    1848              * If we didn't print out any commands to the shell script,
    1849              * there's not much point in executing the shell, is there?
    1850              */
    1851             if (numCommands == 0) {
    1852                 noExec = TRUE;
    1853             }
    1854         }
     2176        /*
     2177        * We're serious here, but if the commands were bogus, we're
     2178        * also dead...
     2179        */
     2180        if (!cmdsOK) {
     2181            DieHorribly();
     2182        }
     2183
     2184        (void) strcpy(tfile, TMPPAT);
     2185        if ((tfd = mkstemp(tfile)) == -1)
     2186            Punt("Cannot create temp file: %s", strerror(errno));
     2187        job->cmdFILE = fdopen(tfd, "w+");
     2188        eunlink(tfile);
     2189        if (job->cmdFILE == NULL) {
     2190            close(tfd);
     2191            Punt("Could not open %s", tfile);
     2192        }
     2193        (void) fcntl(FILENO(job->cmdFILE), F_SETFD, 1);
     2194        /*
     2195        * Send the commands to the command file, flush all its buffers then
     2196        * rewind and remove the thing.
     2197        */
     2198        noExec = FALSE;
     2199
     2200        /*
     2201        * used to be backwards; replace when start doing multiple commands
     2202        * per shell.
     2203        */
     2204        if (compatMake) {
     2205            /*
     2206             * Be compatible: If this is the first time for this node,
     2207             * verify its commands are ok and open the commands list for
     2208             * sequential access by later invocations of JobStart.
     2209             * Once that is done, we take the next command off the list
     2210             * and print it to the command file. If the command was an
     2211             * ellipsis, note that there's nothing more to execute.
     2212             */
     2213            if ((job->flags&JOB_FIRST) && (Lst_Open(gn->commands) != SUCCESS)){
     2214                cmdsOK = FALSE;
     2215            } else {
     2216                LstNode ln = Lst_Next(gn->commands);
     2217
     2218                if ((ln == NILLNODE) ||
     2219                    JobPrintCommand((ClientData) Lst_Datum(ln),
     2220                                    (ClientData) job))
     2221                {
     2222                    noExec = TRUE;
     2223                    Lst_Close(gn->commands);
     2224                }
     2225                if (noExec && !(job->flags & JOB_FIRST)) {
     2226                    /*
     2227                     * If we're not going to execute anything, the job
     2228                     * is done and we need to close down the various
     2229                     * file descriptors we've opened for output, then
     2230                     * call JobDoOutput to catch the final characters or
     2231                     * send the file to the screen... Note that the i/o streams
     2232                     * are only open if this isn't the first job.
     2233                     * Note also that this could not be done in
     2234                     * Job_CatchChildren b/c it wasn't clear if there were
     2235                     * more commands to execute or not...
     2236                     */
     2237                    JobClose(job);
     2238                }
     2239            }
     2240        } else {
     2241            /*
     2242             * We can do all the commands at once. hooray for sanity
     2243             */
     2244            numCommands = 0;
     2245            Lst_ForEach(gn->commands, JobPrintCommand, (ClientData)job);
     2246
     2247            /*
     2248             * If we didn't print out any commands to the shell script,
     2249             * there's not much point in executing the shell, is there?
     2250             */
     2251            if (numCommands == 0) {
     2252                noExec = TRUE;
     2253            }
     2254        }
    18552255    } else if (noExecute) {
    1856         /*
    1857         * Not executing anything -- just print all the commands to stdout
    1858         * in one fell swoop. This will still set up job->tailCmds correctly.
    1859         */
    1860         if (lastNode != gn) {
    1861             MESSAGE(stdout, gn);
    1862             lastNode = gn;
    1863         }
    1864         job->cmdFILE = stdout;
    1865         /*
    1866         * Only print the commands if they're ok, but don't die if they're
    1867         * not -- just let the user know they're bad and keep going. It
    1868         * doesn't do any harm in this case and may do some good.
    1869         */
    1870         if (cmdsOK) {
    1871             Lst_ForEach(gn->commands, JobPrintCommand, (ClientData)job);
    1872         }
    1873         /*
    1874         * Don't execute the shell, thank you.
    1875         */
    1876         noExec = TRUE;
     2256        /*
     2257        * Not executing anything -- just print all the commands to stdout
     2258        * in one fell swoop. This will still set up job->tailCmds correctly.
     2259        */
     2260        if (lastNode != gn) {
     2261            MESSAGE(stdout, gn);
     2262            lastNode = gn;
     2263        }
     2264        job->cmdFILE = stdout;
     2265        /*
     2266        * Only print the commands if they're ok, but don't die if they're
     2267        * not -- just let the user know they're bad and keep going. It
     2268        * doesn't do any harm in this case and may do some good.
     2269        */
     2270        if (cmdsOK) {
     2271            Lst_ForEach(gn->commands, JobPrintCommand, (ClientData)job);
     2272        }
     2273        /*
     2274        * Don't execute the shell, thank you.
     2275        */
     2276        noExec = TRUE;
    18772277    } else {
    1878         /*
    1879         * Just touch the target and note that no shell should be executed.
    1880         * Set cmdFILE to stdout to make life easier. Check the commands, too,
    1881         * but don't die if they're no good -- it does no harm to keep working
    1882         * up the graph.
    1883         */
    1884         job->cmdFILE = stdout;
    1885         Job_Touch(gn, job->flags&JOB_SILENT);
    1886         noExec = TRUE;
     2278        /*
     2279        * Just touch the target and note that no shell should be executed.
     2280        * Set cmdFILE to stdout to make life easier. Check the commands, too,
     2281        * but don't die if they're no good -- it does no harm to keep working
     2282        * up the graph.
     2283        */
     2284        job->cmdFILE = stdout;
     2285        Job_Touch(gn, job->flags&JOB_SILENT);
     2286        noExec = TRUE;
    18872287    }
    18882288
     
    18912291     */
    18922292    if (noExec) {
    1893         /*
    1894         * Unlink and close the command file if we opened one
    1895         */
    1896         if (job->cmdFILE != stdout) {
    1897             if (job->cmdFILE != NULL)
    1898                 (void) fclose(job->cmdFILE);
    1899         } else {
    1900              (void) fflush(stdout);
    1901         }
    1902 
    1903         /*
    1904         * We only want to work our way up the graph if we aren't here because
    1905         * the commands for the job were no good.
    1906         */
    1907         if (cmdsOK) {
    1908             if (aborting == 0) {
    1909                 if (job->tailCmds != NILLNODE) {
    1910                     Lst_ForEachFrom(job->node->commands, job->tailCmds,
    1911                                     JobSaveCommand,
    1912                                    (ClientData)job->node);
    1913                 }
    1914                 job->node->made = MADE;
    1915                 Make_Update(job->node);
    1916             }
    1917             efree((Address)job);
    1918             return(JOB_FINISHED);
    1919         } else {
    1920             efree((Address)job);
    1921             return(JOB_ERROR);
    1922         }
     2293        /*
     2294        * Unlink and close the command file if we opened one
     2295        */
     2296        if (job->cmdFILE != stdout) {
     2297            if (job->cmdFILE != NULL)
     2298                (void) fclose(job->cmdFILE);
     2299        } else {
     2300             (void) fflush(stdout);
     2301        }
     2302
     2303        /*
     2304        * We only want to work our way up the graph if we aren't here because
     2305        * the commands for the job were no good.
     2306        */
     2307        if (cmdsOK) {
     2308            if (aborting == 0) {
     2309                if (job->tailCmds != NILLNODE) {
     2310                    Lst_ForEachFrom(job->node->commands, job->tailCmds,
     2311                                    JobSaveCommand,
     2312                                   (ClientData)job->node);
     2313                }
     2314                job->node->made = MADE;
     2315                Make_Update(job->node);
     2316            }
     2317            efree((Address)job);
     2318            return(JOB_FINISHED);
     2319        } else {
     2320            efree((Address)job);
     2321            return(JOB_ERROR);
     2322        }
    19232323    } else {
    1924         (void) fflush(job->cmdFILE);
     2324        (void) fflush(job->cmdFILE);
    19252325    }
    19262326
     
    19372337     */
    19382338    if (!compatMake || (job->flags & JOB_FIRST)) {
    1939         if (usePipes) {
    1940             int fd[2];
    1941             if (pipe(fd) == -1)
    1942                 Punt("Cannot create pipe: %s", strerror(errno));
    1943             job->inPipe = fd[0];
    1944             job->outPipe = fd[1];
    1945             (void) fcntl(job->inPipe, F_SETFD, 1);
    1946             (void) fcntl(job->outPipe, F_SETFD, 1);
    1947         } else {
    1948             (void) fprintf(stdout, "Remaking `%s'\n", gn->name);
    1949             (void) fflush(stdout);
    1950             (void) strcpy(job->outFile, TMPPAT);
    1951             if ((job->outFd = mkstemp(job->outFile)) == -1)
    1952                 Punt("cannot create temp file: %s", strerror(errno));
    1953             (void) fcntl(job->outFd, F_SETFD, 1);
    1954         }
     2339#ifdef USE_PIPES
     2340        if (usePipes) {
     2341            int fd[2];
     2342            if (pipe(fd) == -1)
     2343                Punt("Cannot create pipe: %s", strerror(errno));
     2344            job->inPipe = fd[0];
     2345            job->outPipe = fd[1];
     2346            (void) fcntl(job->inPipe, F_SETFD, 1);
     2347            (void) fcntl(job->outPipe, F_SETFD, 1);
     2348        }
     2349        else
     2350#endif /* USE_PIPES */
     2351        {
     2352            (void) fprintf(stdout, "Remaking `%s'\n", gn->name);
     2353            (void) fflush(stdout);
     2354            (void) strcpy(job->outFile, TMPPAT);
     2355            if ((job->outFd = mkstemp(job->outFile)) == -1)
     2356                Punt("cannot create temp file: %s", strerror(errno));
     2357            (void) fcntl(job->outFd, F_SETFD, 1);
     2358        }
    19552359    }
    19562360
     
    19582362    if (!(gn->type & OP_NOEXPORT) && !(runLocalFirst && nLocal < maxLocal)) {
    19592363#ifdef RMT_NO_EXEC
    1960         local = !Rmt_Export(shellPath, argv, job);
     2364        local = !Rmt_Export(shellPath, argv, job);
    19612365#else
    1962         local = !Rmt_Begin(shellPath, argv, job->node);
     2366        local = !Rmt_Begin(shellPath, argv, job->node);
    19632367#endif /* RMT_NO_EXEC */
    1964         if (!local) {
    1965             job->flags |= JOB_REMOTE;
    1966         }
     2368        if (!local) {
     2369            job->flags |= JOB_REMOTE;
     2370        }
    19672371    } else
    19682372#endif
    1969         local = TRUE;
     2373        local = TRUE;
    19702374
    19712375    if (local && (((nLocal >= maxLocal) &&
    1972         !(job->flags & JOB_SPECIAL) &&
     2376        !(job->flags & JOB_SPECIAL) &&
    19732377#ifdef REMOTE
    1974         (!(gn->type & OP_NOEXPORT) || (maxLocal != 0))
     2378        (!(gn->type & OP_NOEXPORT) || (maxLocal != 0))
    19752379#else
    1976         (maxLocal != 0)
    1977 #endif
    1978         )))
     2380        (maxLocal != 0)
     2381#endif
     2382        )))
    19792383    {
    1980         /*
    1981         * The job can only be run locally, but we've hit the limit of
    1982         * local concurrency, so put the job on hold until some other job
    1983         * finishes. Note that the special jobs (.BEGIN, .INTERRUPT and .END)
    1984         * may be run locally even when the local limit has been reached
    1985         * (e.g. when maxLocal == 0), though they will be exported if at
    1986         * all possible. In addition, any target marked with .NOEXPORT will
    1987         * be run locally if maxLocal is 0.
    1988         */
    1989         jobFull = TRUE;
    1990 
    1991         if (DEBUG(JOB)) {
    1992            (void) fprintf(stdout, "Can only run job locally.\n");
    1993            (void) fflush(stdout);
    1994         }
    1995         job->flags |= JOB_RESTART;
    1996         (void) Lst_AtEnd(stoppedJobs, (ClientData)job);
     2384        /*
     2385        * The job can only be run locally, but we've hit the limit of
     2386        * local concurrency, so put the job on hold until some other job
     2387        * finishes. Note that the special jobs (.BEGIN, .INTERRUPT and .END)
     2388        * may be run locally even when the local limit has been reached
     2389        * (e.g. when maxLocal == 0), though they will be exported if at
     2390        * all possible. In addition, any target marked with .NOEXPORT will
     2391        * be run locally if maxLocal is 0.
     2392        */
     2393        jobFull = TRUE;
     2394
     2395        if (DEBUG(JOB)) {
     2396           (void) fprintf(stdout, "Can only run job locally.\n");
     2397           (void) fflush(stdout);
     2398        }
     2399        job->flags |= JOB_RESTART;
     2400        (void) Lst_AtEnd(stoppedJobs, (ClientData)job);
    19972401    } else {
    1998         if ((nLocal >= maxLocal) && local) {
    1999             /*
    2000              * If we're running this job locally as a special case (see above),
    2001              * at least say the table is full.
    2002              */
    2003             jobFull = TRUE;
    2004             if (DEBUG(JOB)) {
    2005                 (void) fprintf(stdout, "Local job queue is full.\n");
    2006                 (void) fflush(stdout);
    2007             }
    2008         }
    2009         JobExec(job, argv);
     2402        if ((nLocal >= maxLocal) && local) {
     2403            /*
     2404             * If we're running this job locally as a special case (see above),
     2405             * at least say the table is full.
     2406             */
     2407            jobFull = TRUE;
     2408            if (DEBUG(JOB)) {
     2409                (void) fprintf(stdout, "Local job queue is full.\n");
     2410                (void) fflush(stdout);
     2411            }
     2412        }
     2413        JobExec(job, argv);
    20102414    }
    20112415    return(JOB_RUNNING);
     
    20222426    #ifndef KMK /* @Todo */
    20232427    if (commandShell->noPrint) {
    2024         ecp = Str_FindSubstring(cp, commandShell->noPrint);
    2025         while (ecp != NULL) {
    2026             if (cp != ecp) {
    2027                 *ecp = '\0';
    2028                 if (msg && job->node != lastNode) {
    2029                     MESSAGE(stdout, job->node);
    2030                     lastNode = job->node;
    2031                 }
    2032                 /*
    2033                 * The only way there wouldn't be a newline after
    2034                 * this line is if it were the last in the buffer.
    2035                 * however, since the non-printable comes after it,
    2036                 * there must be a newline, so we don't print one.
    2037                 */
    2038                 (void) fprintf(stdout, "%s", cp);
    2039                 (void) fflush(stdout);
    2040             }
    2041             cp = ecp + commandShell->noPLen;
    2042             if (cp != endp) {
    2043                 /*
    2044                 * Still more to print, look again after skipping
    2045                 * the whitespace following the non-printable
    2046                 * command....
    2047                 */
    2048                 cp++;
    2049                 while (*cp == ' ' || *cp == '\t' || *cp == '\n') {
    2050                     cp++;
    2051                 }
    2052                 ecp = Str_FindSubstring(cp, commandShell->noPrint);
    2053             } else {
    2054                 return cp;
    2055             }
    2056         }
     2428        ecp = Str_FindSubstring(cp, commandShell->noPrint);
     2429        while (ecp != NULL) {
     2430            if (cp != ecp) {
     2431                *ecp = '\0';
     2432                if (msg && job->node != lastNode) {
     2433                    MESSAGE(stdout, job->node);
     2434                    lastNode = job->node;
     2435                }
     2436                /*
     2437                * The only way there wouldn't be a newline after
     2438                * this line is if it were the last in the buffer.
     2439                * however, since the non-printable comes after it,
     2440                * there must be a newline, so we don't print one.
     2441                */
     2442                (void) fprintf(stdout, "%s", cp);
     2443                (void) fflush(stdout);
     2444            }
     2445            cp = ecp + commandShell->noPLen;
     2446            if (cp != endp) {
     2447                /*
     2448                * Still more to print, look again after skipping
     2449                * the whitespace following the non-printable
     2450                * command....
     2451                */
     2452                cp++;
     2453                while (*cp == ' ' || *cp == '\t' || *cp == '\n') {
     2454                    cp++;
     2455                }
     2456                ecp = Str_FindSubstring(cp, commandShell->noPrint);
     2457            } else {
     2458                return cp;
     2459            }
     2460        }
    20572461    }
    20582462    #endif /*!KMK*/
     
    20632467 *-----------------------------------------------------------------------
    20642468 * JobDoOutput  --
    2065  *      This function is called at different times depending on
    2066  *      whether the user has specified that output is to be collected
    2067  *      via pipes or temporary files. In the former case, we are called
    2068  *      whenever there is something to read on the pipe. We collect more
    2069  *      output from the given job and store it in the job's outBuf. If
    2070  *      this makes up a line, we print it tagged by the job's identifier,
    2071  *      as necessary.
    2072  *      If output has been collected in a temporary file, we open the
    2073  *      file and read it line by line, transfering it to our own
    2074  *      output channel until the file is empty. At which point we
    2075  *      remove the temporary file.
    2076  *      In both cases, however, we keep our figurative eye out for the
    2077  *      'noPrint' line for the shell from which the output came. If
    2078  *      we recognize a line, we don't print it. If the command is not
    2079  *      alone on the line (the character after it is not \0 or \n), we
    2080  *      do print whatever follows it.
     2469 *      This function is called at different times depending on
     2470 *      whether the user has specified that output is to be collected
     2471 *      via pipes or temporary files. In the former case, we are called
     2472 *      whenever there is something to read on the pipe. We collect more
     2473 *      output from the given job and store it in the job's outBuf. If
     2474 *      this makes up a line, we print it tagged by the job's identifier,
     2475 *      as necessary.
     2476 *      If output has been collected in a temporary file, we open the
     2477 *      file and read it line by line, transfering it to our own
     2478 *      output channel until the file is empty. At which point we
     2479 *      remove the temporary file.
     2480 *      In both cases, however, we keep our figurative eye out for the
     2481 *      'noPrint' line for the shell from which the output came. If
     2482 *      we recognize a line, we don't print it. If the command is not
     2483 *      alone on the line (the character after it is not \0 or \n), we
     2484 *      do print whatever follows it.
    20812485 *
    20822486 * Results:
    2083  *      None
     2487 *      None
    20842488 *
    20852489 * Side Effects:
    2086  *      curPos may be shifted as may the contents of outBuf.
     2490 *      curPos may be shifted as may the contents of outBuf.
    20872491 *-----------------------------------------------------------------------
    20882492 */
    20892493STATIC void
    20902494JobDoOutput(job, finish)
    2091     register Job   *job;          /* the job whose output needs printing */
    2092     Boolean        finish;        /* TRUE if this is the last time we'll be
    2093                                    * called for this job */
     2495    register Job   *job;          /* the job whose output needs printing */
     2496    Boolean        finish;        /* TRUE if this is the last time we'll be
     2497                                   * called for this job */
    20942498{
    20952499    Boolean       gotNL = FALSE;  /* true if got a newline */
    2096     Boolean       fbuf;           /* true if our buffer filled up */
    2097     register int  nr;             /* number of bytes read */
    2098     register int  i;              /* auxiliary index into outBuf */
    2099     register int  max;            /* limit for i (end of current data) */
    2100     int           nRead;          /* (Temporary) number of bytes read */
    2101 
    2102     FILE          *oFILE;         /* Stream pointer to shell's output file */
     2500    Boolean       fbuf;           /* true if our buffer filled up */
     2501    register int  nr;             /* number of bytes read */
     2502    register int  i;              /* auxiliary index into outBuf */
     2503    register int  max;            /* limit for i (end of current data) */
     2504    int           nRead;          /* (Temporary) number of bytes read */
     2505
     2506    FILE          *oFILE;         /* Stream pointer to shell's output file */
    21032507    char          inLine[132];
    21042508
    21052509
     2510#ifdef USE_PIPES
    21062511    if (usePipes) {
    2107         /*
    2108         * Read as many bytes as will fit in the buffer.
    2109         */
     2512        /*
     2513        * Read as many bytes as will fit in the buffer.
     2514        */
    21102515end_loop:
    2111         gotNL = FALSE;
    2112         fbuf = FALSE;
    2113 
    2114         nRead = read(job->inPipe, &job->outBuf[job->curPos],
    2115                          JOB_BUFSIZE - job->curPos);
    2116         if (nRead < 0) {
    2117             if (DEBUG(JOB)) {
    2118                 perror("JobDoOutput(piperead)");
    2119             }
    2120             nr = 0;
    2121         } else {
    2122             nr = nRead;
    2123         }
    2124 
    2125         /*
    2126          * If we hit the end-of-file (the job is dead), we must flush its
    2127          * remaining output, so pretend we read a newline if there's any
    2128          * output remaining in the buffer.
    2129          * Also clear the 'finish' flag so we stop looping.
    2130          */
    2131         if ((nr == 0) && (job->curPos != 0)) {
    2132             job->outBuf[job->curPos] = '\n';
    2133             nr = 1;
    2134             finish = FALSE;
    2135         } else if (nr == 0) {
    2136             finish = FALSE;
    2137         }
    2138 
    2139         /*
    2140          * Look for the last newline in the bytes we just got. If there is
    2141          * one, break out of the loop with 'i' as its index and gotNL set
    2142          * TRUE.
    2143          */
    2144         max = job->curPos + nr;
    2145         for (i = job->curPos + nr - 1; i >= job->curPos; i--) {
    2146             if (job->outBuf[i] == '\n') {
    2147                 gotNL = TRUE;
    2148                 break;
    2149             } else if (job->outBuf[i] == '\0') {
    2150                 /*
    2151                  * Why?
    2152                  */
    2153                 job->outBuf[i] = ' ';
    2154             }
    2155         }
    2156 
    2157         if (!gotNL) {
    2158             job->curPos += nr;
    2159             if (job->curPos == JOB_BUFSIZE) {
    2160                 /*
    2161                  * If we've run out of buffer space, we have no choice
    2162                  * but to print the stuff. sigh.
    2163                  */
    2164                 fbuf = TRUE;
    2165                 i = job->curPos;
    2166             }
    2167         }
    2168         if (gotNL || fbuf) {
    2169             /*
    2170              * Need to send the output to the screen. Null terminate it
    2171              * first, overwriting the newline character if there was one.
    2172              * So long as the line isn't one we should filter (according
    2173              * to the shell description), we print the line, preceeded
    2174              * by a target banner if this target isn't the same as the
    2175              * one for which we last printed something.
    2176              * The rest of the data in the buffer are then shifted down
    2177              * to the start of the buffer and curPos is set accordingly.
    2178              */
    2179             job->outBuf[i] = '\0';
    2180             if (i >= job->curPos) {
    2181                 char *cp;
    2182 
    2183                 cp = JobOutput(job, job->outBuf, &job->outBuf[i], FALSE);
    2184 
    2185                 /*
    2186                  * There's still more in that thar buffer. This time, though,
    2187                  * we know there's no newline at the end, so we add one of
    2188                  * our own efree will.
    2189                  */
    2190                 if (*cp != '\0') {
    2191                     if (job->node != lastNode) {
    2192                         MESSAGE(stdout, job->node);
    2193                         lastNode = job->node;
    2194                     }
    2195                     (void) fprintf(stdout, "%s%s", cp, gotNL ? "\n" : "");
    2196                     (void) fflush(stdout);
    2197                 }
    2198             }
    2199             if (i < max - 1) {
    2200                 /* shift the remaining characters down */
    2201                 (void) memcpy(job->outBuf, &job->outBuf[i + 1], max - (i + 1));
    2202                 job->curPos = max - (i + 1);
    2203 
    2204             } else {
    2205                 /*
    2206                  * We have written everything out, so we just start over
    2207                  * from the start of the buffer. No copying. No nothing.
    2208                  */
    2209                 job->curPos = 0;
    2210             }
    2211         }
    2212         if (finish) {
    2213             /*
    2214              * If the finish flag is true, we must loop until we hit
    2215              * end-of-file on the pipe. This is guaranteed to happen
    2216              * eventually since the other end of the pipe is now closed
    2217              * (we closed it explicitly and the child has exited). When
    2218              * we do get an EOF, finish will be set FALSE and we'll fall
    2219              * through and out.
    2220              */
    2221             goto end_loop;
    2222         }
    2223     } else {
    2224         /*
    2225          * We've been called to retrieve the output of the job from the
    2226          * temporary file where it's been squirreled away. This consists of
    2227          * opening the file, reading the output line by line, being sure not
    2228          * to print the noPrint line for the shell we used, then close and
    2229          * remove the temporary file. Very simple.
    2230          *
    2231          * Change to read in blocks and do FindSubString type things as for
    2232          * pipes? That would allow for "@echo -n..."
    2233          */
    2234         oFILE = fopen(job->outFile, "r");
    2235         if (oFILE != NULL) {
    2236             (void) fprintf(stdout, "Results of making %s:\n", job->node->name);
    2237             (void) fflush(stdout);
    2238             while (fgets(inLine, sizeof(inLine), oFILE) != NULL) {
    2239                 register char   *cp, *endp, *oendp;
    2240 
    2241                 cp = inLine;
    2242                 oendp = endp = inLine + strlen(inLine);
    2243                 if (endp[-1] == '\n') {
    2244                     *--endp = '\0';
    2245                 }
    2246                 cp = JobOutput(job, inLine, endp, FALSE);
    2247 
    2248                 /*
    2249                  * There's still more in that thar buffer. This time, though,
    2250                  * we know there's no newline at the end, so we add one of
    2251                  * our own efree will.
    2252                  */
    2253                 (void) fprintf(stdout, "%s", cp);
    2254                 (void) fflush(stdout);
    2255                 if (endp != oendp) {
    2256                     (void) fprintf(stdout, "\n");
    2257                     (void) fflush(stdout);
    2258                 }
    2259             }
    2260             (void) fclose(oFILE);
    2261             (void) eunlink(job->outFile);
    2262         }
     2516        gotNL = FALSE;
     2517        fbuf = FALSE;
     2518
     2519        nRead = read(job->inPipe, &job->outBuf[job->curPos],
     2520                         JOB_BUFSIZE - job->curPos);
     2521        if (nRead < 0) {
     2522            if (DEBUG(JOB)) {
     2523                perror("JobDoOutput(piperead)");
     2524            }
     2525            nr = 0;
     2526        } else {
     2527            nr = nRead;
     2528        }
     2529
     2530        /*
     2531         * If we hit the end-of-file (the job is dead), we must flush its
     2532         * remaining output, so pretend we read a newline if there's any
     2533         * output remaining in the buffer.
     2534         * Also clear the 'finish' flag so we stop looping.
     2535         */
     2536        if ((nr == 0) && (job->curPos != 0)) {
     2537            job->outBuf[job->curPos] = '\n';
     2538            nr = 1;
     2539            finish = FALSE;
     2540        } else if (nr == 0) {
     2541            finish = FALSE;
     2542        }
     2543
     2544        /*
     2545         * Look for the last newline in the bytes we just got. If there is
     2546         * one, break out of the loop with 'i' as its index and gotNL set
     2547         * TRUE.
     2548         */
     2549        max = job->curPos + nr;
     2550        for (i = job->curPos + nr - 1; i >= job->curPos; i--) {
     2551            if (job->outBuf[i] == '\n') {
     2552                gotNL = TRUE;
     2553                break;
     2554            } else if (job->outBuf[i] == '\0') {
     2555                /*
     2556                 * Why?
     2557                 */
     2558                job->outBuf[i] = ' ';
     2559            }
     2560        }
     2561
     2562        if (!gotNL) {
     2563            job->curPos += nr;
     2564            if (job->curPos == JOB_BUFSIZE) {
     2565                /*
     2566                 * If we've run out of buffer space, we have no choice
     2567                 * but to print the stuff. sigh.
     2568                 */
     2569                fbuf = TRUE;
     2570                i = job->curPos;
     2571            }
     2572        }
     2573        if (gotNL || fbuf) {
     2574            /*
     2575             * Need to send the output to the screen. Null terminate it
     2576             * first, overwriting the newline character if there was one.
     2577             * So long as the line isn't one we should filter (according
     2578             * to the shell description), we print the line, preceeded
     2579             * by a target banner if this target isn't the same as the
     2580             * one for which we last printed something.
     2581             * The rest of the data in the buffer are then shifted down
     2582             * to the start of the buffer and curPos is set accordingly.
     2583             */
     2584            job->outBuf[i] = '\0';
     2585            if (i >= job->curPos) {
     2586                char *cp;
     2587
     2588                cp = JobOutput(job, job->outBuf, &job->outBuf[i], FALSE);
     2589
     2590                /*
     2591                 * There's still more in that thar buffer. This time, though,
     2592                 * we know there's no newline at the end, so we add one of
     2593                 * our own efree will.
     2594                 */
     2595                if (*cp != '\0') {
     2596                    if (job->node != lastNode) {
     2597                        MESSAGE(stdout, job->node);
     2598                        lastNode = job->node;
     2599                    }
     2600                    (void) fprintf(stdout, "%s%s", cp, gotNL ? "\n" : "");
     2601                    (void) fflush(stdout);
     2602                }
     2603            }
     2604            if (i < max - 1) {
     2605                /* shift the remaining characters down */
     2606                (void) memcpy(job->outBuf, &job->outBuf[i + 1], max - (i + 1));
     2607                job->curPos = max - (i + 1);
     2608
     2609            } else {
     2610                /*
     2611                 * We have written everything out, so we just start over
     2612                 * from the start of the buffer. No copying. No nothing.
     2613                 */
     2614                job->curPos = 0;
     2615            }
     2616        }
     2617        if (finish) {
     2618            /*
     2619             * If the finish flag is true, we must loop until we hit
     2620             * end-of-file on the pipe. This is guaranteed to happen
     2621             * eventually since the other end of the pipe is now closed
     2622             * (we closed it explicitly and the child has exited). When
     2623             * we do get an EOF, finish will be set FALSE and we'll fall
     2624             * through and out.
     2625             */
     2626            goto end_loop;
     2627        }
     2628    }
     2629    else
     2630#endif /* USE_PIPES */
     2631    {
     2632        /*
     2633         * We've been called to retrieve the output of the job from the
     2634         * temporary file where it's been squirreled away. This consists of
     2635         * opening the file, reading the output line by line, being sure not
     2636         * to print the noPrint line for the shell we used, then close and
     2637         * remove the temporary file. Very simple.
     2638         *
     2639         * Change to read in blocks and do FindSubString type things as for
     2640         * pipes? That would allow for "@echo -n..."
     2641         */
     2642        oFILE = fopen(job->outFile, "r");
     2643        if (oFILE != NULL) {
     2644            (void) fprintf(stdout, "Results of making %s:\n", job->node->name);
     2645            (void) fflush(stdout);
     2646            while (fgets(inLine, sizeof(inLine), oFILE) != NULL) {
     2647                register char   *cp, *endp, *oendp;
     2648
     2649                cp = inLine;
     2650                oendp = endp = inLine + strlen(inLine);
     2651                if (endp[-1] == '\n') {
     2652                    *--endp = '\0';
     2653                }
     2654                cp = JobOutput(job, inLine, endp, FALSE);
     2655
     2656                /*
     2657                 * There's still more in that thar buffer. This time, though,
     2658                 * we know there's no newline at the end, so we add one of
     2659                 * our own efree will.
     2660                 */
     2661                (void) fprintf(stdout, "%s", cp);
     2662                (void) fflush(stdout);
     2663                if (endp != oendp) {
     2664                    (void) fprintf(stdout, "\n");
     2665                    (void) fflush(stdout);
     2666                }
     2667            }
     2668            (void) fclose(oFILE);
     2669            (void) eunlink(job->outFile);
     2670        }
    22632671    }
    22642672}
     
    22672675 *-----------------------------------------------------------------------
    22682676 * Job_CatchChildren --
    2269  *      Handle the exit of a child. Called from Make_Make.
     2677 *      Handle the exit of a child. Called from Make_Make.
    22702678 *
    22712679 * Results:
    2272  *      none.
     2680 *      none.
    22732681 *
    22742682 * Side Effects:
    2275  *      The job descriptor is removed from the list of children.
     2683 *      The job descriptor is removed from the list of children.
    22762684 *
    22772685 * Notes:
    2278  *      We do waits, blocking or not, according to the wisdom of our
    2279  *      caller, until there are no more children to report. For each
    2280  *      job, call JobFinish to finish things off. This will take care of
    2281  *      putting jobs on the stoppedJobs queue.
     2686 *      We do waits, blocking or not, according to the wisdom of our
     2687 *      caller, until there are no more children to report. For each
     2688 *      job, call JobFinish to finish things off. This will take care of
     2689 *      putting jobs on the stoppedJobs queue.
    22822690 *
    22832691 *-----------------------------------------------------------------------
     
    22852693void
    22862694Job_CatchChildren(block)
    2287     Boolean       block;        /* TRUE if should block on the wait. */
     2695    Boolean       block;        /* TRUE if should block on the wait. */
    22882696{
    2289     int           pid;          /* pid of dead child */
    2290     register Job  *job;         /* job descriptor for dead child */
    2291     LstNode       jnode;        /* list element for finding job */
    2292     int           status;       /* Exit/termination status */
     2697#ifdef USE_KLIB
     2698    int           pid;          /* pid of dead child */
     2699    register Job *job;          /* job descriptor for dead child */
     2700    LstNode       jnode;        /* list element for finding job */
     2701    KPROCRES      status;       /* Exit/termination status */
    22932702
    22942703    /*
     
    22962705     */
    22972706    if (nLocal == 0) {
    2298         return;
     2707        return;
     2708    }
     2709
     2710    while (!kProcWait(KPID_NULL, KPROCWAIT_FLAGS_NOWAIT, &status, &pid))
     2711    {
     2712        if (DEBUG(JOB)) {
     2713            (void) fprintf(stdout, "Process %d exited or stopped.\n", pid);
     2714            (void) fflush(stdout);
     2715        }
     2716
     2717        jnode = Lst_Find(jobs, (ClientData)&pid, JobCmpPid);
     2718        if (jnode == NILLNODE) {
     2719            Error("Child (%d) not in table?", pid);
     2720            continue;
     2721        } else {
     2722            job = (Job *) Lst_Datum(jnode);
     2723            (void) Lst_Remove(jobs, jnode);
     2724            nJobs -= 1;
     2725            if (jobFull && DEBUG(JOB)) {
     2726                (void) fprintf(stdout, "Job queue is no longer full.\n");
     2727                (void) fflush(stdout);
     2728            }
     2729            jobFull = FALSE;
     2730            nLocal -= 1;
     2731        }
     2732        JobFinish(job, &status);
     2733    }
     2734
     2735#else /* Don't Use kLib */
     2736    int           pid;          /* pid of dead child */
     2737    register Job  *job;         /* job descriptor for dead child */
     2738    LstNode       jnode;        /* list element for finding job */
     2739    int           status;       /* Exit/termination status */
     2740
     2741    /*
     2742     * Don't even bother if we know there's no one around.
     2743     */
     2744    if (nLocal == 0) {
     2745        return;
    22992746    }
    23002747
    23012748    while ((pid = waitpid((pid_t) -1, &status,
    2302                           (block?0:WNOHANG)|WUNTRACED)) > 0)
     2749                          (block?0:WNOHANG)|WUNTRACED)) > 0)
    23032750    {
    2304         if (DEBUG(JOB)) {
    2305             (void) fprintf(stdout, "Process %d exited or stopped.\n", pid);
    2306             (void) fflush(stdout);
    2307         }
    2308 
    2309 
    2310         jnode = Lst_Find(jobs, (ClientData)&pid, JobCmpPid);
    2311 
    2312         if (jnode == NILLNODE) {
    2313             if (WIFSIGNALED(status) && (WTERMSIG(status) == SIGCONT)) {
    2314                 jnode = Lst_Find(stoppedJobs, (ClientData) &pid, JobCmpPid);
    2315                 if (jnode == NILLNODE) {
    2316                     Error("Resumed child (%d) not in table", pid);
    2317                     continue;
    2318                 }
    2319                 job = (Job *)Lst_Datum(jnode);
    2320                 (void) Lst_Remove(stoppedJobs, jnode);
    2321             } else {
    2322                 Error("Child (%d) not in table?", pid);
    2323                 continue;
    2324             }
    2325         } else {
    2326             job = (Job *) Lst_Datum(jnode);
    2327             (void) Lst_Remove(jobs, jnode);
    2328             nJobs -= 1;
    2329             if (jobFull && DEBUG(JOB)) {
    2330                 (void) fprintf(stdout, "Job queue is no longer full.\n");
    2331                 (void) fflush(stdout);
    2332             }
    2333             jobFull = FALSE;
     2751        if (DEBUG(JOB)) {
     2752            (void) fprintf(stdout, "Process %d exited or stopped.\n", pid);
     2753            (void) fflush(stdout);
     2754        }
     2755
     2756
     2757        jnode = Lst_Find(jobs, (ClientData)&pid, JobCmpPid);
     2758
     2759        if (jnode == NILLNODE) {
     2760            if (WIFSIGNALED(status) && (WTERMSIG(status) == SIGCONT)) {
     2761                jnode = Lst_Find(stoppedJobs, (ClientData) &pid, JobCmpPid);
     2762                if (jnode == NILLNODE) {
     2763                    Error("Resumed child (%d) not in table", pid);
     2764                    continue;
     2765                }
     2766                job = (Job *)Lst_Datum(jnode);
     2767                (void) Lst_Remove(stoppedJobs, jnode);
     2768            } else {
     2769                Error("Child (%d) not in table?", pid);
     2770                continue;
     2771            }
     2772        } else {
     2773            job = (Job *) Lst_Datum(jnode);
     2774            (void) Lst_Remove(jobs, jnode);
     2775            nJobs -= 1;
     2776            if (jobFull && DEBUG(JOB)) {
     2777                (void) fprintf(stdout, "Job queue is no longer full.\n");
     2778                (void) fflush(stdout);
     2779            }
     2780            jobFull = FALSE;
    23342781#ifdef REMOTE
    2335             if (!(job->flags & JOB_REMOTE)) {
    2336                 if (DEBUG(JOB)) {
    2337                     (void) fprintf(stdout,
    2338                                    "Job queue has one fewer local process.\n");
    2339                     (void) fflush(stdout);
    2340                 }
    2341                 nLocal -= 1;
    2342             }
     2782            if (!(job->flags & JOB_REMOTE)) {
     2783                if (DEBUG(JOB)) {
     2784                    (void) fprintf(stdout,
     2785                                   "Job queue has one fewer local process.\n");
     2786                    (void) fflush(stdout);
     2787                }
     2788                nLocal -= 1;
     2789            }
    23432790#else
    2344             nLocal -= 1;
    2345 #endif
    2346         }
    2347 
    2348         JobFinish(job, &status);
    2349     }
     2791            nLocal -= 1;
     2792#endif
     2793        }
     2794
     2795        JobFinish(job, &status);
     2796    }
     2797#endif /* USE_KLIB */
    23502798}
    23512799
     
    23532801 *-----------------------------------------------------------------------
    23542802 * Job_CatchOutput --
    2355  *      Catch the output from our children, if we're using
    2356  *      pipes do so. Otherwise just block time until we get a
    2357  *      signal (most likely a SIGCHLD) since there's no point in
    2358  *      just spinning when there's nothing to do and the reaping
    2359  *      of a child can wait for a while.
     2803 *      Catch the output from our children, if we're using
     2804 *      pipes do so. Otherwise just block time until we get a
     2805 *      signal (most likely a SIGCHLD) since there's no point in
     2806 *      just spinning when there's nothing to do and the reaping
     2807 *      of a child can wait for a while.
    23602808 *
    23612809 * Results:
    2362  *      None
     2810 *      None
    23632811 *
    23642812 * Side Effects:
    2365  *      Output is read from pipes if we're piping.
     2813 *      Output is read from pipes if we're piping.
    23662814 * -----------------------------------------------------------------------
    23672815 */
     
    23692817Job_CatchOutput()
    23702818{
    2371     int                   nfds;
    2372     struct timeval        timeout;
    2373     fd_set                readfds;
    2374     register LstNode      ln;
    2375     register Job          *job;
     2819    int                   nfds;
     2820    struct timeval        timeout;
     2821    fd_set                readfds;
     2822    register LstNode      ln;
     2823    register Job          *job;
    23762824#ifdef RMT_WILL_WATCH
    2377     int                   pnJobs;       /* Previous nJobs */
     2825    int                   pnJobs;       /* Previous nJobs */
    23782826#endif
    23792827
     
    23992847     */
    24002848    while (nJobs != 0 && pnJobs == nJobs) {
    2401         Rmt_Wait();
     2849        Rmt_Wait();
    24022850    }
    24032851#else
     2852#ifdef USE_PIPES
    24042853    if (usePipes) {
    2405         readfds = outputs;
    2406         timeout.tv_sec = SEL_SEC;
    2407         timeout.tv_usec = SEL_USEC;
    2408 
    2409         if ((nfds = select(FD_SETSIZE, &readfds, (fd_set *) 0,
    2410                            (fd_set *) 0, &timeout)) <= 0)
    2411             return;
    2412         else {
    2413             if (Lst_Open(jobs) == FAILURE) {
    2414                 Punt("Cannot open job table");
    2415             }
    2416             while (nfds && (ln = Lst_Next(jobs)) != NILLNODE) {
    2417                 job = (Job *) Lst_Datum(ln);
    2418                 if (FD_ISSET(job->inPipe, &readfds)) {
    2419                     JobDoOutput(job, FALSE);
    2420                     nfds -= 1;
    2421                 }
    2422             }
    2423             Lst_Close(jobs);
    2424         }
    2425     }
     2854        readfds = outputs;
     2855        timeout.tv_sec = SEL_SEC;
     2856        timeout.tv_usec = SEL_USEC;
     2857
     2858        if ((nfds = select(FD_SETSIZE, &readfds, (fd_set *) 0,
     2859                           (fd_set *) 0, &timeout)) <= 0)
     2860            return;
     2861        else {
     2862            if (Lst_Open(jobs) == FAILURE) {
     2863                Punt("Cannot open job table");
     2864            }
     2865            while (nfds && (ln = Lst_Next(jobs)) != NILLNODE) {
     2866                job = (Job *) Lst_Datum(ln);
     2867                if (FD_ISSET(job->inPipe, &readfds)) {
     2868                    JobDoOutput(job, FALSE);
     2869                    nfds -= 1;
     2870                }
     2871            }
     2872            Lst_Close(jobs);
     2873        }
     2874    }
     2875#endif /* USE_PIPES */
    24262876#endif /* RMT_WILL_WATCH */
    24272877}
     
    24302880 *-----------------------------------------------------------------------
    24312881 * Job_Make --
    2432  *      Start the creation of a target. Basically a front-end for
    2433  *      JobStart used by the Make module.
     2882 *      Start the creation of a target. Basically a front-end for
     2883 *      JobStart used by the Make module.
    24342884 *
    24352885 * Results:
    2436  *      None.
     2886 *      None.
    24372887 *
    24382888 * Side Effects:
    2439  *      Another job is started.
     2889 *      Another job is started.
    24402890 *
    24412891 *-----------------------------------------------------------------------
     
    24512901 *-----------------------------------------------------------------------
    24522902 * Job_Init --
    2453  *      Initialize the process module
     2903 *      Initialize the process module
    24542904 *
    24552905 * Results:
    2456  *      none
     2906 *      none
    24572907 *
    24582908 * Side Effects:
    2459  *      lists and counters are initialized
     2909 *      lists and counters are initialized
    24602910 *-----------------------------------------------------------------------
    24612911 */
     
    24632913Job_Init(maxproc, maxlocal)
    24642914    int           maxproc;  /* the greatest number of jobs which may be
    2465                              * running at one time */
    2466     int           maxlocal; /* the greatest number of local jobs which may
    2467                              * be running at once. */
     2915                             * running at one time */
     2916    int           maxlocal; /* the greatest number of local jobs which may
     2917                             * be running at once. */
    24682918{
    24692919    GNode         *begin;     /* node for commands to do at the very start */
    24702920
    2471     jobs =        Lst_Init(FALSE);
     2921    jobs =        Lst_Init(FALSE);
     2922#ifdef SIGCONT
    24722923    stoppedJobs = Lst_Init(FALSE);
    2473     maxJobs =     maxproc;
    2474     maxLocal =    maxlocal;
    2475     nJobs =       0;
    2476     nLocal =      0;
    2477     jobFull =     FALSE;
    2478 
    2479     aborting =    0;
    2480     errors =      0;
    2481 
    2482     lastNode =    NILGNODE;
     2924#endif
     2925    maxJobs =     maxproc;
     2926    maxLocal =    maxlocal;
     2927    nJobs =       0;
     2928    nLocal =      0;
     2929    jobFull =     FALSE;
     2930
     2931    aborting =    0;
     2932    errors =      0;
     2933
     2934    lastNode =    NILGNODE;
    24832935
    24842936    if (maxJobs == 1 || beVerbose == 0
    24852937#ifdef REMOTE
    2486         || noMessages
    2487 #endif
    2488                      ) {
    2489         /*
    2490         * If only one job can run at a time, there's no need for a banner,
    2491         * no is there?
    2492         */
    2493         targFmt = "";
     2938        || noMessages
     2939#endif
     2940                     ) {
     2941        /*
     2942        * If only one job can run at a time, there's no need for a banner,
     2943        * no is there?
     2944        */
     2945        targFmt = "";
    24942946    } else {
    2495         targFmt = TARG_FMT;
     2947        targFmt = TARG_FMT;
    24962948    }
    24972949
    24982950#ifndef KMK
    24992951    if (shellPath == NULL) {
    2500         /*
    2501         * The user didn't specify a shell to use, so we are using the
    2502         * default one... Both the absolute path and the last component
    2503         * must be set. The last component is taken from the 'name' field
    2504         * of the default shell description pointed-to by commandShell.
    2505         * All default shells are located in _PATH_DEFSHELLDIR.
    2506         */
    2507         shellName = commandShell->name;
    2508         shellPath = str_concat(_PATH_DEFSHELLDIR, shellName, STR_ADDSLASH);
     2952        /*
     2953        * The user didn't specify a shell to use, so we are using the
     2954        * default one... Both the absolute path and the last component
     2955        * must be set. The last component is taken from the 'name' field
     2956        * of the default shell description pointed-to by commandShell.
     2957        * All default shells are located in _PATH_DEFSHELLDIR.
     2958        */
     2959        shellName = commandShell->name;
     2960        shellPath = str_concat(_PATH_DEFSHELLDIR, shellName, STR_ADDSLASH);
    25092961    }
    25102962
    25112963    if (commandShell->exit == NULL) {
    2512         commandShell->exit = "";
     2964        commandShell->exit = "";
    25132965    }
    25142966    if (commandShell->echo == NULL) {
    2515         commandShell->echo = "";
     2967        commandShell->echo = "";
    25162968    }
    25172969#endif
     
    25222974     */
    25232975    if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
    2524         (void) signal(SIGINT, JobPassSig);
    2525     }
     2976        (void) signal(SIGINT, JobPassSig);
     2977    }
     2978#ifdef SIGHUP  /* not all systems supports this signal */
    25262979    if (signal(SIGHUP, SIG_IGN) != SIG_IGN) {
    2527         (void) signal(SIGHUP, JobPassSig);
    2528     }
     2980        (void) signal(SIGHUP, JobPassSig);
     2981    }
     2982#endif
     2983#ifdef SIGQUIT /* not all systems supports this signal */
    25292984    if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) {
    2530         (void) signal(SIGQUIT, JobPassSig);
    2531     }
     2985        (void) signal(SIGQUIT, JobPassSig);
     2986    }
     2987#endif
    25322988    if (signal(SIGTERM, SIG_IGN) != SIG_IGN) {
    2533         (void) signal(SIGTERM, JobPassSig);
     2989        (void) signal(SIGTERM, JobPassSig);
    25342990    }
    25352991    /*
     
    25412997#if defined(RMT_WANTS_SIGNALS) || defined(USE_PGRP)
    25422998    if (signal(SIGTSTP, SIG_IGN) != SIG_IGN) {
    2543         (void) signal(SIGTSTP, JobPassSig);
     2999        (void) signal(SIGTSTP, JobPassSig);
    25443000    }
    25453001    if (signal(SIGTTOU, SIG_IGN) != SIG_IGN) {
    2546         (void) signal(SIGTTOU, JobPassSig);
     3002        (void) signal(SIGTTOU, JobPassSig);
    25473003    }
    25483004    if (signal(SIGTTIN, SIG_IGN) != SIG_IGN) {
    2549         (void) signal(SIGTTIN, JobPassSig);
     3005        (void) signal(SIGTTIN, JobPassSig);
    25503006    }
    25513007    if (signal(SIGWINCH, SIG_IGN) != SIG_IGN) {
    2552         (void) signal(SIGWINCH, JobPassSig);
     3008        (void) signal(SIGWINCH, JobPassSig);
    25533009    }
    25543010#endif
     
    25573013
    25583014    if (begin != NILGNODE) {
    2559         JobStart(begin, JOB_SPECIAL, (Job *)0);
    2560         while (nJobs) {
    2561             Job_CatchOutput();
     3015        JobStart(begin, JOB_SPECIAL, (Job *)0);
     3016        while (nJobs) {
     3017            Job_CatchOutput();
    25623018#ifndef RMT_WILL_WATCH
    2563             Job_CatchChildren(!usePipes);
     3019            Job_CatchChildren(!usePipes);
    25643020#endif /* RMT_WILL_WATCH */
    2565         }
     3021        }
    25663022    }
    25673023    postCommands = Targ_FindNode(".END", TARG_CREATE);
     
    25713027 *-----------------------------------------------------------------------
    25723028 * Job_Full --
    2573  *      See if the job table is full. It is considered full if it is OR
    2574  *      if we are in the process of aborting OR if we have
    2575  *      reached/exceeded our local quota. This prevents any more jobs
    2576  *      from starting up.
     3029 *      See if the job table is full. It is considered full if it is OR
     3030 *      if we are in the process of aborting OR if we have
     3031 *      reached/exceeded our local quota. This prevents any more jobs
     3032 *      from starting up.
    25773033 *
    25783034 * Results:
    2579  *      TRUE if the job table is full, FALSE otherwise
     3035 *      TRUE if the job table is full, FALSE otherwise
    25803036 * Side Effects:
    2581  *      None.
     3037 *      None.
    25823038 *-----------------------------------------------------------------------
    25833039 */
     
    25913047 *-----------------------------------------------------------------------
    25923048 * Job_Empty --
    2593  *      See if the job table is empty.  Because the local concurrency may
    2594  *      be set to 0, it is possible for the job table to become empty,
    2595  *      while the list of stoppedJobs remains non-empty. In such a case,
    2596  *      we want to restart as many jobs as we can.
     3049 *      See if the job table is empty.  Because the local concurrency may
     3050 *      be set to 0, it is possible for the job table to become empty,
     3051 *      while the list of stoppedJobs remains non-empty. In such a case,
     3052 *      we want to restart as many jobs as we can.
    25973053 *
    25983054 * Results:
    2599  *      TRUE if it is. FALSE if it ain't.
     3055 *      TRUE if it is. FALSE if it ain't.
    26003056 *
    26013057 * Side Effects:
    2602  *      None.
     3058 *      None.
    26033059 *
    26043060 * -----------------------------------------------------------------------
     
    26083064{
    26093065    if (nJobs == 0) {
    2610         if (!Lst_IsEmpty(stoppedJobs) && !aborting) {
    2611             /*
    2612              * The job table is obviously not full if it has no jobs in
    2613              * it...Try and restart the stopped jobs.
    2614              */
    2615             jobFull = FALSE;
    2616             JobRestartJobs();
    2617             return(FALSE);
    2618         } else {
    2619             return(TRUE);
    2620         }
     3066#ifdef SIGCONT
     3067        if (!Lst_IsEmpty(stoppedJobs) && !aborting) {
     3068            /*
     3069             * The job table is obviously not full if it has no jobs in
     3070             * it...Try and restart the stopped jobs.
     3071             */
     3072            jobFull = FALSE;
     3073            JobRestartJobs();
     3074            return(FALSE);
     3075        }
     3076#else
     3077        return(TRUE);
     3078#endif
    26213079    } else {
    2622         return(FALSE);
     3080        return(FALSE);
    26233081    }
    26243082}
     
    26283086 *-----------------------------------------------------------------------
    26293087 * JobMatchShell --
    2630  *      Find a matching shell in 'shells' given its final component.
     3088 *      Find a matching shell in 'shells' given its final component.
    26313089 *
    26323090 * Results:
    2633  *      A pointer to the Shell structure.
     3091 *      A pointer to the Shell structure.
    26343092 *
    26353093 * Side Effects:
    2636  *      None.
     3094 *      None.
    26373095 *
    26383096 *-----------------------------------------------------------------------
     
    26403098static Shell *
    26413099JobMatchShell(name)
    2642     char          *name;      /* Final component of shell path */
     3100    char          *name;      /* Final component of shell path */
    26433101{
    2644     register Shell *sh;       /* Pointer into shells table */
    2645     Shell          *match;    /* Longest-matching shell */
     3102    register Shell *sh;       /* Pointer into shells table */
     3103    Shell          *match;    /* Longest-matching shell */
    26463104    register char *cp1,
    2647                   *cp2;
    2648     char          *eoname;
     3105                  *cp2;
     3106    char          *eoname;
    26493107
    26503108    eoname = name + strlen(name);
     
    26533111
    26543112    for (sh = shells; sh->name != NULL; sh++) {
    2655         for (cp1 = eoname - strlen(sh->name), cp2 = sh->name;
    2656              *cp1 != '\0' && *cp1 == *cp2;
    2657              cp1++, cp2++) {
    2658                 continue;
    2659         }
    2660         if (*cp1 != *cp2) {
    2661             continue;
    2662         } else if (match == NULL || strlen(match->name) < strlen(sh->name)) {
    2663            match = sh;
    2664         }
     3113        for (cp1 = eoname - strlen(sh->name), cp2 = sh->name;
     3114             *cp1 != '\0' && *cp1 == *cp2;
     3115             cp1++, cp2++) {
     3116                continue;
     3117        }
     3118        if (*cp1 != *cp2) {
     3119            continue;
     3120        } else if (match == NULL || strlen(match->name) < strlen(sh->name)) {
     3121           match = sh;
     3122        }
    26653123    }
    26663124    return(match == NULL ? sh : match);
     
    26723130 *-----------------------------------------------------------------------
    26733131 * Job_ParseShell --
    2674  *      Parse a shell specification and set up commandShell, shellPath
    2675  *      and shellName appropriately.
     3132 *      Parse a shell specification and set up commandShell, shellPath
     3133 *      and shellName appropriately.
    26763134 *
    26773135 * Results:
    2678  *      FAILURE if the specification was incorrect.
     3136 *      FAILURE if the specification was incorrect.
    26793137 *
    26803138 * Side Effects:
    2681  *      commandShell points to a Shell structure (either predefined or
    2682  *      created from the shell spec), shellPath is the full path of the
    2683  *      shell described by commandShell, while shellName is just the
    2684  *      final component of shellPath.
     3139 *      commandShell points to a Shell structure (either predefined or
     3140 *      created from the shell spec), shellPath is the full path of the
     3141 *      shell described by commandShell, while shellName is just the
     3142 *      final component of shellPath.
    26853143 *
    26863144 * Notes:
    2687  *      A shell specification consists of a .SHELL target, with dependency
    2688  *      operator, followed by a series of blank-separated words. Double
    2689  *      quotes can be used to use blanks in words. A backslash escapes
    2690  *      anything (most notably a double-quote and a space) and
    2691  *      provides the functionality it does in C. Each word consists of
    2692  *      keyword and value separated by an equal sign. There should be no
    2693  *      unnecessary spaces in the word. The keywords are as follows:
    2694  *          name            Name of shell.
    2695  *          path            Location of shell. Overrides "name" if given
    2696  *          quiet           Command to turn off echoing.
    2697  *          echo            Command to turn echoing on
    2698  *          filter          Result of turning off echoing that shouldn't be
    2699  *                          printed.
    2700  *          echoFlag        Flag to turn echoing on at the start
    2701  *          errFlag         Flag to turn error checking on at the start
    2702  *          hasErrCtl       True if shell has error checking control
    2703  *          check           Command to turn on error checking if hasErrCtl
    2704  *                          is TRUE or template of command to echo a command
    2705  *                          for which error checking is off if hasErrCtl is
    2706  *                          FALSE.
    2707  *          ignore          Command to turn off error checking if hasErrCtl
    2708  *                          is TRUE or template of command to execute a
    2709  *                          command so as to ignore any errors it returns if
    2710  *                          hasErrCtl is FALSE.
     3145 *      A shell specification consists of a .SHELL target, with dependency
     3146 *      operator, followed by a series of blank-separated words. Double
     3147 *      quotes can be used to use blanks in words. A backslash escapes
     3148 *      anything (most notably a double-quote and a space) and
     3149 *      provides the functionality it does in C. Each word consists of
     3150 *      keyword and value separated by an equal sign. There should be no
     3151 *      unnecessary spaces in the word. The keywords are as follows:
     3152 *          name            Name of shell.
     3153 *          path            Location of shell. Overrides "name" if given
     3154 *          quiet           Command to turn off echoing.
     3155 *          echo            Command to turn echoing on
     3156 *          filter          Result of turning off echoing that shouldn't be
     3157 *                          printed.
     3158 *          echoFlag        Flag to turn echoing on at the start
     3159 *          errFlag         Flag to turn error checking on at the start
     3160 *          hasErrCtl       True if shell has error checking control
     3161 *          check           Command to turn on error checking if hasErrCtl
     3162 *                          is TRUE or template of command to echo a command
     3163 *                          for which error checking is off if hasErrCtl is
     3164 *                          FALSE.
     3165 *          ignore          Command to turn off error checking if hasErrCtl
     3166 *                          is TRUE or template of command to execute a
     3167 *                          command so as to ignore any errors it returns if
     3168 *                          hasErrCtl is FALSE.
    27113169 *
    27123170 *-----------------------------------------------------------------------
     
    27143172ReturnStatus
    27153173Job_ParseShell(line)
    2716     char          *line;  /* The shell spec */
     3174    char          *line;  /* The shell spec */
    27173175{
    2718     char          **words;
    2719     int           wordCount;
     3176    char          **words;
     3177    int           wordCount;
    27203178    register char **argv;
    27213179    register int  argc;
    2722     char          *path;
    2723     Shell         newShell;
    2724     Boolean       fullSpec = FALSE;
     3180    char          *path;
     3181    Shell         newShell;
     3182    Boolean       fullSpec = FALSE;
    27253183
    27263184    while (isspace(*line)) {
    2727         line++;
     3185        line++;
    27283186    }
    27293187    words = brk_string(line, &wordCount, TRUE);
     
    27353193     */
    27363194    for (path = NULL, argc = wordCount - 1, argv = words + 1;
    2737         argc != 0;
    2738         argc--, argv++) {
    2739              if (strncmp(*argv, "path=", 5) == 0) {
    2740                 path = &argv[0][5];
    2741              } else if (strncmp(*argv, "name=", 5) == 0) {
    2742                 newShell.name = &argv[0][5];
    2743              } else {
    2744                 if (strncmp(*argv, "quiet=", 6) == 0) {
    2745                      newShell.echoOff = &argv[0][6];
    2746                 } else if (strncmp(*argv, "echo=", 5) == 0) {
    2747                      newShell.echoOn = &argv[0][5];
    2748                 } else if (strncmp(*argv, "filter=", 7) == 0) {
    2749                      newShell.noPrint = &argv[0][7];
    2750                      newShell.noPLen = strlen(newShell.noPrint);
    2751                 } else if (strncmp(*argv, "echoFlag=", 9) == 0) {
    2752                      newShell.echo = &argv[0][9];
    2753                 } else if (strncmp(*argv, "errFlag=", 8) == 0) {
    2754                      newShell.exit = &argv[0][8];
    2755                 } else if (strncmp(*argv, "hasErrCtl=", 10) == 0) {
    2756                      char c = argv[0][10];
    2757                      newShell.hasErrCtl = !((c != 'Y') && (c != 'y') &&
    2758                                            (c != 'T') && (c != 't'));
    2759                 } else if (strncmp(*argv, "check=", 6) == 0) {
    2760                      newShell.errCheck = &argv[0][6];
    2761                 } else if (strncmp(*argv, "ignore=", 7) == 0) {
    2762                      newShell.ignErr = &argv[0][7];
    2763                 } else {
    2764                      Parse_Error(PARSE_FATAL, "Unknown keyword \"%s\"",
    2765                                   *argv);
    2766                      return(FAILURE);
    2767                 }
    2768                 fullSpec = TRUE;
    2769              }
     3195        argc != 0;
     3196        argc--, argv++) {
     3197             if (strncmp(*argv, "path=", 5) == 0) {
     3198                path = &argv[0][5];
     3199             } else if (strncmp(*argv, "name=", 5) == 0) {
     3200                newShell.name = &argv[0][5];
     3201             } else {
     3202                if (strncmp(*argv, "quiet=", 6) == 0) {
     3203                     newShell.echoOff = &argv[0][6];
     3204                } else if (strncmp(*argv, "echo=", 5) == 0) {
     3205                     newShell.echoOn = &argv[0][5];
     3206                } else if (strncmp(*argv, "filter=", 7) == 0) {
     3207                     newShell.noPrint = &argv[0][7];
     3208                     newShell.noPLen = strlen(newShell.noPrint);
     3209                } else if (strncmp(*argv, "echoFlag=", 9) == 0) {
     3210                     newShell.echo = &argv[0][9];
     3211                } else if (strncmp(*argv, "errFlag=", 8) == 0) {
     3212                     newShell.exit = &argv[0][8];
     3213                } else if (strncmp(*argv, "hasErrCtl=", 10) == 0) {
     3214                     char c = argv[0][10];
     3215                     newShell.hasErrCtl = !((c != 'Y') && (c != 'y') &&
     3216                                           (c != 'T') && (c != 't'));
     3217                } else if (strncmp(*argv, "check=", 6) == 0) {
     3218                     newShell.errCheck = &argv[0][6];
     3219                } else if (strncmp(*argv, "ignore=", 7) == 0) {
     3220                     newShell.ignErr = &argv[0][7];
     3221                } else {
     3222                     Parse_Error(PARSE_FATAL, "Unknown keyword \"%s\"",
     3223                                  *argv);
     3224                     return(FAILURE);
     3225                }
     3226                fullSpec = TRUE;
     3227             }
    27703228    }
    27713229
    27723230    if (path == NULL) {
    2773         /*
    2774         * If no path was given, the user wants one of the pre-defined shells,
    2775         * yes? So we find the one s/he wants with the help of JobMatchShell
    2776         * and set things up the right way. shellPath will be set up by
    2777         * Job_Init.
    2778         */
    2779         if (newShell.name == NULL) {
    2780             Parse_Error(PARSE_FATAL, "Neither path nor name specified");
    2781             return(FAILURE);
    2782         } else {
    2783             commandShell = JobMatchShell(newShell.name);
    2784             shellName = newShell.name;
    2785         }
     3231        /*
     3232        * If no path was given, the user wants one of the pre-defined shells,
     3233        * yes? So we find the one s/he wants with the help of JobMatchShell
     3234        * and set things up the right way. shellPath will be set up by
     3235        * Job_Init.
     3236        */
     3237        if (newShell.name == NULL) {
     3238            Parse_Error(PARSE_FATAL, "Neither path nor name specified");
     3239            return(FAILURE);
     3240        } else {
     3241            commandShell = JobMatchShell(newShell.name);
     3242            shellName = newShell.name;
     3243        }
    27863244    } else {
    2787         /*
    2788         * The user provided a path. If s/he gave nothing else (fullSpec is
    2789         * FALSE), try and find a matching shell in the ones we know of.
    2790         * Else we just take the specification at its word and copy it
    2791         * to a new location. In either case, we need to record the
    2792         * path the user gave for the shell.
    2793         */
    2794         shellPath = path;
    2795         path = strrchr(path, '/');
    2796         if (path == NULL) {
    2797             path = shellPath;
    2798         } else {
    2799             path += 1;
    2800         }
    2801         if (newShell.name != NULL) {
    2802             shellName = newShell.name;
    2803         } else {
    2804             shellName = path;
    2805         }
    2806         if (!fullSpec) {
    2807             commandShell = JobMatchShell(shellName);
    2808         } else {
    2809             commandShell = (Shell *) emalloc(sizeof(Shell));
    2810             *commandShell = newShell;
    2811         }
     3245        /*
     3246        * The user provided a path. If s/he gave nothing else (fullSpec is
     3247        * FALSE), try and find a matching shell in the ones we know of.
     3248        * Else we just take the specification at its word and copy it
     3249        * to a new location. In either case, we need to record the
     3250        * path the user gave for the shell.
     3251        */
     3252        shellPath = path;
     3253        path = strrchr(path, '/');
     3254        if (path == NULL) {
     3255            path = shellPath;
     3256        } else {
     3257            path += 1;
     3258        }
     3259        if (newShell.name != NULL) {
     3260            shellName = newShell.name;
     3261        } else {
     3262            shellName = path;
     3263        }
     3264        if (!fullSpec) {
     3265            commandShell = JobMatchShell(shellName);
     3266        } else {
     3267            commandShell = (Shell *) emalloc(sizeof(Shell));
     3268            *commandShell = newShell;
     3269        }
    28123270    }
    28133271
    28143272    if (commandShell->echoOn && commandShell->echoOff) {
    2815         commandShell->hasEchoCtl = TRUE;
     3273        commandShell->hasEchoCtl = TRUE;
    28163274    }
    28173275
    28183276    if (!commandShell->hasErrCtl) {
    2819         if (commandShell->errCheck == NULL) {
    2820             commandShell->errCheck = "";
    2821         }
    2822         if (commandShell->ignErr == NULL) {
    2823             commandShell->ignErr = "%s\n";
    2824         }
     3277        if (commandShell->errCheck == NULL) {
     3278            commandShell->errCheck = "";
     3279        }
     3280        if (commandShell->ignErr == NULL) {
     3281            commandShell->ignErr = "%s\n";
     3282        }
    28253283    }
    28263284
     
    28373295 *-----------------------------------------------------------------------
    28383296 * JobInterrupt --
    2839  *      Handle the receipt of an interrupt.
     3297 *      Handle the receipt of an interrupt.
    28403298 *
    28413299 * Results:
    2842  *      None
     3300 *      None
    28433301 *
    28443302 * Side Effects:
    2845  *      All children are killed. Another job will be started if the
    2846  *      .INTERRUPT target was given.
     3303 *      All children are killed. Another job will be started if the
     3304 *      .INTERRUPT target was given.
    28473305 *-----------------------------------------------------------------------
    28483306 */
    28493307static void
    28503308JobInterrupt(runINTERRUPT, signo)
    2851     int     runINTERRUPT;       /* Non-zero if commands for the .INTERRUPT
    2852                                 * target should be executed */
    2853     int     signo;              /* signal received */
     3309    int     runINTERRUPT;       /* Non-zero if commands for the .INTERRUPT
     3310                                * target should be executed */
     3311    int     signo;              /* signal received */
    28543312{
    2855     LstNode       ln;           /* element in job table */
    2856     Job           *job = NULL;  /* job descriptor in that element */
    2857     GNode         *interrupt;   /* the node describing the .INTERRUPT target */
     3313    LstNode       ln;           /* element in job table */
     3314    Job           *job = NULL;  /* job descriptor in that element */
     3315    GNode         *interrupt;   /* the node describing the .INTERRUPT target */
    28583316
    28593317    aborting = ABORT_INTERRUPT;
     
    28613319   (void) Lst_Open(jobs);
    28623320    while ((ln = Lst_Next(jobs)) != NILLNODE) {
    2863         job = (Job *) Lst_Datum(ln);
    2864 
    2865         if (!Targ_Precious(job->node)) {
    2866             char        *file = (job->node->path == NULL ?
    2867                                 job->node->name :
    2868                                 job->node->path);
    2869             if (!noExecute && eunlink(file) != -1) {
    2870                 Error("*** %s removed", file);
    2871             }
    2872         }
     3321        job = (Job *) Lst_Datum(ln);
     3322
     3323        if (!Targ_Precious(job->node)) {
     3324            char        *file = (job->node->path == NULL ?
     3325                                job->node->name :
     3326                                job->node->path);
     3327            if (!noExecute && eunlink(file) != -1) {
     3328                Error("*** %s removed", file);
     3329            }
     3330        }
    28733331#ifdef RMT_WANTS_SIGNALS
    2874         if (job->flags & JOB_REMOTE) {
    2875             /*
    2876              * If job is remote, let the Rmt module do the killing.
    2877              */
    2878             if (!Rmt_Signal(job, signo)) {
    2879                 /*
    2880                 * If couldn't kill the thing, finish it out now with an
    2881                 * error code, since no exit report will come in likely.
    2882                 */
    2883                 int status;
    2884 
    2885                 status.w_status = 0;
    2886                 status.w_retcode = 1;
    2887                 JobFinish(job, &status);
    2888             }
    2889         } else if (job->pid) {
    2890             KILL(job->pid, signo);
    2891         }
     3332        if (job->flags & JOB_REMOTE) {
     3333            /*
     3334             * If job is remote, let the Rmt module do the killing.
     3335             */
     3336            if (!Rmt_Signal(job, signo)) {
     3337                /*
     3338                * If couldn't kill the thing, finish it out now with an
     3339                * error code, since no exit report will come in likely.
     3340                */
     3341                int status;
     3342
     3343                status.w_status = 0;
     3344                status.w_retcode = 1;
     3345                JobFinish(job, &status);
     3346            }
     3347        } else if (job->pid) {
     3348            KILL(job->pid, signo);
     3349        }
    28923350#else
    2893         if (job->pid) {
    2894             if (DEBUG(JOB)) {
    2895                 (void) fprintf(stdout,
    2896                                "JobInterrupt passing signal to child %d.\n",
    2897                                job->pid);
    2898                 (void) fflush(stdout);
    2899             }
    2900             KILL(job->pid, signo);
    2901         }
     3351        if (job->pid) {
     3352            if (DEBUG(JOB)) {
     3353                (void) fprintf(stdout,
     3354                               "JobInterrupt passing signal to child %d.\n",
     3355                               job->pid);
     3356                (void) fflush(stdout);
     3357            }
     3358            KILL(job->pid, signo);
     3359        }
    29023360#endif /* RMT_WANTS_SIGNALS */
    29033361    }
     
    29063364   (void)Lst_Open(stoppedJobs);
    29073365    while ((ln = Lst_Next(stoppedJobs)) != NILLNODE) {
    2908         job = (Job *) Lst_Datum(ln);
    2909 
    2910         if (job->flags & JOB_RESTART) {
    2911             if (DEBUG(JOB)) {
    2912                 (void) fprintf(stdout, "%s%s",
    2913                                "JobInterrupt skipping job on stopped queue",
    2914                                "-- it was waiting to be restarted.\n");
    2915                 (void) fflush(stdout);
    2916             }
    2917             continue;
    2918         }
    2919         if (!Targ_Precious(job->node)) {
    2920             char        *file = (job->node->path == NULL ?
    2921                                 job->node->name :
    2922                                 job->node->path);
    2923             if (eunlink(file) == 0) {
    2924                 Error("*** %s removed", file);
    2925             }
    2926         }
    2927         /*
    2928         * Resume the thing so it will take the signal.
    2929         */
    2930         if (DEBUG(JOB)) {
    2931             (void) fprintf(stdout,
    2932                            "JobInterrupt passing CONT to stopped child %d.\n",
    2933                            job->pid);
    2934             (void) fflush(stdout);
    2935         }
    2936         KILL(job->pid, SIGCONT);
     3366        job = (Job *) Lst_Datum(ln);
     3367
     3368        if (job->flags & JOB_RESTART) {
     3369            if (DEBUG(JOB)) {
     3370                (void) fprintf(stdout, "%s%s",
     3371                               "JobInterrupt skipping job on stopped queue",
     3372                               "-- it was waiting to be restarted.\n");
     3373                (void) fflush(stdout);
     3374            }
     3375            continue;
     3376        }
     3377        if (!Targ_Precious(job->node)) {
     3378            char        *file = (job->node->path == NULL ?
     3379                                job->node->name :
     3380                                job->node->path);
     3381            if (eunlink(file) == 0) {
     3382                Error("*** %s removed", file);
     3383            }
     3384        }
     3385        /*
     3386        * Resume the thing so it will take the signal.
     3387        */
     3388        if (DEBUG(JOB)) {
     3389            (void) fprintf(stdout,
     3390                           "JobInterrupt passing CONT to stopped child %d.\n",
     3391                           job->pid);
     3392            (void) fflush(stdout);
     3393        }
     3394        KILL(job->pid, SIGCONT);
    29373395#ifdef RMT_WANTS_SIGNALS
    2938         if (job->flags & JOB_REMOTE) {
    2939             /*
    2940              * If job is remote, let the Rmt module do the killing.
    2941              */
    2942             if (!Rmt_Signal(job, SIGINT)) {
    2943                 /*
    2944                 * If couldn't kill the thing, finish it out now with an
    2945                 * error code, since no exit report will come in likely.
    2946                 */
    2947                 int status;
    2948                 status.w_status = 0;
    2949                 status.w_retcode = 1;
    2950                 JobFinish(job, &status);
    2951             }
    2952         } else if (job->pid) {
    2953             if (DEBUG(JOB)) {
    2954                 (void) fprintf(stdout,
    2955                        "JobInterrupt passing interrupt to stopped child %d.\n",
    2956                                job->pid);
    2957                 (void) fflush(stdout);
    2958             }
    2959             KILL(job->pid, SIGINT);
    2960         }
     3396        if (job->flags & JOB_REMOTE) {
     3397            /*
     3398             * If job is remote, let the Rmt module do the killing.
     3399             */
     3400            if (!Rmt_Signal(job, SIGINT)) {
     3401                /*
     3402                * If couldn't kill the thing, finish it out now with an
     3403                * error code, since no exit report will come in likely.
     3404                */
     3405                int status;
     3406                status.w_status = 0;
     3407                status.w_retcode = 1;
     3408                JobFinish(job, &status);
     3409            }
     3410        } else if (job->pid) {
     3411            if (DEBUG(JOB)) {
     3412                (void) fprintf(stdout,
     3413                       "JobInterrupt passing interrupt to stopped child %d.\n",
     3414                               job->pid);
     3415                (void) fflush(stdout);
     3416            }
     3417            KILL(job->pid, SIGINT);
     3418        }
    29613419#endif /* RMT_WANTS_SIGNALS */
    29623420    }
    2963 #endif
    29643421    Lst_Close(stoppedJobs);
     3422#endif
    29653423
    29663424    if (runINTERRUPT && !touchFlag) {
    2967         interrupt = Targ_FindNode(".INTERRUPT", TARG_NOCREATE);
    2968         if (interrupt != NILGNODE) {
    2969             ignoreErrors = FALSE;
    2970 
    2971             JobStart(interrupt, JOB_IGNDOTS, (Job *)0);
    2972             while (nJobs) {
    2973                 Job_CatchOutput();
     3425        interrupt = Targ_FindNode(".INTERRUPT", TARG_NOCREATE);
     3426        if (interrupt != NILGNODE) {
     3427            ignoreErrors = FALSE;
     3428
     3429            JobStart(interrupt, JOB_IGNDOTS, (Job *)0);
     3430            while (nJobs) {
     3431                Job_CatchOutput();
    29743432#ifndef RMT_WILL_WATCH
    2975                 Job_CatchChildren(!usePipes);
     3433                Job_CatchChildren(!usePipes);
    29763434#endif /* RMT_WILL_WATCH */
    2977             }
    2978         }
     3435            }
     3436        }
    29793437    }
    29803438}
     
    29833441 *-----------------------------------------------------------------------
    29843442 * Job_End --
    2985  *      Do final processing such as the running of the commands
    2986  *      attached to the .END target.
     3443 *      Do final processing such as the running of the commands
     3444 *      attached to the .END target.
    29873445 *
    29883446 * Results:
    2989  *      Number of errors reported.
     3447 *      Number of errors reported.
    29903448 *-----------------------------------------------------------------------
    29913449 */
     
    29943452{
    29953453    if (postCommands != NILGNODE && !Lst_IsEmpty(postCommands->commands)) {
    2996         if (errors) {
    2997             Error("Errors reported so .END ignored");
    2998         } else {
    2999             JobStart(postCommands, JOB_SPECIAL | JOB_IGNDOTS, NULL);
    3000 
    3001             while (nJobs) {
    3002                 Job_CatchOutput();
     3454        if (errors) {
     3455            Error("Errors reported so .END ignored");
     3456        } else {
     3457            JobStart(postCommands, JOB_SPECIAL | JOB_IGNDOTS, NULL);
     3458
     3459            while (nJobs) {
     3460                Job_CatchOutput();
    30033461#ifndef RMT_WILL_WATCH
    3004                 Job_CatchChildren(!usePipes);
     3462                Job_CatchChildren(!usePipes);
    30053463#endif /* RMT_WILL_WATCH */
    3006             }
    3007         }
     3464            }
     3465        }
    30083466    }
    30093467    return(errors);
     
    30133471 *-----------------------------------------------------------------------
    30143472 * Job_Wait --
    3015  *      Waits for all running jobs to finish and returns. Sets 'aborting'
    3016  *      to ABORT_WAIT to prevent other jobs from starting.
     3473 *      Waits for all running jobs to finish and returns. Sets 'aborting'
     3474 *      to ABORT_WAIT to prevent other jobs from starting.
    30173475 *
    30183476 * Results:
    3019  *      None.
     3477 *      None.
    30203478 *
    30213479 * Side Effects:
    3022  *      Currently running jobs finish.
     3480 *      Currently running jobs finish.
    30233481 *
    30243482 *-----------------------------------------------------------------------
     
    30293487    aborting = ABORT_WAIT;
    30303488    while (nJobs != 0) {
    3031         Job_CatchOutput();
     3489        Job_CatchOutput();
    30323490#ifndef RMT_WILL_WATCH
    3033         Job_CatchChildren(!usePipes);
     3491        Job_CatchChildren(!usePipes);
    30343492#endif /* RMT_WILL_WATCH */
    30353493    }
     
    30403498 *-----------------------------------------------------------------------
    30413499 * Job_AbortAll --
    3042  *      Abort all currently running jobs without handling output or anything.
    3043  *      This function is to be called only in the event of a major
    3044  *      error. Most definitely NOT to be called from JobInterrupt.
     3500 *      Abort all currently running jobs without handling output or anything.
     3501 *      This function is to be called only in the event of a major
     3502 *      error. Most definitely NOT to be called from JobInterrupt.
    30453503 *
    30463504 * Results:
    3047  *      None
     3505 *      None
    30483506 *
    30493507 * Side Effects:
    3050  *      All children are killed, not just the firstborn
     3508 *      All children are killed, not just the firstborn
    30513509 *-----------------------------------------------------------------------
    30523510 */
     
    30543512Job_AbortAll()
    30553513{
    3056     LstNode             ln;     /* element in job table */
    3057     Job                 *job;   /* the job descriptor in that element */
    3058     int                 foo;
     3514#ifdef USE_KLIB
     3515    LstNode             ln;     /* element in job table */
     3516    Job                *job;    /* the job descriptor in that element */
     3517    KPROCRES            res;
    30593518
    30603519    aborting = ABORT_ERROR;
    30613520
     3521    if (nJobs)
     3522    {
     3523        Lst_Open(jobs);
     3524        while ((ln = Lst_Next(jobs)) != NILLNODE)
     3525        {
     3526            job = (Job *) Lst_Datum(ln);
     3527
     3528            /*
     3529             * kill the child process with increasingly drastic signals to make
     3530             * darn sure it's dead.
     3531             */
     3532            kProcKill(job->pid, KPROCKILL_FLAGS_TREE | KPROCKILL_FLAGS_TYPE_INT);
     3533            kProcKill(job->pid, KPROCKILL_FLAGS_TREE | KPROCKILL_FLAGS_TYPE_KILL);
     3534        }
     3535    }
     3536
     3537    /*
     3538     * Catch as many children as want to report in at first, then give up
     3539     */
     3540    do
     3541    {
     3542        kThrdYield();
     3543    } while (!kProcWait(KPID_NULL, KPROCWAIT_FLAGS_NOWAIT, &res, NULL)); /** @todo checkout this call */
     3544
     3545#else /* Don't use kLib */
     3546    LstNode             ln;     /* element in job table */
     3547    Job                 *job;   /* the job descriptor in that element */
     3548    int                 foo;
     3549
     3550    aborting = ABORT_ERROR;
     3551
    30623552    if (nJobs) {
    30633553
    3064         (void) Lst_Open(jobs);
    3065         while ((ln = Lst_Next(jobs)) != NILLNODE) {
    3066             job = (Job *) Lst_Datum(ln);
    3067 
    3068             /*
    3069              * kill the child process with increasingly drastic signals to make
    3070              * darn sure it's dead.
    3071              */
     3554        (void) Lst_Open(jobs);
     3555        while ((ln = Lst_Next(jobs)) != NILLNODE) {
     3556            job = (Job *) Lst_Datum(ln);
     3557
     3558            /*
     3559             * kill the child process with increasingly drastic signals to make
     3560             * darn sure it's dead.
     3561             */
    30723562#ifdef RMT_WANTS_SIGNALS
    3073             if (job->flags & JOB_REMOTE) {
    3074                 Rmt_Signal(job, SIGINT);
    3075                 Rmt_Signal(job, SIGKILL);
    3076             } else {
    3077                 KILL(job->pid, SIGINT);
    3078                 KILL(job->pid, SIGKILL);
    3079             }
     3563            if (job->flags & JOB_REMOTE) {
     3564                Rmt_Signal(job, SIGINT);
     3565                Rmt_Signal(job, SIGKILL);
     3566            } else {
     3567                KILL(job->pid, SIGINT);
     3568                KILL(job->pid, SIGKILL);
     3569            }
    30803570#else
    3081             KILL(job->pid, SIGINT);
    3082             KILL(job->pid, SIGKILL);
     3571            KILL(job->pid, SIGINT);
     3572            KILL(job->pid, SIGKILL);
    30833573#endif /* RMT_WANTS_SIGNALS */
    3084         }
     3574        }
    30853575    }
    30863576
     
    30893579     */
    30903580    while (waitpid((pid_t) -1, &foo, WNOHANG) > 0)
    3091         continue;
     3581        continue;
     3582#endif /* USE_KLIB */
    30923583}
    30933584
     
    30963587 *-----------------------------------------------------------------------
    30973588 * JobFlagForMigration --
    3098  *      Handle the eviction of a child. Called from RmtStatusChange.
    3099  *      Flags the child as remigratable and then suspends it.
     3589 *      Handle the eviction of a child. Called from RmtStatusChange.
     3590 *      Flags the child as remigratable and then suspends it.
    31003591 *
    31013592 * Results:
    3102  *      none.
     3593 *      none.
    31033594 *
    31043595 * Side Effects:
    3105  *      The job descriptor is flagged for remigration.
     3596 *      The job descriptor is flagged for remigration.
    31063597 *
    31073598 *-----------------------------------------------------------------------
     
    31093600void
    31103601JobFlagForMigration(hostID)
    3111     int           hostID;       /* ID of host we used, for matching children. */
     3602    int           hostID;       /* ID of host we used, for matching children. */
    31123603{
    3113     register Job  *job;         /* job descriptor for dead child */
    3114     LstNode       jnode;        /* list element for finding job */
     3604    register Job  *job;         /* job descriptor for dead child */
     3605    LstNode       jnode;        /* list element for finding job */
    31153606
    31163607    if (DEBUG(JOB)) {
    3117         (void) fprintf(stdout, "JobFlagForMigration(%d) called.\n", hostID);
    3118         (void) fflush(stdout);
     3608        (void) fprintf(stdout, "JobFlagForMigration(%d) called.\n", hostID);
     3609        (void) fflush(stdout);
    31193610    }
    31203611    jnode = Lst_Find(jobs, (ClientData)hostID, JobCmpRmtID);
    31213612
    31223613    if (jnode == NILLNODE) {
    3123         jnode = Lst_Find(stoppedJobs, (ClientData)hostID, JobCmpRmtID);
    3124                 if (jnode == NILLNODE) {
    3125                     if (DEBUG(JOB)) {
    3126                         Error("Evicting host(%d) not in table", hostID);
    3127                     }
    3128                     return;
    3129                 }
     3614        jnode = Lst_Find(stoppedJobs, (ClientData)hostID, JobCmpRmtID);
     3615                if (jnode == NILLNODE) {
     3616                    if (DEBUG(JOB)) {
     3617                        Error("Evicting host(%d) not in table", hostID);
     3618                    }
     3619                    return;
     3620                }
    31303621    }
    31313622    job = (Job *) Lst_Datum(jnode);
    31323623
    31333624    if (DEBUG(JOB)) {
    3134         (void) fprintf(stdout,
    3135                        "JobFlagForMigration(%d) found job '%s'.\n", hostID,
    3136                        job->node->name);
    3137         (void) fflush(stdout);
     3625        (void) fprintf(stdout,
     3626                       "JobFlagForMigration(%d) found job '%s'.\n", hostID,
     3627                       job->node->name);
     3628        (void) fflush(stdout);
    31383629    }
    31393630
     
    31463637
    31473638
     3639#ifdef SIGCONT
    31483640/*-
    31493641 *-----------------------------------------------------------------------
    31503642 * JobRestartJobs --
    3151  *      Tries to restart stopped jobs if there are slots available.
    3152  *      Note that this tries to restart them regardless of pending errors.
    3153  *      It's not good to leave stopped jobs lying around!
     3643 *      Tries to restart stopped jobs if there are slots available.
     3644 *      Note that this tries to restart them regardless of pending errors.
     3645 *      It's not good to leave stopped jobs lying around!
    31543646 *
    31553647 * Results:
    3156  *      None.
     3648 *      None.
    31573649 *
    31583650 * Side Effects:
    3159  *      Resumes(and possibly migrates) jobs.
     3651 *      Resumes(and possibly migrates) jobs.
    31603652 *
    31613653 *-----------------------------------------------------------------------
     
    31653657{
    31663658    while (!jobFull && !Lst_IsEmpty(stoppedJobs)) {
    3167         if (DEBUG(JOB)) {
    3168             (void) fprintf(stdout,
    3169                        "Job queue is not full. Restarting a stopped job.\n");
    3170             (void) fflush(stdout);
    3171         }
    3172         JobRestart((Job *)Lst_DeQueue(stoppedJobs));
     3659        if (DEBUG(JOB)) {
     3660            (void) fprintf(stdout,
     3661                       "Job queue is not full. Restarting a stopped job.\n");
     3662            (void) fflush(stdout);
     3663        }
     3664        JobRestart((Job *)Lst_DeQueue(stoppedJobs));
    31733665    }
    31743666}
     3667#endif
  • trunk/src/kmk/job.h

    r25 r51  
    1818 * 3. All advertising materials mentioning features or use of this software
    1919 *    must display the following acknowledgement:
    20  *      This product includes software developed by the University of
    21  *      California, Berkeley and its contributors.
     20 *      This product includes software developed by the University of
     21 *      California, Berkeley and its contributors.
    2222 * 4. Neither the name of the University nor the names of its contributors
    2323 *    may be used to endorse or promote products derived from this software
     
    3636 * SUCH DAMAGE.
    3737 *
    38  *      from: @(#)job.h 8.1 (Berkeley) 6/6/93
     38 *      from: @(#)job.h 8.1 (Berkeley) 6/6/93
    3939 * $FreeBSD: src/usr.bin/make/job.h,v 1.11 2000/01/17 06:43:41 kris Exp $
    4040 */
     
    4242/*-
    4343 * job.h --
    44  *      Definitions pertaining to the running of jobs in parallel mode.
    45  *      Exported from job.c for the use of remote-execution modules.
     44 *      Definitions pertaining to the running of jobs in parallel mode.
     45 *      Exported from job.c for the use of remote-execution modules.
    4646 */
    4747#ifndef _JOB_H_
    4848#define _JOB_H_
    4949
    50 #define TMPPAT  "/tmp/makeXXXXXXXXXX"
     50#define TMPPAT  "/tmp/makeXXXXXXXXXX"
    5151
    5252/*
     
    5555 * seconds and SEL_USEC is the number of micro-seconds
    5656 */
    57 #define SEL_SEC         0
    58 #define SEL_USEC        100000
     57#define SEL_SEC         0
     58#define SEL_USEC        100000
    5959
    6060
     
    6464 *
    6565 * Each job has several things associated with it:
    66  *      1) The process id of the child shell
    67  *      2) The graph node describing the target being made by this job
    68  *      3) A LstNode for the first command to be saved after the job
    69  *         completes. This is NILLNODE if there was no "..." in the job's
    70  *         commands.
    71  *      4) An FILE* for writing out the commands. This is only
    72  *         used before the job is actually started.
    73  *      5) A union of things used for handling the shell's output. Different
    74  *         parts of the union are used based on the value of the usePipes
    75  *         flag. If it is true, the output is being caught via a pipe and
    76  *         the descriptors of our pipe, an array in which output is line
    77  *         buffered and the current position in that buffer are all
    78  *         maintained for each job. If, on the other hand, usePipes is false,
    79  *         the output is routed to a temporary file and all that is kept
    80  *         is the name of the file and the descriptor open to the file.
    81  *      6) An identifier provided by and for the exclusive use of the
    82  *         Rmt module.
    83  *      7) A word of flags which determine how the module handles errors,
    84  *         echoing, etc. for the job
     66 *      1) The process id of the child shell
     67 *      2) The graph node describing the target being made by this job
     68 *      3) A LstNode for the first command to be saved after the job
     69 *         completes. This is NILLNODE if there was no "..." in the job's
     70 *         commands.
     71 *      4) An FILE* for writing out the commands. This is only
     72 *         used before the job is actually started.
     73 *      5) A union of things used for handling the shell's output. Different
     74 *         parts of the union are used based on the value of the usePipes
     75 *         flag. If it is true, the output is being caught via a pipe and
     76 *         the descriptors of our pipe, an array in which output is line
     77 *         buffered and the current position in that buffer are all
     78 *         maintained for each job. If, on the other hand, usePipes is false,
     79 *         the output is routed to a temporary file and all that is kept
     80 *         is the name of the file and the descriptor open to the file.
     81 *      6) An identifier provided by and for the exclusive use of the
     82 *         Rmt module.
     83 *      7) A word of flags which determine how the module handles errors,
     84 *         echoing, etc. for the job
    8585 *
    8686 * The job "table" is kept as a linked Lst in 'jobs', with the number of
     
    9292 * traversal of the dependency graph.
    9393 */
    94 #define JOB_BUFSIZE     1024
     94#define JOB_BUFSIZE         1024
     95#define JOB_TMPFILESIZE     128
    9596typedef struct Job {
    96     int         pid;        /* The child's process ID */
    97     char        tfile[sizeof(TMPPAT)];
    98                             /* Temporary file to use for job */
    99     GNode       *node;      /* The target the child is making */
    100     LstNode     tailCmds;   /* The node of the first command to be
    101                              * saved when the job has been run */
    102     FILE        *cmdFILE;   /* When creating the shell script, this is
    103                              * where the commands go */
    104     int         rmtID;     /* ID returned from Rmt module */
    105     short       flags;      /* Flags to control treatment of job */
    106 #define JOB_IGNERR      0x001   /* Ignore non-zero exits */
    107 #define JOB_SILENT      0x002   /* no output */
    108 #define JOB_SPECIAL     0x004   /* Target is a special one. i.e. run it locally
    109                                 * if we can't export it and maxLocal is 0 */
    110 #define JOB_IGNDOTS     0x008   /* Ignore "..." lines when processing
    111                                 * commands */
    112 #define JOB_REMOTE      0x010   /* Job is running remotely */
    113 #define JOB_FIRST       0x020   /* Job is first job for the node */
    114 #define JOB_REMIGRATE   0x040   /* Job needs to be remigrated */
    115 #define JOB_RESTART     0x080   /* Job needs to be completely restarted */
    116 #define JOB_RESUME      0x100   /* Job needs to be resumed b/c it stopped,
    117                                 * for some reason */
    118 #define JOB_CONTINUING  0x200   /* We are in the process of resuming this job.
    119                                 * Used to avoid infinite recursion between
    120                                 * JobFinish and JobRestart */
     97    int         pid;        /* The child's process ID */
     98    char        tfile[JOB_TMPFILESIZE];
     99                            /* Temporary file to use for job */
     100    GNode       *node;      /* The target the child is making */
     101    LstNode     tailCmds;   /* The node of the first command to be
     102                             * saved when the job has been run */
     103    FILE        *cmdFILE;   /* When creating the shell script, this is
     104                             * where the commands go */
     105    int         rmtID;     /* ID returned from Rmt module */
     106    short       flags;      /* Flags to control treatment of job */
     107#define JOB_IGNERR      0x001   /* Ignore non-zero exits */
     108#define JOB_SILENT      0x002   /* no output */
     109#define JOB_SPECIAL     0x004   /* Target is a special one. i.e. run it locally
     110                                * if we can't export it and maxLocal is 0 */
     111#define JOB_IGNDOTS     0x008   /* Ignore "..." lines when processing
     112                                * commands */
     113#define JOB_REMOTE      0x010   /* Job is running remotely */
     114#define JOB_FIRST       0x020   /* Job is first job for the node */
     115#define JOB_REMIGRATE   0x040   /* Job needs to be remigrated */
     116#define JOB_RESTART     0x080   /* Job needs to be completely restarted */
     117#define JOB_RESUME      0x100   /* Job needs to be resumed b/c it stopped,
     118                                * for some reason */
     119#define JOB_CONTINUING  0x200   /* We are in the process of resuming this job.
     120                                * Used to avoid infinite recursion between
     121                                * JobFinish and JobRestart */
    121122    union {
    122         struct {
    123             int         op_inPipe;      /* Input side of pipe associated
    124                                         * with job's output channel */
    125             int         op_outPipe;     /* Output side of pipe associated with
    126                                         * job's output channel */
    127             char        op_outBuf[JOB_BUFSIZE + 1];
    128                                         /* Buffer for storing the output of the
    129                                         * job, line by line */
    130             int         op_curPos;      /* Current position in op_outBuf */
    131         }           o_pipe;         /* data used when catching the output via
    132                                      * a pipe */
    133         struct {
    134             char        of_outFile[sizeof(TMPPAT)];
    135                                         /* Name of file to which shell output
    136                                         * was rerouted */
    137             int         of_outFd;       /* Stream open to the output
    138                                         * file. Used to funnel all
    139                                         * from a single job to one file
    140                                         * while still allowing
    141                                         * multiple shell invocations */
    142         }           o_file;         /* Data used when catching the output in
    143                                      * a temporary file */
    144     }           output;     /* Data for tracking a shell's output */
     123        struct {
     124            int         op_inPipe;      /* Input side of pipe associated
     125                                        * with job's output channel */
     126            int         op_outPipe;     /* Output side of pipe associated with
     127                                        * job's output channel */
     128            char        op_outBuf[JOB_BUFSIZE + 1];
     129                                        /* Buffer for storing the output of the
     130                                        * job, line by line */
     131            int         op_curPos;      /* Current position in op_outBuf */
     132        }           o_pipe;         /* data used when catching the output via
     133                                     * a pipe */
     134        struct {
     135            char        of_outFile[JOB_TMPFILESIZE];
     136                                        /* Name of file to which shell output
     137                                        * was rerouted */
     138            int         of_outFd;       /* Stream open to the output
     139                                        * file. Used to funnel all
     140                                        * from a single job to one file
     141                                        * while still allowing
     142                                        * multiple shell invocations */
     143        }           o_file;         /* Data used when catching the output in
     144                                     * a temporary file */
     145    }           output;     /* Data for tracking a shell's output */
    145146} Job;
    146147
    147 #define outPipe         output.o_pipe.op_outPipe
    148 #define inPipe          output.o_pipe.op_inPipe
    149 #define outBuf          output.o_pipe.op_outBuf
    150 #define curPos          output.o_pipe.op_curPos
    151 #define outFile         output.o_file.of_outFile
    152 #define outFd           output.o_file.of_outFd
     148#define outPipe         output.o_pipe.op_outPipe
     149#define inPipe          output.o_pipe.op_inPipe
     150#define outBuf          output.o_pipe.op_outBuf
     151#define curPos          output.o_pipe.op_curPos
     152#define outFile         output.o_file.of_outFile
     153#define outFd           output.o_file.of_outFd
    153154
    154155
     
    157158 * Shell Specifications:
    158159 * Each shell type has associated with it the following information:
    159  *      1) The string which must match the last character of the shell name
    160  *         for the shell to be considered of this type. The longest match
    161  *         wins.
    162  *      2) A command to issue to turn off echoing of command lines
    163  *      3) A command to issue to turn echoing back on again
    164  *      4) What the shell prints, and its length, when given the echo-off
    165  *         command. This line will not be printed when received from the shell
    166  *      5) A boolean to tell if the shell has the ability to control
    167  *         error checking for individual commands.
    168  *      6) The string to turn this checking on.
    169  *      7) The string to turn it off.
    170  *      8) The command-flag to give to cause the shell to start echoing
    171  *         commands right away.
    172  *      9) The command-flag to cause the shell to Lib_Exit when an error is
    173  *         detected in one of the commands.
     160 *      1) The string which must match the last character of the shell name
     161 *         for the shell to be considered of this type. The longest match
     162 *         wins.
     163 *      2) A command to issue to turn off echoing of command lines
     164 *      3) A command to issue to turn echoing back on again
     165 *      4) What the shell prints, and its length, when given the echo-off
     166 *         command. This line will not be printed when received from the shell
     167 *      5) A boolean to tell if the shell has the ability to control
     168 *         error checking for individual commands.
     169 *      6) The string to turn this checking on.
     170 *      7) The string to turn it off.
     171 *      8) The command-flag to give to cause the shell to start echoing
     172 *         commands right away.
     173 *      9) The command-flag to cause the shell to Lib_Exit when an error is
     174 *         detected in one of the commands.
    174175 *
    175176 * Some special stuff goes on if a shell doesn't have error control. In such
     
    181182 */
    182183typedef struct Shell {
    183     char          *name;        /* the name of the shell. For Bourne and C
    184                                 * shells, this is used only to find the
    185                                 * shell description when used as the single
    186                                 * source of a .SHELL target. For user-defined
    187                                 * shells, this is the full path of the shell.
    188                                 */
    189     Boolean       hasEchoCtl;   /* True if both echoOff and echoOn defined */
    190     char          *echoOff;     /* command to turn off echo */
    191     char          *echoOn;      /* command to turn it back on again */
    192     char          *noPrint;     /* command to skip when printing output from
    193                                 * shell. This is usually the command which
    194                                 * was executed to turn off echoing */
    195     int           noPLen;       /* length of noPrint command */
    196     Boolean       hasErrCtl;    /* set if can control error checking for
    197                                 * individual commands */
    198     char          *errCheck;    /* string to turn error checking on */
    199     char          *ignErr;      /* string to turn off error checking */
     184    char          *name;        /* the name of the shell. For Bourne and C
     185                                * shells, this is used only to find the
     186                                * shell description when used as the single
     187                                * source of a .SHELL target. For user-defined
     188                                * shells, this is the full path of the shell.
     189                                */
     190    Boolean       hasEchoCtl;   /* True if both echoOff and echoOn defined */
     191    char          *echoOff;     /* command to turn off echo */
     192    char          *echoOn;      /* command to turn it back on again */
     193    char          *noPrint;     /* command to skip when printing output from
     194                                * shell. This is usually the command which
     195                                * was executed to turn off echoing */
     196    int           noPLen;       /* length of noPrint command */
     197    Boolean       hasErrCtl;    /* set if can control error checking for
     198                                * individual commands */
     199    char          *errCheck;    /* string to turn error checking on */
     200    char          *ignErr;      /* string to turn off error checking */
    200201    /*
    201202     * command-line flags
    202203     */
    203     char          *echo;        /* echo commands */
    204     char          *exit;        /* exit on error */
     204    char          *echo;        /* echo commands */
     205    char          *exit;        /* exit on error */
    205206}               Shell;
    206207
    207208
    208 extern char     *targFmt;       /* Format string for banner that separates
    209                                 * output from multiple jobs. Contains a
    210                                 * single %s where the name of the node being
    211                                 * made should be put. */
    212 extern GNode    *lastNode;      /* Last node for which a banner was printed.
    213                                 * If Rmt module finds it necessary to print
    214                                 * a banner, it should set this to the node
    215                                 * for which the banner was printed */
    216 extern int      nJobs;          /* Number of jobs running (local and remote) */
    217 extern int      nLocal;         /* Number of jobs running locally */
    218 extern Lst      jobs;           /* List of active job descriptors */
    219 extern Lst      stoppedJobs;    /* List of jobs that are stopped or didn't
    220                                 * quite get started */
    221 extern Boolean  jobFull;        /* Non-zero if no more jobs should/will start*/
     209extern char     *targFmt;       /* Format string for banner that separates
     210                                * output from multiple jobs. Contains a
     211                                * single %s where the name of the node being
     212                                * made should be put. */
     213extern GNode    *lastNode;      /* Last node for which a banner was printed.
     214                                * If Rmt module finds it necessary to print
     215                                * a banner, it should set this to the node
     216                                * for which the banner was printed */
     217extern int      nJobs;          /* Number of jobs running (local and remote) */
     218extern int      nLocal;         /* Number of jobs running locally */
     219extern Lst      jobs;           /* List of active job descriptors */
     220extern Lst      stoppedJobs;    /* List of jobs that are stopped or didn't
     221                                * quite get started */
     222extern Boolean  jobFull;        /* Non-zero if no more jobs should/will start*/
    222223
    223224
  • trunk/src/kmk/main.c

    r50 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
     
    4040static const char copyright[] =
    4141"@(#) Copyright (c) 1988, 1989, 1990, 1993\n\
    42         The Regents of the University of California.  All rights reserved.\n";
     42        The Regents of the University of California.  All rights reserved.\n";
    4343#endif /* not lint */
    4444
    4545#ifndef lint
    4646#if 0
    47 static char sccsid[] = "@(#)main.c      8.3 (Berkeley) 3/19/94";
     47static char sccsid[] = "@(#)main.c      8.3 (Berkeley) 3/19/94";
    4848#else
    4949static const char rcsid[] =
    5050  "$FreeBSD: src/usr.bin/make/main.c,v 1.35.2.6 2002/07/24 16:50:18 ru Exp $";
    5151#endif
     52#define KLIBFILEDEF rcsid
    5253#endif /* not lint */
    5354
    5455/*-
    5556 * main.c --
    56  *      The main file for this entire program. Exit routines etc
    57  *      reside here.
     57 *      The main file for this entire program. Exit routines etc
     58 *      reside here.
    5859 *
    5960 * Utility functions defined in this file:
    60  *      Main_ParseArgLine       Takes a line of arguments, breaks them and
    61  *                              treats them as if they were given when first
    62  *                              invoked. Used by the parse module to implement
    63  *                              the .MFLAGS target.
    64  *
    65  *      Error                   Print a tagged error message. The global
    66  *                              MAKE variable must have been defined. This
    67  *                              takes a format string and two optional
    68  *                              arguments for it.
    69  *
    70  *      Fatal                   Print an error message and exit. Also takes
    71  *                              a format string and two arguments.
    72  *
    73  *      Punt                    Aborts all jobs and exits with a message. Also
    74  *                              takes a format string and two arguments.
    75  *
    76  *      Finish                  Finish things up by printing the number of
    77  *                              errors which occured, as passed to it, and
    78  *                              exiting.
    79  */
    80 
    81 #if defined(USE_KLIB) //|| defined(KMK)
     61 *      Main_ParseArgLine       Takes a line of arguments, breaks them and
     62 *                              treats them as if they were given when first
     63 *                              invoked. Used by the parse module to implement
     64 *                              the .MFLAGS target.
     65 *
     66 *      Error                   Print a tagged error message. The global
     67 *                              MAKE variable must have been defined. This
     68 *                              takes a format string and two optional
     69 *                              arguments for it.
     70 *
     71 *      Fatal                   Print an error message and exit. Also takes
     72 *                              a format string and two arguments.
     73 *
     74 *      Punt                    Aborts all jobs and exits with a message. Also
     75 *                              takes a format string and two arguments.
     76 *
     77 *      Finish                  Finish things up by printing the number of
     78 *                              errors which occured, as passed to it, and
     79 *                              exiting.
     80 */
     81
     82#if defined(USE_KLIB)
    8283    #define KLIB_INSTRICT
    8384    #include <kLib/kLib.h>
     
    9697#endif
    9798#ifndef MACHINE
    98 # if !defined(__IBMC__)
    9999#  include <sys/utsname.h>
    100 # endif
    101 #endif
    102 #if !defined(__IBMC__)
     100#endif
     101#ifndef USE_KLIB
    103102#include <sys/wait.h>
     103#endif
    104104#include <err.h>
    105 #endif
    106105#include <stdlib.h>
    107106#include <errno.h>
    108107#include <fcntl.h>
    109108#include <stdio.h>
    110 #if !defined(__IBMC__) && !defined(__EMX__)
     109#if defined(__EMX__)
    111110#include <sysexits.h>
    112111#endif
    113 #if defined(__STDC__) || defined(__IBMC__)
     112#if defined(__STDC__)
    114113#include <stdarg.h>
    115114#else
     
    129128  #define S_ISDIR(mode)  (((mode) & S_IFMT) == S_IFDIR)
    130129 #endif
    131 #endif
     130 char *realpath(const char *pszFileName, char *pszResolvedName);
     131 #define snprintf kStrNFormat
     132#endif
     133#include <getopt.h>
    132134#include "make.h"
    133135#include "hash.h"
     
    136138#include "pathnames.h"
    137139
    138 #ifndef DEFMAXLOCAL
    139 #define DEFMAXLOCAL DEFMAXJOBS
    140 #endif  /* DEFMAXLOCAL */
    141 
    142 #define MAKEFLAGS       ".MAKEFLAGS"
    143 
    144 Lst                     create;         /* Targets to be made */
    145 time_t                  now;            /* Time at start of make */
    146 GNode                   *DEFAULT;       /* .DEFAULT node */
    147 Boolean                 allPrecious;    /* .PRECIOUS given on line by itself */
    148 
    149 static Boolean          noBuiltins;     /* -r flag */
    150 static Lst              makefiles;      /* ordered list of makefiles to read */
    151 static Boolean          printVars;      /* print value of one or more vars */
    152 static Boolean          expandVars;     /* fully expand printed variables */
    153 static Lst              variables;      /* list of variables to print */
    154 int                     maxJobs;        /* -j argument */
     140#ifndef DEFMAXLOCAL
     141#define DEFMAXLOCAL DEFMAXJOBS
     142#endif  /* DEFMAXLOCAL */
     143
     144#define MAKEFLAGS       ".MAKEFLAGS"
     145
     146Lst                     create;         /* Targets to be made */
     147time_t                  now;            /* Time at start of make */
     148GNode                   *DEFAULT;       /* .DEFAULT node */
     149Boolean                 allPrecious;    /* .PRECIOUS given on line by itself */
     150
     151static Boolean          noBuiltins;     /* -r flag */
     152static Lst              makefiles;      /* ordered list of makefiles to read */
     153static Boolean          printVars;      /* print value of one or more vars */
     154static Boolean          expandVars;     /* fully expand printed variables */
     155static Lst              variables;      /* list of variables to print */
     156int                     maxJobs;        /* -j argument */
    155157static Boolean          forceJobs;      /* -j argument given */
    156 static int              maxLocal;       /* -L argument */
    157 Boolean                 compatMake;     /* -B argument */
    158 Boolean                 debug;          /* -d flag */
    159 Boolean                 noExecute;      /* -n flag */
    160 Boolean                 keepgoing;      /* -k flag */
    161 Boolean                 queryFlag;      /* -q flag */
    162 Boolean                 touchFlag;      /* -t flag */
    163 Boolean                 usePipes;       /* !-P flag */
    164 Boolean                 ignoreErrors;   /* -i flag */
    165 Boolean                 beSilent;       /* -s flag */
    166 Boolean                 beVerbose;      /* -v flag */
    167 Boolean                 oldVars;        /* variable substitution style */
    168 Boolean                 checkEnvFirst;  /* -e flag */
    169 Lst                     envFirstVars;   /* (-E) vars to override from env */
    170 static Boolean          jobsRunning;    /* TRUE if the jobs might be running */
     158static int              maxLocal;       /* -L argument */
     159Boolean                 compatMake;     /* -B argument */
     160Boolean                 debug;          /* -d flag */
     161Boolean                 noExecute;      /* -n flag */
     162Boolean                 keepgoing;      /* -k flag */
     163Boolean                 queryFlag;      /* -q flag */
     164Boolean                 touchFlag;      /* -t flag */
     165Boolean                 usePipes;       /* !-P flag */
     166Boolean                 ignoreErrors;   /* -i flag */
     167Boolean                 beSilent;       /* -s flag */
     168Boolean                 beVerbose;      /* -v flag */
     169Boolean                 oldVars;        /* variable substitution style */
     170Boolean                 checkEnvFirst;  /* -e flag */
     171Lst                     envFirstVars;   /* (-E) vars to override from env */
     172static Boolean          jobsRunning;    /* TRUE if the jobs might be running */
    171173#ifdef NMAKE
    172174static Boolean          go_to_objdir;   /* ! -o flag */
    173175#endif
    174 static void             MainParseArgs __P((int, char **));
    175 char *                  chdir_verify_path __P((char *, char *));
    176 static int              ReadMakefile __P((ClientData, ClientData));
    177 static void             usage __P((void));
    178 
    179 static char *curdir;                    /* startup directory */
    180 static char *objdir;                    /* where we chdir'ed to */
     176static void             MainParseArgs __P((int, char **));
     177char *                  chdir_verify_path __P((char *, char *));
     178static int              ReadMakefile __P((ClientData, ClientData));
     179static void             usage __P((void));
     180
     181static char *curdir;                    /* startup directory */
     182static char *objdir;                    /* where we chdir'ed to */
     183#ifdef KMK
     184char *                  argv0 = NULL;
     185#endif
    181186
    182187/*-
    183188 * MainParseArgs --
    184  *      Parse a given argument vector. Called from main() and from
    185  *      Main_ParseArgLine() when the .MAKEFLAGS target is used.
    186  *
    187  *      XXX: Deal with command line overriding .MAKEFLAGS in makefile
     189 *      Parse a given argument vector. Called from main() and from
     190 *      Main_ParseArgLine() when the .MAKEFLAGS target is used.
     191 *
     192 *      XXX: Deal with command line overriding .MAKEFLAGS in makefile
    188193 *
    189194 * Results:
    190  *      None
     195 *      None
    191196 *
    192197 * Side Effects:
    193  *      Various global and local flags will be set depending on the flags
    194  *      given
     198 *      Various global and local flags will be set depending on the flags
     199 *      given
    195200 */
    196201static void
    197202MainParseArgs(argc, argv)
    198         int argc;
    199         char **argv;
    200 {
    201         extern int optind;
    202         extern char *optarg;
    203         char *p;
    204         int c;
    205 
    206         optind = 1;     /* since we're called more than once */
     203        int argc;
     204        char **argv;
     205{
     206        extern int optind;
     207        extern char *optarg;
     208        char *p;
     209        int c;
     210
     211        optind = 1;     /* since we're called more than once */
    207212#ifdef REMOTE
    208213# ifdef NMAKE
     
    218223# endif
    219224#endif
    220 rearg:  while((c = getopt(argc, argv, OPTFLAGS)) != -1) {
    221                 switch(c) {
    222                 case 'D':
    223                         Var_Set(optarg, "1", VAR_GLOBAL);
    224                         Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL);
    225                         Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
    226                         break;
    227                 case 'I':
    228                         Parse_AddIncludeDir(optarg);
    229                         Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL);
    230                         Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
    231                         break;
    232                 case 'V':
    233                         printVars = TRUE;
    234                         (void)Lst_AtEnd(variables, (ClientData)optarg);
    235                         Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL);
    236                         Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
    237                         break;
    238                 case 'X':
    239                         expandVars = FALSE;
    240                         break;
    241                 case 'B':
    242                         compatMake = TRUE;
    243                         Var_Append(MAKEFLAGS, "-B", VAR_GLOBAL);
    244                         break;
     225rearg:  while((c = getopt(argc, argv, OPTFLAGS)) != -1) {
     226                switch(c) {
     227                case 'D':
     228                        Var_Set(optarg, "1", VAR_GLOBAL);
     229                        Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL);
     230                        Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
     231                        break;
     232                case 'I':
     233                        Parse_AddIncludeDir(optarg);
     234                        Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL);
     235                        Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
     236                        break;
     237                case 'V':
     238                        printVars = TRUE;
     239                        (void)Lst_AtEnd(variables, (ClientData)optarg);
     240                        Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL);
     241                        Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
     242                        break;
     243                case 'X':
     244                        expandVars = FALSE;
     245                        break;
     246                case 'B':
     247                        compatMake = TRUE;
     248                        Var_Append(MAKEFLAGS, "-B", VAR_GLOBAL);
     249                        break;
    245250#ifdef REMOTE
    246                 case 'L': {
    247                         char *endptr;
    248 
    249                         maxLocal = strtol(optarg, &endptr, 10);
    250                         if (maxLocal < 0 || *endptr != '\0') {
    251                                 warnx("illegal number, -L argument -- %s",
    252                                     optarg);
    253                                 usage();
    254                         }
    255                         Var_Append(MAKEFLAGS, "-L", VAR_GLOBAL);
    256                         Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
    257                         break;
    258                 }
    259 #endif
    260                 case 'P':
    261                         usePipes = FALSE;
    262                         Var_Append(MAKEFLAGS, "-P", VAR_GLOBAL);
    263                         break;
    264                 case 'S':
    265                         keepgoing = FALSE;
    266                         Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL);
    267                         break;
    268                 case 'd': {
    269                         char *modules = optarg;
    270 
    271                         for (; *modules; ++modules)
    272                                 switch (*modules) {
    273                                 case 'A':
    274                                         debug = ~0;
    275                                         break;
    276                                 case 'a':
     251                case 'L': {
     252                        char *endptr;
     253
     254                        maxLocal = strtol(optarg, &endptr, 10);
     255                        if (maxLocal < 0 || *endptr != '\0') {
     256                                warnx("illegal number, -L argument -- %s",
     257                                    optarg);
     258                                usage();
     259                        }
     260                        Var_Append(MAKEFLAGS, "-L", VAR_GLOBAL);
     261                        Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
     262                        break;
     263                }
     264#endif
     265                case 'P':
     266                        usePipes = FALSE;
     267                        Var_Append(MAKEFLAGS, "-P", VAR_GLOBAL);
     268                        break;
     269                case 'S':
     270                        keepgoing = FALSE;
     271                        Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL);
     272                        break;
     273                case 'd': {
     274                        char *modules = optarg;
     275
     276                        for (; *modules; ++modules)
     277                                switch (*modules) {
     278                                case 'A':
     279                                        debug = ~0;
     280                                        break;
     281                                case 'a':
    277282#ifdef USE_ARCHIVES
    278                                         debug |= DEBUG_ARCH;
     283                                        debug |= DEBUG_ARCH;
    279284#endif /* else ignore */
    280                                         break;
    281                                 case 'c':
    282                                         debug |= DEBUG_COND;
    283                                         break;
    284                                 case 'd':
    285                                         debug |= DEBUG_DIR;
    286                                         break;
    287                                 case 'f':
    288                                         debug |= DEBUG_FOR;
    289                                         break;
    290                                 case 'g':
    291                                         if (modules[1] == '1') {
    292                                                 debug |= DEBUG_GRAPH1;
    293                                                 ++modules;
    294                                         }
    295                                         else if (modules[1] == '2') {
    296                                                 debug |= DEBUG_GRAPH2;
    297                                                 ++modules;
    298                                         }
    299                                         break;
    300                                 case 'j':
    301                                         debug |= DEBUG_JOB;
    302                                         break;
    303                                 case 'l':
    304                                         debug |= DEBUG_LOUD;
    305                                         break;
    306                                 case 'm':
    307                                         debug |= DEBUG_MAKE;
    308                                         break;
     285                                        break;
     286                                case 'c':
     287                                        debug |= DEBUG_COND;
     288                                        break;
     289                                case 'd':
     290                                        debug |= DEBUG_DIR;
     291                                        break;
     292                                case 'f':
     293                                        debug |= DEBUG_FOR;
     294                                        break;
     295                                case 'g':
     296                                        if (modules[1] == '1') {
     297                                                debug |= DEBUG_GRAPH1;
     298                                                ++modules;
     299                                        }
     300                                        else if (modules[1] == '2') {
     301                                                debug |= DEBUG_GRAPH2;
     302                                                ++modules;
     303                                        }
     304                                        break;
     305                                case 'j':
     306                                        debug |= DEBUG_JOB;
     307                                        break;
     308                                case 'l':
     309                                        debug |= DEBUG_LOUD;
     310                                        break;
     311                                case 'm':
     312                                        debug |= DEBUG_MAKE;
     313                                        break;
    309314                                case 'p':     /*kso*/
    310                                         debug |= DEBUG_PARSE;
     315                                        debug |= DEBUG_PARSE;
    311316                                        break;
    312317                                case 's':
    313                                         debug |= DEBUG_SUFF;
    314                                         break;
    315                                 case 't':
    316                                         debug |= DEBUG_TARG;
    317                                         break;
    318                                 case 'v':
    319                                         debug |= DEBUG_VAR;
    320                                         break;
    321                                 default:
    322                                         warnx("illegal argument to d option -- %c", *modules);
    323                                         usage();
    324                                 }
    325                         Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL);
    326                         Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
    327                         break;
    328                 }
    329                 case 'E':
    330                         p = emalloc(strlen(optarg) + 1);
    331                         (void)strcpy(p, optarg);
    332                         (void)Lst_AtEnd(envFirstVars, (ClientData)p);
    333                         Var_Append(MAKEFLAGS, "-E", VAR_GLOBAL);
    334                         Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
    335                         break;
    336                 case 'e':
    337                         checkEnvFirst = TRUE;
    338                         Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL);
    339                         break;
    340                 case 'f':
    341                         (void)Lst_AtEnd(makefiles, (ClientData)optarg);
    342                         break;
    343                 case 'i':
    344                         ignoreErrors = TRUE;
    345                         Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL);
    346                         break;
    347                 case 'j': {
    348                         char *endptr;
    349 
    350                         forceJobs = TRUE;
    351                         maxJobs = strtol(optarg, &endptr, 10);
    352                         if (maxJobs <= 0 || *endptr != '\0') {
    353                                 warnx("illegal number, -j argument -- %s",
    354                                     optarg);
    355                                 usage();
    356                         }
     318                                        debug |= DEBUG_SUFF;
     319                                        break;
     320                                case 't':
     321                                        debug |= DEBUG_TARG;
     322                                        break;
     323                                case 'v':
     324                                        debug |= DEBUG_VAR;
     325                                        break;
     326                                default:
     327                                        warnx("illegal argument to d option -- %c", *modules);
     328                                        usage();
     329                                }
     330                        Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL);
     331                        Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
     332                        break;
     333                }
     334                case 'E':
     335                        p = emalloc(strlen(optarg) + 1);
     336                        (void)strcpy(p, optarg);
     337                        (void)Lst_AtEnd(envFirstVars, (ClientData)p);
     338                        Var_Append(MAKEFLAGS, "-E", VAR_GLOBAL);
     339                        Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
     340                        break;
     341                case 'e':
     342                        checkEnvFirst = TRUE;
     343                        Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL);
     344                        break;
     345                case 'f':
     346                        (void)Lst_AtEnd(makefiles, (ClientData)optarg);
     347                        break;
     348                case 'i':
     349                        ignoreErrors = TRUE;
     350                        Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL);
     351                        break;
     352                case 'j': {
     353                        char *endptr;
     354
     355                        forceJobs = TRUE;
     356                        maxJobs = strtol(optarg, &endptr, 10);
     357                        if (maxJobs <= 0 || *endptr != '\0') {
     358                                warnx("illegal number, -j argument -- %s",
     359                                    optarg);
     360                                usage();
     361                        }
    357362#ifndef REMOTE
    358                         maxLocal = maxJobs;
    359 #endif
    360                         Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL);
    361                         Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
    362                         break;
    363                 }
    364                 case 'k':
    365                         keepgoing = TRUE;
    366                         Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL);
    367                         break;
    368                 case 'm':
    369                         Dir_AddDir(sysIncPath, optarg);
    370                         Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL);
    371                         Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
    372                         break;
    373                 case 'n':
    374                         noExecute = TRUE;
    375                         Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL);
    376                         break;
     363                        maxLocal = maxJobs;
     364#endif
     365                        Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL);
     366                        Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
     367                        break;
     368                }
     369                case 'k':
     370                        keepgoing = TRUE;
     371                        Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL);
     372                        break;
     373                case 'm':
     374                        Dir_AddDir(sysIncPath, optarg);
     375                        Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL);
     376                        Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
     377                        break;
     378                case 'n':
     379                        noExecute = TRUE;
     380                        Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL);
     381                        break;
    377382#ifdef NMAKE
    378383                case 'o':
    379384                        go_to_objdir = TRUE;
    380                         Var_Append(MAKEFLAGS, "-o", VAR_GLOBAL);
    381                         break;
    382 #endif
    383                 case 'q':
    384                         queryFlag = TRUE;
    385                         /* Kind of nonsensical, wot? */
    386                         Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL);
    387                         break;
    388                 case 'r':
    389                         noBuiltins = TRUE;
    390                         Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL);
    391                         break;
    392                 case 's':
    393                         beSilent = TRUE;
    394                         Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL);
    395                         break;
    396                 case 't':
    397                         touchFlag = TRUE;
    398                         Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL);
    399                         break;
    400                 case 'v':
    401                         beVerbose = TRUE;
    402                         Var_Append(MAKEFLAGS, "-v", VAR_GLOBAL);
    403                         break;
    404                 default:
    405                 case '?':
    406                         usage();
    407                 }
    408         }
    409 
    410         oldVars = TRUE;
    411 
    412         /*
    413         * See if the rest of the arguments are variable assignments and
    414         * perform them if so. Else take them to be targets and stuff them
    415         * on the end of the "create" list.
    416         */
    417         for (argv += optind, argc -= optind; *argv; ++argv, --argc)
    418                 if (Parse_IsVar(*argv))
    419                         Parse_DoVar(*argv, VAR_CMD);
    420                 else {
    421                         if (!**argv)
    422                                 Punt("illegal (null) argument.");
    423                         if (**argv == '-') {
    424                                 if ((*argv)[1])
    425                                         optind = 0;     /* -flag... */
    426                                 else
    427                                         optind = 1;     /* - */
    428                                 goto rearg;
    429                         }
    430                         (void)Lst_AtEnd(create, (ClientData)estrdup(*argv));
    431                 }
     385                        Var_Append(MAKEFLAGS, "-o", VAR_GLOBAL);
     386                        break;
     387#endif
     388                case 'q':
     389                        queryFlag = TRUE;
     390                        /* Kind of nonsensical, wot? */
     391                        Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL);
     392                        break;
     393                case 'r':
     394                        noBuiltins = TRUE;
     395                        Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL);
     396                        break;
     397                case 's':
     398                        beSilent = TRUE;
     399                        Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL);
     400                        break;
     401                case 't':
     402                        touchFlag = TRUE;
     403                        Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL);
     404                        break;
     405                case 'v':
     406                        beVerbose = TRUE;
     407                        Var_Append(MAKEFLAGS, "-v", VAR_GLOBAL);
     408                        break;
     409                default:
     410                case '?':
     411                        usage();
     412                }
     413        }
     414
     415        oldVars = TRUE;
     416
     417        /*
     418        * See if the rest of the arguments are variable assignments and
     419        * perform them if so. Else take them to be targets and stuff them
     420        * on the end of the "create" list.
     421        */
     422        for (argv += optind, argc -= optind; *argv; ++argv, --argc)
     423                if (Parse_IsVar(*argv))
     424                        Parse_DoVar(*argv, VAR_CMD);
     425                else {
     426                        if (!**argv)
     427                                Punt("illegal (null) argument.");
     428                        if (**argv == '-') {
     429                                if ((*argv)[1])
     430                                        optind = 0;     /* -flag... */
     431                                else
     432                                        optind = 1;     /* - */
     433                                goto rearg;
     434                        }
     435                        (void)Lst_AtEnd(create, (ClientData)estrdup(*argv));
     436                }
    432437}
    433438
    434439/*-
    435440 * Main_ParseArgLine --
    436  *      Used by the parse module when a .MFLAGS or .MAKEFLAGS target
    437  *      is encountered and by main() when reading the .MAKEFLAGS envariable.
    438  *      Takes a line of arguments and breaks it into its
    439  *      component words and passes those words and the number of them to the
    440  *      MainParseArgs function.
    441  *      The line should have all its leading whitespace removed.
     441 *      Used by the parse module when a .MFLAGS or .MAKEFLAGS target
     442 *      is encountered and by main() when reading the .MAKEFLAGS envariable.
     443 *      Takes a line of arguments and breaks it into its
     444 *      component words and passes those words and the number of them to the
     445 *      MainParseArgs function.
     446 *      The line should have all its leading whitespace removed.
    442447 *
    443448 * Results:
    444  *      None
     449 *      None
    445450 *
    446451 * Side Effects:
    447  *      Only those that come from the various arguments.
     452 *      Only those that come from the various arguments.
    448453 */
    449454void
    450455Main_ParseArgLine(line)
    451         char *line;                     /* Line to fracture */
    452 {
    453         char **argv;                    /* Manufactured argument vector */
    454         int argc;                       /* Number of arguments in argv */
    455 
    456         if (line == NULL)
    457                 return;
    458         for (; *line == ' '; ++line)
    459                 continue;
    460         if (!*line)
    461                 return;
    462 
    463         argv = brk_string(line, &argc, TRUE);
    464         MainParseArgs(argc, argv);
     456        char *line;                     /* Line to fracture */
     457{
     458        char **argv;                    /* Manufactured argument vector */
     459        int argc;                       /* Number of arguments in argv */
     460
     461        if (line == NULL)
     462                return;
     463        for (; *line == ' '; ++line)
     464                continue;
     465        if (!*line)
     466                return;
     467
     468        argv = brk_string(line, &argc, TRUE);
     469        MainParseArgs(argc, argv);
    465470}
    466471
    467472char *
    468473chdir_verify_path(path, obpath)
    469         char *path;
    470         char *obpath;
     474        char *path;
     475        char *obpath;
    471476{
    472477        struct stat sb;
     
    476481#endif
    477482
    478         if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
    479                 if (chdir(path)) {
    480                         warn("warning: %s", path);
    481                         return 0;
    482                 }
    483                 else {
    484                         if (path[0] != '/') {
    485                                 (void) snprintf(obpath, MAXPATHLEN, "%s/%s",
    486                                                 curdir, path);
    487                                 return obpath;
    488                         }
    489                         else
    490                                 return path;
    491                 }
    492         }
    493 
    494         return 0;
     483        if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
     484                if (chdir(path)) {
     485                        warn("warning: %s", path);
     486                        return 0;
     487                }
     488                else {
     489                        if (path[0] != '/') {
     490                                (void) snprintf(obpath, MAXPATHLEN, "%s/%s",
     491                                                curdir, path);
     492                                return obpath;
     493                        }
     494                        else
     495                                return path;
     496                }
     497        }
     498
     499        return 0;
    495500}
    496501
     
    498503/*-
    499504 * main --
    500  *      The main function, for obvious reasons. Initializes variables
    501  *      and a few modules, then parses the arguments give it in the
    502  *      environment and on the command line. Reads the system makefile
    503  *      followed by either Makefile, makefile or the file given by the
    504  *      -f argument. Sets the .MAKEFLAGS PMake variable based on all the
    505  *      flags it has received by then uses either the Make or the Compat
    506  *      module to create the initial list of targets.
     505 *      The main function, for obvious reasons. Initializes variables
     506 *      and a few modules, then parses the arguments give it in the
     507 *      environment and on the command line. Reads the system makefile
     508 *      followed by either Makefile, makefile or the file given by the
     509 *      -f argument. Sets the .MAKEFLAGS PMake variable based on all the
     510 *      flags it has received by then uses either the Make or the Compat
     511 *      module to create the initial list of targets.
    507512 *
    508513 * Results:
    509  *      If -q was given, exits -1 if anything was out-of-date. Else it exits
    510  *      0.
     514 *      If -q was given, exits -1 if anything was out-of-date. Else it exits
     515 *      0.
    511516 *
    512517 * Side Effects:
    513  *      The program exits when done. Targets are created. etc. etc. etc.
     518 *      The program exits when done. Targets are created. etc. etc. etc.
    514519 */
    515520int
     
    519524main(argc, argv)
    520525#endif
    521         int argc;
    522         char **argv;
    523 {
    524         Lst targs;      /* target nodes to create -- passed to Make_Init */
    525         Boolean outOfDate = TRUE;       /* FALSE if all targets up to date */
    526         struct stat sa;
    527         char *p, *p1, *path, *pathp;
     526        int argc;
     527        char **argv;
     528{
     529        Lst targs;      /* target nodes to create -- passed to Make_Init */
     530        Boolean outOfDate = TRUE;       /* FALSE if all targets up to date */
     531        struct stat sa;
     532        char *p, *p1, *path, *pathp;
    528533#ifdef WANT_ENV_PWD
    529         struct stat sb;
    530         char *pwd;
    531 #endif
    532         char mdpath[MAXPATHLEN + 1];
    533         char obpath[MAXPATHLEN + 1];
    534         char cdpath[MAXPATHLEN + 1];
    535         char *machine = getenv("MACHINE");
    536         char *machine_arch = getenv("MACHINE_ARCH");
    537         char *machine_cpu = getenv("MACHINE_CPU");
    538         Lst sysMkPath;                  /* Path of sys.mk */
    539         char *cp = NULL, *start;
    540                                         /* avoid faults on read-only strings */
     534        struct stat sb;
     535        char *pwd;
     536#endif
     537        char mdpath[MAXPATHLEN + 1];
     538        char obpath[MAXPATHLEN + 1];
     539        char cdpath[MAXPATHLEN + 1];
     540        char *machine = getenv("MACHINE");
     541        char *machine_arch = getenv("MACHINE_ARCH");
     542        char *machine_cpu = getenv("MACHINE_CPU");
     543        Lst sysMkPath;                  /* Path of sys.mk */
     544        char *cp = NULL, *start;
     545                                        /* avoid faults on read-only strings */
    541546        #ifndef KMK
    542         static char syspath[] = _PATH_DEFSYSPATH;
     547        static char syspath[] = _PATH_DEFSYSPATH;
    543548        #endif
    544549
     550        #ifdef KMK
     551        /*
     552         * Save ourselfs.
     553         */
     554        argv0 = argv[0];
     555        #endif
     556
    545557#ifdef RLIMIT_NOFILE
    546         /*
    547         * get rid of resource limit on file descriptors
    548         */
    549         {
    550                 struct rlimit rl;
    551                 if (getrlimit(RLIMIT_NOFILE, &rl) != -1 &&
    552                     rl.rlim_cur != rl.rlim_max) {
    553                         rl.rlim_cur = rl.rlim_max;
    554                         (void) setrlimit(RLIMIT_NOFILE, &rl);
    555                 }
    556         }
    557 #endif
    558         /*
    559         * Find where we are and take care of PWD for the automounter...
    560         * All this code is so that we know where we are when we start up
    561         * on a different machine with pmake.
    562         */
    563         curdir = cdpath;
    564         if (getcwd(curdir, MAXPATHLEN) == NULL)
    565                 err(2, NULL);
    566 
    567         if (stat(curdir, &sa) == -1)
    568             err(2, "%s", curdir);
     558        /*
     559        * get rid of resource limit on file descriptors
     560        */
     561        {
     562                struct rlimit rl;
     563                if (getrlimit(RLIMIT_NOFILE, &rl) != -1 &&
     564                    rl.rlim_cur != rl.rlim_max) {
     565                        rl.rlim_cur = rl.rlim_max;
     566                        (void) setrlimit(RLIMIT_NOFILE, &rl);
     567                }
     568        }
     569#endif
     570        /*
     571        * Find where we are and take care of PWD for the automounter...
     572        * All this code is so that we know where we are when we start up
     573        * on a different machine with pmake.
     574        */
     575        curdir = cdpath;
     576        if (getcwd(curdir, MAXPATHLEN) == NULL)
     577                err(2, NULL);
     578
     579        if (stat(curdir, &sa) == -1)
     580            err(2, "%s", curdir);
    569581
    570582#ifdef WANT_ENV_PWD
    571         if ((pwd = getenv("PWD")) != NULL) {
    572             if (stat(pwd, &sb) == 0 && sa.st_ino == sb.st_ino &&
    573                 sa.st_dev == sb.st_dev)
    574                 (void) strcpy(curdir, pwd);
    575         }
     583        if ((pwd = getenv("PWD")) != NULL) {
     584            if (stat(pwd, &sb) == 0 && sa.st_ino == sb.st_ino &&
     585                sa.st_dev == sb.st_dev)
     586                (void) strcpy(curdir, pwd);
     587        }
    576588#endif
    577589
    578590#if defined(__i386__) && defined(__FreeBSD_version) && \
    579591    __FreeBSD_version > 300003
    580         /*
    581         * PC-98 kernel sets the `i386' string to the utsname.machine and
    582         * it cannot be distinguished from IBM-PC by uname(3).  Therefore,
    583         * we check machine.ispc98 and adjust the machine variable before
    584         * using usname(3) below.
    585         * NOTE: machdep.ispc98 was defined on 1998/8/31. At that time,
    586         * __FreeBSD_version was defined as 300003. So, this check can
    587         * safely be done with any kernel with version > 300003.
    588         */
    589         if (!machine) {
    590                 int     ispc98;
    591                 size_t  len;
    592 
    593                 len = sizeof(ispc98);
    594                 if (!sysctlbyname("machdep.ispc98", &ispc98, &len, NULL, 0)) {
    595                         if (ispc98)
    596                                 machine = "pc98";
    597                 }
    598         }
    599 #endif
    600 
    601         /*
    602         * Get the name of this type of MACHINE from utsname
    603         * so we can share an executable for similar machines.
    604         * (i.e. m68k: amiga hp300, mac68k, sun3, ...)
    605         *
    606         * Note that while MACHINE is decided at run-time,
    607         * MACHINE_ARCH is always known at compile time.
    608         */
    609         if (!machine) {
     592        /*
     593        * PC-98 kernel sets the `i386' string to the utsname.machine and
     594        * it cannot be distinguished from IBM-PC by uname(3).  Therefore,
     595        * we check machine.ispc98 and adjust the machine variable before
     596        * using usname(3) below.
     597        * NOTE: machdep.ispc98 was defined on 1998/8/31. At that time,
     598        * __FreeBSD_version was defined as 300003. So, this check can
     599        * safely be done with any kernel with version > 300003.
     600        */
     601        if (!machine) {
     602                int     ispc98;
     603                size_t  len;
     604
     605                len = sizeof(ispc98);
     606                if (!sysctlbyname("machdep.ispc98", &ispc98, &len, NULL, 0)) {
     607                        if (ispc98)
     608                                machine = "pc98";
     609                }
     610        }
     611#endif
     612
     613        /*
     614        * Get the name of this type of MACHINE from utsname
     615        * so we can share an executable for similar machines.
     616        * (i.e. m68k: amiga hp300, mac68k, sun3, ...)
     617        *
     618        * Note that while MACHINE is decided at run-time,
     619        * MACHINE_ARCH is always known at compile time.
     620        */
     621        if (!machine) {
    610622#ifndef MACHINE
    611             struct utsname utsname;
    612 
    613             if (uname(&utsname) == -1) {
    614                     perror(MAKE_NAME ": uname");
    615                     exit(2);
    616             }
    617             machine = utsname.machine;
    618 #else
    619             machine = MACHINE;
    620 #endif
    621         }
    622 
    623         if (!machine_arch) {
     623            struct utsname utsname;
     624
     625            if (uname(&utsname) == -1) {
     626                    perror(MAKE_NAME ": uname");
     627                    exit(2);
     628            }
     629            machine = utsname.machine;
     630#else
     631            machine = MACHINE;
     632#endif
     633        }
     634
     635        if (!machine_arch) {
    624636#ifndef MACHINE_ARCH
    625                 machine_arch = "unknown";
    626 #else
    627                 machine_arch = MACHINE_ARCH;
    628 #endif
    629         }
    630 
    631         /*
    632         * Set machine_cpu to the minumum supported CPU revision based
    633         * on the target architecture, if not already set.
    634         */
    635         if (!machine_cpu) {
    636                 if (!strcmp(machine_arch, "i386"))
    637                         machine_cpu = "i386";
    638                 else if (!strcmp(machine_arch, "alpha"))
    639                         machine_cpu = "ev4";
    640                 else
    641                         machine_cpu = "unknown";
    642         }
    643        
     637                machine_arch = "unknown";
     638#else
     639                machine_arch = MACHINE_ARCH;
     640#endif
     641        }
     642
     643        /*
     644        * Set machine_cpu to the minumum supported CPU revision based
     645        * on the target architecture, if not already set.
     646        */
     647        if (!machine_cpu) {
     648                if (!strcmp(machine_arch, "i386"))
     649                        machine_cpu = "i386";
     650                else if (!strcmp(machine_arch, "alpha"))
     651                        machine_cpu = "ev4";
     652                else
     653                        machine_cpu = "unknown";
     654        }
     655
    644656        #ifdef KMK
    645657        /* @todo figure out how to set object directory! */
    646658        #else
    647         /*
    648         * The object directory location is determined using the
    649         * following order of preference:
    650         *
    651          *      1. MAKEOBJDIRPREFIX`cwd`
    652          *      2. MAKEOBJDIR
    653          *      3. _PATH_OBJDIR.${MACHINE}
    654          *      4. _PATH_OBJDIR
    655          *      5. _PATH_OBJDIRPREFIX`cwd`
    656         *
    657         * If one of the first two fails, use the current directory.
    658         * If the remaining three all fail, use the current directory.
    659         *
    660         * Once things are initted,
    661         * have to add the original directory to the search path,
    662         * and modify the paths for the Makefiles apropriately.  The
    663         * current directory is also placed as a variable for make scripts.
    664         */
    665         if (!(pathp = getenv("MAKEOBJDIRPREFIX"))) {
    666                 if (!(path = getenv("MAKEOBJDIR"))) {
    667                         path = _PATH_OBJDIR;
    668                         pathp = _PATH_OBJDIRPREFIX;
    669                         (void) snprintf(mdpath, MAXPATHLEN, "%s.%s",
    670                                         path, machine);
    671                         if (!(objdir = chdir_verify_path(mdpath, obpath)))
    672                                 if (!(objdir=chdir_verify_path(path, obpath))) {
    673                                         (void) snprintf(mdpath, MAXPATHLEN,
    674                                                         "%s%s", pathp, curdir);
    675                                         if (!(objdir=chdir_verify_path(mdpath,
    676                                                                        obpath)))
    677                                                 objdir = curdir;
    678                                 }
    679                 }
    680                 else if (!(objdir = chdir_verify_path(path, obpath)))
    681                         objdir = curdir;
    682         }
    683         else {
    684                 (void) snprintf(mdpath, MAXPATHLEN, "%s%s", pathp, curdir);
    685                 if (!(objdir = chdir_verify_path(mdpath, obpath)))
    686                         objdir = curdir;
    687         }
     659        /*
     660        * The object directory location is determined using the
     661        * following order of preference:
     662        *
     663         *      1. MAKEOBJDIRPREFIX`cwd`
     664         *      2. MAKEOBJDIR
     665         *      3. _PATH_OBJDIR.${MACHINE}
     666         *      4. _PATH_OBJDIR
     667         *      5. _PATH_OBJDIRPREFIX`cwd`
     668        *
     669        * If one of the first two fails, use the current directory.
     670        * If the remaining three all fail, use the current directory.
     671        *
     672        * Once things are initted,
     673        * have to add the original directory to the search path,
     674        * and modify the paths for the Makefiles apropriately.  The
     675        * current directory is also placed as a variable for make scripts.
     676        */
     677        if (!(pathp = getenv("MAKEOBJDIRPREFIX"))) {
     678                if (!(path = getenv("MAKEOBJDIR"))) {
     679                        path = _PATH_OBJDIR;
     680                        pathp = _PATH_OBJDIRPREFIX;
     681                        (void) snprintf(mdpath, MAXPATHLEN, "%s.%s",
     682                                        path, machine);
     683                        if (!(objdir = chdir_verify_path(mdpath, obpath)))
     684                                if (!(objdir=chdir_verify_path(path, obpath))) {
     685                                        (void) snprintf(mdpath, MAXPATHLEN,
     686                                                        "%s%s", pathp, curdir);
     687                                        if (!(objdir=chdir_verify_path(mdpath,
     688                                                                       obpath)))
     689                                                objdir = curdir;
     690                                }
     691                }
     692                else if (!(objdir = chdir_verify_path(path, obpath)))
     693                        objdir = curdir;
     694        }
     695        else {
     696                (void) snprintf(mdpath, MAXPATHLEN, "%s%s", pathp, curdir);
     697                if (!(objdir = chdir_verify_path(mdpath, obpath)))
     698                        objdir = curdir;
     699        }
    688700        #endif
    689701
    690702#ifdef WANT_ENV_PWD
    691703        #ifdef USE_KLIB
    692         kEnvSet("PWD", objdir);
     704        kEnvSet("PWD", objdir);
    693705        #else
    694         setenv("PWD", objdir, 1);
     706        setenv("PWD", objdir, 1);
    695707        #endif
    696708#endif
    697709
    698         create = Lst_Init(FALSE);
    699         makefiles = Lst_Init(FALSE);
    700         envFirstVars = Lst_Init(FALSE);
    701         printVars = FALSE;
    702         expandVars = TRUE;
    703         variables = Lst_Init(FALSE);
    704         beSilent = FALSE;               /* Print commands as executed */
    705         ignoreErrors = FALSE;           /* Pay attention to non-zero returns */
    706         noExecute = FALSE;              /* Execute all commands */
    707         keepgoing = FALSE;              /* Stop on error */
    708         allPrecious = FALSE;            /* Remove targets when interrupted */
    709         queryFlag = FALSE;              /* This is not just a check-run */
    710         noBuiltins = FALSE;             /* Read the built-in rules */
    711         touchFlag = FALSE;              /* Actually update targets */
    712         usePipes = TRUE;                /* Catch child output in pipes */
    713         debug = 0;                      /* No debug verbosity, please. */
    714         jobsRunning = FALSE;
     710        create = Lst_Init(FALSE);
     711        makefiles = Lst_Init(FALSE);
     712        envFirstVars = Lst_Init(FALSE);
     713        printVars = FALSE;
     714        expandVars = TRUE;
     715        variables = Lst_Init(FALSE);
     716        beSilent = FALSE;               /* Print commands as executed */
     717        ignoreErrors = FALSE;           /* Pay attention to non-zero returns */
     718        noExecute = FALSE;              /* Execute all commands */
     719        keepgoing = FALSE;              /* Stop on error */
     720        allPrecious = FALSE;            /* Remove targets when interrupted */
     721        queryFlag = FALSE;              /* This is not just a check-run */
     722        noBuiltins = FALSE;             /* Read the built-in rules */
     723        touchFlag = FALSE;              /* Actually update targets */
     724#ifdef USE_PIPES
     725        usePipes = TRUE;                /* Catch child output in pipes */
     726#else
     727        usePipes = FALSE;               /* Don't catch child output in pipes if multiple wait isn't supported */
     728#endif
     729        debug = 0;                      /* No debug verbosity, please. */
     730        jobsRunning = FALSE;
    715731#ifdef NMAKE
    716         go_to_objdir = FALSE;
    717 #endif
    718 
    719         maxLocal = DEFMAXLOCAL;         /* Set default local max concurrency */
     732        go_to_objdir = FALSE;
     733#endif
     734
     735        maxLocal = DEFMAXLOCAL;         /* Set default local max concurrency */
    720736#ifdef REMOTE
    721         maxJobs = DEFMAXJOBS;           /* Set default max concurrency */
    722 #else
    723         maxJobs = maxLocal;
    724 #endif
    725         forceJobs = FALSE;              /* No -j flag */
    726         compatMake = FALSE;             /* No compat mode */
    727 
    728 
    729         /*
    730         * Initialize the parsing, directory and variable modules to prepare
    731         * for the reading of inclusion paths and variable settings on the
    732         * command line
    733         */
    734         Dir_Init();             /* Initialize directory structures so -I flags
    735                                 * can be processed correctly */
    736         Parse_Init();           /* Need to initialize the paths of #include
    737                                 * directories */
    738         Var_Init();             /* As well as the lists of variables for
    739                                 * parsing arguments */
     737        maxJobs = DEFMAXJOBS;           /* Set default max concurrency */
     738#else
     739        maxJobs = maxLocal;
     740#endif
     741        forceJobs = FALSE;              /* No -j flag */
     742        compatMake = FALSE;             /* No compat mode */
     743
     744
     745        /*
     746        * Initialize the parsing, directory and variable modules to prepare
     747        * for the reading of inclusion paths and variable settings on the
     748        * command line
     749        */
     750        Dir_Init();             /* Initialize directory structures so -I flags
     751                                * can be processed correctly */
     752        Parse_Init();           /* Need to initialize the paths of #include
     753                                * directories */
     754        Var_Init();             /* As well as the lists of variables for
     755                                * parsing arguments */
    740756        str_init();
    741         if (objdir != curdir)
    742                 Dir_AddDir(dirSearchPath, curdir);
    743         Var_Set(".CURDIR", curdir, VAR_GLOBAL);
    744         Var_Set(".OBJDIR", objdir, VAR_GLOBAL);
    745 
    746         /*
    747         * Initialize various variables.
    748          *      MAKE also gets this name, for compatibility
    749          *      .MAKEFLAGS gets set to the empty string just in case.
    750          *      MFLAGS also gets initialized empty, for compatibility.
    751         */
    752         Var_Set("MAKE", argv[0], VAR_GLOBAL);
    753         Var_Set(MAKEFLAGS, "", VAR_GLOBAL);
    754         Var_Set("MFLAGS", "", VAR_GLOBAL);
    755         Var_Set("MACHINE", machine, VAR_GLOBAL);
    756         Var_Set("MACHINE_ARCH", machine_arch, VAR_GLOBAL);
    757         Var_Set("MACHINE_CPU", machine_cpu, VAR_GLOBAL);
    758 
    759         /*
    760         * First snag any flags out of the MAKE environment variable.
    761         * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's
    762         * in a different format).
    763         */
     757        if (objdir != curdir)
     758                Dir_AddDir(dirSearchPath, curdir);
     759        Var_Set(".CURDIR", curdir, VAR_GLOBAL);
     760        Var_Set(".OBJDIR", objdir, VAR_GLOBAL);
     761
     762        /*
     763        * Initialize various variables.
     764         *      MAKE also gets this name, for compatibility
     765         *      .MAKEFLAGS gets set to the empty string just in case.
     766         *      MFLAGS also gets initialized empty, for compatibility.
     767        */
     768        Var_Set("MAKE", argv[0], VAR_GLOBAL);
     769        Var_Set(MAKEFLAGS, "", VAR_GLOBAL);
     770        Var_Set("MFLAGS", "", VAR_GLOBAL);
     771        Var_Set("MACHINE", machine, VAR_GLOBAL);
     772        Var_Set("MACHINE_ARCH", machine_arch, VAR_GLOBAL);
     773        Var_Set("MACHINE_CPU", machine_cpu, VAR_GLOBAL);
     774
     775        /*
     776        * First snag any flags out of the MAKE environment variable.
     777        * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's
     778        * in a different format).
     779        */
    764780#ifdef POSIX
    765         Main_ParseArgLine(getenv("MAKEFLAGS"));
    766 #else
    767         Main_ParseArgLine(getenv("MAKE"));
    768 #endif
    769 
    770         MainParseArgs(argc, argv);
    771 
    772         /*
    773          * Be compatible if user did not specify -j and did not explicitly
    774          * turned compatibility on
    775          */
    776         if (!compatMake && !forceJobs)
    777                 compatMake = TRUE;
    778 
    779         /*
    780          * Initialize archive, target and suffix modules in preparation for
    781          * parsing the makefile(s)
    782          */
     781        Main_ParseArgLine(getenv("MAKEFLAGS"));
     782#else
     783        Main_ParseArgLine(getenv("MAKE"));
     784#endif
     785
     786#ifdef KMK
     787        /*
     788         * Completely ignore the tool argument.
     789         */
     790        if (argc > 1 && !kStrCmp(argv[1], "--kMk"))
     791        {
     792            argc--;
     793            argv++;
     794        }
     795#endif
     796        MainParseArgs(argc, argv);
     797
     798        /*
     799         * Be compatible if user did not specify -j and did not explicitly
     800         * turned compatibility on
     801         */
     802        if (!compatMake && !forceJobs)
     803                compatMake = TRUE;
     804
     805        /*
     806         * Initialize archive, target and suffix modules in preparation for
     807         * parsing the makefile(s)
     808         */
    783809#ifdef USE_ARCHIVES
    784         Arch_Init();
    785 #endif
    786         Targ_Init();
    787         Suff_Init();
    788 
    789         DEFAULT = NILGNODE;
    790         (void)time(&now);
    791 
    792         /*
    793         * Set up the .TARGETS variable to contain the list of targets to be
    794         * created. If none specified, make the variable empty -- the parser
    795         * will fill the thing in with the default or .MAIN target.
    796         */
    797         if (!Lst_IsEmpty(create)) {
    798                 LstNode ln;
    799 
    800                 for (ln = Lst_First(create); ln != NILLNODE;
    801                     ln = Lst_Succ(ln)) {
    802                         char *name = (char *)Lst_Datum(ln);
    803 
    804                         Var_Append(".TARGETS", name, VAR_GLOBAL);
    805                 }
    806         } else
    807                 Var_Set(".TARGETS", "", VAR_GLOBAL);
     810        Arch_Init();
     811#endif
     812        Targ_Init();
     813        Suff_Init();
     814
     815        DEFAULT = NILGNODE;
     816        (void)time(&now);
     817
     818        /*
     819        * Set up the .TARGETS variable to contain the list of targets to be
     820        * created. If none specified, make the variable empty -- the parser
     821        * will fill the thing in with the default or .MAIN target.
     822        */
     823        if (!Lst_IsEmpty(create)) {
     824                LstNode ln;
     825
     826                for (ln = Lst_First(create); ln != NILLNODE;
     827                    ln = Lst_Succ(ln)) {
     828                        char *name = (char *)Lst_Datum(ln);
     829
     830                        Var_Append(".TARGETS", name, VAR_GLOBAL);
     831                }
     832        } else
     833                Var_Set(".TARGETS", "", VAR_GLOBAL);
    808834
    809835
    810836        #ifdef KMK
    811         /*
    812         * Add current directory tree to system include path all levels up to the root.
     837        /*
     838        * Add current directory tree to system include path all levels up to the root.
    813839         * ASSUMES that curdir is absolute.
    814         */
     840        */
    815841        {
    816842            char *  psz = estrdup(curdir);
     
    834860
    835861        #else
    836         /*
    837         * If no user-supplied system path was given (through the -m option)
    838         * add the directories from the DEFSYSPATH (more than one may be given
    839         * as dir1:...:dirn) to the system include path.
    840         */
    841         if (Lst_IsEmpty(sysIncPath)) {
    842                 for (start = syspath; *start != '\0'; start = cp) {
    843                         for (cp = start; *cp != '\0' && *cp != ':'; cp++)
    844                                 continue;
    845                         if (*cp == '\0') {
    846                                 Dir_AddDir(sysIncPath, start);
    847                         } else {
    848                                 *cp++ = '\0';
    849                                 Dir_AddDir(sysIncPath, start);
    850                         }
    851                 }
    852         }
     862        /*
     863        * If no user-supplied system path was given (through the -m option)
     864        * add the directories from the DEFSYSPATH (more than one may be given
     865        * as dir1:...:dirn) to the system include path.
     866        */
     867        if (Lst_IsEmpty(sysIncPath)) {
     868                for (start = syspath; *start != '\0'; start = cp) {
     869                        for (cp = start; *cp != '\0' && *cp != ':'; cp++)
     870                                continue;
     871                        if (*cp == '\0') {
     872                                Dir_AddDir(sysIncPath, start);
     873                        } else {
     874                                *cp++ = '\0';
     875                                Dir_AddDir(sysIncPath, start);
     876                        }
     877                }
     878        }
    853879        #endif
    854880
    855         /*
    856         * Read in the built-in rules first, followed by the specified
    857         * makefile, if it was (makefile != (char *) NULL), or the default
    858         * Makefile and makefile, in that order, if it wasn't.
    859         */
    860         if (!noBuiltins) {
    861                 LstNode ln;
    862 
    863                 sysMkPath = Lst_Init (FALSE);
    864                 Dir_Expand (_PATH_DEFSYSMK, sysIncPath, sysMkPath);
     881        /*
     882        * Read in the built-in rules first, followed by the specified
     883        * makefile, if it was (makefile != (char *) NULL), or the default
     884        * Makefile and makefile, in that order, if it wasn't.
     885        */
     886        if (!noBuiltins) {
     887                LstNode ln;
     888
     889                sysMkPath = Lst_Init (FALSE);
     890                Dir_Expand (_PATH_DEFSYSMK, sysIncPath, sysMkPath);
    865891#ifdef NMAKE
    866                 if (!Lst_IsEmpty(sysMkPath))
     892                if (!Lst_IsEmpty(sysMkPath))
    867893                {
    868894                    ln = Lst_Find(sysMkPath, (ClientData)NULL, ReadMakefile);
     
    872898
    873899#elif defined(KMK)
    874                 if (!Lst_IsEmpty(sysMkPath))
     900                if (!Lst_IsEmpty(sysMkPath))
    875901                {
    876902                    ln = Lst_Find(sysMkPath, (ClientData)NULL, ReadMakefile);
     
    879905
    880906                }
    881                 Error(MAKE_NAME ": no config rules (%s).", _PATH_DEFSYSMK);
    882 #else
    883                 if (Lst_IsEmpty(sysMkPath))
    884                         Fatal(MAKE_NAME ": no system rules (%s).", _PATH_DEFSYSMK);
    885                 ln = Lst_Find(sysMkPath, (ClientData)NULL, ReadMakefile);
    886                 if (ln != NILLNODE)
    887                         Fatal(MAKE_NAME ": cannot open %s.", (char *)Lst_Datum(ln));
    888 #endif
    889         }
    890 
    891         if (!Lst_IsEmpty(makefiles)) {
    892                 LstNode ln;
    893 
    894                 ln = Lst_Find(makefiles, (ClientData)NULL, ReadMakefile);
    895                 if (ln != NILLNODE)
    896                         Fatal(MAKE_NAME ": cannot open %s.", (char *)Lst_Datum(ln));
    897         } else
     907                Error(MAKE_NAME ": no config rules (%s).", _PATH_DEFSYSMK);
     908#else
     909                if (Lst_IsEmpty(sysMkPath))
     910                        Fatal(MAKE_NAME ": no system rules (%s).", _PATH_DEFSYSMK);
     911                ln = Lst_Find(sysMkPath, (ClientData)NULL, ReadMakefile);
     912                if (ln != NILLNODE)
     913                        Fatal(MAKE_NAME ": cannot open %s.", (char *)Lst_Datum(ln));
     914#endif
     915        }
     916
     917        if (!Lst_IsEmpty(makefiles)) {
     918                LstNode ln;
     919
     920                ln = Lst_Find(makefiles, (ClientData)NULL, ReadMakefile);
     921                if (ln != NILLNODE)
     922                        Fatal(MAKE_NAME ": cannot open %s.", (char *)Lst_Datum(ln));
     923        } else
    898924            #ifdef KMK
    899925            if (    !ReadMakefile("Makefile.kMk", NULL)
     
    911937            #endif
    912938
    913         (void)ReadMakefile(".depend", NULL);
    914 
    915         Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL);
    916         efree(p1);
    917 
    918         /* Install all the flags into the MAKE envariable. */
    919         if (((p = Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1)) != NULL) && *p)
     939        (void)ReadMakefile(".depend", NULL);
     940
     941        Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL);
     942        efree(p1);
     943
     944        /* Install all the flags into the MAKE envariable. */
     945        if (((p = Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1)) != NULL) && *p)
    920946#ifdef POSIX
    921947                #ifdef USE_KLIB
    922948                kEnvSet("MAKEFLAGS", p, TRUE);
    923949                #else
    924                 setenv("MAKEFLAGS", p, 1);
     950                setenv("MAKEFLAGS", p, 1);
    925951                #endif
    926952#else
    927953                #ifdef USE_KLIB
    928                 kEnvSet("MAKE", p, TRUE);
     954                kEnvSet("MAKE", p, TRUE);
    929955                #else
    930                 setenv("MAKE", p, 1);
     956                setenv("MAKE", p, 1);
    931957                #endif
    932958#endif
    933         efree(p1);
    934 
    935         /*
    936         * For compatibility, look at the directories in the VPATH variable
    937         * and add them to the search path, if the variable is defined. The
    938         * variable's value is in the same format as the PATH envariable, i.e.
    939         * <directory>:<directory>:<directory>...
    940         */
    941         if (Var_Exists("VPATH", VAR_CMD)) {
    942                 char *vpath, *path, *cp, savec;
    943                 /*
    944                 * GCC stores string constants in read-only memory, but
    945                 * Var_Subst will want to write this thing, so store it
    946                 * in an array
    947                 */
    948                 static char VPATH[] = "${VPATH}";
    949 
    950                 vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE);
    951                 path = vpath;
    952                 do {
    953                         /* skip to end of directory */
    954                         for (cp = path; *cp != ':' && *cp != '\0'; cp++)
    955                                 continue;
    956                         /* Save terminator character so know when to stop */
    957                         savec = *cp;
    958                         *cp = '\0';
    959                         /* Add directory to search path */
    960                         Dir_AddDir(dirSearchPath, path);
    961                         *cp = savec;
    962                         path = cp + 1;
    963                 } while (savec == ':');
    964                 (void)efree((Address)vpath);
    965         }
    966 
    967         /*
    968         * Now that all search paths have been read for suffixes et al, it's
    969         * time to add the default search path to their lists...
    970         */
    971         Suff_DoPaths();
    972 
    973         /* print the initial graph, if the user requested it */
    974         if (DEBUG(GRAPH1))
    975                 Targ_PrintGraph(1);
    976 
    977         /* print the values of any variables requested by the user */
    978         if (printVars) {
    979                 LstNode ln;
    980 
    981                 for (ln = Lst_First(variables); ln != NILLNODE;
    982                     ln = Lst_Succ(ln)) {
    983                         char *value;
    984                         if (expandVars) {
    985                                 p1 = emalloc(strlen((char *)Lst_Datum(ln)) + 1 + 3);
    986                                 /* This sprintf is safe, because of the malloc above */
    987                                 (void)sprintf(p1, "${%s}", (char *)Lst_Datum(ln));
    988                                 value = Var_Subst(NULL, p1, VAR_GLOBAL, FALSE);
    989                         } else {
    990                                 value = Var_Value((char *)Lst_Datum(ln),
    991                                                   VAR_GLOBAL, &p1);
    992                         }
    993                         printf("%s\n", value ? value : "");
    994                         if (p1)
    995                                 efree(p1);
    996                 }
    997         }
    998 
    999         /*
    1000         * Have now read the entire graph and need to make a list of targets
    1001         * to create. If none was given on the command line, we consult the
    1002         * parsing module to find the main target(s) to create.
    1003         */
    1004         if (Lst_IsEmpty(create))
    1005                 targs = Parse_MainName();
    1006         else
    1007                 targs = Targ_FindList(create, TARG_CREATE);
    1008 
    1009         if (!compatMake && !printVars) {
    1010                 /*
    1011                 * Initialize job module before traversing the graph, now that
    1012                 * any .BEGIN and .END targets have been read.  This is done
    1013                 * only if the -q flag wasn't given (to prevent the .BEGIN from
    1014                 * being executed should it exist).
    1015                 */
    1016                 if (!queryFlag) {
    1017                         if (maxLocal == -1)
    1018                                 maxLocal = maxJobs;
    1019                         Job_Init(maxJobs, maxLocal);
    1020                         jobsRunning = TRUE;
    1021                 }
    1022 
    1023                 /* Traverse the graph, checking on all the targets */
    1024                 outOfDate = Make_Run(targs);
    1025         } else if (!printVars) {
    1026                 /*
    1027                 * Compat_Init will take care of creating all the targets as
    1028                 * well as initializing the module.
    1029                 */
    1030                 Compat_Run(targs);
    1031         }
    1032 
    1033         Lst_Destroy(targs, NOFREE);
    1034         Lst_Destroy(variables, NOFREE);
    1035         Lst_Destroy(makefiles, NOFREE);
    1036         Lst_Destroy(create, (void (*) __P((ClientData))) efree);
    1037 
    1038         /* print the graph now it's been processed if the user requested it */
    1039         if (DEBUG(GRAPH2))
    1040                 Targ_PrintGraph(2);
    1041 
    1042         Suff_End();
     959        efree(p1);
     960
     961        /*
     962        * For compatibility, look at the directories in the VPATH variable
     963        * and add them to the search path, if the variable is defined. The
     964        * variable's value is in the same format as the PATH envariable, i.e.
     965        * <directory>:<directory>:<directory>...
     966        */
     967        if (Var_Exists("VPATH", VAR_CMD)) {
     968                char *vpath, *path, *cp, savec;
     969                /*
     970                * GCC stores string constants in read-only memory, but
     971                * Var_Subst will want to write this thing, so store it
     972                * in an array
     973                */
     974                static char VPATH[] = "${VPATH}";
     975
     976                vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE);
     977                path = vpath;
     978                do {
     979                        /* skip to end of directory */
     980                        for (cp = path; *cp != ':' && *cp != '\0'; cp++)
     981                                continue;
     982                        /* Save terminator character so know when to stop */
     983                        savec = *cp;
     984                        *cp = '\0';
     985                        /* Add directory to search path */
     986                        Dir_AddDir(dirSearchPath, path);
     987                        *cp = savec;
     988                        path = cp + 1;
     989                } while (savec == ':');
     990                (void)efree((Address)vpath);
     991        }
     992
     993        /*
     994        * Now that all search paths have been read for suffixes et al, it's
     995        * time to add the default search path to their lists...
     996        */
     997        Suff_DoPaths();
     998
     999        /* print the initial graph, if the user requested it */
     1000        if (DEBUG(GRAPH1))
     1001                Targ_PrintGraph(1);
     1002
     1003        /* print the values of any variables requested by the user */
     1004        if (printVars) {
     1005                LstNode ln;
     1006
     1007                for (ln = Lst_First(variables); ln != NILLNODE;
     1008                    ln = Lst_Succ(ln)) {
     1009                        char *value;
     1010                        if (expandVars) {
     1011                                p1 = emalloc(strlen((char *)Lst_Datum(ln)) + 1 + 3);
     1012                                /* This sprintf is safe, because of the malloc above */
     1013                                (void)sprintf(p1, "${%s}", (char *)Lst_Datum(ln));
     1014                                value = Var_Subst(NULL, p1, VAR_GLOBAL, FALSE);
     1015                        } else {
     1016                                value = Var_Value((char *)Lst_Datum(ln),
     1017                                                  VAR_GLOBAL, &p1);
     1018                        }
     1019                        printf("%s\n", value ? value : "");
     1020                        if (p1)
     1021                                efree(p1);
     1022                }
     1023        }
     1024
     1025        /*
     1026        * Have now read the entire graph and need to make a list of targets
     1027        * to create. If none was given on the command line, we consult the
     1028        * parsing module to find the main target(s) to create.
     1029        */
     1030        if (Lst_IsEmpty(create))
     1031                targs = Parse_MainName();
     1032        else
     1033                targs = Targ_FindList(create, TARG_CREATE);
     1034
     1035        if (!compatMake && !printVars) {
     1036                /*
     1037                * Initialize job module before traversing the graph, now that
     1038                * any .BEGIN and .END targets have been read.  This is done
     1039                * only if the -q flag wasn't given (to prevent the .BEGIN from
     1040                * being executed should it exist).
     1041                */
     1042                if (!queryFlag) {
     1043                        if (maxLocal == -1)
     1044                                maxLocal = maxJobs;
     1045                        Job_Init(maxJobs, maxLocal);
     1046                        jobsRunning = TRUE;
     1047                }
     1048
     1049                /* Traverse the graph, checking on all the targets */
     1050                outOfDate = Make_Run(targs);
     1051        } else if (!printVars) {
     1052                /*
     1053                * Compat_Init will take care of creating all the targets as
     1054                * well as initializing the module.
     1055                */
     1056                Compat_Run(targs);
     1057        }
     1058
     1059        Lst_Destroy(targs, NOFREE);
     1060        Lst_Destroy(variables, NOFREE);
     1061        Lst_Destroy(makefiles, NOFREE);
     1062        Lst_Destroy(create, (void (*) __P((ClientData))) efree);
     1063
     1064        /* print the graph now it's been processed if the user requested it */
     1065        if (DEBUG(GRAPH2))
     1066                Targ_PrintGraph(2);
     1067
     1068        Suff_End();
    10431069        Targ_End();
    10441070#ifdef USE_ARCHIVES
    1045         Arch_End();
    1046 #endif
    1047         str_end();
    1048         Var_End();
    1049         Parse_End();
    1050         Dir_End();
    1051 
    1052         if (queryFlag && outOfDate)
    1053                 return(1);
    1054         else
    1055                 return(0);
     1071        Arch_End();
     1072#endif
     1073        str_end();
     1074        Var_End();
     1075        Parse_End();
     1076        Dir_End();
     1077
     1078        if (queryFlag && outOfDate)
     1079                return(1);
     1080        else
     1081                return(0);
    10561082}
    10571083
    10581084/*-
    10591085 * ReadMakefile  --
    1060  *      Open and parse the given makefile.
     1086 *      Open and parse the given makefile.
    10611087 *
    10621088 * Results:
    1063  *      TRUE if ok. FALSE if couldn't open file.
     1089 *      TRUE if ok. FALSE if couldn't open file.
    10641090 *
    10651091 * Side Effects:
    1066  *      lots
     1092 *      lots
    10671093 */
    10681094static Boolean
    10691095ReadMakefile(p, q)
    1070         ClientData p, q;
    1071 {
    1072         char *fname = p;                /* makefile to read */
    1073         extern Lst parseIncPath;
    1074         FILE *stream;
    1075         char *name, path[MAXPATHLEN + 1];
    1076         char *MAKEFILE;
    1077         int setMAKEFILE;
    1078 
    1079         if (!strcmp(fname, "-")) {
    1080                 Parse_File("(stdin)", stdin);
    1081                 Var_Set("MAKEFILE", "", VAR_GLOBAL);
    1082         } else {
    1083                 setMAKEFILE = strcmp(fname, ".depend");
    1084 
    1085                 /* if we've chdir'd, rebuild the path name */
    1086                 if (curdir != objdir && *fname != '/') {
    1087                         (void)snprintf(path, MAXPATHLEN, "%s/%s", curdir, fname);
    1088                         if (realpath(path, path) != NULL &&
    1089                             (stream = fopen(path, "r")) != NULL) {
    1090                                 MAKEFILE = fname;
    1091                                 fname = path;
    1092                                 goto found;
    1093                         }
    1094                 } else if (realpath(fname, path) != NULL) {
    1095                         MAKEFILE = fname;
    1096                         fname = path;
    1097                         if ((stream = fopen(fname, "r")) != NULL)
    1098                                 goto found;
    1099                 }
    1100                 /* look in -I and system include directories. */
    1101                 name = Dir_FindFile(fname, parseIncPath);
    1102                 if (!name)
    1103                         name = Dir_FindFile(fname, sysIncPath);
    1104                 if (!name || !(stream = fopen(name, "r")))
    1105                         return(FALSE);
    1106                 MAKEFILE = fname = name;
    1107                 /*
    1108                 * set the MAKEFILE variable desired by System V fans -- the
    1109                 * placement of the setting here means it gets set to the last
    1110                 * makefile specified, as it is set by SysV make.
    1111                 */
     1096        ClientData p, q;
     1097{
     1098        char *fname = p;                /* makefile to read */
     1099        extern Lst parseIncPath;
     1100        FILE *stream;
     1101        char *name, path[MAXPATHLEN + 1];
     1102        char *MAKEFILE;
     1103        int setMAKEFILE;
     1104
     1105        if (!strcmp(fname, "-")) {
     1106                Parse_File("(stdin)", stdin);
     1107                Var_Set("MAKEFILE", "", VAR_GLOBAL);
     1108        } else {
     1109                setMAKEFILE = strcmp(fname, ".depend");
     1110
     1111                /* if we've chdir'd, rebuild the path name */
     1112                if (curdir != objdir && *fname != '/') {
     1113                        (void)snprintf(path, MAXPATHLEN, "%s/%s", curdir, fname);
     1114                        if (realpath(path, path) != NULL &&
     1115                            (stream = fopen(path, "r")) != NULL) {
     1116                                MAKEFILE = fname;
     1117                                fname = path;
     1118                                goto found;
     1119                        }
     1120                } else if (realpath(fname, path) != NULL) {
     1121                        MAKEFILE = fname;
     1122                        fname = path;
     1123                        if ((stream = fopen(fname, "r")) != NULL)
     1124                                goto found;
     1125                }
     1126                /* look in -I and system include directories. */
     1127                name = Dir_FindFile(fname, parseIncPath);
     1128                if (!name)
     1129                        name = Dir_FindFile(fname, sysIncPath);
     1130                if (!name || !(stream = fopen(name, "r")))
     1131                        return(FALSE);
     1132                MAKEFILE = fname = name;
     1133                /*
     1134                * set the MAKEFILE variable desired by System V fans -- the
     1135                * placement of the setting here means it gets set to the last
     1136                * makefile specified, as it is set by SysV make.
     1137                */
    11121138found:
    1113                 if (setMAKEFILE)
    1114                         Var_Set("MAKEFILE", MAKEFILE, VAR_GLOBAL);
    1115                 Parse_File(fname, stream);
    1116                 (void)fclose(stream);
    1117         }
    1118         return(TRUE);
     1139                if (setMAKEFILE)
     1140                        Var_Set("MAKEFILE", MAKEFILE, VAR_GLOBAL);
     1141                Parse_File(fname, stream);
     1142                (void)fclose(stream);
     1143        }
     1144        return(TRUE);
    11191145}
    11201146
    11211147/*-
    11221148 * Cmd_Exec --
    1123  *      Execute the command in cmd, and return the output of that command
    1124  *      in a string.
     1149 *      Execute the command in cmd, and return the output of that command
     1150 *      in a string.
    11251151 *
    11261152 * Results:
    1127  *      A string containing the output of the command, or the empty string
    1128  *      If err is not NULL, it contains the reason for the command failure
     1153 *      A string containing the output of the command, or the empty string
     1154 *      If err is not NULL, it contains the reason for the command failure
    11291155 *
    11301156 * Side Effects:
    1131  *      The string must be freed by the caller.
     1157 *      The string must be freed by the caller.
    11321158 */
    11331159char *
     
    11361162    char **err;
    11371163{
    1138     char        *args[4];       /* Args for invoking the shell */
    1139     int         fds[2];         /* Pipe streams */
    1140     int         cpid;           /* Child PID */
    1141     int         pid;            /* PID from wait() */
    1142     char        *res;           /* result */
    1143     int         status;         /* command exit status */
    1144     Buffer      buf;            /* buffer to store the result */
    1145     char        *cp;
    1146     int         cc;
     1164#ifdef KMK
     1165    /** @todo this can be executed directly in the shell!!!
     1166     */
     1167    int         rc;
     1168    char *      args[4];                /* Args for invoking the shell */
     1169    KFILE       fhPipe;                 /* Pipe handle. */
     1170    KPID        cpid;                   /* Child PID */
     1171    KPROCRES    status;                 /* Child exit status. */
     1172    char *      res;                    /* result */
     1173    Buffer      buf;                    /* buffer to store the result */
     1174    char *      cp;
     1175    int         cc;
     1176
     1177
     1178    *err = NULL;
     1179
     1180    /*
     1181     * Set up arguments for shell
     1182     */
     1183    args[0] = argv0;
     1184    args[1] = "--kShell";
     1185    args[2] = cmd;
     1186    args[3] = NULL;
     1187
     1188
     1189    /*
     1190     * Execute command in pipe.
     1191     */
     1192    rc = kProcPiped(&args[0],
     1193                    KPROCPIPED_FLAGS_STDOUT,
     1194                    &cpid,
     1195                    &fhPipe);
     1196    if (!rc)
     1197    {
     1198        FILE *phPipe;
     1199        buf = Buf_Init (MAKE_BSIZE);
     1200
     1201        /*
     1202         * Read the output using a file stream for automatic '\n' newline conv.
     1203         */
     1204        phPipe = fdopen(fhPipe, "r");
     1205        cc = -1;
     1206        if (phPipe)
     1207        {
     1208            do {
     1209                char   result[BUFSIZ];
     1210                cc = fread(result, 1, sizeof(result), phPipe);
     1211                if (cc > 0)
     1212                    Buf_AddBytes(buf, cc, (Byte *) result);
     1213            }
     1214            while (cc > 0 || (cc == -1 && errno == EINTR));
     1215            fclose(phPipe);
     1216        }
     1217
     1218        /*
     1219         * Close the input side of the pipe and wait for the child to exit.
     1220         */
     1221        kFileClose(fhPipe);
     1222        rc = kProcWait(cpid, KPROCWAIT_FLAGS_WAIT, &status, NULL);
     1223
     1224        /*
     1225         * Check for errors, get buffered bits.
     1226         */
     1227        if (cc == -1)
     1228            *err = "Error reading shell's output for \"%s\"";
     1229
     1230        res = (char *)Buf_GetAll (buf, &cc);
     1231        Buf_Destroy (buf, FALSE);
     1232
     1233        if (status.uExitCode || status.fFlags != KPROCRES_FLAGS_NORMAL)
     1234            *err = "\"%s\" returned non-zero status";
     1235
     1236        /*
     1237         * Null-terminate the result, convert newlines to spaces and
     1238         * install it in the variable. Final newline is removed.
     1239         */
     1240        res[cc] = '\0';
     1241        cp = &res[cc] - 1;
     1242        if (*cp == '\n')
     1243            *cp-- = '\0';
     1244
     1245        while (cp >= res)
     1246        {
     1247            if (*cp == '\n')
     1248                *cp = ' ';
     1249            cp--;
     1250        }
     1251
     1252        return res;
     1253    }
     1254    else
     1255        *err = "Couldn't exec \"%s\"";
     1256
     1257    res = emalloc(1);
     1258    *res = '\0';
     1259    return res;
     1260
     1261#else  /* not KMK */
     1262
     1263    char        *args[4];       /* Args for invoking the shell */
     1264    int         fds[2];         /* Pipe streams */
     1265    int         cpid;           /* Child PID */
     1266    int         pid;            /* PID from wait() */
     1267    char        *res;           /* result */
     1268    int         status;         /* command exit status */
     1269    Buffer      buf;            /* buffer to store the result */
     1270    char        *cp;
     1271    int         cc;
    11471272
    11481273
     
    11611286     */
    11621287    if (pipe(fds) == -1) {
    1163         *err = "Couldn't create pipe for \"%s\"";
    1164         goto bad;
     1288        *err = "Couldn't create pipe for \"%s\"";
     1289        goto bad;
    11651290    }
    11661291
     
    11691294     */
    11701295#ifdef __EMX__
    1171     switch (cpid = fork()) {
    1172 #else
    1173     switch (cpid = vfork()) {
    1174 #endif
     1296    switch (cpid = fork())
     1297#else
     1298    switch (cpid = vfork())
     1299#endif
     1300    {
    11751301    case 0:
    1176         /*
    1177         * Close input side of pipe
    1178         */
    1179         (void) close(fds[0]);
    1180 
    1181         /*
    1182         * Duplicate the output stream to the shell's output, then
    1183         * shut the extra thing down. Note we don't fetch the error
    1184         * stream...why not? Why?
    1185         */
    1186         (void) dup2(fds[1], 1);
    1187         (void) close(fds[1]);
     1302        /*
     1303        * Close input side of pipe
     1304        */
     1305        (void) close(fds[0]);
     1306
     1307        /*
     1308        * Duplicate the output stream to the shell's output, then
     1309        * shut the extra thing down. Note we don't fetch the error
     1310        * stream...why not? Why?
     1311        */
     1312        (void) dup2(fds[1], 1);
     1313        (void) close(fds[1]);
    11881314
    11891315        #ifdef OS2
     
    11941320            if (!psz)
    11951321                psz = "c:\\os2\\cmd.exe";
    1196             (void) execv(psz, args);
     1322            (void) execv(psz, args);
    11971323        }
    11981324        #else
    1199         (void) execv("/bin/sh", args);
     1325        (void) execv("/bin/sh", args);
    12001326        #endif
    1201         _exit(1);
    1202         /*NOTREACHED*/
     1327        _exit(1);
     1328        /*NOTREACHED*/
    12031329
    12041330    case -1:
    1205         *err = "Couldn't exec \"%s\"";
    1206         goto bad;
     1331        *err = "Couldn't exec \"%s\"";
     1332        goto bad;
    12071333
    12081334    default:
    1209         /*
    1210         * No need for the writing half
    1211         */
    1212         (void) close(fds[1]);
    1213 
    1214         buf = Buf_Init (MAKE_BSIZE);
    1215 
    1216         do {
    1217             char   result[BUFSIZ];
    1218             cc = read(fds[0], result, sizeof(result));
    1219             if (cc > 0)
    1220                 Buf_AddBytes(buf, cc, (Byte *) result);
    1221         }
    1222         while (cc > 0 || (cc == -1 && errno == EINTR));
    1223 
    1224         /*
    1225         * Close the input side of the pipe.
    1226         */
    1227         (void) close(fds[0]);
    1228 
    1229         /*
    1230         * Wait for the process to exit.
    1231         */
    1232         while(((pid = wait(&status)) != cpid) && (pid >= 0))
    1233             continue;
    1234 
    1235         if (cc == -1)
    1236             *err = "Error reading shell's output for \"%s\"";
    1237 
    1238         res = (char *)Buf_GetAll (buf, &cc);
    1239         Buf_Destroy (buf, FALSE);
    1240 
    1241         if (status)
    1242             *err = "\"%s\" returned non-zero status";
    1243 
    1244         /*
    1245         * Null-terminate the result, convert newlines to spaces and
    1246         * install it in the variable.
    1247         */
    1248         res[cc] = '\0';
    1249         cp = &res[cc] - 1;
    1250 
    1251         if (*cp == '\n') {
    1252             /*
    1253              * A final newline is just stripped
    1254              */
    1255             *cp-- = '\0';
    1256         }
    1257         while (cp >= res) {
    1258             if (*cp == '\n') {
    1259                 *cp = ' ';
    1260             }
    1261             cp--;
    1262         }
    1263         break;
     1335        /*
     1336        * No need for the writing half
     1337        */
     1338        (void) close(fds[1]);
     1339
     1340        buf = Buf_Init (MAKE_BSIZE);
     1341
     1342        do {
     1343            char   result[BUFSIZ];
     1344            cc = read(fds[0], result, sizeof(result));
     1345            if (cc > 0)
     1346                Buf_AddBytes(buf, cc, (Byte *) result);
     1347        }
     1348        while (cc > 0 || (cc == -1 && errno == EINTR));
     1349
     1350        /*
     1351        * Close the input side of the pipe.
     1352        */
     1353        (void) close(fds[0]);
     1354
     1355        /*
     1356        * Wait for the process to exit.
     1357        */
     1358        while(((pid = wait(&status)) != cpid) && (pid >= 0))
     1359            continue;
     1360
     1361        if (cc == -1)
     1362            *err = "Error reading shell's output for \"%s\"";
     1363
     1364        res = (char *)Buf_GetAll (buf, &cc);
     1365        Buf_Destroy (buf, FALSE);
     1366
     1367        if (status)
     1368            *err = "\"%s\" returned non-zero status";
     1369
     1370        /*
     1371        * Null-terminate the result, convert newlines to spaces and
     1372        * install it in the variable.
     1373        */
     1374        res[cc] = '\0';
     1375        cp = &res[cc] - 1;
     1376
     1377        if (*cp == '\n') {
     1378            /*
     1379             * A final newline is just stripped
     1380             */
     1381            *cp-- = '\0';
     1382        }
     1383        while (cp >= res) {
     1384            if (*cp == '\n') {
     1385                *cp = ' ';
     1386            }
     1387            cp--;
     1388        }
     1389        break;
    12641390    }
    12651391    return res;
     
    12681394    *res = '\0';
    12691395    return res;
     1396#endif /* KMK */
    12701397}
    12711398
    12721399/*-
    12731400 * Error --
    1274  *      Print an error message given its format.
     1401 *      Print an error message given its format.
    12751402 *
    12761403 * Results:
    1277  *      None.
     1404 *      None.
    12781405 *
    12791406 * Side Effects:
    1280  *      The message is printed.
     1407 *      The message is printed.
    12811408 */
    12821409/* VARARGS */
     
    12861413#else
    12871414Error(va_alist)
    1288         va_dcl
    1289 #endif
    1290 {
    1291         va_list ap;
     1415        va_dcl
     1416#endif
     1417{
     1418        va_list ap;
    12921419#if defined(__STDC__) || defined(__IBMC__)
    1293         va_start(ap, fmt);
    1294 #else
    1295         char *fmt;
    1296 
    1297         va_start(ap);
    1298         fmt = va_arg(ap, char *);
    1299 #endif
    1300         (void)vfprintf(stderr, fmt, ap);
    1301         va_end(ap);
    1302         (void)fprintf(stderr, "\n");
    1303         (void)fflush(stderr);
     1420        va_start(ap, fmt);
     1421#else
     1422        char *fmt;
     1423
     1424        va_start(ap);
     1425        fmt = va_arg(ap, char *);
     1426#endif
     1427        (void)vfprintf(stderr, fmt, ap);
     1428        va_end(ap);
     1429        (void)fprintf(stderr, "\n");
     1430        (void)fflush(stderr);
    13041431}
    13051432
    13061433/*-
    13071434 * Fatal --
    1308  *      Produce a Fatal error message. If jobs are running, waits for them
    1309  *      to finish.
     1435 *      Produce a Fatal error message. If jobs are running, waits for them
     1436 *      to finish.
    13101437 *
    13111438 * Results:
    1312  *      None
     1439 *      None
    13131440 *
    13141441 * Side Effects:
    1315  *      The program exits
     1442 *      The program exits
    13161443 */
    13171444/* VARARGS */
     
    13211448#else
    13221449Fatal(va_alist)
    1323         va_dcl
    1324 #endif
    1325 {
    1326         va_list ap;
     1450        va_dcl
     1451#endif
     1452{
     1453        va_list ap;
    13271454#if defined(__STDC__) || defined(__IBMC__)
    1328         va_start(ap, fmt);
    1329 #else
    1330         char *fmt;
    1331 
    1332         va_start(ap);
    1333         fmt = va_arg(ap, char *);
    1334 #endif
    1335         if (jobsRunning)
    1336                 Job_Wait();
    1337 
    1338         (void)vfprintf(stderr, fmt, ap);
    1339         va_end(ap);
    1340         (void)fprintf(stderr, "\n");
    1341         (void)fflush(stderr);
    1342 
    1343         if (DEBUG(GRAPH2))
    1344                 Targ_PrintGraph(2);
    1345         exit(2);                /* Not 1 so -q can distinguish error */
     1455        va_start(ap, fmt);
     1456#else
     1457        char *fmt;
     1458
     1459        va_start(ap);
     1460        fmt = va_arg(ap, char *);
     1461#endif
     1462        if (jobsRunning)
     1463                Job_Wait();
     1464
     1465        (void)vfprintf(stderr, fmt, ap);
     1466        va_end(ap);
     1467        (void)fprintf(stderr, "\n");
     1468        (void)fflush(stderr);
     1469
     1470        if (DEBUG(GRAPH2))
     1471                Targ_PrintGraph(2);
     1472        exit(2);                /* Not 1 so -q can distinguish error */
    13461473}
    13471474
    13481475/*
    13491476 * Punt --
    1350  *      Major exception once jobs are being created. Kills all jobs, prints
    1351  *      a message and exits.
     1477 *      Major exception once jobs are being created. Kills all jobs, prints
     1478 *      a message and exits.
    13521479 *
    13531480 * Results:
    1354  *      None
     1481 *      None
    13551482 *
    13561483 * Side Effects:
    1357  *      All children are killed indiscriminately and the program Lib_Exits
     1484 *      All children are killed indiscriminately and the program Lib_Exits
    13581485 */
    13591486/* VARARGS */
     
    13631490#else
    13641491Punt(va_alist)
    1365         va_dcl
    1366 #endif
    1367 {
    1368         va_list ap;
     1492        va_dcl
     1493#endif
     1494{
     1495        va_list ap;
    13691496#if defined(__STDC__) || defined(__IBMC__)
    1370         va_start(ap, fmt);
    1371 #else
    1372         char *fmt;
    1373 
    1374         va_start(ap);
    1375         fmt = va_arg(ap, char *);
    1376 #endif
    1377 
    1378         (void)fprintf(stderr, MAKE_NAME ": ");
    1379         (void)vfprintf(stderr, fmt, ap);
    1380         va_end(ap);
    1381         (void)fprintf(stderr, "\n");
    1382         (void)fflush(stderr);
    1383 
    1384         DieHorribly();
     1497        va_start(ap, fmt);
     1498#else
     1499        char *fmt;
     1500
     1501        va_start(ap);
     1502        fmt = va_arg(ap, char *);
     1503#endif
     1504
     1505        (void)fprintf(stderr, MAKE_NAME ": ");
     1506        (void)vfprintf(stderr, fmt, ap);
     1507        va_end(ap);
     1508        (void)fprintf(stderr, "\n");
     1509        (void)fflush(stderr);
     1510
     1511        DieHorribly();
    13851512}
    13861513
    13871514/*-
    13881515 * DieHorribly --
    1389  *      Exit without giving a message.
     1516 *      Exit without giving a message.
    13901517 *
    13911518 * Results:
    1392  *      None
     1519 *      None
    13931520 *
    13941521 * Side Effects:
    1395  *      A big one...
     1522 *      A big one...
    13961523 */
    13971524void
    13981525DieHorribly()
    13991526{
    1400         if (jobsRunning)
    1401                 Job_AbortAll();
    1402         if (DEBUG(GRAPH2))
    1403                 Targ_PrintGraph(2);
    1404         exit(2);                /* Not 1, so -q can distinguish error */
     1527        if (jobsRunning)
     1528                Job_AbortAll();
     1529        if (DEBUG(GRAPH2))
     1530                Targ_PrintGraph(2);
     1531        exit(2);                /* Not 1, so -q can distinguish error */
    14051532}
    14061533
    14071534/*
    14081535 * Finish --
    1409  *      Called when aborting due to errors in child shell to signal
    1410  *      abnormal exit.
     1536 *      Called when aborting due to errors in child shell to signal
     1537 *      abnormal exit.
    14111538 *
    14121539 * Results:
    1413  *      None
     1540 *      None
    14141541 *
    14151542 * Side Effects:
    1416  *      The program exits
     1543 *      The program exits
    14171544 */
    14181545void
    14191546Finish(errors)
    1420         int errors;     /* number of errors encountered in Make_Make */
    1421 {
    1422         Fatal("%d error%s", errors, errors == 1 ? "" : "s");
     1547        int errors;     /* number of errors encountered in Make_Make */
     1548{
     1549        Fatal("%d error%s", errors, errors == 1 ? "" : "s");
    14231550}
    14241551
    14251552/*
    14261553 * emalloc --
    1427  *      malloc, but die on error.
     1554 *      malloc, but die on error.
    14281555 */
    14291556void *
    14301557emalloc(len)
    1431         size_t len;
    1432 {
    1433         void *p;
    1434 
    1435         if ((p = malloc(len)) == NULL)
    1436                 enomem();
    1437         return(p);
     1558        size_t len;
     1559{
     1560        void *p;
     1561
     1562        if ((p = malloc(len)) == NULL)
     1563                enomem();
     1564        return(p);
    14381565}
    14391566
    14401567/*
    14411568 * estrdup --
    1442  *      strdup, but die on error.
     1569 *      strdup, but die on error.
    14431570 */
    14441571char *
    14451572estrdup(str)
    1446         const char *str;
    1447 {
    1448         char *p;
    1449 
    1450         if ((p = strdup(str)) == NULL)
    1451                 enomem();
    1452         return(p);
     1573        const char *str;
     1574{
     1575        char *p;
     1576
     1577        if ((p = strdup(str)) == NULL)
     1578                enomem();
     1579        return(p);
    14531580}
    14541581
    14551582/*
    14561583 * erealloc --
    1457  *      realloc, but die on error.
     1584 *      realloc, but die on error.
    14581585 */
    14591586void *
    14601587erealloc(ptr, size)
    1461         void *ptr;
    1462         size_t size;
    1463 {
    1464         if ((ptr = realloc(ptr, size)) == NULL)
    1465                 enomem();
    1466         return(ptr);
     1588        void *ptr;
     1589        size_t size;
     1590{
     1591        if ((ptr = realloc(ptr, size)) == NULL)
     1592                enomem();
     1593        return(ptr);
    14671594}
    14681595
     
    14811608/*
    14821609 * enomem --
    1483  *      die when out of memory.
     1610 *      die when out of memory.
    14841611 */
    14851612void
    14861613enomem()
    14871614{
    1488         err(2, NULL);
     1615        err(2, NULL);
    14891616}
    14901617
    14911618/*
    14921619 * enunlink --
    1493  *      Remove a file carefully, avoiding directories.
     1620 *      Remove a file carefully, avoiding directories.
    14941621 */
    14951622int
    14961623eunlink(file)
    1497         const char *file;
    1498 {
    1499         struct stat st;
    1500 
    1501 #ifdef __EMX__
    1502         if (stat(file, &st) == -1)
    1503 #else
    1504         if (lstat(file, &st) == -1)
    1505 #endif
    1506                 return -1;
    1507 
    1508         if (S_ISDIR(st.st_mode)) {
    1509                 errno = EISDIR;
    1510                 return -1;
    1511         }
    1512         return unlink(file);
     1624        const char *file;
     1625{
     1626        struct stat st;
     1627
     1628#if defined(OS2)
     1629        if (stat(file, &st) == -1)
     1630#else
     1631        if (lstat(file, &st) == -1)
     1632#endif
     1633                return -1;
     1634
     1635        if (S_ISDIR(st.st_mode)) {
     1636                errno = EISDIR;
     1637                return -1;
     1638        }
     1639        return unlink(file);
    15131640}
    15141641
    15151642/*
    15161643 * usage --
    1517  *      exit with usage message
     1644 *      exit with usage message
    15181645 */
    15191646static void
    15201647usage()
    15211648{
    1522         (void)fprintf(stderr, "%s\n%s\n%s\n"
     1649        (void)fprintf(stderr, "%s\n%s\n%s\n"
    15231650#ifdef NMAKE
    15241651"%s\n"
     
    15381665#endif
    15391666);
    1540         exit(2);
     1667        exit(2);
    15411668}
    15421669
  • trunk/src/kmk/make.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[] = "@(#)make.c      8.1 (Berkeley) 6/6/93";
     41static char sccsid[] = "@(#)make.c      8.1 (Berkeley) 6/6/93";
    4242#else
    4343static const char rcsid[] =
    4444  "$FreeBSD: src/usr.bin/make/make.c,v 1.11 1999/09/11 13:08:01 hoek Exp $";
    4545#endif
     46#define KLIBFILEDEF rcsid
    4647#endif /* not lint */
    4748
    4849/*-
    4950 * make.c --
    50  *      The functions which perform the examination of targets and
    51  *      their suitability for creation
     51 *      The functions which perform the examination of targets and
     52 *      their suitability for creation
    5253 *
    5354 * Interface:
    54  *      Make_Run                Initialize things for the module and recreate
    55  *                              whatever needs recreating. Returns TRUE if
    56  *                              work was (or would have been) done and FALSE
    57  *                              otherwise.
    58  *
    59  *      Make_Update             Update all parents of a given child. Performs
    60  *                              various bookkeeping chores like the updating
    61  *                              of the cmtime field of the parent, filling
    62  *                              of the IMPSRC context variable, etc. It will
    63  *                              place the parent on the toBeMade queue if it
    64  *                              should be.
    65  *
    66  *      Make_TimeStamp          Function to set the parent's cmtime field
    67  *                              based on a child's modification time.
    68  *
    69  *      Make_DoAllVar           Set up the various local variables for a
    70  *                              target, including the .ALLSRC variable, making
    71  *                              sure that any variable that needs to exist
    72  *                              at the very least has the empty value.
    73  *
    74  *      Make_OODate             Determine if a target is out-of-date.
    75  *
    76  *      Make_HandleUse          See if a child is a .USE node for a parent
    77  *                              and perform the .USE actions if so.
     55 *      Make_Run                Initialize things for the module and recreate
     56 *                              whatever needs recreating. Returns TRUE if
     57 *                              work was (or would have been) done and FALSE
     58 *                              otherwise.
     59 *
     60 *      Make_Update             Update all parents of a given child. Performs
     61 *                              various bookkeeping chores like the updating
     62 *                              of the cmtime field of the parent, filling
     63 *                              of the IMPSRC context variable, etc. It will
     64 *                              place the parent on the toBeMade queue if it
     65 *                              should be.
     66 *
     67 *      Make_TimeStamp          Function to set the parent's cmtime field
     68 *                              based on a child's modification time.
     69 *
     70 *      Make_DoAllVar           Set up the various local variables for a
     71 *                              target, including the .ALLSRC variable, making
     72 *                              sure that any variable that needs to exist
     73 *                              at the very least has the empty value.
     74 *
     75 *      Make_OODate             Determine if a target is out-of-date.
     76 *
     77 *      Make_HandleUse          See if a child is a .USE node for a parent
     78 *                              and perform the .USE actions if so.
    7879 */
    7980
     
    8384#include    "job.h"
    8485
    85 static Lst      toBeMade;       /* The current fringe of the graph. These
    86                                 * are nodes which await examination by
    87                                 * MakeOODate. It is added to by
    88                                 * Make_Update and subtracted from by
    89                                 * MakeStartJobs */
    90 static int      numNodes;       /* Number of nodes to be processed. If this
    91                                 * is non-zero when Job_Empty() returns
    92                                 * TRUE, there's a cycle in the graph */
     86static Lst      toBeMade;       /* The current fringe of the graph. These
     87                                * are nodes which await examination by
     88                                * MakeOODate. It is added to by
     89                                * Make_Update and subtracted from by
     90                                * MakeStartJobs */
     91static int      numNodes;       /* Number of nodes to be processed. If this
     92                                * is non-zero when Job_Empty() returns
     93                                * TRUE, there's a cycle in the graph */
    9394
    9495static int MakeAddChild __P((ClientData, ClientData));
     
    101102 *-----------------------------------------------------------------------
    102103 * Make_TimeStamp --
    103  *      Set the cmtime field of a parent node based on the mtime stamp in its
    104  *      child. Called from MakeOODate via Lst_ForEach.
    105  *
    106  * Results:
    107  *      Always returns 0.
    108  *
    109  * Side Effects:
    110  *      The cmtime of the parent node will be changed if the mtime
    111  *      field of the child is greater than it.
     104 *      Set the cmtime field of a parent node based on the mtime stamp in its
     105 *      child. Called from MakeOODate via Lst_ForEach.
     106 *
     107 * Results:
     108 *      Always returns 0.
     109 *
     110 * Side Effects:
     111 *      The cmtime of the parent node will be changed if the mtime
     112 *      field of the child is greater than it.
    112113 *-----------------------------------------------------------------------
    113114 */
    114115int
    115116Make_TimeStamp (pgn, cgn)
    116     GNode *pgn; /* the current parent */
    117     GNode *cgn; /* the child we've just examined */
     117    GNode *pgn; /* the current parent */
     118    GNode *cgn; /* the child we've just examined */
    118119{
    119120    if (cgn->mtime > pgn->cmtime) {
    120         pgn->cmtime = cgn->mtime;
     121        pgn->cmtime = cgn->mtime;
    121122    }
    122123    return (0);
     
    125126static int
    126127MakeTimeStamp (pgn, cgn)
    127     ClientData pgn;     /* the current parent */
    128     ClientData cgn;     /* the child we've just examined */
     128    ClientData pgn;     /* the current parent */
     129    ClientData cgn;     /* the child we've just examined */
    129130{
    130131    return Make_TimeStamp((GNode *) pgn, (GNode *) cgn);
     
    135136 *-----------------------------------------------------------------------
    136137 * Make_OODate --
    137  *      See if a given node is out of date with respect to its sources.
    138  *      Used by Make_Run when deciding which nodes to place on the
    139  *      toBeMade queue initially and by Make_Update to screen out USE and
    140  *      EXEC nodes. In the latter case, however, any other sort of node
    141  *      must be considered out-of-date since at least one of its children
    142  *      will have been recreated.
    143  *
    144  * Results:
    145  *      TRUE if the node is out of date. FALSE otherwise.
    146  *
    147  * Side Effects:
    148  *      The mtime field of the node and the cmtime field of its parents
    149  *      will/may be changed.
     138 *      See if a given node is out of date with respect to its sources.
     139 *      Used by Make_Run when deciding which nodes to place on the
     140 *      toBeMade queue initially and by Make_Update to screen out USE and
     141 *      EXEC nodes. In the latter case, however, any other sort of node
     142 *      must be considered out-of-date since at least one of its children
     143 *      will have been recreated.
     144 *
     145 * Results:
     146 *      TRUE if the node is out of date. FALSE otherwise.
     147 *
     148 * Side Effects:
     149 *      The mtime field of the node and the cmtime field of its parents
     150 *      will/may be changed.
    150151 *-----------------------------------------------------------------------
    151152 */
    152153Boolean
    153154Make_OODate (gn)
    154     register GNode *gn;       /* the node to check */
     155    register GNode *gn;       /* the node to check */
    155156{
    156157    Boolean         oodate;
     
    161162     */
    162163    if ((gn->type & (OP_JOIN|OP_USE|OP_EXEC)) == 0) {
    163         (void) Dir_MTime (gn);
    164         if (DEBUG(MAKE)) {
    165             if (gn->mtime != 0) {
    166                 printf ("modified %s...", Targ_FmtTime(gn->mtime));
    167             } else {
    168                 printf ("non-existent...");
    169             }
    170         }
     164        (void) Dir_MTime (gn);
     165        if (DEBUG(MAKE)) {
     166            if (gn->mtime != 0) {
     167                printf ("modified %s...", Targ_FmtTime(gn->mtime));
     168            } else {
     169                printf ("non-existent...");
     170            }
     171        }
    171172    }
    172173
    173174    /*
    174175     * A target is remade in one of the following circumstances:
    175      *  its modification time is smaller than that of its youngest child
    176      *      and it would actually be run (has commands or type OP_NOP)
    177      *  it's the object of a force operator
    178      *  it has no children, was on the lhs of an operator and doesn't exist
    179      *      already.
     176     *  its modification time is smaller than that of its youngest child
     177     *      and it would actually be run (has commands or type OP_NOP)
     178     *  it's the object of a force operator
     179     *  it has no children, was on the lhs of an operator and doesn't exist
     180     *      already.
    180181     *
    181182     * Libraries are only considered out-of-date if the archive module says
     
    186187     */
    187188    if (gn->type & OP_USE) {
    188         /*
    189         * If the node is a USE node it is *never* out of date
    190         * no matter *what*.
    191         */
    192         if (DEBUG(MAKE)) {
    193             printf(".USE node...");
    194         }
    195         oodate = FALSE;
     189        /*
     190        * If the node is a USE node it is *never* out of date
     191        * no matter *what*.
     192        */
     193        if (DEBUG(MAKE)) {
     194            printf(".USE node...");
     195        }
     196        oodate = FALSE;
    196197#ifdef USE_ARCHIVES
    197198    } else if (gn->type & OP_LIB) {
    198         if (DEBUG(MAKE)) {
    199             printf("library...");
    200         }
    201 
    202         /*
    203         * always out of date if no children and :: target
    204         */
    205 
    206         oodate = Arch_LibOODate (gn) ||
    207             ((gn->cmtime == 0) && (gn->type & OP_DOUBLEDEP));
     199        if (DEBUG(MAKE)) {
     200            printf("library...");
     201        }
     202
     203        /*
     204        * always out of date if no children and :: target
     205        */
     206
     207        oodate = Arch_LibOODate (gn) ||
     208            ((gn->cmtime == 0) && (gn->type & OP_DOUBLEDEP));
    208209#endif
    209210    } else if (gn->type & OP_JOIN) {
    210         /*
    211         * A target with the .JOIN attribute is only considered
    212         * out-of-date if any of its children was out-of-date.
    213         */
    214         if (DEBUG(MAKE)) {
    215             printf(".JOIN node...");
    216         }
    217         oodate = gn->childMade;
     211        /*
     212        * A target with the .JOIN attribute is only considered
     213        * out-of-date if any of its children was out-of-date.
     214        */
     215        if (DEBUG(MAKE)) {
     216            printf(".JOIN node...");
     217        }
     218        oodate = gn->childMade;
    218219    } else if (gn->type & (OP_FORCE|OP_EXEC|OP_PHONY)) {
    219         /*
    220         * A node which is the object of the force (!) operator or which has
    221         * the .EXEC attribute is always considered out-of-date.
    222         */
    223         if (DEBUG(MAKE)) {
    224             if (gn->type & OP_FORCE) {
    225                 printf("! operator...");
    226             } else if (gn->type & OP_PHONY) {
    227                 printf(".PHONY node...");
    228             } else {
    229                 printf(".EXEC node...");
    230             }
    231         }
    232         oodate = TRUE;
     220        /*
     221        * A node which is the object of the force (!) operator or which has
     222        * the .EXEC attribute is always considered out-of-date.
     223        */
     224        if (DEBUG(MAKE)) {
     225            if (gn->type & OP_FORCE) {
     226                printf("! operator...");
     227            } else if (gn->type & OP_PHONY) {
     228                printf(".PHONY node...");
     229            } else {
     230                printf(".EXEC node...");
     231            }
     232        }
     233        oodate = TRUE;
    233234    } else if ((gn->mtime < gn->cmtime) ||
    234                ((gn->cmtime == 0) &&
    235                 ((gn->mtime==0) || (gn->type & OP_DOUBLEDEP))))
     235               ((gn->cmtime == 0) &&
     236                ((gn->mtime==0) || (gn->type & OP_DOUBLEDEP))))
    236237    {
    237         /*
    238         * A node whose modification time is less than that of its
    239         * youngest child or that has no children (cmtime == 0) and
    240         * either doesn't exist (mtime == 0) or was the object of a
    241         * :: operator is out-of-date. Why? Because that's the way Make does
    242         * it.
    243         */
    244         if (DEBUG(MAKE)) {
    245             if (gn->mtime < gn->cmtime) {
    246                 printf("modified before source...");
    247             } else if (gn->mtime == 0) {
    248                 printf("non-existent and no sources...");
    249             } else {
    250                 printf(":: operator and no sources...");
    251             }
    252         }
    253         oodate = TRUE;
     238        /*
     239        * A node whose modification time is less than that of its
     240        * youngest child or that has no children (cmtime == 0) and
     241        * either doesn't exist (mtime == 0) or was the object of a
     242        * :: operator is out-of-date. Why? Because that's the way Make does
     243        * it.
     244        */
     245        if (DEBUG(MAKE)) {
     246            if (gn->mtime < gn->cmtime) {
     247                printf("modified before source...");
     248            } else if (gn->mtime == 0) {
     249                printf("non-existent and no sources...");
     250            } else {
     251                printf(":: operator and no sources...");
     252            }
     253        }
     254        oodate = TRUE;
    254255    } else {
    255256#if 0
    256         /* WHY? */
    257         if (DEBUG(MAKE)) {
    258             printf("source %smade...", gn->childMade ? "" : "not ");
    259         }
    260         oodate = gn->childMade;
     257        /* WHY? */
     258        if (DEBUG(MAKE)) {
     259            printf("source %smade...", gn->childMade ? "" : "not ");
     260        }
     261        oodate = gn->childMade;
    261262#else
    262         oodate = FALSE;
     263        oodate = FALSE;
    263264#endif /* 0 */
    264265    }
     
    272273     */
    273274    if (!oodate) {
    274         Lst_ForEach (gn->parents, MakeTimeStamp, (ClientData)gn);
     275        Lst_ForEach (gn->parents, MakeTimeStamp, (ClientData)gn);
    275276    }
    276277
     
    282283 *-----------------------------------------------------------------------
    283284 * MakeAddChild  --
    284  *      Function used by Make_Run to add a child to the list l.
    285  *      It will only add the child if its make field is FALSE.
    286  *
    287  * Results:
    288  *      Always returns 0
    289  *
    290  * Side Effects:
    291  *      The given list is extended
     285 *      Function used by Make_Run to add a child to the list l.
     286 *      It will only add the child if its make field is FALSE.
     287 *
     288 * Results:
     289 *      Always returns 0
     290 *
     291 * Side Effects:
     292 *      The given list is extended
    292293 *-----------------------------------------------------------------------
    293294 */
    294295static int
    295296MakeAddChild (gnp, lp)
    296     ClientData     gnp;         /* the node to add */
    297     ClientData     lp;          /* the list to which to add it */
     297    ClientData     gnp;         /* the node to add */
     298    ClientData     lp;          /* the list to which to add it */
    298299{
    299300    GNode          *gn = (GNode *) gnp;
     
    301302
    302303    if (!gn->make && !(gn->type & OP_USE)) {
    303         (void)Lst_EnQueue (l, (ClientData)gn);
     304        (void)Lst_EnQueue (l, (ClientData)gn);
    304305    }
    305306    return (0);
     
    310311 *-----------------------------------------------------------------------
    311312 * Make_HandleUse --
    312  *      Function called by Make_Run and SuffApplyTransform on the downward
    313  *      pass to handle .USE and transformation nodes. A callback function
    314  *      for Lst_ForEach, it implements the .USE and transformation
    315  *      functionality by copying the node's commands, type flags
    316  *      and children to the parent node. Should be called before the
    317  *      children are enqueued to be looked at by MakeAddChild.
    318  *
    319  *      A .USE node is much like an explicit transformation rule, except
    320  *      its commands are always added to the target node, even if the
    321  *      target already has commands.
    322  *
    323  * Results:
    324  *      returns 0.
    325  *
    326  * Side Effects:
    327  *      Children and commands may be added to the parent and the parent's
    328  *      type may be changed.
     313 *      Function called by Make_Run and SuffApplyTransform on the downward
     314 *      pass to handle .USE and transformation nodes. A callback function
     315 *      for Lst_ForEach, it implements the .USE and transformation
     316 *      functionality by copying the node's commands, type flags
     317 *      and children to the parent node. Should be called before the
     318 *      children are enqueued to be looked at by MakeAddChild.
     319 *
     320 *      A .USE node is much like an explicit transformation rule, except
     321 *      its commands are always added to the target node, even if the
     322 *      target already has commands.
     323 *
     324 * Results:
     325 *      returns 0.
     326 *
     327 * Side Effects:
     328 *      Children and commands may be added to the parent and the parent's
     329 *      type may be changed.
    329330 *
    330331 *-----------------------------------------------------------------------
     
    332333int
    333334Make_HandleUse (cgn, pgn)
    334     register GNode      *cgn;   /* The .USE node */
    335     register GNode      *pgn;   /* The target of the .USE node */
    336 {
    337     register GNode      *gn;    /* A child of the .USE node */
    338     register LstNode    ln;     /* An element in the children list */
     335    register GNode      *cgn;   /* The .USE node */
     336    register GNode      *pgn;   /* The target of the .USE node */
     337{
     338    register GNode      *gn;    /* A child of the .USE node */
     339    register LstNode    ln;     /* An element in the children list */
    339340
    340341    if (cgn->type & (OP_USE|OP_TRANSFORM)) {
    341         if ((cgn->type & OP_USE) || Lst_IsEmpty(pgn->commands)) {
    342             /*
    343              * .USE or transformation and target has no commands -- append
    344              * the child's commands to the parent.
    345              */
    346             (void) Lst_Concat (pgn->commands, cgn->commands, LST_CONCNEW);
    347         }
    348 
    349         if (Lst_Open (cgn->children) == SUCCESS) {
    350             while ((ln = Lst_Next (cgn->children)) != NILLNODE) {
    351                 gn = (GNode *)Lst_Datum (ln);
    352 
    353                 if (Lst_Member (pgn->children, gn) == NILLNODE) {
    354                     (void) Lst_AtEnd (pgn->children, gn);
    355                     (void) Lst_AtEnd (gn->parents, pgn);
    356                     pgn->unmade += 1;
    357                 }
    358             }
    359             Lst_Close (cgn->children);
    360         }
    361 
    362         pgn->type |= cgn->type & ~(OP_OPMASK|OP_USE|OP_TRANSFORM);
    363 
    364         /*
    365         * This child node is now "made", so we decrement the count of
    366         * unmade children in the parent... We also remove the child
    367         * from the parent's list to accurately reflect the number of decent
    368         * children the parent has. This is used by Make_Run to decide
    369         * whether to queue the parent or examine its children...
    370         */
    371         if (cgn->type & OP_USE) {
    372             pgn->unmade--;
    373         }
     342        if ((cgn->type & OP_USE) || Lst_IsEmpty(pgn->commands)) {
     343            /*
     344             * .USE or transformation and target has no commands -- append
     345             * the child's commands to the parent.
     346             */
     347            (void) Lst_Concat (pgn->commands, cgn->commands, LST_CONCNEW);
     348        }
     349
     350        if (Lst_Open (cgn->children) == SUCCESS) {
     351            while ((ln = Lst_Next (cgn->children)) != NILLNODE) {
     352                gn = (GNode *)Lst_Datum (ln);
     353
     354                if (Lst_Member (pgn->children, gn) == NILLNODE) {
     355                    (void) Lst_AtEnd (pgn->children, gn);
     356                    (void) Lst_AtEnd (gn->parents, pgn);
     357                    pgn->unmade += 1;
     358                }
     359            }
     360            Lst_Close (cgn->children);
     361        }
     362
     363        pgn->type |= cgn->type & ~(OP_OPMASK|OP_USE|OP_TRANSFORM);
     364
     365        /*
     366        * This child node is now "made", so we decrement the count of
     367        * unmade children in the parent... We also remove the child
     368        * from the parent's list to accurately reflect the number of decent
     369        * children the parent has. This is used by Make_Run to decide
     370        * whether to queue the parent or examine its children...
     371        */
     372        if (cgn->type & OP_USE) {
     373            pgn->unmade--;
     374        }
    374375    }
    375376    return (0);
     
    377378static int
    378379MakeHandleUse (pgn, cgn)
    379     ClientData pgn;     /* the current parent */
    380     ClientData cgn;     /* the child we've just examined */
     380    ClientData pgn;     /* the current parent */
     381    ClientData cgn;     /* the child we've just examined */
    381382{
    382383    return Make_HandleUse((GNode *) pgn, (GNode *) cgn);
     
    387388 *-----------------------------------------------------------------------
    388389 * Make_Update  --
    389  *      Perform update on the parents of a node. Used by JobFinish once
    390  *      a node has been dealt with and by MakeStartJobs if it finds an
    391  *      up-to-date node.
    392  *
    393  * Results:
    394  *      Always returns 0
    395  *
    396  * Side Effects:
    397  *      The unmade field of pgn is decremented and pgn may be placed on
    398  *      the toBeMade queue if this field becomes 0.
    399  *
    400  *      If the child was made, the parent's childMade field will be set true
    401  *      and its cmtime set to now.
    402  *
    403  *      If the child wasn't made, the cmtime field of the parent will be
    404  *      altered if the child's mtime is big enough.
    405  *
    406  *      Finally, if the child is the implied source for the parent, the
    407  *      parent's IMPSRC variable is set appropriately.
     390 *      Perform update on the parents of a node. Used by JobFinish once
     391 *      a node has been dealt with and by MakeStartJobs if it finds an
     392 *      up-to-date node.
     393 *
     394 * Results:
     395 *      Always returns 0
     396 *
     397 * Side Effects:
     398 *      The unmade field of pgn is decremented and pgn may be placed on
     399 *      the toBeMade queue if this field becomes 0.
     400 *
     401 *      If the child was made, the parent's childMade field will be set true
     402 *      and its cmtime set to now.
     403 *
     404 *      If the child wasn't made, the cmtime field of the parent will be
     405 *      altered if the child's mtime is big enough.
     406 *
     407 *      Finally, if the child is the implied source for the parent, the
     408 *      parent's IMPSRC variable is set appropriately.
    408409 *
    409410 *-----------------------------------------------------------------------
     
    411412void
    412413Make_Update (cgn)
    413     register GNode *cgn;        /* the child node */
    414 {
    415     register GNode      *pgn;   /* the parent node */
    416     register char       *cname; /* the child's name */
    417     register LstNode    ln;     /* Element in parents and iParents lists */
     414    register GNode *cgn;        /* the child node */
     415{
     416    register GNode      *pgn;   /* the parent node */
     417    register char       *cname; /* the child's name */
     418    register LstNode    ln;     /* Element in parents and iParents lists */
    418419    char *p1;
    419420
     
    428429    if (cgn->made != UPTODATE) {
    429430#ifndef RECHECK
    430         /*
    431         * We can't re-stat the thing, but we can at least take care of rules
    432         * where a target depends on a source that actually creates the
    433         * target, but only if it has changed, e.g.
    434         *
    435         * parse.h : parse.o
    436         *
    437         * parse.o : parse.y
    438          *      yacc -d parse.y
    439          *      cc -c y.tab.c
    440          *      mv y.tab.o parse.o
    441          *      cmp -s y.tab.h parse.h || mv y.tab.h parse.h
    442         *
    443         * In this case, if the definitions produced by yacc haven't changed
    444         * from before, parse.h won't have been updated and cgn->mtime will
    445         * reflect the current modification time for parse.h. This is
    446         * something of a kludge, I admit, but it's a useful one..
    447         * XXX: People like to use a rule like
    448         *
    449         * FRC:
    450         *
    451         * To force things that depend on FRC to be made, so we have to
    452         * check for gn->children being empty as well...
    453         */
    454         if (!Lst_IsEmpty(cgn->commands) || Lst_IsEmpty(cgn->children)) {
    455             cgn->mtime = now;
    456         }
     431        /*
     432        * We can't re-stat the thing, but we can at least take care of rules
     433        * where a target depends on a source that actually creates the
     434        * target, but only if it has changed, e.g.
     435        *
     436        * parse.h : parse.o
     437        *
     438        * parse.o : parse.y
     439         *      yacc -d parse.y
     440         *      cc -c y.tab.c
     441         *      mv y.tab.o parse.o
     442         *      cmp -s y.tab.h parse.h || mv y.tab.h parse.h
     443        *
     444        * In this case, if the definitions produced by yacc haven't changed
     445        * from before, parse.h won't have been updated and cgn->mtime will
     446        * reflect the current modification time for parse.h. This is
     447        * something of a kludge, I admit, but it's a useful one..
     448        * XXX: People like to use a rule like
     449        *
     450        * FRC:
     451        *
     452        * To force things that depend on FRC to be made, so we have to
     453        * check for gn->children being empty as well...
     454        */
     455        if (!Lst_IsEmpty(cgn->commands) || Lst_IsEmpty(cgn->children)) {
     456            cgn->mtime = now;
     457        }
    457458#else
    458         /*
    459         * This is what Make does and it's actually a good thing, as it
    460         * allows rules like
    461         *
    462          *      cmp -s y.tab.h parse.h || cp y.tab.h parse.h
    463         *
    464         * to function as intended. Unfortunately, thanks to the stateless
    465         * nature of NFS (by which I mean the loose coupling of two clients
    466         * using the same file from a common server), there are times
    467         * when the modification time of a file created on a remote
    468         * machine will not be modified before the local stat() implied by
    469         * the Dir_MTime occurs, thus leading us to believe that the file
    470         * is unchanged, wreaking havoc with files that depend on this one.
    471         *
    472         * I have decided it is better to make too much than to make too
    473         * little, so this stuff is commented out unless you're sure it's ok.
    474         * -- ardeb 1/12/88
    475         */
    476         /*
    477         * Christos, 4/9/92: If we are  saving commands pretend that
    478         * the target is made now. Otherwise archives with ... rules
    479         * don't work!
    480         */
    481         if (noExecute || (cgn->type & OP_SAVE_CMDS) || Dir_MTime(cgn) == 0) {
    482             cgn->mtime = now;
    483         }
    484         if (DEBUG(MAKE)) {
    485             printf("update time: %s\n", Targ_FmtTime(cgn->mtime));
    486         }
     459        /*
     460        * This is what Make does and it's actually a good thing, as it
     461        * allows rules like
     462        *
     463         *      cmp -s y.tab.h parse.h || cp y.tab.h parse.h
     464        *
     465        * to function as intended. Unfortunately, thanks to the stateless
     466        * nature of NFS (by which I mean the loose coupling of two clients
     467        * using the same file from a common server), there are times
     468        * when the modification time of a file created on a remote
     469        * machine will not be modified before the local stat() implied by
     470        * the Dir_MTime occurs, thus leading us to believe that the file
     471        * is unchanged, wreaking havoc with files that depend on this one.
     472        *
     473        * I have decided it is better to make too much than to make too
     474        * little, so this stuff is commented out unless you're sure it's ok.
     475        * -- ardeb 1/12/88
     476        */
     477        /*
     478        * Christos, 4/9/92: If we are  saving commands pretend that
     479        * the target is made now. Otherwise archives with ... rules
     480        * don't work!
     481        */
     482        if (noExecute || (cgn->type & OP_SAVE_CMDS) || Dir_MTime(cgn) == 0) {
     483            cgn->mtime = now;
     484        }
     485        if (DEBUG(MAKE)) {
     486            printf("update time: %s\n", Targ_FmtTime(cgn->mtime));
     487        }
    487488#endif
    488489    }
    489490
    490491    if (Lst_Open (cgn->parents) == SUCCESS) {
    491         while ((ln = Lst_Next (cgn->parents)) != NILLNODE) {
    492             pgn = (GNode *)Lst_Datum (ln);
    493             if (pgn->make) {
    494                 pgn->unmade -= 1;
    495 
    496                 if ( ! (cgn->type & (OP_EXEC|OP_USE))) {
    497                     if (cgn->made == MADE) {
    498                         pgn->childMade = TRUE;
    499                         if (pgn->cmtime < cgn->mtime) {
    500                             pgn->cmtime = cgn->mtime;
    501                         }
    502                     } else {
    503                         (void)Make_TimeStamp (pgn, cgn);
    504                     }
    505                 }
    506                 if (pgn->unmade == 0) {
    507                     /*
    508                      * Queue the node up -- any unmade predecessors will
    509                      * be dealt with in MakeStartJobs.
    510                      */
    511                     (void)Lst_EnQueue (toBeMade, (ClientData)pgn);
    512                 } else if (pgn->unmade < 0) {
    513                     Error ("Graph cycles through %s", pgn->name);
    514                 }
    515             }
    516         }
    517         Lst_Close (cgn->parents);
     492        while ((ln = Lst_Next (cgn->parents)) != NILLNODE) {
     493            pgn = (GNode *)Lst_Datum (ln);
     494            if (pgn->make) {
     495                pgn->unmade -= 1;
     496
     497                if ( ! (cgn->type & (OP_EXEC|OP_USE))) {
     498                    if (cgn->made == MADE) {
     499                        pgn->childMade = TRUE;
     500                        if (pgn->cmtime < cgn->mtime) {
     501                            pgn->cmtime = cgn->mtime;
     502                        }
     503                    } else {
     504                        (void)Make_TimeStamp (pgn, cgn);
     505                    }
     506                }
     507                if (pgn->unmade == 0) {
     508                    /*
     509                     * Queue the node up -- any unmade predecessors will
     510                     * be dealt with in MakeStartJobs.
     511                     */
     512                    (void)Lst_EnQueue (toBeMade, (ClientData)pgn);
     513                } else if (pgn->unmade < 0) {
     514                    Error ("Graph cycles through %s", pgn->name);
     515                }
     516            }
     517        }
     518        Lst_Close (cgn->parents);
    518519    }
    519520    /*
     
    524525     */
    525526    for (ln = Lst_First(cgn->successors); ln != NILLNODE; ln = Lst_Succ(ln)) {
    526         GNode   *succ = (GNode *)Lst_Datum(ln);
    527 
    528         if (succ->make && succ->unmade == 0 && succ->made == UNMADE &&
    529             Lst_Member(toBeMade, (ClientData)succ) == NILLNODE)
    530         {
    531             (void)Lst_EnQueue(toBeMade, (ClientData)succ);
    532         }
     527        GNode   *succ = (GNode *)Lst_Datum(ln);
     528
     529        if (succ->make && succ->unmade == 0 && succ->made == UNMADE &&
     530            Lst_Member(toBeMade, (ClientData)succ) == NILLNODE)
     531        {
     532            (void)Lst_EnQueue(toBeMade, (ClientData)succ);
     533        }
    533534    }
    534535
     
    538539     */
    539540    if (Lst_Open (cgn->iParents) == SUCCESS) {
    540         char    *p1;
    541         char    *cpref = Var_Value(PREFIX, cgn, &p1);
    542 
    543         while ((ln = Lst_Next (cgn->iParents)) != NILLNODE) {
    544             pgn = (GNode *)Lst_Datum (ln);
    545             if (pgn->make) {
    546                 Var_Set (IMPSRC, cname, pgn);
    547                 Var_Set (PREFIX, cpref, pgn);
    548             }
    549         }
    550         efree(p1);
    551         Lst_Close (cgn->iParents);
     541        char    *p1;
     542        char    *cpref = Var_Value(PREFIX, cgn, &p1);
     543
     544        while ((ln = Lst_Next (cgn->iParents)) != NILLNODE) {
     545            pgn = (GNode *)Lst_Datum (ln);
     546            if (pgn->make) {
     547                Var_Set (IMPSRC, cname, pgn);
     548                Var_Set (PREFIX, cpref, pgn);
     549            }
     550        }
     551        efree(p1);
     552        Lst_Close (cgn->iParents);
    552553    }
    553554}
     
    557558 *-----------------------------------------------------------------------
    558559 * MakeAddAllSrc --
    559  *      Add a child's name to the ALLSRC and OODATE variables of the given
    560  *      node. Called from Make_DoAllVar via Lst_ForEach. A child is added only
    561  *      if it has not been given the .EXEC, .USE or .INVISIBLE attributes.
    562  *      .EXEC and .USE children are very rarely going to be files, so...
    563  *      A child is added to the OODATE variable if its modification time is
    564  *      later than that of its parent, as defined by Make, except if the
    565  *      parent is a .JOIN node. In that case, it is only added to the OODATE
    566  *      variable if it was actually made (since .JOIN nodes don't have
    567  *      modification times, the comparison is rather unfair...)..
    568  *
    569  * Results:
    570  *      Always returns 0
    571  *
    572  * Side Effects:
    573  *      The ALLSRC variable for the given node is extended.
     560 *      Add a child's name to the ALLSRC and OODATE variables of the given
     561 *      node. Called from Make_DoAllVar via Lst_ForEach. A child is added only
     562 *      if it has not been given the .EXEC, .USE or .INVISIBLE attributes.
     563 *      .EXEC and .USE children are very rarely going to be files, so...
     564 *      A child is added to the OODATE variable if its modification time is
     565 *      later than that of its parent, as defined by Make, except if the
     566 *      parent is a .JOIN node. In that case, it is only added to the OODATE
     567 *      variable if it was actually made (since .JOIN nodes don't have
     568 *      modification times, the comparison is rather unfair...)..
     569 *
     570 * Results:
     571 *      Always returns 0
     572 *
     573 * Side Effects:
     574 *      The ALLSRC variable for the given node is extended.
    574575 *-----------------------------------------------------------------------
    575576 */
    576577static int
    577578MakeAddAllSrc (cgnp, pgnp)
    578     ClientData  cgnp;   /* The child to add */
    579     ClientData  pgnp;   /* The parent to whose ALLSRC variable it should be */
    580                         /* added */
    581 {
    582     GNode       *cgn = (GNode *) cgnp;
    583     GNode       *pgn = (GNode *) pgnp;
     579    ClientData  cgnp;   /* The child to add */
     580    ClientData  pgnp;   /* The parent to whose ALLSRC variable it should be */
     581                        /* added */
     582{
     583    GNode       *cgn = (GNode *) cgnp;
     584    GNode       *pgn = (GNode *) pgnp;
    584585    if ((cgn->type & (OP_EXEC|OP_USE|OP_INVISIBLE)) == 0) {
    585         char *child;
    586         char *p1 = NULL;
    587 
    588         if (OP_NOP(cgn->type)) {
    589             /*
    590              * this node is only source; use the specific pathname for it
    591              */
    592             child = cgn->path ? cgn->path : cgn->name;
    593         }
    594         else
    595             child = Var_Value(TARGET, cgn, &p1);
    596         Var_Append (ALLSRC, child, pgn);
    597         if (pgn->type & OP_JOIN) {
    598             if (cgn->made == MADE) {
    599                 Var_Append(OODATE, child, pgn);
    600             }
    601         } else if ((pgn->mtime < cgn->mtime) ||
    602                    (cgn->mtime >= now && cgn->made == MADE))
    603         {
    604             /*
    605              * It goes in the OODATE variable if the parent is younger than the
    606              * child or if the child has been modified more recently than
    607              * the start of the make. This is to keep pmake from getting
    608              * confused if something else updates the parent after the
    609              * make starts (shouldn't happen, I know, but sometimes it
    610              * does). In such a case, if we've updated the kid, the parent
    611              * is likely to have a modification time later than that of
    612              * the kid and anything that relies on the OODATE variable will
    613              * be hosed.
    614              *
    615              * XXX: This will cause all made children to go in the OODATE
    616              * variable, even if they're not touched, if RECHECK isn't defined,
    617              * since cgn->mtime is set to now in Make_Update. According to
    618              * some people, this is good...
    619              */
    620             Var_Append(OODATE, child, pgn);
    621         }
    622         efree(p1);
     586        char *child;
     587        char *p1 = NULL;
     588
     589        if (OP_NOP(cgn->type)) {
     590            /*
     591             * this node is only source; use the specific pathname for it
     592             */
     593            child = cgn->path ? cgn->path : cgn->name;
     594        }
     595        else
     596            child = Var_Value(TARGET, cgn, &p1);
     597        Var_Append (ALLSRC, child, pgn);
     598        if (pgn->type & OP_JOIN) {
     599            if (cgn->made == MADE) {
     600                Var_Append(OODATE, child, pgn);
     601            }
     602        } else if ((pgn->mtime < cgn->mtime) ||
     603                   (cgn->mtime >= now && cgn->made == MADE))
     604        {
     605            /*
     606             * It goes in the OODATE variable if the parent is younger than the
     607             * child or if the child has been modified more recently than
     608             * the start of the make. This is to keep pmake from getting
     609             * confused if something else updates the parent after the
     610             * make starts (shouldn't happen, I know, but sometimes it
     611             * does). In such a case, if we've updated the kid, the parent
     612             * is likely to have a modification time later than that of
     613             * the kid and anything that relies on the OODATE variable will
     614             * be hosed.
     615             *
     616             * XXX: This will cause all made children to go in the OODATE
     617             * variable, even if they're not touched, if RECHECK isn't defined,
     618             * since cgn->mtime is set to now in Make_Update. According to
     619             * some people, this is good...
     620             */
     621            Var_Append(OODATE, child, pgn);
     622        }
     623        efree(p1);
    623624    }
    624625    return (0);
     
    632633 *
    633634 * Results:
    634  *      Always returns 0
    635  *
    636  * Side Effects:
    637  *      The PARENTS variable for the given node is extended.
     635 *      Always returns 0
     636 *
     637 * Side Effects:
     638 *      The PARENTS variable for the given node is extended.
    638639 *-----------------------------------------------------------------------
    639640 */
    640641static int
    641642MakeAddParents (pgnp, cgnp)
    642     ClientData  pgnp;   /* The parent to add to add */
    643     ClientData  cgnp;   /* The child to whose PARENTS variable it should be */
    644 {
    645     GNode       *pgn = (GNode *) pgnp;
    646     GNode       *cgn = (GNode *) cgnp;
     643    ClientData  pgnp;   /* The parent to add to add */
     644    ClientData  cgnp;   /* The child to whose PARENTS variable it should be */
     645{
     646    GNode       *pgn = (GNode *) pgnp;
     647    GNode       *cgn = (GNode *) cgnp;
    647648    if ((pgn->type & (OP_EXEC|OP_USE|OP_INVISIBLE)) == 0) {
    648         char *parent;
    649         char *p1 = NULL;
    650 
    651 
    652         if (OP_NOP(pgn->type) || !(parent = Var_Value(TARGET, pgn, &p1))) {
    653             /* this node is only source; use the specific pathname for it */
    654             parent = pgn->path ? pgn->path : pgn->name;
    655         }
    656         Var_Append(PARENTS, parent, cgn);
    657         efree(p1);
     649        char *parent;
     650        char *p1 = NULL;
     651
     652
     653        if (OP_NOP(pgn->type) || !(parent = Var_Value(TARGET, pgn, &p1))) {
     654            /* this node is only source; use the specific pathname for it */
     655            parent = pgn->path ? pgn->path : pgn->name;
     656        }
     657        Var_Append(PARENTS, parent, cgn);
     658        efree(p1);
    658659    }
    659660    return (0);
     
    665666 *-----------------------------------------------------------------------
    666667 * Make_DoAllVar --
    667  *      Set up the ALLSRC and OODATE variables. Sad to say, it must be
    668  *      done separately, rather than while traversing the graph. This is
    669  *      because Make defined OODATE to contain all sources whose modification
    670  *      times were later than that of the target, *not* those sources that
    671  *      were out-of-date. Since in both compatibility and native modes,
    672  *      the modification time of the parent isn't found until the child
    673  *      has been dealt with, we have to wait until now to fill in the
    674  *      variable. As for ALLSRC, the ordering is important and not
    675  *      guaranteed when in native mode, so it must be set here, too.
    676  *
    677  * Results:
    678  *      None
    679  *
    680  * Side Effects:
    681  *      The ALLSRC and OODATE variables of the given node is filled in.
    682  *      If the node is a .JOIN node, its TARGET variable will be set to
    683  *      match its ALLSRC variable.
     668 *      Set up the ALLSRC and OODATE variables. Sad to say, it must be
     669 *      done separately, rather than while traversing the graph. This is
     670 *      because Make defined OODATE to contain all sources whose modification
     671 *      times were later than that of the target, *not* those sources that
     672 *      were out-of-date. Since in both compatibility and native modes,
     673 *      the modification time of the parent isn't found until the child
     674 *      has been dealt with, we have to wait until now to fill in the
     675 *      variable. As for ALLSRC, the ordering is important and not
     676 *      guaranteed when in native mode, so it must be set here, too.
     677 *
     678 * Results:
     679 *      None
     680 *
     681 * Side Effects:
     682 *      The ALLSRC and OODATE variables of the given node is filled in.
     683 *      If the node is a .JOIN node, its TARGET variable will be set to
     684 *      match its ALLSRC variable.
    684685 *-----------------------------------------------------------------------
    685686 */
    686687void
    687688Make_DoAllVar (gn)
    688     GNode       *gn;
     689    GNode       *gn;
    689690{
    690691    Lst_ForEach (gn->children, MakeAddAllSrc, (ClientData) gn);
     
    694695
    695696    if (!Var_Exists (OODATE, gn)) {
    696         Var_Set (OODATE, "", gn);
     697        Var_Set (OODATE, "", gn);
    697698    }
    698699    if (!Var_Exists (ALLSRC, gn)) {
    699         Var_Set (ALLSRC, "", gn);
     700        Var_Set (ALLSRC, "", gn);
    700701    }
    701702
    702703    if (gn->type & OP_JOIN) {
    703         char *p1;
    704         Var_Set (TARGET, Var_Value (ALLSRC, gn, &p1), gn);
    705         efree(p1);
     704        char *p1;
     705        Var_Set (TARGET, Var_Value (ALLSRC, gn, &p1), gn);
     706        efree(p1);
    706707    }
    707708}
     
    711712 *-----------------------------------------------------------------------
    712713 * MakeStartJobs --
    713  *      Start as many jobs as possible.
    714  *
    715  * Results:
    716  *      If the query flag was given to pmake, no job will be started,
    717  *      but as soon as an out-of-date target is found, this function
    718  *      returns TRUE. At all other times, this function returns FALSE.
    719  *
    720  * Side Effects:
    721  *      Nodes are removed from the toBeMade queue and job table slots
    722  *      are filled.
     714 *      Start as many jobs as possible.
     715 *
     716 * Results:
     717 *      If the query flag was given to pmake, no job will be started,
     718 *      but as soon as an out-of-date target is found, this function
     719 *      returns TRUE. At all other times, this function returns FALSE.
     720 *
     721 * Side Effects:
     722 *      Nodes are removed from the toBeMade queue and job table slots
     723 *      are filled.
    723724 *
    724725 *-----------------------------------------------------------------------
     
    727728MakeStartJobs ()
    728729{
    729     register GNode      *gn;
     730    register GNode      *gn;
    730731
    731732    while (!Job_Full() && !Lst_IsEmpty (toBeMade)) {
    732         gn = (GNode *) Lst_DeQueue (toBeMade);
    733         if (DEBUG(MAKE)) {
    734             printf ("Examining %s...", gn->name);
    735         }
    736         /*
    737         * Make sure any and all predecessors that are going to be made,
    738         * have been.
    739         */
    740         if (!Lst_IsEmpty(gn->preds)) {
    741             LstNode ln;
    742 
    743             for (ln = Lst_First(gn->preds); ln != NILLNODE; ln = Lst_Succ(ln)){
    744                 GNode   *pgn = (GNode *)Lst_Datum(ln);
    745 
    746                 if (pgn->make && pgn->made == UNMADE) {
    747                     if (DEBUG(MAKE)) {
    748                         printf("predecessor %s not made yet.\n", pgn->name);
    749                     }
    750                     break;
    751                 }
    752             }
    753             /*
    754              * If ln isn't nil, there's a predecessor as yet unmade, so we
    755              * just drop this node on the floor. When the node in question
    756              * has been made, it will notice this node as being ready to
    757              * make but as yet unmade and will place the node on the queue.
    758              */
    759             if (ln != NILLNODE) {
    760                 continue;
    761             }
    762         }
    763 
    764         numNodes--;
    765         if (Make_OODate (gn)) {
    766             if (DEBUG(MAKE)) {
    767                 printf ("out-of-date\n");
    768             }
    769             if (queryFlag) {
    770                 return (TRUE);
    771             }
    772             Make_DoAllVar (gn);
    773             Job_Make (gn);
    774         } else {
    775             if (DEBUG(MAKE)) {
    776                 printf ("up-to-date\n");
    777             }
    778             gn->made = UPTODATE;
    779             if (gn->type & OP_JOIN) {
    780                 /*
    781                 * Even for an up-to-date .JOIN node, we need it to have its
    782                 * context variables so references to it get the correct
    783                 * value for .TARGET when building up the context variables
    784                 * of its parent(s)...
    785                 */
    786                 Make_DoAllVar (gn);
    787             }
    788 
    789             Make_Update (gn);
    790         }
     733        gn = (GNode *) Lst_DeQueue (toBeMade);
     734        if (DEBUG(MAKE)) {
     735            printf ("Examining %s...", gn->name);
     736        }
     737        /*
     738        * Make sure any and all predecessors that are going to be made,
     739        * have been.
     740        */
     741        if (!Lst_IsEmpty(gn->preds)) {
     742            LstNode ln;
     743
     744            for (ln = Lst_First(gn->preds); ln != NILLNODE; ln = Lst_Succ(ln)){
     745                GNode   *pgn = (GNode *)Lst_Datum(ln);
     746
     747                if (pgn->make && pgn->made == UNMADE) {
     748                    if (DEBUG(MAKE)) {
     749                        printf("predecessor %s not made yet.\n", pgn->name);
     750                    }
     751                    break;
     752                }
     753            }
     754            /*
     755             * If ln isn't nil, there's a predecessor as yet unmade, so we
     756             * just drop this node on the floor. When the node in question
     757             * has been made, it will notice this node as being ready to
     758             * make but as yet unmade and will place the node on the queue.
     759             */
     760            if (ln != NILLNODE) {
     761                continue;
     762            }
     763        }
     764
     765        numNodes--;
     766        if (Make_OODate (gn)) {
     767            if (DEBUG(MAKE)) {
     768                printf ("out-of-date\n");
     769            }
     770            if (queryFlag) {
     771                return (TRUE);
     772            }
     773            Make_DoAllVar (gn);
     774            Job_Make (gn);
     775        } else {
     776            if (DEBUG(MAKE)) {
     777                printf ("up-to-date\n");
     778            }
     779            gn->made = UPTODATE;
     780            if (gn->type & OP_JOIN) {
     781                /*
     782                * Even for an up-to-date .JOIN node, we need it to have its
     783                * context variables so references to it get the correct
     784                * value for .TARGET when building up the context variables
     785                * of its parent(s)...
     786                */
     787                Make_DoAllVar (gn);
     788            }
     789
     790            Make_Update (gn);
     791        }
    791792    }
    792793    return (FALSE);
     
    797798 *-----------------------------------------------------------------------
    798799 * MakePrintStatus --
    799  *      Print the status of a top-level node, viz. it being up-to-date
    800  *      already or not created due to an error in a lower level.
    801  *      Callback function for Make_Run via Lst_ForEach.
    802  *
    803  * Results:
    804  *      Always returns 0.
    805  *
    806  * Side Effects:
    807  *      A message may be printed.
     800 *      Print the status of a top-level node, viz. it being up-to-date
     801 *      already or not created due to an error in a lower level.
     802 *      Callback function for Make_Run via Lst_ForEach.
     803 *
     804 * Results:
     805 *      Always returns 0.
     806 *
     807 * Side Effects:
     808 *      A message may be printed.
    808809 *
    809810 *-----------------------------------------------------------------------
     
    811812static int
    812813MakePrintStatus(gnp, cyclep)
    813     ClientData  gnp;        /* Node to examine */
    814     ClientData  cyclep;     /* True if gn->unmade being non-zero implies
    815                              * a cycle in the graph, not an error in an
    816                              * inferior */
    817 {
    818     GNode       *gn = (GNode *) gnp;
    819     Boolean     cycle = *(Boolean *) cyclep;
     814    ClientData  gnp;        /* Node to examine */
     815    ClientData  cyclep;     /* True if gn->unmade being non-zero implies
     816                             * a cycle in the graph, not an error in an
     817                             * inferior */
     818{
     819    GNode       *gn = (GNode *) gnp;
     820    Boolean     cycle = *(Boolean *) cyclep;
    820821    if (gn->made == UPTODATE) {
    821         printf ("`%s' is up to date.\n", gn->name);
     822        printf ("`%s' is up to date.\n", gn->name);
    822823    } else if (gn->unmade != 0) {
    823         if (cycle) {
    824             Boolean t = TRUE;
    825             /*
    826              * If printing cycles and came to one that has unmade children,
    827              * print out the cycle by recursing on its children. Note a
    828              * cycle like:
    829              *  a : b
    830              *  b : c
    831              *  c : b
    832              * will cause this to erroneously complain about a being in
    833              * the cycle, but this is a good approximation.
    834              */
    835             if (gn->made == CYCLE) {
    836                 Error("Graph cycles through `%s'", gn->name);
    837                 gn->made = ENDCYCLE;
    838                 Lst_ForEach(gn->children, MakePrintStatus, (ClientData) &t);
    839                 gn->made = UNMADE;
    840             } else if (gn->made != ENDCYCLE) {
    841                 gn->made = CYCLE;
    842                 Lst_ForEach(gn->children, MakePrintStatus, (ClientData) &t);
    843             }
    844         } else {
    845             printf ("`%s' not remade because of errors.\n", gn->name);
    846         }
     824        if (cycle) {
     825            Boolean t = TRUE;
     826            /*
     827             * If printing cycles and came to one that has unmade children,
     828             * print out the cycle by recursing on its children. Note a
     829             * cycle like:
     830             *  a : b
     831             *  b : c
     832             *  c : b
     833             * will cause this to erroneously complain about a being in
     834             * the cycle, but this is a good approximation.
     835             */
     836            if (gn->made == CYCLE) {
     837                Error("Graph cycles through `%s'", gn->name);
     838                gn->made = ENDCYCLE;
     839                Lst_ForEach(gn->children, MakePrintStatus, (ClientData) &t);
     840                gn->made = UNMADE;
     841            } else if (gn->made != ENDCYCLE) {
     842                gn->made = CYCLE;
     843                Lst_ForEach(gn->children, MakePrintStatus, (ClientData) &t);
     844            }
     845        } else {
     846            printf ("`%s' not remade because of errors.\n", gn->name);
     847        }
    847848    }
    848849    return (0);
     
    853854 *-----------------------------------------------------------------------
    854855 * Make_Run --
    855  *      Initialize the nodes to remake and the list of nodes which are
    856  *      ready to be made by doing a breadth-first traversal of the graph
    857  *      starting from the nodes in the given list. Once this traversal
    858  *      is finished, all the 'leaves' of the graph are in the toBeMade
    859  *      queue.
    860  *      Using this queue and the Job module, work back up the graph,
    861  *      calling on MakeStartJobs to keep the job table as full as
    862  *      possible.
    863  *
    864  * Results:
    865  *      TRUE if work was done. FALSE otherwise.
    866  *
    867  * Side Effects:
    868  *      The make field of all nodes involved in the creation of the given
    869  *      targets is set to 1. The toBeMade list is set to contain all the
    870  *      'leaves' of these subgraphs.
     856 *      Initialize the nodes to remake and the list of nodes which are
     857 *      ready to be made by doing a breadth-first traversal of the graph
     858 *      starting from the nodes in the given list. Once this traversal
     859 *      is finished, all the 'leaves' of the graph are in the toBeMade
     860 *      queue.
     861 *      Using this queue and the Job module, work back up the graph,
     862 *      calling on MakeStartJobs to keep the job table as full as
     863 *      possible.
     864 *
     865 * Results:
     866 *      TRUE if work was done. FALSE otherwise.
     867 *
     868 * Side Effects:
     869 *      The make field of all nodes involved in the creation of the given
     870 *      targets is set to 1. The toBeMade list is set to contain all the
     871 *      'leaves' of these subgraphs.
    871872 *-----------------------------------------------------------------------
    872873 */
    873874Boolean
    874875Make_Run (targs)
    875     Lst             targs;      /* the initial list of targets */
    876 {
    877     register GNode  *gn;        /* a temporary pointer */
    878     register Lst    examine;    /* List of targets to examine */
    879     int             errors;     /* Number of errors the Job module reports */
     876    Lst             targs;      /* the initial list of targets */
     877{
     878    register GNode  *gn;        /* a temporary pointer */
     879    register Lst    examine;    /* List of targets to examine */
     880    int             errors;     /* Number of errors the Job module reports */
    880881
    881882    toBeMade = Lst_Init (FALSE);
     
    893894     */
    894895    while (!Lst_IsEmpty (examine)) {
    895         gn = (GNode *) Lst_DeQueue (examine);
    896 
    897         if (!gn->make) {
    898             gn->make = TRUE;
    899             numNodes++;
    900 
    901             /*
    902              * Apply any .USE rules before looking for implicit dependencies
    903              * to make sure everything has commands that should...
    904              */
    905             Lst_ForEach (gn->children, MakeHandleUse, (ClientData)gn);
    906             Suff_FindDeps (gn);
    907 
    908             if (gn->unmade != 0) {
    909                 Lst_ForEach (gn->children, MakeAddChild, (ClientData)examine);
    910             } else {
    911                 (void)Lst_EnQueue (toBeMade, (ClientData)gn);
    912             }
    913         }
     896        gn = (GNode *) Lst_DeQueue (examine);
     897
     898        if (!gn->make) {
     899            gn->make = TRUE;
     900            numNodes++;
     901
     902            /*
     903             * Apply any .USE rules before looking for implicit dependencies
     904             * to make sure everything has commands that should...
     905             */
     906            Lst_ForEach (gn->children, MakeHandleUse, (ClientData)gn);
     907            Suff_FindDeps (gn);
     908
     909            if (gn->unmade != 0) {
     910                Lst_ForEach (gn->children, MakeAddChild, (ClientData)examine);
     911            } else {
     912                (void)Lst_EnQueue (toBeMade, (ClientData)gn);
     913            }
     914        }
    914915    }
    915916
     
    917918
    918919    if (queryFlag) {
    919         /*
    920         * We wouldn't do any work unless we could start some jobs in the
    921         * next loop... (we won't actually start any, of course, this is just
    922         * to see if any of the targets was out of date)
    923         */
    924         return (MakeStartJobs());
     920        /*
     921        * We wouldn't do any work unless we could start some jobs in the
     922        * next loop... (we won't actually start any, of course, this is just
     923        * to see if any of the targets was out of date)
     924        */
     925        return (MakeStartJobs());
    925926    } else {
    926         /*
    927         * Initialization. At the moment, no jobs are running and until some
    928         * get started, nothing will happen since the remaining upward
    929         * traversal of the graph is performed by the routines in job.c upon
    930         * the finishing of a job. So we fill the Job table as much as we can
    931         * before going into our loop.
    932         */
    933         (void) MakeStartJobs();
     927        /*
     928        * Initialization. At the moment, no jobs are running and until some
     929        * get started, nothing will happen since the remaining upward
     930        * traversal of the graph is performed by the routines in job.c upon
     931        * the finishing of a job. So we fill the Job table as much as we can
     932        * before going into our loop.
     933        */
     934        (void) MakeStartJobs();
    934935    }
    935936
     
    945946     */
    946947    while (!Job_Empty ()) {
    947         Job_CatchOutput ();
    948         Job_CatchChildren (!usePipes);
    949         (void)MakeStartJobs();
     948        Job_CatchOutput ();
     949        Job_CatchChildren (!usePipes);
     950        (void)MakeStartJobs();
    950951    }
    951952
  • trunk/src/kmk/make.h

    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
     
    3636 * SUCH DAMAGE.
    3737 *
    38  *      from: @(#)make.h        8.3 (Berkeley) 6/13/95
     38 *      from: @(#)make.h        8.3 (Berkeley) 6/13/95
    3939 * $FreeBSD: src/usr.bin/make/make.h,v 1.12.2.2 2001/02/13 03:13:58 will Exp $
    4040 */
     
    4242/*-
    4343 * make.h --
    44  *      The global definitions for pmake
     44 *      The global definitions for pmake
    4545 */
    4646
     
    6060/*kso: #  if defined(__STDC__) || defined(__cplusplus) */
    6161#  if defined(__STDC__) || defined(__cplusplus) || defined(__IBMC__)
    62 #   define      __P(protos)     protos          /* full-blown ANSI C */
     62#   define      __P(protos)     protos          /* full-blown ANSI C */
    6363#  else
    64 #   define      __P(protos)     ()              /* traditional C preprocessor */
     64#   define      __P(protos)     ()              /* traditional C preprocessor */
    6565#  endif
    6666# endif
     
    7676#endif
    7777
    78 #if defined(__IBMC__)
    79 #include <stdlib.h>
    80 #include <time.h>
    81 /*#ifdef __STDC__*/
    82 #elif defined(__STDC__)
     78#if defined(__STDC__) || defined(__IBMC__)
    8379#include <stdlib.h>
    8480#include <unistd.h>
     
    9389 * The structure for an individual graph node. Each node has several
    9490 * pieces of data associated with it.
    95  *      1) the name of the target it describes
    96  *      2) the location of the target file in the file system.
    97  *      3) the type of operator used to define its sources (qv. parse.c)
    98  *      4) whether it is involved in this invocation of make
    99  *      5) whether the target has been remade
    100  *      6) whether any of its children has been remade
    101  *      7) the number of its children that are, as yet, unmade
    102  *      8) its modification time
    103  *      9) the modification time of its youngest child (qv. make.c)
    104  *      10) a list of nodes for which this is a source
    105  *      11) a list of nodes on which this depends
    106  *      12) a list of nodes that depend on this, as gleaned from the
    107  *          transformation rules.
    108  *      13) a list of nodes of the same name created by the :: operator
    109  *      14) a list of nodes that must be made (if they're made) before
    110  *          this node can be, but that do no enter into the datedness of
    111  *          this node.
    112  *      15) a list of nodes that must be made (if they're made) after
    113  *          this node is, but that do not depend on this node, in the
    114  *          normal sense.
    115  *      16) a Lst of ``local'' variables that are specific to this target
    116  *         and this target only (qv. var.c [$@ $< $?, etc.])
    117  *      17) a Lst of strings that are commands to be given to a shell
    118  *         to create this target.
     91 *      1) the name of the target it describes
     92 *      2) the location of the target file in the file system.
     93 *      3) the type of operator used to define its sources (qv. parse.c)
     94 *      4) whether it is involved in this invocation of make
     95 *      5) whether the target has been remade
     96 *      6) whether any of its children has been remade
     97 *      7) the number of its children that are, as yet, unmade
     98 *      8) its modification time
     99 *      9) the modification time of its youngest child (qv. make.c)
     100 *      10) a list of nodes for which this is a source
     101 *      11) a list of nodes on which this depends
     102 *      12) a list of nodes that depend on this, as gleaned from the
     103 *          transformation rules.
     104 *      13) a list of nodes of the same name created by the :: operator
     105 *      14) a list of nodes that must be made (if they're made) before
     106 *          this node can be, but that do no enter into the datedness of
     107 *          this node.
     108 *      15) a list of nodes that must be made (if they're made) after
     109 *          this node is, but that do not depend on this node, in the
     110 *          normal sense.
     111 *      16) a Lst of ``local'' variables that are specific to this target
     112 *         and this target only (qv. var.c [$@ $< $?, etc.])
     113 *      17) a Lst of strings that are commands to be given to a shell
     114 *         to create this target.
    119115 */
    120116typedef struct GNode {
    121     char            *name;      /* The target's name */
    122     char            *path;      /* The full pathname of the file */
    123     int             type;       /* Its type (see the OP flags, below) */
    124     int             order;      /* Its wait weight */
    125 
    126     Boolean         make;       /* TRUE if this target needs to be remade */
     117    char            *name;      /* The target's name */
     118    char            *path;      /* The full pathname of the file */
     119    int             type;       /* Its type (see the OP flags, below) */
     120    int             order;      /* Its wait weight */
     121
     122    Boolean         make;       /* TRUE if this target needs to be remade */
    127123    enum {
    128         UNMADE, BEINGMADE, MADE, UPTODATE, ERROR, ABORTED,
    129         CYCLE, ENDCYCLE
    130     }               made;       /* Set to reflect the state of processing
    131                                 * on this node:
    132                                 *  UNMADE - Not examined yet
    133                                 *  BEINGMADE - Target is already being made.
    134                                  *      Indicates a cycle in the graph. (compat
    135                                  *      mode only)
    136                                 *  MADE - Was out-of-date and has been made
    137                                 *  UPTODATE - Was already up-to-date
    138                                 *  ERROR - An error occured while it was being
    139                                  *      made (used only in compat mode)
    140                                 *  ABORTED - The target was aborted due to
    141                                  *      an error making an inferior (compat).
    142                                 *  CYCLE - Marked as potentially being part of
    143                                  *      a graph cycle. If we come back to a
    144                                  *      node marked this way, it is printed
    145                                  *      and 'made' is changed to ENDCYCLE.
    146                                 *  ENDCYCLE - the cycle has been completely
    147                                  *      printed. Go back and unmark all its
    148                                  *      members.
    149                                 */
    150     Boolean         childMade;  /* TRUE if one of this target's children was
    151                                 * made */
    152     int             unmade;     /* The number of unmade children */
    153 
    154     int             mtime;      /* Its modification time */
    155     int             cmtime;     /* The modification time of its youngest
    156                                 * child */
    157 
    158     Lst             iParents;   /* Links to parents for which this is an
    159                                 * implied source, if any */
    160     Lst             cohorts;    /* Other nodes for the :: operator */
    161     Lst             parents;    /* Nodes that depend on this one */
    162     Lst             children;   /* Nodes on which this one depends */
    163     Lst             successors; /* Nodes that must be made after this one */
    164     Lst             preds;      /* Nodes that must be made before this one */
    165 
    166     Lst             context;    /* The local variables */
    167     Lst             commands;   /* Creation commands */
    168 
    169     struct _Suff    *suffix;    /* Suffix for the node (determined by
    170                                 * Suff_FindDeps and opaque to everyone
    171                                 * but the Suff module) */
     124        UNMADE, BEINGMADE, MADE, UPTODATE, ERROR, ABORTED,
     125        CYCLE, ENDCYCLE
     126    }               made;       /* Set to reflect the state of processing
     127                                * on this node:
     128                                *  UNMADE - Not examined yet
     129                                *  BEINGMADE - Target is already being made.
     130                                 *      Indicates a cycle in the graph. (compat
     131                                 *      mode only)
     132                                *  MADE - Was out-of-date and has been made
     133                                *  UPTODATE - Was already up-to-date
     134                                *  ERROR - An error occured while it was being
     135                                 *      made (used only in compat mode)
     136                                *  ABORTED - The target was aborted due to
     137                                 *      an error making an inferior (compat).
     138                                *  CYCLE - Marked as potentially being part of
     139                                 *      a graph cycle. If we come back to a
     140                                 *      node marked this way, it is printed
     141                                 *      and 'made' is changed to ENDCYCLE.
     142                                *  ENDCYCLE - the cycle has been completely
     143                                 *      printed. Go back and unmark all its
     144                                 *      members.
     145                                */
     146    Boolean         childMade;  /* TRUE if one of this target's children was
     147                                * made */
     148    int             unmade;     /* The number of unmade children */
     149
     150    int             mtime;      /* Its modification time */
     151    int             cmtime;     /* The modification time of its youngest
     152                                * child */
     153
     154    Lst             iParents;   /* Links to parents for which this is an
     155                                * implied source, if any */
     156    Lst             cohorts;    /* Other nodes for the :: operator */
     157    Lst             parents;    /* Nodes that depend on this one */
     158    Lst             children;   /* Nodes on which this one depends */
     159    Lst             successors; /* Nodes that must be made after this one */
     160    Lst             preds;      /* Nodes that must be made before this one */
     161
     162    Lst             context;    /* The local variables */
     163    Lst             commands;   /* Creation commands */
     164
     165    struct _Suff    *suffix;    /* Suffix for the node (determined by
     166                                * Suff_FindDeps and opaque to everyone
     167                                * but the Suff module) */
    172168} GNode;
    173169
     
    175171 * Manifest constants
    176172 */
    177 #define NILGNODE        ((GNode *) NIL)
     173#define NILGNODE        ((GNode *) NIL)
    178174
    179175/*
     
    186182 * righthand side...
    187183 */
    188 #define OP_DEPENDS      0x00000001  /* Execution of commands depends on
    189                                      * kids (:) */
    190 #define OP_FORCE        0x00000002  /* Always execute commands (!) */
    191 #define OP_DOUBLEDEP    0x00000004  /* Execution of commands depends on kids
    192                                      * per line (::) */
    193 #define OP_OPMASK       (OP_DEPENDS|OP_FORCE|OP_DOUBLEDEP)
    194 
    195 #define OP_OPTIONAL     0x00000008  /* Don't care if the target doesn't
    196                                      * exist and can't be created */
    197 #define OP_USE          0x00000010  /* Use associated commands for parents */
    198 #define OP_EXEC         0x00000020  /* Target is never out of date, but always
    199                                      * execute commands anyway. Its time
    200                                      * doesn't matter, so it has none...sort
    201                                      * of */
    202 #define OP_IGNORE       0x00000040  /* Ignore errors when creating the node */
    203 #define OP_PRECIOUS     0x00000080  /* Don't remove the target when
    204                                      * interrupted */
    205 #define OP_SILENT       0x00000100  /* Don't echo commands when executed */
    206 #define OP_MAKE         0x00000200  /* Target is a recurrsive make so its
    207                                      * commands should always be executed when
    208                                      * it is out of date, regardless of the
    209                                      * state of the -n or -t flags */
    210 #define OP_JOIN         0x00000400  /* Target is out-of-date only if any of its
    211                                      * children was out-of-date */
    212 #define OP_INVISIBLE    0x00004000  /* The node is invisible to its parents.
    213                                      * I.e. it doesn't show up in the parents's
    214                                      * local variables. */
    215 #define OP_NOTMAIN      0x00008000  /* The node is exempt from normal 'main
    216                                      * target' processing in parse.c */
    217 #define OP_PHONY        0x00010000  /* Not a file target; run always */
     184#define OP_DEPENDS      0x00000001  /* Execution of commands depends on
     185                                     * kids (:) */
     186#define OP_FORCE        0x00000002  /* Always execute commands (!) */
     187#define OP_DOUBLEDEP    0x00000004  /* Execution of commands depends on kids
     188                                     * per line (::) */
     189#define OP_OPMASK       (OP_DEPENDS|OP_FORCE|OP_DOUBLEDEP)
     190
     191#define OP_OPTIONAL     0x00000008  /* Don't care if the target doesn't
     192                                     * exist and can't be created */
     193#define OP_USE          0x00000010  /* Use associated commands for parents */
     194#define OP_EXEC         0x00000020  /* Target is never out of date, but always
     195                                     * execute commands anyway. Its time
     196                                     * doesn't matter, so it has none...sort
     197                                     * of */
     198#define OP_IGNORE       0x00000040  /* Ignore errors when creating the node */
     199#define OP_PRECIOUS     0x00000080  /* Don't remove the target when
     200                                     * interrupted */
     201#define OP_SILENT       0x00000100  /* Don't echo commands when executed */
     202#define OP_MAKE         0x00000200  /* Target is a recurrsive make so its
     203                                     * commands should always be executed when
     204                                     * it is out of date, regardless of the
     205                                     * state of the -n or -t flags */
     206#define OP_JOIN         0x00000400  /* Target is out-of-date only if any of its
     207                                     * children was out-of-date */
     208#define OP_INVISIBLE    0x00004000  /* The node is invisible to its parents.
     209                                     * I.e. it doesn't show up in the parents's
     210                                     * local variables. */
     211#define OP_NOTMAIN      0x00008000  /* The node is exempt from normal 'main
     212                                     * target' processing in parse.c */
     213#define OP_PHONY        0x00010000  /* Not a file target; run always */
    218214/* Attributes applied by PMake */
    219 #define OP_TRANSFORM    0x80000000  /* The node is a transformation rule */
     215#define OP_TRANSFORM    0x80000000  /* The node is a transformation rule */
    220216#ifdef USE_ARCHIVES
    221 #define OP_MEMBER       0x40000000  /* Target is a member of an archive */
    222 #define OP_LIB          0x20000000  /* Target is a library */
    223 #define OP_ARCHV        0x10000000  /* Target is an archive construct */
    224 #endif
    225 #define OP_HAS_COMMANDS 0x08000000  /* Target has all the commands it should.
    226                                      * Used when parsing to catch multiple
    227                                      * commands for a target */
    228 #define OP_SAVE_CMDS    0x04000000  /* Saving commands on .END (Compat) */
    229 #define OP_DEPS_FOUND   0x02000000  /* Already processed by Suff_FindDeps */
     217#define OP_MEMBER       0x40000000  /* Target is a member of an archive */
     218#define OP_LIB          0x20000000  /* Target is a library */
     219#define OP_ARCHV        0x10000000  /* Target is an archive construct */
     220#endif
     221#define OP_HAS_COMMANDS 0x08000000  /* Target has all the commands it should.
     222                                     * Used when parsing to catch multiple
     223                                     * commands for a target */
     224#define OP_SAVE_CMDS    0x04000000  /* Saving commands on .END (Compat) */
     225#define OP_DEPS_FOUND   0x02000000  /* Already processed by Suff_FindDeps */
    230226
    231227/*
     
    233229 * object of a dependency operator
    234230 */
    235 #define OP_NOP(t)       (((t) & OP_OPMASK) == 0x00000000)
     231#define OP_NOP(t)       (((t) & OP_OPMASK) == 0x00000000)
    236232
    237233/*
     
    243239 * a NIL pointer will be returned.
    244240 */
    245 #define TARG_CREATE     0x01      /* create node if not found */
    246 #define TARG_NOCREATE   0x00      /* don't create it */
     241#define TARG_CREATE     0x01      /* create node if not found */
     242#define TARG_NOCREATE   0x00      /* don't create it */
    247243
    248244/*
     
    255251 * schemes allocate in powers of two.
    256252 */
    257 #define MAKE_BSIZE              256     /* starting size for expandable buffers */
     253#define MAKE_BSIZE              256     /* starting size for expandable buffers */
    258254
    259255/*
     
    266262 * Str_Concat returns.
    267263 */
    268 #define STR_ADDSPACE    0x01    /* add a space when Str_Concat'ing */
    269 #define STR_DOFREE      0x02    /* free source strings after concatenation */
    270 #define STR_ADDSLASH    0x04    /* add a slash when Str_Concat'ing */
     264#define STR_ADDSPACE    0x01    /* add a space when Str_Concat'ing */
     265#define STR_DOFREE      0x02    /* free source strings after concatenation */
     266#define STR_ADDSLASH    0x04    /* add a slash when Str_Concat'ing */
    271267
    272268/*
     
    275271 * as the first argument to Parse_Error.
    276272 */
    277 #define PARSE_WARNING   2
    278 #define PARSE_FATAL     1
     273#define PARSE_WARNING   2
     274#define PARSE_FATAL     1
    279275
    280276/*
    281277 * Values returned by Cond_Eval.
    282278 */
    283 #define COND_PARSE      0       /* Parse the next lines */
    284 #define COND_SKIP       1       /* Skip the next lines */
    285 #define COND_INVALID    2       /* Not a conditional statement */
     279#define COND_PARSE      0       /* Parse the next lines */
     280#define COND_SKIP       1       /* Skip the next lines */
     281#define COND_INVALID    2       /* Not a conditional statement */
    286282
    287283/*
    288284 * Definitions for the "local" variables. Used only for clarity.
    289285 */
    290 #define TARGET            "@"   /* Target of dependency */
    291 #define OODATE            "?"   /* All out-of-date sources */
    292 #define ALLSRC            ">"   /* All sources */
    293 #define IMPSRC            "<"   /* Source implied by transformation */
    294 #define PREFIX            "*"   /* Common prefix */
     286#define TARGET            "@"   /* Target of dependency */
     287#define OODATE            "?"   /* All out-of-date sources */
     288#define ALLSRC            ">"   /* All sources */
     289#define IMPSRC            "<"   /* Source implied by transformation */
     290#define PREFIX            "*"   /* Common prefix */
    295291#ifdef KMK
    296292#define PARENTS           "^"   /* Parent of this target (if any) (long name .PARENTS) */
    297293#endif
    298294#ifdef USE_ARCHIVES
    299 #define ARCHIVE           "!"   /* Archive in "archive(member)" syntax */
    300 #define MEMBER            "%"   /* Member in "archive(member)" syntax */
     295#define ARCHIVE           "!"   /* Archive in "archive(member)" syntax */
     296#define MEMBER            "%"   /* Member in "archive(member)" syntax */
    301297#endif
    302298
     
    311307 * Global Variables
    312308 */
    313 extern Lst      create;         /* The list of target names specified on the
    314                                 * command line. used to resolve #if
    315                                 * make(...) statements */
    316 extern Lst      dirSearchPath;  /* The list of directories to search when
    317                                 * looking for targets */
    318 
    319 extern Boolean  compatMake;     /* True if we are make compatible */
    320 extern Boolean  ignoreErrors;   /* True if should ignore all errors */
    321 extern Boolean  beSilent;       /* True if should print no commands */
    322 extern Boolean  beVerbose;      /* True if should print extra cruft */
    323 extern Boolean  noExecute;      /* True if should execute nothing */
    324 extern Boolean  allPrecious;    /* True if every target is precious */
    325 extern Boolean  keepgoing;      /* True if should continue on unaffected
    326                                 * portions of the graph when have an error
    327                                 * in one portion */
    328 extern Boolean  touchFlag;      /* TRUE if targets should just be 'touched'
    329                                 * if out of date. Set by the -t flag */
    330 extern Boolean  usePipes;       /* TRUE if should capture the output of
    331                                 * subshells by means of pipes. Otherwise it
    332                                 * is routed to temporary files from which it
    333                                 * is retrieved when the shell exits */
    334 extern Boolean  queryFlag;      /* TRUE if we aren't supposed to really make
    335                                 * anything, just see if the targets are out-
    336                                 * of-date */
    337 
    338 extern Boolean  checkEnvFirst;  /* TRUE if environment should be searched for
    339                                 * all variables before the global context */
    340 extern Lst      envFirstVars;   /* List of specific variables for which the
    341                                 * environment should be searched before the
    342                                 * global context */
    343 
    344 extern GNode    *DEFAULT;       /* .DEFAULT rule */
    345 
    346 extern GNode    *VAR_GLOBAL;    /* Variables defined in a global context, e.g
    347                                 * in the Makefile itself */
    348 extern GNode    *VAR_CMD;       /* Variables defined on the command line */
    349 extern char     var_Error[];    /* Value returned by Var_Parse when an error
    350                                 * is encountered. It actually points to
    351                                 * an empty string, so naive callers needn't
    352                                 * worry about it. */
    353 
    354 extern time_t   now;            /* The time at the start of this whole
    355                                 * process */
    356 
    357 extern Boolean  oldVars;        /* Do old-style variable substitution */
    358 
    359 extern Lst      sysIncPath;     /* The system include path. */
     309extern Lst      create;         /* The list of target names specified on the
     310                                * command line. used to resolve #if
     311                                * make(...) statements */
     312extern Lst      dirSearchPath;  /* The list of directories to search when
     313                                * looking for targets */
     314
     315extern Boolean  compatMake;     /* True if we are make compatible */
     316extern Boolean  ignoreErrors;   /* True if should ignore all errors */
     317extern Boolean  beSilent;       /* True if should print no commands */
     318extern Boolean  beVerbose;      /* True if should print extra cruft */
     319extern Boolean  noExecute;      /* True if should execute nothing */
     320extern Boolean  allPrecious;    /* True if every target is precious */
     321extern Boolean  keepgoing;      /* True if should continue on unaffected
     322                                * portions of the graph when have an error
     323                                * in one portion */
     324extern Boolean  touchFlag;      /* TRUE if targets should just be 'touched'
     325                                * if out of date. Set by the -t flag */
     326extern Boolean  usePipes;       /* TRUE if should capture the output of
     327                                * subshells by means of pipes. Otherwise it
     328                                * is routed to temporary files from which it
     329                                * is retrieved when the shell exits */
     330extern Boolean  queryFlag;      /* TRUE if we aren't supposed to really make
     331                                * anything, just see if the targets are out-
     332                                * of-date */
     333
     334extern Boolean  checkEnvFirst;  /* TRUE if environment should be searched for
     335                                * all variables before the global context */
     336extern Lst      envFirstVars;   /* List of specific variables for which the
     337                                * environment should be searched before the
     338                                * global context */
     339
     340extern GNode    *DEFAULT;       /* .DEFAULT rule */
     341
     342extern GNode    *VAR_GLOBAL;    /* Variables defined in a global context, e.g
     343                                * in the Makefile itself */
     344extern GNode    *VAR_CMD;       /* Variables defined on the command line */
     345extern char     var_Error[];    /* Value returned by Var_Parse when an error
     346                                * is encountered. It actually points to
     347                                * an empty string, so naive callers needn't
     348                                * worry about it. */
     349
     350extern time_t   now;            /* The time at the start of this whole
     351                                * process */
     352
     353extern Boolean  oldVars;        /* Do old-style variable substitution */
     354
     355extern Lst      sysIncPath;     /* The system include path. */
    360356
    361357/*
    362358 * debug control:
    363  *      There is one bit per module.  It is up to the module what debug
    364  *      information to print.
     359 *      There is one bit per module.  It is up to the module what debug
     360 *      information to print.
    365361 */
    366362extern int debug;
    367363#ifdef USE_ARCHIVES
    368 #define DEBUG_ARCH      0x0001
    369 #endif
    370 #define DEBUG_COND      0x0002
    371 #define DEBUG_DIR       0x0004
    372 #define DEBUG_GRAPH1    0x0008
    373 #define DEBUG_GRAPH2    0x0010
    374 #define DEBUG_JOB       0x0020
    375 #define DEBUG_MAKE      0x0040
    376 #define DEBUG_SUFF      0x0080
    377 #define DEBUG_TARG      0x0100
    378 #define DEBUG_VAR       0x0200
    379 #define DEBUG_FOR       0x0400
    380 #define DEBUG_LOUD      0x0800
     364#define DEBUG_ARCH      0x0001
     365#endif
     366#define DEBUG_COND      0x0002
     367#define DEBUG_DIR       0x0004
     368#define DEBUG_GRAPH1    0x0008
     369#define DEBUG_GRAPH2    0x0010
     370#define DEBUG_JOB       0x0020
     371#define DEBUG_MAKE      0x0040
     372#define DEBUG_SUFF      0x0080
     373#define DEBUG_TARG      0x0100
     374#define DEBUG_VAR       0x0200
     375#define DEBUG_FOR       0x0400
     376#define DEBUG_LOUD      0x0800
    381377#define DEBUG_PARSE     0x8000 /*kso*/
    382378
    383379/*#ifdef __STDC__*/
    384380#if defined(__STDC__) || defined(__IBMC__)
    385 #define CONCAT(a,b)     a##b
     381#define CONCAT(a,b)     a##b
    386382#else
    387 #define I(a)            a
    388 #define CONCAT(a,b)     I(a)b
     383#define I(a)            a
     384#define CONCAT(a,b)     I(a)b
    389385#endif /* __STDC__ */
    390386
    391387
    392388
    393 #define DEBUG(module)   (debug & CONCAT(DEBUG_,module))
     389#define DEBUG(module)   (debug & CONCAT(DEBUG_,module))
    394390#define ISDOT(c) ((c)[0] == '.' && (((c)[1] == '\0') || ((c)[1] == '/')))
    395391#define ISDOTDOT(c) ((c)[0] == '.' && ISDOT(&((c)[1])))
  • trunk/src/kmk/nonints.h

    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
     
    3636 * SUCH DAMAGE.
    3737 *
    38  *      from: @(#)nonints.h     8.3 (Berkeley) 3/19/94
     38 *      from: @(#)nonints.h     8.3 (Berkeley) 3/19/94
    3939 * $FreeBSD: src/usr.bin/make/nonints.h,v 1.8 1999/08/28 01:03:35 peter Exp $
    4040 */
     41
     42#ifndef __nonints_h__
     43#define __nonints_h__
    4144
    4245/* arch.c */
     
    149152void Var_End __P((void));
    150153void Var_Dump __P((GNode *));
     154
     155#endif
  • 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}
  • trunk/src/kmk/str.c

    r35 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[] = "@(#)str.c       5.8 (Berkeley) 6/1/90";
     41static char sccsid[] = "@(#)str.c       5.8 (Berkeley) 6/1/90";
    4242#else
    4343static const char rcsid[] =
    4444  "$FreeBSD: src/usr.bin/make/str.c,v 1.12.2.1 2002/06/17 04:30:48 jmallett Exp $";
    4545#endif
     46#define KLIBFILEDEF rcsid
    4647#endif /* not lint */
    4748
     
    5354/*
    5455 * str_init --
    55  *      Initialize the strings package
     56 *      Initialize the strings package
    5657 *
    5758 */
     
    6768/*
    6869 * str_end --
    69  *      Cleanup the strings package
     70 *      Cleanup the strings package
    7071 *
    7172 */
     
    7475{
    7576    if (argv) {
    76         if (argv[0])
    77             efree(argv[0]);
    78         efree((Address) argv);
     77        if (argv[0])
     78            efree(argv[0]);
     79        efree((Address) argv);
    7980    }
    8081    if (buffer)
    81         efree(buffer);
     82        efree(buffer);
    8283}
    8384
    8485/*-
    8586 * str_concat --
    86  *      concatenate the two strings, inserting a space or slash between them,
    87  *      freeing them if requested.
     87 *      concatenate the two strings, inserting a space or slash between them,
     88 *      freeing them if requested.
    8889 *
    8990 * returns --
    90  *      the resulting string in allocated space.
     91 *      the resulting string in allocated space.
    9192 */
    9293char *
    9394str_concat(s1, s2, flags)
    94         char *s1, *s2;
    95         int flags;
    96 {
    97         register int len1, len2;
    98         register char *result;
    99 
    100         /* get the length of both strings */
    101         len1 = strlen(s1);
    102         len2 = strlen(s2);
    103 
    104         /* allocate length plus separator plus EOS */
    105         result = emalloc((u_int)(len1 + len2 + 2));
    106 
    107         /* copy first string into place */
    108         memcpy(result, s1, len1);
    109 
    110         /* add separator character */
    111         if (flags & STR_ADDSPACE) {
    112                 result[len1] = ' ';
    113                 ++len1;
    114         } else if (flags & STR_ADDSLASH) {
    115                 result[len1] = '/';
    116                 ++len1;
    117         }
    118 
    119         /* copy second string plus EOS into place */
    120         memcpy(result + len1, s2, len2 + 1);
    121 
    122         /* efree original strings */
    123         if (flags & STR_DOFREE) {
    124                 (void)efree(s1);
    125                 (void)efree(s2);
    126         }
    127         return(result);
     95        char *s1, *s2;
     96        int flags;
     97{
     98        register int len1, len2;
     99        register char *result;
     100
     101        /* get the length of both strings */
     102        len1 = strlen(s1);
     103        len2 = strlen(s2);
     104
     105        /* allocate length plus separator plus EOS */
     106        result = emalloc((u_int)(len1 + len2 + 2));
     107
     108        /* copy first string into place */
     109        memcpy(result, s1, len1);
     110
     111        /* add separator character */
     112        if (flags & STR_ADDSPACE) {
     113                result[len1] = ' ';
     114                ++len1;
     115        } else if (flags & STR_ADDSLASH) {
     116                result[len1] = '/';
     117                ++len1;
     118        }
     119
     120        /* copy second string plus EOS into place */
     121        memcpy(result + len1, s2, len2 + 1);
     122
     123        /* efree original strings */
     124        if (flags & STR_DOFREE) {
     125                (void)efree(s1);
     126                (void)efree(s2);
     127        }
     128        return(result);
    128129}
    129130
    130131/*-
    131132 * brk_string --
    132  *      Fracture a string into an array of words (as delineated by tabs or
    133  *      spaces) taking quotation marks into account.  Leading tabs/spaces
    134  *      are ignored.
     133 *      Fracture a string into an array of words (as delineated by tabs or
     134 *      spaces) taking quotation marks into account.  Leading tabs/spaces
     135 *      are ignored.
    135136 *
    136137 * returns --
    137  *      Pointer to the array of pointers to the words.  To make life easier,
    138  *      the first word is always the value of the .MAKE variable.
     138 *      Pointer to the array of pointers to the words.  To make life easier,
     139 *      the first word is always the value of the .MAKE variable.
    139140 */
    140141char **
    141142brk_string(str, store_argc, expand)
    142         register char *str;
    143         int *store_argc;
    144         Boolean expand;
    145 {
    146         register int argc, ch;
    147         register char inquote, *p, *start, *t;
    148         int len;
    149 
    150         /* skip leading space chars. */
    151         for (; *str == ' ' || *str == '\t'; ++str)
    152                 continue;
    153 
    154         /* allocate room for a copy of the string */
    155         if ((len = strlen(str) + 1) > curlen) {
    156                 if (buffer)
    157                     efree(buffer);
    158                 buffer = emalloc(curlen = len);
    159         }
    160 
    161         /*
    162         * copy the string; at the same time, parse backslashes,
    163         * quotes and build the argument list.
    164         */
    165         argc = 1;
    166         inquote = '\0';
    167         for (p = str, start = t = buffer;; ++p) {
    168                 switch(ch = *p) {
    169                 case '"':
    170                 case '\'':
    171                         if (inquote) {
    172                                 if (inquote == ch)
    173                                         inquote = '\0';
    174                                 else
    175                                         break;
    176                         } else {
    177                                 inquote = (char) ch;
    178                                 /* Don't miss "" or '' */
    179                                 if (start == NULL && p[1] == inquote) {
    180                                         start = t + 1;
    181                                         break;
    182                                 }
    183                         }
    184                         if (!expand) {
    185                                 if (!start)
    186                                         start = t;
    187                                 *t++ = ch;
    188                         }
    189                         continue;
    190                 case ' ':
    191                 case '\t':
    192                 case '\n':
    193                         if (inquote)
    194                                 break;
    195                         if (!start)
    196                                 continue;
    197                         /* FALLTHROUGH */
    198                 case '\0':
    199                         /*
    200                         * end of a token -- make sure there's enough argv
    201                         * space and save off a pointer.
    202                         */
    203                         if (!start)
    204                             goto done;
    205 
    206                         *t++ = '\0';
    207                         if (argc == argmax) {
    208                                 argmax *= 2;            /* ramp up fast */
    209                                 argv = (char **)erealloc(argv,
    210                                     (argmax + 1) * sizeof(char *));
    211                         }
    212                         argv[argc++] = start;
    213                         start = (char *)NULL;
    214                         if (ch == '\n' || ch == '\0')
    215                                 goto done;
    216                         continue;
    217                 case '\\':
    218                         if (!expand) {
    219                                 if (!start)
    220                                         start = t;
    221                                 *t++ = '\\';
    222                                 ch = *++p;
    223                                 break;
    224                         }
    225 
    226                         switch (ch = *++p) {
    227                         case '\0':
    228                         case '\n':
    229                                 /* hmmm; fix it up as best we can */
    230                                 ch = '\\';
    231                                 --p;
    232                                 break;
    233                         case 'b':
    234                                 ch = '\b';
    235                                 break;
    236                         case 'f':
    237                                 ch = '\f';
    238                                 break;
    239                         case 'n':
    240                                 ch = '\n';
    241                                 break;
    242                         case 'r':
    243                                 ch = '\r';
    244                                 break;
    245                         case 't':
    246                                 ch = '\t';
    247                                 break;
    248                         }
    249                         break;
    250                 }
    251                 if (!start)
    252                         start = t;
    253                 *t++ = (char) ch;
    254         }
    255 done:   argv[argc] = (char *)NULL;
    256         *store_argc = argc;
    257         return(argv);
     143        register char *str;
     144        int *store_argc;
     145        Boolean expand;
     146{
     147        register int argc, ch;
     148        register char inquote, *p, *start, *t;
     149        int len;
     150
     151        /* skip leading space chars. */
     152        for (; *str == ' ' || *str == '\t'; ++str)
     153                continue;
     154
     155        /* allocate room for a copy of the string */
     156        if ((len = strlen(str) + 1) > curlen) {
     157                if (buffer)
     158                    efree(buffer);
     159                buffer = emalloc(curlen = len);
     160        }
     161
     162        /*
     163        * copy the string; at the same time, parse backslashes,
     164        * quotes and build the argument list.
     165        */
     166        argc = 1;
     167        inquote = '\0';
     168        for (p = str, start = t = buffer;; ++p) {
     169                switch(ch = *p) {
     170                case '"':
     171                case '\'':
     172                        if (inquote) {
     173                                if (inquote == ch)
     174                                        inquote = '\0';
     175                                else
     176                                        break;
     177                        } else {
     178                                inquote = (char) ch;
     179                                /* Don't miss "" or '' */
     180                                if (start == NULL && p[1] == inquote) {
     181                                        start = t + 1;
     182                                        break;
     183                                }
     184                        }
     185                        if (!expand) {
     186                                if (!start)
     187                                        start = t;
     188                                *t++ = ch;
     189                        }
     190                        continue;
     191                case ' ':
     192                case '\t':
     193                case '\n':
     194                        if (inquote)
     195                                break;
     196                        if (!start)
     197                                continue;
     198                        /* FALLTHROUGH */
     199                case '\0':
     200                        /*
     201                        * end of a token -- make sure there's enough argv
     202                        * space and save off a pointer.
     203                        */
     204                        if (!start)
     205                            goto done;
     206
     207                        *t++ = '\0';
     208                        if (argc == argmax) {
     209                                argmax *= 2;            /* ramp up fast */
     210                                argv = (char **)erealloc(argv,
     211                                    (argmax + 1) * sizeof(char *));
     212                        }
     213                        argv[argc++] = start;
     214                        start = (char *)NULL;
     215                        if (ch == '\n' || ch == '\0')
     216                                goto done;
     217                        continue;
     218                case '\\':
     219                        if (!expand) {
     220                                if (!start)
     221                                        start = t;
     222                                *t++ = '\\';
     223                                ch = *++p;
     224                                break;
     225                        }
     226
     227                        switch (ch = *++p) {
     228                        case '\0':
     229                        case '\n':
     230                                /* hmmm; fix it up as best we can */
     231                                ch = '\\';
     232                                --p;
     233                                break;
     234                        case 'b':
     235                                ch = '\b';
     236                                break;
     237                        case 'f':
     238                                ch = '\f';
     239                                break;
     240                        case 'n':
     241                                ch = '\n';
     242                                break;
     243                        case 'r':
     244                                ch = '\r';
     245                                break;
     246                        case 't':
     247                                ch = '\t';
     248                                break;
     249                        }
     250                        break;
     251                }
     252                if (!start)
     253                        start = t;
     254                *t++ = (char) ch;
     255        }
     256done:   argv[argc] = (char *)NULL;
     257        *store_argc = argc;
     258        return(argv);
    258259}
    259260
     
    270271char *
    271272Str_FindSubstring(string, substring)
    272         register char *string;          /* String to search. */
    273         char *substring;                /* Substring to find in string */
    274 {
    275         register char *a, *b;
    276 
    277         /*
    278         * First scan quickly through the two strings looking for a single-
    279         * character match.  When it's found, then compare the rest of the
    280         * substring.
    281         */
    282 
    283         for (b = substring; *string != 0; string += 1) {
    284                 if (*string != *b)
    285                         continue;
    286                 a = string;
    287                 for (;;) {
    288                         if (*b == 0)
    289                                 return(string);
    290                         if (*a++ != *b++)
    291                                 break;
    292                 }
    293                 b = substring;
    294         }
    295         return((char *) NULL);
     273        register char *string;          /* String to search. */
     274        char *substring;                /* Substring to find in string */
     275{
     276        register char *a, *b;
     277
     278        /*
     279        * First scan quickly through the two strings looking for a single-
     280        * character match.  When it's found, then compare the rest of the
     281        * substring.
     282        */
     283
     284        for (b = substring; *string != 0; string += 1) {
     285                if (*string != *b)
     286                        continue;
     287                a = string;
     288                for (;;) {
     289                        if (*b == 0)
     290                                return(string);
     291                        if (*a++ != *b++)
     292                                break;
     293                }
     294                b = substring;
     295        }
     296        return((char *) NULL);
    296297}
    297298
     
    309310int
    310311Str_Match(string, pattern)
    311         register char *string;          /* String */
    312         register char *pattern;         /* Pattern */
    313 {
    314         char c2;
    315 
    316         for (;;) {
    317                 /*
    318                 * See if we're at the end of both the pattern and the
    319                 * string. If, we succeeded.  If we're at the end of the
    320                 * pattern but not at the end of the string, we failed.
    321                 */
    322                 if (*pattern == 0)
    323                         return(!*string);
    324                 if (*string == 0 && *pattern != '*')
    325                         return(0);
    326                 /*
    327                 * Check for a "*" as the next pattern character.  It matches
    328                 * any substring.  We handle this by calling ourselves
    329                 * recursively for each postfix of string, until either we
    330                 * match or we reach the end of the string.
    331                 */
    332                 if (*pattern == '*') {
    333                         pattern += 1;
    334                         if (*pattern == 0)
    335                                 return(1);
    336                         while (*string != 0) {
    337                                 if (Str_Match(string, pattern))
    338                                         return(1);
    339                                 ++string;
    340                         }
    341                         return(0);
    342                 }
    343                 /*
    344                 * Check for a "?" as the next pattern character.  It matches
    345                 * any single character.
    346                 */
    347                 if (*pattern == '?')
    348                         goto thisCharOK;
    349                 /*
    350                 * Check for a "[" as the next pattern character.  It is
    351                 * followed by a list of characters that are acceptable, or
    352                 * by a range (two characters separated by "-").
    353                 */
    354                 if (*pattern == '[') {
    355                         ++pattern;
    356                         for (;;) {
    357                                 if ((*pattern == ']') || (*pattern == 0))
    358                                         return(0);
    359                                 if (*pattern == *string)
    360                                         break;
    361                                 if (pattern[1] == '-') {
    362                                         c2 = pattern[2];
    363                                         if (c2 == 0)
    364                                                 return(0);
    365                                         if ((*pattern <= *string) &&
    366                                             (c2 >= *string))
    367                                                 break;
    368                                         if ((*pattern >= *string) &&
    369                                             (c2 <= *string))
    370                                                 break;
    371                                         pattern += 2;
    372                                 }
    373                                 ++pattern;
    374                         }
    375                         while ((*pattern != ']') && (*pattern != 0))
    376                                 ++pattern;
    377                         goto thisCharOK;
    378                 }
    379                 /*
    380                 * If the next pattern character is '/', just strip off the
    381                 * '/' so we do exact matching on the character that follows.
    382                 */
    383                 if (*pattern == '\\') {
    384                         ++pattern;
    385                         if (*pattern == 0)
    386                                 return(0);
    387                 }
    388                 /*
    389                 * There's no special character.  Just make sure that the
    390                 * next characters of each string match.
    391                 */
    392                 if (*pattern != *string)
    393                         return(0);
    394 thisCharOK:     ++pattern;
    395                 ++string;
    396         }
     312        register char *string;          /* String */
     313        register char *pattern;         /* Pattern */
     314{
     315        char c2;
     316
     317        for (;;) {
     318                /*
     319                * See if we're at the end of both the pattern and the
     320                * string. If, we succeeded.  If we're at the end of the
     321                * pattern but not at the end of the string, we failed.
     322                */
     323                if (*pattern == 0)
     324                        return(!*string);
     325                if (*string == 0 && *pattern != '*')
     326                        return(0);
     327                /*
     328                * Check for a "*" as the next pattern character.  It matches
     329                * any substring.  We handle this by calling ourselves
     330                * recursively for each postfix of string, until either we
     331                * match or we reach the end of the string.
     332                */
     333                if (*pattern == '*') {
     334                        pattern += 1;
     335                        if (*pattern == 0)
     336                                return(1);
     337                        while (*string != 0) {
     338                                if (Str_Match(string, pattern))
     339                                        return(1);
     340                                ++string;
     341                        }
     342                        return(0);
     343                }
     344                /*
     345                * Check for a "?" as the next pattern character.  It matches
     346                * any single character.
     347                */
     348                if (*pattern == '?')
     349                        goto thisCharOK;
     350                /*
     351                * Check for a "[" as the next pattern character.  It is
     352                * followed by a list of characters that are acceptable, or
     353                * by a range (two characters separated by "-").
     354                */
     355                if (*pattern == '[') {
     356                        ++pattern;
     357                        for (;;) {
     358                                if ((*pattern == ']') || (*pattern == 0))
     359                                        return(0);
     360                                if (*pattern == *string)
     361                                        break;
     362                                if (pattern[1] == '-') {
     363                                        c2 = pattern[2];
     364                                        if (c2 == 0)
     365                                                return(0);
     366                                        if ((*pattern <= *string) &&
     367                                            (c2 >= *string))
     368                                                break;
     369                                        if ((*pattern >= *string) &&
     370                                            (c2 <= *string))
     371                                                break;
     372                                        pattern += 2;
     373                                }
     374                                ++pattern;
     375                        }
     376                        while ((*pattern != ']') && (*pattern != 0))
     377                                ++pattern;
     378                        goto thisCharOK;
     379                }
     380                /*
     381                * If the next pattern character is '/', just strip off the
     382                * '/' so we do exact matching on the character that follows.
     383                */
     384                if (*pattern == '\\') {
     385                        ++pattern;
     386                        if (*pattern == 0)
     387                                return(0);
     388                }
     389                /*
     390                * There's no special character.  Just make sure that the
     391                * next characters of each string match.
     392                */
     393                if (*pattern != *string)
     394                        return(0);
     395thisCharOK:     ++pattern;
     396                ++string;
     397        }
    397398}
    398399
     
    401402 *-----------------------------------------------------------------------
    402403 * Str_SYSVMatch --
    403  *      Check word against pattern for a match (% is wild),
     404 *      Check word against pattern for a match (% is wild),
    404405 *
    405406 * Results:
    406  *      Returns the beginning position of a match or null. The number
    407  *      of characters matched is returned in len.
     407 *      Returns the beginning position of a match or null. The number
     408 *      of characters matched is returned in len.
    408409 *
    409410 * Side Effects:
    410  *      None
     411 *      None
    411412 *
    412413 *-----------------------------------------------------------------------
     
    414415char *
    415416Str_SYSVMatch(word, pattern, len)
    416     char        *word;          /* Word to examine */
    417     char        *pattern;       /* Pattern to examine against */
    418     int         *len;           /* Number of characters to substitute */
     417    char        *word;          /* Word to examine */
     418    char        *pattern;       /* Pattern to examine against */
     419    int         *len;           /* Number of characters to substitute */
    419420{
    420421    char *p = pattern;
     
    423424
    424425    if (*w == '\0') {
    425         /* Zero-length word cannot be matched against */
    426         *len = 0;
    427         return NULL;
     426        /* Zero-length word cannot be matched against */
     427        *len = 0;
     428        return NULL;
    428429    }
    429430
    430431    if (*p == '\0') {
    431         /* Null pattern is the whole string */
    432         *len = strlen(w);
    433         return w;
     432        /* Null pattern is the whole string */
     433        *len = strlen(w);
     434        return w;
    434435    }
    435436
    436437    if ((m = strchr(p, '%')) != NULL) {
    437         /* check that the prefix matches */
    438         for (; p != m && *w && *w == *p; w++, p++)
    439              continue;
    440 
    441         if (p != m)
    442             return NULL;        /* No match */
    443 
    444         if (*++p == '\0') {
    445             /* No more pattern, return the rest of the string */
    446             *len = strlen(w);
    447             return w;
    448         }
     438        /* check that the prefix matches */
     439        for (; p != m && *w && *w == *p; w++, p++)
     440             continue;
     441
     442        if (p != m)
     443            return NULL;        /* No match */
     444
     445        if (*++p == '\0') {
     446            /* No more pattern, return the rest of the string */
     447            *len = strlen(w);
     448            return w;
     449        }
    449450    }
    450451
     
    453454    /* Find a matching tail */
    454455    do
    455         if (strcmp(p, w) == 0) {
    456             *len = w - m;
    457             return m;
    458         }
     456        if (strcmp(p, w) == 0) {
     457            *len = w - m;
     458            return m;
     459        }
    459460    while (*w++ != '\0');
    460461
     
    466467 *-----------------------------------------------------------------------
    467468 * Str_SYSVSubst --
    468  *      Substitute '%' on the pattern with len characters from src.
    469  *      If the pattern does not contain a '%' prepend len characters
    470  *      from src.
     469 *      Substitute '%' on the pattern with len characters from src.
     470 *      If the pattern does not contain a '%' prepend len characters
     471 *      from src.
    471472 *
    472473 * Results:
    473  *      None
     474 *      None
    474475 *
    475476 * Side Effects:
    476  *      Places result on buf
     477 *      Places result on buf
    477478 *
    478479 *-----------------------------------------------------------------------
     
    488489
    489490    if ((m = strchr(pat, '%')) != NULL) {
    490         /* Copy the prefix */
    491         Buf_AddBytes(buf, m - pat, (Byte *) pat);
    492         /* skip the % */
    493         pat = m + 1;
     491        /* Copy the prefix */
     492        Buf_AddBytes(buf, m - pat, (Byte *) pat);
     493        /* skip the % */
     494        pat = m + 1;
    494495    }
    495496
  • trunk/src/kmk/suff.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[] = "@(#)suff.c      8.4 (Berkeley) 3/21/94";
     41static char sccsid[] = "@(#)suff.c      8.4 (Berkeley) 3/21/94";
    4242#else
    4343static const char rcsid[] =
    4444  "$FreeBSD: src/usr.bin/make/suff.c,v 1.12.2.1 2001/03/09 01:13:24 tmm Exp $";
    4545#endif
     46#define KLIBFILEDEF rcsid
    4647#endif /* not lint */
    4748
    4849/*-
    4950 * suff.c --
    50  *      Functions to maintain suffix lists and find implicit dependents
    51  *      using suffix transformation rules
     51 *      Functions to maintain suffix lists and find implicit dependents
     52 *      using suffix transformation rules
    5253 *
    5354 * Interface:
    54  *      Suff_Init               Initialize all things to do with suffixes.
    55  *
    56  *      Suff_End                Cleanup the module
    57  *
    58  *      Suff_DoPaths            This function is used to make life easier
    59  *                              when searching for a file according to its
    60  *                              suffix. It takes the global search path,
    61  *                              as defined using the .PATH: target, and appends
    62  *                              its directories to the path of each of the
    63  *                              defined suffixes, as specified using
    64  *                              .PATH<suffix>: targets. In addition, all
    65  *                              directories given for suffixes labeled as
    66  *                              include files or libraries, using the .INCLUDES
    67  *                              or .LIBS targets, are played with using
    68  *                              Dir_MakeFlags to create the .INCLUDES and
    69  *                              .LIBS global variables.
    70  *
    71  *      Suff_ClearSuffixes      Clear out all the suffixes and defined
    72  *                              transformations.
    73  *
    74  *      Suff_IsTransform        Return TRUE if the passed string is the lhs
    75  *                              of a transformation rule.
    76  *
    77  *      Suff_AddSuffix          Add the passed string as another known suffix.
    78  *
    79  *      Suff_GetPath            Return the search path for the given suffix.
    80  *
    81  *      Suff_AddInclude         Mark the given suffix as denoting an include
    82  *                              file.
    83  *
    84  *      Suff_AddLib             Mark the given suffix as denoting a library.
    85  *
    86  *      Suff_AddTransform       Add another transformation to the suffix
    87  *                              graph. Returns  GNode suitable for framing, I
    88  *                              mean, tacking commands, attributes, etc. on.
    89  *
    90  *      Suff_SetNull            Define the suffix to consider the suffix of
    91  *                              any file that doesn't have a known one.
    92  *
    93  *      Suff_FindDeps           Find implicit sources for and the location of
    94  *                              a target based on its suffix. Returns the
    95  *                              bottom-most node added to the graph or NILGNODE
    96  *                              if the target had no implicit sources.
    97  */
    98 
    99 #include          <stdio.h>
    100 #include          "make.h"
    101 #include          "hash.h"
    102 #include          "dir.h"
    103 
    104 static Lst       sufflist;      /* Lst of suffixes */
    105 static Lst       suffClean;     /* Lst of suffixes to be cleaned */
    106 static Lst       srclist;       /* Lst of sources */
    107 static Lst       transforms;    /* Lst of transformation rules */
    108 
    109 static int        sNum = 0;     /* Counter for assigning suffix numbers */
     55 *      Suff_Init               Initialize all things to do with suffixes.
     56 *
     57 *      Suff_End                Cleanup the module
     58 *
     59 *      Suff_DoPaths            This function is used to make life easier
     60 *                              when searching for a file according to its
     61 *                              suffix. It takes the global search path,
     62 *                              as defined using the .PATH: target, and appends
     63 *                              its directories to the path of each of the
     64 *                              defined suffixes, as specified using
     65 *                              .PATH<suffix>: targets. In addition, all
     66 *                              directories given for suffixes labeled as
     67 *                              include files or libraries, using the .INCLUDES
     68 *                              or .LIBS targets, are played with using
     69 *                              Dir_MakeFlags to create the .INCLUDES and
     70 *                              .LIBS global variables.
     71 *
     72 *      Suff_ClearSuffixes      Clear out all the suffixes and defined
     73 *                              transformations.
     74 *
     75 *      Suff_IsTransform        Return TRUE if the passed string is the lhs
     76 *                              of a transformation rule.
     77 *
     78 *      Suff_AddSuffix          Add the passed string as another known suffix.
     79 *
     80 *      Suff_GetPath            Return the search path for the given suffix.
     81 *
     82 *      Suff_AddInclude         Mark the given suffix as denoting an include
     83 *                              file.
     84 *
     85 *      Suff_AddLib             Mark the given suffix as denoting a library.
     86 *
     87 *      Suff_AddTransform       Add another transformation to the suffix
     88 *                              graph. Returns  GNode suitable for framing, I
     89 *                              mean, tacking commands, attributes, etc. on.
     90 *
     91 *      Suff_SetNull            Define the suffix to consider the suffix of
     92 *                              any file that doesn't have a known one.
     93 *
     94 *      Suff_FindDeps           Find implicit sources for and the location of
     95 *                              a target based on its suffix. Returns the
     96 *                              bottom-most node added to the graph or NILGNODE
     97 *                              if the target had no implicit sources.
     98 */
     99
     100#include          <stdio.h>
     101#include          <strings.h>
     102#include          "make.h"
     103#include          "hash.h"
     104#include          "dir.h"
     105
     106static Lst       sufflist;      /* Lst of suffixes */
     107static Lst       suffClean;     /* Lst of suffixes to be cleaned */
     108static Lst       srclist;       /* Lst of sources */
     109static Lst       transforms;    /* Lst of transformation rules */
     110
     111static int        sNum = 0;     /* Counter for assigning suffix numbers */
    110112
    111113/*
     
    113115 */
    114116typedef struct _Suff {
    115     char         *name;         /* The suffix itself */
    116     int          nameLen;       /* Length of the suffix */
    117     short        flags;         /* Type of suffix */
    118 #define SUFF_INCLUDE      0x01      /* One which is #include'd */
     117    char         *name;         /* The suffix itself */
     118    int          nameLen;       /* Length of the suffix */
     119    short        flags;         /* Type of suffix */
     120#define SUFF_INCLUDE      0x01      /* One which is #include'd */
    119121#ifdef USE_ARCHIVES
    120 #define SUFF_LIBRARY      0x02      /* One which contains a library */
     122#define SUFF_LIBRARY      0x02      /* One which contains a library */
    121123#endif
    122 #define SUFF_NULL         0x04      /* The empty suffix */
    123     Lst          searchPath;    /* The path along which files of this suffix
    124                                 * may be found */
    125     int          sNum;          /* The suffix number */
    126     int          refCount;      /* Reference count of list membership */
    127     Lst          parents;       /* Suffixes we have a transformation to */
    128     Lst          children;      /* Suffixes we have a transformation from */
    129     Lst          ref;           /* List of lists this suffix is referenced */
     124#define SUFF_NULL         0x04      /* The empty suffix */
     125    Lst          searchPath;    /* The path along which files of this suffix
     126                                * may be found */
     127    int          sNum;          /* The suffix number */
     128    int          refCount;      /* Reference count of list membership */
     129    Lst          parents;       /* Suffixes we have a transformation to */
     130    Lst          children;      /* Suffixes we have a transformation from */
     131    Lst          ref;           /* List of lists this suffix is referenced */
    130132} Suff;
    131133
     
    134136 */
    135137typedef struct _Src {
    136     char            *file;      /* The file to look for */
    137     char            *pref;      /* Prefix from which file was formed */
    138     Suff            *suff;      /* The suffix on the file */
    139     struct _Src     *parent;    /* The Src for which this is a source */
    140     GNode           *node;      /* The node describing the file */
    141     int             children;   /* Count of existing children (so we don't efree
    142                                 * this thing too early or never nuke it) */
     138    char            *file;      /* The file to look for */
     139    char            *pref;      /* Prefix from which file was formed */
     140    Suff            *suff;      /* The suffix on the file */
     141    struct _Src     *parent;    /* The Src for which this is a source */
     142    GNode           *node;      /* The node describing the file */
     143    int             children;   /* Count of existing children (so we don't efree
     144                                * this thing too early or never nuke it) */
    143145#ifdef DEBUG_SRC
    144     Lst             cp;         /* Debug; children list */
     146    Lst             cp;         /* Debug; children list */
    145147#endif
    146148} Src;
     
    155157} LstSrc;
    156158
    157 static Suff         *suffNull;  /* The NULL suffix for this run */
    158 static Suff         *emptySuff; /* The empty suffix required for POSIX
    159                                 * single-suffix transformation rules */
     159static Suff         *suffNull;  /* The NULL suffix for this run */
     160static Suff         *emptySuff; /* The empty suffix required for POSIX
     161                                * single-suffix transformation rules */
    160162
    161163
     
    187189static int SuffPrintTrans __P((ClientData, ClientData));
    188190
    189         /*************** Lst Predicates ****************/
     191        /*************** Lst Predicates ****************/
    190192/*-
    191193 *-----------------------------------------------------------------------
    192194 * SuffStrIsPrefix  --
    193  *      See if pref is a prefix of str.
    194  *
    195  * Results:
    196  *      NULL if it ain't, pointer to character in str after prefix if so
    197  *
    198  * Side Effects:
    199  *      None
     195 *      See if pref is a prefix of str.
     196 *
     197 * Results:
     198 *      NULL if it ain't, pointer to character in str after prefix if so
     199 *
     200 * Side Effects:
     201 *      None
    200202 *-----------------------------------------------------------------------
    201203 */
    202204static char    *
    203205SuffStrIsPrefix (pref, str)
    204     register char  *pref;       /* possible prefix */
    205     register char  *str;        /* string to check */
     206    register char  *pref;       /* possible prefix */
     207    register char  *str;        /* string to check */
    206208{
    207209    while (*str && *pref == *str) {
    208         pref++;
    209         str++;
     210        pref++;
     211        str++;
    210212    }
    211213
     
    216218 *-----------------------------------------------------------------------
    217219 * SuffSuffIsSuffix  --
    218  *      See if suff is a suffix of str. Str should point to THE END of the
    219  *      string to check. (THE END == the null byte)
    220  *
    221  * Results:
    222  *      NULL if it ain't, pointer to character in str before suffix if
    223  *      it is.
    224  *
    225  * Side Effects:
    226  *      None
     220 *      See if suff is a suffix of str. Str should point to THE END of the
     221 *      string to check. (THE END == the null byte)
     222 *
     223 * Results:
     224 *      NULL if it ain't, pointer to character in str before suffix if
     225 *      it is.
     226 *
     227 * Side Effects:
     228 *      None
    227229 *-----------------------------------------------------------------------
    228230 */
    229231static char *
    230232SuffSuffIsSuffix (s, str)
    231     register Suff  *s;          /* possible suffix */
    232     char           *str;        /* string to examine */
    233 {
    234     register char  *p1;         /* Pointer into suffix name */
    235     register char  *p2;         /* Pointer into string being examined */
     233    register Suff  *s;          /* possible suffix */
     234    char           *str;        /* string to examine */
     235{
     236    register char  *p1;         /* Pointer into suffix name */
     237    register char  *p2;         /* Pointer into string being examined */
    236238
    237239    p1 = s->name + s->nameLen;
     
    239241
    240242    while (p1 >= s->name && *p1 == *p2) {
    241         p1--;
    242         p2--;
     243        p1--;
     244        p2--;
    243245    }
    244246
     
    249251 *-----------------------------------------------------------------------
    250252 * SuffSuffIsSuffixP --
    251  *      Predicate form of SuffSuffIsSuffix. Passed as the callback function
    252  *      to Lst_Find.
    253  *
    254  * Results:
    255  *      0 if the suffix is the one desired, non-zero if not.
    256  *
    257  * Side Effects:
    258  *      None.
     253 *      Predicate form of SuffSuffIsSuffix. Passed as the callback function
     254 *      to Lst_Find.
     255 *
     256 * Results:
     257 *      0 if the suffix is the one desired, non-zero if not.
     258 *
     259 * Side Effects:
     260 *      None.
    259261 *
    260262 *-----------------------------------------------------------------------
     
    271273 *-----------------------------------------------------------------------
    272274 * SuffSuffHasNameP --
    273  *      Callback procedure for finding a suffix based on its name. Used by
    274  *      Suff_GetPath.
    275  *
    276  * Results:
    277  *      0 if the suffix is of the given name. non-zero otherwise.
    278  *
    279  * Side Effects:
    280  *      None
     275 *      Callback procedure for finding a suffix based on its name. Used by
     276 *      Suff_GetPath.
     277 *
     278 * Results:
     279 *      0 if the suffix is of the given name. non-zero otherwise.
     280 *
     281 * Side Effects:
     282 *      None
    281283 *-----------------------------------------------------------------------
    282284 */
    283285static int
    284286SuffSuffHasNameP (s, sname)
    285     ClientData    s;                /* Suffix to check */
    286     ClientData    sname;            /* Desired name */
     287    ClientData    s;                /* Suffix to check */
     288    ClientData    sname;            /* Desired name */
    287289{
    288290    return (strcmp ((char *) sname, ((Suff *) s)->name));
     
    292294 *-----------------------------------------------------------------------
    293295 * SuffSuffIsPrefix  --
    294  *      See if the suffix described by s is a prefix of the string. Care
    295  *      must be taken when using this to search for transformations and
    296  *      what-not, since there could well be two suffixes, one of which
    297  *      is a prefix of the other...
    298  *
    299  * Results:
    300  *      0 if s is a prefix of str. non-zero otherwise
    301  *
    302  * Side Effects:
    303  *      None
     296 *      See if the suffix described by s is a prefix of the string. Care
     297 *      must be taken when using this to search for transformations and
     298 *      what-not, since there could well be two suffixes, one of which
     299 *      is a prefix of the other...
     300 *
     301 * Results:
     302 *      0 if s is a prefix of str. non-zero otherwise
     303 *
     304 * Side Effects:
     305 *      None
    304306 *-----------------------------------------------------------------------
    305307 */
    306308static int
    307309SuffSuffIsPrefix (s, str)
    308     ClientData   s;             /* suffix to compare */
    309     ClientData   str;   /* string to examine */
     310    ClientData   s;             /* suffix to compare */
     311    ClientData   str;   /* string to examine */
    310312{
    311313    return (SuffStrIsPrefix (((Suff *) s)->name, (char *) str) == NULL ? 1 : 0);
     
    315317 *-----------------------------------------------------------------------
    316318 * SuffGNHasNameP  --
    317  *      See if the graph node has the desired name
    318  *
    319  * Results:
    320  *      0 if it does. non-zero if it doesn't
    321  *
    322  * Side Effects:
    323  *      None
     319 *      See if the graph node has the desired name
     320 *
     321 * Results:
     322 *      0 if it does. non-zero if it doesn't
     323 *
     324 * Side Effects:
     325 *      None
    324326 *-----------------------------------------------------------------------
    325327 */
    326328static int
    327329SuffGNHasNameP (gn, name)
    328     ClientData      gn;         /* current node we're looking at */
    329     ClientData      name;       /* name we're looking for */
     330    ClientData      gn;         /* current node we're looking at */
     331    ClientData      name;       /* name we're looking for */
    330332{
    331333    return (strcmp ((char *) name, ((GNode *) gn)->name));
    332334}
    333335
    334             /*********** Maintenance Functions ************/
     336            /*********** Maintenance Functions ************/
    335337
    336338/*-
    337339 *-----------------------------------------------------------------------
    338340 * SuffFree  --
    339  *      Free up all memory associated with the given suffix structure.
    340  *
    341  * Results:
    342  *      none
    343  *
    344  * Side Effects:
    345  *      the suffix entry is detroyed
     341 *      Free up all memory associated with the given suffix structure.
     342 *
     343 * Results:
     344 *      none
     345 *
     346 * Side Effects:
     347 *      the suffix entry is detroyed
    346348 *-----------------------------------------------------------------------
    347349 */
     
    353355
    354356    if (s == suffNull)
    355         suffNull = NULL;
     357        suffNull = NULL;
    356358
    357359    if (s == emptySuff)
    358         emptySuff = NULL;
     360        emptySuff = NULL;
    359361
    360362    Lst_Destroy (s->ref, NOFREE);
     
    370372 *-----------------------------------------------------------------------
    371373 * SuffRemove  --
    372  *      Remove the suffix into the list
    373  *
    374  * Results:
    375  *      None
    376  *
    377  * Side Effects:
    378  *      The reference count for the suffix is decremented
     374 *      Remove the suffix into the list
     375 *
     376 * Results:
     377 *      None
     378 *
     379 * Side Effects:
     380 *      The reference count for the suffix is decremented
    379381 *-----------------------------------------------------------------------
    380382 */
     
    386388    LstNode ln = Lst_Member(l, (ClientData)s);
    387389    if (ln != NILLNODE) {
    388         Lst_Remove(l, ln);
    389         s->refCount--;
     390        Lst_Remove(l, ln);
     391        s->refCount--;
    390392    }
    391393}
     
    395397 *-----------------------------------------------------------------------
    396398 * SuffInsert  --
    397  *      Insert the suffix into the list keeping the list ordered by suffix
    398  *      numbers.
    399  *
    400  * Results:
    401  *      None
    402  *
    403  * Side Effects:
    404  *      The reference count of the suffix is incremented
     399 *      Insert the suffix into the list keeping the list ordered by suffix
     400 *      numbers.
     401 *
     402 * Results:
     403 *      None
     404 *
     405 * Side Effects:
     406 *      The reference count of the suffix is incremented
    405407 *-----------------------------------------------------------------------
    406408 */
    407409static void
    408410SuffInsert (l, s)
    409     Lst           l;            /* the list where in s should be inserted */
    410     Suff          *s;           /* the suffix to insert */
    411 {
    412     LstNode       ln;           /* current element in l we're examining */
    413     Suff          *s2 = NULL;   /* the suffix descriptor in this element */
     411    Lst           l;            /* the list where in s should be inserted */
     412    Suff          *s;           /* the suffix to insert */
     413{
     414    LstNode       ln;           /* current element in l we're examining */
     415    Suff          *s2 = NULL;   /* the suffix descriptor in this element */
    414416
    415417    if (Lst_Open (l) == FAILURE) {
    416         return;
     418        return;
    417419    }
    418420    while ((ln = Lst_Next (l)) != NILLNODE) {
    419         s2 = (Suff *) Lst_Datum (ln);
    420         if (s2->sNum >= s->sNum) {
    421             break;
    422         }
     421        s2 = (Suff *) Lst_Datum (ln);
     422        if (s2->sNum >= s->sNum) {
     423            break;
     424        }
    423425    }
    424426
    425427    Lst_Close (l);
    426428    if (DEBUG(SUFF)) {
    427         printf("inserting %s(%d)...", s->name, s->sNum);
     429        printf("inserting %s(%d)...", s->name, s->sNum);
    428430    }
    429431    if (ln == NILLNODE) {
    430         if (DEBUG(SUFF)) {
    431             printf("at end of list\n");
    432         }
    433         (void)Lst_AtEnd (l, (ClientData)s);
    434         s->refCount++;
    435         (void)Lst_AtEnd(s->ref, (ClientData) l);
     432        if (DEBUG(SUFF)) {
     433            printf("at end of list\n");
     434        }
     435        (void)Lst_AtEnd (l, (ClientData)s);
     436        s->refCount++;
     437        (void)Lst_AtEnd(s->ref, (ClientData) l);
    436438    } else if (s2->sNum != s->sNum) {
    437         if (DEBUG(SUFF)) {
    438             printf("before %s(%d)\n", s2->name, s2->sNum);
    439         }
    440         (void)Lst_Insert (l, ln, (ClientData)s);
    441         s->refCount++;
    442         (void)Lst_AtEnd(s->ref, (ClientData) l);
     439        if (DEBUG(SUFF)) {
     440            printf("before %s(%d)\n", s2->name, s2->sNum);
     441        }
     442        (void)Lst_Insert (l, ln, (ClientData)s);
     443        s->refCount++;
     444        (void)Lst_AtEnd(s->ref, (ClientData) l);
    443445    } else if (DEBUG(SUFF)) {
    444         printf("already there\n");
     446        printf("already there\n");
    445447    }
    446448}
     
    449451 *-----------------------------------------------------------------------
    450452 * Suff_ClearSuffixes --
    451  *      This is gross. Nuke the list of suffixes but keep all transformation
    452  *      rules around. The transformation graph is destroyed in this process,
    453  *      but we leave the list of rules so when a new graph is formed the rules
    454  *      will remain.
    455  *      This function is called from the parse module when a
    456  *      .SUFFIXES:\n line is encountered.
    457  *
    458  * Results:
    459  *      none
    460  *
    461  * Side Effects:
    462  *      the sufflist and its graph nodes are destroyed
     453 *      This is gross. Nuke the list of suffixes but keep all transformation
     454 *      rules around. The transformation graph is destroyed in this process,
     455 *      but we leave the list of rules so when a new graph is formed the rules
     456 *      will remain.
     457 *      This function is called from the parse module when a
     458 *      .SUFFIXES:\n line is encountered.
     459 *
     460 * Results:
     461 *      none
     462 *
     463 * Side Effects:
     464 *      the sufflist and its graph nodes are destroyed
    463465 *-----------------------------------------------------------------------
    464466 */
     
    483485 *-----------------------------------------------------------------------
    484486 * SuffParseTransform --
    485  *      Parse a transformation string to find its two component suffixes.
    486  *
    487  * Results:
    488  *      TRUE if the string is a valid transformation and FALSE otherwise.
    489  *
    490  * Side Effects:
    491  *      The passed pointers are overwritten.
     487 *      Parse a transformation string to find its two component suffixes.
     488 *
     489 * Results:
     490 *      TRUE if the string is a valid transformation and FALSE otherwise.
     491 *
     492 * Side Effects:
     493 *      The passed pointers are overwritten.
    492494 *
    493495 *-----------------------------------------------------------------------
     
    495497static Boolean
    496498SuffParseTransform(str, srcPtr, targPtr)
    497     char                *str;           /* String being parsed */
    498     Suff                **srcPtr;       /* Place to store source of trans. */
    499     Suff                **targPtr;      /* Place to store target of trans. */
    500 {
    501     register LstNode    srcLn;      /* element in suffix list of trans source*/
    502     register Suff       *src;       /* Source of transformation */
    503     register LstNode    targLn;     /* element in suffix list of trans target*/
    504     register char       *str2;      /* Extra pointer (maybe target suffix) */
    505     LstNode             singleLn;   /* element in suffix list of any suffix
    506                                      * that exactly matches str */
    507     Suff                *single = NULL;/* Source of possible transformation to
    508                                      * null suffix */
     499    char                *str;           /* String being parsed */
     500    Suff                **srcPtr;       /* Place to store source of trans. */
     501    Suff                **targPtr;      /* Place to store target of trans. */
     502{
     503    register LstNode    srcLn;      /* element in suffix list of trans source*/
     504    register Suff       *src;       /* Source of transformation */
     505    register LstNode    targLn;     /* element in suffix list of trans target*/
     506    register char       *str2;      /* Extra pointer (maybe target suffix) */
     507    LstNode             singleLn;   /* element in suffix list of any suffix
     508                                     * that exactly matches str */
     509    Suff                *single = NULL;/* Source of possible transformation to
     510                                     * null suffix */
    509511
    510512    srcLn = NILLNODE;
     
    518520     */
    519521    for (;;) {
    520         if (srcLn == NILLNODE) {
    521             srcLn = Lst_Find(sufflist, (ClientData)str, SuffSuffIsPrefix);
    522         } else {
    523             srcLn = Lst_FindFrom (sufflist, Lst_Succ(srcLn), (ClientData)str,
    524                                   SuffSuffIsPrefix);
    525         }
    526         if (srcLn == NILLNODE) {
    527             /*
    528              * Ran out of source suffixes -- no such rule
    529              */
    530             if (singleLn != NILLNODE) {
    531                 /*
    532                 * Not so fast Mr. Smith! There was a suffix that encompassed
    533                 * the entire string, so we assume it was a transformation
    534                 * to the null suffix (thank you POSIX). We still prefer to
    535                 * find a double rule over a singleton, hence we leave this
    536                 * check until the end.
    537                 *
    538                 * XXX: Use emptySuff over suffNull?
    539                 */
    540                 *srcPtr = single;
    541                 *targPtr = suffNull;
    542                 return(TRUE);
    543             }
    544             return (FALSE);
    545         }
    546         src = (Suff *) Lst_Datum (srcLn);
    547         str2 = str + src->nameLen;
    548         if (*str2 == '\0') {
    549             single = src;
    550             singleLn = srcLn;
    551         } else {
    552             targLn = Lst_Find(sufflist, (ClientData)str2, SuffSuffHasNameP);
    553             if (targLn != NILLNODE) {
    554                 *srcPtr = src;
    555                 *targPtr = (Suff *)Lst_Datum(targLn);
    556                 return (TRUE);
    557             }
    558         }
     522        if (srcLn == NILLNODE) {
     523            srcLn = Lst_Find(sufflist, (ClientData)str, SuffSuffIsPrefix);
     524        } else {
     525            srcLn = Lst_FindFrom (sufflist, Lst_Succ(srcLn), (ClientData)str,
     526                                  SuffSuffIsPrefix);
     527        }
     528        if (srcLn == NILLNODE) {
     529            /*
     530             * Ran out of source suffixes -- no such rule
     531             */
     532            if (singleLn != NILLNODE) {
     533                /*
     534                * Not so fast Mr. Smith! There was a suffix that encompassed
     535                * the entire string, so we assume it was a transformation
     536                * to the null suffix (thank you POSIX). We still prefer to
     537                * find a double rule over a singleton, hence we leave this
     538                * check until the end.
     539                *
     540                * XXX: Use emptySuff over suffNull?
     541                */
     542                *srcPtr = single;
     543                *targPtr = suffNull;
     544                return(TRUE);
     545            }
     546            return (FALSE);
     547        }
     548        src = (Suff *) Lst_Datum (srcLn);
     549        str2 = str + src->nameLen;
     550        if (*str2 == '\0') {
     551            single = src;
     552            singleLn = srcLn;
     553        } else {
     554            targLn = Lst_Find(sufflist, (ClientData)str2, SuffSuffHasNameP);
     555            if (targLn != NILLNODE) {
     556                *srcPtr = src;
     557                *targPtr = (Suff *)Lst_Datum(targLn);
     558                return (TRUE);
     559            }
     560        }
    559561    }
    560562}
     
    563565 *-----------------------------------------------------------------------
    564566 * Suff_IsTransform  --
    565  *      Return TRUE if the given string is a transformation rule
    566  *
    567  *
    568  * Results:
    569  *      TRUE if the string is a concatenation of two known suffixes.
    570  *      FALSE otherwise
    571  *
    572  * Side Effects:
    573  *      None
     567 *      Return TRUE if the given string is a transformation rule
     568 *
     569 *
     570 * Results:
     571 *      TRUE if the string is a concatenation of two known suffixes.
     572 *      FALSE otherwise
     573 *
     574 * Side Effects:
     575 *      None
    574576 *-----------------------------------------------------------------------
    575577 */
    576578Boolean
    577579Suff_IsTransform (str)
    578     char          *str;         /* string to check */
    579 {
    580     Suff          *src, *targ;
     580    char          *str;         /* string to check */
     581{
     582    Suff          *src, *targ;
    581583
    582584    return (SuffParseTransform(str, &src, &targ));
     
    586588 *-----------------------------------------------------------------------
    587589 * Suff_AddTransform --
    588  *      Add the transformation rule described by the line to the
    589  *      list of rules and place the transformation itself in the graph
    590  *
    591  * Results:
    592  *      The node created for the transformation in the transforms list
    593  *
    594  * Side Effects:
    595  *      The node is placed on the end of the transforms Lst and links are
    596  *      made between the two suffixes mentioned in the target name
     590 *      Add the transformation rule described by the line to the
     591 *      list of rules and place the transformation itself in the graph
     592 *
     593 * Results:
     594 *      The node created for the transformation in the transforms list
     595 *
     596 * Side Effects:
     597 *      The node is placed on the end of the transforms Lst and links are
     598 *      made between the two suffixes mentioned in the target name
    597599 *-----------------------------------------------------------------------
    598600 */
    599601GNode *
    600602Suff_AddTransform (line)
    601     char          *line;        /* name of transformation to add */
    602 {
    603     GNode         *gn;          /* GNode of transformation rule */
    604     Suff          *s,           /* source suffix */
    605                   *t;           /* target suffix */
    606     LstNode       ln;           /* Node for existing transformation */
     603    char          *line;        /* name of transformation to add */
     604{
     605    GNode         *gn;          /* GNode of transformation rule */
     606    Suff          *s,           /* source suffix */
     607                  *t;           /* target suffix */
     608    LstNode       ln;           /* Node for existing transformation */
    607609
    608610    ln = Lst_Find (transforms, (ClientData)line, SuffGNHasNameP);
    609611    if (ln == NILLNODE) {
    610         /*
    611         * Make a new graph node for the transformation. It will be filled in
    612         * by the Parse module.
    613         */
    614         gn = Targ_NewGN (line);
    615         (void)Lst_AtEnd (transforms, (ClientData)gn);
     612        /*
     613        * Make a new graph node for the transformation. It will be filled in
     614        * by the Parse module.
     615        */
     616        gn = Targ_NewGN (line);
     617        (void)Lst_AtEnd (transforms, (ClientData)gn);
    616618    } else {
    617         /*
    618         * New specification for transformation rule. Just nuke the old list
    619         * of commands so they can be filled in again... We don't actually
    620         * efree the commands themselves, because a given command can be
    621         * attached to several different transformations.
    622         */
    623         gn = (GNode *) Lst_Datum (ln);
    624         Lst_Destroy (gn->commands, NOFREE);
    625         Lst_Destroy (gn->children, NOFREE);
    626         gn->commands = Lst_Init (FALSE);
    627         gn->children = Lst_Init (FALSE);
     619        /*
     620        * New specification for transformation rule. Just nuke the old list
     621        * of commands so they can be filled in again... We don't actually
     622        * efree the commands themselves, because a given command can be
     623        * attached to several different transformations.
     624        */
     625        gn = (GNode *) Lst_Datum (ln);
     626        Lst_Destroy (gn->commands, NOFREE);
     627        Lst_Destroy (gn->children, NOFREE);
     628        gn->commands = Lst_Init (FALSE);
     629        gn->children = Lst_Init (FALSE);
    628630    }
    629631
     
    636638     */
    637639    if (DEBUG(SUFF)) {
    638         printf("defining transformation from `%s' to `%s'\n",
    639                 s->name, t->name);
     640        printf("defining transformation from `%s' to `%s'\n",
     641                s->name, t->name);
    640642    }
    641643    SuffInsert (t->children, s);
     
    648650 *-----------------------------------------------------------------------
    649651 * Suff_EndTransform --
    650  *      Handle the finish of a transformation definition, removing the
    651  *      transformation from the graph if it has neither commands nor
    652  *      sources. This is a callback procedure for the Parse module via
    653  *      Lst_ForEach
    654  *
    655  * Results:
    656  *      === 0
    657  *
    658  * Side Effects:
    659  *      If the node has no commands or children, the children and parents
    660  *      lists of the affected suffices are altered.
     652 *      Handle the finish of a transformation definition, removing the
     653 *      transformation from the graph if it has neither commands nor
     654 *      sources. This is a callback procedure for the Parse module via
     655 *      Lst_ForEach
     656 *
     657 * Results:
     658 *      === 0
     659 *
     660 * Side Effects:
     661 *      If the node has no commands or children, the children and parents
     662 *      lists of the affected suffices are altered.
    661663 *
    662664 *-----------------------------------------------------------------------
     
    664666int
    665667Suff_EndTransform(gnp, dummy)
    666     ClientData   gnp;           /* Node for transformation */
    667     ClientData   dummy;         /* Node for transformation */
     668    ClientData   gnp;           /* Node for transformation */
     669    ClientData   dummy;         /* Node for transformation */
    668670{
    669671    GNode *gn = (GNode *) gnp;
    670672
    671673    if ((gn->type & OP_TRANSFORM) && Lst_IsEmpty(gn->commands) &&
    672         Lst_IsEmpty(gn->children))
     674        Lst_IsEmpty(gn->children))
    673675    {
    674         Suff    *s, *t;
    675 
    676         (void)SuffParseTransform(gn->name, &s, &t);
    677 
    678         if (DEBUG(SUFF)) {
    679             printf("deleting transformation from `%s' to `%s'\n",
    680                     s->name, t->name);
    681         }
    682 
    683         /*
    684         * Remove the source from the target's children list. We check for a
    685         * nil return to handle a beanhead saying something like
    686         *  .c.o .c.o:
    687         *
    688         * We'll be called twice when the next target is seen, but .c and .o
    689         * are only linked once...
    690         */
    691         SuffRemove(t->children, s);
    692 
    693         /*
    694         * Remove the target from the source's parents list
    695         */
    696         SuffRemove(s->parents, t);
     676        Suff    *s, *t;
     677
     678        (void)SuffParseTransform(gn->name, &s, &t);
     679
     680        if (DEBUG(SUFF)) {
     681            printf("deleting transformation from `%s' to `%s'\n",
     682                    s->name, t->name);
     683        }
     684
     685        /*
     686        * Remove the source from the target's children list. We check for a
     687        * nil return to handle a beanhead saying something like
     688        *  .c.o .c.o:
     689        *
     690        * We'll be called twice when the next target is seen, but .c and .o
     691        * are only linked once...
     692        */
     693        SuffRemove(t->children, s);
     694
     695        /*
     696        * Remove the target from the source's parents list
     697        */
     698        SuffRemove(s->parents, t);
    697699    } else if ((gn->type & OP_TRANSFORM) && DEBUG(SUFF)) {
    698         printf("transformation %s complete\n", gn->name);
     700        printf("transformation %s complete\n", gn->name);
    699701    }
    700702
     
    705707 *-----------------------------------------------------------------------
    706708 * SuffRebuildGraph --
    707  *      Called from Suff_AddSuffix via Lst_ForEach to search through the
    708  *      list of existing transformation rules and rebuild the transformation
    709  *      graph when it has been destroyed by Suff_ClearSuffixes. If the
    710  *      given rule is a transformation involving this suffix and another,
    711  *      existing suffix, the proper relationship is established between
    712  *      the two.
    713  *
    714  * Results:
    715  *      Always 0.
    716  *
    717  * Side Effects:
    718  *      The appropriate links will be made between this suffix and
    719  *      others if transformation rules exist for it.
     709 *      Called from Suff_AddSuffix via Lst_ForEach to search through the
     710 *      list of existing transformation rules and rebuild the transformation
     711 *      graph when it has been destroyed by Suff_ClearSuffixes. If the
     712 *      given rule is a transformation involving this suffix and another,
     713 *      existing suffix, the proper relationship is established between
     714 *      the two.
     715 *
     716 * Results:
     717 *      Always 0.
     718 *
     719 * Side Effects:
     720 *      The appropriate links will be made between this suffix and
     721 *      others if transformation rules exist for it.
    720722 *
    721723 *-----------------------------------------------------------------------
     
    724726SuffRebuildGraph(transformp, sp)
    725727    ClientData  transformp; /* Transformation to test */
    726     ClientData  sp;         /* Suffix to rebuild */
    727 {
    728     GNode       *transform = (GNode *) transformp;
    729     Suff        *s = (Suff *) sp;
    730     char        *cp;
    731     LstNode     ln;
    732     Suff        *s2 = NULL;
     728    ClientData  sp;         /* Suffix to rebuild */
     729{
     730    GNode       *transform = (GNode *) transformp;
     731    Suff        *s = (Suff *) sp;
     732    char        *cp;
     733    LstNode     ln;
     734    Suff        *s2 = NULL;
    733735
    734736    /*
     
    737739    cp = SuffStrIsPrefix(s->name, transform->name);
    738740    if (cp != (char *)NULL) {
    739         if (cp[0] == '\0')  /* null rule */
    740             s2 = suffNull;
    741         else {
    742             ln = Lst_Find(sufflist, (ClientData)cp, SuffSuffHasNameP);
    743             if (ln != NILLNODE)
    744                 s2 = (Suff *)Lst_Datum(ln);
    745         }
    746         if (s2 != NULL) {
    747             /*
    748              * Found target. Link in and return, since it can't be anything
    749              * else.
    750              */
    751             SuffInsert(s2->children, s);
    752             SuffInsert(s->parents, s2);
    753             return(0);
    754         }
     741        if (cp[0] == '\0')  /* null rule */
     742            s2 = suffNull;
     743        else {
     744            ln = Lst_Find(sufflist, (ClientData)cp, SuffSuffHasNameP);
     745            if (ln != NILLNODE)
     746                s2 = (Suff *)Lst_Datum(ln);
     747        }
     748        if (s2 != NULL) {
     749            /*
     750             * Found target. Link in and return, since it can't be anything
     751             * else.
     752             */
     753            SuffInsert(s2->children, s);
     754            SuffInsert(s->parents, s2);
     755            return(0);
     756        }
    755757    }
    756758
     
    760762    cp = SuffSuffIsSuffix(s, transform->name + strlen(transform->name));
    761763    if (cp != (char *)NULL) {
    762         /*
    763         * Null-terminate the source suffix in order to find it.
    764         */
    765         cp[1] = '\0';
    766         ln = Lst_Find(sufflist, (ClientData)transform->name, SuffSuffHasNameP);
    767         /*
    768         * Replace the start of the target suffix
    769         */
    770         cp[1] = s->name[0];
    771         if (ln != NILLNODE) {
    772             /*
    773              * Found it -- establish the proper relationship
    774              */
    775             s2 = (Suff *)Lst_Datum(ln);
    776             SuffInsert(s->children, s2);
    777             SuffInsert(s2->parents, s);
    778         }
     764        /*
     765        * Null-terminate the source suffix in order to find it.
     766        */
     767        cp[1] = '\0';
     768        ln = Lst_Find(sufflist, (ClientData)transform->name, SuffSuffHasNameP);
     769        /*
     770        * Replace the start of the target suffix
     771        */
     772        cp[1] = s->name[0];
     773        if (ln != NILLNODE) {
     774            /*
     775             * Found it -- establish the proper relationship
     776             */
     777            s2 = (Suff *)Lst_Datum(ln);
     778            SuffInsert(s->children, s2);
     779            SuffInsert(s2->parents, s);
     780        }
    779781    }
    780782    return(0);
     
    784786 *-----------------------------------------------------------------------
    785787 * Suff_AddSuffix --
    786  *      Add the suffix in string to the end of the list of known suffixes.
    787  *      Should we restructure the suffix graph? Make doesn't...
    788  *
    789  * Results:
    790  *      None
    791  *
    792  * Side Effects:
    793  *      A GNode is created for the suffix and a Suff structure is created and
    794  *      added to the suffixes list unless the suffix was already known.
     788 *      Add the suffix in string to the end of the list of known suffixes.
     789 *      Should we restructure the suffix graph? Make doesn't...
     790 *
     791 * Results:
     792 *      None
     793 *
     794 * Side Effects:
     795 *      A GNode is created for the suffix and a Suff structure is created and
     796 *      added to the suffixes list unless the suffix was already known.
    795797 *-----------------------------------------------------------------------
    796798 */
    797799void
    798800Suff_AddSuffix (str)
    799     char          *str;     /* the name of the suffix to add */
    800 {
    801     Suff          *s;       /* new suffix descriptor */
    802     LstNode       ln;
     801    char          *str;     /* the name of the suffix to add */
     802{
     803    Suff          *s;       /* new suffix descriptor */
     804    LstNode       ln;
    803805
    804806    ln = Lst_Find (sufflist, (ClientData)str, SuffSuffHasNameP);
    805807    if (ln == NILLNODE) {
    806         s = (Suff *) emalloc (sizeof (Suff));
    807 
    808         s->name =       estrdup (str);
    809         s->nameLen =    strlen (s->name);
    810         s->searchPath = Lst_Init (FALSE);
    811         s->children =   Lst_Init (FALSE);
    812         s->parents =    Lst_Init (FALSE);
    813         s->ref =        Lst_Init (FALSE);
    814         s->sNum =       sNum++;
    815         s->flags =      0;
    816         s->refCount =   0;
    817 
    818         (void)Lst_AtEnd (sufflist, (ClientData)s);
    819         /*
    820         * Look for any existing transformations from or to this suffix.
    821         * XXX: Only do this after a Suff_ClearSuffixes?
    822         */
    823         Lst_ForEach (transforms, SuffRebuildGraph, (ClientData)s);
     808        s = (Suff *) emalloc (sizeof (Suff));
     809
     810        s->name =       estrdup (str);
     811        s->nameLen =    strlen (s->name);
     812        s->searchPath = Lst_Init (FALSE);
     813        s->children =   Lst_Init (FALSE);
     814        s->parents =    Lst_Init (FALSE);
     815        s->ref =        Lst_Init (FALSE);
     816        s->sNum =       sNum++;
     817        s->flags =      0;
     818        s->refCount =   0;
     819
     820        (void)Lst_AtEnd (sufflist, (ClientData)s);
     821        /*
     822        * Look for any existing transformations from or to this suffix.
     823        * XXX: Only do this after a Suff_ClearSuffixes?
     824        */
     825        Lst_ForEach (transforms, SuffRebuildGraph, (ClientData)s);
    824826    }
    825827}
     
    828830 *-----------------------------------------------------------------------
    829831 * Suff_GetPath --
    830  *      Return the search path for the given suffix, if it's defined.
    831  *
    832  * Results:
    833  *      The searchPath for the desired suffix or NILLST if the suffix isn't
    834  *      defined.
    835  *
    836  * Side Effects:
    837  *      None
     832 *      Return the search path for the given suffix, if it's defined.
     833 *
     834 * Results:
     835 *      The searchPath for the desired suffix or NILLST if the suffix isn't
     836 *      defined.
     837 *
     838 * Side Effects:
     839 *      None
    838840 *-----------------------------------------------------------------------
    839841 */
    840842Lst
    841843Suff_GetPath (sname)
    842     char          *sname;
    843 {
    844     LstNode       ln;
    845     Suff          *s;
     844    char          *sname;
     845{
     846    LstNode       ln;
     847    Suff          *s;
    846848
    847849    ln = Lst_Find (sufflist, (ClientData)sname, SuffSuffHasNameP);
    848850    if (ln == NILLNODE) {
    849         return (NILLST);
     851        return (NILLST);
    850852    } else {
    851         s = (Suff *) Lst_Datum (ln);
    852         return (s->searchPath);
     853        s = (Suff *) Lst_Datum (ln);
     854        return (s->searchPath);
    853855    }
    854856}
     
    857859 *-----------------------------------------------------------------------
    858860 * Suff_DoPaths --
    859  *      Extend the search paths for all suffixes to include the default
    860  *      search path.
    861  *
    862  * Results:
    863  *      None.
    864  *
    865  * Side Effects:
    866  *      The searchPath field of all the suffixes is extended by the
    867  *      directories in dirSearchPath. If paths were specified for the
    868  *      ".h" suffix, the directories are stuffed into a global variable
    869  *      called ".INCLUDES" with each directory preceeded by a -I. The same
    870  *      is done for the ".a" suffix, except the variable is called
    871  *      ".LIBS" and the flag is -L.
     861 *      Extend the search paths for all suffixes to include the default
     862 *      search path.
     863 *
     864 * Results:
     865 *      None.
     866 *
     867 * Side Effects:
     868 *      The searchPath field of all the suffixes is extended by the
     869 *      directories in dirSearchPath. If paths were specified for the
     870 *      ".h" suffix, the directories are stuffed into a global variable
     871 *      called ".INCLUDES" with each directory preceeded by a -I. The same
     872 *      is done for the ".a" suffix, except the variable is called
     873 *      ".LIBS" and the flag is -L.
    872874 *-----------------------------------------------------------------------
    873875 */
     
    875877Suff_DoPaths()
    876878{
    877     register Suff       *s;
    878     register LstNode    ln;
    879     char                *ptr;
    880     Lst                 inIncludes; /* Cumulative .INCLUDES path */
    881     Lst                 inLibs;     /* Cumulative .LIBS path */
     879    register Suff       *s;
     880    register LstNode    ln;
     881    char                *ptr;
     882    Lst                 inIncludes; /* Cumulative .INCLUDES path */
     883    Lst                 inLibs;     /* Cumulative .LIBS path */
    882884
    883885    if (Lst_Open (sufflist) == FAILURE) {
    884         return;
     886        return;
    885887    }
    886888
     
    889891
    890892    while ((ln = Lst_Next (sufflist)) != NILLNODE) {
    891         s = (Suff *) Lst_Datum (ln);
    892         if (!Lst_IsEmpty (s->searchPath)) {
     893        s = (Suff *) Lst_Datum (ln);
     894        if (!Lst_IsEmpty (s->searchPath)) {
    893895#ifdef INCLUDES
    894             if (s->flags & SUFF_INCLUDE) {
    895                 Dir_Concat(inIncludes, s->searchPath);
    896             }
     896            if (s->flags & SUFF_INCLUDE) {
     897                Dir_Concat(inIncludes, s->searchPath);
     898            }
    897899#endif /* INCLUDES */
    898900#ifdef USE_ARCHIVES
    899901#ifdef LIBRARIES
    900             if (s->flags & SUFF_LIBRARY) {
    901                 Dir_Concat(inLibs, s->searchPath);
    902             }
     902            if (s->flags & SUFF_LIBRARY) {
     903                Dir_Concat(inLibs, s->searchPath);
     904            }
    903905#endif /* LIBRARIES */
    904906#endif
    905             Dir_Concat(s->searchPath, dirSearchPath);
    906         } else {
    907             Lst_Destroy (s->searchPath, Dir_Destroy);
    908             s->searchPath = Lst_Duplicate(dirSearchPath, Dir_CopyDir);
    909         }
     907            Dir_Concat(s->searchPath, dirSearchPath);
     908        } else {
     909            Lst_Destroy (s->searchPath, Dir_Destroy);
     910            s->searchPath = Lst_Duplicate(dirSearchPath, Dir_CopyDir);
     911        }
    910912    }
    911913
     
    924926 *-----------------------------------------------------------------------
    925927 * Suff_AddInclude --
    926  *      Add the given suffix as a type of file which gets included.
    927  *      Called from the parse module when a .INCLUDES line is parsed.
    928  *      The suffix must have already been defined.
    929  *
    930  * Results:
    931  *      None.
    932  *
    933  * Side Effects:
    934  *      The SUFF_INCLUDE bit is set in the suffix's flags field
     928 *      Add the given suffix as a type of file which gets included.
     929 *      Called from the parse module when a .INCLUDES line is parsed.
     930 *      The suffix must have already been defined.
     931 *
     932 * Results:
     933 *      None.
     934 *
     935 * Side Effects:
     936 *      The SUFF_INCLUDE bit is set in the suffix's flags field
    935937 *
    936938 *-----------------------------------------------------------------------
     
    938940void
    939941Suff_AddInclude (sname)
    940     char          *sname;     /* Name of suffix to mark */
    941 {
    942     LstNode       ln;
    943     Suff          *s;
     942    char          *sname;     /* Name of suffix to mark */
     943{
     944    LstNode       ln;
     945    Suff          *s;
    944946
    945947    ln = Lst_Find (sufflist, (ClientData)sname, SuffSuffHasNameP);
    946948    if (ln != NILLNODE) {
    947         s = (Suff *) Lst_Datum (ln);
    948         s->flags |= SUFF_INCLUDE;
     949        s = (Suff *) Lst_Datum (ln);
     950        s->flags |= SUFF_INCLUDE;
    949951    }
    950952}
     
    954956 *-----------------------------------------------------------------------
    955957 * Suff_AddLib --
    956  *      Add the given suffix as a type of file which is a library.
    957  *      Called from the parse module when parsing a .LIBS line. The
    958  *      suffix must have been defined via .SUFFIXES before this is
    959  *      called.
    960  *
    961  * Results:
    962  *      None.
    963  *
    964  * Side Effects:
    965  *      The SUFF_LIBRARY bit is set in the suffix's flags field
     958 *      Add the given suffix as a type of file which is a library.
     959 *      Called from the parse module when parsing a .LIBS line. The
     960 *      suffix must have been defined via .SUFFIXES before this is
     961 *      called.
     962 *
     963 * Results:
     964 *      None.
     965 *
     966 * Side Effects:
     967 *      The SUFF_LIBRARY bit is set in the suffix's flags field
    966968 *
    967969 *-----------------------------------------------------------------------
     
    969971void
    970972Suff_AddLib (sname)
    971     char          *sname;     /* Name of suffix to mark */
    972 {
    973     LstNode       ln;
    974     Suff          *s;
     973    char          *sname;     /* Name of suffix to mark */
     974{
     975    LstNode       ln;
     976    Suff          *s;
    975977
    976978    ln = Lst_Find (sufflist, (ClientData)sname, SuffSuffHasNameP);
    977979    if (ln != NILLNODE) {
    978         s = (Suff *) Lst_Datum (ln);
    979         s->flags |= SUFF_LIBRARY;
     980        s = (Suff *) Lst_Datum (ln);
     981        s->flags |= SUFF_LIBRARY;
    980982    }
    981983}
    982984#endif /* USE_ARCHIVES */
    983985
    984           /********** Implicit Source Search Functions *********/
     986          /********** Implicit Source Search Functions *********/
    985987
    986988/*-
    987989 *-----------------------------------------------------------------------
    988990 * SuffAddSrc  --
    989  *      Add a suffix as a Src structure to the given list with its parent
    990  *      being the given Src structure. If the suffix is the null suffix,
    991  *      the prefix is used unaltered as the file name in the Src structure.
    992  *
    993  * Results:
    994  *      always returns 0
    995  *
    996  * Side Effects:
    997  *      A Src structure is created and tacked onto the end of the list
     991 *      Add a suffix as a Src structure to the given list with its parent
     992 *      being the given Src structure. If the suffix is the null suffix,
     993 *      the prefix is used unaltered as the file name in the Src structure.
     994 *
     995 * Results:
     996 *      always returns 0
     997 *
     998 * Side Effects:
     999 *      A Src structure is created and tacked onto the end of the list
    9981000 *-----------------------------------------------------------------------
    9991001 */
    10001002static int
    10011003SuffAddSrc (sp, lsp)
    1002     ClientData  sp;         /* suffix for which to create a Src structure */
    1003     ClientData  lsp;        /* list and parent for the new Src */
    1004 {
    1005     Suff        *s = (Suff *) sp;
     1004    ClientData  sp;         /* suffix for which to create a Src structure */
     1005    ClientData  lsp;        /* list and parent for the new Src */
     1006{
     1007    Suff        *s = (Suff *) sp;
    10061008    LstSrc      *ls = (LstSrc *) lsp;
    1007     Src         *s2;        /* new Src structure */
    1008     Src         *targ;      /* Target structure */
     1009    Src         *s2;        /* new Src structure */
     1010    Src         *targ;      /* Target structure */
    10091011
    10101012    targ = ls->s;
    10111013
    10121014    if ((s->flags & SUFF_NULL) && (*s->name != '\0')) {
    1013         /*
    1014         * If the suffix has been marked as the NULL suffix, also create a Src
    1015         * structure for a file with no suffix attached. Two birds, and all
    1016         * that...
    1017         */
    1018         s2 = (Src *) emalloc (sizeof (Src));
    1019         s2->file =      estrdup(targ->pref);
    1020         s2->pref =      targ->pref;
    1021         s2->parent =    targ;
    1022         s2->node =      NILGNODE;
    1023         s2->suff =      s;
    1024         s->refCount++;
    1025         s2->children =  0;
    1026         targ->children += 1;
    1027         (void)Lst_AtEnd (ls->l, (ClientData)s2);
     1015        /*
     1016        * If the suffix has been marked as the NULL suffix, also create a Src
     1017        * structure for a file with no suffix attached. Two birds, and all
     1018        * that...
     1019        */
     1020        s2 = (Src *) emalloc (sizeof (Src));
     1021        s2->file =      estrdup(targ->pref);
     1022        s2->pref =      targ->pref;
     1023        s2->parent =    targ;
     1024        s2->node =      NILGNODE;
     1025        s2->suff =      s;
     1026        s->refCount++;
     1027        s2->children =  0;
     1028        targ->children += 1;
     1029        (void)Lst_AtEnd (ls->l, (ClientData)s2);
    10281030#ifdef DEBUG_SRC
    1029         s2->cp = Lst_Init(FALSE);
    1030         Lst_AtEnd(targ->cp, (ClientData) s2);
    1031         printf("1 add %x %x to %x:", targ, s2, ls->l);
    1032         Lst_ForEach(ls->l, PrintAddr, (ClientData) 0);
    1033         printf("\n");
     1031        s2->cp = Lst_Init(FALSE);
     1032        Lst_AtEnd(targ->cp, (ClientData) s2);
     1033        printf("1 add %x %x to %x:", targ, s2, ls->l);
     1034        Lst_ForEach(ls->l, PrintAddr, (ClientData) 0);
     1035        printf("\n");
    10341036#endif
    10351037    }
    10361038    s2 = (Src *) emalloc (sizeof (Src));
    1037     s2->file =      str_concat (targ->pref, s->name, 0);
    1038     s2->pref =      targ->pref;
     1039    s2->file =      str_concat (targ->pref, s->name, 0);
     1040    s2->pref =      targ->pref;
    10391041    s2->parent =    targ;
    1040     s2->node =      NILGNODE;
    1041     s2->suff =      s;
     1042    s2->node =      NILGNODE;
     1043    s2->suff =      s;
    10421044    s->refCount++;
    10431045    s2->children =  0;
     
    10581060 *-----------------------------------------------------------------------
    10591061 * SuffAddLevel  --
    1060  *      Add all the children of targ as Src structures to the given list
    1061  *
    1062  * Results:
    1063  *      None
    1064  *
    1065  * Side Effects:
    1066  *      Lots of structures are created and added to the list
     1062 *      Add all the children of targ as Src structures to the given list
     1063 *
     1064 * Results:
     1065 *      None
     1066 *
     1067 * Side Effects:
     1068 *      Lots of structures are created and added to the list
    10671069 *-----------------------------------------------------------------------
    10681070 */
    10691071static void
    10701072SuffAddLevel (l, targ)
    1071     Lst            l;           /* list to which to add the new level */
    1072     Src            *targ;       /* Src structure to use as the parent */
     1073    Lst            l;           /* list to which to add the new level */
     1074    Src            *targ;       /* Src structure to use as the parent */
    10731075{
    10741076    LstSrc         ls;
     
    10831085 *----------------------------------------------------------------------
    10841086 * SuffRemoveSrc --
    1085  *      Free all src structures in list that don't have a reference count
    1086  *
    1087  * Results:
    1088  *      Ture if an src was removed
    1089  *
    1090  * Side Effects:
    1091  *      The memory is efree'd.
     1087 *      Free all src structures in list that don't have a reference count
     1088 *
     1089 * Results:
     1090 *      Ture if an src was removed
     1091 *
     1092 * Side Effects:
     1093 *      The memory is efree'd.
    10921094 *----------------------------------------------------------------------
    10931095 */
     
    11011103
    11021104    if (Lst_Open (l) == FAILURE) {
    1103         return 0;
     1105        return 0;
    11041106    }
    11051107#ifdef DEBUG_SRC
     
    11111113
    11121114    while ((ln = Lst_Next (l)) != NILLNODE) {
    1113         s = (Src *) Lst_Datum (ln);
    1114         if (s->children == 0) {
    1115             efree ((Address)s->file);
    1116             if (!s->parent)
    1117                 efree((Address)s->pref);
    1118             else {
     1115        s = (Src *) Lst_Datum (ln);
     1116        if (s->children == 0) {
     1117            efree ((Address)s->file);
     1118            if (!s->parent)
     1119                efree((Address)s->pref);
     1120            else {
    11191121#ifdef DEBUG_SRC
    1120                 LstNode ln = Lst_Member(s->parent->cp, (ClientData)s);
    1121                 if (ln != NILLNODE)
    1122                     Lst_Remove(s->parent->cp, ln);
     1122                LstNode ln = Lst_Member(s->parent->cp, (ClientData)s);
     1123                if (ln != NILLNODE)
     1124                    Lst_Remove(s->parent->cp, ln);
    11231125#endif
    1124                 --s->parent->children;
    1125             }
     1126                --s->parent->children;
     1127            }
    11261128#ifdef DEBUG_SRC
    1127             printf("efree: [l=%x] p=%x %d\n", l, s, s->children);
    1128             Lst_Destroy(s->cp, NOFREE);
     1129            printf("efree: [l=%x] p=%x %d\n", l, s, s->children);
     1130            Lst_Destroy(s->cp, NOFREE);
    11291131#endif
    1130             Lst_Remove(l, ln);
    1131             efree ((Address)s);
    1132             t |= 1;
    1133             Lst_Close(l);
    1134             return TRUE;
    1135         }
     1132            Lst_Remove(l, ln);
     1133            efree ((Address)s);
     1134            t |= 1;
     1135            Lst_Close(l);
     1136            return TRUE;
     1137        }
    11361138#ifdef DEBUG_SRC
    1137         else {
    1138             printf("keep: [l=%x] p=%x %d: ", l, s, s->children);
    1139             Lst_ForEach(s->cp, PrintAddr, (ClientData) 0);
    1140             printf("\n");
    1141         }
     1139        else {
     1140            printf("keep: [l=%x] p=%x %d: ", l, s, s->children);
     1141            Lst_ForEach(s->cp, PrintAddr, (ClientData) 0);
     1142            printf("\n");
     1143        }
    11421144#endif
    11431145    }
     
    11511153 *-----------------------------------------------------------------------
    11521154 * SuffFindThem --
    1153  *      Find the first existing file/target in the list srcs
    1154  *
    1155  * Results:
    1156  *      The lowest structure in the chain of transformations
    1157  *
    1158  * Side Effects:
    1159  *      None
     1155 *      Find the first existing file/target in the list srcs
     1156 *
     1157 * Results:
     1158 *      The lowest structure in the chain of transformations
     1159 *
     1160 * Side Effects:
     1161 *      None
    11601162 *-----------------------------------------------------------------------
    11611163 */
    11621164static Src *
    11631165SuffFindThem (srcs, slst)
    1164     Lst            srcs;        /* list of Src structures to search through */
    1165     Lst            slst;
    1166 {
    1167     Src            *s;          /* current Src */
    1168     Src            *rs;         /* returned Src */
    1169     char           *ptr;
     1166    Lst            srcs;        /* list of Src structures to search through */
     1167    Lst            slst;
     1168{
     1169    Src            *s;          /* current Src */
     1170    Src            *rs;         /* returned Src */
     1171    char           *ptr;
    11701172
    11711173    rs = (Src *) NULL;
    11721174
    11731175    while (!Lst_IsEmpty (srcs)) {
    1174         s = (Src *) Lst_DeQueue (srcs);
    1175 
    1176         if (DEBUG(SUFF)) {
    1177             printf ("\ttrying %s...", s->file);
    1178         }
    1179 
    1180         /*
    1181         * A file is considered to exist if either a node exists in the
    1182         * graph for it or the file actually exists.
    1183         */
    1184         if (Targ_FindNode(s->file, TARG_NOCREATE) != NILGNODE) {
     1176        s = (Src *) Lst_DeQueue (srcs);
     1177
     1178        if (DEBUG(SUFF)) {
     1179            printf ("\ttrying %s...", s->file);
     1180        }
     1181
     1182        /*
     1183        * A file is considered to exist if either a node exists in the
     1184        * graph for it or the file actually exists.
     1185        */
     1186        if (Targ_FindNode(s->file, TARG_NOCREATE) != NILGNODE) {
    11851187#ifdef DEBUG_SRC
    1186             printf("remove %x from %x\n", s, srcs);
     1188            printf("remove %x from %x\n", s, srcs);
    11871189#endif
    1188             rs = s;
    1189             break;
    1190         }
    1191 
    1192         if ((ptr = Dir_FindFile (s->file, s->suff->searchPath)) != NULL) {
    1193             rs = s;
     1190            rs = s;
     1191            break;
     1192        }
     1193
     1194        if ((ptr = Dir_FindFile (s->file, s->suff->searchPath)) != NULL) {
     1195            rs = s;
    11941196#ifdef DEBUG_SRC
    1195             printf("remove %x from %x\n", s, srcs);
     1197            printf("remove %x from %x\n", s, srcs);
    11961198#endif
    1197             efree(ptr);
    1198             break;
    1199         }
    1200 
    1201         if (DEBUG(SUFF)) {
    1202             printf ("not there\n");
    1203         }
    1204 
    1205         SuffAddLevel (srcs, s);
    1206         Lst_AtEnd(slst, (ClientData) s);
     1199            efree(ptr);
     1200            break;
     1201        }
     1202
     1203        if (DEBUG(SUFF)) {
     1204            printf ("not there\n");
     1205        }
     1206
     1207        SuffAddLevel (srcs, s);
     1208        Lst_AtEnd(slst, (ClientData) s);
    12071209    }
    12081210
    12091211    if (DEBUG(SUFF) && rs) {
    1210         printf ("got it\n");
     1212        printf ("got it\n");
    12111213    }
    12121214    return (rs);
     
    12161218 *-----------------------------------------------------------------------
    12171219 * SuffFindCmds --
    1218  *      See if any of the children of the target in the Src structure is
    1219  *      one from which the target can be transformed. If there is one,
    1220  *      a Src structure is put together for it and returned.
    1221  *
    1222  * Results:
    1223  *      The Src structure of the "winning" child, or NIL if no such beast.
    1224  *
    1225  * Side Effects:
    1226  *      A Src structure may be allocated.
     1220 *      See if any of the children of the target in the Src structure is
     1221 *      one from which the target can be transformed. If there is one,
     1222 *      a Src structure is put together for it and returned.
     1223 *
     1224 * Results:
     1225 *      The Src structure of the "winning" child, or NIL if no such beast.
     1226 *
     1227 * Side Effects:
     1228 *      A Src structure may be allocated.
    12271229 *
    12281230 *-----------------------------------------------------------------------
     
    12301232static Src *
    12311233SuffFindCmds (targ, slst)
    1232     Src         *targ;  /* Src structure to play with */
    1233     Lst         slst;
    1234 {
    1235     LstNode             ln;     /* General-purpose list node */
    1236     register GNode      *t,     /* Target GNode */
    1237                         *s;     /* Source GNode */
    1238     int                 prefLen;/* The length of the defined prefix */
    1239     Suff                *suff;  /* Suffix on matching beastie */
    1240     Src                 *ret;   /* Return value */
    1241     char                *cp;
     1234    Src         *targ;  /* Src structure to play with */
     1235    Lst         slst;
     1236{
     1237    LstNode             ln;     /* General-purpose list node */
     1238    register GNode      *t,     /* Target GNode */
     1239                        *s;     /* Source GNode */
     1240    int                 prefLen;/* The length of the defined prefix */
     1241    Suff                *suff;  /* Suffix on matching beastie */
     1242    Src                 *ret;   /* Return value */
     1243    char                *cp;
    12421244
    12431245    t = targ->node;
     
    12461248
    12471249    while ((ln = Lst_Next (t->children)) != NILLNODE) {
    1248         s = (GNode *)Lst_Datum (ln);
    1249 
    1250         cp = strrchr (s->name, '/');
    1251         if (cp == (char *)NULL) {
    1252             cp = s->name;
    1253         } else {
    1254             cp++;
    1255         }
    1256         if (strncmp (cp, targ->pref, prefLen) == 0) {
    1257             /*
    1258              * The node matches the prefix ok, see if it has a known
    1259              * suffix.
    1260              */
    1261             ln = Lst_Find (sufflist, (ClientData)&cp[prefLen],
    1262                            SuffSuffHasNameP);
    1263             if (ln != NILLNODE) {
    1264                 /*
    1265                 * It even has a known suffix, see if there's a transformation
    1266                 * defined between the node's suffix and the target's suffix.
    1267                 *
    1268                 * XXX: Handle multi-stage transformations here, too.
    1269                 */
    1270                 suff = (Suff *)Lst_Datum (ln);
    1271 
    1272                 if (Lst_Member (suff->parents,
    1273                                 (ClientData)targ->suff) != NILLNODE)
    1274                 {
    1275                     /*
    1276                      * Hot Damn! Create a new Src structure to describe
    1277                      * this transformation (making sure to duplicate the
    1278                      * source node's name so Suff_FindDeps can efree it
    1279                      * again (ick)), and return the new structure.
    1280                      */
    1281                     ret = (Src *)emalloc (sizeof (Src));
    1282                     ret->file = estrdup(s->name);
    1283                     ret->pref = targ->pref;
    1284                     ret->suff = suff;
    1285                     suff->refCount++;
    1286                     ret->parent = targ;
    1287                     ret->node = s;
    1288                     ret->children = 0;
    1289                     targ->children += 1;
     1250        s = (GNode *)Lst_Datum (ln);
     1251
     1252        cp = strrchr (s->name, '/');
     1253        if (cp == (char *)NULL) {
     1254            cp = s->name;
     1255        } else {
     1256            cp++;
     1257        }
     1258        if (strncmp (cp, targ->pref, prefLen) == 0) {
     1259            /*
     1260             * The node matches the prefix ok, see if it has a known
     1261             * suffix.
     1262             */
     1263            ln = Lst_Find (sufflist, (ClientData)&cp[prefLen],
     1264                           SuffSuffHasNameP);
     1265            if (ln != NILLNODE) {
     1266                /*
     1267                * It even has a known suffix, see if there's a transformation
     1268                * defined between the node's suffix and the target's suffix.
     1269                *
     1270                * XXX: Handle multi-stage transformations here, too.
     1271                */
     1272                suff = (Suff *)Lst_Datum (ln);
     1273
     1274                if (Lst_Member (suff->parents,
     1275                                (ClientData)targ->suff) != NILLNODE)
     1276                {
     1277                    /*
     1278                     * Hot Damn! Create a new Src structure to describe
     1279                     * this transformation (making sure to duplicate the
     1280                     * source node's name so Suff_FindDeps can efree it
     1281                     * again (ick)), and return the new structure.
     1282                     */
     1283                    ret = (Src *)emalloc (sizeof (Src));
     1284                    ret->file = estrdup(s->name);
     1285                    ret->pref = targ->pref;
     1286                    ret->suff = suff;
     1287                    suff->refCount++;
     1288                    ret->parent = targ;
     1289                    ret->node = s;
     1290                    ret->children = 0;
     1291                    targ->children += 1;
    12901292#ifdef DEBUG_SRC
    1291                     ret->cp = Lst_Init(FALSE);
    1292                     printf("3 add %x %x\n", targ, ret);
    1293                     Lst_AtEnd(targ->cp, (ClientData) ret);
     1293                    ret->cp = Lst_Init(FALSE);
     1294                    printf("3 add %x %x\n", targ, ret);
     1295                    Lst_AtEnd(targ->cp, (ClientData) ret);
    12941296#endif
    1295                     Lst_AtEnd(slst, (ClientData) ret);
    1296                     if (DEBUG(SUFF)) {
    1297                         printf ("\tusing existing source %s\n", s->name);
    1298                     }
    1299                     return (ret);
    1300                 }
    1301             }
    1302         }
     1297                    Lst_AtEnd(slst, (ClientData) ret);
     1298                    if (DEBUG(SUFF)) {
     1299                        printf ("\tusing existing source %s\n", s->name);
     1300                    }
     1301                    return (ret);
     1302                }
     1303            }
     1304        }
    13031305    }
    13041306    Lst_Close (t->children);
     
    13091311 *-----------------------------------------------------------------------
    13101312 * SuffExpandChildren --
    1311  *      Expand the names of any children of a given node that contain
    1312  *      variable invocations or file wildcards into actual targets.
    1313  *
    1314  * Results:
    1315  *      === 0 (continue)
    1316  *
    1317  * Side Effects:
    1318  *      The expanded node is removed from the parent's list of children,
    1319  *      and the parent's unmade counter is decremented, but other nodes
    1320  *      may be added.
     1313 *      Expand the names of any children of a given node that contain
     1314 *      variable invocations or file wildcards into actual targets.
     1315 *
     1316 * Results:
     1317 *      === 0 (continue)
     1318 *
     1319 * Side Effects:
     1320 *      The expanded node is removed from the parent's list of children,
     1321 *      and the parent's unmade counter is decremented, but other nodes
     1322 *      may be added.
    13211323 *
    13221324 *-----------------------------------------------------------------------
     
    13241326static int
    13251327SuffExpandChildren(cgnp, pgnp)
    1326     ClientData  cgnp;       /* Child to examine */
    1327     ClientData  pgnp;       /* Parent node being processed */
    1328 {
    1329     GNode       *cgn = (GNode *) cgnp;
    1330     GNode       *pgn = (GNode *) pgnp;
    1331     GNode       *gn;        /* New source 8) */
    1332     LstNode     prevLN;    /* Node after which new source should be put */
    1333     LstNode     ln;         /* List element for old source */
    1334     char        *cp;        /* Expanded value */
     1328    ClientData  cgnp;       /* Child to examine */
     1329    ClientData  pgnp;       /* Parent node being processed */
     1330{
     1331    GNode       *cgn = (GNode *) cgnp;
     1332    GNode       *pgn = (GNode *) pgnp;
     1333    GNode       *gn;        /* New source 8) */
     1334    LstNode     prevLN;    /* Node after which new source should be put */
     1335    LstNode     ln;         /* List element for old source */
     1336    char        *cp;        /* Expanded value */
    13351337
    13361338    /*
     
    13471349     */
    13481350    if (strchr(cgn->name, '$') != (char *)NULL) {
    1349         if (DEBUG(SUFF)) {
    1350             printf("Expanding \"%s\"...", cgn->name);
    1351         }
    1352         cp = Var_Subst(NULL, cgn->name, pgn, TRUE);
    1353 
    1354         if (cp != (char *)NULL) {
    1355             Lst     members = Lst_Init(FALSE);
     1351        if (DEBUG(SUFF)) {
     1352            printf("Expanding \"%s\"...", cgn->name);
     1353        }
     1354        cp = Var_Subst(NULL, cgn->name, pgn, TRUE);
     1355
     1356        if (cp != (char *)NULL) {
     1357            Lst     members = Lst_Init(FALSE);
    13561358
    13571359#ifdef USE_ARCHIVES
    1358             if (cgn->type & OP_ARCHV) {
    1359                 /*
    1360                 * Node was an archive(member) target, so we want to call
    1361                 * on the Arch module to find the nodes for us, expanding
    1362                 * variables in the parent's context.
    1363                 */
    1364                 char    *sacrifice = cp;
    1365 
    1366                 (void)Arch_ParseArchive(&sacrifice, members, pgn);
    1367             } else
     1360            if (cgn->type & OP_ARCHV) {
     1361                /*
     1362                * Node was an archive(member) target, so we want to call
     1363                * on the Arch module to find the nodes for us, expanding
     1364                * variables in the parent's context.
     1365                */
     1366                char    *sacrifice = cp;
     1367
     1368                (void)Arch_ParseArchive(&sacrifice, members, pgn);
     1369            } else
    13681370#endif
    13691371            {
    1370                 /*
    1371                 * Break the result into a vector of strings whose nodes
    1372                 * we can find, then add those nodes to the members list.
    1373                 * Unfortunately, we can't use brk_string b/c it
    1374                 * doesn't understand about variable specifications with
    1375                 * spaces in them...
    1376                 */
    1377                 char        *start;
    1378                 char        *initcp = cp;   /* For freeing... */
    1379 
    1380                 for (start = cp; *start == ' ' || *start == '\t'; start++)
    1381                     continue;
    1382                 for (cp = start; *cp != '\0'; cp++) {
    1383                     if (*cp == ' ' || *cp == '\t') {
    1384                         /*
    1385                         * White-space -- terminate element, find the node,
    1386                         * add it, skip any further spaces.
    1387                         */
    1388                         *cp++ = '\0';
    1389                         gn = Targ_FindNode(start, TARG_CREATE);
    1390                         (void)Lst_AtEnd(members, (ClientData)gn);
    1391                         while (*cp == ' ' || *cp == '\t') {
    1392                             cp++;
    1393                         }
    1394                         /*
    1395                         * Adjust cp for increment at start of loop, but
    1396                         * set start to first non-space.
    1397                         */
    1398                         start = cp--;
    1399                     } else if (*cp == '$') {
    1400                         /*
    1401                         * Start of a variable spec -- contact variable module
    1402                         * to find the end so we can skip over it.
    1403                         */
    1404                         char    *junk;
    1405                         int     len;
    1406                         Boolean doFree;
    1407 
    1408                         junk = Var_Parse(cp, pgn, TRUE, &len, &doFree);
    1409                         if (junk != var_Error) {
    1410                             cp += len - 1;
    1411                         }
    1412 
    1413                         if (doFree) {
    1414                             efree(junk);
    1415                         }
    1416                     } else if (*cp == '\\' && *cp != '\0') {
    1417                         /*
    1418                         * Escaped something -- skip over it
    1419                         */
    1420                         cp++;
    1421                     }
    1422                 }
    1423 
    1424                 if (cp != start) {
    1425                     /*
    1426                      * Stuff left over -- add it to the list too
    1427                      */
    1428                     gn = Targ_FindNode(start, TARG_CREATE);
    1429                     (void)Lst_AtEnd(members, (ClientData)gn);
    1430                 }
    1431                 /*
    1432                 * Point cp back at the beginning again so the variable value
    1433                 * can be freed.
    1434                 */
    1435                 cp = initcp;
    1436             }
    1437             /*
    1438              * Add all elements of the members list to the parent node.
    1439              */
    1440             while(!Lst_IsEmpty(members)) {
    1441                 gn = (GNode *)Lst_DeQueue(members);
    1442 
    1443                 if (DEBUG(SUFF)) {
    1444                     printf("%s...", gn->name);
    1445                 }
    1446                 if (Lst_Member(pgn->children, (ClientData)gn) == NILLNODE) {
    1447                     (void)Lst_Append(pgn->children, prevLN, (ClientData)gn);
    1448                     prevLN = Lst_Succ(prevLN);
    1449                     (void)Lst_AtEnd(gn->parents, (ClientData)pgn);
    1450                     pgn->unmade++;
    1451                 }
    1452             }
    1453             Lst_Destroy(members, NOFREE);
    1454             /*
    1455              * Free the result
    1456              */
    1457             efree((char *)cp);
    1458         }
    1459         /*
    1460         * Now the source is expanded, remove it from the list of children to
    1461         * keep it from being processed.
    1462         */
    1463         ln = Lst_Member(pgn->children, (ClientData)cgn);
    1464         pgn->unmade--;
    1465         Lst_Remove(pgn->children, ln);
    1466         if (DEBUG(SUFF)) {
    1467             printf("\n");
    1468         }
     1372                /*
     1373                * Break the result into a vector of strings whose nodes
     1374                * we can find, then add those nodes to the members list.
     1375                * Unfortunately, we can't use brk_string b/c it
     1376                * doesn't understand about variable specifications with
     1377                * spaces in them...
     1378                */
     1379                char        *start;
     1380                char        *initcp = cp;   /* For freeing... */
     1381
     1382                for (start = cp; *start == ' ' || *start == '\t'; start++)
     1383                    continue;
     1384                for (cp = start; *cp != '\0'; cp++) {
     1385                    if (*cp == ' ' || *cp == '\t') {
     1386                        /*
     1387                        * White-space -- terminate element, find the node,
     1388                        * add it, skip any further spaces.
     1389                        */
     1390                        *cp++ = '\0';
     1391                        gn = Targ_FindNode(start, TARG_CREATE);
     1392                        (void)Lst_AtEnd(members, (ClientData)gn);
     1393                        while (*cp == ' ' || *cp == '\t') {
     1394                            cp++;
     1395                        }
     1396                        /*
     1397                        * Adjust cp for increment at start of loop, but
     1398                        * set start to first non-space.
     1399                        */
     1400                        start = cp--;
     1401                    } else if (*cp == '$') {
     1402                        /*
     1403                        * Start of a variable spec -- contact variable module
     1404                        * to find the end so we can skip over it.
     1405                        */
     1406                        char    *junk;
     1407                        int     len;
     1408                        Boolean doFree;
     1409
     1410                        junk = Var_Parse(cp, pgn, TRUE, &len, &doFree);
     1411                        if (junk != var_Error) {
     1412                            cp += len - 1;
     1413                        }
     1414
     1415                        if (doFree) {
     1416                            efree(junk);
     1417                        }
     1418                    } else if (*cp == '\\' && *cp != '\0') {
     1419                        /*
     1420                        * Escaped something -- skip over it
     1421                        */
     1422                        cp++;
     1423                    }
     1424                }
     1425
     1426                if (cp != start) {
     1427                    /*
     1428                     * Stuff left over -- add it to the list too
     1429                     */
     1430                    gn = Targ_FindNode(start, TARG_CREATE);
     1431                    (void)Lst_AtEnd(members, (ClientData)gn);
     1432                }
     1433                /*
     1434                * Point cp back at the beginning again so the variable value
     1435                * can be freed.
     1436                */
     1437                cp = initcp;
     1438            }
     1439            /*
     1440             * Add all elements of the members list to the parent node.
     1441             */
     1442            while(!Lst_IsEmpty(members)) {
     1443                gn = (GNode *)Lst_DeQueue(members);
     1444
     1445                if (DEBUG(SUFF)) {
     1446                    printf("%s...", gn->name);
     1447                }
     1448                if (Lst_Member(pgn->children, (ClientData)gn) == NILLNODE) {
     1449                    (void)Lst_Append(pgn->children, prevLN, (ClientData)gn);
     1450                    prevLN = Lst_Succ(prevLN);
     1451                    (void)Lst_AtEnd(gn->parents, (ClientData)pgn);
     1452                    pgn->unmade++;
     1453                }
     1454            }
     1455            Lst_Destroy(members, NOFREE);
     1456            /*
     1457             * Free the result
     1458             */
     1459            efree((char *)cp);
     1460        }
     1461        /*
     1462        * Now the source is expanded, remove it from the list of children to
     1463        * keep it from being processed.
     1464        */
     1465        ln = Lst_Member(pgn->children, (ClientData)cgn);
     1466        pgn->unmade--;
     1467        Lst_Remove(pgn->children, ln);
     1468        if (DEBUG(SUFF)) {
     1469            printf("\n");
     1470        }
    14691471    } else if (Dir_HasWildcards(cgn->name)) {
    1470         Lst     exp;        /* List of expansions */
    1471         Lst     path;       /* Search path along which to expand */
    1472 
    1473         /*
    1474         * Find a path along which to expand the word.
    1475         *
    1476         * If the word has a known suffix, use that path.
    1477         * If it has no known suffix and we're allowed to use the null
    1478         *   suffix, use its path.
    1479         * Else use the default system search path.
    1480         */
    1481         cp = cgn->name + strlen(cgn->name);
    1482         ln = Lst_Find(sufflist, (ClientData)cp, SuffSuffIsSuffixP);
    1483 
    1484         if (DEBUG(SUFF)) {
    1485             printf("Wildcard expanding \"%s\"...", cgn->name);
    1486         }
    1487 
    1488         if (ln != NILLNODE) {
    1489             Suff    *s = (Suff *)Lst_Datum(ln);
    1490 
    1491             if (DEBUG(SUFF)) {
    1492                 printf("suffix is \"%s\"...", s->name);
    1493             }
    1494             path = s->searchPath;
    1495         } else {
    1496             /*
    1497              * Use default search path
    1498              */
    1499             path = dirSearchPath;
    1500         }
    1501 
    1502         /*
    1503         * Expand the word along the chosen path
    1504         */
    1505         exp = Lst_Init(FALSE);
    1506         Dir_Expand(cgn->name, path, exp);
    1507 
    1508         while (!Lst_IsEmpty(exp)) {
    1509             /*
    1510              * Fetch next expansion off the list and find its GNode
    1511              */
    1512             cp = (char *)Lst_DeQueue(exp);
    1513 
    1514             if (DEBUG(SUFF)) {
    1515                 printf("%s...", cp);
    1516             }
    1517             gn = Targ_FindNode(cp, TARG_CREATE);
    1518 
    1519             /*
    1520              * If gn isn't already a child of the parent, make it so and
    1521              * up the parent's count of unmade children.
    1522              */
    1523             if (Lst_Member(pgn->children, (ClientData)gn) == NILLNODE) {
    1524                 (void)Lst_Append(pgn->children, prevLN, (ClientData)gn);
    1525                 prevLN = Lst_Succ(prevLN);
    1526                 (void)Lst_AtEnd(gn->parents, (ClientData)pgn);
    1527                 pgn->unmade++;
    1528             }
    1529         }
    1530 
    1531         /*
    1532         * Nuke what's left of the list
    1533         */
    1534         Lst_Destroy(exp, NOFREE);
    1535 
    1536         /*
    1537         * Now the source is expanded, remove it from the list of children to
    1538         * keep it from being processed.
    1539         */
    1540         ln = Lst_Member(pgn->children, (ClientData)cgn);
    1541         pgn->unmade--;
    1542         Lst_Remove(pgn->children, ln);
    1543         if (DEBUG(SUFF)) {
    1544             printf("\n");
    1545         }
     1472        Lst     exp;        /* List of expansions */
     1473        Lst     path;       /* Search path along which to expand */
     1474
     1475        /*
     1476        * Find a path along which to expand the word.
     1477        *
     1478        * If the word has a known suffix, use that path.
     1479        * If it has no known suffix and we're allowed to use the null
     1480        *   suffix, use its path.
     1481        * Else use the default system search path.
     1482        */
     1483        cp = cgn->name + strlen(cgn->name);
     1484        ln = Lst_Find(sufflist, (ClientData)cp, SuffSuffIsSuffixP);
     1485
     1486        if (DEBUG(SUFF)) {
     1487            printf("Wildcard expanding \"%s\"...", cgn->name);
     1488        }
     1489
     1490        if (ln != NILLNODE) {
     1491            Suff    *s = (Suff *)Lst_Datum(ln);
     1492
     1493            if (DEBUG(SUFF)) {
     1494                printf("suffix is \"%s\"...", s->name);
     1495            }
     1496            path = s->searchPath;
     1497        } else {
     1498            /*
     1499             * Use default search path
     1500             */
     1501            path = dirSearchPath;
     1502        }
     1503
     1504        /*
     1505        * Expand the word along the chosen path
     1506        */
     1507        exp = Lst_Init(FALSE);
     1508        Dir_Expand(cgn->name, path, exp);
     1509
     1510        while (!Lst_IsEmpty(exp)) {
     1511            /*
     1512             * Fetch next expansion off the list and find its GNode
     1513             */
     1514            cp = (char *)Lst_DeQueue(exp);
     1515
     1516            if (DEBUG(SUFF)) {
     1517                printf("%s...", cp);
     1518            }
     1519            gn = Targ_FindNode(cp, TARG_CREATE);
     1520
     1521            /*
     1522             * If gn isn't already a child of the parent, make it so and
     1523             * up the parent's count of unmade children.
     1524             */
     1525            if (Lst_Member(pgn->children, (ClientData)gn) == NILLNODE) {
     1526                (void)Lst_Append(pgn->children, prevLN, (ClientData)gn);
     1527                prevLN = Lst_Succ(prevLN);
     1528                (void)Lst_AtEnd(gn->parents, (ClientData)pgn);
     1529                pgn->unmade++;
     1530            }
     1531        }
     1532
     1533        /*
     1534        * Nuke what's left of the list
     1535        */
     1536        Lst_Destroy(exp, NOFREE);
     1537
     1538        /*
     1539        * Now the source is expanded, remove it from the list of children to
     1540        * keep it from being processed.
     1541        */
     1542        ln = Lst_Member(pgn->children, (ClientData)cgn);
     1543        pgn->unmade--;
     1544        Lst_Remove(pgn->children, ln);
     1545        if (DEBUG(SUFF)) {
     1546            printf("\n");
     1547        }
    15461548    }
    15471549
     
    15521554 *-----------------------------------------------------------------------
    15531555 * SuffApplyTransform --
    1554  *      Apply a transformation rule, given the source and target nodes
    1555  *      and suffixes.
    1556  *
    1557  * Results:
    1558  *      TRUE if successful, FALSE if not.
    1559  *
    1560  * Side Effects:
    1561  *      The source and target are linked and the commands from the
    1562  *      transformation are added to the target node's commands list.
    1563  *      All attributes but OP_DEPMASK and OP_TRANSFORM are applied
    1564  *      to the target. The target also inherits all the sources for
    1565  *      the transformation rule.
     1556 *      Apply a transformation rule, given the source and target nodes
     1557 *      and suffixes.
     1558 *
     1559 * Results:
     1560 *      TRUE if successful, FALSE if not.
     1561 *
     1562 * Side Effects:
     1563 *      The source and target are linked and the commands from the
     1564 *      transformation are added to the target node's commands list.
     1565 *      All attributes but OP_DEPMASK and OP_TRANSFORM are applied
     1566 *      to the target. The target also inherits all the sources for
     1567 *      the transformation rule.
    15661568 *
    15671569 *-----------------------------------------------------------------------
     
    15691571static Boolean
    15701572SuffApplyTransform(tGn, sGn, t, s)
    1571     GNode       *tGn;       /* Target node */
    1572     GNode       *sGn;       /* Source node */
    1573     Suff        *t;         /* Target suffix */
    1574     Suff        *s;         /* Source suffix */
    1575 {
    1576     LstNode     ln;         /* General node */
    1577     char        *tname;     /* Name of transformation rule */
    1578     GNode       *gn;        /* Node for same */
     1573    GNode       *tGn;       /* Target node */
     1574    GNode       *sGn;       /* Source node */
     1575    Suff        *t;         /* Target suffix */
     1576    Suff        *s;         /* Source suffix */
     1577{
     1578    LstNode     ln;         /* General node */
     1579    char        *tname;     /* Name of transformation rule */
     1580    GNode       *gn;        /* Node for same */
    15791581
    15801582    if (Lst_Member(tGn->children, (ClientData)sGn) == NILLNODE) {
    1581         /*
    1582         * Not already linked, so form the proper links between the
    1583         * target and source.
    1584         */
    1585         (void)Lst_AtEnd(tGn->children, (ClientData)sGn);
    1586         (void)Lst_AtEnd(sGn->parents, (ClientData)tGn);
    1587         tGn->unmade += 1;
     1583        /*
     1584        * Not already linked, so form the proper links between the
     1585        * target and source.
     1586        */
     1587        (void)Lst_AtEnd(tGn->children, (ClientData)sGn);
     1588        (void)Lst_AtEnd(sGn->parents, (ClientData)tGn);
     1589        tGn->unmade += 1;
    15881590    }
    15891591
    15901592    if ((sGn->type & OP_OPMASK) == OP_DOUBLEDEP) {
    1591         /*
    1592         * When a :: node is used as the implied source of a node, we have
    1593         * to link all its cohorts in as sources as well. Only the initial
    1594         * sGn gets the target in its iParents list, however, as that
    1595         * will be sufficient to get the .IMPSRC variable set for tGn
    1596         */
    1597         for (ln=Lst_First(sGn->cohorts); ln != NILLNODE; ln=Lst_Succ(ln)) {
    1598             gn = (GNode *)Lst_Datum(ln);
    1599 
    1600             if (Lst_Member(tGn->children, (ClientData)gn) == NILLNODE) {
    1601                 /*
    1602                 * Not already linked, so form the proper links between the
    1603                 * target and source.
    1604                 */
    1605                 (void)Lst_AtEnd(tGn->children, (ClientData)gn);
    1606                 (void)Lst_AtEnd(gn->parents, (ClientData)tGn);
    1607                 tGn->unmade += 1;
    1608             }
    1609         }
     1593        /*
     1594        * When a :: node is used as the implied source of a node, we have
     1595        * to link all its cohorts in as sources as well. Only the initial
     1596        * sGn gets the target in its iParents list, however, as that
     1597        * will be sufficient to get the .IMPSRC variable set for tGn
     1598        */
     1599        for (ln=Lst_First(sGn->cohorts); ln != NILLNODE; ln=Lst_Succ(ln)) {
     1600            gn = (GNode *)Lst_Datum(ln);
     1601
     1602            if (Lst_Member(tGn->children, (ClientData)gn) == NILLNODE) {
     1603                /*
     1604                * Not already linked, so form the proper links between the
     1605                * target and source.
     1606                */
     1607                (void)Lst_AtEnd(tGn->children, (ClientData)gn);
     1608                (void)Lst_AtEnd(gn->parents, (ClientData)tGn);
     1609                tGn->unmade += 1;
     1610            }
     1611        }
    16101612    }
    16111613    /*
     
    16171619
    16181620    if (ln == NILLNODE) {
    1619         /*
    1620         * Not really such a transformation rule (can happen when we're
    1621         * called to link an OP_MEMBER and OP_ARCHV node), so return
    1622         * FALSE.
    1623         */
    1624         return(FALSE);
     1621        /*
     1622        * Not really such a transformation rule (can happen when we're
     1623        * called to link an OP_MEMBER and OP_ARCHV node), so return
     1624        * FALSE.
     1625        */
     1626        return(FALSE);
    16251627    }
    16261628
     
    16281630
    16291631    if (DEBUG(SUFF)) {
    1630         printf("\tapplying %s -> %s to \"%s\"\n", s->name, t->name, tGn->name);
     1632        printf("\tapplying %s -> %s to \"%s\"\n", s->name, t->name, tGn->name);
    16311633    }
    16321634
     
    16461648    ln = Lst_Succ(ln);
    16471649    if (ln != NILLNODE) {
    1648         Lst_ForEachFrom(tGn->children, ln,
    1649                         SuffExpandChildren, (ClientData)tGn);
     1650        Lst_ForEachFrom(tGn->children, ln,
     1651                        SuffExpandChildren, (ClientData)tGn);
    16501652    }
    16511653
     
    16641666 *-----------------------------------------------------------------------
    16651667 * SuffFindArchiveDeps --
    1666  *      Locate dependencies for an OP_ARCHV node.
    1667  *
    1668  * Results:
    1669  *      None
    1670  *
    1671  * Side Effects:
    1672  *      Same as Suff_FindDeps
     1668 *      Locate dependencies for an OP_ARCHV node.
     1669 *
     1670 * Results:
     1671 *      None
     1672 *
     1673 * Side Effects:
     1674 *      Same as Suff_FindDeps
    16731675 *
    16741676 *-----------------------------------------------------------------------
     
    16761678static void
    16771679SuffFindArchiveDeps(gn, slst)
    1678     GNode       *gn;        /* Node for which to locate dependencies */
    1679     Lst         slst;
    1680 {
    1681     char        *eoarch;    /* End of archive portion */
    1682     char        *eoname;    /* End of member portion */
    1683     GNode       *mem;       /* Node for member */
    1684     static char *copy[] = { /* Variables to be copied from the member node */
    1685         TARGET,             /* Must be first */
    1686         PREFIX,             /* Must be second */
     1680    GNode       *gn;        /* Node for which to locate dependencies */
     1681    Lst         slst;
     1682{
     1683    char        *eoarch;    /* End of archive portion */
     1684    char        *eoname;    /* End of member portion */
     1685    GNode       *mem;       /* Node for member */
     1686    static char *copy[] = { /* Variables to be copied from the member node */
     1687        TARGET,             /* Must be first */
     1688        PREFIX,             /* Must be second */
    16871689    };
    1688     int         i;          /* Index into copy and vals */
    1689     Suff        *ms;        /* Suffix descriptor for member */
    1690     char        *name;      /* Start of member's name */
     1690    int         i;          /* Index into copy and vals */
     1691    Suff        *ms;        /* Suffix descriptor for member */
     1692    char        *name;      /* Start of member's name */
    16911693
    16921694    /*
     
    16971699    eoname = strchr (eoarch, ')');
    16981700
    1699     *eoname = '\0';       /* Nuke parentheses during suffix search */
    1700     *eoarch = '\0';       /* So a suffix can be found */
     1701    *eoname = '\0';       /* Nuke parentheses during suffix search */
     1702    *eoarch = '\0';       /* So a suffix can be found */
    17011703
    17021704    name = eoarch + 1;
     
    17161718     */
    17171719    if (Lst_Member(gn->children, (ClientData)mem) == NILLNODE) {
    1718         (void)Lst_AtEnd(gn->children, (ClientData)mem);
    1719         (void)Lst_AtEnd(mem->parents, (ClientData)gn);
    1720         gn->unmade += 1;
     1720        (void)Lst_AtEnd(gn->children, (ClientData)mem);
     1721        (void)Lst_AtEnd(mem->parents, (ClientData)gn);
     1722        gn->unmade += 1;
    17211723    }
    17221724
     
    17251727     */
    17261728    for (i = (sizeof(copy)/sizeof(copy[0]))-1; i >= 0; i--) {
    1727         char *p1;
    1728         Var_Set(copy[i], Var_Value(copy[i], mem, &p1), gn);
    1729         efree(p1);
     1729        char *p1;
     1730        Var_Set(copy[i], Var_Value(copy[i], mem, &p1), gn);
     1731        efree(p1);
    17301732
    17311733    }
     
    17331735    ms = mem->suffix;
    17341736    if (ms == NULL) {
    1735         /*
    1736         * Didn't know what it was -- use .NULL suffix if not in make mode
    1737         */
    1738         if (DEBUG(SUFF)) {
    1739             printf("using null suffix\n");
    1740         }
    1741         ms = suffNull;
     1737        /*
     1738        * Didn't know what it was -- use .NULL suffix if not in make mode
     1739        */
     1740        if (DEBUG(SUFF)) {
     1741            printf("using null suffix\n");
     1742        }
     1743        ms = suffNull;
    17421744    }
    17431745
     
    17501752
    17511753    if (ms != NULL) {
    1752         /*
    1753         * Member has a known suffix, so look for a transformation rule from
    1754         * it to a possible suffix of the archive. Rather than searching
    1755         * through the entire list, we just look at suffixes to which the
    1756         * member's suffix may be transformed...
    1757         */
    1758         LstNode     ln;
    1759 
    1760         /*
    1761         * Use first matching suffix...
    1762         */
    1763         ln = Lst_Find(ms->parents, eoarch, SuffSuffIsSuffixP);
    1764 
    1765         if (ln != NILLNODE) {
    1766             /*
    1767              * Got one -- apply it
    1768              */
    1769             if (!SuffApplyTransform(gn, mem, (Suff *)Lst_Datum(ln), ms) &&
    1770                 DEBUG(SUFF))
    1771             {
    1772                 printf("\tNo transformation from %s -> %s\n",
    1773                        ms->name, ((Suff *)Lst_Datum(ln))->name);
    1774             }
    1775         }
     1754        /*
     1755        * Member has a known suffix, so look for a transformation rule from
     1756        * it to a possible suffix of the archive. Rather than searching
     1757        * through the entire list, we just look at suffixes to which the
     1758        * member's suffix may be transformed...
     1759        */
     1760        LstNode     ln;
     1761
     1762        /*
     1763        * Use first matching suffix...
     1764        */
     1765        ln = Lst_Find(ms->parents, eoarch, SuffSuffIsSuffixP);
     1766
     1767        if (ln != NILLNODE) {
     1768            /*
     1769             * Got one -- apply it
     1770             */
     1771            if (!SuffApplyTransform(gn, mem, (Suff *)Lst_Datum(ln), ms) &&
     1772                DEBUG(SUFF))
     1773            {
     1774                printf("\tNo transformation from %s -> %s\n",
     1775                       ms->name, ((Suff *)Lst_Datum(ln))->name);
     1776            }
     1777        }
    17761778    }
    17771779
     
    17881790     */
    17891791    if (OP_NOP(gn->type)) {
    1790         gn->type |= OP_DEPENDS;
     1792        gn->type |= OP_DEPENDS;
    17911793    }
    17921794
     
    18021804 *-----------------------------------------------------------------------
    18031805 * SuffFindNormalDeps --
    1804  *      Locate implicit dependencies for regular targets.
    1805  *
    1806  * Results:
    1807  *      None.
    1808  *
    1809  * Side Effects:
    1810  *      Same as Suff_FindDeps...
     1806 *      Locate implicit dependencies for regular targets.
     1807 *
     1808 * Results:
     1809 *      None.
     1810 *
     1811 * Side Effects:
     1812 *      Same as Suff_FindDeps...
    18111813 *
    18121814 *-----------------------------------------------------------------------
     
    18141816static void
    18151817SuffFindNormalDeps(gn, slst)
    1816     GNode       *gn;        /* Node for which to find sources */
    1817     Lst         slst;
    1818 {
    1819     char        *eoname;    /* End of name */
    1820     char        *sopref;    /* Start of prefix */
    1821     LstNode     ln;         /* Next suffix node to check */
    1822     Lst         srcs;       /* List of sources at which to look */
    1823     Lst         targs;      /* List of targets to which things can be
    1824                              * transformed. They all have the same file,
    1825                              * but different suff and pref fields */
    1826     Src         *bottom;    /* Start of found transformation path */
    1827     Src         *src;       /* General Src pointer */
    1828     char        *pref;      /* Prefix to use */
    1829     Src         *targ;      /* General Src target pointer */
     1818    GNode       *gn;        /* Node for which to find sources */
     1819    Lst         slst;
     1820{
     1821    char        *eoname;    /* End of name */
     1822    char        *sopref;    /* Start of prefix */
     1823    LstNode     ln;         /* Next suffix node to check */
     1824    Lst         srcs;       /* List of sources at which to look */
     1825    Lst         targs;      /* List of targets to which things can be
     1826                             * transformed. They all have the same file,
     1827                             * but different suff and pref fields */
     1828    Src         *bottom;    /* Start of found transformation path */
     1829    Src         *src;       /* General Src pointer */
     1830    char        *pref;      /* Prefix to use */
     1831    Src         *targ;      /* General Src target pointer */
    18301832
    18311833
     
    18611863
    18621864    while (ln != NILLNODE) {
    1863         /*
    1864         * Look for next possible suffix...
    1865         */
    1866         ln = Lst_FindFrom(sufflist, ln, eoname, SuffSuffIsSuffixP);
    1867 
    1868         if (ln != NILLNODE) {
    1869             int     prefLen;        /* Length of the prefix */
    1870             Src     *targ;
    1871 
    1872             /*
    1873              * Allocate a Src structure to which things can be transformed
    1874              */
    1875             targ = (Src *)emalloc(sizeof (Src));
    1876             targ->file = estrdup(gn->name);
    1877             targ->suff = (Suff *)Lst_Datum(ln);
    1878             targ->suff->refCount++;
    1879             targ->node = gn;
    1880             targ->parent = (Src *)NULL;
    1881             targ->children = 0;
     1865        /*
     1866        * Look for next possible suffix...
     1867        */
     1868        ln = Lst_FindFrom(sufflist, ln, eoname, SuffSuffIsSuffixP);
     1869
     1870        if (ln != NILLNODE) {
     1871            int     prefLen;        /* Length of the prefix */
     1872            Src     *targ;
     1873
     1874            /*
     1875             * Allocate a Src structure to which things can be transformed
     1876             */
     1877            targ = (Src *)emalloc(sizeof (Src));
     1878            targ->file = estrdup(gn->name);
     1879            targ->suff = (Suff *)Lst_Datum(ln);
     1880            targ->suff->refCount++;
     1881            targ->node = gn;
     1882            targ->parent = (Src *)NULL;
     1883            targ->children = 0;
    18821884#ifdef DEBUG_SRC
    1883             targ->cp = Lst_Init(FALSE);
     1885            targ->cp = Lst_Init(FALSE);
    18841886#endif
    18851887
    1886             /*
    1887              * Allocate room for the prefix, whose end is found by subtracting
    1888              * the length of the suffix from the end of the name.
    1889              */
    1890             prefLen = (eoname - targ->suff->nameLen) - sopref;
    1891             targ->pref = emalloc(prefLen + 1);
    1892             memcpy(targ->pref, sopref, prefLen);
    1893             targ->pref[prefLen] = '\0';
    1894 
    1895             /*
    1896              * Add nodes from which the target can be made
    1897              */
    1898             SuffAddLevel(srcs, targ);
    1899 
    1900             /*
    1901              * Record the target so we can nuke it
    1902              */
    1903             (void)Lst_AtEnd(targs, (ClientData)targ);
    1904 
    1905             /*
    1906              * Search from this suffix's successor...
    1907              */
    1908             ln = Lst_Succ(ln);
    1909         }
     1888            /*
     1889             * Allocate room for the prefix, whose end is found by subtracting
     1890             * the length of the suffix from the end of the name.
     1891             */
     1892            prefLen = (eoname - targ->suff->nameLen) - sopref;
     1893            targ->pref = emalloc(prefLen + 1);
     1894            memcpy(targ->pref, sopref, prefLen);
     1895            targ->pref[prefLen] = '\0';
     1896
     1897            /*
     1898             * Add nodes from which the target can be made
     1899             */
     1900            SuffAddLevel(srcs, targ);
     1901
     1902            /*
     1903             * Record the target so we can nuke it
     1904             */
     1905            (void)Lst_AtEnd(targs, (ClientData)targ);
     1906
     1907            /*
     1908             * Search from this suffix's successor...
     1909             */
     1910            ln = Lst_Succ(ln);
     1911        }
    19101912    }
    19111913
     
    19141916     */
    19151917    if (Lst_IsEmpty(targs) && suffNull != NULL) {
    1916         if (DEBUG(SUFF)) {
    1917             printf("\tNo known suffix on %s. Using .NULL suffix\n", gn->name);
    1918         }
    1919 
    1920         targ = (Src *)emalloc(sizeof (Src));
    1921         targ->file = estrdup(gn->name);
    1922         targ->suff = suffNull;
    1923         targ->suff->refCount++;
    1924         targ->node = gn;
    1925         targ->parent = (Src *)NULL;
    1926         targ->children = 0;
    1927         targ->pref = estrdup(sopref);
     1918        if (DEBUG(SUFF)) {
     1919            printf("\tNo known suffix on %s. Using .NULL suffix\n", gn->name);
     1920        }
     1921
     1922        targ = (Src *)emalloc(sizeof (Src));
     1923        targ->file = estrdup(gn->name);
     1924        targ->suff = suffNull;
     1925        targ->suff->refCount++;
     1926        targ->node = gn;
     1927        targ->parent = (Src *)NULL;
     1928        targ->children = 0;
     1929        targ->pref = estrdup(sopref);
    19281930#ifdef DEBUG_SRC
    1929         targ->cp = Lst_Init(FALSE);
     1931        targ->cp = Lst_Init(FALSE);
    19301932#endif
    19311933
    1932         /*
    1933         * Only use the default suffix rules if we don't have commands
    1934         * or dependencies defined for this gnode
    1935         */
    1936         if (Lst_IsEmpty(gn->commands) && Lst_IsEmpty(gn->children))
    1937             SuffAddLevel(srcs, targ);
    1938         else {
    1939             if (DEBUG(SUFF))
    1940                 printf("not ");
    1941         }
    1942 
    1943         if (DEBUG(SUFF))
    1944             printf("adding suffix rules\n");
    1945 
    1946         (void)Lst_AtEnd(targs, (ClientData)targ);
     1934        /*
     1935        * Only use the default suffix rules if we don't have commands
     1936        * or dependencies defined for this gnode
     1937        */
     1938        if (Lst_IsEmpty(gn->commands) && Lst_IsEmpty(gn->children))
     1939            SuffAddLevel(srcs, targ);
     1940        else {
     1941            if (DEBUG(SUFF))
     1942                printf("not ");
     1943        }
     1944
     1945        if (DEBUG(SUFF))
     1946            printf("adding suffix rules\n");
     1947
     1948        (void)Lst_AtEnd(targs, (ClientData)targ);
    19471949    }
    19481950
     
    19541956
    19551957    if (bottom == (Src *)NULL) {
    1956         /*
    1957         * No known transformations -- use the first suffix found for setting
    1958         * the local variables.
    1959         */
    1960         if (!Lst_IsEmpty(targs)) {
    1961             targ = (Src *)Lst_Datum(Lst_First(targs));
    1962         } else {
    1963             targ = (Src *)NULL;
    1964         }
     1958        /*
     1959        * No known transformations -- use the first suffix found for setting
     1960        * the local variables.
     1961        */
     1962        if (!Lst_IsEmpty(targs)) {
     1963            targ = (Src *)Lst_Datum(Lst_First(targs));
     1964        } else {
     1965            targ = (Src *)NULL;
     1966        }
    19651967    } else {
    1966         /*
    1967         * Work up the transformation path to find the suffix of the
    1968         * target to which the transformation was made.
    1969         */
    1970         for (targ = bottom; targ->parent != NULL; targ = targ->parent)
    1971             continue;
     1968        /*
     1969        * Work up the transformation path to find the suffix of the
     1970        * target to which the transformation was made.
     1971        */
     1972        for (targ = bottom; targ->parent != NULL; targ = targ->parent)
     1973            continue;
    19721974    }
    19731975
     
    19901992
    19911993    if (targ == NULL) {
    1992         if (DEBUG(SUFF)) {
    1993             printf("\tNo valid suffix on %s\n", gn->name);
    1994         }
     1994        if (DEBUG(SUFF)) {
     1995            printf("\tNo valid suffix on %s\n", gn->name);
     1996        }
    19951997
    19961998sfnd_abort:
    1997         /*
    1998         * Deal with finding the thing on the default search path if the
    1999         * node is only a source (not on the lhs of a dependency operator
    2000         * or [XXX] it has neither children or commands).
    2001         */
    2002         if (OP_NOP(gn->type) ||
    2003             (Lst_IsEmpty(gn->children) && Lst_IsEmpty(gn->commands)))
    2004         {
    2005             gn->path = Dir_FindFile(gn->name,
    2006                                     (targ == NULL ? dirSearchPath :
    2007                                      targ->suff->searchPath));
    2008             if (gn->path != NULL) {
    2009                 char *ptr;
    2010                 Var_Set(TARGET, gn->path, gn);
    2011 
    2012                 if (targ != NULL) {
    2013                     /*
    2014                      * Suffix known for the thing -- trim the suffix off
    2015                      * the path to form the proper .PREFIX variable.
    2016                      */
    2017                     int         savep = strlen(gn->path) - targ->suff->nameLen;
    2018                     char        savec;
    2019 
    2020                     if (gn->suffix)
    2021                         gn->suffix->refCount--;
    2022                     gn->suffix = targ->suff;
    2023                     gn->suffix->refCount++;
    2024 
    2025                     savec = gn->path[savep];
    2026                     gn->path[savep] = '\0';
    2027 
    2028                     if ((ptr = strrchr(gn->path, '/')) != NULL)
    2029                         ptr++;
    2030                     else
    2031                         ptr = gn->path;
    2032 
    2033                     Var_Set(PREFIX, ptr, gn);
    2034 
    2035                     gn->path[savep] = savec;
    2036                 } else {
    2037                     /*
    2038                      * The .PREFIX gets the full path if the target has
    2039                      * no known suffix.
    2040                      */
    2041                     if (gn->suffix)
    2042                         gn->suffix->refCount--;
    2043                     gn->suffix = NULL;
    2044 
    2045                     if ((ptr = strrchr(gn->path, '/')) != NULL)
    2046                         ptr++;
    2047                     else
    2048                         ptr = gn->path;
    2049 
    2050                     Var_Set(PREFIX, ptr, gn);
    2051                 }
    2052             }
    2053         } else {
    2054             /*
    2055              * Not appropriate to search for the thing -- set the
    2056              * path to be the name so Dir_MTime won't go grovelling for
    2057              * it.
    2058              */
    2059             if (gn->suffix)
    2060                 gn->suffix->refCount--;
    2061             gn->suffix = (targ == NULL) ? NULL : targ->suff;
    2062             if (gn->suffix)
    2063                 gn->suffix->refCount++;
    2064             efree(gn->path);
    2065             gn->path = estrdup(gn->name);
    2066         }
    2067 
    2068         goto sfnd_return;
     1999        /*
     2000        * Deal with finding the thing on the default search path if the
     2001        * node is only a source (not on the lhs of a dependency operator
     2002        * or [XXX] it has neither children or commands).
     2003        */
     2004        if (OP_NOP(gn->type) ||
     2005            (Lst_IsEmpty(gn->children) && Lst_IsEmpty(gn->commands)))
     2006        {
     2007            gn->path = Dir_FindFile(gn->name,
     2008                                    (targ == NULL ? dirSearchPath :
     2009                                     targ->suff->searchPath));
     2010            if (gn->path != NULL) {
     2011                char *ptr;
     2012                Var_Set(TARGET, gn->path, gn);
     2013
     2014                if (targ != NULL) {
     2015                    /*
     2016                     * Suffix known for the thing -- trim the suffix off
     2017                     * the path to form the proper .PREFIX variable.
     2018                     */
     2019                    int         savep = strlen(gn->path) - targ->suff->nameLen;
     2020                    char        savec;
     2021
     2022                    if (gn->suffix)
     2023                        gn->suffix->refCount--;
     2024                    gn->suffix = targ->suff;
     2025                    gn->suffix->refCount++;
     2026
     2027                    savec = gn->path[savep];
     2028                    gn->path[savep] = '\0';
     2029
     2030                    if ((ptr = strrchr(gn->path, '/')) != NULL)
     2031                        ptr++;
     2032                    else
     2033                        ptr = gn->path;
     2034
     2035                    Var_Set(PREFIX, ptr, gn);
     2036
     2037                    gn->path[savep] = savec;
     2038                } else {
     2039                    /*
     2040                     * The .PREFIX gets the full path if the target has
     2041                     * no known suffix.
     2042                     */
     2043                    if (gn->suffix)
     2044                        gn->suffix->refCount--;
     2045                    gn->suffix = NULL;
     2046
     2047                    if ((ptr = strrchr(gn->path, '/')) != NULL)
     2048                        ptr++;
     2049                    else
     2050                        ptr = gn->path;
     2051
     2052                    Var_Set(PREFIX, ptr, gn);
     2053                }
     2054            }
     2055        } else {
     2056            /*
     2057             * Not appropriate to search for the thing -- set the
     2058             * path to be the name so Dir_MTime won't go grovelling for
     2059             * it.
     2060             */
     2061            if (gn->suffix)
     2062                gn->suffix->refCount--;
     2063            gn->suffix = (targ == NULL) ? NULL : targ->suff;
     2064            if (gn->suffix)
     2065                gn->suffix->refCount++;
     2066            efree(gn->path);
     2067            gn->path = estrdup(gn->name);
     2068        }
     2069
     2070        goto sfnd_return;
    20692071    }
    20702072
     
    20752077     */
    20762078    if (targ->suff->flags & SUFF_LIBRARY) {
    2077         gn->type |= OP_LIB;
     2079        gn->type |= OP_LIB;
    20782080    }
    20792081#endif
     
    20832085     */
    20842086    if (!Lst_IsEmpty(gn->children)) {
    2085         src = SuffFindCmds(targ, slst);
    2086 
    2087         if (src != (Src *)NULL) {
    2088             /*
    2089              * Free up all the Src structures in the transformation path
    2090              * up to, but not including, the parent node.
    2091              */
    2092             while (bottom && bottom->parent != NULL) {
    2093                 if (Lst_Member(slst, (ClientData) bottom) == NILLNODE) {
    2094                     Lst_AtEnd(slst, (ClientData) bottom);
    2095                 }
    2096                 bottom = bottom->parent;
    2097             }
    2098             bottom = src;
    2099         }
     2087        src = SuffFindCmds(targ, slst);
     2088
     2089        if (src != (Src *)NULL) {
     2090            /*
     2091             * Free up all the Src structures in the transformation path
     2092             * up to, but not including, the parent node.
     2093             */
     2094            while (bottom && bottom->parent != NULL) {
     2095                if (Lst_Member(slst, (ClientData) bottom) == NILLNODE) {
     2096                    Lst_AtEnd(slst, (ClientData) bottom);
     2097                }
     2098                bottom = bottom->parent;
     2099            }
     2100            bottom = src;
     2101        }
    21002102    }
    21012103
    21022104    if (bottom == NULL) {
    2103         /*
    2104         * No idea from where it can come -- return now.
    2105         */
    2106         goto sfnd_abort;
     2105        /*
     2106        * No idea from where it can come -- return now.
     2107        */
     2108        goto sfnd_abort;
    21072109    }
    21082110
     
    21202122     */
    21212123    if (bottom->node == NILGNODE) {
    2122         bottom->node = Targ_FindNode(bottom->file, TARG_CREATE);
     2124        bottom->node = Targ_FindNode(bottom->file, TARG_CREATE);
    21232125    }
    21242126
    21252127    for (src = bottom; src->parent != (Src *)NULL; src = src->parent) {
    2126         targ = src->parent;
    2127 
    2128         if (src->node->suffix)
    2129             src->node->suffix->refCount--;
    2130         src->node->suffix = src->suff;
    2131         src->node->suffix->refCount++;
    2132 
    2133         if (targ->node == NILGNODE) {
    2134             targ->node = Targ_FindNode(targ->file, TARG_CREATE);
    2135         }
    2136 
    2137         SuffApplyTransform(targ->node, src->node,
    2138                            targ->suff, src->suff);
    2139 
    2140         if (targ->node != gn) {
    2141             /*
    2142              * Finish off the dependency-search process for any nodes
    2143              * between bottom and gn (no point in questing around the
    2144              * filesystem for their implicit source when it's already
    2145              * known). Note that the node can't have any sources that
    2146              * need expanding, since SuffFindThem will stop on an existing
    2147              * node, so all we need to do is set the standard and System V
    2148              * variables.
    2149              */
    2150             targ->node->type |= OP_DEPS_FOUND;
    2151 
    2152             Var_Set(PREFIX, targ->pref, targ->node);
    2153 
    2154             Var_Set(TARGET, targ->node->name, targ->node);
    2155         }
     2128        targ = src->parent;
     2129
     2130        if (src->node->suffix)
     2131            src->node->suffix->refCount--;
     2132        src->node->suffix = src->suff;
     2133        src->node->suffix->refCount++;
     2134
     2135        if (targ->node == NILGNODE) {
     2136            targ->node = Targ_FindNode(targ->file, TARG_CREATE);
     2137        }
     2138
     2139        SuffApplyTransform(targ->node, src->node,
     2140                           targ->suff, src->suff);
     2141
     2142        if (targ->node != gn) {
     2143            /*
     2144             * Finish off the dependency-search process for any nodes
     2145             * between bottom and gn (no point in questing around the
     2146             * filesystem for their implicit source when it's already
     2147             * known). Note that the node can't have any sources that
     2148             * need expanding, since SuffFindThem will stop on an existing
     2149             * node, so all we need to do is set the standard and System V
     2150             * variables.
     2151             */
     2152            targ->node->type |= OP_DEPS_FOUND;
     2153
     2154            Var_Set(PREFIX, targ->pref, targ->node);
     2155
     2156            Var_Set(TARGET, targ->node->name, targ->node);
     2157        }
    21562158    }
    21572159
    21582160    if (gn->suffix)
    2159         gn->suffix->refCount--;
     2161        gn->suffix->refCount--;
    21602162    gn->suffix = src->suff;
    21612163    gn->suffix->refCount++;
     
    21732175sfnd_return:
    21742176    if (bottom)
    2175         if (Lst_Member(slst, (ClientData) bottom) == NILLNODE)
    2176             Lst_AtEnd(slst, (ClientData) bottom);
     2177        if (Lst_Member(slst, (ClientData) bottom) == NILLNODE)
     2178            Lst_AtEnd(slst, (ClientData) bottom);
    21772179
    21782180    while (SuffRemoveSrc(srcs) || SuffRemoveSrc(targs))
    2179         continue;
     2181        continue;
    21802182
    21812183    Lst_Concat(slst, srcs, LST_CONCLINK);
     
    21872189 *-----------------------------------------------------------------------
    21882190 * Suff_FindDeps  --
    2189  *      Find implicit sources for the target described by the graph node
    2190  *      gn
    2191  *
    2192  * Results:
    2193  *      Nothing.
    2194  *
    2195  * Side Effects:
    2196  *      Nodes are added to the graph below the passed-in node. The nodes
    2197  *      are marked to have their IMPSRC variable filled in. The
    2198  *      PREFIX variable is set for the given node and all its
    2199  *      implied children.
     2191 *      Find implicit sources for the target described by the graph node
     2192 *      gn
     2193 *
     2194 * Results:
     2195 *      Nothing.
     2196 *
     2197 * Side Effects:
     2198 *      Nodes are added to the graph below the passed-in node. The nodes
     2199 *      are marked to have their IMPSRC variable filled in. The
     2200 *      PREFIX variable is set for the given node and all its
     2201 *      implied children.
    22002202 *
    22012203 * Notes:
    2202  *      The path found by this target is the shortest path in the
    2203  *      transformation graph, which may pass through non-existent targets,
    2204  *      to an existing target. The search continues on all paths from the
    2205  *      root suffix until a file is found. I.e. if there's a path
    2206  *      .o -> .c -> .l -> .l,v from the root and the .l,v file exists but
    2207  *      the .c and .l files don't, the search will branch out in
    2208  *      all directions from .o and again from all the nodes on the
    2209  *      next level until the .l,v node is encountered.
     2204 *      The path found by this target is the shortest path in the
     2205 *      transformation graph, which may pass through non-existent targets,
     2206 *      to an existing target. The search continues on all paths from the
     2207 *      root suffix until a file is found. I.e. if there's a path
     2208 *      .o -> .c -> .l -> .l,v from the root and the .l,v file exists but
     2209 *      the .c and .l files don't, the search will branch out in
     2210 *      all directions from .o and again from all the nodes on the
     2211 *      next level until the .l,v node is encountered.
    22102212 *
    22112213 *-----------------------------------------------------------------------
     
    22192221    SuffFindDeps(gn, srclist);
    22202222    while (SuffRemoveSrc(srclist))
    2221         continue;
     2223        continue;
    22222224}
    22232225
     
    22252227static void
    22262228SuffFindDeps (gn, slst)
    2227     GNode         *gn;          /* node we're dealing with */
    2228     Lst           slst;
     2229    GNode         *gn;          /* node we're dealing with */
     2230    Lst           slst;
    22292231{
    22302232    if (gn->type & OP_DEPS_FOUND) {
    2231         /*
    2232         * If dependencies already found, no need to do it again...
    2233         */
    2234         return;
     2233        /*
     2234        * If dependencies already found, no need to do it again...
     2235        */
     2236        return;
    22352237    } else {
    2236         gn->type |= OP_DEPS_FOUND;
     2238        gn->type |= OP_DEPS_FOUND;
    22372239    }
    22382240
    22392241    if (DEBUG(SUFF)) {
    2240         printf ("SuffFindDeps (%s)\n", gn->name);
     2242        printf ("SuffFindDeps (%s)\n", gn->name);
    22412243    }
    22422244
    22432245#ifdef USE_ARCHIVES
    22442246    if (gn->type & OP_ARCHV) {
    2245         SuffFindArchiveDeps(gn, slst);
     2247        SuffFindArchiveDeps(gn, slst);
    22462248    } else if (gn->type & OP_LIB) {
    2247         /*
    2248         * If the node is a library, it is the arch module's job to find it
    2249         * and set the TARGET variable accordingly. We merely provide the
    2250         * search path, assuming all libraries end in ".a" (if the suffix
    2251         * hasn't been defined, there's nothing we can do for it, so we just
    2252         * set the TARGET variable to the node's name in order to give it a
    2253         * value).
    2254         */
    2255         LstNode ln;
    2256         Suff    *s;
    2257 
    2258         ln = Lst_Find (sufflist, (ClientData)LIBSUFF, SuffSuffHasNameP);
    2259         if (gn->suffix)
    2260             gn->suffix->refCount--;
    2261         if (ln != NILLNODE) {
    2262             gn->suffix = s = (Suff *) Lst_Datum (ln);
    2263             gn->suffix->refCount++;
    2264             Arch_FindLib (gn, s->searchPath);
    2265         } else {
    2266             gn->suffix = NULL;
    2267             Var_Set (TARGET, gn->name, gn);
    2268         }
    2269         /*
    2270         * Because a library (-lfoo) target doesn't follow the standard
    2271         * filesystem conventions, we don't set the regular variables for
    2272         * the thing. .PREFIX is simply made empty...
    2273         */
    2274         Var_Set(PREFIX, "", gn);
     2249        /*
     2250        * If the node is a library, it is the arch module's job to find it
     2251        * and set the TARGET variable accordingly. We merely provide the
     2252        * search path, assuming all libraries end in ".a" (if the suffix
     2253        * hasn't been defined, there's nothing we can do for it, so we just
     2254        * set the TARGET variable to the node's name in order to give it a
     2255        * value).
     2256        */
     2257        LstNode ln;
     2258        Suff    *s;
     2259
     2260        ln = Lst_Find (sufflist, (ClientData)LIBSUFF, SuffSuffHasNameP);
     2261        if (gn->suffix)
     2262            gn->suffix->refCount--;
     2263        if (ln != NILLNODE) {
     2264            gn->suffix = s = (Suff *) Lst_Datum (ln);
     2265            gn->suffix->refCount++;
     2266            Arch_FindLib (gn, s->searchPath);
     2267        } else {
     2268            gn->suffix = NULL;
     2269            Var_Set (TARGET, gn->name, gn);
     2270        }
     2271        /*
     2272        * Because a library (-lfoo) target doesn't follow the standard
     2273        * filesystem conventions, we don't set the regular variables for
     2274        * the thing. .PREFIX is simply made empty...
     2275        */
     2276        Var_Set(PREFIX, "", gn);
    22752277    } else
    22762278#endif /* USE_ARCHIVES */
    2277         SuffFindNormalDeps(gn, slst);
     2279        SuffFindNormalDeps(gn, slst);
    22782280}
    22792281
     
    22812283 *-----------------------------------------------------------------------
    22822284 * Suff_SetNull --
    2283  *      Define which suffix is the null suffix.
    2284  *
    2285  * Results:
    2286  *      None.
    2287  *
    2288  * Side Effects:
    2289  *      'suffNull' is altered.
     2285 *      Define which suffix is the null suffix.
     2286 *
     2287 * Results:
     2288 *      None.
     2289 *
     2290 * Side Effects:
     2291 *      'suffNull' is altered.
    22902292 *
    22912293 * Notes:
    2292  *      Need to handle the changing of the null suffix gracefully so the
    2293  *      old transformation rules don't just go away.
     2294 *      Need to handle the changing of the null suffix gracefully so the
     2295 *      old transformation rules don't just go away.
    22942296 *
    22952297 *-----------------------------------------------------------------------
     
    22972299void
    22982300Suff_SetNull(name)
    2299     char    *name;          /* Name of null suffix */
     2301    char    *name;          /* Name of null suffix */
    23002302{
    23012303    Suff    *s;
     
    23042306    ln = Lst_Find(sufflist, (ClientData)name, SuffSuffHasNameP);
    23052307    if (ln != NILLNODE) {
    2306         s = (Suff *)Lst_Datum(ln);
    2307         if (suffNull != (Suff *)NULL) {
    2308             suffNull->flags &= ~SUFF_NULL;
    2309         }
    2310         s->flags |= SUFF_NULL;
    2311         /*
    2312         * XXX: Here's where the transformation mangling would take place
    2313         */
    2314         suffNull = s;
     2308        s = (Suff *)Lst_Datum(ln);
     2309        if (suffNull != (Suff *)NULL) {
     2310            suffNull->flags &= ~SUFF_NULL;
     2311        }
     2312        s->flags |= SUFF_NULL;
     2313        /*
     2314        * XXX: Here's where the transformation mangling would take place
     2315        */
     2316        suffNull = s;
    23152317    } else {
    2316         Parse_Error (PARSE_WARNING, "Desired null suffix %s not defined.",
    2317                      name);
     2318        Parse_Error (PARSE_WARNING, "Desired null suffix %s not defined.",
     2319                     name);
    23182320    }
    23192321}
     
    23222324 *-----------------------------------------------------------------------
    23232325 * Suff_Init --
    2324  *      Initialize suffixes module
    2325  *
    2326  * Results:
    2327  *      None
    2328  *
    2329  * Side Effects:
    2330  *      Many
     2326 *      Initialize suffixes module
     2327 *
     2328 * Results:
     2329 *      None
     2330 *
     2331 * Side Effects:
     2332 *      Many
    23312333 *-----------------------------------------------------------------------
    23322334 */
     
    23472349    emptySuff = suffNull = (Suff *) emalloc (sizeof (Suff));
    23482350
    2349     suffNull->name =        estrdup ("");
     2351    suffNull->name =        estrdup ("");
    23502352    suffNull->nameLen =     0;
    23512353    suffNull->searchPath =  Lst_Init (FALSE);
    23522354    Dir_Concat(suffNull->searchPath, dirSearchPath);
    23532355    suffNull->children =    Lst_Init (FALSE);
    2354     suffNull->parents =     Lst_Init (FALSE);
    2355     suffNull->ref =         Lst_Init (FALSE);
    2356     suffNull->sNum =        sNum++;
    2357     suffNull->flags =       SUFF_NULL;
     2356    suffNull->parents =     Lst_Init (FALSE);
     2357    suffNull->ref =         Lst_Init (FALSE);
     2358    suffNull->sNum =        sNum++;
     2359    suffNull->flags =       SUFF_NULL;
    23582360    suffNull->refCount =    1;
    23592361
     
    23642366 *----------------------------------------------------------------------
    23652367 * Suff_End --
    2366  *      Cleanup the this module
    2367  *
    2368  * Results:
    2369  *      None
    2370  *
    2371  * Side Effects:
    2372  *      The memory is efree'd.
     2368 *      Cleanup the this module
     2369 *
     2370 * Results:
     2371 *      None
     2372 *
     2373 * Side Effects:
     2374 *      The memory is efree'd.
    23732375 *----------------------------------------------------------------------
    23742376 */
     
    23802382    Lst_Destroy(suffClean, SuffFree);
    23812383    if (suffNull)
    2382         SuffFree(suffNull);
     2384        SuffFree(suffNull);
    23832385    Lst_Destroy(srclist, NOFREE);
    23842386    Lst_Destroy(transforms, NOFREE);
     
    24022404{
    24032405    Suff    *s = (Suff *) sp;
    2404     int     flags;
    2405     int     flag;
     2406    int     flags;
     2407    int     flag;
    24062408
    24072409    printf ("# `%s' [%d] ", s->name, s->refCount);
     
    24092411    flags = s->flags;
    24102412    if (flags) {
    2411         fputs (" (", stdout);
    2412         while (flags) {
    2413             flag = 1 << (ffs(flags) - 1);
    2414             flags &= ~flag;
    2415             switch (flag) {
    2416                 case SUFF_NULL:
    2417                     printf ("NULL");
    2418                     break;
    2419                 case SUFF_INCLUDE:
    2420                     printf ("INCLUDE");
    2421                     break;
     2413        fputs (" (", stdout);
     2414        while (flags) {
     2415            flag = 1 << (ffs(flags) - 1);
     2416            flags &= ~flag;
     2417            switch (flag) {
     2418                case SUFF_NULL:
     2419                    printf ("NULL");
     2420                    break;
     2421                case SUFF_INCLUDE:
     2422                    printf ("INCLUDE");
     2423                    break;
    24222424#ifdef USE_ARCHIVES
    2423                 case SUFF_LIBRARY:
    2424                     printf ("LIBRARY");
    2425                     break;
     2425                case SUFF_LIBRARY:
     2426                    printf ("LIBRARY");
     2427                    break;
    24262428#endif
    2427             }
    2428             fputc(flags ? '|' : ')', stdout);
    2429         }
     2429            }
     2430            fputc(flags ? '|' : ')', stdout);
     2431        }
    24302432    }
    24312433    fputc ('\n', stdout);
  • trunk/src/kmk/targ.c

    r47 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[] = "@(#)targ.c      8.2 (Berkeley) 3/19/94";
     41static char sccsid[] = "@(#)targ.c      8.2 (Berkeley) 3/19/94";
    4242#else
    4343static const char rcsid[] =
    4444  "$FreeBSD: src/usr.bin/make/targ.c,v 1.10 1999/09/11 13:08:02 hoek Exp $";
    4545#endif
     46#define KLIBFILEDEF rcsid
    4647#endif /* not lint */
    4748
    4849/*-
    4950 * targ.c --
    50  *      Functions for maintaining the Lst allTargets. Target nodes are
     51 *      Functions for maintaining the Lst allTargets. Target nodes are
    5152 * kept in two structures: a Lst, maintained by the list library, and a
    5253 * hash table, maintained by the hash library.
    5354 *
    5455 * Interface:
    55  *      Targ_Init               Initialization procedure.
    56  *
    57  *      Targ_End                Cleanup the module
    58  *
    59  *      Targ_NewGN              Create a new GNode for the passed target
    60  *                              (string). The node is *not* placed in the
    61  *                              hash table, though all its fields are
    62  *                              initialized.
    63  *
    64  *      Targ_FindNode           Find the node for a given target, creating
    65  *                              and storing it if it doesn't exist and the
    66  *                              flags are right (TARG_CREATE)
    67  *
    68  *      Targ_FindList           Given a list of names, find nodes for all
    69  *                              of them. If a name doesn't exist and the
    70  *                              TARG_NOCREATE flag was given, an error message
    71  *                              is printed. Else, if a name doesn't exist,
    72  *                              its node is created.
    73  *
    74  *      Targ_Ignore             Return TRUE if errors should be ignored when
    75  *                              creating the given target.
    76  *
    77  *      Targ_Silent             Return TRUE if we should be silent when
    78  *                              creating the given target.
    79  *
    80  *      Targ_Precious           Return TRUE if the target is precious and
    81  *                              should not be removed if we are interrupted.
     56 *      Targ_Init               Initialization procedure.
     57 *
     58 *      Targ_End                Cleanup the module
     59 *
     60 *      Targ_NewGN              Create a new GNode for the passed target
     61 *                              (string). The node is *not* placed in the
     62 *                              hash table, though all its fields are
     63 *                              initialized.
     64 *
     65 *      Targ_FindNode           Find the node for a given target, creating
     66 *                              and storing it if it doesn't exist and the
     67 *                              flags are right (TARG_CREATE)
     68 *
     69 *      Targ_FindList           Given a list of names, find nodes for all
     70 *                              of them. If a name doesn't exist and the
     71 *                              TARG_NOCREATE flag was given, an error message
     72 *                              is printed. Else, if a name doesn't exist,
     73 *                              its node is created.
     74 *
     75 *      Targ_Ignore             Return TRUE if errors should be ignored when
     76 *                              creating the given target.
     77 *
     78 *      Targ_Silent             Return TRUE if we should be silent when
     79 *                              creating the given target.
     80 *
     81 *      Targ_Precious           Return TRUE if the target is precious and
     82 *                              should not be removed if we are interrupted.
    8283 *
    8384 * Debugging:
    84  *      Targ_PrintGraph         Print out the entire graphm all variables
    85  *                              and statistics for the directory cache. Should
    86  *                              print something for suffixes, too, but...
    87  */
    88 
    89 #include          <stdio.h>
    90 #include          <time.h>
    91 #include          "make.h"
    92 #include          "hash.h"
    93 #include          "dir.h"
    94 
    95 static Lst        allTargets;   /* the list of all targets found so far */
    96 static Lst        allGNs;       /* List of all the GNodes */
    97 static Hash_Table targets;      /* a hash table of same */
    98 
    99 #define HTSIZE  191             /* initial size of hash table */
     85 *      Targ_PrintGraph         Print out the entire graphm all variables
     86 *                              and statistics for the directory cache. Should
     87 *                              print something for suffixes, too, but...
     88 */
     89
     90#include          <stdio.h>
     91#include          <time.h>
     92#include          <strings.h>
     93#include          "make.h"
     94#include          "hash.h"
     95#include          "dir.h"
     96
     97static Lst        allTargets;   /* the list of all targets found so far */
     98static Lst        allGNs;       /* List of all the GNodes */
     99static Hash_Table targets;      /* a hash table of same */
     100
     101#define HTSIZE  191             /* initial size of hash table */
    100102
    101103static int TargPrintOnlySrc __P((ClientData, ClientData));
     
    107109 *-----------------------------------------------------------------------
    108110 * Targ_Init --
    109  *      Initialize this module
    110  *
    111  * Results:
    112  *      None
    113  *
    114  * Side Effects:
    115  *      The allTargets list and the targets hash table are initialized
     111 *      Initialize this module
     112 *
     113 * Results:
     114 *      None
     115 *
     116 * Side Effects:
     117 *      The allTargets list and the targets hash table are initialized
    116118 *-----------------------------------------------------------------------
    117119 */
     
    126128 *-----------------------------------------------------------------------
    127129 * Targ_End --
    128  *      Finalize this module
    129  *
    130  * Results:
    131  *      None
    132  *
    133  * Side Effects:
    134  *      All lists and gnodes are cleared
     130 *      Finalize this module
     131 *
     132 * Results:
     133 *      None
     134 *
     135 * Side Effects:
     136 *      All lists and gnodes are cleared
    135137 *-----------------------------------------------------------------------
    136138 */
     
    140142    Lst_Destroy(allTargets, NOFREE);
    141143    if (allGNs)
    142         Lst_Destroy(allGNs, TargFreeGN);
     144        Lst_Destroy(allGNs, TargFreeGN);
    143145    Hash_DeleteTable(&targets);
    144146}
     
    147149 *-----------------------------------------------------------------------
    148150 * Targ_NewGN  --
    149  *      Create and initialize a new graph node
    150  *
    151  * Results:
    152  *      An initialized graph node with the name field filled with a copy
    153  *      of the passed name
    154  *
    155  * Side Effects:
    156  *      The gnode is added to the list of all gnodes.
     151 *      Create and initialize a new graph node
     152 *
     153 * Results:
     154 *      An initialized graph node with the name field filled with a copy
     155 *      of the passed name
     156 *
     157 * Side Effects:
     158 *      The gnode is added to the list of all gnodes.
    157159 *-----------------------------------------------------------------------
    158160 */
    159161GNode *
    160162Targ_NewGN (name)
    161     char           *name;       /* the name to stick in the new node */
     163    char           *name;       /* the name to stick in the new node */
    162164{
    163165    register GNode *gn;
     
    168170#ifdef USE_ARCHIVES
    169171    if (name[0] == '-' && name[1] == 'l') {
    170         gn->type = OP_LIB;
     172        gn->type = OP_LIB;
    171173    } else {
    172         gn->type = 0;
     174        gn->type = 0;
    173175    }
    174176#else
    175177    gn->type = 0;
    176178#endif
    177     gn->unmade =        0;
    178     gn->make =          FALSE;
    179     gn->made =          UNMADE;
    180     gn->childMade =     FALSE;
    181     gn->order =         0;
     179    gn->unmade =        0;
     180    gn->make =          FALSE;
     181    gn->made =          UNMADE;
     182    gn->childMade =     FALSE;
     183    gn->order =         0;
    182184    gn->mtime = gn->cmtime = 0;
    183     gn->iParents =      Lst_Init (FALSE);
    184     gn->cohorts =       Lst_Init (FALSE);
    185     gn->parents =       Lst_Init (FALSE);
    186     gn->children =      Lst_Init (FALSE);
    187     gn->successors =    Lst_Init (FALSE);
    188     gn->preds =         Lst_Init (FALSE);
    189     gn->context =       Lst_Init (FALSE);
    190     gn->commands =      Lst_Init (FALSE);
    191     gn->suffix =        NULL;
     185    gn->iParents =      Lst_Init (FALSE);
     186    gn->cohorts =       Lst_Init (FALSE);
     187    gn->parents =       Lst_Init (FALSE);
     188    gn->children =      Lst_Init (FALSE);
     189    gn->successors =    Lst_Init (FALSE);
     190    gn->preds =         Lst_Init (FALSE);
     191    gn->context =       Lst_Init (FALSE);
     192    gn->commands =      Lst_Init (FALSE);
     193    gn->suffix =        NULL;
    192194
    193195    if (allGNs == NULL)
    194         allGNs = Lst_Init(FALSE);
     196        allGNs = Lst_Init(FALSE);
    195197    Lst_AtEnd(allGNs, (ClientData) gn);
    196198
     
    201203 *-----------------------------------------------------------------------
    202204 * TargFreeGN  --
    203  *      Destroy a GNode
    204  *
    205  * Results:
    206  *      None.
    207  *
    208  * Side Effects:
    209  *      None.
     205 *      Destroy a GNode
     206 *
     207 * Results:
     208 *      None.
     209 *
     210 * Side Effects:
     211 *      None.
    210212 *-----------------------------------------------------------------------
    211213 */
     
    235237 *-----------------------------------------------------------------------
    236238 * Targ_FindNode  --
    237  *      Find a node in the list using the given name for matching
    238  *
    239  * Results:
    240  *      The node in the list if it was. If it wasn't, return NILGNODE of
    241  *      flags was TARG_NOCREATE or the newly created and initialized node
    242  *      if it was TARG_CREATE
    243  *
    244  * Side Effects:
    245  *      Sometimes a node is created and added to the list
     239 *      Find a node in the list using the given name for matching
     240 *
     241 * Results:
     242 *      The node in the list if it was. If it wasn't, return NILGNODE of
     243 *      flags was TARG_NOCREATE or the newly created and initialized node
     244 *      if it was TARG_CREATE
     245 *
     246 * Side Effects:
     247 *      Sometimes a node is created and added to the list
    246248 *-----------------------------------------------------------------------
    247249 */
    248250GNode *
    249251Targ_FindNode (name, flags)
    250     char           *name;       /* the name to find */
    251     int             flags;      /* flags governing events when target not
    252                                 * found */
    253 {
    254     GNode         *gn;        /* node in that element */
    255     Hash_Entry    *he;        /* New or used hash entry for node */
    256     Boolean       isNew;      /* Set TRUE if Hash_CreateEntry had to create */
    257                               /* an entry for the node */
     252    char           *name;       /* the name to find */
     253    int             flags;      /* flags governing events when target not
     254                                * found */
     255{
     256    GNode         *gn;        /* node in that element */
     257    Hash_Entry    *he;        /* New or used hash entry for node */
     258    Boolean       isNew;      /* Set TRUE if Hash_CreateEntry had to create */
     259                              /* an entry for the node */
    258260
    259261
    260262    if (flags & TARG_CREATE) {
    261         he = Hash_CreateEntry (&targets, name, &isNew);
    262         if (isNew) {
    263             gn = Targ_NewGN (name);
    264             Hash_SetValue (he, gn);
    265             (void) Lst_AtEnd (allTargets, (ClientData)gn);
    266         }
     263        he = Hash_CreateEntry (&targets, name, &isNew);
     264        if (isNew) {
     265            gn = Targ_NewGN (name);
     266            Hash_SetValue (he, gn);
     267            (void) Lst_AtEnd (allTargets, (ClientData)gn);
     268        }
    267269    } else {
    268         he = Hash_FindEntry (&targets, name);
     270        he = Hash_FindEntry (&targets, name);
    269271    }
    270272
    271273    if (he == (Hash_Entry *) NULL) {
    272         return (NILGNODE);
     274        return (NILGNODE);
    273275    } else {
    274         return ((GNode *) Hash_GetValue (he));
     276        return ((GNode *) Hash_GetValue (he));
    275277    }
    276278}
     
    279281 *-----------------------------------------------------------------------
    280282 * Targ_FindList --
    281  *      Make a complete list of GNodes from the given list of names
    282  *
    283  * Results:
    284  *      A complete list of graph nodes corresponding to all instances of all
    285  *      the names in names.
    286  *
    287  * Side Effects:
    288  *      If flags is TARG_CREATE, nodes will be created for all names in
    289  *      names which do not yet have graph nodes. If flags is TARG_NOCREATE,
    290  *      an error message will be printed for each name which can't be found.
     283 *      Make a complete list of GNodes from the given list of names
     284 *
     285 * Results:
     286 *      A complete list of graph nodes corresponding to all instances of all
     287 *      the names in names.
     288 *
     289 * Side Effects:
     290 *      If flags is TARG_CREATE, nodes will be created for all names in
     291 *      names which do not yet have graph nodes. If flags is TARG_NOCREATE,
     292 *      an error message will be printed for each name which can't be found.
    291293 * -----------------------------------------------------------------------
    292294 */
    293295Lst
    294296Targ_FindList (names, flags)
    295     Lst            names;       /* list of names to find */
    296     int            flags;       /* flags used if no node is found for a given
    297                                 * name */
    298 {
    299     Lst            nodes;       /* result list */
    300     register LstNode  ln;               /* name list element */
    301     register GNode *gn;         /* node in tLn */
    302     char          *name;
     297    Lst            names;       /* list of names to find */
     298    int            flags;       /* flags used if no node is found for a given
     299                                * name */
     300{
     301    Lst            nodes;       /* result list */
     302    register LstNode  ln;               /* name list element */
     303    register GNode *gn;         /* node in tLn */
     304    char          *name;
    303305
    304306    nodes = Lst_Init (FALSE);
    305307
    306308    if (Lst_Open (names) == FAILURE) {
    307         return (nodes);
     309        return (nodes);
    308310    }
    309311    while ((ln = Lst_Next (names)) != NILLNODE) {
    310         name = (char *)Lst_Datum(ln);
    311         gn = Targ_FindNode (name, flags);
    312         if (gn != NILGNODE) {
    313             /*
    314              * Note: Lst_AtEnd must come before the Lst_Concat so the nodes
    315              * are added to the list in the order in which they were
    316              * encountered in the makefile.
    317              */
    318             (void) Lst_AtEnd (nodes, (ClientData)gn);
    319             if (gn->type & OP_DOUBLEDEP) {
    320                 (void)Lst_Concat (nodes, gn->cohorts, LST_CONCNEW);
    321             }
    322         } else if (flags == TARG_NOCREATE) {
    323             Error ("\"%s\" -- target unknown.", name);
    324         }
     312        name = (char *)Lst_Datum(ln);
     313        gn = Targ_FindNode (name, flags);
     314        if (gn != NILGNODE) {
     315            /*
     316             * Note: Lst_AtEnd must come before the Lst_Concat so the nodes
     317             * are added to the list in the order in which they were
     318             * encountered in the makefile.
     319             */
     320            (void) Lst_AtEnd (nodes, (ClientData)gn);
     321            if (gn->type & OP_DOUBLEDEP) {
     322                (void)Lst_Concat (nodes, gn->cohorts, LST_CONCNEW);
     323            }
     324        } else if (flags == TARG_NOCREATE) {
     325            Error ("\"%s\" -- target unknown.", name);
     326        }
    325327    }
    326328    Lst_Close (names);
     
    331333 *-----------------------------------------------------------------------
    332334 * Targ_Ignore  --
    333  *      Return true if should ignore errors when creating gn
    334  *
    335  * Results:
    336  *      TRUE if should ignore errors
    337  *
    338  * Side Effects:
    339  *      None
     335 *      Return true if should ignore errors when creating gn
     336 *
     337 * Results:
     338 *      TRUE if should ignore errors
     339 *
     340 * Side Effects:
     341 *      None
    340342 *-----------------------------------------------------------------------
    341343 */
    342344Boolean
    343345Targ_Ignore (gn)
    344     GNode          *gn;         /* node to check for */
     346    GNode          *gn;         /* node to check for */
    345347{
    346348    if (ignoreErrors || gn->type & OP_IGNORE) {
    347         return (TRUE);
     349        return (TRUE);
    348350    } else {
    349         return (FALSE);
     351        return (FALSE);
    350352    }
    351353}
     
    354356 *-----------------------------------------------------------------------
    355357 * Targ_Silent  --
    356  *      Return true if be silent when creating gn
    357  *
    358  * Results:
    359  *      TRUE if should be silent
    360  *
    361  * Side Effects:
    362  *      None
     358 *      Return true if be silent when creating gn
     359 *
     360 * Results:
     361 *      TRUE if should be silent
     362 *
     363 * Side Effects:
     364 *      None
    363365 *-----------------------------------------------------------------------
    364366 */
    365367Boolean
    366368Targ_Silent (gn)
    367     GNode          *gn;         /* node to check for */
     369    GNode          *gn;         /* node to check for */
    368370{
    369371    if (beSilent || gn->type & OP_SILENT) {
    370         return (TRUE);
     372        return (TRUE);
    371373    } else {
    372         return (FALSE);
     374        return (FALSE);
    373375    }
    374376}
     
    377379 *-----------------------------------------------------------------------
    378380 * Targ_Precious --
    379  *      See if the given target is precious
    380  *
    381  * Results:
    382  *      TRUE if it is precious. FALSE otherwise
    383  *
    384  * Side Effects:
    385  *      None
     381 *      See if the given target is precious
     382 *
     383 * Results:
     384 *      TRUE if it is precious. FALSE otherwise
     385 *
     386 * Side Effects:
     387 *      None
    386388 *-----------------------------------------------------------------------
    387389 */
    388390Boolean
    389391Targ_Precious (gn)
    390     GNode          *gn;         /* the node to check */
     392    GNode          *gn;         /* the node to check */
    391393{
    392394    if (allPrecious || (gn->type & (OP_PRECIOUS|OP_DOUBLEDEP))) {
    393         return (TRUE);
     395        return (TRUE);
    394396    } else {
    395         return (FALSE);
     397        return (FALSE);
    396398    }
    397399}
     
    399401/******************* DEBUG INFO PRINTING ****************/
    400402
    401 static GNode      *mainTarg;    /* the main target, as set by Targ_SetMain */
     403static GNode      *mainTarg;    /* the main target, as set by Targ_SetMain */
    402404/*-
    403405 *-----------------------------------------------------------------------
    404406 * Targ_SetMain --
    405  *      Set our idea of the main target we'll be creating. Used for
    406  *      debugging output.
    407  *
    408  * Results:
    409  *      None.
    410  *
    411  * Side Effects:
    412  *      "mainTarg" is set to the main target's node.
     407 *      Set our idea of the main target we'll be creating. Used for
     408 *      debugging output.
     409 *
     410 * Results:
     411 *      None.
     412 *
     413 * Side Effects:
     414 *      "mainTarg" is set to the main target's node.
    413415 *-----------------------------------------------------------------------
    414416 */
    415417void
    416418Targ_SetMain (gn)
    417     GNode   *gn;        /* The main target we'll create */
     419    GNode   *gn;        /* The main target we'll create */
    418420{
    419421    mainTarg = gn;
     
    423425TargPrintName (gnp, ppath)
    424426    ClientData     gnp;
    425     ClientData      ppath;
     427    ClientData      ppath;
    426428{
    427429    GNode *gn = (GNode *) gnp;
     
    429431#ifdef notdef
    430432    if (ppath) {
    431         if (gn->path) {
    432             printf ("[%s]  ", gn->path);
    433         }
    434         if (gn == mainTarg) {
    435             printf ("(MAIN NAME)  ");
    436         }
     433        if (gn->path) {
     434            printf ("[%s]  ", gn->path);
     435        }
     436        if (gn == mainTarg) {
     437            printf ("(MAIN NAME)  ");
     438        }
    437439    }
    438440#endif /* notdef */
     
    453455 *-----------------------------------------------------------------------
    454456 * Targ_FmtTime --
    455  *      Format a modification time in some reasonable way and return it.
    456  *
    457  * Results:
    458  *      The time reformatted.
    459  *
    460  * Side Effects:
    461  *      The time is placed in a static area, so it is overwritten
    462  *      with each call.
     457 *      Format a modification time in some reasonable way and return it.
     458 *
     459 * Results:
     460 *      The time reformatted.
     461 *
     462 * Side Effects:
     463 *      The time is placed in a static area, so it is overwritten
     464 *      with each call.
    463465 *
    464466 *-----------------------------------------------------------------------
     
    468470    time_t    time;
    469471{
    470     struct tm           *parts;
    471     static char         buf[128];
     472    struct tm           *parts;
     473    static char         buf[128];
    472474
    473475    parts = localtime(&time);
     
    487489 *-----------------------------------------------------------------------
    488490 * Targ_PrintType --
    489  *      Print out a type field giving only those attributes the user can
    490  *      set.
     491 *      Print out a type field giving only those attributes the user can
     492 *      set.
    491493 *
    492494 * Results:
     
    502504    register int    tbit;
    503505
    504 #ifdef __STDC__
    505 #define PRINTBIT(attr)  case CONCAT(OP_,attr): printf("." #attr " "); break
     506#if defined(__STDC__) || defined(__IBMC__)
     507#define PRINTBIT(attr)  case CONCAT(OP_,attr): printf("." #attr " "); break
    506508#define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG)) printf("." #attr " "); break
    507509#else
    508 #define PRINTBIT(attr)  case CONCAT(OP_,attr): printf(".attr "); break
    509 #define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG)) printf(".attr "); break
     510#define PRINTBIT(attr)  case CONCAT(OP_,attr): printf(".attr "); break
     511#define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG)) printf(".attr "); break
    510512#endif /* __STDC__ */
    511513
     
    513515
    514516    while (type) {
    515         tbit = 1 << (ffs(type) - 1);
    516         type &= ~tbit;
    517 
    518         switch(tbit) {
    519             PRINTBIT(OPTIONAL);
    520             PRINTBIT(USE);
    521             PRINTBIT(EXEC);
    522             PRINTBIT(IGNORE);
    523             PRINTBIT(PRECIOUS);
    524             PRINTBIT(SILENT);
    525             PRINTBIT(MAKE);
    526             PRINTBIT(JOIN);
    527             PRINTBIT(INVISIBLE);
    528             PRINTBIT(NOTMAIN);
     517        tbit = 1 << (ffs(type) - 1);
     518        type &= ~tbit;
     519
     520        switch(tbit) {
     521            PRINTBIT(OPTIONAL);
     522            PRINTBIT(USE);
     523            PRINTBIT(EXEC);
     524            PRINTBIT(IGNORE);
     525            PRINTBIT(PRECIOUS);
     526            PRINTBIT(SILENT);
     527            PRINTBIT(MAKE);
     528            PRINTBIT(JOIN);
     529            PRINTBIT(INVISIBLE);
     530            PRINTBIT(NOTMAIN);
    529531#ifdef USE_ARCHIVES
    530             PRINTDBIT(LIB);
     532            PRINTDBIT(LIB);
    531533            /*XXX: MEMBER is defined, so CONCAT(OP_,MEMBER) gives OP_"%" */
    532             case OP_MEMBER: if (DEBUG(TARG)) printf(".MEMBER "); break;
    533             PRINTDBIT(ARCHV);
     534            case OP_MEMBER: if (DEBUG(TARG)) printf(".MEMBER "); break;
     535            PRINTDBIT(ARCHV);
    534536#endif
    535         }
     537        }
    536538    }
    537539}
     
    540542 *-----------------------------------------------------------------------
    541543 * TargPrintNode --
    542  *      print the contents of a node
     544 *      print the contents of a node
    543545 *-----------------------------------------------------------------------
    544546 */
     
    546548TargPrintNode (gnp, passp)
    547549    ClientData   gnp;
    548     ClientData  passp;
     550    ClientData  passp;
    549551{
    550552    GNode         *gn = (GNode *) gnp;
    551     int           pass = *(int *) passp;
     553    int           pass = *(int *) passp;
    552554    if (!OP_NOP(gn->type)) {
    553         printf("#\n");
    554         if (gn == mainTarg) {
    555             printf("# *** MAIN TARGET ***\n");
    556         }
    557         if (pass == 2) {
    558             if (gn->unmade) {
    559                 printf("# %d unmade children\n", gn->unmade);
    560             } else {
    561                 printf("# No unmade children\n");
    562             }
    563             if (! (gn->type & (OP_JOIN|OP_USE|OP_EXEC))) {
    564                 if (gn->mtime != 0) {
    565                     printf("# last modified %s: %s\n",
    566                               Targ_FmtTime(gn->mtime),
    567                               (gn->made == UNMADE ? "unmade" :
    568                                (gn->made == MADE ? "made" :
    569                                 (gn->made == UPTODATE ? "up-to-date" :
    570                                 "error when made"))));
    571                 } else if (gn->made != UNMADE) {
    572                     printf("# non-existent (maybe): %s\n",
    573                               (gn->made == MADE ? "made" :
    574                                (gn->made == UPTODATE ? "up-to-date" :
    575                                 (gn->made == ERROR ? "error when made" :
    576                                 "aborted"))));
    577                 } else {
    578                     printf("# unmade\n");
    579                 }
    580             }
    581             if (!Lst_IsEmpty (gn->iParents)) {
    582                 printf("# implicit parents: ");
    583                 Lst_ForEach (gn->iParents, TargPrintName, (ClientData)0);
    584                 fputc ('\n', stdout);
    585             }
    586         }
    587         if (!Lst_IsEmpty (gn->parents)) {
    588             printf("# parents: ");
    589             Lst_ForEach (gn->parents, TargPrintName, (ClientData)0);
    590             fputc ('\n', stdout);
    591         }
    592 
    593         printf("%-16s", gn->name);
    594         switch (gn->type & OP_OPMASK) {
    595             case OP_DEPENDS:
    596                 printf(": "); break;
    597             case OP_FORCE:
    598                 printf("! "); break;
    599             case OP_DOUBLEDEP:
    600                 printf(":: "); break;
    601         }
    602         Targ_PrintType (gn->type);
    603         Lst_ForEach (gn->children, TargPrintName, (ClientData)0);
    604         fputc ('\n', stdout);
    605         Lst_ForEach (gn->commands, Targ_PrintCmd, (ClientData)0);
    606         printf("\n\n");
    607         if (gn->type & OP_DOUBLEDEP) {
    608             Lst_ForEach (gn->cohorts, TargPrintNode, (ClientData)&pass);
    609         }
     555        printf("#\n");
     556        if (gn == mainTarg) {
     557            printf("# *** MAIN TARGET ***\n");
     558        }
     559        if (pass == 2) {
     560            if (gn->unmade) {
     561                printf("# %d unmade children\n", gn->unmade);
     562            } else {
     563                printf("# No unmade children\n");
     564            }
     565            if (! (gn->type & (OP_JOIN|OP_USE|OP_EXEC))) {
     566                if (gn->mtime != 0) {
     567                    printf("# last modified %s: %s\n",
     568                              Targ_FmtTime(gn->mtime),
     569                              (gn->made == UNMADE ? "unmade" :
     570                               (gn->made == MADE ? "made" :
     571                                (gn->made == UPTODATE ? "up-to-date" :
     572                                "error when made"))));
     573                } else if (gn->made != UNMADE) {
     574                    printf("# non-existent (maybe): %s\n",
     575                              (gn->made == MADE ? "made" :
     576                               (gn->made == UPTODATE ? "up-to-date" :
     577                                (gn->made == ERROR ? "error when made" :
     578                                "aborted"))));
     579                } else {
     580                    printf("# unmade\n");
     581                }
     582            }
     583            if (!Lst_IsEmpty (gn->iParents)) {
     584                printf("# implicit parents: ");
     585                Lst_ForEach (gn->iParents, TargPrintName, (ClientData)0);
     586                fputc ('\n', stdout);
     587            }
     588        }
     589        if (!Lst_IsEmpty (gn->parents)) {
     590            printf("# parents: ");
     591            Lst_ForEach (gn->parents, TargPrintName, (ClientData)0);
     592            fputc ('\n', stdout);
     593        }
     594
     595        printf("%-16s", gn->name);
     596        switch (gn->type & OP_OPMASK) {
     597            case OP_DEPENDS:
     598                printf(": "); break;
     599            case OP_FORCE:
     600                printf("! "); break;
     601            case OP_DOUBLEDEP:
     602                printf(":: "); break;
     603        }
     604        Targ_PrintType (gn->type);
     605        Lst_ForEach (gn->children, TargPrintName, (ClientData)0);
     606        fputc ('\n', stdout);
     607        Lst_ForEach (gn->commands, Targ_PrintCmd, (ClientData)0);
     608        printf("\n\n");
     609        if (gn->type & OP_DOUBLEDEP) {
     610            Lst_ForEach (gn->cohorts, TargPrintNode, (ClientData)&pass);
     611        }
    610612    }
    611613    return (0);
     
    615617 *-----------------------------------------------------------------------
    616618 * TargPrintOnlySrc --
    617  *      Print only those targets that are just a source.
    618  *
    619  * Results:
    620  *      0.
    621  *
    622  * Side Effects:
    623  *      The name of each file is printed preceeded by #\t
     619 *      Print only those targets that are just a source.
     620 *
     621 * Results:
     622 *      0.
     623 *
     624 * Side Effects:
     625 *      The name of each file is printed preceeded by #\t
    624626 *
    625627 *-----------------------------------------------------------------------
     
    627629static int
    628630TargPrintOnlySrc(gnp, dummy)
    629     ClientData    gnp;
    630     ClientData    dummy;
    631 {
    632     GNode         *gn = (GNode *) gnp;
     631    ClientData    gnp;
     632    ClientData    dummy;
     633{
     634    GNode         *gn = (GNode *) gnp;
    633635    if (OP_NOP(gn->type))
    634         printf("#\t%s [%s]\n", gn->name, gn->path ? gn->path : gn->name);
     636        printf("#\t%s [%s]\n", gn->name, gn->path ? gn->path : gn->name);
    635637
    636638    return (dummy ? 0 : 0);
     
    640642 *-----------------------------------------------------------------------
    641643 * Targ_PrintGraph --
    642  *      print the entire graph. heh heh
    643  *
    644  * Results:
    645  *      none
    646  *
    647  * Side Effects:
    648  *      lots o' output
     644 *      print the entire graph. heh heh
     645 *
     646 * Results:
     647 *      none
     648 *
     649 * Side Effects:
     650 *      lots o' output
    649651 *-----------------------------------------------------------------------
    650652 */
    651653void
    652654Targ_PrintGraph (pass)
    653     int     pass;       /* Which pass this is. 1 => no processing
    654                         * 2 => processing done */
     655    int     pass;       /* Which pass this is. 1 => no processing
     656                        * 2 => processing done */
    655657{
    656658    printf("#*** Input graph:\n");
  • trunk/src/kmk/util.c

    r35 r51  
    55#ifndef lint
    66static char rcsid[] = "$FreeBSD: src/usr.bin/make/util.c,v 1.5.2.2 2001/02/13 03:13:58 will Exp $";
     7#define KLIBFILEDEF rcsid
    78#endif
    89
     
    2728    static char buf[100];
    2829    if (e < 0 || e >= sys_nerr) {
    29         sprintf(buf, "Unknown error %d", e);
    30         return buf;
     30        sprintf(buf, "Unknown error %d", e);
     31        return buf;
    3132    }
    3233    else
    33         return sys_errlist[e];
     34        return sys_errlist[e];
    3435}
    3536#endif
     
    5051
    5152    if (str == NULL)
    52         return NULL;
     53        return NULL;
    5354    len = strlen(str) + 1;
    5455    if ((p = emalloc(len)) == NULL)
    55         return NULL;
     56        return NULL;
    5657
    5758    return memcpy(p, str, len);
     
    6061#endif
    6162
    62 #if defined(sun) || defined(__hpux) || defined(__sgi) || defined(__EMX__) || (defined(OS2) && defined(__IBMC__))
     63#ifndef USE_KLIB
     64#if defined(sun) || defined(__hpux) || defined(__sgi) || defined(__EMX__)
    6365
    6466int
     
    7577
    7678    if (ptr == NULL)
    77         return -1;
     79        return -1;
    7880
    7981    p = ptr;
    8082
    8183    while (*name)
    82         *p++ = *name++;
     84        *p++ = *name++;
    8385
    8486    *p++ = '=';
    8587
    8688    while (*value)
    87         *p++ = *value++;
     89        *p++ = *value++;
    8890
    8991    *p = '\0';
     
    9395    return len;
    9496}
     97#endif
    9598#endif
    9699
     
    157160
    158161/* strrcpy():
    159  *      Like strcpy, going backwards and returning the new pointer
     162 *      Like strcpy, going backwards and returning the new pointer
    160163 */
    161164static char *
     
    166169
    167170    while (len)
    168         *--ptr = str[--len];
     171        *--ptr = str[--len];
    169172
    170173    return (ptr);
     
    185188    /* find the inode of root */
    186189    if (stat("/", &st_root) == -1) {
    187         (void) sprintf(pathname,
    188                         "getwd: Cannot stat \"/\" (%s)", strerror(errno));
    189         return (NULL);
     190        (void) sprintf(pathname,
     191                        "getwd: Cannot stat \"/\" (%s)", strerror(errno));
     192        return (NULL);
    190193    }
    191194    pathbuf[MAXPATHLEN - 1] = '\0';
     
    196199    /* find the inode of the current directory */
    197200    if (lstat(".", &st_cur) == -1) {
    198         (void) sprintf(pathname,
    199                         "getwd: Cannot stat \".\" (%s)", strerror(errno));
    200         return (NULL);
     201        (void) sprintf(pathname,
     202                        "getwd: Cannot stat \".\" (%s)", strerror(errno));
     203        return (NULL);
    201204    }
    202205    nextpathptr = strrcpy(nextpathptr, "../");
     
    205208    for (;;) {
    206209
    207         /* look if we found root yet */
    208         if (st_cur.st_ino == st_root.st_ino &&
    209             DEV_DEV_COMPARE(st_cur.st_dev, st_root.st_dev)) {
    210             (void) strcpy(pathname, *pathptr != '/' ? "/" : pathptr);
    211             return (pathname);
    212         }
    213 
    214         /* open the parent directory */
    215         if (stat(nextpathptr, &st_dotdot) == -1) {
    216             snprintf(pathname, sizeof(pathname),
    217                             "getwd: Cannot stat directory \"%s\" (%s)",
    218                             nextpathptr, strerror(errno));
    219             return (NULL);
    220         }
    221         if ((dp = opendir(nextpathptr)) == NULL) {
    222              snprintf(pathname, sizeof(pathname),
    223                             "getwd: Cannot open directory \"%s\" (%s)",
    224                             nextpathptr, strerror(errno));
    225             return (NULL);
    226         }
    227 
    228         /* look in the parent for the entry with the same inode */
    229         if (DEV_DEV_COMPARE(st_dotdot.st_dev, st_cur.st_dev)) {
    230             /* Parent has same device. No need to stat every member */
    231             for (d = readdir(dp); d != NULL; d = readdir(dp))
    232                 if (d->d_fileno == st_cur.st_ino)
    233                     break;
    234         }
    235         else {
    236             /*
    237              * Parent has a different device. This is a mount point so we
    238              * need to stat every member
    239              */
    240             for (d = readdir(dp); d != NULL; d = readdir(dp)) {
    241                 if (ISDOT(d->d_name) || ISDOTDOT(d->d_name))
    242                     continue;
    243                 (void) strcpy(cur_name_add, d->d_name);
    244                 if (lstat(nextpathptr, &st_next) == -1) {
    245                     snprintf(pathname, sizeof(pathname), "getwd: Cannot stat \"%s\" (%s)",
    246                                     d->d_name, strerror(errno));
    247                     (void) closedir(dp);
    248                     return (NULL);
    249                 }
    250                 /* check if we found it yet */
    251                 if (st_next.st_ino == st_cur.st_ino &&
    252                     DEV_DEV_COMPARE(st_next.st_dev, st_cur.st_dev))
    253                     break;
    254             }
    255         }
    256         if (d == NULL) {
    257             (void) sprintf(pathname, "getwd: Cannot find \".\" in \"..\"");
    258             (void) closedir(dp);
    259             return (NULL);
    260         }
    261         st_cur = st_dotdot;
    262         pathptr = strrcpy(pathptr, d->d_name);
    263         pathptr = strrcpy(pathptr, "/");
    264         nextpathptr = strrcpy(nextpathptr, "../");
    265         (void) closedir(dp);
    266         *cur_name_add = '\0';
     210        /* look if we found root yet */
     211        if (st_cur.st_ino == st_root.st_ino &&
     212            DEV_DEV_COMPARE(st_cur.st_dev, st_root.st_dev)) {
     213            (void) strcpy(pathname, *pathptr != '/' ? "/" : pathptr);
     214            return (pathname);
     215        }
     216
     217        /* open the parent directory */
     218        if (stat(nextpathptr, &st_dotdot) == -1) {
     219            snprintf(pathname, sizeof(pathname),
     220                            "getwd: Cannot stat directory \"%s\" (%s)",
     221                            nextpathptr, strerror(errno));
     222            return (NULL);
     223        }
     224        if ((dp = opendir(nextpathptr)) == NULL) {
     225             snprintf(pathname, sizeof(pathname),
     226                            "getwd: Cannot open directory \"%s\" (%s)",
     227                            nextpathptr, strerror(errno));
     228            return (NULL);
     229        }
     230
     231        /* look in the parent for the entry with the same inode */
     232        if (DEV_DEV_COMPARE(st_dotdot.st_dev, st_cur.st_dev)) {
     233            /* Parent has same device. No need to stat every member */
     234            for (d = readdir(dp); d != NULL; d = readdir(dp))
     235                if (d->d_fileno == st_cur.st_ino)
     236                    break;
     237        }
     238        else {
     239            /*
     240             * Parent has a different device. This is a mount point so we
     241             * need to stat every member
     242             */
     243            for (d = readdir(dp); d != NULL; d = readdir(dp)) {
     244                if (ISDOT(d->d_name) || ISDOTDOT(d->d_name))
     245                    continue;
     246                (void) strcpy(cur_name_add, d->d_name);
     247                if (lstat(nextpathptr, &st_next) == -1) {
     248                    snprintf(pathname, sizeof(pathname), "getwd: Cannot stat \"%s\" (%s)",
     249                                    d->d_name, strerror(errno));
     250                    (void) closedir(dp);
     251                    return (NULL);
     252                }
     253                /* check if we found it yet */
     254                if (st_next.st_ino == st_cur.st_ino &&
     255                    DEV_DEV_COMPARE(st_next.st_dev, st_cur.st_dev))
     256                    break;
     257            }
     258        }
     259        if (d == NULL) {
     260            (void) sprintf(pathname, "getwd: Cannot find \".\" in \"..\"");
     261            (void) closedir(dp);
     262            return (NULL);
     263        }
     264        st_cur = st_dotdot;
     265        pathptr = strrcpy(pathptr, d->d_name);
     266        pathptr = strrcpy(pathptr, "/");
     267        nextpathptr = strrcpy(nextpathptr, "../");
     268        (void) closedir(dp);
     269        *cur_name_add = '\0';
    267270    }
    268271} /* end getwd */
     
    336339
    337340    if (sigaction(s, &sa, &osa) == -1)
    338         return SIG_ERR;
     341        return SIG_ERR;
    339342    else
    340         return osa.sa_handler;
    341 }
    342 
    343 #endif
     343        return osa.sa_handler;
     344}
     345
     346#endif
  • trunk/src/kmk/var.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[] = "@(#)var.c       8.3 (Berkeley) 3/19/94";
     41static char sccsid[] = "@(#)var.c       8.3 (Berkeley) 3/19/94";
    4242#else
    4343static const char rcsid[] =
    4444  "$FreeBSD: src/usr.bin/make/var.c,v 1.16.2.3 2002/02/27 14:18:57 cjc Exp $";
    4545#endif
     46#define KLIBFILEDEF rcsid
    4647#endif /* not lint */
    4748
    4849/*-
    4950 * var.c --
    50  *      Variable-handling functions
     51 *      Variable-handling functions
    5152 *
    5253 * Interface:
    53  *      Var_Set             Set the value of a variable in the given
    54  *                          context. The variable is created if it doesn't
    55  *                          yet exist. The value and variable name need not
    56  *                          be preserved.
    57  *
    58  *      Var_Append          Append more characters to an existing variable
    59  *                          in the given context. The variable needn't
    60  *                          exist already -- it will be created if it doesn't.
    61  *                          A space is placed between the old value and the
    62  *                          new one.
    63  *
    64  *      Var_Exists          See if a variable exists.
    65  *
    66  *      Var_Value           Return the value of a variable in a context or
    67  *                          NULL if the variable is undefined.
    68  *
    69  *      Var_Subst           Substitute named variable, or all variables if
    70  *                          NULL in a string using
    71  *                          the given context as the top-most one. If the
    72  *                          third argument is non-zero, Parse_Error is
    73  *                          called if any variables are undefined.
    74  *
    75  *      Var_Parse           Parse a variable expansion from a string and
    76  *                          return the result and the number of characters
    77  *                          consumed.
    78  *
    79  *      Var_Delete          Delete a variable in a context.
    80  *
    81  *      Var_Init            Initialize this module.
     54 *      Var_Set             Set the value of a variable in the given
     55 *                          context. The variable is created if it doesn't
     56 *                          yet exist. The value and variable name need not
     57 *                          be preserved.
     58 *
     59 *      Var_Append          Append more characters to an existing variable
     60 *                          in the given context. The variable needn't
     61 *                          exist already -- it will be created if it doesn't.
     62 *                          A space is placed between the old value and the
     63 *                          new one.
     64 *
     65 *      Var_Exists          See if a variable exists.
     66 *
     67 *      Var_Value           Return the value of a variable in a context or
     68 *                          NULL if the variable is undefined.
     69 *
     70 *      Var_Subst           Substitute named variable, or all variables if
     71 *                          NULL in a string using
     72 *                          the given context as the top-most one. If the
     73 *                          third argument is non-zero, Parse_Error is
     74 *                          called if any variables are undefined.
     75 *
     76 *      Var_Parse           Parse a variable expansion from a string and
     77 *                          return the result and the number of characters
     78 *                          consumed.
     79 *
     80 *      Var_Delete          Delete a variable in a context.
     81 *
     82 *      Var_Init            Initialize this module.
    8283 *
    8384 * Debugging:
    84  *      Var_Dump            Print out all variables defined in the given
    85  *                          context.
     85 *      Var_Dump            Print out all variables defined in the given
     86 *                          context.
    8687 *
    8788 * XXX: There's a lot of duplication in these functions.
     
    106107 * a flag, as things outside this module don't give a hoot.
    107108 */
    108 char    var_Error[] = "";
     109char    var_Error[] = "";
    109110
    110111/*
     
    113114 * identical string instances...
    114115 */
    115 static char     varNoError[] = "";
     116static char     varNoError[] = "";
    116117
    117118/*
    118119 * Internally, variables are contained in four different contexts.
    119  *      1) the environment. They may not be changed. If an environment
    120  *          variable is appended-to, the result is placed in the global
    121  *          context.
    122  *      2) the global context. Variables set in the Makefile are located in
    123  *          the global context. It is the penultimate context searched when
    124  *          substituting.
    125  *      3) the command-line context. All variables set on the command line
    126  *         are placed in this context. They are UNALTERABLE once placed here.
    127  *      4) the local context. Each target has associated with it a context
    128  *         list. On this list are located the structures describing such
    129  *         local variables as $(@) and $(*)
     120 *      1) the environment. They may not be changed. If an environment
     121 *          variable is appended-to, the result is placed in the global
     122 *          context.
     123 *      2) the global context. Variables set in the Makefile are located in
     124 *          the global context. It is the penultimate context searched when
     125 *          substituting.
     126 *      3) the command-line context. All variables set on the command line
     127 *         are placed in this context. They are UNALTERABLE once placed here.
     128 *      4) the local context. Each target has associated with it a context
     129 *         list. On this list are located the structures describing such
     130 *         local variables as $(@) and $(*)
    130131 * The four contexts are searched in the reverse order from which they are
    131132 * listed.
     
    134135GNode          *VAR_CMD;      /* variables defined on the command-line */
    135136
    136 static Lst      allVars;      /* List of all variables */
    137 
    138 #define FIND_CMD        0x1   /* look in VAR_CMD when searching */
    139 #define FIND_GLOBAL     0x2   /* look in VAR_GLOBAL as well */
    140 #define FIND_ENV        0x4   /* look in the environment also */
     137static Lst      allVars;      /* List of all variables */
     138
     139#define FIND_CMD        0x1   /* look in VAR_CMD when searching */
     140#define FIND_GLOBAL     0x2   /* look in VAR_GLOBAL as well */
     141#define FIND_ENV        0x4   /* look in the environment also */
    141142
    142143typedef struct Var {
    143     char          *name;        /* the variable's name */
    144     Buffer        val;          /* its value */
    145     int           flags;        /* miscellaneous status flags */
    146 #define VAR_IN_USE      1           /* Variable's value currently being used.
    147                                      * Used to avoid recursion */
    148 #define VAR_FROM_ENV    2           /* Variable comes from the environment */
    149 #define VAR_JUNK        4           /* Variable is a junk variable that
    150                                      * should be destroyed when done with
    151                                      * it. Used by Var_Parse for undefined,
    152                                      * modified variables */
     144    char          *name;        /* the variable's name */
     145    Buffer        val;          /* its value */
     146    int           flags;        /* miscellaneous status flags */
     147#define VAR_IN_USE      1           /* Variable's value currently being used.
     148                                     * Used to avoid recursion */
     149#define VAR_FROM_ENV    2           /* Variable comes from the environment */
     150#define VAR_JUNK        4           /* Variable is a junk variable that
     151                                     * should be destroyed when done with
     152                                     * it. Used by Var_Parse for undefined,
     153                                     * modified variables */
    153154}  Var;
    154155
    155156/* Var*Pattern flags */
    156 #define VAR_SUB_GLOBAL  0x01    /* Apply substitution globally */
    157 #define VAR_SUB_ONE     0x02    /* Apply substitution to one word */
    158 #define VAR_SUB_MATCHED 0x04    /* There was a match */
    159 #define VAR_MATCH_START 0x08    /* Match at start of word */
    160 #define VAR_MATCH_END   0x10    /* Match at end of word */
    161 #define VAR_NOSUBST     0x20    /* don't expand vars in VarGetPattern */
     157#define VAR_SUB_GLOBAL  0x01    /* Apply substitution globally */
     158#define VAR_SUB_ONE     0x02    /* Apply substitution to one word */
     159#define VAR_SUB_MATCHED 0x04    /* There was a match */
     160#define VAR_MATCH_START 0x08    /* Match at start of word */
     161#define VAR_MATCH_END   0x10    /* Match at end of word */
     162#define VAR_NOSUBST     0x20    /* don't expand vars in VarGetPattern */
    162163
    163164typedef struct {
    164     char          *lhs;     /* String to match */
    165     int           leftLen;  /* Length of string */
    166     char          *rhs;     /* Replacement string (w/ &'s removed) */
    167     int           rightLen; /* Length of replacement */
    168     int           flags;
     165    char          *lhs;     /* String to match */
     166    int           leftLen;  /* Length of string */
     167    char          *rhs;     /* Replacement string (w/ &'s removed) */
     168    int           rightLen; /* Length of replacement */
     169    int           flags;
    169170} VarPattern;
    170171
    171172typedef struct {
    172     regex_t        re;
    173     int            nsub;
    174     regmatch_t    *matches;
    175     char          *replace;
    176     int            flags;
     173    regex_t        re;
     174    int            nsub;
     175    regmatch_t    *matches;
     176    char          *replace;
     177    int            flags;
    177178} VarREPattern;
    178179
     
    185186static Boolean VarSuffix __P((char *, Boolean, Buffer, ClientData));
    186187static Boolean VarRoot __P((char *, Boolean, Buffer, ClientData));
    187 #if defined(NMAKE) || defined(KMK)
     188#ifdef USE_BASEANDROOT_MODIFIERS
    188189static Boolean VarBase __P((char *, Boolean, Buffer, ClientData));
    189190#endif
     
    197198static Boolean VarSubstitute __P((char *, Boolean, Buffer, ClientData));
    198199static char *VarGetPattern __P((GNode *, int, char **, int, int *, int *,
    199                                 VarPattern *));
     200                                VarPattern *));
    200201static char *VarQuote __P((char *));
    201202static char *VarModify __P((char *, Boolean (*)(char *, Boolean, Buffer,
    202                                                 ClientData),
    203                             ClientData));
     203                                                ClientData),
     204                            ClientData));
    204205static int VarPrintVar __P((ClientData, ClientData));
    205206
     
    207208 *-----------------------------------------------------------------------
    208209 * VarCmp  --
    209  *      See if the given variable matches the named one. Called from
    210  *      Lst_Find when searching for a variable of a given name.
    211  *
    212  * Results:
    213  *      0 if they match. non-zero otherwise.
    214  *
    215  * Side Effects:
    216  *      none
     210 *      See if the given variable matches the named one. Called from
     211 *      Lst_Find when searching for a variable of a given name.
     212 *
     213 * Results:
     214 *      0 if they match. non-zero otherwise.
     215 *
     216 * Side Effects:
     217 *      none
    217218 *-----------------------------------------------------------------------
    218219 */
    219220static int
    220221VarCmp (v, name)
    221     ClientData     v;           /* VAR structure to compare */
    222     ClientData     name;        /* name to look for */
     222    ClientData     v;           /* VAR structure to compare */
     223    ClientData     name;        /* name to look for */
    223224{
    224225    return (strcmp ((char *) name, ((Var *) v)->name));
     
    228229 *-----------------------------------------------------------------------
    229230 * StrCmp  --
    230  *      See if the given strings matches. Called from
    231  *      Lst_Find when searching for a environment-variable-overrided var.
    232  *
    233  * Results:
    234  *      0 if they match. non-zero otherwise.
    235  *
    236  * Side Effects:
    237  *      none
     231 *      See if the given strings matches. Called from
     232 *      Lst_Find when searching for a environment-variable-overrided var.
     233 *
     234 * Results:
     235 *      0 if they match. non-zero otherwise.
     236 *
     237 * Side Effects:
     238 *      none
    238239 *-----------------------------------------------------------------------
    239240 */
     
    251252 *-----------------------------------------------------------------------
    252253 * VarFind --
    253  *      Find the given variable in the given context and any other contexts
    254  *      indicated.
    255  *
    256  * Results:
    257  *      A pointer to the structure describing the desired variable or
    258  *      NIL if the variable does not exist.
    259  *
    260  * Side Effects:
    261  *      None
     254 *      Find the given variable in the given context and any other contexts
     255 *      indicated.
     256 *
     257 * Results:
     258 *      A pointer to the structure describing the desired variable or
     259 *      NIL if the variable does not exist.
     260 *
     261 * Side Effects:
     262 *      None
    262263 *-----------------------------------------------------------------------
    263264 */
    264265static Var *
    265266VarFind (name, ctxt, flags)
    266     char                *name;  /* name to find */
    267     GNode               *ctxt;  /* context in which to find it */
    268     int                 flags;  /* FIND_GLOBAL set means to look in the
    269                                 * VAR_GLOBAL context as well.
    270                                 * FIND_CMD set means to look in the VAR_CMD
    271                                 * context also.
    272                                 * FIND_ENV set means to look in the
    273                                 * environment */
    274 {
    275     Boolean             localCheckEnvFirst;
    276     LstNode             var;
    277     Var                 *v;
    278 
    279         /*
    280         * If the variable name begins with a '.', it could very well be one of
    281         * the local ones.  We check the name against all the local variables
    282         * and substitute the short version in for 'name' if it matches one of
    283         * them.
    284         */
    285         if (*name == '.' && isupper((unsigned char) name[1]))
    286                 switch (name[1]) {
    287                 case 'A':
    288                         if (!strcmp(name, ".ALLSRC"))
    289                                 name = ALLSRC;
     267    char                *name;  /* name to find */
     268    GNode               *ctxt;  /* context in which to find it */
     269    int                 flags;  /* FIND_GLOBAL set means to look in the
     270                                * VAR_GLOBAL context as well.
     271                                * FIND_CMD set means to look in the VAR_CMD
     272                                * context also.
     273                                * FIND_ENV set means to look in the
     274                                * environment */
     275{
     276    Boolean             localCheckEnvFirst;
     277    LstNode             var;
     278    Var                 *v;
     279
     280        /*
     281        * If the variable name begins with a '.', it could very well be one of
     282        * the local ones.  We check the name against all the local variables
     283        * and substitute the short version in for 'name' if it matches one of
     284        * them.
     285        */
     286        if (*name == '.' && isupper((unsigned char) name[1]))
     287                switch (name[1]) {
     288                case 'A':
     289                        if (!strcmp(name, ".ALLSRC"))
     290                                name = ALLSRC;
    290291#ifdef USE_ARCHIVES
    291                         if (!strcmp(name, ".ARCHIVE"))
    292                                 name = ARCHIVE;
     292                        if (!strcmp(name, ".ARCHIVE"))
     293                                name = ARCHIVE;
    293294#endif
    294                         break;
    295                 case 'I':
    296                         if (!strcmp(name, ".IMPSRC"))
    297                                 name = IMPSRC;
    298                         break;
     295                        break;
     296                case 'I':
     297                        if (!strcmp(name, ".IMPSRC"))
     298                                name = IMPSRC;
     299                        break;
    299300#ifdef USE_ARCHIVES
    300                 case 'M':
    301                         if (!strcmp(name, ".MEMBER"))
    302                                 name = MEMBER;
    303                         break;
     301                case 'M':
     302                        if (!strcmp(name, ".MEMBER"))
     303                                name = MEMBER;
     304                        break;
    304305#endif
    305                 case 'O':
    306                         if (!strcmp(name, ".OODATE"))
    307                                 name = OODATE;
    308                         break;
    309                 case 'P':
    310                         if (!strcmp(name, ".PREFIX"))
    311                                 name = PREFIX;
     306                case 'O':
     307                        if (!strcmp(name, ".OODATE"))
     308                                name = OODATE;
     309                        break;
     310                case 'P':
     311                        if (!strcmp(name, ".PREFIX"))
     312                                name = PREFIX;
    312313                        #ifdef USE_PARENTS
    313314                        else if (!strcmp(name, ".PARENTS"))
    314315                                name = PARENTS;
    315316                        #endif
    316                         break;
    317                 case 'T':
    318                         if (!strcmp(name, ".TARGET"))
    319                                 name = TARGET;
    320                         break;
    321                 }
     317                        break;
     318                case 'T':
     319                        if (!strcmp(name, ".TARGET"))
     320                                name = TARGET;
     321                        break;
     322                }
    322323
    323324    /*
     
    326327     */
    327328    if (Lst_Find (envFirstVars, (ClientData)name,
    328                   (int (*)(ClientData, ClientData)) VarStrCmp) != NILLNODE)
     329                  (int (*)(ClientData, ClientData)) VarStrCmp) != NILLNODE)
    329330    {
    330         localCheckEnvFirst = TRUE;
     331        localCheckEnvFirst = TRUE;
    331332    } else {
    332         localCheckEnvFirst = FALSE;
     333        localCheckEnvFirst = FALSE;
    333334    }
    334335
     
    341342
    342343    if ((var == NILLNODE) && (flags & FIND_CMD) && (ctxt != VAR_CMD)) {
    343         var = Lst_Find (VAR_CMD->context, (ClientData)name, VarCmp);
     344        var = Lst_Find (VAR_CMD->context, (ClientData)name, VarCmp);
    344345    }
    345346    if ((var == NILLNODE) && (flags & FIND_GLOBAL) && (ctxt != VAR_GLOBAL) &&
    346         !checkEnvFirst && !localCheckEnvFirst)
     347        !checkEnvFirst && !localCheckEnvFirst)
    347348    {
    348         var = Lst_Find (VAR_GLOBAL->context, (ClientData)name, VarCmp);
     349        var = Lst_Find (VAR_GLOBAL->context, (ClientData)name, VarCmp);
    349350    }
    350351    if ((var == NILLNODE) && (flags & FIND_ENV)) {
    351352        #ifdef USE_KLIB
    352         const char *env;
    353         if ((env = kEnvGet (name)) != NULL) {
     353        const char *env;
     354        if ((env = kEnvGet (name)) != NULL) {
    354355        #else
    355356        char *env;
    356         if ((env = getenv (name)) != NULL) {
     357        if ((env = getenv (name)) != NULL) {
    357358        #endif
    358             int         len;
    359 
    360             v = (Var *) emalloc(sizeof(Var));
    361             v->name = estrdup(name);
    362 
    363             len = strlen(env);
    364 
    365             v->val = Buf_Init(len);
    366             Buf_AddBytes(v->val, len, (Byte *)env);
    367 
    368             v->flags = VAR_FROM_ENV;
    369             return (v);
    370         } else if ((checkEnvFirst || localCheckEnvFirst) &&
    371                    (flags & FIND_GLOBAL) && (ctxt != VAR_GLOBAL))
    372         {
    373             var = Lst_Find (VAR_GLOBAL->context, (ClientData)name, VarCmp);
    374             if (var == NILLNODE) {
    375                 return ((Var *) NIL);
    376             } else {
    377                 return ((Var *)Lst_Datum(var));
    378             }
    379         } else {
    380             return((Var *)NIL);
    381         }
     359            int         len;
     360
     361            v = (Var *) emalloc(sizeof(Var));
     362            v->name = estrdup(name);
     363
     364            len = strlen(env);
     365
     366            v->val = Buf_Init(len);
     367            Buf_AddBytes(v->val, len, (Byte *)env);
     368
     369            v->flags = VAR_FROM_ENV;
     370            return (v);
     371        } else if ((checkEnvFirst || localCheckEnvFirst) &&
     372                   (flags & FIND_GLOBAL) && (ctxt != VAR_GLOBAL))
     373        {
     374            var = Lst_Find (VAR_GLOBAL->context, (ClientData)name, VarCmp);
     375            if (var == NILLNODE) {
     376                return ((Var *) NIL);
     377            } else {
     378                return ((Var *)Lst_Datum(var));
     379            }
     380        } else {
     381            return((Var *)NIL);
     382        }
    382383    } else if (var == NILLNODE) {
    383         return ((Var *) NIL);
     384        return ((Var *) NIL);
    384385    } else {
    385         return ((Var *) Lst_Datum (var));
     386        return ((Var *) Lst_Datum (var));
    386387    }
    387388}
     
    390391 *-----------------------------------------------------------------------
    391392 * VarAdd  --
    392  *      Add a new variable of name name and value val to the given context
    393  *
    394  * Results:
    395  *      None
    396  *
    397  * Side Effects:
    398  *      The new variable is placed at the front of the given context
    399  *      The name and val arguments are duplicated so they may
    400  *      safely be freed.
     393 *      Add a new variable of name name and value val to the given context
     394 *
     395 * Results:
     396 *      None
     397 *
     398 * Side Effects:
     399 *      The new variable is placed at the front of the given context
     400 *      The name and val arguments are duplicated so they may
     401 *      safely be freed.
    401402 *-----------------------------------------------------------------------
    402403 */
    403404static void
    404405VarAdd (name, val, ctxt)
    405     char           *name;       /* name of variable to add */
    406     char           *val;        /* value to set it to */
    407     GNode          *ctxt;       /* context in which to set it */
     406    char           *name;       /* name of variable to add */
     407    char           *val;        /* value to set it to */
     408    GNode          *ctxt;       /* context in which to set it */
    408409{
    409410    register Var   *v;
    410     int           len;
     411    int           len;
    411412
    412413    v = (Var *) emalloc (sizeof (Var));
     
    423424    (void) Lst_AtEnd (allVars, (ClientData) v);
    424425    if (DEBUG(VAR)) {
    425         printf("%s:%s = %s\n", ctxt->name, name, val);
     426        printf("%s:%s = %s\n", ctxt->name, name, val);
    426427    }
    427428}
     
    431432 *-----------------------------------------------------------------------
    432433 * VarDelete  --
    433  *      Delete a variable and all the space associated with it.
    434  *
    435  * Results:
    436  *      None
    437  *
    438  * Side Effects:
    439  *      None
     434 *      Delete a variable and all the space associated with it.
     435 *
     436 * Results:
     437 *      None
     438 *
     439 * Side Effects:
     440 *      None
    440441 *-----------------------------------------------------------------------
    441442 */
     
    455456 *-----------------------------------------------------------------------
    456457 * Var_Delete --
    457  *      Remove a variable from a context.
    458  *
    459  * Results:
    460  *      None.
    461  *
    462  * Side Effects:
    463  *      The Var structure is removed and freed.
     458 *      Remove a variable from a context.
     459 *
     460 * Results:
     461 *      None.
     462 *
     463 * Side Effects:
     464 *      The Var structure is removed and freed.
    464465 *
    465466 *-----------------------------------------------------------------------
     
    467468void
    468469Var_Delete(name, ctxt)
    469     char          *name;
    470     GNode         *ctxt;
    471 {
    472     LstNode       ln;
     470    char          *name;
     471    GNode         *ctxt;
     472{
     473    LstNode       ln;
    473474
    474475    if (DEBUG(VAR)) {
    475         printf("%s:delete %s\n", ctxt->name, name);
     476        printf("%s:delete %s\n", ctxt->name, name);
    476477    }
    477478    ln = Lst_Find(ctxt->context, (ClientData)name, VarCmp);
    478479    if (ln != NILLNODE) {
    479         register Var      *v;
    480 
    481         v = (Var *)Lst_Datum(ln);
    482         Lst_Remove(ctxt->context, ln);
    483         ln = Lst_Member(allVars, v);
    484         Lst_Remove(allVars, ln);
    485         VarDelete((ClientData) v);
     480        register Var      *v;
     481
     482        v = (Var *)Lst_Datum(ln);
     483        Lst_Remove(ctxt->context, ln);
     484        ln = Lst_Member(allVars, v);
     485        Lst_Remove(allVars, ln);
     486        VarDelete((ClientData) v);
    486487    }
    487488}
     
    490491 *-----------------------------------------------------------------------
    491492 * Var_Set --
    492  *      Set the variable name to the value val in the given context.
    493  *
    494  * Results:
    495  *      None.
    496  *
    497  * Side Effects:
    498  *      If the variable doesn't yet exist, a new record is created for it.
    499  *      Else the old value is freed and the new one stuck in its place
     493 *      Set the variable name to the value val in the given context.
     494 *
     495 * Results:
     496 *      None.
     497 *
     498 * Side Effects:
     499 *      If the variable doesn't yet exist, a new record is created for it.
     500 *      Else the old value is freed and the new one stuck in its place
    500501 *
    501502 * Notes:
    502  *      The variable is searched for only in its context before being
    503  *      created in that context. I.e. if the context is VAR_GLOBAL,
    504  *      only VAR_GLOBAL->context is searched. Likewise if it is VAR_CMD, only
    505  *      VAR_CMD->context is searched. This is done to avoid the literally
    506  *      thousands of unnecessary strcmp's that used to be done to
    507  *      set, say, $(@) or $(<).
     503 *      The variable is searched for only in its context before being
     504 *      created in that context. I.e. if the context is VAR_GLOBAL,
     505 *      only VAR_GLOBAL->context is searched. Likewise if it is VAR_CMD, only
     506 *      VAR_CMD->context is searched. This is done to avoid the literally
     507 *      thousands of unnecessary strcmp's that used to be done to
     508 *      set, say, $(@) or $(<).
    508509 *-----------------------------------------------------------------------
    509510 */
    510511void
    511512Var_Set (name, val, ctxt)
    512     char           *name;       /* name of variable to set */
    513     char           *val;        /* value to give to the variable */
    514     GNode          *ctxt;       /* context in which to set it */
     513    char           *name;       /* name of variable to set */
     514    char           *val;        /* value to give to the variable */
     515    GNode          *ctxt;       /* context in which to set it */
    515516{
    516517    register Var   *v;
     
    523524    v = VarFind (name, ctxt, 0);
    524525    if (v == (Var *) NIL) {
    525         VarAdd (name, val, ctxt);
     526        VarAdd (name, val, ctxt);
    526527    } else {
    527         Buf_Discard(v->val, Buf_Size(v->val));
    528         Buf_AddBytes(v->val, strlen(val), (Byte *)val);
    529 
    530         if (DEBUG(VAR)) {
    531             printf("%s:%s = %s\n", ctxt->name, name, val);
    532         }
     528        Buf_Discard(v->val, Buf_Size(v->val));
     529        Buf_AddBytes(v->val, strlen(val), (Byte *)val);
     530
     531        if (DEBUG(VAR)) {
     532            printf("%s:%s = %s\n", ctxt->name, name, val);
     533        }
    533534    }
    534535    /*
     
    540541        kEnvSet(name, val, TRUE);
    541542        #else
    542         setenv(name, val, 1);
     543        setenv(name, val, 1);
    543544        #endif
    544545    }
     
    548549 *-----------------------------------------------------------------------
    549550 * Var_Append --
    550  *      The variable of the given name has the given value appended to it in
    551  *      the given context.
    552  *
    553  * Results:
    554  *      None
    555  *
    556  * Side Effects:
    557  *      If the variable doesn't exist, it is created. Else the strings
    558  *      are concatenated (with a space in between).
     551 *      The variable of the given name has the given value appended to it in
     552 *      the given context.
     553 *
     554 * Results:
     555 *      None
     556 *
     557 * Side Effects:
     558 *      If the variable doesn't exist, it is created. Else the strings
     559 *      are concatenated (with a space in between).
    559560 *
    560561 * Notes:
    561  *      Only if the variable is being sought in the global context is the
    562  *      environment searched.
    563  *      XXX: Knows its calling circumstances in that if called with ctxt
    564  *      an actual target, it will only search that context since only
    565  *      a local variable could be being appended to. This is actually
    566  *      a big win and must be tolerated.
     562 *      Only if the variable is being sought in the global context is the
     563 *      environment searched.
     564 *      XXX: Knows its calling circumstances in that if called with ctxt
     565 *      an actual target, it will only search that context since only
     566 *      a local variable could be being appended to. This is actually
     567 *      a big win and must be tolerated.
    567568 *-----------------------------------------------------------------------
    568569 */
    569570void
    570571Var_Append (name, val, ctxt)
    571     char           *name;       /* Name of variable to modify */
    572     char           *val;        /* String to append to it */
    573     GNode          *ctxt;       /* Context in which this should occur */
     572    char           *name;       /* Name of variable to modify */
     573    char           *val;        /* String to append to it */
     574    GNode          *ctxt;       /* Context in which this should occur */
    574575{
    575576    register Var   *v;
     
    578579
    579580    if (v == (Var *) NIL) {
    580         VarAdd (name, val, ctxt);
     581        VarAdd (name, val, ctxt);
    581582    } else {
    582         Buf_AddByte(v->val, (Byte)' ');
    583         Buf_AddBytes(v->val, strlen(val), (Byte *)val);
    584 
    585         if (DEBUG(VAR)) {
    586             printf("%s:%s = %s\n", ctxt->name, name,
    587                    (char *) Buf_GetAll(v->val, (int *)NULL));
    588         }
    589 
    590         if (v->flags & VAR_FROM_ENV) {
    591             /*
    592              * If the original variable came from the environment, we
    593              * have to install it in the global context (we could place
    594              * it in the environment, but then we should provide a way to
    595              * export other variables...)
    596              */
    597             v->flags &= ~VAR_FROM_ENV;
    598             Lst_AtFront(ctxt->context, (ClientData)v);
    599         }
     583        Buf_AddByte(v->val, (Byte)' ');
     584        Buf_AddBytes(v->val, strlen(val), (Byte *)val);
     585
     586        if (DEBUG(VAR)) {
     587            printf("%s:%s = %s\n", ctxt->name, name,
     588                   (char *) Buf_GetAll(v->val, (int *)NULL));
     589        }
     590
     591        if (v->flags & VAR_FROM_ENV) {
     592            /*
     593             * If the original variable came from the environment, we
     594             * have to install it in the global context (we could place
     595             * it in the environment, but then we should provide a way to
     596             * export other variables...)
     597             */
     598            v->flags &= ~VAR_FROM_ENV;
     599            Lst_AtFront(ctxt->context, (ClientData)v);
     600        }
    600601    }
    601602}
     
    604605 *-----------------------------------------------------------------------
    605606 * Var_Exists --
    606  *      See if the given variable exists.
    607  *
    608  * Results:
    609  *      TRUE if it does, FALSE if it doesn't
    610  *
    611  * Side Effects:
    612  *      None.
     607 *      See if the given variable exists.
     608 *
     609 * Results:
     610 *      TRUE if it does, FALSE if it doesn't
     611 *
     612 * Side Effects:
     613 *      None.
    613614 *
    614615 *-----------------------------------------------------------------------
     
    616617Boolean
    617618Var_Exists(name, ctxt)
    618     char          *name;        /* Variable to find */
    619     GNode         *ctxt;        /* Context in which to start search */
    620 {
    621     Var           *v;
     619    char          *name;        /* Variable to find */
     620    GNode         *ctxt;        /* Context in which to start search */
     621{
     622    Var           *v;
    622623
    623624    v = VarFind(name, ctxt, FIND_CMD|FIND_GLOBAL|FIND_ENV);
    624625
    625626    if (v == (Var *)NIL) {
    626         return(FALSE);
     627        return(FALSE);
    627628    } else if (v->flags & VAR_FROM_ENV) {
    628         efree(v->name);
    629         Buf_Destroy(v->val, TRUE);
    630         efree((char *)v);
     629        efree(v->name);
     630        Buf_Destroy(v->val, TRUE);
     631        efree((char *)v);
    631632    }
    632633    return(TRUE);
     
    636637 *-----------------------------------------------------------------------
    637638 * Var_Value --
    638  *      Return the value of the named variable in the given context
    639  *
    640  * Results:
    641  *      The value if the variable exists, NULL if it doesn't
    642  *
    643  * Side Effects:
    644  *      None
     639 *      Return the value of the named variable in the given context
     640 *
     641 * Results:
     642 *      The value if the variable exists, NULL if it doesn't
     643 *
     644 * Side Effects:
     645 *      None
    645646 *-----------------------------------------------------------------------
    646647 */
    647648char *
    648649Var_Value (name, ctxt, frp)
    649     char           *name;       /* name to find */
    650     GNode          *ctxt;       /* context in which to search for it */
    651     char           **frp;
     650    char           *name;       /* name to find */
     651    GNode          *ctxt;       /* context in which to search for it */
     652    char           **frp;
    652653{
    653654    Var            *v;
     
    656657    *frp = NULL;
    657658    if (v != (Var *) NIL) {
    658         char *p = ((char *)Buf_GetAll(v->val, (int *)NULL));
    659         if (v->flags & VAR_FROM_ENV) {
    660             Buf_Destroy(v->val, FALSE);
    661             efree((Address) v);
    662             *frp = p;
    663         }
    664         return p;
     659        char *p = ((char *)Buf_GetAll(v->val, (int *)NULL));
     660        if (v->flags & VAR_FROM_ENV) {
     661            Buf_Destroy(v->val, FALSE);
     662            efree((Address) v);
     663            *frp = p;
     664        }
     665        return p;
    665666    } else {
    666         return ((char *) NULL);
     667        return ((char *) NULL);
    667668    }
    668669}
     
    671672 *-----------------------------------------------------------------------
    672673 * VarHead --
    673  *      Remove the tail of the given word and place the result in the given
    674  *      buffer.
    675  *
    676  * Results:
    677  *      TRUE if characters were added to the buffer (a space needs to be
    678  *      added to the buffer before the next word).
    679  *
    680  * Side Effects:
    681  *      The trimmed word is added to the buffer.
     674 *      Remove the tail of the given word and place the result in the given
     675 *      buffer.
     676 *
     677 * Results:
     678 *      TRUE if characters were added to the buffer (a space needs to be
     679 *      added to the buffer before the next word).
     680 *
     681 * Side Effects:
     682 *      The trimmed word is added to the buffer.
    682683 *
    683684 *-----------------------------------------------------------------------
     
    685686static Boolean
    686687VarHead (word, addSpace, buf, dummy)
    687     char          *word;        /* Word to trim */
    688     Boolean       addSpace;     /* True if need to add a space to the buffer
    689                                 * before sticking in the head */
    690     Buffer        buf;          /* Buffer in which to store it */
    691     ClientData    dummy;
     688    char          *word;        /* Word to trim */
     689    Boolean       addSpace;     /* True if need to add a space to the buffer
     690                                * before sticking in the head */
     691    Buffer        buf;          /* Buffer in which to store it */
     692    ClientData    dummy;
    692693{
    693694    register char *slash;
     
    695696    slash = strrchr (word, '/');
    696697    if (slash != (char *)NULL) {
    697         if (addSpace) {
    698             Buf_AddByte (buf, (Byte)' ');
    699         }
    700         *slash = '\0';
    701         Buf_AddBytes (buf, strlen (word), (Byte *)word);
    702         *slash = '/';
    703         return (TRUE);
     698        if (addSpace) {
     699            Buf_AddByte (buf, (Byte)' ');
     700        }
     701        *slash = '\0';
     702        Buf_AddBytes (buf, strlen (word), (Byte *)word);
     703        *slash = '/';
     704        return (TRUE);
    704705    } else {
    705         /*
    706         * If no directory part, give . (q.v. the POSIX standard)
    707         */
    708         if (addSpace) {
    709             Buf_AddBytes(buf, 2, (Byte *)" .");
    710         } else {
    711             Buf_AddByte(buf, (Byte)'.');
    712         }
     706        /*
     707        * If no directory part, give . (q.v. the POSIX standard)
     708        */
     709        if (addSpace) {
     710            Buf_AddBytes(buf, 2, (Byte *)" .");
     711        } else {
     712            Buf_AddByte(buf, (Byte)'.');
     713        }
    713714    }
    714715    return(dummy ? TRUE : TRUE);
     
    718719 *-----------------------------------------------------------------------
    719720 * VarTail --
    720  *      Remove the head of the given word and place the result in the given
    721  *      buffer.
    722  *
    723  * Results:
    724  *      TRUE if characters were added to the buffer (a space needs to be
    725  *      added to the buffer before the next word).
    726  *
    727  * Side Effects:
    728  *      The trimmed word is added to the buffer.
     721 *      Remove the head of the given word and place the result in the given
     722 *      buffer.
     723 *
     724 * Results:
     725 *      TRUE if characters were added to the buffer (a space needs to be
     726 *      added to the buffer before the next word).
     727 *
     728 * Side Effects:
     729 *      The trimmed word is added to the buffer.
    729730 *
    730731 *-----------------------------------------------------------------------
     
    732733static Boolean
    733734VarTail (word, addSpace, buf, dummy)
    734     char          *word;        /* Word to trim */
    735     Boolean       addSpace;     /* TRUE if need to stick a space in the
    736                                 * buffer before adding the tail */
    737     Buffer        buf;          /* Buffer in which to store it */
    738     ClientData    dummy;
     735    char          *word;        /* Word to trim */
     736    Boolean       addSpace;     /* TRUE if need to stick a space in the
     737                                * buffer before adding the tail */
     738    Buffer        buf;          /* Buffer in which to store it */
     739    ClientData    dummy;
    739740{
    740741    register char *slash;
    741742
    742743    if (addSpace) {
    743         Buf_AddByte (buf, (Byte)' ');
     744        Buf_AddByte (buf, (Byte)' ');
    744745    }
    745746
    746747    slash = strrchr (word, '/');
    747748    if (slash != (char *)NULL) {
    748         *slash++ = '\0';
    749         Buf_AddBytes (buf, strlen(slash), (Byte *)slash);
    750         slash[-1] = '/';
     749        *slash++ = '\0';
     750        Buf_AddBytes (buf, strlen(slash), (Byte *)slash);
     751        slash[-1] = '/';
    751752    } else {
    752         Buf_AddBytes (buf, strlen(word), (Byte *)word);
     753        Buf_AddBytes (buf, strlen(word), (Byte *)word);
    753754    }
    754755    return (dummy ? TRUE : TRUE);
     
    758759 *-----------------------------------------------------------------------
    759760 * VarSuffix --
    760  *      Place the suffix of the given word in the given buffer.
    761  *
    762  * Results:
    763  *      TRUE if characters were added to the buffer (a space needs to be
    764  *      added to the buffer before the next word).
    765  *
    766  * Side Effects:
    767  *      The suffix from the word is placed in the buffer.
     761 *      Place the suffix of the given word in the given buffer.
     762 *
     763 * Results:
     764 *      TRUE if characters were added to the buffer (a space needs to be
     765 *      added to the buffer before the next word).
     766 *
     767 * Side Effects:
     768 *      The suffix from the word is placed in the buffer.
    768769 *
    769770 *-----------------------------------------------------------------------
     
    771772static Boolean
    772773VarSuffix (word, addSpace, buf, dummy)
    773     char          *word;        /* Word to trim */
    774     Boolean       addSpace;     /* TRUE if need to add a space before placing
    775                                 * the suffix in the buffer */
    776     Buffer        buf;          /* Buffer in which to store it */
    777     ClientData    dummy;
     774    char          *word;        /* Word to trim */
     775    Boolean       addSpace;     /* TRUE if need to add a space before placing
     776                                * the suffix in the buffer */
     777    Buffer        buf;          /* Buffer in which to store it */
     778    ClientData    dummy;
    778779{
    779780    register char *dot;
     
    781782    dot = strrchr (word, '.');
    782783    if (dot != (char *)NULL) {
    783         if (addSpace) {
    784             Buf_AddByte (buf, (Byte)' ');
    785         }
    786         *dot++ = '\0';
    787         Buf_AddBytes (buf, strlen (dot), (Byte *)dot);
    788         dot[-1] = '.';
    789         addSpace = TRUE;
     784        if (addSpace) {
     785            Buf_AddByte (buf, (Byte)' ');
     786        }
     787        *dot++ = '\0';
     788        Buf_AddBytes (buf, strlen (dot), (Byte *)dot);
     789        dot[-1] = '.';
     790        addSpace = TRUE;
    790791    }
    791792    return (dummy ? addSpace : addSpace);
     
    795796 *-----------------------------------------------------------------------
    796797 * VarRoot --
    797  *      Remove the suffix of the given word and place the result in the
    798  *      buffer.
    799  *
    800  * Results:
    801  *      TRUE if characters were added to the buffer (a space needs to be
    802  *      added to the buffer before the next word).
    803  *
    804  * Side Effects:
    805  *      The trimmed word is added to the buffer.
     798 *      Remove the suffix of the given word and place the result in the
     799 *      buffer.
     800 *
     801 * Results:
     802 *      TRUE if characters were added to the buffer (a space needs to be
     803 *      added to the buffer before the next word).
     804 *
     805 * Side Effects:
     806 *      The trimmed word is added to the buffer.
    806807 *
    807808 *-----------------------------------------------------------------------
     
    809810static Boolean
    810811VarRoot (word, addSpace, buf, dummy)
    811     char          *word;        /* Word to trim */
    812     Boolean       addSpace;     /* TRUE if need to add a space to the buffer
    813                                 * before placing the root in it */
    814     Buffer        buf;          /* Buffer in which to store it */
    815     ClientData    dummy;
     812    char          *word;        /* Word to trim */
     813    Boolean       addSpace;     /* TRUE if need to add a space to the buffer
     814                                * before placing the root in it */
     815    Buffer        buf;          /* Buffer in which to store it */
     816    ClientData    dummy;
    816817{
    817818    register char *dot;
    818819
    819820    if (addSpace) {
    820         Buf_AddByte (buf, (Byte)' ');
     821        Buf_AddByte (buf, (Byte)' ');
    821822    }
    822823
    823824    dot = strrchr (word, '.');
    824825    if (dot != (char *)NULL) {
    825         *dot = '\0';
    826         Buf_AddBytes (buf, strlen (word), (Byte *)word);
    827         *dot = '.';
     826        *dot = '\0';
     827        Buf_AddBytes (buf, strlen (word), (Byte *)word);
     828        *dot = '.';
    828829    } else {
    829         Buf_AddBytes (buf, strlen(word), (Byte *)word);
     830        Buf_AddBytes (buf, strlen(word), (Byte *)word);
    830831    }
    831832    return (dummy ? TRUE : TRUE);
    832833}
    833834
    834 #if defined(NMAKE) || defined(KMK)
     835#ifdef USE_BASEANDROOT_MODIFIERS
    835836/*-
    836837 *-----------------------------------------------------------------------
    837838 * VarBase --
    838  *      Remove the head and suffix of the given word and place the result
    839  *      in the given buffer.
    840  *
    841  * Results:
    842  *      TRUE if characters were added to the buffer (a space needs to be
    843  *      added to the buffer before the next word).
    844  *
    845  * Side Effects:
    846  *      The trimmed word is added to the buffer.
     839 *      Remove the head and suffix of the given word and place the result
     840 *      in the given buffer.
     841 *
     842 * Results:
     843 *      TRUE if characters were added to the buffer (a space needs to be
     844 *      added to the buffer before the next word).
     845 *
     846 * Side Effects:
     847 *      The trimmed word is added to the buffer.
    847848 *
    848849 *-----------------------------------------------------------------------
     
    850851static Boolean
    851852VarBase (word, addSpace, buf, dummy)
    852     char          *word;        /* Word to trim */
    853     Boolean       addSpace;     /* TRUE if need to stick a space in the
    854                                 * buffer before adding the tail */
    855     Buffer        buf;          /* Buffer in which to store it */
    856     ClientData    dummy;
     853    char          *word;        /* Word to trim */
     854    Boolean       addSpace;     /* TRUE if need to stick a space in the
     855                                * buffer before adding the tail */
     856    Buffer        buf;          /* Buffer in which to store it */
     857    ClientData    dummy;
    857858{
    858859    register char *slash;
    859860
    860861    if (addSpace) {
    861         Buf_AddByte (buf, (Byte)' ');
     862        Buf_AddByte (buf, (Byte)' ');
    862863    }
    863864
    864865    slash = strrchr (word, '/');
    865866    if (slash != (char *)NULL) {
    866         register char *dot;
     867        register char *dot;
    867868        *slash++ = '\0';
    868869        dot = strrchr (slash, '.');
     
    875876        else
    876877            Buf_AddBytes (buf, strlen(slash), (Byte *)slash);
    877         slash[-1] = '/';
     878        slash[-1] = '/';
    878879    } else {
    879         register char *dot;
     880        register char *dot;
    880881        dot = strrchr (slash, '.');
    881882        if (dot)
     
    896897 *-----------------------------------------------------------------------
    897898 * VarMatch --
    898  *      Place the word in the buffer if it matches the given pattern.
    899  *      Callback function for VarModify to implement the :M modifier.
    900  *
    901  * Results:
    902  *      TRUE if a space should be placed in the buffer before the next
    903  *      word.
    904  *
    905  * Side Effects:
    906  *      The word may be copied to the buffer.
     899 *      Place the word in the buffer if it matches the given pattern.
     900 *      Callback function for VarModify to implement the :M modifier.
     901 *
     902 * Results:
     903 *      TRUE if a space should be placed in the buffer before the next
     904 *      word.
     905 *
     906 * Side Effects:
     907 *      The word may be copied to the buffer.
    907908 *
    908909 *-----------------------------------------------------------------------
     
    910911static Boolean
    911912VarMatch (word, addSpace, buf, pattern)
    912     char          *word;        /* Word to examine */
    913     Boolean       addSpace;     /* TRUE if need to add a space to the
    914                                 * buffer before adding the word, if it
    915                                 * matches */
    916     Buffer        buf;          /* Buffer in which to store it */
    917     ClientData    pattern;      /* Pattern the word must match */
     913    char          *word;        /* Word to examine */
     914    Boolean       addSpace;     /* TRUE if need to add a space to the
     915                                * buffer before adding the word, if it
     916                                * matches */
     917    Buffer        buf;          /* Buffer in which to store it */
     918    ClientData    pattern;      /* Pattern the word must match */
    918919{
    919920    if (Str_Match(word, (char *) pattern)) {
    920         if (addSpace) {
    921             Buf_AddByte(buf, (Byte)' ');
    922         }
    923         addSpace = TRUE;
    924         Buf_AddBytes(buf, strlen(word), (Byte *)word);
     921        if (addSpace) {
     922            Buf_AddByte(buf, (Byte)' ');
     923        }
     924        addSpace = TRUE;
     925        Buf_AddBytes(buf, strlen(word), (Byte *)word);
    925926    }
    926927    return(addSpace);
     
    931932 *-----------------------------------------------------------------------
    932933 * VarSYSVMatch --
    933  *      Place the word in the buffer if it matches the given pattern.
    934  *      Callback function for VarModify to implement the System V %
    935  *      modifiers.
    936  *
    937  * Results:
    938  *      TRUE if a space should be placed in the buffer before the next
    939  *      word.
    940  *
    941  * Side Effects:
    942  *      The word may be copied to the buffer.
     934 *      Place the word in the buffer if it matches the given pattern.
     935 *      Callback function for VarModify to implement the System V %
     936 *      modifiers.
     937 *
     938 * Results:
     939 *      TRUE if a space should be placed in the buffer before the next
     940 *      word.
     941 *
     942 * Side Effects:
     943 *      The word may be copied to the buffer.
    943944 *
    944945 *-----------------------------------------------------------------------
     
    946947static Boolean
    947948VarSYSVMatch (word, addSpace, buf, patp)
    948     char          *word;        /* Word to examine */
    949     Boolean       addSpace;     /* TRUE if need to add a space to the
    950                                 * buffer before adding the word, if it
    951                                 * matches */
    952     Buffer        buf;          /* Buffer in which to store it */
    953     ClientData    patp;         /* Pattern the word must match */
     949    char          *word;        /* Word to examine */
     950    Boolean       addSpace;     /* TRUE if need to add a space to the
     951                                * buffer before adding the word, if it
     952                                * matches */
     953    Buffer        buf;          /* Buffer in which to store it */
     954    ClientData    patp;         /* Pattern the word must match */
    954955{
    955956    int len;
    956957    char *ptr;
    957     VarPattern    *pat = (VarPattern *) patp;
     958    VarPattern    *pat = (VarPattern *) patp;
    958959
    959960    if (addSpace)
    960         Buf_AddByte(buf, (Byte)' ');
     961        Buf_AddByte(buf, (Byte)' ');
    961962
    962963    addSpace = TRUE;
    963964
    964965    if ((ptr = Str_SYSVMatch(word, pat->lhs, &len)) != NULL)
    965         Str_SYSVSubst(buf, pat->rhs, ptr, len);
     966        Str_SYSVSubst(buf, pat->rhs, ptr, len);
    966967    else
    967         Buf_AddBytes(buf, strlen(word), (Byte *) word);
     968        Buf_AddBytes(buf, strlen(word), (Byte *) word);
    968969
    969970    return(addSpace);
     
    975976 *-----------------------------------------------------------------------
    976977 * VarNoMatch --
    977  *      Place the word in the buffer if it doesn't match the given pattern.
    978  *      Callback function for VarModify to implement the :N modifier.
    979  *
    980  * Results:
    981  *      TRUE if a space should be placed in the buffer before the next
    982  *      word.
    983  *
    984  * Side Effects:
    985  *      The word may be copied to the buffer.
     978 *      Place the word in the buffer if it doesn't match the given pattern.
     979 *      Callback function for VarModify to implement the :N modifier.
     980 *
     981 * Results:
     982 *      TRUE if a space should be placed in the buffer before the next
     983 *      word.
     984 *
     985 * Side Effects:
     986 *      The word may be copied to the buffer.
    986987 *
    987988 *-----------------------------------------------------------------------
     
    989990static Boolean
    990991VarNoMatch (word, addSpace, buf, pattern)
    991     char          *word;        /* Word to examine */
    992     Boolean       addSpace;     /* TRUE if need to add a space to the
    993                                 * buffer before adding the word, if it
    994                                 * matches */
    995     Buffer        buf;          /* Buffer in which to store it */
    996     ClientData    pattern;      /* Pattern the word must match */
     992    char          *word;        /* Word to examine */
     993    Boolean       addSpace;     /* TRUE if need to add a space to the
     994                                * buffer before adding the word, if it
     995                                * matches */
     996    Buffer        buf;          /* Buffer in which to store it */
     997    ClientData    pattern;      /* Pattern the word must match */
    997998{
    998999    if (!Str_Match(word, (char *) pattern)) {
    999         if (addSpace) {
    1000             Buf_AddByte(buf, (Byte)' ');
    1001         }
    1002         addSpace = TRUE;
    1003         Buf_AddBytes(buf, strlen(word), (Byte *)word);
     1000        if (addSpace) {
     1001            Buf_AddByte(buf, (Byte)' ');
     1002        }
     1003        addSpace = TRUE;
     1004        Buf_AddBytes(buf, strlen(word), (Byte *)word);
    10041005    }
    10051006    return(addSpace);
     
    10101011 *-----------------------------------------------------------------------
    10111012 * VarSubstitute --
    1012  *      Perform a string-substitution on the given word, placing the
    1013  *      result in the passed buffer.
    1014  *
    1015  * Results:
    1016  *      TRUE if a space is needed before more characters are added.
    1017  *
    1018  * Side Effects:
    1019  *      None.
     1013 *      Perform a string-substitution on the given word, placing the
     1014 *      result in the passed buffer.
     1015 *
     1016 * Results:
     1017 *      TRUE if a space is needed before more characters are added.
     1018 *
     1019 * Side Effects:
     1020 *      None.
    10201021 *
    10211022 *-----------------------------------------------------------------------
     
    10231024static Boolean
    10241025VarSubstitute (word, addSpace, buf, patternp)
    1025     char                *word;      /* Word to modify */
    1026     Boolean             addSpace;   /* True if space should be added before
    1027                                      * other characters */
    1028     Buffer              buf;        /* Buffer for result */
    1029     ClientData          patternp;   /* Pattern for substitution */
    1030 {
    1031     register int        wordLen;    /* Length of word */
    1032     register char       *cp;        /* General pointer */
    1033     VarPattern  *pattern = (VarPattern *) patternp;
     1026    char                *word;      /* Word to modify */
     1027    Boolean             addSpace;   /* True if space should be added before
     1028                                     * other characters */
     1029    Buffer              buf;        /* Buffer for result */
     1030    ClientData          patternp;   /* Pattern for substitution */
     1031{
     1032    register int        wordLen;    /* Length of word */
     1033    register char       *cp;        /* General pointer */
     1034    VarPattern  *pattern = (VarPattern *) patternp;
    10341035
    10351036    wordLen = strlen(word);
    10361037    if (1) { /* substitute in each word of the variable */
    1037         /*
    1038         * Break substitution down into simple anchored cases
    1039         * and if none of them fits, perform the general substitution case.
    1040         */
    1041         if ((pattern->flags & VAR_MATCH_START) &&
    1042             (strncmp(word, pattern->lhs, pattern->leftLen) == 0)) {
    1043                 /*
    1044                 * Anchored at start and beginning of word matches pattern
    1045                 */
    1046                 if ((pattern->flags & VAR_MATCH_END) &&
    1047                     (wordLen == pattern->leftLen)) {
    1048                         /*
    1049                         * Also anchored at end and matches to the end (word
    1050                         * is same length as pattern) add space and rhs only
    1051                         * if rhs is non-null.
    1052                         */
    1053                         if (pattern->rightLen != 0) {
    1054                             if (addSpace) {
    1055                                 Buf_AddByte(buf, (Byte)' ');
    1056                             }
    1057                             addSpace = TRUE;
    1058                             Buf_AddBytes(buf, pattern->rightLen,
    1059                                         (Byte *)pattern->rhs);
    1060                         }
    1061                 } else if (pattern->flags & VAR_MATCH_END) {
    1062                     /*
    1063                      * Doesn't match to end -- copy word wholesale
    1064                      */
    1065                     goto nosub;
    1066                 } else {
    1067                     /*
    1068                      * Matches at start but need to copy in trailing characters
    1069                      */
    1070                     if ((pattern->rightLen + wordLen - pattern->leftLen) != 0){
    1071                         if (addSpace) {
    1072                             Buf_AddByte(buf, (Byte)' ');
    1073                         }
    1074                         addSpace = TRUE;
    1075                     }
    1076                     Buf_AddBytes(buf, pattern->rightLen, (Byte *)pattern->rhs);
    1077                     Buf_AddBytes(buf, wordLen - pattern->leftLen,
    1078                                 (Byte *)(word + pattern->leftLen));
    1079                 }
    1080         } else if (pattern->flags & VAR_MATCH_START) {
    1081             /*
    1082              * Had to match at start of word and didn't -- copy whole word.
    1083              */
    1084             goto nosub;
    1085         } else if (pattern->flags & VAR_MATCH_END) {
    1086             /*
    1087              * Anchored at end, Find only place match could occur (leftLen
    1088              * characters from the end of the word) and see if it does. Note
    1089              * that because the $ will be left at the end of the lhs, we have
    1090              * to use strncmp.
    1091              */
    1092             cp = word + (wordLen - pattern->leftLen);
    1093             if ((cp >= word) &&
    1094                 (strncmp(cp, pattern->lhs, pattern->leftLen) == 0)) {
    1095                 /*
    1096                 * Match found. If we will place characters in the buffer,
    1097                 * add a space before hand as indicated by addSpace, then
    1098                 * stuff in the initial, unmatched part of the word followed
    1099                 * by the right-hand-side.
    1100                 */
    1101                 if (((cp - word) + pattern->rightLen) != 0) {
    1102                     if (addSpace) {
    1103                         Buf_AddByte(buf, (Byte)' ');
    1104                     }
    1105                     addSpace = TRUE;
    1106                 }
    1107                 Buf_AddBytes(buf, cp - word, (Byte *)word);
    1108                 Buf_AddBytes(buf, pattern->rightLen, (Byte *)pattern->rhs);
    1109             } else {
    1110                 /*
    1111                 * Had to match at end and didn't. Copy entire word.
    1112                 */
    1113                 goto nosub;
    1114             }
    1115         } else {
    1116             /*
    1117              * Pattern is unanchored: search for the pattern in the word using
    1118              * String_FindSubstring, copying unmatched portions and the
    1119              * right-hand-side for each match found, handling non-global
    1120              * substitutions correctly, etc. When the loop is done, any
    1121              * remaining part of the word (word and wordLen are adjusted
    1122              * accordingly through the loop) is copied straight into the
    1123              * buffer.
    1124              * addSpace is set FALSE as soon as a space is added to the
    1125              * buffer.
    1126              */
    1127             register Boolean done;
    1128             int origSize;
    1129 
    1130             done = FALSE;
    1131             origSize = Buf_Size(buf);
    1132             while (!done) {
    1133                 cp = Str_FindSubstring(word, pattern->lhs);
    1134                 if (cp != (char *)NULL) {
    1135                     if (addSpace && (((cp - word) + pattern->rightLen) != 0)){
    1136                         Buf_AddByte(buf, (Byte)' ');
    1137                         addSpace = FALSE;
    1138                     }
    1139                     Buf_AddBytes(buf, cp-word, (Byte *)word);
    1140                     Buf_AddBytes(buf, pattern->rightLen, (Byte *)pattern->rhs);
    1141                     wordLen -= (cp - word) + pattern->leftLen;
    1142                     word = cp + pattern->leftLen;
    1143                     if (wordLen == 0 || (pattern->flags & VAR_SUB_GLOBAL) == 0){
    1144                         done = TRUE;
    1145                     }
    1146                 } else {
    1147                     done = TRUE;
    1148                 }
    1149             }
    1150             if (wordLen != 0) {
    1151                 if (addSpace) {
    1152                     Buf_AddByte(buf, (Byte)' ');
    1153                 }
    1154                 Buf_AddBytes(buf, wordLen, (Byte *)word);
    1155             }
    1156             /*
    1157              * If added characters to the buffer, need to add a space
    1158              * before we add any more. If we didn't add any, just return
    1159              * the previous value of addSpace.
    1160              */
    1161             return ((Buf_Size(buf) != origSize) || addSpace);
    1162         }
    1163         /*
    1164         * Common code for anchored substitutions:
    1165         * addSpace was set TRUE if characters were added to the buffer.
    1166         */
    1167         return (addSpace);
     1038        /*
     1039        * Break substitution down into simple anchored cases
     1040        * and if none of them fits, perform the general substitution case.
     1041        */
     1042        if ((pattern->flags & VAR_MATCH_START) &&
     1043            (strncmp(word, pattern->lhs, pattern->leftLen) == 0)) {
     1044                /*
     1045                * Anchored at start and beginning of word matches pattern
     1046                */
     1047                if ((pattern->flags & VAR_MATCH_END) &&
     1048                    (wordLen == pattern->leftLen)) {
     1049                        /*
     1050                        * Also anchored at end and matches to the end (word
     1051                        * is same length as pattern) add space and rhs only
     1052                        * if rhs is non-null.
     1053                        */
     1054                        if (pattern->rightLen != 0) {
     1055                            if (addSpace) {
     1056                                Buf_AddByte(buf, (Byte)' ');
     1057                            }
     1058                            addSpace = TRUE;
     1059                            Buf_AddBytes(buf, pattern->rightLen,
     1060                                        (Byte *)pattern->rhs);
     1061                        }
     1062                } else if (pattern->flags & VAR_MATCH_END) {
     1063                    /*
     1064                     * Doesn't match to end -- copy word wholesale
     1065                     */
     1066                    goto nosub;
     1067                } else {
     1068                    /*
     1069                     * Matches at start but need to copy in trailing characters
     1070                     */
     1071                    if ((pattern->rightLen + wordLen - pattern->leftLen) != 0){
     1072                        if (addSpace) {
     1073                            Buf_AddByte(buf, (Byte)' ');
     1074                        }
     1075                        addSpace = TRUE;
     1076                    }
     1077                    Buf_AddBytes(buf, pattern->rightLen, (Byte *)pattern->rhs);
     1078                    Buf_AddBytes(buf, wordLen - pattern->leftLen,
     1079                                (Byte *)(word + pattern->leftLen));
     1080                }
     1081        } else if (pattern->flags & VAR_MATCH_START) {
     1082            /*
     1083             * Had to match at start of word and didn't -- copy whole word.
     1084             */
     1085            goto nosub;
     1086        } else if (pattern->flags & VAR_MATCH_END) {
     1087            /*
     1088             * Anchored at end, Find only place match could occur (leftLen
     1089             * characters from the end of the word) and see if it does. Note
     1090             * that because the $ will be left at the end of the lhs, we have
     1091             * to use strncmp.
     1092             */
     1093            cp = word + (wordLen - pattern->leftLen);
     1094            if ((cp >= word) &&
     1095                (strncmp(cp, pattern->lhs, pattern->leftLen) == 0)) {
     1096                /*
     1097                * Match found. If we will place characters in the buffer,
     1098                * add a space before hand as indicated by addSpace, then
     1099                * stuff in the initial, unmatched part of the word followed
     1100                * by the right-hand-side.
     1101                */
     1102                if (((cp - word) + pattern->rightLen) != 0) {
     1103                    if (addSpace) {
     1104                        Buf_AddByte(buf, (Byte)' ');
     1105                    }
     1106                    addSpace = TRUE;
     1107                }
     1108                Buf_AddBytes(buf, cp - word, (Byte *)word);
     1109                Buf_AddBytes(buf, pattern->rightLen, (Byte *)pattern->rhs);
     1110            } else {
     1111                /*
     1112                * Had to match at end and didn't. Copy entire word.
     1113                */
     1114                goto nosub;
     1115            }
     1116        } else {
     1117            /*
     1118             * Pattern is unanchored: search for the pattern in the word using
     1119             * String_FindSubstring, copying unmatched portions and the
     1120             * right-hand-side for each match found, handling non-global
     1121             * substitutions correctly, etc. When the loop is done, any
     1122             * remaining part of the word (word and wordLen are adjusted
     1123             * accordingly through the loop) is copied straight into the
     1124             * buffer.
     1125             * addSpace is set FALSE as soon as a space is added to the
     1126             * buffer.
     1127             */
     1128            register Boolean done;
     1129            int origSize;
     1130
     1131            done = FALSE;
     1132            origSize = Buf_Size(buf);
     1133            while (!done) {
     1134                cp = Str_FindSubstring(word, pattern->lhs);
     1135                if (cp != (char *)NULL) {
     1136                    if (addSpace && (((cp - word) + pattern->rightLen) != 0)){
     1137                        Buf_AddByte(buf, (Byte)' ');
     1138                        addSpace = FALSE;
     1139                    }
     1140                    Buf_AddBytes(buf, cp-word, (Byte *)word);
     1141                    Buf_AddBytes(buf, pattern->rightLen, (Byte *)pattern->rhs);
     1142                    wordLen -= (cp - word) + pattern->leftLen;
     1143                    word = cp + pattern->leftLen;
     1144                    if (wordLen == 0 || (pattern->flags & VAR_SUB_GLOBAL) == 0){
     1145                        done = TRUE;
     1146                    }
     1147                } else {
     1148                    done = TRUE;
     1149                }
     1150            }
     1151            if (wordLen != 0) {
     1152                if (addSpace) {
     1153                    Buf_AddByte(buf, (Byte)' ');
     1154                }
     1155                Buf_AddBytes(buf, wordLen, (Byte *)word);
     1156            }
     1157            /*
     1158             * If added characters to the buffer, need to add a space
     1159             * before we add any more. If we didn't add any, just return
     1160             * the previous value of addSpace.
     1161             */
     1162            return ((Buf_Size(buf) != origSize) || addSpace);
     1163        }
     1164        /*
     1165        * Common code for anchored substitutions:
     1166        * addSpace was set TRUE if characters were added to the buffer.
     1167        */
     1168        return (addSpace);
    11681169    }
    11691170 nosub:
    11701171    if (addSpace) {
    1171         Buf_AddByte(buf, (Byte)' ');
     1172        Buf_AddByte(buf, (Byte)' ');
    11721173    }
    11731174    Buf_AddBytes(buf, wordLen, (Byte *)word);
     
    11781179 *-----------------------------------------------------------------------
    11791180 * VarREError --
    1180  *      Print the error caused by a regcomp or regexec call.
    1181  *
    1182  * Results:
    1183  *      None.
    1184  *
    1185  * Side Effects:
    1186  *      An error gets printed.
     1181 *      Print the error caused by a regcomp or regexec call.
     1182 *
     1183 * Results:
     1184 *      None.
     1185 *
     1186 * Side Effects:
     1187 *      An error gets printed.
    11871188 *
    11881189 *-----------------------------------------------------------------------
     
    12081209 *-----------------------------------------------------------------------
    12091210 * VarRESubstitute --
    1210  *      Perform a regex substitution on the given word, placing the
    1211  *      result in the passed buffer.
    1212  *
    1213  * Results:
    1214  *      TRUE if a space is needed before more characters are added.
    1215  *
    1216  * Side Effects:
    1217  *      None.
     1211 *      Perform a regex substitution on the given word, placing the
     1212 *      result in the passed buffer.
     1213 *
     1214 * Results:
     1215 *      TRUE if a space is needed before more characters are added.
     1216 *
     1217 * Side Effects:
     1218 *      None.
    12181219 *
    12191220 *-----------------------------------------------------------------------
     
    12331234    int flags = 0;
    12341235
    1235 #define MAYBE_ADD_SPACE()               \
    1236         if (addSpace && !added)         \
    1237             Buf_AddByte(buf, ' ');      \
    1238         added = 1
     1236#define MAYBE_ADD_SPACE()               \
     1237        if (addSpace && !added)         \
     1238            Buf_AddByte(buf, ' ');      \
     1239        added = 1
    12391240
    12401241    added = 0;
     
    12431244
    12441245    if ((pat->flags & (VAR_SUB_ONE|VAR_SUB_MATCHED)) ==
    1245         (VAR_SUB_ONE|VAR_SUB_MATCHED))
    1246         xrv = REG_NOMATCH;
     1246        (VAR_SUB_ONE|VAR_SUB_MATCHED))
     1247        xrv = REG_NOMATCH;
    12471248    else {
    12481249    tryagain:
    1249         xrv = regexec(&pat->re, wp, pat->nsub, pat->matches, flags);
     1250        xrv = regexec(&pat->re, wp, pat->nsub, pat->matches, flags);
    12501251    }
    12511252
    12521253    switch (xrv) {
    12531254    case 0:
    1254         pat->flags |= VAR_SUB_MATCHED;
    1255         if (pat->matches[0].rm_so > 0) {
    1256             MAYBE_ADD_SPACE();
    1257             Buf_AddBytes(buf, pat->matches[0].rm_so, wp);
    1258         }
    1259 
    1260         for (rp = pat->replace; *rp; rp++) {
    1261             if ((*rp == '\\') && ((rp[1] == '&') || (rp[1] == '\\'))) {
    1262                 MAYBE_ADD_SPACE();
    1263                 Buf_AddByte(buf,rp[1]);
    1264                 rp++;
    1265             }
    1266             else if ((*rp == '&') ||
    1267                 ((*rp == '\\') && isdigit((unsigned char)rp[1]))) {
    1268                 int n;
    1269                 char *subbuf;
    1270                 int sublen;
    1271                 char errstr[3];
    1272 
    1273                 if (*rp == '&') {
    1274                     n = 0;
    1275                     errstr[0] = '&';
    1276                     errstr[1] = '\0';
    1277                 } else {
    1278                     n = rp[1] - '0';
    1279                     errstr[0] = '\\';
    1280                     errstr[1] = rp[1];
    1281                     errstr[2] = '\0';
    1282                     rp++;
    1283                 }
    1284 
    1285                 if (n > pat->nsub) {
    1286                     Error("No subexpression %s", &errstr[0]);
    1287                     subbuf = "";
    1288                     sublen = 0;
    1289                 } else if ((pat->matches[n].rm_so == -1) &&
    1290                            (pat->matches[n].rm_eo == -1)) {
    1291                     Error("No match for subexpression %s", &errstr[0]);
    1292                     subbuf = "";
    1293                     sublen = 0;
    1294                 } else {
    1295                     subbuf = wp + pat->matches[n].rm_so;
    1296                     sublen = pat->matches[n].rm_eo - pat->matches[n].rm_so;
    1297                 }
    1298 
    1299                 if (sublen > 0) {
    1300                     MAYBE_ADD_SPACE();
    1301                     Buf_AddBytes(buf, sublen, subbuf);
    1302                 }
    1303             } else {
    1304                 MAYBE_ADD_SPACE();
    1305                 Buf_AddByte(buf, *rp);
    1306             }
    1307         }
    1308         wp += pat->matches[0].rm_eo;
    1309         if (pat->flags & VAR_SUB_GLOBAL) {
    1310             flags |= REG_NOTBOL;
    1311             if (pat->matches[0].rm_so == 0 && pat->matches[0].rm_eo == 0) {
    1312                 MAYBE_ADD_SPACE();
    1313                 Buf_AddByte(buf, *wp);
    1314                 wp++;
    1315 
    1316             }
    1317             if (*wp)
    1318                 goto tryagain;
    1319         }
    1320         if (*wp) {
    1321             MAYBE_ADD_SPACE();
    1322             Buf_AddBytes(buf, strlen(wp), wp);
    1323         }
    1324         break;
     1255        pat->flags |= VAR_SUB_MATCHED;
     1256        if (pat->matches[0].rm_so > 0) {
     1257            MAYBE_ADD_SPACE();
     1258            Buf_AddBytes(buf, pat->matches[0].rm_so, wp);
     1259        }
     1260
     1261        for (rp = pat->replace; *rp; rp++) {
     1262            if ((*rp == '\\') && ((rp[1] == '&') || (rp[1] == '\\'))) {
     1263                MAYBE_ADD_SPACE();
     1264                Buf_AddByte(buf,rp[1]);
     1265                rp++;
     1266            }
     1267            else if ((*rp == '&') ||
     1268                ((*rp == '\\') && isdigit((unsigned char)rp[1]))) {
     1269                int n;
     1270                char *subbuf;
     1271                int sublen;
     1272                char errstr[3];
     1273
     1274                if (*rp == '&') {
     1275                    n = 0;
     1276                    errstr[0] = '&';
     1277                    errstr[1] = '\0';
     1278                } else {
     1279                    n = rp[1] - '0';
     1280                    errstr[0] = '\\';
     1281                    errstr[1] = rp[1];
     1282                    errstr[2] = '\0';
     1283                    rp++;
     1284                }
     1285
     1286                if (n > pat->nsub) {
     1287                    Error("No subexpression %s", &errstr[0]);
     1288                    subbuf = "";
     1289                    sublen = 0;
     1290                } else if ((pat->matches[n].rm_so == -1) &&
     1291                           (pat->matches[n].rm_eo == -1)) {
     1292                    Error("No match for subexpression %s", &errstr[0]);
     1293                    subbuf = "";
     1294                    sublen = 0;
     1295                } else {
     1296                    subbuf = wp + pat->matches[n].rm_so;
     1297                    sublen = pat->matches[n].rm_eo - pat->matches[n].rm_so;
     1298                }
     1299
     1300                if (sublen > 0) {
     1301                    MAYBE_ADD_SPACE();
     1302                    Buf_AddBytes(buf, sublen, subbuf);
     1303                }
     1304            } else {
     1305                MAYBE_ADD_SPACE();
     1306                Buf_AddByte(buf, *rp);
     1307            }
     1308        }
     1309        wp += pat->matches[0].rm_eo;
     1310        if (pat->flags & VAR_SUB_GLOBAL) {
     1311            flags |= REG_NOTBOL;
     1312            if (pat->matches[0].rm_so == 0 && pat->matches[0].rm_eo == 0) {
     1313                MAYBE_ADD_SPACE();
     1314                Buf_AddByte(buf, *wp);
     1315                wp++;
     1316
     1317            }
     1318            if (*wp)
     1319                goto tryagain;
     1320        }
     1321        if (*wp) {
     1322            MAYBE_ADD_SPACE();
     1323            Buf_AddBytes(buf, strlen(wp), wp);
     1324        }
     1325        break;
    13251326    default:
    1326         VarREError(xrv, &pat->re, "Unexpected regex error");
     1327        VarREError(xrv, &pat->re, "Unexpected regex error");
    13271328       /* fall through */
    13281329    case REG_NOMATCH:
    1329         if (*wp) {
    1330             MAYBE_ADD_SPACE();
    1331             Buf_AddBytes(buf,strlen(wp),wp);
    1332         }
    1333         break;
     1330        if (*wp) {
     1331            MAYBE_ADD_SPACE();
     1332            Buf_AddBytes(buf,strlen(wp),wp);
     1333        }
     1334        break;
    13341335    }
    13351336    return(addSpace||added);
     
    13401341 *-----------------------------------------------------------------------
    13411342 * VarModify --
    1342  *      Modify each of the words of the passed string using the given
    1343  *      function. Used to implement all modifiers.
    1344  *
    1345  * Results:
    1346  *      A string of all the words modified appropriately.
    1347  *
    1348  * Side Effects:
    1349  *      None.
     1343 *      Modify each of the words of the passed string using the given
     1344 *      function. Used to implement all modifiers.
     1345 *
     1346 * Results:
     1347 *      A string of all the words modified appropriately.
     1348 *
     1349 * Side Effects:
     1350 *      None.
    13501351 *
    13511352 *-----------------------------------------------------------------------
     
    13531354static char *
    13541355VarModify (str, modProc, datum)
    1355     char          *str;             /* String whose words should be trimmed */
    1356                                     /* Function to use to modify them */
    1357     Boolean       (*modProc) __P((char *, Boolean, Buffer, ClientData));
    1358     ClientData    datum;            /* Datum to pass it */
    1359 {
    1360     Buffer        buf;              /* Buffer for the new string */
    1361     Boolean       addSpace;         /* TRUE if need to add a space to the
    1362                                      * buffer before adding the trimmed
    1363                                      * word */
    1364     char **av;                      /* word list [first word does not count] */
     1356    char          *str;             /* String whose words should be trimmed */
     1357                                    /* Function to use to modify them */
     1358    Boolean       (*modProc) __P((char *, Boolean, Buffer, ClientData));
     1359    ClientData    datum;            /* Datum to pass it */
     1360{
     1361    Buffer        buf;              /* Buffer for the new string */
     1362    Boolean       addSpace;         /* TRUE if need to add a space to the
     1363                                     * buffer before adding the trimmed
     1364                                     * word */
     1365    char **av;                      /* word list [first word does not count] */
    13651366    int ac, i;
    13661367
     
    13711372
    13721373    for (i = 1; i < ac; i++)
    1373         addSpace = (*modProc)(av[i], addSpace, buf, datum);
     1374        addSpace = (*modProc)(av[i], addSpace, buf, datum);
    13741375
    13751376    Buf_AddByte (buf, '\0');
     
    13821383 *-----------------------------------------------------------------------
    13831384 * VarGetPattern --
    1384  *      Pass through the tstr looking for 1) escaped delimiters,
    1385  *      '$'s and backslashes (place the escaped character in
    1386  *      uninterpreted) and 2) unescaped $'s that aren't before
    1387  *      the delimiter (expand the variable substitution unless flags
    1388  *      has VAR_NOSUBST set).
    1389  *      Return the expanded string or NULL if the delimiter was missing
    1390  *      If pattern is specified, handle escaped ampersands, and replace
    1391  *      unescaped ampersands with the lhs of the pattern.
    1392  *
    1393  * Results:
    1394  *      A string of all the words modified appropriately.
    1395  *      If length is specified, return the string length of the buffer
    1396  *      If flags is specified and the last character of the pattern is a
    1397  *      $ set the VAR_MATCH_END bit of flags.
    1398  *
    1399  * Side Effects:
    1400  *      None.
     1385 *      Pass through the tstr looking for 1) escaped delimiters,
     1386 *      '$'s and backslashes (place the escaped character in
     1387 *      uninterpreted) and 2) unescaped $'s that aren't before
     1388 *      the delimiter (expand the variable substitution unless flags
     1389 *      has VAR_NOSUBST set).
     1390 *      Return the expanded string or NULL if the delimiter was missing
     1391 *      If pattern is specified, handle escaped ampersands, and replace
     1392 *      unescaped ampersands with the lhs of the pattern.
     1393 *
     1394 * Results:
     1395 *      A string of all the words modified appropriately.
     1396 *      If length is specified, return the string length of the buffer
     1397 *      If flags is specified and the last character of the pattern is a
     1398 *      $ set the VAR_MATCH_END bit of flags.
     1399 *
     1400 * Side Effects:
     1401 *      None.
    14011402 *-----------------------------------------------------------------------
    14021403 */
     
    14151416    int junk;
    14161417    if (length == NULL)
    1417         length = &junk;
     1418        length = &junk;
    14181419
    14191420#define IS_A_MATCH(cp, delim) \
     
    14281429     */
    14291430    for (cp = *tstr; *cp && (*cp != delim); cp++) {
    1430         if (IS_A_MATCH(cp, delim)) {
    1431             Buf_AddByte(buf, (Byte) cp[1]);
    1432             cp++;
    1433         } else if (*cp == '$') {
    1434             if (cp[1] == delim) {
    1435                 if (flags == NULL)
    1436                     Buf_AddByte(buf, (Byte) *cp);
    1437                 else
    1438                     /*
    1439                      * Unescaped $ at end of pattern => anchor
    1440                      * pattern at end.
    1441                      */
    1442                     *flags |= VAR_MATCH_END;
    1443             } else {
    1444                 if (flags == NULL || (*flags & VAR_NOSUBST) == 0) {
    1445                     char   *cp2;
    1446                     int     len;
    1447                     Boolean freeIt;
    1448 
    1449                     /*
    1450                      * If unescaped dollar sign not before the
    1451                      * delimiter, assume it's a variable
    1452                      * substitution and recurse.
    1453                      */
    1454                     cp2 = Var_Parse(cp, ctxt, err, &len, &freeIt);
    1455                     Buf_AddBytes(buf, strlen(cp2), (Byte *) cp2);
    1456                     if (freeIt)
    1457                         efree(cp2);
    1458                     cp += len - 1;
    1459                 } else {
    1460                     char *cp2 = &cp[1];
    1461 
    1462                     if (*cp2 == '(' || *cp2 == '{') {
    1463                         /*
    1464                         * Find the end of this variable reference
    1465                         * and suck it in without further ado.
    1466                         * It will be interperated later.
    1467                         */
    1468                         int have = *cp2;
    1469                         int want = (*cp2 == '(') ? ')' : '}';
    1470                         int depth = 1;
    1471 
    1472                         for (++cp2; *cp2 != '\0' && depth > 0; ++cp2) {
    1473                             if (cp2[-1] != '\\') {
    1474                                 if (*cp2 == have)
    1475                                     ++depth;
    1476                                 if (*cp2 == want)
    1477                                     --depth;
    1478                             }
    1479                         }
    1480                         Buf_AddBytes(buf, cp2 - cp, (Byte *)cp);
    1481                         cp = --cp2;
    1482                     } else
    1483                         Buf_AddByte(buf, (Byte) *cp);
    1484                 }
    1485             }
    1486         }
    1487         else if (pattern && *cp == '&')
    1488             Buf_AddBytes(buf, pattern->leftLen, (Byte *)pattern->lhs);
    1489         else
    1490             Buf_AddByte(buf, (Byte) *cp);
     1431        if (IS_A_MATCH(cp, delim)) {
     1432            Buf_AddByte(buf, (Byte) cp[1]);
     1433            cp++;
     1434        } else if (*cp == '$') {
     1435            if (cp[1] == delim) {
     1436                if (flags == NULL)
     1437                    Buf_AddByte(buf, (Byte) *cp);
     1438                else
     1439                    /*
     1440                     * Unescaped $ at end of pattern => anchor
     1441                     * pattern at end.
     1442                     */
     1443                    *flags |= VAR_MATCH_END;
     1444            } else {
     1445                if (flags == NULL || (*flags & VAR_NOSUBST) == 0) {
     1446                    char   *cp2;
     1447                    int     len;
     1448                    Boolean freeIt;
     1449
     1450                    /*
     1451                     * If unescaped dollar sign not before the
     1452                     * delimiter, assume it's a variable
     1453                     * substitution and recurse.
     1454                     */
     1455                    cp2 = Var_Parse(cp, ctxt, err, &len, &freeIt);
     1456                    Buf_AddBytes(buf, strlen(cp2), (Byte *) cp2);
     1457                    if (freeIt)
     1458                        efree(cp2);
     1459                    cp += len - 1;
     1460                } else {
     1461                    char *cp2 = &cp[1];
     1462
     1463                    if (*cp2 == '(' || *cp2 == '{') {
     1464                        /*
     1465                        * Find the end of this variable reference
     1466                        * and suck it in without further ado.
     1467                        * It will be interperated later.
     1468                        */
     1469                        int have = *cp2;
     1470                        int want = (*cp2 == '(') ? ')' : '}';
     1471                        int depth = 1;
     1472
     1473                        for (++cp2; *cp2 != '\0' && depth > 0; ++cp2) {
     1474                            if (cp2[-1] != '\\') {
     1475                                if (*cp2 == have)
     1476                                    ++depth;
     1477                                if (*cp2 == want)
     1478                                    --depth;
     1479                            }
     1480                        }
     1481                        Buf_AddBytes(buf, cp2 - cp, (Byte *)cp);
     1482                        cp = --cp2;
     1483                    } else
     1484                        Buf_AddByte(buf, (Byte) *cp);
     1485                }
     1486            }
     1487        }
     1488        else if (pattern && *cp == '&')
     1489            Buf_AddBytes(buf, pattern->leftLen, (Byte *)pattern->lhs);
     1490        else
     1491            Buf_AddByte(buf, (Byte) *cp);
    14911492    }
    14921493
     
    14941495
    14951496    if (*cp != delim) {
    1496         *tstr = cp;
    1497         *length = 0;
    1498         return NULL;
     1497        *tstr = cp;
     1498        *length = 0;
     1499        return NULL;
    14991500    }
    15001501    else {
    1501         *tstr = ++cp;
    1502         cp = (char *) Buf_GetAll(buf, length);
    1503         *length -= 1;   /* Don't count the NULL */
    1504         Buf_Destroy(buf, FALSE);
    1505         return cp;
     1502        *tstr = ++cp;
     1503        cp = (char *) Buf_GetAll(buf, length);
     1504        *length -= 1;   /* Don't count the NULL */
     1505        Buf_Destroy(buf, FALSE);
     1506        return cp;
    15061507    }
    15071508}
     
    15111512 *-----------------------------------------------------------------------
    15121513 * VarQuote --
    1513  *      Quote shell meta-characters in the string
    1514  *
    1515  * Results:
    1516  *      The quoted string
    1517  *
    1518  * Side Effects:
    1519  *      None.
     1514 *      Quote shell meta-characters in the string
     1515 *
     1516 * Results:
     1517 *      The quoted string
     1518 *
     1519 * Side Effects:
     1520 *      None.
    15201521 *
    15211522 *-----------------------------------------------------------------------
     
    15231524static char *
    15241525VarQuote(str)
    1525         char *str;
    1526 {
    1527 
    1528     Buffer        buf;
     1526        char *str;
     1527{
     1528
     1529    Buffer        buf;
    15291530    /* This should cover most shells :-( */
    15301531    static char meta[] = "\n \t'`\";&<>()|*?{}[]\\$!#^~";
     
    15321533    buf = Buf_Init (MAKE_BSIZE);
    15331534    for (; *str; str++) {
    1534         if (strchr(meta, *str) != NULL)
    1535             Buf_AddByte(buf, (Byte)'\\');
    1536         Buf_AddByte(buf, (Byte)*str);
     1535        if (strchr(meta, *str) != NULL)
     1536            Buf_AddByte(buf, (Byte)'\\');
     1537        Buf_AddByte(buf, (Byte)*str);
    15371538    }
    15381539    Buf_AddByte(buf, (Byte) '\0');
     
    15451546 *-----------------------------------------------------------------------
    15461547 * Var_Parse --
    1547  *      Given the start of a variable invocation, extract the variable
    1548  *      name and find its value, then modify it according to the
    1549  *      specification.
    1550  *
    1551  * Results:
    1552  *      The (possibly-modified) value of the variable or var_Error if the
    1553  *      specification is invalid. The length of the specification is
    1554  *      placed in *lengthPtr (for invalid specifications, this is just
    1555  *      2...?).
    1556  *      A Boolean in *freePtr telling whether the returned string should
    1557  *      be freed by the caller.
    1558  *
    1559  * Side Effects:
    1560  *      None.
     1548 *      Given the start of a variable invocation, extract the variable
     1549 *      name and find its value, then modify it according to the
     1550 *      specification.
     1551 *
     1552 * Results:
     1553 *      The (possibly-modified) value of the variable or var_Error if the
     1554 *      specification is invalid. The length of the specification is
     1555 *      placed in *lengthPtr (for invalid specifications, this is just
     1556 *      2...?).
     1557 *      A Boolean in *freePtr telling whether the returned string should
     1558 *      be freed by the caller.
     1559 *
     1560 * Side Effects:
     1561 *      None.
    15611562 *
    15621563 *-----------------------------------------------------------------------
     
    15641565char *
    15651566Var_Parse (str, ctxt, err, lengthPtr, freePtr)
    1566     char          *str;         /* The string to parse */
    1567     GNode         *ctxt;        /* The context for the variable */
    1568     Boolean         err;        /* TRUE if undefined variables are an error */
    1569     int             *lengthPtr; /* OUT: The length of the specification */
    1570     Boolean         *freePtr;   /* OUT: TRUE if caller should efree result */
    1571 {
    1572     register char   *tstr;      /* Pointer into str */
    1573     Var             *v;         /* Variable in invocation */
    1574     char            *cp;        /* Secondary pointer into str (place marker
    1575                                 * for tstr) */
    1576     Boolean         haveModifier;/* TRUE if have modifiers for the variable */
    1577     register char   endc;       /* Ending character when variable in parens
    1578                                 * or braces */
    1579     register char   startc=0;   /* Starting character when variable in parens
    1580                                 * or braces */
    1581     int             cnt;        /* Used to count brace pairs when variable in
    1582                                 * in parens or braces */
    1583     char            *start;
    1584     char             delim;
    1585     Boolean         dynamic;    /* TRUE if the variable is local and we're
    1586                                 * expanding it in a non-local context. This
    1587                                 * is done to support dynamic sources. The
    1588                                 * result is just the invocation, unaltered */
    1589     int         vlen;           /* length of variable name, after embedded variable
    1590                                 * expansion */
     1567    char          *str;         /* The string to parse */
     1568    GNode         *ctxt;        /* The context for the variable */
     1569    Boolean         err;        /* TRUE if undefined variables are an error */
     1570    int             *lengthPtr; /* OUT: The length of the specification */
     1571    Boolean         *freePtr;   /* OUT: TRUE if caller should efree result */
     1572{
     1573    register char   *tstr;      /* Pointer into str */
     1574    Var             *v;         /* Variable in invocation */
     1575    char            *cp;        /* Secondary pointer into str (place marker
     1576                                * for tstr) */
     1577    Boolean         haveModifier;/* TRUE if have modifiers for the variable */
     1578    register char   endc;       /* Ending character when variable in parens
     1579                                * or braces */
     1580    register char   startc=0;   /* Starting character when variable in parens
     1581                                * or braces */
     1582    int             cnt;        /* Used to count brace pairs when variable in
     1583                                * in parens or braces */
     1584    char            *start;
     1585    char             delim;
     1586    Boolean         dynamic;    /* TRUE if the variable is local and we're
     1587                                * expanding it in a non-local context. This
     1588                                * is done to support dynamic sources. The
     1589                                * result is just the invocation, unaltered */
     1590    int         vlen;           /* length of variable name, after embedded variable
     1591                                * expansion */
    15911592
    15921593    *freePtr = FALSE;
    15931594    dynamic = FALSE;
    15941595    start = str;
    1595 //debugkso: fprintf(stderr, "var: str=%s\n", str);
    15961596
    15971597    if (str[1] != '(' && str[1] != '{') {
    1598         /*
    1599         * If it's not bounded by braces of some sort, life is much simpler.
    1600         * We just need to check for the first character and return the
    1601         * value if it exists.
    1602         */
    1603         char      name[2];
    1604 
    1605         name[0] = str[1];
    1606         name[1] = '\0';
    1607 
    1608         v = VarFind (name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
    1609         if (v == (Var *)NIL) {
    1610             *lengthPtr = 2;
    1611 
    1612             if ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)) {
    1613                 /*
    1614                 * If substituting a local variable in a non-local context,
    1615                 * assume it's for dynamic source stuff. We have to handle
    1616                 * this specially and return the longhand for the variable
    1617                 * with the dollar sign escaped so it makes it back to the
    1618                 * caller. Only four of the local variables are treated
    1619                 * specially as they are the only four that will be set
    1620                 * when dynamic sources are expanded.
    1621                 */
    1622                 /* XXX: It looks like $% and $! are reversed here */
    1623                 switch (str[1]) {
    1624                     case '@':
    1625                         return("$(.TARGET)");
    1626                     case '%':
    1627                         return("$(.ARCHIVE)");
    1628                     case '*':
    1629                         return("$(.PREFIX)");
    1630                     case '!':
    1631                         return("$(.MEMBER)");
     1598        /*
     1599        * If it's not bounded by braces of some sort, life is much simpler.
     1600        * We just need to check for the first character and return the
     1601        * value if it exists.
     1602        */
     1603        char      name[2];
     1604
     1605        name[0] = str[1];
     1606        name[1] = '\0';
     1607
     1608        v = VarFind (name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
     1609        if (v == (Var *)NIL) {
     1610            *lengthPtr = 2;
     1611
     1612            if ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)) {
     1613                /*
     1614                * If substituting a local variable in a non-local context,
     1615                * assume it's for dynamic source stuff. We have to handle
     1616                * this specially and return the longhand for the variable
     1617                * with the dollar sign escaped so it makes it back to the
     1618                * caller. Only four of the local variables are treated
     1619                * specially as they are the only four that will be set
     1620                * when dynamic sources are expanded.
     1621                */
     1622                /* XXX: It looks like $% and $! are reversed here */
     1623                switch (str[1]) {
     1624                    case '@':
     1625                        return("$(.TARGET)");
     1626                    case '%':
     1627                        return("$(.ARCHIVE)");
     1628                    case '*':
     1629                        return("$(.PREFIX)");
     1630                    case '!':
     1631                        return("$(.MEMBER)");
    16321632                    #ifdef USE_PARENTS
    1633                     case '^':
    1634                         return("$(.PARENTS)");
     1633                    case '^':
     1634                        return("$(.PARENTS)");
    16351635                    #endif
    1636                 }
    1637             }
    1638             /*
    1639              * Error
    1640              */
    1641             return (err ? var_Error : varNoError);
    1642         } else {
    1643             haveModifier = FALSE;
    1644             tstr = &str[1];
    1645             endc = str[1];
    1646         }
     1636                }
     1637            }
     1638            /*
     1639             * Error
     1640             */
     1641            return (err ? var_Error : varNoError);
     1642        } else {
     1643            haveModifier = FALSE;
     1644            tstr = &str[1];
     1645            endc = str[1];
     1646        }
    16471647    } else {
    1648         /* build up expanded variable name in this buffer */
    1649         Buffer  buf = Buf_Init(MAKE_BSIZE);
    1650 
    1651         startc = str[1];
    1652         endc = startc == '(' ? ')' : '}';
    1653 
    1654         /*
    1655         * Skip to the end character or a colon, whichever comes first,
    1656         * replacing embedded variables as we go.
    1657         */
    1658         for (tstr = str + 2; *tstr != '\0' && *tstr != endc && *tstr != ':'; tstr++)
    1659                 if (*tstr == '$') {
    1660                         int     rlen;
    1661                         Boolean rfree;
    1662                         char*   rval = Var_Parse(tstr, ctxt, err, &rlen, &rfree);
    1663 
    1664                         if (rval == var_Error) {
    1665                                 Fatal("Error expanding embedded variable.");
    1666                         } else if (rval != NULL) {
    1667                                 Buf_AddBytes(buf, strlen(rval), (Byte *) rval);
    1668                                 if (rfree)
    1669                                         efree(rval);
    1670                         }
    1671                         tstr += rlen - 1;
    1672                 } else
    1673                         Buf_AddByte(buf, (Byte) *tstr);
    1674        
    1675         if (*tstr == '\0') {
    1676             /*
    1677              * If we never did find the end character, return NULL
    1678              * right now, setting the length to be the distance to
    1679              * the end of the string, since that's what make does.
    1680              */
    1681             *lengthPtr = tstr - str;
    1682             return (var_Error);
    1683         }
    1684        
    1685         haveModifier = (*tstr == ':');
    1686         *tstr = '\0';
    1687 
    1688         Buf_AddByte(buf, (Byte) '\0');
    1689         str = Buf_GetAll(buf, NULL);
    1690         vlen = strlen(str);
    1691 
    1692         v = VarFind (str, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
    1693         if ((v == (Var *)NIL) && (ctxt != VAR_CMD) && (ctxt != VAR_GLOBAL) &&
    1694 #if defined(NMAKE) || defined(KMK)
    1695             (vlen == 2) && (str[1] == 'F' || str[1] == 'D' || str[1] == 'B' || str[1] == 'R'))
     1648        /* build up expanded variable name in this buffer */
     1649        Buffer  buf = Buf_Init(MAKE_BSIZE);
     1650
     1651        startc = str[1];
     1652        endc = startc == '(' ? ')' : '}';
     1653
     1654        /*
     1655        * Skip to the end character or a colon, whichever comes first,
     1656        * replacing embedded variables as we go.
     1657        */
     1658        for (tstr = str + 2; *tstr != '\0' && *tstr != endc && *tstr != ':'; tstr++)
     1659                if (*tstr == '$') {
     1660                        int     rlen;
     1661                        Boolean rfree;
     1662                        char*   rval = Var_Parse(tstr, ctxt, err, &rlen, &rfree);
     1663
     1664                        if (rval == var_Error) {
     1665                                Fatal("Error expanding embedded variable.");
     1666                        } else if (rval != NULL) {
     1667                                Buf_AddBytes(buf, strlen(rval), (Byte *) rval);
     1668                                if (rfree)
     1669                                        efree(rval);
     1670                        }
     1671                        tstr += rlen - 1;
     1672                } else
     1673                        Buf_AddByte(buf, (Byte) *tstr);
     1674
     1675        if (*tstr == '\0') {
     1676            /*
     1677             * If we never did find the end character, return NULL
     1678             * right now, setting the length to be the distance to
     1679             * the end of the string, since that's what make does.
     1680             */
     1681            *lengthPtr = tstr - str;
     1682            return (var_Error);
     1683        }
     1684
     1685        haveModifier = (*tstr == ':');
     1686        *tstr = '\0';
     1687
     1688        Buf_AddByte(buf, (Byte) '\0');
     1689        str = Buf_GetAll(buf, NULL);
     1690        vlen = strlen(str);
     1691
     1692        v = VarFind (str, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
     1693        if ((v == (Var *)NIL) && (ctxt != VAR_CMD) && (ctxt != VAR_GLOBAL) &&
     1694#ifdef USE_BASEANDROOT_MODIFIERS
     1695            (vlen == 2) && (str[1] == 'F' || str[1] == 'D' || str[1] == 'B' || str[1] == 'R'))
    16961696#else
    1697             (vlen == 2) && (str[1] == 'F' || str[1] == 'D'))
     1697            (vlen == 2) && (str[1] == 'F' || str[1] == 'D'))
    16981698#endif
    1699         {
    1700             /*
    1701              * Check for bogus D and F forms of local variables since we're
    1702              * in a local context and the name is the right length.
    1703              */
    1704             switch(str[0]) {
    1705                 case '@':
    1706                 case '%':
    1707                 case '*':
    1708                 case '!':
    1709                 case '>':
    1710                 case '<':
    1711                 {
    1712                     char    vname[2];
    1713                     char    *val;
    1714 
    1715                     /*
    1716                      * Well, it's local -- go look for it.
    1717                      */
    1718                     vname[0] = str[0];
    1719                     vname[1] = '\0';
    1720                     v = VarFind(vname, ctxt, 0);
    1721 
    1722                     if (v != (Var *)NIL && !haveModifier) {
    1723                         /*
    1724                         * No need for nested expansion or anything, as we're
    1725                         * the only one who sets these things and we sure don't
    1726                         * put nested invocations in them...
    1727                         */
    1728                         val = (char *)Buf_GetAll(v->val, (int *)NULL);
    1729 
    1730 #if defined(NMAKE) || defined(KMK)
    1731                         switch (str[1])
     1699        {
     1700            /*
     1701             * Check for bogus D and F forms of local variables since we're
     1702             * in a local context and the name is the right length.
     1703             */
     1704            switch(str[0]) {
     1705                case '@':
     1706                case '%':
     1707                case '*':
     1708                case '!':
     1709                case '>':
     1710                case '<':
     1711                {
     1712                    char    vname[2];
     1713                    char    *val;
     1714
     1715                    /*
     1716                     * Well, it's local -- go look for it.
     1717                     */
     1718                    vname[0] = str[0];
     1719                    vname[1] = '\0';
     1720                    v = VarFind(vname, ctxt, 0);
     1721
     1722                    if (v != (Var *)NIL && !haveModifier) {
     1723                        /*
     1724                        * No need for nested expansion or anything, as we're
     1725                        * the only one who sets these things and we sure don't
     1726                        * put nested invocations in them...
     1727                        */
     1728                        val = (char *)Buf_GetAll(v->val, (int *)NULL);
     1729
     1730#ifdef USE_BASEANDROOT_MODIFIERS
     1731                        switch (str[1])
    17321732                        {
    17331733                        case 'D': val = VarModify(val, VarHead, (ClientData)0); break;
     
    17351735                        case 'R': val = VarModify(val, VarRoot, (ClientData)0); break;
    17361736                        default:  val = VarModify(val, VarTail, (ClientData)0); break;
    1737                         }
     1737                        }
    17381738#else
    1739                         if (str[1] == 'D') {
    1740                             val = VarModify(val, VarHead, (ClientData)0);
    1741                         } else {
    1742                             val = VarModify(val, VarTail, (ClientData)0);
    1743                         }
     1739                        if (str[1] == 'D') {
     1740                            val = VarModify(val, VarHead, (ClientData)0);
     1741                        } else {
     1742                            val = VarModify(val, VarTail, (ClientData)0);
     1743                        }
    17441744#endif
    1745                         /*
    1746                          * Resulting string is dynamically allocated, so
    1747                          * tell caller to efree it.
    1748                          */
    1749                         *freePtr = TRUE;
    1750                         *lengthPtr = tstr-start+1;
    1751                         *tstr = endc;
    1752                         Buf_Destroy(buf, TRUE);
    1753                         return(val);
    1754                     }
    1755                     break;
    1756                 }
    1757             }
    1758         }
    1759 
    1760         if (v == (Var *)NIL) {
    1761 //debugkso: fprintf(stderr, "\tv == (Var *)NIL vlen=%d str=%s\n", vlen, str);
    1762 
    1763             if (((vlen == 1) ||
    1764                  (((vlen == 2) && (str[1] == 'F' ||
    1765 #if defined(NMAKE) || defined(KMK)
     1745                        /*
     1746                         * Resulting string is dynamically allocated, so
     1747                         * tell caller to efree it.
     1748                         */
     1749                        *freePtr = TRUE;
     1750                        *lengthPtr = tstr-start+1;
     1751                        *tstr = endc;
     1752                        Buf_Destroy(buf, TRUE);
     1753                        return(val);
     1754                    }
     1755                    break;
     1756                }
     1757            }
     1758        }
     1759
     1760        if (v == (Var *)NIL) {
     1761
     1762            if (((vlen == 1) ||
     1763                 (((vlen == 2) && (str[1] == 'F' ||
     1764#ifdef USE_BASEANDROOT_MODIFIERS
    17661765                                         str[1] == 'D' || str[1] == 'B' || str[1] == 'R')))) &&
    17671766#else
    1768                                         str[1] == 'D')))) &&
     1767                                        str[1] == 'D')))) &&
    17691768#endif
    1770                 ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)))
    1771             {
    1772                 /*
    1773                 * If substituting a local variable in a non-local context,
    1774                 * assume it's for dynamic source stuff. We have to handle
    1775                 * this specially and return the longhand for the variable
    1776                 * with the dollar sign escaped so it makes it back to the
    1777                 * caller. Only four of the local variables are treated
    1778                 * specially as they are the only four that will be set
    1779                 * when dynamic sources are expanded.
    1780                 */
    1781                 switch (str[0]) {
    1782                     case '@':
    1783                     case '%':
    1784                     case '*':
    1785                     case '!':
     1769                ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)))
     1770            {
     1771                /*
     1772                * If substituting a local variable in a non-local context,
     1773                * assume it's for dynamic source stuff. We have to handle
     1774                * this specially and return the longhand for the variable
     1775                * with the dollar sign escaped so it makes it back to the
     1776                * caller. Only four of the local variables are treated
     1777                * specially as they are the only four that will be set
     1778                * when dynamic sources are expanded.
     1779                */
     1780                switch (str[0]) {
     1781                    case '@':
     1782                    case '%':
     1783                    case '*':
     1784                    case '!':
    17861785                    #ifdef USE_PARENTS
    1787                     case '^':
     1786                    case '^':
    17881787                    #endif
    1789                         dynamic = TRUE;
    1790                         break;
    1791                 }
    1792             } else if ((vlen > 2) && (str[0] == '.') &&
    1793                        isupper((unsigned char) str[1]) &&
    1794                        ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)))
    1795             {
    1796                 int     len;
    1797 
    1798                 len = vlen - 1;
    1799                 if ((strncmp(str, ".TARGET", len) == 0) ||
    1800                     (strncmp(str, ".ARCHIVE", len) == 0) ||
    1801                     (strncmp(str, ".PREFIX", len) == 0) ||
     1788                        dynamic = TRUE;
     1789                        break;
     1790                }
     1791            } else if ((vlen > 2) && (str[0] == '.') &&
     1792                       isupper((unsigned char) str[1]) &&
     1793                       ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)))
     1794            {
     1795                int     len;
     1796
     1797                len = vlen - 1;
     1798                if ((strncmp(str, ".TARGET", len) == 0) ||
     1799                    (strncmp(str, ".ARCHIVE", len) == 0) ||
     1800                    (strncmp(str, ".PREFIX", len) == 0) ||
    18021801                    #ifdef USE_PARENTS
    1803                     (strncmp(str, ".PARENTS", len) == 0) ||
     1802                    (strncmp(str, ".PARENTS", len) == 0) ||
    18041803                    #endif
    1805                     (strncmp(str, ".MEMBER", len) == 0))
    1806                 {
    1807                     dynamic = TRUE;
    1808                 }
    1809             }
    1810 
    1811             if (!haveModifier) {
    1812                 /*
    1813                 * No modifiers -- have specification length so we can return
    1814                 * now.
    1815                 */
    1816                 *lengthPtr = tstr - start + 1;
    1817                 *tstr = endc;
    1818                 if (dynamic) {
    1819                     str = emalloc(*lengthPtr + 1);
    1820                     strncpy(str, start, *lengthPtr);
    1821                     str[*lengthPtr] = '\0';
    1822                     *freePtr = TRUE;
    1823                     Buf_Destroy(buf, TRUE);
    1824                     return(str);
    1825                 } else {
    1826                     Buf_Destroy(buf, TRUE);
    1827                     return (err ? var_Error : varNoError);
    1828                 }
    1829             } else {
    1830                 /*
    1831                 * Still need to get to the end of the variable specification,
    1832                 * so kludge up a Var structure for the modifications
    1833                 */
    1834                 v = (Var *) emalloc(sizeof(Var));
    1835                 v->name = &str[1];
    1836                 v->val = Buf_Init(1);
    1837                 v->flags = VAR_JUNK;
    1838             }
    1839         }
    1840         Buf_Destroy(buf, TRUE);
     1804                    (strncmp(str, ".MEMBER", len) == 0))
     1805                {
     1806                    dynamic = TRUE;
     1807                }
     1808            }
     1809
     1810            if (!haveModifier) {
     1811                /*
     1812                * No modifiers -- have specification length so we can return
     1813                * now.
     1814                */
     1815                *lengthPtr = tstr - start + 1;
     1816                *tstr = endc;
     1817                if (dynamic) {
     1818                    str = emalloc(*lengthPtr + 1);
     1819                    strncpy(str, start, *lengthPtr);
     1820                    str[*lengthPtr] = '\0';
     1821                    *freePtr = TRUE;
     1822                    Buf_Destroy(buf, TRUE);
     1823                    return(str);
     1824                } else {
     1825                    Buf_Destroy(buf, TRUE);
     1826                    return (err ? var_Error : varNoError);
     1827                }
     1828            } else {
     1829                /*
     1830                * Still need to get to the end of the variable specification,
     1831                * so kludge up a Var structure for the modifications
     1832                */
     1833                v = (Var *) emalloc(sizeof(Var));
     1834                v->name = &str[1];
     1835                v->val = Buf_Init(1);
     1836                v->flags = VAR_JUNK;
     1837            }
     1838        }
     1839        Buf_Destroy(buf, TRUE);
    18411840    }
    18421841
    18431842    if (v->flags & VAR_IN_USE) {
    1844         Fatal("Variable %s is recursive.", v->name);
    1845         /*NOTREACHED*/
     1843        Fatal("Variable %s is recursive.", v->name);
     1844        /*NOTREACHED*/
    18461845    } else {
    1847         v->flags |= VAR_IN_USE;
     1846        v->flags |= VAR_IN_USE;
    18481847    }
    18491848    /*
     
    18581857    str = (char *)Buf_GetAll(v->val, (int *)NULL);
    18591858    if (strchr (str, '$') != (char *)NULL) {
    1860         str = Var_Subst(NULL, str, ctxt, err);
    1861         *freePtr = TRUE;
     1859        str = Var_Subst(NULL, str, ctxt, err);
     1860        *freePtr = TRUE;
    18621861    }
    18631862
     
    18671866     * Now we need to apply any modifiers the user wants applied.
    18681867     * These are:
    1869      *            :M<pattern>   words which match the given <pattern>.
    1870      *                          <pattern> is of the standard file
    1871      *                          wildcarding form.
    1872      *            :S<d><pat1><d><pat2><d>[g]
    1873      *                          Substitute <pat2> for <pat1> in the value
    1874      *            :C<d><pat1><d><pat2><d>[g]
    1875      *                          Substitute <pat2> for regex <pat1> in the value
    1876      *            :H            Substitute the head of each word
    1877      *            :T            Substitute the tail of each word
    1878      *            :E            Substitute the extension (minus '.') of
    1879      *                          each word
    1880      *            :R            Substitute the root of each word
    1881      *                          (pathname minus the suffix).
    1882      *            :lhs=rhs      Like :S, but the rhs goes to the end of
    1883      *                          the invocation.
    1884      *            :U            Converts variable to upper-case.
    1885      *            :L            Converts variable to lower-case.
     1868     *            :M<pattern>   words which match the given <pattern>.
     1869     *                          <pattern> is of the standard file
     1870     *                          wildcarding form.
     1871     *            :S<d><pat1><d><pat2><d>[g]
     1872     *                          Substitute <pat2> for <pat1> in the value
     1873     *            :C<d><pat1><d><pat2><d>[g]
     1874     *                          Substitute <pat2> for regex <pat1> in the value
     1875     *            :H            Substitute the head of each word
     1876     *            :T            Substitute the tail of each word
     1877     *            :E            Substitute the extension (minus '.') of
     1878     *                          each word
     1879     *            :R            Substitute the root of each word
     1880     *                          (pathname minus the suffix).
     1881     *            :lhs=rhs      Like :S, but the rhs goes to the end of
     1882     *                          the invocation.
     1883     *            :U            Converts variable to upper-case.
     1884     *            :L            Converts variable to lower-case.
    18861885     */
    18871886    if ((str != (char *)NULL) && haveModifier) {
    1888         /*
    1889         * Skip initial colon while putting it back.
    1890         */
    1891         *tstr++ = ':';
    1892         while (*tstr != endc) {
    1893             char        *newStr;    /* New value to return */
    1894             char        termc;      /* Character which terminated scan */
    1895 
    1896             if (DEBUG(VAR)) {
    1897                 printf("Applying :%c to \"%s\"\n", *tstr, str);
    1898             }
    1899             switch (*tstr) {
    1900                 case 'U':
    1901                         if (tstr[1] == endc || tstr[1] == ':') {
    1902                                 Buffer buf;
    1903                                 buf = Buf_Init(MAKE_BSIZE);
    1904                                 for (cp = str; *cp ; cp++)
    1905                                         Buf_AddByte(buf, (Byte) toupper(*cp));
    1906 
    1907                                 Buf_AddByte(buf, (Byte) '\0');
    1908                                 newStr = (char *) Buf_GetAll(buf, (int *) NULL);
    1909                                 Buf_Destroy(buf, FALSE);
    1910 
    1911                                 cp = tstr + 1;
    1912                                 termc = *cp;
    1913                                 break;
    1914                         }
    1915                         /* FALLTHROUGH */
    1916                 case 'L':
    1917                         if (tstr[1] == endc || tstr[1] == ':') {
    1918                                 Buffer buf;
    1919                                 buf = Buf_Init(MAKE_BSIZE);
    1920                                 for (cp = str; *cp ; cp++)
    1921                                         Buf_AddByte(buf, (Byte) tolower(*cp));
    1922 
    1923                                 Buf_AddByte(buf, (Byte) '\0');
    1924                                 newStr = (char *) Buf_GetAll(buf, (int *) NULL);
    1925                                 Buf_Destroy(buf, FALSE);
    1926 
    1927                                 cp = tstr + 1;
    1928                                 termc = *cp;
    1929                                 break;
    1930                         }
    1931                         /* FALLTHROUGH */
    1932                 case 'N':
    1933                 case 'M':
    1934                 {
    1935                     char    *pattern;
    1936                     char    *cp2;
    1937                     Boolean copy;
    1938 
    1939                     copy = FALSE;
    1940                     for (cp = tstr + 1;
    1941                         *cp != '\0' && *cp != ':' && *cp != endc;
    1942                         cp++)
    1943                     {
    1944                         if (*cp == '\\' && (cp[1] == ':' || cp[1] == endc)){
    1945                             copy = TRUE;
    1946                             cp++;
    1947                         }
    1948                     }
    1949                     termc = *cp;
    1950                     *cp = '\0';
    1951                     if (copy) {
    1952                         /*
    1953                         * Need to compress the \:'s out of the pattern, so
    1954                         * allocate enough room to hold the uncompressed
    1955                         * pattern (note that cp started at tstr+1, so
    1956                         * cp - tstr takes the null byte into account) and
    1957                         * compress the pattern into the space.
    1958                         */
    1959                         pattern = emalloc(cp - tstr);
    1960                         for (cp2 = pattern, cp = tstr + 1;
    1961                              *cp != '\0';
    1962                              cp++, cp2++)
    1963                         {
    1964                             if ((*cp == '\\') &&
    1965                                 (cp[1] == ':' || cp[1] == endc)) {
    1966                                     cp++;
    1967                             }
    1968                             *cp2 = *cp;
    1969                         }
    1970                         *cp2 = '\0';
    1971                     } else {
    1972                         pattern = &tstr[1];
    1973                     }
    1974                     if (*tstr == 'M' || *tstr == 'm') {
    1975                         newStr = VarModify(str, VarMatch, (ClientData)pattern);
    1976                     } else {
    1977                         newStr = VarModify(str, VarNoMatch,
    1978                                            (ClientData)pattern);
    1979                     }
    1980                     if (copy) {
    1981                         efree(pattern);
    1982                     }
    1983                     break;
    1984                 }
    1985                 case 'S':
    1986                 {
    1987                     VarPattern      pattern;
    1988                     register char   delim;
    1989                     Buffer          buf;        /* Buffer for patterns */
    1990 
    1991                     pattern.flags = 0;
    1992                     delim = tstr[1];
    1993                     tstr += 2;
    1994 
    1995                     /*
    1996                      * If pattern begins with '^', it is anchored to the
    1997                      * start of the word -- skip over it and flag pattern.
    1998                      */
    1999                     if (*tstr == '^') {
    2000                         pattern.flags |= VAR_MATCH_START;
    2001                         tstr += 1;
    2002                     }
    2003 
    2004                     buf = Buf_Init(0);
    2005 
    2006                     /*
    2007                      * Pass through the lhs looking for 1) escaped delimiters,
    2008                      * '$'s and backslashes (place the escaped character in
    2009                      * uninterpreted) and 2) unescaped $'s that aren't before
    2010                      * the delimiter (expand the variable substitution).
    2011                      * The result is left in the Buffer buf.
    2012                      */
    2013                     for (cp = tstr; *cp != '\0' && *cp != delim; cp++) {
    2014                         if ((*cp == '\\') &&
    2015                             ((cp[1] == delim) ||
    2016                              (cp[1] == '$') ||
    2017                              (cp[1] == '\\')))
    2018                         {
    2019                             Buf_AddByte(buf, (Byte)cp[1]);
    2020                             cp++;
    2021                         } else if (*cp == '$') {
    2022                             if (cp[1] != delim) {
    2023                                 /*
    2024                                 * If unescaped dollar sign not before the
    2025                                 * delimiter, assume it's a variable
    2026                                 * substitution and recurse.
    2027                                 */
    2028                                 char        *cp2;
    2029                                 int         len;
    2030                                 Boolean     freeIt;
    2031 
    2032                                 cp2 = Var_Parse(cp, ctxt, err, &len, &freeIt);
    2033                                 Buf_AddBytes(buf, strlen(cp2), (Byte *)cp2);
    2034                                 if (freeIt) {
    2035                                     efree(cp2);
    2036                                 }
    2037                                 cp += len - 1;
    2038                             } else {
    2039                                 /*
    2040                                 * Unescaped $ at end of pattern => anchor
    2041                                 * pattern at end.
    2042                                 */
    2043                                 pattern.flags |= VAR_MATCH_END;
    2044                             }
    2045                         } else {
    2046                             Buf_AddByte(buf, (Byte)*cp);
    2047                         }
    2048                     }
    2049 
    2050                     Buf_AddByte(buf, (Byte)'\0');
    2051 
    2052                     /*
    2053                      * If lhs didn't end with the delimiter, complain and
    2054                      * return NULL
    2055                      */
    2056                     if (*cp != delim) {
    2057                         *lengthPtr = cp - start + 1;
    2058                         if (*freePtr) {
    2059                             efree(str);
    2060                         }
    2061                         Buf_Destroy(buf, TRUE);
    2062                         Error("Unclosed substitution for %s (%c missing)",
    2063                               v->name, delim);
    2064                         return (var_Error);
    2065                     }
    2066 
    2067                     /*
    2068                      * Fetch pattern and destroy buffer, but preserve the data
    2069                      * in it, since that's our lhs. Note that Buf_GetAll
    2070                      * will return the actual number of bytes, which includes
    2071                      * the null byte, so we have to decrement the length by
    2072                      * one.
    2073                      */
    2074                     pattern.lhs = (char *)Buf_GetAll(buf, &pattern.leftLen);
    2075                     pattern.leftLen--;
    2076                     Buf_Destroy(buf, FALSE);
    2077 
    2078                     /*
    2079                      * Now comes the replacement string. Three things need to
    2080                      * be done here: 1) need to compress escaped delimiters and
    2081                      * ampersands and 2) need to replace unescaped ampersands
    2082                      * with the l.h.s. (since this isn't regexp, we can do
    2083                      * it right here) and 3) expand any variable substitutions.
    2084                      */
    2085                     buf = Buf_Init(0);
    2086 
    2087                     tstr = cp + 1;
    2088                     for (cp = tstr; *cp != '\0' && *cp != delim; cp++) {
    2089                         if ((*cp == '\\') &&
    2090                             ((cp[1] == delim) ||
    2091                              (cp[1] == '&') ||
    2092                              (cp[1] == '\\') ||
    2093                              (cp[1] == '$')))
    2094                         {
    2095                             Buf_AddByte(buf, (Byte)cp[1]);
    2096                             cp++;
    2097                         } else if ((*cp == '$') && (cp[1] != delim)) {
    2098                             char    *cp2;
    2099                             int     len;
    2100                             Boolean freeIt;
    2101 
    2102                             cp2 = Var_Parse(cp, ctxt, err, &len, &freeIt);
    2103                             Buf_AddBytes(buf, strlen(cp2), (Byte *)cp2);
    2104                             cp += len - 1;
    2105                             if (freeIt) {
    2106                                 efree(cp2);
    2107                             }
    2108                         } else if (*cp == '&') {
    2109                             Buf_AddBytes(buf, pattern.leftLen,
    2110                                         (Byte *)pattern.lhs);
    2111                         } else {
    2112                             Buf_AddByte(buf, (Byte)*cp);
    2113                         }
    2114                     }
    2115 
    2116                     Buf_AddByte(buf, (Byte)'\0');
    2117 
    2118                     /*
    2119                      * If didn't end in delimiter character, complain
    2120                      */
    2121                     if (*cp != delim) {
    2122                         *lengthPtr = cp - start + 1;
    2123                         if (*freePtr) {
    2124                             efree(str);
    2125                         }
    2126                         Buf_Destroy(buf, TRUE);
    2127                         Error("Unclosed substitution for %s (%c missing)",
    2128                               v->name, delim);
    2129                         return (var_Error);
    2130                     }
    2131 
    2132                     pattern.rhs = (char *)Buf_GetAll(buf, &pattern.rightLen);
    2133                     pattern.rightLen--;
    2134                     Buf_Destroy(buf, FALSE);
    2135 
    2136                     /*
    2137                      * Check for global substitution. If 'g' after the final
    2138                      * delimiter, substitution is global and is marked that
    2139                      * way.
    2140                      */
    2141                     cp++;
    2142                     if (*cp == 'g') {
    2143                         pattern.flags |= VAR_SUB_GLOBAL;
    2144                         cp++;
    2145                     }
    2146 
    2147                     termc = *cp;
    2148                     newStr = VarModify(str, VarSubstitute,
    2149                                        (ClientData)&pattern);
    2150                     /*
    2151                      * Free the two strings.
    2152                      */
    2153                     efree(pattern.lhs);
    2154                     efree(pattern.rhs);
    2155                     break;
    2156                 }
    2157                 case 'C':
    2158                 {
    2159                     VarREPattern    pattern;
    2160                     char           *re;
    2161                     int             error;
    2162 
    2163                     pattern.flags = 0;
    2164                     delim = tstr[1];
    2165                     tstr += 2;
    2166 
    2167                     cp = tstr;
    2168 
    2169                     if ((re = VarGetPattern(ctxt, err, &cp, delim, NULL,
    2170                         NULL, NULL)) == NULL) {
    2171                         /* was: goto cleanup */
    2172                         *lengthPtr = cp - start + 1;
    2173                         if (*freePtr)
    2174                             efree(str);
    2175                         if (delim != '\0')
    2176                             Error("Unclosed substitution for %s (%c missing)",
    2177                                   v->name, delim);
    2178                         return (var_Error);
    2179                     }
    2180 
    2181                     if ((pattern.replace = VarGetPattern(ctxt, err, &cp,
    2182                         delim, NULL, NULL, NULL)) == NULL){
    2183                         efree(re);
    2184 
    2185                         /* was: goto cleanup */
    2186                         *lengthPtr = cp - start + 1;
    2187                         if (*freePtr)
    2188                             efree(str);
    2189                         if (delim != '\0')
    2190                             Error("Unclosed substitution for %s (%c missing)",
    2191                                   v->name, delim);
    2192                         return (var_Error);
    2193                     }
    2194 
    2195                     for (;; cp++) {
    2196                         switch (*cp) {
    2197                         case 'g':
    2198                             pattern.flags |= VAR_SUB_GLOBAL;
    2199                             continue;
    2200                         case '1':
    2201                             pattern.flags |= VAR_SUB_ONE;
    2202                             continue;
    2203                         }
    2204                         break;
    2205                     }
    2206 
    2207                     termc = *cp;
    2208 
    2209                     error = regcomp(&pattern.re, re, REG_EXTENDED);
    2210                     efree(re);
    2211                     if (error)  {
    2212                         *lengthPtr = cp - start + 1;
    2213                         VarREError(error, &pattern.re, "RE substitution error");
    2214                         efree(pattern.replace);
    2215                         return (var_Error);
    2216                     }
    2217 
    2218                     pattern.nsub = pattern.re.re_nsub + 1;
    2219                     if (pattern.nsub < 1)
    2220                         pattern.nsub = 1;
    2221                     if (pattern.nsub > 10)
    2222                         pattern.nsub = 10;
    2223                     pattern.matches = emalloc(pattern.nsub *
    2224                                               sizeof(regmatch_t));
    2225                     newStr = VarModify(str, VarRESubstitute,
    2226                                        (ClientData) &pattern);
    2227                     regfree(&pattern.re);
    2228                     efree(pattern.replace);
    2229                     efree(pattern.matches);
    2230                     break;
    2231                 }
    2232                 case 'Q':
    2233                     if (tstr[1] == endc || tstr[1] == ':') {
    2234                         newStr = VarQuote (str);
    2235                         cp = tstr + 1;
    2236                         termc = *cp;
    2237                         break;
    2238                     }
    2239                     /*FALLTHRU*/
    2240                 case 'T':
    2241                     if (tstr[1] == endc || tstr[1] == ':') {
    2242                         newStr = VarModify (str, VarTail, (ClientData)0);
    2243                         cp = tstr + 1;
    2244                         termc = *cp;
    2245                         break;
    2246                     }
    2247                     /*FALLTHRU*/
    2248                 case 'H':
    2249                     if (tstr[1] == endc || tstr[1] == ':') {
    2250                         newStr = VarModify (str, VarHead, (ClientData)0);
    2251                         cp = tstr + 1;
    2252                         termc = *cp;
    2253                         break;
    2254                     }
    2255                     /*FALLTHRU*/
    2256                 case 'E':
    2257                     if (tstr[1] == endc || tstr[1] == ':') {
    2258                         newStr = VarModify (str, VarSuffix, (ClientData)0);
    2259                         cp = tstr + 1;
    2260                         termc = *cp;
    2261                         break;
    2262                     }
    2263                     /*FALLTHRU*/
    2264                 case 'R':
    2265                     if (tstr[1] == endc || tstr[1] == ':') {
    2266                         newStr = VarModify (str, VarRoot, (ClientData)0);
    2267                         cp = tstr + 1;
    2268                         termc = *cp;
    2269                         break;
    2270                     }
    2271                     /*FALLTHRU*/
     1887        /*
     1888        * Skip initial colon while putting it back.
     1889        */
     1890        *tstr++ = ':';
     1891        while (*tstr != endc) {
     1892            char        *newStr;    /* New value to return */
     1893            char        termc;      /* Character which terminated scan */
     1894
     1895            if (DEBUG(VAR)) {
     1896                printf("Applying :%c to \"%s\"\n", *tstr, str);
     1897            }
     1898            switch (*tstr) {
     1899                case 'U':
     1900                        if (tstr[1] == endc || tstr[1] == ':') {
     1901                                Buffer buf;
     1902                                buf = Buf_Init(MAKE_BSIZE);
     1903                                for (cp = str; *cp ; cp++)
     1904                                        Buf_AddByte(buf, (Byte) toupper(*cp));
     1905
     1906                                Buf_AddByte(buf, (Byte) '\0');
     1907                                newStr = (char *) Buf_GetAll(buf, (int *) NULL);
     1908                                Buf_Destroy(buf, FALSE);
     1909
     1910                                cp = tstr + 1;
     1911                                termc = *cp;
     1912                                break;
     1913                        }
     1914                        /* FALLTHROUGH */
     1915                case 'L':
     1916                        if (tstr[1] == endc || tstr[1] == ':') {
     1917                                Buffer buf;
     1918                                buf = Buf_Init(MAKE_BSIZE);
     1919                                for (cp = str; *cp ; cp++)
     1920                                        Buf_AddByte(buf, (Byte) tolower(*cp));
     1921
     1922                                Buf_AddByte(buf, (Byte) '\0');
     1923                                newStr = (char *) Buf_GetAll(buf, (int *) NULL);
     1924                                Buf_Destroy(buf, FALSE);
     1925
     1926                                cp = tstr + 1;
     1927                                termc = *cp;
     1928                                break;
     1929                        }
     1930                        /* FALLTHROUGH */
     1931                case 'N':
     1932                case 'M':
     1933                {
     1934                    char    *pattern;
     1935                    char    *cp2;
     1936                    Boolean copy;
     1937
     1938                    copy = FALSE;
     1939                    for (cp = tstr + 1;
     1940                        *cp != '\0' && *cp != ':' && *cp != endc;
     1941                        cp++)
     1942                    {
     1943                        if (*cp == '\\' && (cp[1] == ':' || cp[1] == endc)){
     1944                            copy = TRUE;
     1945                            cp++;
     1946                        }
     1947                    }
     1948                    termc = *cp;
     1949                    *cp = '\0';
     1950                    if (copy) {
     1951                        /*
     1952                        * Need to compress the \:'s out of the pattern, so
     1953                        * allocate enough room to hold the uncompressed
     1954                        * pattern (note that cp started at tstr+1, so
     1955                        * cp - tstr takes the null byte into account) and
     1956                        * compress the pattern into the space.
     1957                        */
     1958                        pattern = emalloc(cp - tstr);
     1959                        for (cp2 = pattern, cp = tstr + 1;
     1960                             *cp != '\0';
     1961                             cp++, cp2++)
     1962                        {
     1963                            if ((*cp == '\\') &&
     1964                                (cp[1] == ':' || cp[1] == endc)) {
     1965                                    cp++;
     1966                            }
     1967                            *cp2 = *cp;
     1968                        }
     1969                        *cp2 = '\0';
     1970                    } else {
     1971                        pattern = &tstr[1];
     1972                    }
     1973                    if (*tstr == 'M' || *tstr == 'm') {
     1974                        newStr = VarModify(str, VarMatch, (ClientData)pattern);
     1975                    } else {
     1976                        newStr = VarModify(str, VarNoMatch,
     1977                                           (ClientData)pattern);
     1978                    }
     1979                    if (copy) {
     1980                        efree(pattern);
     1981                    }
     1982                    break;
     1983                }
     1984                case 'S':
     1985                {
     1986                    VarPattern      pattern;
     1987                    register char   delim;
     1988                    Buffer          buf;        /* Buffer for patterns */
     1989
     1990                    pattern.flags = 0;
     1991                    delim = tstr[1];
     1992                    tstr += 2;
     1993
     1994                    /*
     1995                     * If pattern begins with '^', it is anchored to the
     1996                     * start of the word -- skip over it and flag pattern.
     1997                     */
     1998                    if (*tstr == '^') {
     1999                        pattern.flags |= VAR_MATCH_START;
     2000                        tstr += 1;
     2001                    }
     2002
     2003                    buf = Buf_Init(0);
     2004
     2005                    /*
     2006                     * Pass through the lhs looking for 1) escaped delimiters,
     2007                     * '$'s and backslashes (place the escaped character in
     2008                     * uninterpreted) and 2) unescaped $'s that aren't before
     2009                     * the delimiter (expand the variable substitution).
     2010                     * The result is left in the Buffer buf.
     2011                     */
     2012                    for (cp = tstr; *cp != '\0' && *cp != delim; cp++) {
     2013                        if ((*cp == '\\') &&
     2014                            ((cp[1] == delim) ||
     2015                             (cp[1] == '$') ||
     2016                             (cp[1] == '\\')))
     2017                        {
     2018                            Buf_AddByte(buf, (Byte)cp[1]);
     2019                            cp++;
     2020                        } else if (*cp == '$') {
     2021                            if (cp[1] != delim) {
     2022                                /*
     2023                                * If unescaped dollar sign not before the
     2024                                * delimiter, assume it's a variable
     2025                                * substitution and recurse.
     2026                                */
     2027                                char        *cp2;
     2028                                int         len;
     2029                                Boolean     freeIt;
     2030
     2031                                cp2 = Var_Parse(cp, ctxt, err, &len, &freeIt);
     2032                                Buf_AddBytes(buf, strlen(cp2), (Byte *)cp2);
     2033                                if (freeIt) {
     2034                                    efree(cp2);
     2035                                }
     2036                                cp += len - 1;
     2037                            } else {
     2038                                /*
     2039                                * Unescaped $ at end of pattern => anchor
     2040                                * pattern at end.
     2041                                */
     2042                                pattern.flags |= VAR_MATCH_END;
     2043                            }
     2044                        } else {
     2045                            Buf_AddByte(buf, (Byte)*cp);
     2046                        }
     2047                    }
     2048
     2049                    Buf_AddByte(buf, (Byte)'\0');
     2050
     2051                    /*
     2052                     * If lhs didn't end with the delimiter, complain and
     2053                     * return NULL
     2054                     */
     2055                    if (*cp != delim) {
     2056                        *lengthPtr = cp - start + 1;
     2057                        if (*freePtr) {
     2058                            efree(str);
     2059                        }
     2060                        Buf_Destroy(buf, TRUE);
     2061                        Error("Unclosed substitution for %s (%c missing)",
     2062                              v->name, delim);
     2063                        return (var_Error);
     2064                    }
     2065
     2066                    /*
     2067                     * Fetch pattern and destroy buffer, but preserve the data
     2068                     * in it, since that's our lhs. Note that Buf_GetAll
     2069                     * will return the actual number of bytes, which includes
     2070                     * the null byte, so we have to decrement the length by
     2071                     * one.
     2072                     */
     2073                    pattern.lhs = (char *)Buf_GetAll(buf, &pattern.leftLen);
     2074                    pattern.leftLen--;
     2075                    Buf_Destroy(buf, FALSE);
     2076
     2077                    /*
     2078                     * Now comes the replacement string. Three things need to
     2079                     * be done here: 1) need to compress escaped delimiters and
     2080                     * ampersands and 2) need to replace unescaped ampersands
     2081                     * with the l.h.s. (since this isn't regexp, we can do
     2082                     * it right here) and 3) expand any variable substitutions.
     2083                     */
     2084                    buf = Buf_Init(0);
     2085
     2086                    tstr = cp + 1;
     2087                    for (cp = tstr; *cp != '\0' && *cp != delim; cp++) {
     2088                        if ((*cp == '\\') &&
     2089                            ((cp[1] == delim) ||
     2090                             (cp[1] == '&') ||
     2091                             (cp[1] == '\\') ||
     2092                             (cp[1] == '$')))
     2093                        {
     2094                            Buf_AddByte(buf, (Byte)cp[1]);
     2095                            cp++;
     2096                        } else if ((*cp == '$') && (cp[1] != delim)) {
     2097                            char    *cp2;
     2098                            int     len;
     2099                            Boolean freeIt;
     2100
     2101                            cp2 = Var_Parse(cp, ctxt, err, &len, &freeIt);
     2102                            Buf_AddBytes(buf, strlen(cp2), (Byte *)cp2);
     2103                            cp += len - 1;
     2104                            if (freeIt) {
     2105                                efree(cp2);
     2106                            }
     2107                        } else if (*cp == '&') {
     2108                            Buf_AddBytes(buf, pattern.leftLen,
     2109                                        (Byte *)pattern.lhs);
     2110                        } else {
     2111                            Buf_AddByte(buf, (Byte)*cp);
     2112                        }
     2113                    }
     2114
     2115                    Buf_AddByte(buf, (Byte)'\0');
     2116
     2117                    /*
     2118                     * If didn't end in delimiter character, complain
     2119                     */
     2120                    if (*cp != delim) {
     2121                        *lengthPtr = cp - start + 1;
     2122                        if (*freePtr) {
     2123                            efree(str);
     2124                        }
     2125                        Buf_Destroy(buf, TRUE);
     2126                        Error("Unclosed substitution for %s (%c missing)",
     2127                              v->name, delim);
     2128                        return (var_Error);
     2129                    }
     2130
     2131                    pattern.rhs = (char *)Buf_GetAll(buf, &pattern.rightLen);
     2132                    pattern.rightLen--;
     2133                    Buf_Destroy(buf, FALSE);
     2134
     2135                    /*
     2136                     * Check for global substitution. If 'g' after the final
     2137                     * delimiter, substitution is global and is marked that
     2138                     * way.
     2139                     */
     2140                    cp++;
     2141                    if (*cp == 'g') {
     2142                        pattern.flags |= VAR_SUB_GLOBAL;
     2143                        cp++;
     2144                    }
     2145
     2146                    termc = *cp;
     2147                    newStr = VarModify(str, VarSubstitute,
     2148                                       (ClientData)&pattern);
     2149                    /*
     2150                     * Free the two strings.
     2151                     */
     2152                    efree(pattern.lhs);
     2153                    efree(pattern.rhs);
     2154                    break;
     2155                }
     2156                case 'C':
     2157                {
     2158                    VarREPattern    pattern;
     2159                    char           *re;
     2160                    int             error;
     2161
     2162                    pattern.flags = 0;
     2163                    delim = tstr[1];
     2164                    tstr += 2;
     2165
     2166                    cp = tstr;
     2167
     2168                    if ((re = VarGetPattern(ctxt, err, &cp, delim, NULL,
     2169                        NULL, NULL)) == NULL) {
     2170                        /* was: goto cleanup */
     2171                        *lengthPtr = cp - start + 1;
     2172                        if (*freePtr)
     2173                            efree(str);
     2174                        if (delim != '\0')
     2175                            Error("Unclosed substitution for %s (%c missing)",
     2176                                  v->name, delim);
     2177                        return (var_Error);
     2178                    }
     2179
     2180                    if ((pattern.replace = VarGetPattern(ctxt, err, &cp,
     2181                        delim, NULL, NULL, NULL)) == NULL){
     2182                        efree(re);
     2183
     2184                        /* was: goto cleanup */
     2185                        *lengthPtr = cp - start + 1;
     2186                        if (*freePtr)
     2187                            efree(str);
     2188                        if (delim != '\0')
     2189                            Error("Unclosed substitution for %s (%c missing)",
     2190                                  v->name, delim);
     2191                        return (var_Error);
     2192                    }
     2193
     2194                    for (;; cp++) {
     2195                        switch (*cp) {
     2196                        case 'g':
     2197                            pattern.flags |= VAR_SUB_GLOBAL;
     2198                            continue;
     2199                        case '1':
     2200                            pattern.flags |= VAR_SUB_ONE;
     2201                            continue;
     2202                        }
     2203                        break;
     2204                    }
     2205
     2206                    termc = *cp;
     2207
     2208                    error = regcomp(&pattern.re, re, REG_EXTENDED);
     2209                    efree(re);
     2210                    if (error)  {
     2211                        *lengthPtr = cp - start + 1;
     2212                        VarREError(error, &pattern.re, "RE substitution error");
     2213                        efree(pattern.replace);
     2214                        return (var_Error);
     2215                    }
     2216
     2217                    pattern.nsub = pattern.re.re_nsub + 1;
     2218                    if (pattern.nsub < 1)
     2219                        pattern.nsub = 1;
     2220                    if (pattern.nsub > 10)
     2221                        pattern.nsub = 10;
     2222                    pattern.matches = emalloc(pattern.nsub *
     2223                                              sizeof(regmatch_t));
     2224                    newStr = VarModify(str, VarRESubstitute,
     2225                                       (ClientData) &pattern);
     2226                    regfree(&pattern.re);
     2227                    efree(pattern.replace);
     2228                    efree(pattern.matches);
     2229                    break;
     2230                }
     2231                case 'Q':
     2232                    if (tstr[1] == endc || tstr[1] == ':') {
     2233                        newStr = VarQuote (str);
     2234                        cp = tstr + 1;
     2235                        termc = *cp;
     2236                        break;
     2237                    }
     2238                    /*FALLTHRU*/
     2239                case 'T':
     2240                    if (tstr[1] == endc || tstr[1] == ':') {
     2241                        newStr = VarModify (str, VarTail, (ClientData)0);
     2242                        cp = tstr + 1;
     2243                        termc = *cp;
     2244                        break;
     2245                    }
     2246                    /*FALLTHRU*/
     2247                case 'H':
     2248                    if (tstr[1] == endc || tstr[1] == ':') {
     2249                        newStr = VarModify (str, VarHead, (ClientData)0);
     2250                        cp = tstr + 1;
     2251                        termc = *cp;
     2252                        break;
     2253                    }
     2254                    /*FALLTHRU*/
     2255                case 'E':
     2256                    if (tstr[1] == endc || tstr[1] == ':') {
     2257                        newStr = VarModify (str, VarSuffix, (ClientData)0);
     2258                        cp = tstr + 1;
     2259                        termc = *cp;
     2260                        break;
     2261                    }
     2262                    /*FALLTHRU*/
     2263                case 'R':
     2264                    if (tstr[1] == endc || tstr[1] == ':') {
     2265                        newStr = VarModify (str, VarRoot, (ClientData)0);
     2266                        cp = tstr + 1;
     2267                        termc = *cp;
     2268                        break;
     2269                    }
     2270                    /*FALLTHRU*/
    22722271#ifdef SUNSHCMD
    2273                 case 's':
    2274                     if (tstr[1] == 'h' && (tstr[2] == endc || tstr[2] == ':')) {
    2275                         char *err;
    2276                         newStr = Cmd_Exec (str, &err);
    2277                         if (err)
    2278                             Error (err, str);
    2279                         cp = tstr + 2;
    2280                         termc = *cp;
    2281                         break;
    2282                     }
    2283                     /*FALLTHRU*/
     2272                case 's':
     2273                    if (tstr[1] == 'h' && (tstr[2] == endc || tstr[2] == ':')) {
     2274                        char *err;
     2275                        newStr = Cmd_Exec (str, &err);
     2276                        if (err)
     2277                            Error (err, str);
     2278                        cp = tstr + 2;
     2279                        termc = *cp;
     2280                        break;
     2281                    }
     2282                    /*FALLTHRU*/
    22842283#endif
    2285                 default:
    2286                 {
     2284                default:
     2285                {
    22872286#if defined(SYSVVARSUB) || defined(NMAKE)
    2288                     /*
    2289                      * This can either be a bogus modifier or a System-V
    2290                      * substitution command.
    2291                      */
    2292                     VarPattern      pattern;
    2293                     Boolean         eqFound;
    2294 
    2295                     pattern.flags = 0;
    2296                     eqFound = FALSE;
    2297                     /*
    2298                      * First we make a pass through the string trying
    2299                      * to verify it is a SYSV-make-style translation:
    2300                      * it must be: <string1>=<string2>)
    2301                      */
    2302                     cp = tstr;
    2303                     cnt = 1;
    2304                     while (*cp != '\0' && cnt) {
    2305                         if (*cp == '=') {
    2306                             eqFound = TRUE;
    2307                             /* continue looking for endc */
    2308                         }
    2309                         else if (*cp == endc)
    2310                             cnt--;
    2311                         else if (*cp == startc)
    2312                             cnt++;
    2313                         if (cnt)
    2314                             cp++;
    2315                     }
     2287                    /*
     2288                     * This can either be a bogus modifier or a System-V
     2289                     * substitution command.
     2290                     */
     2291                    VarPattern      pattern;
     2292                    Boolean         eqFound;
     2293
     2294                    pattern.flags = 0;
     2295                    eqFound = FALSE;
     2296                    /*
     2297                     * First we make a pass through the string trying
     2298                     * to verify it is a SYSV-make-style translation:
     2299                     * it must be: <string1>=<string2>)
     2300                     */
     2301                    cp = tstr;
     2302                    cnt = 1;
     2303                    while (*cp != '\0' && cnt) {
     2304                        if (*cp == '=') {
     2305                            eqFound = TRUE;
     2306                            /* continue looking for endc */
     2307                        }
     2308                        else if (*cp == endc)
     2309                            cnt--;
     2310                        else if (*cp == startc)
     2311                            cnt++;
     2312                        if (cnt)
     2313                            cp++;
     2314                    }
    23162315fprintf(stderr, "debug: cp=\"%s\" endc=%c eqFound=%d tstr=\"%s\"\n", cp, endc, eqFound, tstr);
    2317                     if (*cp == endc && eqFound) {
    2318 
    2319                         /*
    2320                         * Now we break this sucker into the lhs and
    2321                         * rhs. We must null terminate them of course.
    2322                         */
    2323                         for (cp = tstr; *cp != '='; cp++)
    2324                             continue;
    2325                         pattern.lhs = tstr;
    2326                         pattern.leftLen = cp - tstr;
    2327                         *cp++ = '\0';
    2328 
    2329                         pattern.rhs = cp;
    2330                         cnt = 1;
    2331                         while (cnt) {
    2332                             if (*cp == endc)
    2333                                 cnt--;
    2334                             else if (*cp == startc)
    2335                                 cnt++;
    2336                             if (cnt)
    2337                                 cp++;
    2338                         }
    2339                         pattern.rightLen = cp - pattern.rhs;
    2340                         *cp = '\0';
    2341 
    2342                         /*
    2343                         * SYSV modifications happen through the whole
    2344                         * string. Note the pattern is anchored at the end.
    2345                         */
    2346                         newStr = VarModify(str, VarSYSVMatch,
    2347                                            (ClientData)&pattern);
    2348 
    2349                         /*
    2350                         * Restore the nulled characters
    2351                         */
    2352                         pattern.lhs[pattern.leftLen] = '=';
    2353                         pattern.rhs[pattern.rightLen] = endc;
    2354                         termc = endc;
    2355                     } else
     2316                    if (*cp == endc && eqFound) {
     2317
     2318                        /*
     2319                        * Now we break this sucker into the lhs and
     2320                        * rhs. We must null terminate them of course.
     2321                        */
     2322                        for (cp = tstr; *cp != '='; cp++)
     2323                            continue;
     2324                        pattern.lhs = tstr;
     2325                        pattern.leftLen = cp - tstr;
     2326                        *cp++ = '\0';
     2327
     2328                        pattern.rhs = cp;
     2329                        cnt = 1;
     2330                        while (cnt) {
     2331                            if (*cp == endc)
     2332                                cnt--;
     2333                            else if (*cp == startc)
     2334                                cnt++;
     2335                            if (cnt)
     2336                                cp++;
     2337                        }
     2338                        pattern.rightLen = cp - pattern.rhs;
     2339                        *cp = '\0';
     2340
     2341                        /*
     2342                        * SYSV modifications happen through the whole
     2343                        * string. Note the pattern is anchored at the end.
     2344                        */
     2345                        newStr = VarModify(str, VarSYSVMatch,
     2346                                           (ClientData)&pattern);
     2347
     2348                        /*
     2349                        * Restore the nulled characters
     2350                        */
     2351                        pattern.lhs[pattern.leftLen] = '=';
     2352                        pattern.rhs[pattern.rightLen] = endc;
     2353                        termc = endc;
     2354                    } else
    23562355#endif
    2357                     {
    2358                         Error ("Unknown modifier '%c'\n", *tstr);
    2359                         for (cp = tstr+1;
    2360                              *cp != ':' && *cp != endc && *cp != '\0';
    2361                              cp++)
    2362                                 continue;
    2363                         termc = *cp;
    2364                         newStr = var_Error;
    2365                     }
    2366                 }
    2367             }
    2368             if (DEBUG(VAR)) {
    2369                 printf("Result is \"%s\"\n", newStr);
    2370             }
    2371 
    2372             if (*freePtr) {
    2373                 efree (str);
    2374             }
    2375             str = newStr;
    2376             if (str != var_Error) {
    2377                 *freePtr = TRUE;
    2378             } else {
    2379                 *freePtr = FALSE;
    2380             }
    2381             if (termc == '\0') {
    2382                 Error("Unclosed variable specification for %s", v->name);
    2383             } else if (termc == ':') {
    2384                 *cp++ = termc;
    2385             } else {
    2386                 *cp = termc;
    2387             }
    2388             tstr = cp;
    2389         }
    2390         *lengthPtr = tstr - start + 1;
     2356                    {
     2357                        Error ("Unknown modifier '%c'\n", *tstr);
     2358                        for (cp = tstr+1;
     2359                             *cp != ':' && *cp != endc && *cp != '\0';
     2360                             cp++)
     2361                                continue;
     2362                        termc = *cp;
     2363                        newStr = var_Error;
     2364                    }
     2365                }
     2366            }
     2367            if (DEBUG(VAR)) {
     2368                printf("Result is \"%s\"\n", newStr);
     2369            }
     2370
     2371            if (*freePtr) {
     2372                efree (str);
     2373            }
     2374            str = newStr;
     2375            if (str != var_Error) {
     2376                *freePtr = TRUE;
     2377            } else {
     2378                *freePtr = FALSE;
     2379            }
     2380            if (termc == '\0') {
     2381                Error("Unclosed variable specification for %s", v->name);
     2382            } else if (termc == ':') {
     2383                *cp++ = termc;
     2384            } else {
     2385                *cp = termc;
     2386            }
     2387            tstr = cp;
     2388        }
     2389        *lengthPtr = tstr - start + 1;
    23912390    } else {
    2392         *lengthPtr = tstr - start + 1;
    2393         *tstr = endc;
     2391        *lengthPtr = tstr - start + 1;
     2392        *tstr = endc;
    23942393    }
    23952394
    23962395    if (v->flags & VAR_FROM_ENV) {
    2397         Boolean   destroy = FALSE;
    2398 
    2399         if (str != (char *)Buf_GetAll(v->val, (int *)NULL)) {
    2400             destroy = TRUE;
    2401         } else {
    2402             /*
    2403              * Returning the value unmodified, so tell the caller to efree
    2404              * the thing.
    2405              */
    2406             *freePtr = TRUE;
    2407         }
    2408         Buf_Destroy(v->val, destroy);
    2409         efree((Address)v);
     2396        Boolean   destroy = FALSE;
     2397
     2398        if (str != (char *)Buf_GetAll(v->val, (int *)NULL)) {
     2399            destroy = TRUE;
     2400        } else {
     2401            /*
     2402             * Returning the value unmodified, so tell the caller to efree
     2403             * the thing.
     2404             */
     2405            *freePtr = TRUE;
     2406        }
     2407        Buf_Destroy(v->val, destroy);
     2408        efree((Address)v);
    24102409    } else if (v->flags & VAR_JUNK) {
    2411         /*
    2412         * Perform any efree'ing needed and set *freePtr to FALSE so the caller
    2413         * doesn't try to efree a static pointer.
    2414         */
    2415         if (*freePtr) {
    2416             efree(str);
    2417         }
    2418         *freePtr = FALSE;
    2419         Buf_Destroy(v->val, TRUE);
    2420         efree((Address)v);
    2421         if (dynamic) {
    2422             str = emalloc(*lengthPtr + 1);
    2423             strncpy(str, start, *lengthPtr);
    2424             str[*lengthPtr] = '\0';
    2425             *freePtr = TRUE;
    2426         } else {
    2427             str = err ? var_Error : varNoError;
    2428         }
     2410        /*
     2411        * Perform any efree'ing needed and set *freePtr to FALSE so the caller
     2412        * doesn't try to efree a static pointer.
     2413        */
     2414        if (*freePtr) {
     2415            efree(str);
     2416        }
     2417        *freePtr = FALSE;
     2418        Buf_Destroy(v->val, TRUE);
     2419        efree((Address)v);
     2420        if (dynamic) {
     2421            str = emalloc(*lengthPtr + 1);
     2422            strncpy(str, start, *lengthPtr);
     2423            str[*lengthPtr] = '\0';
     2424            *freePtr = TRUE;
     2425        } else {
     2426            str = err ? var_Error : varNoError;
     2427        }
    24292428    }
    24302429    return (str);
     
    24342433 *-----------------------------------------------------------------------
    24352434 * Var_Subst  --
    2436  *      Substitute for all variables in the given string in the given context
    2437  *      If undefErr is TRUE, Parse_Error will be called when an undefined
    2438  *      variable is encountered.
    2439  *
    2440  * Results:
    2441  *      The resulting string.
    2442  *
    2443  * Side Effects:
    2444  *      None. The old string must be freed by the caller
     2435 *      Substitute for all variables in the given string in the given context
     2436 *      If undefErr is TRUE, Parse_Error will be called when an undefined
     2437 *      variable is encountered.
     2438 *
     2439 * Results:
     2440 *      The resulting string.
     2441 *
     2442 * Side Effects:
     2443 *      None. The old string must be freed by the caller
    24452444 *-----------------------------------------------------------------------
    24462445 */
    24472446char *
    24482447Var_Subst (var, str, ctxt, undefErr)
    2449     char          *var;             /* Named variable || NULL for all */
    2450     char          *str;             /* the string in which to substitute */
    2451     GNode         *ctxt;            /* the context wherein to find variables */
    2452     Boolean       undefErr;         /* TRUE if undefineds are an error */
    2453 {
    2454     Buffer        buf;              /* Buffer for forming things */
    2455     char          *val;             /* Value to substitute for a variable */
    2456     int           length;           /* Length of the variable invocation */
    2457     Boolean       doFree;           /* Set true if val should be freed */
     2448    char          *var;             /* Named variable || NULL for all */
     2449    char          *str;             /* the string in which to substitute */
     2450    GNode         *ctxt;            /* the context wherein to find variables */
     2451    Boolean       undefErr;         /* TRUE if undefineds are an error */
     2452{
     2453    Buffer        buf;              /* Buffer for forming things */
     2454    char          *val;             /* Value to substitute for a variable */
     2455    int           length;           /* Length of the variable invocation */
     2456    Boolean       doFree;           /* Set true if val should be freed */
    24582457    static Boolean errorReported;   /* Set true if an error has already
    2459                                      * been reported to prevent a plethora
    2460                                      * of messages when recursing */
     2458                                     * been reported to prevent a plethora
     2459                                     * of messages when recursing */
    24612460
    24622461    buf = Buf_Init (MAKE_BSIZE);
     
    24642463
    24652464    while (*str) {
    2466         if (var == NULL && (*str == '$') && (str[1] == '$')) {
    2467             /*
    2468              * A dollar sign may be escaped either with another dollar sign.
    2469              * In such a case, we skip over the escape character and store the
    2470              * dollar sign into the buffer directly.
    2471              */
    2472             str++;
    2473             Buf_AddByte(buf, (Byte)*str);
    2474             str++;
    2475         } else if (*str != '$') {
    2476             /*
    2477              * Skip as many characters as possible -- either to the end of
    2478              * the string or to the next dollar sign (variable invocation).
    2479              */
    2480             char  *cp;
    2481 
    2482             for (cp = str++; *str != '$' && *str != '\0'; str++)
    2483                 continue;
    2484             Buf_AddBytes(buf, str - cp, (Byte *)cp);
    2485         } else {
    2486             if (var != NULL) {
    2487                 int expand;
    2488                 for (;;) {
    2489                     if (str[1] != '(' && str[1] != '{') {
    2490                         if (str[1] != *var) {
    2491                             Buf_AddBytes(buf, 2, (Byte *) str);
    2492                             str += 2;
    2493                             expand = FALSE;
    2494                         }
    2495                         else
    2496                             expand = TRUE;
    2497                         break;
    2498                     }
    2499                     else {
    2500                         char *p;
    2501 
    2502                         /*
    2503                         * Scan up to the end of the variable name.
    2504                         */
    2505                         for (p = &str[2]; *p &&
    2506                              *p != ':' && *p != ')' && *p != '}'; p++)
    2507                             if (*p == '$')
    2508                                 break;
    2509                         /*
    2510                         * A variable inside the variable. We cannot expand
    2511                         * the external variable yet, so we try again with
    2512                         * the nested one
    2513                         */
    2514                         if (*p == '$') {
    2515                             Buf_AddBytes(buf, p - str, (Byte *) str);
    2516                             str = p;
    2517                             continue;
    2518                         }
    2519 
    2520                         if (strncmp(var, str + 2, p - str - 2) != 0 ||
    2521                             var[p - str - 2] != '\0') {
    2522                             /*
    2523                              * Not the variable we want to expand, scan
    2524                              * until the next variable
    2525                              */
    2526                             for (;*p != '$' && *p != '\0'; p++)
    2527                                 continue;
    2528                             Buf_AddBytes(buf, p - str, (Byte *) str);
    2529                             str = p;
    2530                             expand = FALSE;
    2531                         }
    2532                         else
    2533                             expand = TRUE;
    2534                         break;
    2535                     }
    2536                 }
    2537                 if (!expand)
    2538                     continue;
    2539             }
    2540 
    2541             val = Var_Parse (str, ctxt, undefErr, &length, &doFree);
    2542 
    2543             /*
    2544              * When we come down here, val should either point to the
    2545              * value of this variable, suitably modified, or be NULL.
    2546              * Length should be the total length of the potential
    2547              * variable invocation (from $ to end character...)
    2548              */
    2549             if (val == var_Error || val == varNoError) {
    2550                 /*
    2551                 * If performing old-time variable substitution, skip over
    2552                 * the variable and continue with the substitution. Otherwise,
    2553                 * store the dollar sign and advance str so we continue with
    2554                 * the string...
    2555                 */
    2556                 if (oldVars) {
    2557                     str += length;
    2558                 } else if (undefErr) {
    2559                     /*
    2560                      * If variable is undefined, complain and skip the
    2561                      * variable. The complaint will stop us from doing anything
    2562                      * when the file is parsed.
    2563                      */
    2564                     if (!errorReported) {
    2565                         Parse_Error (PARSE_FATAL,
    2566                                      "Undefined variable \"%.*s\"",length,str);
    2567                     }
    2568                     str += length;
    2569                     errorReported = TRUE;
    2570                 } else {
    2571                     Buf_AddByte (buf, (Byte)*str);
    2572                     str += 1;
    2573                 }
    2574             } else {
    2575                 /*
    2576                 * We've now got a variable structure to store in. But first,
    2577                 * advance the string pointer.
    2578                 */
    2579                 str += length;
    2580 
    2581                 /*
    2582                 * Copy all the characters from the variable value straight
    2583                 * into the new string.
    2584                 */
    2585                 Buf_AddBytes (buf, strlen (val), (Byte *)val);
    2586                 if (doFree) {
    2587                     efree ((Address)val);
    2588                 }
    2589             }
    2590         }
     2465        if (var == NULL && (*str == '$') && (str[1] == '$')) {
     2466            /*
     2467             * A dollar sign may be escaped either with another dollar sign.
     2468             * In such a case, we skip over the escape character and store the
     2469             * dollar sign into the buffer directly.
     2470             */
     2471            str++;
     2472            Buf_AddByte(buf, (Byte)*str);
     2473            str++;
     2474        } else if (*str != '$') {
     2475            /*
     2476             * Skip as many characters as possible -- either to the end of
     2477             * the string or to the next dollar sign (variable invocation).
     2478             */
     2479            char  *cp;
     2480
     2481            for (cp = str++; *str != '$' && *str != '\0'; str++)
     2482                continue;
     2483            Buf_AddBytes(buf, str - cp, (Byte *)cp);
     2484        } else {
     2485            if (var != NULL) {
     2486                int expand;
     2487                for (;;) {
     2488                    if (str[1] != '(' && str[1] != '{') {
     2489                        if (str[1] != *var) {
     2490                            Buf_AddBytes(buf, 2, (Byte *) str);
     2491                            str += 2;
     2492                            expand = FALSE;
     2493                        }
     2494                        else
     2495                            expand = TRUE;
     2496                        break;
     2497                    }
     2498                    else {
     2499                        char *p;
     2500
     2501                        /*
     2502                        * Scan up to the end of the variable name.
     2503                        */
     2504                        for (p = &str[2]; *p &&
     2505                             *p != ':' && *p != ')' && *p != '}'; p++)
     2506                            if (*p == '$')
     2507                                break;
     2508                        /*
     2509                        * A variable inside the variable. We cannot expand
     2510                        * the external variable yet, so we try again with
     2511                        * the nested one
     2512                        */
     2513                        if (*p == '$') {
     2514                            Buf_AddBytes(buf, p - str, (Byte *) str);
     2515                            str = p;
     2516                            continue;
     2517                        }
     2518
     2519                        if (strncmp(var, str + 2, p - str - 2) != 0 ||
     2520                            var[p - str - 2] != '\0') {
     2521                            /*
     2522                             * Not the variable we want to expand, scan
     2523                             * until the next variable
     2524                             */
     2525                            for (;*p != '$' && *p != '\0'; p++)
     2526                                continue;
     2527                            Buf_AddBytes(buf, p - str, (Byte *) str);
     2528                            str = p;
     2529                            expand = FALSE;
     2530                        }
     2531                        else
     2532                            expand = TRUE;
     2533                        break;
     2534                    }
     2535                }
     2536                if (!expand)
     2537                    continue;
     2538            }
     2539
     2540            val = Var_Parse (str, ctxt, undefErr, &length, &doFree);
     2541
     2542            /*
     2543             * When we come down here, val should either point to the
     2544             * value of this variable, suitably modified, or be NULL.
     2545             * Length should be the total length of the potential
     2546             * variable invocation (from $ to end character...)
     2547             */
     2548            if (val == var_Error || val == varNoError) {
     2549                /*
     2550                * If performing old-time variable substitution, skip over
     2551                * the variable and continue with the substitution. Otherwise,
     2552                * store the dollar sign and advance str so we continue with
     2553                * the string...
     2554                */
     2555                if (oldVars) {
     2556                    str += length;
     2557                } else if (undefErr) {
     2558                    /*
     2559                     * If variable is undefined, complain and skip the
     2560                     * variable. The complaint will stop us from doing anything
     2561                     * when the file is parsed.
     2562                     */
     2563                    if (!errorReported) {
     2564                        Parse_Error (PARSE_FATAL,
     2565                                     "Undefined variable \"%.*s\"",length,str);
     2566                    }
     2567                    str += length;
     2568                    errorReported = TRUE;
     2569                } else {
     2570                    Buf_AddByte (buf, (Byte)*str);
     2571                    str += 1;
     2572                }
     2573            } else {
     2574                /*
     2575                * We've now got a variable structure to store in. But first,
     2576                * advance the string pointer.
     2577                */
     2578                str += length;
     2579
     2580                /*
     2581                * Copy all the characters from the variable value straight
     2582                * into the new string.
     2583                */
     2584                Buf_AddBytes (buf, strlen (val), (Byte *)val);
     2585                if (doFree) {
     2586                    efree ((Address)val);
     2587                }
     2588            }
     2589        }
    25912590    }
    25922591
     
    26002599 *-----------------------------------------------------------------------
    26012600 * Var_GetTail --
    2602  *      Return the tail from each of a list of words. Used to set the
    2603  *      System V local variables.
    2604  *
    2605  * Results:
    2606  *      The resulting string.
    2607  *
    2608  * Side Effects:
    2609  *      None.
     2601 *      Return the tail from each of a list of words. Used to set the
     2602 *      System V local variables.
     2603 *
     2604 * Results:
     2605 *      The resulting string.
     2606 *
     2607 * Side Effects:
     2608 *      None.
    26102609 *
    26112610 *-----------------------------------------------------------------------
     
    26132612char *
    26142613Var_GetTail(file)
    2615     char        *file;      /* Filename to modify */
     2614    char        *file;      /* Filename to modify */
    26162615{
    26172616    return(VarModify(file, VarTail, (ClientData)0));
     
    26212620 *-----------------------------------------------------------------------
    26222621 * Var_GetHead --
    2623  *      Find the leading components of a (list of) filename(s).
    2624  *      XXX: VarHead does not replace foo by ., as (sun) System V make
    2625  *      does.
    2626  *
    2627  * Results:
    2628  *      The leading components.
    2629  *
    2630  * Side Effects:
    2631  *      None.
     2622 *      Find the leading components of a (list of) filename(s).
     2623 *      XXX: VarHead does not replace foo by ., as (sun) System V make
     2624 *      does.
     2625 *
     2626 * Results:
     2627 *      The leading components.
     2628 *
     2629 * Side Effects:
     2630 *      None.
    26322631 *
    26332632 *-----------------------------------------------------------------------
     
    26352634char *
    26362635Var_GetHead(file)
    2637     char        *file;      /* Filename to manipulate */
     2636    char        *file;      /* Filename to manipulate */
    26382637{
    26392638    return(VarModify(file, VarHead, (ClientData)0));
     
    26432642 *-----------------------------------------------------------------------
    26442643 * Var_Init --
    2645  *      Initialize the module
    2646  *
    2647  * Results:
    2648  *      None
    2649  *
    2650  * Side Effects:
    2651  *      The VAR_CMD and VAR_GLOBAL contexts are created
     2644 *      Initialize the module
     2645 *
     2646 * Results:
     2647 *      None
     2648 *
     2649 * Side Effects:
     2650 *      The VAR_CMD and VAR_GLOBAL contexts are created
    26522651 *-----------------------------------------------------------------------
    26532652 */
     
    26832682 *-----------------------------------------------------------------------
    26842683 * Var_Dump --
    2685  *      print all variables in a context
     2684 *      print all variables in a context
    26862685 *-----------------------------------------------------------------------
    26872686 */
  • trunk/src/makefile.os2.icc.mk

    r48 r51  
    3333POSTFIX     = .prf
    3434!endif
    35 OBJDIR      = ..\obj\os2-icc-kmk.$(POSTFIX)
     35OBJDIR      = ..\obj\os2-icc-kmk$(POSTFIX)
    3636
    3737# paths
     
    4040
    4141# compiler setup
     42CC          = icc.exe
    4243!ifdef DEBUG
    4344CFLAGS_1    = /O- -DDEBUG
     
    4647CFLAGS_1    = /O+ /Gh
    4748!endif
    48 CFLAGS      = /Q /Ti+ /Gm /Ge /Gl -DOS2 -D__i386__ -DKMK -I$(PATH_KLIB)\Generic\include -I$(PATH_TOOLKIT)\h -I$(PATH_VAC308)\include $(CFLAGS_1)
    49 CFLAGS_KMK  = /IkMk\include $(CFLAGS)
     49CFLAGS      = /Q /Ti+ /Gm /Ge /Gl /W3 -DOS2 -D__i386__ -DKMK \
     50              -I$(PATH_KLIB)\Generic\include \
     51              -I$(PATH_KLIB)\Generic\include\kLibCRT \
     52              -I$(PATH_TOOLKIT)\h \
     53              -I$(PATH_VAC308)\include \
     54              $(CFLAGS_1)
     55CFLAGS_KMK  = -IkMk\include -IkMk -DUSE_KLIB $(CFLAGS) -UDEBUG  -DMACHINE=\"ibmos2\" -DMACHINE_ARCH=\"x86\" -DMACHINE_CPU=\"386\" \
    5056
    5157# linker setup
     58LD          = ilink.exe
     59STRIP       =
    5260!ifdef DEBUG
    5361LDFLAGS_1   = /NOEXEPACK
     
    5765!endif
    5866!ifndef LDFLAGS_1 #releas
    59 LDFLAGS_1   = /EXEPACK:2 /Packcode /Packdata
     67LDFLAGS_1   = /Packcode /Packdata
     68STRIP       = lxlite.exe
    6069!endif
    6170LDFLAGS     = /NoLogo /NoExtDictionary /Optfunc /Base:0x10000 /Map /Linenumbers /Debug /PmType:vio $(LDFLAGS_1)
     
    7382
    7483{.\kMk\lst.lib}.c{$(OBJDIR)}.obj:
    75     $(CC) -c $(CFLAGS_KMK) -Fo$(OBJDIR)\$(@F) $(MAKEDIR)\kMk\lst.lib$(<F)
     84    $(CC) -c $(CFLAGS_KMK) -Fo$(OBJDIR)\$(@F) $(MAKEDIR)\kMk\lst.lib\$(<F)
    7685
    7786
     
    143152!endif
    144153!endif
    145 $(PATH_TOOLKIT)\os2386.lib \
    146 $(VAC308_TOOLKIT)\cppom30.lib \
    147                    
    148                
    149 # the rules             
     154$(PATH_TOOLKIT)\lib\os2386.lib \
     155$(PATH_VAC308)\lib\cppom30.lib \
     156
     157
     158# the rules
    150159all: $(OBJDIR) $(OBJDIR)\kMk.exe
    151160
    152161
    153162$(OBJDIR):
    154     -mkdir ..\obj
    155     -mkdir $(OBJDIR)
     163    -if not exist ..\obj    mkdir ..\obj
     164    -if not exist $(OBJDIR) mkdir $(OBJDIR)
    156165
    157166$(OBJDIR)\kMk.exe: $(OBJS)
     
    162171$(LIBS)
    163172<<KEEP
     173!if "$(STRIP)" != ""
     174    copy $(OBJDIR)\kMk.exe $(OBJDIR)\kMk.dbg
     175    $(STRIP) $(OBJDIR)\kMk.exe
     176!endif
    164177
     178
     179clean:
     180!if "$(OBJDIR)" != "" && "$(OBJDIR)" != "\"
     181!if "$(COMSPEC:CMD.EXE=sure)" != "$(COMSPEC)"
     182    -del /N $(OBJDIR)\*
     183!else # assume 4os2
     184    -del /Y /E $(OBJDIR)\*
     185!endif
     186!endif
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