[BACK]Return to suff.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / make

Annotation of src/usr.bin/make/suff.c, Revision 1.67

1.41      espie       1: /*     $OpenPackages$ */
1.67    ! espie       2: /*     $OpenBSD: suff.c,v 1.66 2007/09/17 09:16:58 espie Exp $ */
1.5       millert     3: /*     $NetBSD: suff.c,v 1.13 1996/11/06 17:59:25 christos Exp $       */
1.1       deraadt     4:
                      5: /*
1.5       millert     6:  * Copyright (c) 1988, 1989, 1990, 1993
                      7:  *     The Regents of the University of California.  All rights reserved.
1.1       deraadt     8:  * Copyright (c) 1989 by Berkeley Softworks
                      9:  * All rights reserved.
                     10:  *
                     11:  * This code is derived from software contributed to Berkeley by
                     12:  * Adam de Boor.
                     13:  *
                     14:  * Redistribution and use in source and binary forms, with or without
                     15:  * modification, are permitted provided that the following conditions
                     16:  * are met:
                     17:  * 1. Redistributions of source code must retain the above copyright
                     18:  *    notice, this list of conditions and the following disclaimer.
                     19:  * 2. Redistributions in binary form must reproduce the above copyright
                     20:  *    notice, this list of conditions and the following disclaimer in the
                     21:  *    documentation and/or other materials provided with the distribution.
1.50      millert    22:  * 3. Neither the name of the University nor the names of its contributors
1.1       deraadt    23:  *    may be used to endorse or promote products derived from this software
                     24:  *    without specific prior written permission.
                     25:  *
                     26:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     27:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     28:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     29:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     30:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     31:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     32:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     33:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     34:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     35:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     36:  * SUCH DAMAGE.
                     37:  */
                     38:
                     39: /*-
                     40:  * suff.c --
                     41:  *     Functions to maintain suffix lists and find implicit dependents
                     42:  *     using suffix transformation rules
                     43:  *
                     44:  * Interface:
1.41      espie      45:  *     Suff_Init               Initialize all things to do with suffixes.
1.1       deraadt    46:  *
1.41      espie      47:  *     Suff_End                Cleanup the module
1.1       deraadt    48:  *
1.41      espie      49:  *     Suff_DoPaths            This function is used to make life easier
                     50:  *                             when searching for a file according to its
                     51:  *                             suffix. It takes the global search path,
                     52:  *                             as defined using the .PATH: target, and appends
                     53:  *                             its directories to the path of each of the
                     54:  *                             defined suffixes, as specified using
                     55:  *                             .PATH<suffix>: targets. In addition, all
                     56:  *                             directories given for suffixes labeled as
                     57:  *                             include files or libraries, using the .INCLUDES
                     58:  *                             or .LIBS targets, are played with using
                     59:  *                             Dir_MakeFlags to create the .INCLUDES and
                     60:  *                             .LIBS global variables.
1.1       deraadt    61:  *
1.41      espie      62:  *     Suff_ClearSuffixes      Clear out all the suffixes and defined
                     63:  *                             transformations.
1.1       deraadt    64:  *
1.42      espie      65:  *     Suff_IsTransform        Return true if the passed string is the lhs
1.41      espie      66:  *                             of a transformation rule.
1.1       deraadt    67:  *
1.41      espie      68:  *     Suff_AddSuffix          Add the passed string as another known suffix.
1.1       deraadt    69:  *
1.41      espie      70:  *     Suff_GetPath            Return the search path for the given suffix.
1.1       deraadt    71:  *
1.41      espie      72:  *     Suff_AddInclude         Mark the given suffix as denoting an include
                     73:  *                             file.
1.1       deraadt    74:  *
1.41      espie      75:  *     Suff_AddLib             Mark the given suffix as denoting a library.
1.1       deraadt    76:  *
1.41      espie      77:  *     Suff_AddTransform       Add another transformation to the suffix
                     78:  *                             graph. Returns  GNode suitable for framing, I
                     79:  *                             mean, tacking commands, attributes, etc. on.
1.1       deraadt    80:  *
1.41      espie      81:  *     Suff_SetNull            Define the suffix to consider the suffix of
                     82:  *                             any file that doesn't have a known one.
1.1       deraadt    83:  *
1.41      espie      84:  *     Suff_FindDeps           Find implicit sources for and the location of
                     85:  *                             a target based on its suffix. Returns the
                     86:  *                             bottom-most node added to the graph or NULL
                     87:  *                             if the target had no implicit sources.
1.1       deraadt    88:  */
                     89:
1.42      espie      90: #include <ctype.h>
                     91: #include <stdio.h>
1.43      espie      92: #include <stdlib.h>
1.42      espie      93: #include <string.h>
                     94: #include "config.h"
                     95: #include "defines.h"
                     96: #include "dir.h"
1.63      espie      97: #include "direxpand.h"
1.42      espie      98: #include "arch.h"
                     99: #include "suff.h"
                    100: #include "var.h"
                    101: #include "targ.h"
                    102: #include "error.h"
                    103: #include "str.h"
                    104: #include "lst.h"
                    105: #include "memory.h"
                    106: #include "gnode.h"
                    107: #include "make.h"
1.52      espie     108: #include "stats.h"
1.36      espie     109:
1.41      espie     110: static LIST     sufflist;      /* Lst of suffixes */
1.14      espie     111: #ifdef CLEANUP
1.29      espie     112: static LIST     suffClean;     /* Lst of suffixes to be cleaned */
1.14      espie     113: #endif
1.29      espie     114: static LIST     srclist;       /* Lst of sources */
1.41      espie     115: static LIST     transforms;    /* Lst of transformation rules */
1.1       deraadt   116:
1.41      espie     117: static int       sNum = 0;     /* Counter for assigning suffix numbers */
1.1       deraadt   118:
                    119: /*
                    120:  * Structure describing an individual suffix.
                    121:  */
1.40      espie     122: typedef struct Suff_ {
1.41      espie     123:     char        *name;         /* The suffix itself */
                    124:     int         nameLen;       /* Length of the suffix */
                    125:     short       flags;         /* Type of suffix */
1.1       deraadt   126: #define SUFF_INCLUDE     0x01      /* One which is #include'd */
                    127: #define SUFF_LIBRARY     0x02      /* One which contains a library */
1.41      espie     128: #define SUFF_NULL        0x04      /* The empty suffix */
                    129:     LIST        searchPath;    /* The path along which files of this suffix
1.1       deraadt   130:                                 * may be found */
1.41      espie     131:     int         sNum;          /* The suffix number */
                    132:     LIST        parents;       /* Suffixes we have a transformation to */
                    133:     LIST        children;      /* Suffixes we have a transformation from */
1.29      espie     134:     LIST        ref;           /* List of lists this suffix is referenced */
1.1       deraadt   135: } Suff;
                    136:
                    137: /*
                    138:  * Structure used in the search for implied sources.
                    139:  */
1.40      espie     140: typedef struct Src_ {
1.41      espie     141:     char           *file;      /* The file to look for */
                    142:     char           *pref;      /* Prefix from which file was formed */
                    143:     Suff           *suff;      /* The suffix on the file */
1.40      espie     144:     struct Src_     *parent;   /* The Src for which this is a source */
1.41      espie     145:     GNode          *node;      /* The node describing the file */
                    146:     int            children;   /* Count of existing children (so we don't free
1.1       deraadt   147:                                 * this thing too early or never nuke it) */
                    148: #ifdef DEBUG_SRC
1.41      espie     149:     LIST           cp;         /* Debug; children list */
1.1       deraadt   150: #endif
                    151: } Src;
                    152:
                    153: /*
                    154:  * A structure for passing more than one argument to the Lst-library-invoked
                    155:  * function...
                    156:  */
                    157: typedef struct {
1.41      espie     158:     Lst           l;
                    159:     Src           *s;
1.1       deraadt   160: } LstSrc;
                    161:
1.41      espie     162: static Suff        *suffNull;  /* The NULL suffix for this run */
1.56      espie     163: static Suff        *emptySuff; /* The empty suffix required for POSIX
                    164:                                 * single-suffix transformation rules */
1.1       deraadt   165:
                    166:
1.41      espie     167: static char *SuffStrIsPrefix(const char *, const char *);
                    168: static char *SuffSuffIsSuffix(Suff *, const char *);
                    169: static int SuffSuffIsSuffixP(void *, const void *);
                    170: static int SuffSuffIsPrefix(void *, const void *);
1.52      espie     171: static int SuffHasNameP(void *, const void *);
                    172: static int GNodeHasNameP(void *, const void *);
1.41      espie     173: static void SuffUnRef(Lst, Suff *);
                    174: #ifdef CLEANUP
                    175: static void SuffFree(void *);
                    176: #endif
                    177: static void SuffInsert(Lst, Suff *);
1.42      espie     178: static bool SuffParseTransform(const char *, Suff **, Suff **);
1.41      espie     179: static void SuffRebuildGraph(void *, void *);
                    180: static void SuffAddSrc(void *, void *);
                    181: static int SuffRemoveSrc(Lst);
                    182: static void SuffAddLevel(Lst, Src *);
                    183: static Src *SuffFindThem(Lst, Lst);
                    184: static Src *SuffFindCmds(Src *, Lst);
                    185: static void SuffExpandChildren(void *, void *);
                    186: static void SuffExpandVarChildren(LstNode, GNode *, GNode *);
                    187: static void SuffExpandWildChildren(LstNode, GNode *, GNode *);
1.42      espie     188: static bool SuffApplyTransform(GNode *, GNode *, Suff *, Suff *);
1.41      espie     189: static void SuffFindDeps(GNode *, Lst);
                    190: static void SuffFindArchiveDeps(GNode *, Lst);
                    191: static void SuffFindNormalDeps(GNode *, Lst);
                    192: static void SuffPrintName(void *);
                    193: static void SuffPrintSuff(void *);
                    194: static void SuffPrintTrans(void *);
1.1       deraadt   195:
1.52      espie     196: static LstNode suff_find_by_name(const char *);
                    197: static LstNode transform_find_by_name(const char *);
                    198:
1.42      espie     199: #ifdef DEBUG_SRC
                    200: static void PrintAddr(void *);
                    201: #endif
1.1       deraadt   202:        /*************** Lst Predicates ****************/
                    203: /*-
                    204:  *-----------------------------------------------------------------------
                    205:  * SuffStrIsPrefix  --
1.51      espie     206:  *     See if prefix is a prefix of str.
1.1       deraadt   207:  *
                    208:  * Results:
                    209:  *     NULL if it ain't, pointer to character in str after prefix if so
                    210:  *-----------------------------------------------------------------------
                    211:  */
                    212: static char    *
1.51      espie     213: SuffStrIsPrefix(const char *prefix, const char *str)
1.1       deraadt   214: {
1.66      espie     215:        while (*str && *prefix == *str) {
                    216:                prefix++;
                    217:                str++;
                    218:        }
1.1       deraadt   219:
1.66      espie     220:        return *prefix ? NULL : (char *)str;
1.1       deraadt   221: }
                    222:
                    223: /*-
                    224:  *-----------------------------------------------------------------------
                    225:  * SuffSuffIsSuffix  --
1.41      espie     226:  *     See if suff is a suffix of str. str should point to the end of the
                    227:  *     string to check.
1.1       deraadt   228:  *
                    229:  * Results:
1.41      espie     230:  *     NULL if it ain't, pointer to first character of suffix in str if
1.1       deraadt   231:  *     it is.
                    232:  *-----------------------------------------------------------------------
                    233:  */
                    234: static char *
1.51      espie     235: SuffSuffIsSuffix(Suff *s, const char *str)
1.1       deraadt   236: {
1.66      espie     237:        const char         *p1;         /* Pointer into suffix name */
                    238:        const char         *p2;         /* Pointer into string being examined */
1.1       deraadt   239:
1.66      espie     240:        p1 = s->name + s->nameLen;
                    241:        p2 = str;
1.1       deraadt   242:
1.66      espie     243:        while (p1 != s->name) {
                    244:                p1--;
                    245:                p2--;
                    246:                if (*p1 != *p2)
                    247:                        return NULL;
                    248:        }
1.1       deraadt   249:
1.66      espie     250:        return (char *)p2;
1.1       deraadt   251: }
                    252:
                    253: /*-
                    254:  *-----------------------------------------------------------------------
                    255:  * SuffSuffIsSuffixP --
                    256:  *     Predicate form of SuffSuffIsSuffix. Passed as the callback function
                    257:  *     to Lst_Find.
                    258:  *
                    259:  * Results:
                    260:  *     0 if the suffix is the one desired, non-zero if not.
                    261:  *-----------------------------------------------------------------------
                    262:  */
                    263: static int
1.51      espie     264: SuffSuffIsSuffixP(void *s, const void *str)
1.1       deraadt   265: {
1.66      espie     266:        return !SuffSuffIsSuffix((Suff *)s, (const char *)str);
1.1       deraadt   267: }
                    268:
                    269: static int
1.52      espie     270: SuffHasNameP(void *s, const void *sname)
1.1       deraadt   271: {
1.66      espie     272:        return strcmp((const char *)sname, ((Suff *)s)->name);
1.1       deraadt   273: }
                    274:
1.52      espie     275: static LstNode
                    276: suff_find_by_name(const char *name)
                    277: {
                    278: #ifdef STATS_SUFF
1.66      espie     279:        STAT_SUFF_LOOKUP_NAME++;
1.52      espie     280: #endif
1.66      espie     281:        return Lst_FindConst(&sufflist, SuffHasNameP, name);
1.52      espie     282: }
                    283:
                    284: static int
                    285: GNodeHasNameP(void *gn, const void *name)
                    286: {
1.66      espie     287:        return strcmp((const char *)name, ((GNode *)gn)->name);
1.52      espie     288: }
                    289:
                    290: static LstNode
                    291: transform_find_by_name(const char *name)
                    292: {
                    293: #ifdef STATS_SUFF
1.66      espie     294:        STAT_TRANSFORM_LOOKUP_NAME++;
1.52      espie     295: #endif
1.66      espie     296:        return Lst_FindConst(&transforms, GNodeHasNameP, name);
1.52      espie     297: }
1.1       deraadt   298: /*-
                    299:  *-----------------------------------------------------------------------
                    300:  * SuffSuffIsPrefix  --
                    301:  *     See if the suffix described by s is a prefix of the string. Care
                    302:  *     must be taken when using this to search for transformations and
                    303:  *     what-not, since there could well be two suffixes, one of which
                    304:  *     is a prefix of the other...
                    305:  *
                    306:  * Results:
                    307:  *     0 if s is a prefix of str. non-zero otherwise
                    308:  *-----------------------------------------------------------------------
                    309:  */
                    310: static int
1.51      espie     311: SuffSuffIsPrefix(void *s, const void *str)
1.1       deraadt   312: {
1.67    ! espie     313:        return SuffStrIsPrefix(((Suff *)s)->name,
1.66      espie     314:            (const char *)str) == NULL ? 1 : 0;
1.1       deraadt   315: }
                    316:
1.41      espie     317:            /*********** Maintenance Functions ************/
1.1       deraadt   318:
                    319: static void
1.51      espie     320: SuffUnRef(Lst l, Suff *sp)
1.1       deraadt   321: {
1.66      espie     322:        LstNode ln = Lst_Member(l, sp);
                    323:        if (ln != NULL)
                    324:                Lst_Remove(l, ln);
                    325:     }
1.1       deraadt   326:
1.41      espie     327: #ifdef CLEANUP
1.1       deraadt   328: /*-
                    329:  *-----------------------------------------------------------------------
1.41      espie     330:  * SuffFree  --
                    331:  *     Free up all memory associated with the given suffix structure.
                    332:  *
                    333:  * Side Effects:
                    334:  *     the suffix entry is detroyed
1.1       deraadt   335:  *-----------------------------------------------------------------------
                    336:  */
1.24      espie     337: static void
1.51      espie     338: SuffFree(void *sp)
1.1       deraadt   339: {
1.66      espie     340:        Suff    *s = (Suff *)sp;
1.41      espie     341:
1.66      espie     342:        if (s == suffNull)
                    343:                suffNull = NULL;
1.41      espie     344:
1.66      espie     345:        if (s == emptySuff)
                    346:                emptySuff = NULL;
1.56      espie     347:
1.66      espie     348:        Lst_Destroy(&s->ref, NOFREE);
                    349:        Lst_Destroy(&s->children, NOFREE);
                    350:        Lst_Destroy(&s->parents, NOFREE);
                    351:        Lst_Destroy(&s->searchPath, Dir_Destroy);
1.41      espie     352:
1.66      espie     353:        free(s->name);
                    354:        free(s);
1.1       deraadt   355: }
1.41      espie     356: #endif
                    357:
                    358:
1.1       deraadt   359: /*-
                    360:  *-----------------------------------------------------------------------
                    361:  * SuffInsert  --
                    362:  *     Insert the suffix into the list keeping the list ordered by suffix
                    363:  *     numbers.
                    364:  *
                    365:  * Side Effects:
                    366:  *     The reference count of the suffix is incremented
                    367:  *-----------------------------------------------------------------------
                    368:  */
                    369: static void
1.51      espie     370: SuffInsert(Lst l, Suff *s)
1.1       deraadt   371: {
1.66      espie     372:        LstNode   ln;           /* current element in l we're examining */
                    373:        Suff      *s2 = NULL;   /* the suffix descriptor in this element */
1.1       deraadt   374:
1.66      espie     375:        for (ln = Lst_First(l); ln != NULL; ln = Lst_Adv(ln)) {
                    376:                s2 = (Suff *)Lst_Datum(ln);
                    377:                if (s2->sNum >= s->sNum)
                    378:                        break;
                    379:        }
1.1       deraadt   380:
                    381:        if (DEBUG(SUFF)) {
1.66      espie     382:                printf("inserting %s(%d)...", s->name, s->sNum);
1.1       deraadt   383:        }
1.66      espie     384:        if (ln == NULL) {
                    385:                if (DEBUG(SUFF)) {
                    386:                        printf("at end of list\n");
                    387:                }
                    388:                Lst_AtEnd(l, s);
                    389:                Lst_AtEnd(&s->ref, l);
                    390:        } else if (s2->sNum != s->sNum) {
                    391:                if (DEBUG(SUFF)) {
                    392:                        printf("before %s(%d)\n", s2->name, s2->sNum);
                    393:                }
                    394:                Lst_Insert(l, ln, s);
                    395:                Lst_AtEnd(&s->ref, l);
                    396:        } else if (DEBUG(SUFF)) {
                    397:                printf("already there\n");
1.1       deraadt   398:        }
                    399: }
                    400:
                    401: /*-
                    402:  *-----------------------------------------------------------------------
                    403:  * Suff_ClearSuffixes --
                    404:  *     This is gross. Nuke the list of suffixes but keep all transformation
                    405:  *     rules around. The transformation graph is destroyed in this process,
                    406:  *     but we leave the list of rules so when a new graph is formed the rules
                    407:  *     will remain.
                    408:  *     This function is called from the parse module when a
                    409:  *     .SUFFIXES:\n line is encountered.
                    410:  *
                    411:  * Side Effects:
                    412:  *     the sufflist and its graph nodes are destroyed
                    413:  *-----------------------------------------------------------------------
                    414:  */
                    415: void
1.51      espie     416: Suff_ClearSuffixes(void)
1.1       deraadt   417: {
1.14      espie     418: #ifdef CLEANUP
1.66      espie     419:        Lst_ConcatDestroy(&suffClean, &sufflist);
1.14      espie     420: #endif
1.66      espie     421:        Lst_Init(&sufflist);
                    422:        sNum = 0;
                    423:        suffNull = emptySuff;
1.1       deraadt   424: }
                    425:
                    426: /*-
                    427:  *-----------------------------------------------------------------------
                    428:  * SuffParseTransform --
                    429:  *     Parse a transformation string to find its two component suffixes.
                    430:  *
                    431:  * Results:
1.42      espie     432:  *     true if the string is a valid transformation and false otherwise.
1.1       deraadt   433:  *
                    434:  * Side Effects:
                    435:  *     The passed pointers are overwritten.
                    436:  *-----------------------------------------------------------------------
                    437:  */
1.42      espie     438: static bool
1.51      espie     439: SuffParseTransform(
                    440:     const char         *str,           /* String being parsed */
                    441:     Suff               **srcPtr,       /* Place to store source of trans. */
                    442:     Suff               **targPtr)      /* Place to store target of trans. */
1.41      espie     443: {
1.66      espie     444:        LstNode         srcLn;      /* element in suffix list of trans source*/
                    445:        Suff            *src;       /* Source of transformation */
                    446:        LstNode         targLn;     /* element in suffix list of trans target*/
                    447:        const char              *str2;      /* Extra pointer (maybe target suffix) */
                    448:        LstNode         singleLn;   /* element in suffix list of any suffix
                    449:                                         * that exactly matches str */
                    450:        Suff            *single = NULL;/* Source of possible transformation to
                    451:                                         * null suffix */
                    452:
                    453:        srcLn = NULL;
                    454:        singleLn = NULL;
                    455:
                    456:        /*
                    457:         * Loop looking first for a suffix that matches the start of the
                    458:         * string and then for one that exactly matches the rest of it. If
                    459:         * we can find two that meet these criteria, we've successfully
                    460:         * parsed the string.
                    461:         */
                    462:        for (;;) {
                    463:                if (srcLn == NULL)
                    464:                        srcLn = Lst_FindConst(&sufflist, SuffSuffIsPrefix, str);
                    465:                else
1.67    ! espie     466:                        srcLn = Lst_FindFromConst(Lst_Succ(srcLn),
1.66      espie     467:                            SuffSuffIsPrefix, str);
                    468:                if (srcLn == NULL) {
                    469:                        /*
                    470:                         * Ran out of source suffixes -- no such rule
                    471:                         */
                    472:                        if (singleLn != NULL) {
                    473:                                /*
                    474:                                 * Not so fast Mr. Smith! There was a suffix
                    475:                                 * that encompassed the entire string, so we
                    476:                                 * assume it was a transformation to the null
                    477:                                 * suffix (thank you POSIX). We still prefer to
                    478:                                 * find a double rule over a singleton, hence
                    479:                                 * we leave this check until the end.
                    480:                                 *
                    481:                                 * XXX: Use emptySuff over suffNull?
                    482:                                 */
                    483:                                *srcPtr = single;
                    484:                                *targPtr = suffNull;
                    485:                                return true;
                    486:                        }
                    487:                        return false;
                    488:                }
                    489:                src = (Suff *)Lst_Datum(srcLn);
                    490:                str2 = str + src->nameLen;
                    491:                if (*str2 == '\0') {
                    492:                        single = src;
                    493:                        singleLn = srcLn;
                    494:                } else {
                    495:                        targLn = suff_find_by_name(str2);
                    496:                        if (targLn != NULL) {
                    497:                                *srcPtr = src;
                    498:                                *targPtr = (Suff *)Lst_Datum(targLn);
                    499:                                return true;
                    500:                        }
                    501:                }
1.1       deraadt   502:        }
                    503: }
                    504:
                    505: /*-
                    506:  *-----------------------------------------------------------------------
                    507:  * Suff_IsTransform  --
1.42      espie     508:  *     Return true if the given string is a transformation rule
1.1       deraadt   509:  *
                    510:  * Results:
1.42      espie     511:  *     true if the string is a concatenation of two known suffixes.
                    512:  *     false otherwise
1.1       deraadt   513:  *-----------------------------------------------------------------------
                    514:  */
1.42      espie     515: bool
1.51      espie     516: Suff_IsTransform(const char *str)
1.1       deraadt   517: {
1.66      espie     518:        Suff      *src, *targ;
1.1       deraadt   519:
1.66      espie     520:        return SuffParseTransform(str, &src, &targ);
1.1       deraadt   521: }
                    522:
                    523: /*-
                    524:  *-----------------------------------------------------------------------
                    525:  * Suff_AddTransform --
                    526:  *     Add the transformation rule described by the line to the
                    527:  *     list of rules and place the transformation itself in the graph
                    528:  *
                    529:  * Results:
                    530:  *     The node created for the transformation in the transforms list
                    531:  *
                    532:  * Side Effects:
                    533:  *     The node is placed on the end of the transforms Lst and links are
                    534:  *     made between the two suffixes mentioned in the target name
                    535:  *-----------------------------------------------------------------------
                    536:  */
                    537: GNode *
1.51      espie     538: Suff_AddTransform(const char *line)
1.1       deraadt   539: {
1.66      espie     540:        GNode     *gn;          /* GNode of transformation rule */
                    541:        Suff      *s,           /* source suffix */
                    542:                      *t;               /* target suffix */
                    543:        LstNode   ln;           /* Node for existing transformation */
1.1       deraadt   544:
1.66      espie     545:        ln = transform_find_by_name(line);
                    546:        if (ln == NULL) {
                    547:                /*
                    548:                 * Make a new graph node for the transformation. It will be
                    549:                 * filled in by the Parse module.
                    550:                 */
                    551:                gn = Targ_NewGN(line);
                    552:                Lst_AtEnd(&transforms, gn);
                    553:        } else {
                    554:                /*
                    555:                 * New specification for transformation rule. Just nuke the old
                    556:                 * list of commands so they can be filled in again... We don't
                    557:                 * actually free the commands themselves, because a given
                    558:                 * command can be attached to several different
                    559:                 * transformations.
                    560:                 */
                    561:                gn = (GNode *)Lst_Datum(ln);
                    562:                Lst_Destroy(&gn->commands, NOFREE);
                    563:                Lst_Init(&gn->commands);
                    564:                Lst_Destroy(&gn->children, NOFREE);
                    565:                Lst_Init(&gn->children);
                    566:        }
1.1       deraadt   567:
1.66      espie     568:        gn->type = OP_TRANSFORM;
1.1       deraadt   569:
1.66      espie     570:        (void)SuffParseTransform(line, &s, &t);
1.1       deraadt   571:
1.66      espie     572:        /*
                    573:         * link the two together in the proper relationship and order
                    574:         */
                    575:        if (DEBUG(SUFF)) {
                    576:                printf("defining transformation from `%s' to `%s'\n",
                    577:                    s->name, t->name);
                    578:        }
                    579:        SuffInsert(&t->children, s);
                    580:        SuffInsert(&s->parents, t);
1.1       deraadt   581:
1.66      espie     582:        return gn;
1.1       deraadt   583: }
                    584:
                    585: /*-
                    586:  *-----------------------------------------------------------------------
                    587:  * Suff_EndTransform --
                    588:  *     Handle the finish of a transformation definition, removing the
                    589:  *     transformation from the graph if it has neither commands nor
                    590:  *     sources. This is a callback procedure for the Parse module via
                    591:  *     Lst_ForEach
                    592:  *
                    593:  * Side Effects:
                    594:  *     If the node has no commands or children, the children and parents
                    595:  *     lists of the affected suffices are altered.
                    596:  *-----------------------------------------------------------------------
                    597:  */
1.27      espie     598: void
1.51      espie     599: Suff_EndTransform(void *gnp)
1.1       deraadt   600: {
1.66      espie     601:        GNode *gn = (GNode *)gnp;
1.5       millert   602:
1.66      espie     603:        if ((gn->type & OP_TRANSFORM) && Lst_IsEmpty(&gn->commands) &&
                    604:            Lst_IsEmpty(&gn->children)) {
                    605:                Suff    *s, *t;
                    606:
                    607:                if (!SuffParseTransform(gn->name, &s, &t))
                    608:                        return;
                    609:
                    610:                if (DEBUG(SUFF)) {
                    611:                        printf("deleting transformation from `%s' to `%s'\n",
                    612:                            s->name, t->name);
                    613:                }
1.1       deraadt   614:
1.66      espie     615:                /*
                    616:                 * Remove the source from the target's children list.
                    617:                 *
                    618:                 * We'll be called twice when the next target is seen, but .c
                    619:                 * and .o are only linked once...
                    620:                 */
                    621:                SuffUnRef(&t->children, s);
1.1       deraadt   622:
1.66      espie     623:                /*
                    624:                 * Remove the target from the source's parents list
                    625:                 */
                    626:                if (s != NULL)
                    627:                        SuffUnRef(&s->parents, t);
                    628:        } else if ((gn->type & OP_TRANSFORM) && DEBUG(SUFF)) {
                    629:                printf("transformation %s complete\n", gn->name);
1.1       deraadt   630:        }
                    631: }
                    632:
                    633: /*-
                    634:  *-----------------------------------------------------------------------
                    635:  * SuffRebuildGraph --
                    636:  *     Called from Suff_AddSuffix via Lst_ForEach to search through the
                    637:  *     list of existing transformation rules and rebuild the transformation
                    638:  *     graph when it has been destroyed by Suff_ClearSuffixes. If the
                    639:  *     given rule is a transformation involving this suffix and another,
                    640:  *     existing suffix, the proper relationship is established between
                    641:  *     the two.
                    642:  *
                    643:  * Side Effects:
                    644:  *     The appropriate links will be made between this suffix and
                    645:  *     others if transformation rules exist for it.
                    646:  *-----------------------------------------------------------------------
                    647:  */
1.27      espie     648: static void
1.51      espie     649: SuffRebuildGraph(
                    650:     void       *transformp,    /* Transformation to test */
                    651:     void       *sp)            /* Suffix to rebuild */
1.1       deraadt   652: {
1.66      espie     653:        GNode   *transform = (GNode *)transformp;
                    654:        Suff    *s = (Suff *)sp;
                    655:        char    *cp;
                    656:        LstNode ln;
                    657:        Suff    *s2;
                    658:
                    659:        /* First see if it is a transformation from this suffix.  */
                    660:        cp = SuffStrIsPrefix(s->name, transform->name);
                    661:        if (cp != NULL) {
                    662:                ln = suff_find_by_name(cp);
                    663:                if (ln != NULL) {
                    664:                        /* Found target. Link in and return, since it can't be
                    665:                         * anything else.  */
                    666:                        s2 = (Suff *)Lst_Datum(ln);
                    667:                        SuffInsert(&s2->children, s);
                    668:                        SuffInsert(&s->parents, s2);
                    669:                        return;
                    670:                }
1.1       deraadt   671:        }
                    672:
1.66      espie     673:        /* Not from, maybe to?  */
                    674:        cp = SuffSuffIsSuffix(s, transform->name + strlen(transform->name));
                    675:        if (cp != NULL) {
                    676:                /* Null-terminate the source suffix in order to find it.  */
                    677:                *cp = '\0';
                    678:                ln = suff_find_by_name(transform->name);
                    679:                /* Replace the start of the target suffix.  */
                    680:                *cp = s->name[0];
                    681:                if (ln != NULL) {
                    682:                        /* Found it -- establish the proper relationship.  */
                    683:                        s2 = (Suff *)Lst_Datum(ln);
                    684:                        SuffInsert(&s->children, s2);
                    685:                        SuffInsert(&s2->parents, s);
                    686:                }
1.1       deraadt   687:        }
                    688: }
                    689:
                    690: /*-
                    691:  *-----------------------------------------------------------------------
                    692:  * Suff_AddSuffix --
                    693:  *     Add the suffix in string to the end of the list of known suffixes.
                    694:  *     Should we restructure the suffix graph? Make doesn't...
                    695:  *
                    696:  * Side Effects:
                    697:  *     A GNode is created for the suffix and a Suff structure is created and
                    698:  *     added to the suffixes list unless the suffix was already known.
                    699:  *-----------------------------------------------------------------------
                    700:  */
                    701: void
1.52      espie     702: Suff_AddSuffix(const char *str)
1.1       deraadt   703: {
1.66      espie     704:        Suff      *s;       /* new suffix descriptor */
                    705:        LstNode   ln;
1.1       deraadt   706:
1.66      espie     707:        ln = suff_find_by_name(str);
                    708:        if (ln == NULL) {
                    709:                s = emalloc(sizeof(Suff));
                    710:
                    711:                s->name =       estrdup(str);
                    712:                s->nameLen =    strlen(s->name);
                    713:                Lst_Init(&s->searchPath);
                    714:                Lst_Init(&s->children);
                    715:                Lst_Init(&s->parents);
                    716:                Lst_Init(&s->ref);
                    717:                s->sNum =       sNum++;
                    718:                s->flags =      0;
1.1       deraadt   719:
1.66      espie     720:                Lst_AtEnd(&sufflist, s);
                    721:                /*
                    722:                 * Look for any existing transformations from or to this suffix.
                    723:                 * XXX: Only do this after a Suff_ClearSuffixes?
                    724:                 */
                    725:                Lst_ForEach(&transforms, SuffRebuildGraph, s);
                    726:        }
1.1       deraadt   727: }
                    728:
                    729: /*-
                    730:  *-----------------------------------------------------------------------
                    731:  * Suff_GetPath --
                    732:  *     Return the search path for the given suffix, if it's defined.
                    733:  *
                    734:  * Results:
1.18      espie     735:  *     The searchPath for the desired suffix or NULL if the suffix isn't
1.1       deraadt   736:  *     defined.
                    737:  *-----------------------------------------------------------------------
                    738:  */
                    739: Lst
1.52      espie     740: Suff_GetPath(const char *sname)
1.1       deraadt   741: {
1.66      espie     742:        LstNode   ln;
                    743:        Suff      *s;
1.1       deraadt   744:
1.66      espie     745:        ln = suff_find_by_name(sname);
                    746:        if (ln == NULL) {
                    747:                return NULL;
                    748:        } else {
                    749:                s = (Suff *)Lst_Datum(ln);
                    750:                return &s->searchPath;
                    751:        }
1.1       deraadt   752: }
                    753:
                    754: /*-
                    755:  *-----------------------------------------------------------------------
                    756:  * Suff_DoPaths --
                    757:  *     Extend the search paths for all suffixes to include the default
                    758:  *     search path.
                    759:  *
                    760:  * Side Effects:
                    761:  *     The searchPath field of all the suffixes is extended by the
1.64      espie     762:  *     directories in defaultPath. If paths were specified for the
1.1       deraadt   763:  *     ".h" suffix, the directories are stuffed into a global variable
1.54      jsg       764:  *     called ".INCLUDES" with each directory preceded by a -I. The same
1.1       deraadt   765:  *     is done for the ".a" suffix, except the variable is called
                    766:  *     ".LIBS" and the flag is -L.
                    767:  *-----------------------------------------------------------------------
                    768:  */
                    769: void
1.51      espie     770: Suff_DoPaths(void)
1.1       deraadt   771: {
1.66      espie     772:        Suff            *s;
                    773:        LstNode         ln;
                    774:        char            *ptr;
                    775:        LIST            inIncludes; /* Cumulative .INCLUDES path */
                    776:        LIST            inLibs;     /* Cumulative .LIBS path */
                    777:
                    778:        Lst_Init(&inIncludes);
                    779:        Lst_Init(&inLibs);
                    780:
                    781:        for (ln = Lst_First(&sufflist); ln != NULL; ln = Lst_Adv(ln)) {
                    782:                s = (Suff *)Lst_Datum(ln);
                    783:                if (!Lst_IsEmpty(&s->searchPath)) {
                    784:                        if (s->flags & SUFF_INCLUDE) {
                    785:                                Dir_Concat(&inIncludes, &s->searchPath);
                    786:                        }
                    787:                        if (s->flags & SUFF_LIBRARY) {
                    788:                                Dir_Concat(&inLibs, &s->searchPath);
                    789:                        }
                    790:                        Dir_Concat(&s->searchPath, defaultPath);
                    791:                } else
                    792:                        Lst_Clone(&s->searchPath, defaultPath, Dir_CopyDir);
                    793:        }
                    794:
                    795:        Var_Set(".INCLUDES", ptr = Dir_MakeFlags("-I", &inIncludes));
                    796:        free(ptr);
                    797:        Var_Set(".LIBS", ptr = Dir_MakeFlags("-L", &inLibs));
                    798:        free(ptr);
1.1       deraadt   799:
1.66      espie     800:        Lst_Destroy(&inIncludes, Dir_Destroy);
                    801:        Lst_Destroy(&inLibs, Dir_Destroy);
1.1       deraadt   802: }
                    803:
                    804: /*-
                    805:  *-----------------------------------------------------------------------
                    806:  * Suff_AddInclude --
                    807:  *     Add the given suffix as a type of file which gets included.
                    808:  *     Called from the parse module when a .INCLUDES line is parsed.
                    809:  *     The suffix must have already been defined.
                    810:  *
                    811:  * Side Effects:
                    812:  *     The SUFF_INCLUDE bit is set in the suffix's flags field
                    813:  *-----------------------------------------------------------------------
                    814:  */
                    815: void
1.52      espie     816: Suff_AddInclude(const char *sname)     /* Name of suffix to mark */
1.1       deraadt   817: {
1.66      espie     818:        LstNode   ln;
                    819:        Suff      *s;
1.1       deraadt   820:
1.66      espie     821:        ln = suff_find_by_name(sname);
                    822:        if (ln != NULL) {
                    823:                s = (Suff *)Lst_Datum(ln);
                    824:                s->flags |= SUFF_INCLUDE;
                    825:        }
1.1       deraadt   826: }
                    827:
                    828: /*-
                    829:  *-----------------------------------------------------------------------
                    830:  * Suff_AddLib --
                    831:  *     Add the given suffix as a type of file which is a library.
                    832:  *     Called from the parse module when parsing a .LIBS line. The
                    833:  *     suffix must have been defined via .SUFFIXES before this is
                    834:  *     called.
                    835:  *
                    836:  * Side Effects:
                    837:  *     The SUFF_LIBRARY bit is set in the suffix's flags field
                    838:  *-----------------------------------------------------------------------
                    839:  */
                    840: void
1.52      espie     841: Suff_AddLib(const char *sname) /* Name of suffix to mark */
1.1       deraadt   842: {
1.66      espie     843:        LstNode   ln;
                    844:        Suff      *s;
1.1       deraadt   845:
1.66      espie     846:        ln = suff_find_by_name(sname);
                    847:        if (ln != NULL) {
                    848:                s = (Suff *)Lst_Datum(ln);
                    849:                s->flags |= SUFF_LIBRARY;
                    850:        }
1.1       deraadt   851: }
                    852:
1.41      espie     853:          /********** Implicit Source Search Functions *********/
1.1       deraadt   854:
                    855: /*-
                    856:  *-----------------------------------------------------------------------
                    857:  * SuffAddSrc  --
                    858:  *     Add a suffix as a Src structure to the given list with its parent
                    859:  *     being the given Src structure. If the suffix is the null suffix,
                    860:  *     the prefix is used unaltered as the file name in the Src structure.
                    861:  *
                    862:  * Side Effects:
                    863:  *     A Src structure is created and tacked onto the end of the list
                    864:  *-----------------------------------------------------------------------
                    865:  */
1.27      espie     866: static void
1.51      espie     867: SuffAddSrc(
                    868:     void *sp,      /* suffix for which to create a Src structure */
                    869:     void *lsp)     /* list and parent for the new Src */
1.1       deraadt   870: {
1.66      espie     871:        Suff    *s = (Suff *)sp;
                    872:        LstSrc  *ls = (LstSrc *)lsp;
                    873:        Src     *s2;        /* new Src structure */
                    874:        Src     *targ;      /* Target structure */
1.1       deraadt   875:
1.66      espie     876:        targ = ls->s;
1.5       millert   877:
1.66      espie     878:        if ((s->flags & SUFF_NULL) && *s->name != '\0') {
                    879:                /*
                    880:                 * If the suffix has been marked as the NULL suffix, also
                    881:                 * create a Src structure for a file with no suffix attached.
                    882:                 * Two birds, and all that...
                    883:                 */
                    884:                s2 = emalloc(sizeof(Src));
                    885:                s2->file =      estrdup(targ->pref);
                    886:                s2->pref =      targ->pref;
                    887:                s2->parent =    targ;
                    888:                s2->node =      NULL;
                    889:                s2->suff =      s;
                    890:                s2->children =  0;
                    891:                targ->children++;
                    892:                Lst_AtEnd(ls->l, s2);
                    893: #ifdef DEBUG_SRC
                    894:                Lst_Init(&s2->cp);
                    895:                Lst_AtEnd(&targ->cp, s2);
                    896:                printf("1 add %x %x to %x:", targ, s2, ls->l);
                    897:                Lst_Every(ls->l, PrintAddr);
                    898:                printf("\n");
                    899: #endif
                    900:        }
1.41      espie     901:        s2 = emalloc(sizeof(Src));
1.66      espie     902:        s2->file =          Str_concat(targ->pref, s->name, 0);
                    903:        s2->pref =          targ->pref;
                    904:        s2->parent =    targ;
                    905:        s2->node =          NULL;
                    906:        s2->suff =          s;
                    907:        s2->children =  0;
1.65      espie     908:        targ->children++;
1.25      espie     909:        Lst_AtEnd(ls->l, s2);
1.1       deraadt   910: #ifdef DEBUG_SRC
1.66      espie     911:     Lst_Init(&s2->cp);
1.29      espie     912:        Lst_AtEnd(&targ->cp, s2);
1.66      espie     913:        printf("2 add %x %x to %x:", targ, s2, ls->l);
1.27      espie     914:        Lst_Every(ls->l, PrintAddr);
1.1       deraadt   915:        printf("\n");
                    916: #endif
1.41      espie     917:
1.1       deraadt   918: }
                    919:
                    920: /*-
                    921:  *-----------------------------------------------------------------------
                    922:  * SuffAddLevel  --
                    923:  *     Add all the children of targ as Src structures to the given list
                    924:  *
                    925:  * Side Effects:
1.41      espie     926:  *     Lots of structures are created and added to the list
1.1       deraadt   927:  *-----------------------------------------------------------------------
                    928:  */
                    929: static void
1.51      espie     930: SuffAddLevel(
                    931:     Lst           l,           /* list to which to add the new level */
                    932:     Src           *targ)       /* Src structure to use as the parent */
1.1       deraadt   933: {
1.66      espie     934:        LstSrc     ls;
1.1       deraadt   935:
1.66      espie     936:        ls.s = targ;
                    937:        ls.l = l;
1.1       deraadt   938:
1.66      espie     939:        Lst_ForEach(&targ->suff->children, SuffAddSrc, &ls);
1.1       deraadt   940: }
                    941:
                    942: /*-
                    943:  *----------------------------------------------------------------------
                    944:  * SuffRemoveSrc --
                    945:  *     Free all src structures in list that don't have a reference count
                    946:  *
                    947:  * Results:
1.41      espie     948:  *     Ture if an src was removed
1.1       deraadt   949:  *
                    950:  * Side Effects:
                    951:  *     The memory is free'd.
                    952:  *----------------------------------------------------------------------
                    953:  */
                    954: static int
1.51      espie     955: SuffRemoveSrc(Lst l)
1.1       deraadt   956: {
1.66      espie     957:        LstNode ln;
                    958:        Src *s;
                    959:        int t = 0;
1.1       deraadt   960:
                    961: #ifdef DEBUG_SRC
1.66      espie     962:        printf("cleaning %lx: ", (unsigned long)l);
                    963:        Lst_Every(l, PrintAddr);
                    964:        printf("\n");
1.1       deraadt   965: #endif
                    966:
                    967:
1.66      espie     968:        for (ln = Lst_First(l); ln != NULL; ln = Lst_Adv(ln)) {
                    969:                s = (Src *)Lst_Datum(ln);
                    970:                if (s->children == 0) {
                    971:                        free(s->file);
                    972:                        if (!s->parent)
                    973:                                free(s->pref);
                    974:                        else {
1.1       deraadt   975: #ifdef DEBUG_SRC
1.66      espie     976:                                LstNode ln2 = Lst_Member(&s->parent->cp, s);
                    977:                                if (ln2 != NULL)
                    978:                                    Lst_Remove(&s->parent->cp, ln2);
1.1       deraadt   979: #endif
1.66      espie     980:                                --s->parent->children;
                    981:                        }
1.1       deraadt   982: #ifdef DEBUG_SRC
1.66      espie     983:                        printf("free: [l=%x] p=%x %d\n", l, s, s->children);
                    984:                        Lst_Destroy(&s->cp, NOFREE);
1.1       deraadt   985: #endif
1.66      espie     986:                        Lst_Remove(l, ln);
                    987:                        free(s);
                    988:                        t |= 1;
                    989:                        return true;
                    990:                }
1.1       deraadt   991: #ifdef DEBUG_SRC
1.66      espie     992:                else {
                    993:                        printf("keep: [l=%x] p=%x %d: ", l, s, s->children);
                    994:                        Lst_Every(&s->cp, PrintAddr);
                    995:                        printf("\n");
                    996:                }
                    997: #endif
1.1       deraadt   998:        }
                    999:
1.66      espie    1000:        return t;
1.1       deraadt  1001: }
                   1002:
                   1003: /*-
                   1004:  *-----------------------------------------------------------------------
                   1005:  * SuffFindThem --
                   1006:  *     Find the first existing file/target in the list srcs
                   1007:  *
                   1008:  * Results:
                   1009:  *     The lowest structure in the chain of transformations
                   1010:  *-----------------------------------------------------------------------
                   1011:  */
                   1012: static Src *
1.51      espie    1013: SuffFindThem(
                   1014:     Lst           srcs,        /* list of Src structures to search through */
                   1015:     Lst           slst)
1.1       deraadt  1016: {
1.66      espie    1017:        Src        *s;          /* current Src */
                   1018:        Src        *rs;         /* returned Src */
                   1019:        char       *ptr;
                   1020:
                   1021:        rs = NULL;
                   1022:
                   1023:        while ((s = (Src *)Lst_DeQueue(srcs)) != NULL) {
                   1024:                if (DEBUG(SUFF)) {
                   1025:                        printf("\ttrying %s...", s->file);
                   1026:                }
1.1       deraadt  1027:
1.66      espie    1028:                /*
                   1029:                 * A file is considered to exist if either a node exists in the
                   1030:                 * graph for it or the file actually exists.
                   1031:                 */
                   1032:                if (Targ_FindNode(s->file, TARG_NOCREATE) != NULL) {
1.1       deraadt  1033: #ifdef DEBUG_SRC
1.66      espie    1034:                        printf("remove %x from %x\n", s, srcs);
1.1       deraadt  1035: #endif
1.66      espie    1036:                        rs = s;
                   1037:                        break;
                   1038:                }
1.1       deraadt  1039:
1.67    ! espie    1040:                if ((ptr = Dir_FindFile(s->file, &s->suff->searchPath))
1.66      espie    1041:                    != NULL) {
                   1042:                        rs = s;
1.1       deraadt  1043: #ifdef DEBUG_SRC
1.66      espie    1044:                        printf("remove %x from %x\n", s, srcs);
1.1       deraadt  1045: #endif
1.66      espie    1046:                        free(ptr);
                   1047:                        break;
                   1048:                }
                   1049:
                   1050:                if (DEBUG(SUFF)) {
                   1051:                        printf("not there\n");
                   1052:                }
                   1053:
                   1054:                SuffAddLevel(srcs, s);
                   1055:                Lst_AtEnd(slst, s);
1.1       deraadt  1056:        }
                   1057:
1.66      espie    1058:        if (DEBUG(SUFF) && rs) {
                   1059:                printf("got it\n");
1.1       deraadt  1060:        }
1.66      espie    1061:        return rs;
1.1       deraadt  1062: }
                   1063:
                   1064: /*-
                   1065:  *-----------------------------------------------------------------------
                   1066:  * SuffFindCmds --
                   1067:  *     See if any of the children of the target in the Src structure is
                   1068:  *     one from which the target can be transformed. If there is one,
                   1069:  *     a Src structure is put together for it and returned.
                   1070:  *
                   1071:  * Results:
1.18      espie    1072:  *     The Src structure of the "winning" child, or NULL if no such beast.
1.1       deraadt  1073:  *
                   1074:  * Side Effects:
                   1075:  *     A Src structure may be allocated.
                   1076:  *-----------------------------------------------------------------------
                   1077:  */
                   1078: static Src *
1.51      espie    1079: SuffFindCmds(
                   1080:     Src        *targ,  /* Src structure to play with */
                   1081:     Lst        slst)
1.41      espie    1082: {
1.66      espie    1083:        LstNode         ln;     /* General-purpose list node */
                   1084:        GNode           *t,     /* Target GNode */
                   1085:                            *s; /* Source GNode */
                   1086:        int             prefLen;/* The length of the defined prefix */
                   1087:        Suff            *suff;  /* Suffix on matching beastie */
                   1088:        Src             *ret;   /* Return value */
                   1089:        const char              *cp;
                   1090:
                   1091:        t = targ->node;
                   1092:        prefLen = strlen(targ->pref);
                   1093:
                   1094:        for (ln = Lst_First(&t->children); ln != NULL; ln = Lst_Adv(ln)) {
                   1095:                s = (GNode *)Lst_Datum(ln);
                   1096:
                   1097:                cp = strrchr(s->name, '/');
                   1098:                if (cp == NULL) {
                   1099:                        cp = s->name;
                   1100:                } else {
                   1101:                        cp++;
                   1102:                }
                   1103:                if (strncmp(cp, targ->pref, prefLen) == 0) {
                   1104:                        /* The node matches the prefix ok, see if it has a known
                   1105:                         * suffix.      */
                   1106:                        LstNode ln2;
                   1107:                        ln2 = suff_find_by_name(&cp[prefLen]);
                   1108:                        if (ln2 != NULL) {
                   1109:                                /*
                   1110:                                 * It even has a known suffix, see if there's a
                   1111:                                 * transformation defined between the node's
                   1112:                                 * suffix and the target's suffix.
                   1113:                                 *
                   1114:                                 * XXX: Handle multi-stage transformations
                   1115:                                 * here, too.
                   1116:                                 */
                   1117:                                suff = (Suff *)Lst_Datum(ln2);
                   1118:
1.67    ! espie    1119:                                if (Lst_Member(&suff->parents, targ->suff)
1.66      espie    1120:                                    != NULL) {
                   1121:                                        /*
                   1122:                                         * Hot Damn! Create a new Src structure
                   1123:                                         * to describe this transformation
                   1124:                                         * (making sure to duplicate the source
                   1125:                                         * node's name so Suff_FindDeps can
                   1126:                                         * free it again (ick)), and return the
                   1127:                                         * new structure.
                   1128:                                         */
                   1129:                                        ret = emalloc(sizeof(Src));
                   1130:                                        ret->file = estrdup(s->name);
                   1131:                                        ret->pref = targ->pref;
                   1132:                                        ret->suff = suff;
                   1133:                                        ret->parent = targ;
                   1134:                                        ret->node = s;
                   1135:                                        ret->children = 0;
                   1136:                                        targ->children++;
1.1       deraadt  1137: #ifdef DEBUG_SRC
1.66      espie    1138:                                        Lst_Init(&ret->cp);
                   1139:                                        printf("3 add %x %x\n", targ, ret);
                   1140:                                        Lst_AtEnd(&targ->cp, ret);
                   1141: #endif
                   1142:                                        Lst_AtEnd(slst, ret);
                   1143:                                        if (DEBUG(SUFF)) {
                   1144:                                                printf ("\tusing existing source %s\n", s->name);
                   1145:                                        }
                   1146:                                        return ret;
                   1147:                            }
                   1148:                        }
1.1       deraadt  1149:                }
                   1150:        }
1.66      espie    1151:        return NULL;
1.41      espie    1152: }
                   1153:
                   1154: static void
1.51      espie    1155: SuffExpandVarChildren(LstNode after, GNode *cgn, GNode *pgn)
1.41      espie    1156: {
1.66      espie    1157:        GNode   *gn;            /* New source 8) */
                   1158:        char    *cp;            /* Expanded value */
                   1159:        LIST    members;
                   1160:
1.41      espie    1161:
1.66      espie    1162:        if (DEBUG(SUFF))
                   1163:                printf("Expanding \"%s\"...", cgn->name);
1.41      espie    1164:
1.66      espie    1165:        cp = Var_Subst(cgn->name, &pgn->context, true);
                   1166:        if (cp == NULL) {
                   1167:                printf("Problem substituting in %s", cgn->name);
                   1168:                printf("\n");
                   1169:                return;
                   1170:        }
1.41      espie    1171:
1.66      espie    1172:        Lst_Init(&members);
1.41      espie    1173:
1.66      espie    1174:        if (cgn->type & OP_ARCHV) {
                   1175:                /*
                   1176:                 * Node was an archive(member) target, so we want to call
                   1177:                 * on the Arch module to find the nodes for us, expanding
                   1178:                 * variables in the parent's context.
                   1179:                 */
                   1180:                char    *sacrifice = cp;
1.41      espie    1181:
1.66      espie    1182:                (void)Arch_ParseArchive(&sacrifice, &members, &pgn->context);
                   1183:        } else {
                   1184:                /* Break the result into a vector of strings whose nodes
                   1185:                 * we can find, then add those nodes to the members list.
                   1186:                 * Unfortunately, we can't use brk_string because it
                   1187:                 * doesn't understand about variable specifications with
                   1188:                 * spaces in them...  */
                   1189:                char        *start, *cp2;
                   1190:
                   1191:                for (start = cp; *start == ' ' || *start == '\t'; start++)
                   1192:                        continue;
                   1193:                for (cp2 = start; *cp2 != '\0';) {
                   1194:                        if (isspace(*cp2)) {
                   1195:                                /* White-space -- terminate element, find the
                   1196:                                 * node, add it, skip any further spaces.  */
                   1197:                                gn = Targ_FindNodei(start, cp2, TARG_CREATE);
                   1198:                                cp2++;
                   1199:                                Lst_AtEnd(&members, gn);
                   1200:                                while (isspace(*cp2))
                   1201:                                        cp2++;
                   1202:                                /* Adjust cp2 for increment at start of loop,
                   1203:                                 * but set start to first non-space.  */
                   1204:                                start = cp2;
                   1205:                        } else if (*cp2 == '$')
                   1206:                                /* Start of a variable spec -- contact variable
                   1207:                                 * module to find the end so we can skip over
                   1208:                                 * it.  */
                   1209:                                Var_ParseSkip(&cp2, &pgn->context);
                   1210:                        else if (*cp2 == '\\' && cp2[1] != '\0')
                   1211:                                /* Escaped something -- skip over it.  */
                   1212:                                cp2+=2;
                   1213:                        else
                   1214:                                cp2++;
                   1215:                }
1.41      espie    1216:
1.66      espie    1217:                if (cp2 != start) {
                   1218:                        /* Stuff left over -- add it to the list too.  */
                   1219:                        gn = Targ_FindNodei(start, cp2, TARG_CREATE);
                   1220:                        Lst_AtEnd(&members, gn);
                   1221:                }
1.41      espie    1222:        }
1.66      espie    1223:        /* Add all elements of the members list to the parent node.  */
                   1224:        while ((gn = (GNode *)Lst_DeQueue(&members)) != NULL) {
                   1225:                if (DEBUG(SUFF))
                   1226:                        printf("%s...", gn->name);
                   1227:                if (Lst_Member(&pgn->children, gn) == NULL) {
                   1228:                        Lst_Append(&pgn->children, after, gn);
                   1229:                        after = Lst_Adv(after);
                   1230:                        Lst_AtEnd(&gn->parents, pgn);
                   1231:                        pgn->unmade++;
                   1232:                }
                   1233:        }
                   1234:        /* Free the result.  */
                   1235:        free(cp);
1.41      espie    1236:        if (DEBUG(SUFF))
1.66      espie    1237:                printf("\n");
1.41      espie    1238: }
                   1239:
                   1240: static void
1.51      espie    1241: SuffExpandWildChildren(LstNode after, GNode *cgn, GNode *pgn)
1.41      espie    1242: {
1.66      espie    1243:        LstNode ln;             /* List element for old source */
                   1244:        char    *cp;            /* Expanded value */
1.41      espie    1245:
1.66      espie    1246:        LIST    exp;        /* List of expansions */
                   1247:        Lst     path;       /* Search path along which to expand */
1.41      espie    1248:
1.66      espie    1249:        if (DEBUG(SUFF))
                   1250:                printf("Wildcard expanding \"%s\"...", cgn->name);
1.41      espie    1251:
1.66      espie    1252:        /* Find a path along which to expand the word.
                   1253:         *
                   1254:         * If the word has a known suffix, use that path.
                   1255:         * If it has no known suffix and we're allowed to use the null
                   1256:         *       suffix, use its path.
                   1257:         * Else use the default system search path.  */
                   1258:        cp = cgn->name + strlen(cgn->name);
                   1259:        ln = Lst_FindConst(&sufflist, SuffSuffIsSuffixP, cp);
1.41      espie    1260:
1.66      espie    1261:        if (ln != NULL) {
                   1262:                Suff    *s = (Suff *)Lst_Datum(ln);
1.41      espie    1263:
1.66      espie    1264:                if (DEBUG(SUFF))
                   1265:                        printf("suffix is \"%s\"...", s->name);
                   1266:                path = &s->searchPath;
                   1267:        } else
                   1268:                /* Use default search path.  */
                   1269:                path = defaultPath;
1.41      espie    1270:
1.66      espie    1271:        /* Expand the word along the chosen path. */
                   1272:        Lst_Init(&exp);
                   1273:        Dir_Expand(cgn->name, path, &exp);
                   1274:
                   1275:        /* Fetch next expansion off the list and find its GNode.  */
                   1276:        while ((cp = (char *)Lst_DeQueue(&exp)) != NULL) {
                   1277:                GNode           *gn;            /* New source 8) */
                   1278:                if (DEBUG(SUFF))
                   1279:                        printf("%s...", cp);
                   1280:                gn = Targ_FindNode(cp, TARG_CREATE);
                   1281:
                   1282:                /* If gn isn't already a child of the parent, make it so and
                   1283:                 * up the parent's count of unmade children.  */
                   1284:                if (Lst_Member(&pgn->children, gn) == NULL) {
                   1285:                        Lst_Append(&pgn->children, after, gn);
                   1286:                        after = Lst_Adv(after);
                   1287:                        Lst_AtEnd(&gn->parents, pgn);
                   1288:                        pgn->unmade++;
                   1289:                }
1.41      espie    1290:        }
                   1291:
1.66      espie    1292:        if (DEBUG(SUFF))
                   1293:                printf("\n");
1.1       deraadt  1294: }
                   1295:
                   1296: /*-
                   1297:  *-----------------------------------------------------------------------
                   1298:  * SuffExpandChildren --
                   1299:  *     Expand the names of any children of a given node that contain
                   1300:  *     variable invocations or file wildcards into actual targets.
                   1301:  *
                   1302:  * Side Effects:
                   1303:  *     The expanded node is removed from the parent's list of children,
                   1304:  *     and the parent's unmade counter is decremented, but other nodes
1.41      espie    1305:  *     may be added.
1.1       deraadt  1306:  *-----------------------------------------------------------------------
                   1307:  */
1.27      espie    1308: static void
1.51      espie    1309: SuffExpandChildren(
                   1310:     void       *cgnp,          /* Child to examine */
                   1311:     void       *pgnp)          /* Parent node being processed */
1.1       deraadt  1312: {
1.66      espie    1313:        GNode   *cgn = (GNode *)cgnp;
                   1314:        GNode   *pgn = (GNode *)pgnp;
                   1315:        LstNode ln;
                   1316:        /* New nodes effectively take the place of the child, so we place them
                   1317:         * after the child.  */
                   1318:        ln = Lst_Member(&pgn->children, cgn);
                   1319:
                   1320:        /* First do variable expansion -- this takes precedence over wildcard
                   1321:         * expansion. If the result contains wildcards, they'll be gotten to
                   1322:         * later since the resulting words are tacked on to the end of the
                   1323:         * children list.  */
                   1324:        if (strchr(cgn->name, '$') != NULL)
                   1325:                SuffExpandVarChildren(ln, cgn, pgn);
                   1326:        else if (Dir_HasWildcards(cgn->name))
                   1327:                SuffExpandWildChildren(ln, cgn, pgn);
                   1328:        else
                   1329:                /* Third case: nothing to expand.  */
                   1330:                return;
                   1331:
                   1332:        /* Since the source was expanded, remove it from the list of children to
                   1333:         * keep it from being processed.  */
                   1334:        pgn->unmade--;
                   1335:        Lst_Remove(&pgn->children, ln);
1.1       deraadt  1336: }
                   1337:
                   1338: /*-
                   1339:  *-----------------------------------------------------------------------
                   1340:  * SuffApplyTransform --
                   1341:  *     Apply a transformation rule, given the source and target nodes
                   1342:  *     and suffixes.
                   1343:  *
                   1344:  * Results:
1.42      espie    1345:  *     true if successful, false if not.
1.1       deraadt  1346:  *
                   1347:  * Side Effects:
                   1348:  *     The source and target are linked and the commands from the
                   1349:  *     transformation are added to the target node's commands list.
                   1350:  *     All attributes but OP_DEPMASK and OP_TRANSFORM are applied
                   1351:  *     to the target. The target also inherits all the sources for
                   1352:  *     the transformation rule.
                   1353:  *-----------------------------------------------------------------------
                   1354:  */
1.42      espie    1355: static bool
1.51      espie    1356: SuffApplyTransform(
                   1357:     GNode      *tGn,   /* Target node */
                   1358:     GNode      *sGn,   /* Source node */
                   1359:     Suff       *t,     /* Target suffix */
                   1360:     Suff       *s)     /* Source suffix */
1.1       deraadt  1361: {
1.66      espie    1362:        LstNode ln;     /* General node */
                   1363:        LstNode np;         /* Next node for loop */
                   1364:        char    *tname; /* Name of transformation rule */
                   1365:        GNode   *gn;    /* Node for same */
1.1       deraadt  1366:
1.66      espie    1367:        if (Lst_AddNew(&tGn->children, sGn)) {
1.41      espie    1368:                /* Not already linked, so form the proper links between the
                   1369:                 * target and source.  */
1.66      espie    1370:                Lst_AtEnd(&sGn->parents, tGn);
1.41      espie    1371:                tGn->unmade++;
1.1       deraadt  1372:        }
                   1373:
1.66      espie    1374:        if ((sGn->type & OP_OPMASK) == OP_DOUBLEDEP) {
                   1375:                /* When a :: node is used as the implied source of a node, we
                   1376:                 * have to link all its cohorts in as sources as well. Only the
                   1377:                 * initial sGn gets the target in its iParents list, however,
                   1378:                 * as that will be sufficient to get the .IMPSRC variable set
                   1379:                 * for tGn.     */
                   1380:                for (ln=Lst_First(&sGn->cohorts); ln != NULL; ln=Lst_Adv(ln)) {
                   1381:                        gn = (GNode *)Lst_Datum(ln);
                   1382:
                   1383:                        if (Lst_AddNew(&tGn->children, gn)) {
                   1384:                                /* Not already linked, so form the proper links
                   1385:                                 * between the target and source.  */
                   1386:                                Lst_AtEnd(&gn->parents, tGn);
                   1387:                                tGn->unmade++;
                   1388:                        }
                   1389:                }
                   1390:        }
                   1391:        /* Locate the transformation rule itself.  */
                   1392:        tname = Str_concat(s->name, t->name, 0);
                   1393:        ln = transform_find_by_name(tname);
                   1394:        free(tname);
                   1395:
                   1396:        if (ln == NULL)
                   1397:                /*
                   1398:                 * Not really such a transformation rule (can happen when we're
                   1399:                 * called to link an OP_MEMBER and OP_ARCHV node), so return
                   1400:                 * false.
                   1401:                 */
                   1402:                return false;
1.1       deraadt  1403:
1.66      espie    1404:        gn = (GNode *)Lst_Datum(ln);
1.5       millert  1405:
1.66      espie    1406:        if (DEBUG(SUFF))
1.67    ! espie    1407:                printf("\tapplying %s -> %s to \"%s\"\n", s->name, t->name,
1.66      espie    1408:                    tGn->name);
1.1       deraadt  1409:
1.66      espie    1410:        /* Record last child for expansion purposes.  */
                   1411:        ln = Lst_Last(&tGn->children);
1.5       millert  1412:
1.66      espie    1413:        /* Pass the buck to Make_HandleUse to apply the rule.  */
                   1414:        Make_HandleUse(gn, tGn);
1.1       deraadt  1415:
1.66      espie    1416:        /* Deal with wildcards and variables in any acquired sources.  */
                   1417:        for (ln = Lst_Succ(ln); ln != NULL; ln = np) {
                   1418:                np = Lst_Adv(ln);
                   1419:                SuffExpandChildren(Lst_Datum(ln), tGn);
                   1420:        }
1.1       deraadt  1421:
1.66      espie    1422:        /* Keep track of another parent to which this beast is transformed so
                   1423:         * the .IMPSRC variable can be set correctly for the parent.  */
                   1424:        Lst_AtEnd(&sGn->iParents, tGn);
1.1       deraadt  1425:
1.66      espie    1426:        return true;
1.1       deraadt  1427: }
                   1428:
                   1429:
                   1430: /*-
                   1431:  *-----------------------------------------------------------------------
                   1432:  * SuffFindArchiveDeps --
                   1433:  *     Locate dependencies for an OP_ARCHV node.
                   1434:  *
                   1435:  * Side Effects:
                   1436:  *     Same as Suff_FindDeps
                   1437:  *-----------------------------------------------------------------------
                   1438:  */
                   1439: static void
1.51      espie    1440: SuffFindArchiveDeps(
                   1441:     GNode      *gn,        /* Node for which to locate dependencies */
                   1442:     Lst        slst)
1.1       deraadt  1443: {
1.66      espie    1444:        char    *eoarch;    /* End of archive portion */
                   1445:        char    *eoname;    /* End of member portion */
                   1446:        GNode   *mem;       /* Node for member */
                   1447:        Suff    *ms;        /* Suffix descriptor for member */
                   1448:        char    *name;      /* Start of member's name */
                   1449:
                   1450:        /* The node is an archive(member) pair. so we must find a suffix
                   1451:         * for both of them.  */
                   1452:        eoarch = strchr(gn->name, '(');
                   1453:        if (eoarch == NULL)
                   1454:                return;
                   1455:
                   1456:        name = eoarch + 1;
                   1457:
                   1458:        eoname = strchr(name, ')');
                   1459:        if (eoname == NULL)
                   1460:                return;
                   1461:
                   1462:        /* To simplify things, call Suff_FindDeps recursively on the member now,
                   1463:         * so we can simply compare the member's .PREFIX and .TARGET variables
                   1464:         * to locate its suffix. This allows us to figure out the suffix to
                   1465:         * use for the archive without having to do a quadratic search over the
                   1466:         * suffix list, backtracking for each one...  */
                   1467:        mem = Targ_FindNodei(name, eoname, TARG_CREATE);
                   1468:        SuffFindDeps(mem, slst);
                   1469:
                   1470:        /* Create the link between the two nodes right off. */
                   1471:        if (Lst_AddNew(&gn->children, mem)) {
                   1472:                Lst_AtEnd(&mem->parents, gn);
                   1473:                gn->unmade++;
                   1474:        }
                   1475:
                   1476:        /* Copy variables from member node to this one.  */
                   1477:        Varq_Set(TARGET_INDEX, Varq_Value(TARGET_INDEX, mem), gn);
                   1478:        Varq_Set(PREFIX_INDEX, Varq_Value(PREFIX_INDEX, mem), gn);
                   1479:
                   1480:        ms = mem->suffix;
                   1481:        if (ms == NULL) {
                   1482:                /* Didn't know what it was -- use .NULL suffix if not in make
                   1483:                 * mode.  */
                   1484:                if (DEBUG(SUFF))
                   1485:                        printf("using null suffix\n");
                   1486:                ms = suffNull;
                   1487:        }
1.5       millert  1488:
1.1       deraadt  1489:
1.66      espie    1490:        /* Set the other two local variables required for this target.  */
                   1491:        Varq_Set(MEMBER_INDEX, mem->name, gn);
                   1492:        Varq_Set(ARCHIVE_INDEX, gn->name, gn);
1.1       deraadt  1493:
1.66      espie    1494:        if (ms != NULL) {
                   1495:                /*
                   1496:                 * Member has a known suffix, so look for a transformation rule
                   1497:                 * from it to a possible suffix of the archive. Rather than
                   1498:                 * searching through the entire list, we just look at suffixes
                   1499:                 * to which the member's suffix may be transformed...
                   1500:                 */
                   1501:                LstNode     ln;
1.1       deraadt  1502:
1.66      espie    1503:                /* Use first matching suffix...  */
                   1504:                ln = Lst_FindConst(&ms->parents, SuffSuffIsSuffixP, eoarch);
1.1       deraadt  1505:
1.66      espie    1506:                if (ln != NULL) {
                   1507:                        /* Got one -- apply it.  */
                   1508:                        if (!SuffApplyTransform(gn, mem, (Suff *)Lst_Datum(ln),
                   1509:                            ms) && DEBUG(SUFF))
                   1510:                                printf("\tNo transformation from %s -> %s\n",
                   1511:                                    ms->name, ((Suff *)Lst_Datum(ln))->name);
                   1512:                }
1.1       deraadt  1513:        }
                   1514:
1.66      espie    1515:        /* Pretend gn appeared to the left of a dependency operator so
                   1516:         * the user needn't provide a transformation from the member to the
                   1517:         * archive.  */
                   1518:        if (OP_NOP(gn->type))
                   1519:                gn->type |= OP_DEPENDS;
                   1520:
                   1521:        /* Flag the member as such so we remember to look in the archive for
                   1522:         * its modification time.  */
                   1523:        mem->type |= OP_MEMBER;
1.1       deraadt  1524: }
                   1525:
                   1526: /*-
                   1527:  *-----------------------------------------------------------------------
                   1528:  * SuffFindNormalDeps --
                   1529:  *     Locate implicit dependencies for regular targets.
                   1530:  *
                   1531:  * Side Effects:
                   1532:  *     Same as Suff_FindDeps...
                   1533:  *-----------------------------------------------------------------------
                   1534:  */
                   1535: static void
1.51      espie    1536: SuffFindNormalDeps(
                   1537:     GNode      *gn,        /* Node for which to find sources */
                   1538:     Lst        slst)
1.1       deraadt  1539: {
1.66      espie    1540:        char    *eoname;    /* End of name */
                   1541:        char    *sopref;    /* Start of prefix */
                   1542:        LstNode ln;         /* Next suffix node to check */
                   1543:        LstNode np;
                   1544:        LIST    srcs;       /* List of sources at which to look */
                   1545:        LIST    targs;      /* List of targets to which things can be
                   1546:                                 * transformed. They all have the same file,
                   1547:                                 * but different suff and pref fields */
                   1548:        Src     *bottom;    /* Start of found transformation path */
                   1549:        Src     *src;       /* General Src pointer */
                   1550:        char    *pref;      /* Prefix to use */
                   1551:        Src     *targ;      /* General Src target pointer */
                   1552:
                   1553:
                   1554:        eoname = gn->name + strlen(gn->name);
                   1555:
                   1556:        sopref = gn->name;
                   1557:
                   1558:        /* Begin at the beginning...  */
                   1559:        ln = Lst_First(&sufflist);
                   1560:        Lst_Init(&srcs);
                   1561:        Lst_Init(&targs);
                   1562:
                   1563:        /* We're caught in a catch-22 here. On the one hand, we want to use any
                   1564:         * transformation implied by the target's sources, but we can't examine
                   1565:         * the sources until we've expanded any variables/wildcards they may
                   1566:         * hold, and we can't do that until we've set up the target's local
                   1567:         * variables and we can't do that until we know what the proper suffix
                   1568:         * for the target is (in case there are two suffixes one of which is a
                   1569:         * suffix of the other) and we can't know that until we've found its
                   1570:         * implied source, which we may not want to use if there's an existing
                   1571:         * source that implies a different transformation.
                   1572:         *
                   1573:         * In an attempt to get around this, which may not work all the time,
                   1574:         * but should work most of the time, we look for implied sources first,
                   1575:         * checking transformations to all possible suffixes of the target, use
                   1576:         * what we find to set the target's local variables, expand the
                   1577:         * children, then look for any overriding transformations they imply.
                   1578:         * Should we find one, we discard the one we found before.      */
                   1579:
                   1580:        while (ln != NULL) {
                   1581:                /* Look for next possible suffix...  */
                   1582:                ln = Lst_FindFromConst(ln, SuffSuffIsSuffixP, eoname);
                   1583:
                   1584:                if (ln != NULL) {
                   1585:                        int     prefLen;            /* Length of the prefix */
                   1586:                        Src     *targ;
                   1587:
                   1588:                        /* Allocate a Src structure to which things can be
                   1589:                         * transformed.  */
                   1590:                        targ = emalloc(sizeof(Src));
                   1591:                        targ->file = estrdup(gn->name);
                   1592:                        targ->suff = (Suff *)Lst_Datum(ln);
                   1593:                        targ->node = gn;
                   1594:                        targ->parent = NULL;
                   1595:                        targ->children = 0;
1.1       deraadt  1596: #ifdef DEBUG_SRC
1.66      espie    1597:                        Lst_Init(&targ->cp);
1.1       deraadt  1598: #endif
1.5       millert  1599:
1.66      espie    1600:                        /* Allocate room for the prefix, whose end is found by
                   1601:                         * subtracting the length of the suffix from the end of
                   1602:                         * the name.  */
                   1603:                        prefLen = (eoname - targ->suff->nameLen) - sopref;
                   1604:                        targ->pref = emalloc(prefLen + 1);
                   1605:                        memcpy(targ->pref, sopref, prefLen);
                   1606:                        targ->pref[prefLen] = '\0';
1.1       deraadt  1607:
1.66      espie    1608:                        /* Add nodes from which the target can be made.  */
                   1609:                        SuffAddLevel(&srcs, targ);
1.1       deraadt  1610:
1.66      espie    1611:                        /* Record the target so we can nuke it.  */
                   1612:                        Lst_AtEnd(&targs, targ);
1.1       deraadt  1613:
1.66      espie    1614:                        /* Search from this suffix's successor...  */
                   1615:                        ln = Lst_Succ(ln);
                   1616:                }
1.1       deraadt  1617:        }
                   1618:
1.66      espie    1619:        /* Handle target of unknown suffix...  */
                   1620:        if (Lst_IsEmpty(&targs) && suffNull != NULL) {
                   1621:                if (DEBUG(SUFF)) {
                   1622:                        printf("\tNo known suffix on %s. Using .NULL suffix\n",
                   1623:                            gn->name);
                   1624:                }
1.5       millert  1625:
1.66      espie    1626:                targ = emalloc(sizeof(Src));
                   1627:                targ->file = estrdup(gn->name);
                   1628:                targ->suff = suffNull;
                   1629:                targ->node = gn;
                   1630:                targ->parent = NULL;
                   1631:                targ->children = 0;
                   1632:                targ->pref = estrdup(sopref);
1.1       deraadt  1633: #ifdef DEBUG_SRC
1.66      espie    1634:                Lst_Init(&targ->cp);
1.1       deraadt  1635: #endif
                   1636:
1.66      espie    1637:                /* Only use the default suffix rules if we don't have commands
                   1638:                 * or dependencies defined for this gnode.  */
                   1639:                if (Lst_IsEmpty(&gn->commands) && Lst_IsEmpty(&gn->children))
                   1640:                        SuffAddLevel(&srcs, targ);
                   1641:                else {
                   1642:                        if (DEBUG(SUFF))
                   1643:                                printf("not ");
                   1644:                }
1.1       deraadt  1645:
1.66      espie    1646:                if (DEBUG(SUFF))
                   1647:                        printf("adding suffix rules\n");
1.1       deraadt  1648:
1.66      espie    1649:                Lst_AtEnd(&targs, targ);
                   1650:        }
1.5       millert  1651:
1.66      espie    1652:        /* Using the list of possible sources built up from the target
                   1653:         * suffix(es), try and find an existing file/target that matches.  */
                   1654:        bottom = SuffFindThem(&srcs, slst);
                   1655:
                   1656:        if (bottom == NULL) {
                   1657:                /* No known transformations -- use the first suffix found for
                   1658:                 * setting the local variables.  */
                   1659:                if (!Lst_IsEmpty(&targs))
                   1660:                        targ = (Src *)Lst_Datum(Lst_First(&targs));
                   1661:                else
                   1662:                        targ = NULL;
                   1663:        } else {
                   1664:                /* Work up the transformation path to find the suffix of the
                   1665:                 * target to which the transformation was made.  */
                   1666:                for (targ = bottom; targ->parent != NULL; targ = targ->parent)
                   1667:                        continue;
                   1668:        }
                   1669:
                   1670:        /* The .TARGET variable we always set to be the name at this point,
                   1671:         * since it's only set to the path if the thing is only a source and
                   1672:         * if it's only a source, it doesn't matter what we put here as far
                   1673:         * as expanding sources is concerned, since it has none...      */
                   1674:        Varq_Set(TARGET_INDEX, gn->name, gn);
                   1675:
                   1676:        pref = targ != NULL ? targ->pref : gn->name;
                   1677:        Varq_Set(PREFIX_INDEX, pref, gn);
                   1678:
                   1679:        /* Now we've got the important local variables set, expand any sources
                   1680:         * that still contain variables or wildcards in their names.  */
                   1681:        for (ln = Lst_First(&gn->children); ln != NULL; ln = np) {
                   1682:                np = Lst_Adv(ln);
                   1683:                SuffExpandChildren(Lst_Datum(ln), gn);
                   1684:        }
                   1685:
                   1686:        if (targ == NULL) {
                   1687:                if (DEBUG(SUFF))
                   1688:                        printf("\tNo valid suffix on %s\n", gn->name);
1.1       deraadt  1689:
                   1690: sfnd_abort:
1.66      espie    1691:                /* Deal with finding the thing on the default search path if
                   1692:                 * the node is only a source (not on the lhs of a dependency
                   1693:                 * operator or [XXX] it has neither children or commands).  */
                   1694:                if (OP_NOP(gn->type) ||
1.67    ! espie    1695:                    (Lst_IsEmpty(&gn->children) &&
1.66      espie    1696:                    Lst_IsEmpty(&gn->commands))) {
                   1697:                        gn->path = Dir_FindFile(gn->name,
                   1698:                            (targ == NULL ? defaultPath :
                   1699:                            &targ->suff->searchPath));
                   1700:                        if (gn->path != NULL) {
                   1701:                                char *ptr;
                   1702:                                Varq_Set(TARGET_INDEX, gn->path, gn);
                   1703:
                   1704:                                if (targ != NULL) {
                   1705:                                        /* Suffix known for the thing -- trim
                   1706:                                         * the suffix off the path to form the
                   1707:                                         * proper .PREFIX variable.  */
1.67    ! espie    1708:                                        int savep = strlen(gn->path) -
1.66      espie    1709:                                            targ->suff->nameLen;
                   1710:                                        char savec;
                   1711:
                   1712:                                        gn->suffix = targ->suff;
                   1713:
                   1714:                                        savec = gn->path[savep];
                   1715:                                        gn->path[savep] = '\0';
                   1716:
1.67    ! espie    1717:                                        if ((ptr = strrchr(gn->path, '/'))
1.66      espie    1718:                                            != NULL)
                   1719:                                                ptr++;
                   1720:                                        else
                   1721:                                                ptr = gn->path;
                   1722:
                   1723:                                        Varq_Set(PREFIX_INDEX, ptr, gn);
                   1724:
                   1725:                                        gn->path[savep] = savec;
                   1726:                                } else {
                   1727:                                        /* The .PREFIX gets the full path if
                   1728:                                         * the target has no known suffix.  */
                   1729:                                        gn->suffix = NULL;
                   1730:
1.67    ! espie    1731:                                        if ((ptr = strrchr(gn->path, '/'))
1.66      espie    1732:                                            != NULL)
                   1733:                                                ptr++;
                   1734:                                        else
                   1735:                                                ptr = gn->path;
                   1736:
                   1737:                                        Varq_Set(PREFIX_INDEX, ptr, gn);
                   1738:                                }
                   1739:                        }
                   1740:                } else {
                   1741:                        /* Not appropriate to search for the thing -- set the
                   1742:                         * path to be the name so Dir_MTime won't go grovelling
                   1743:                         * for it.  */
                   1744:                        gn->suffix = targ == NULL ? NULL : targ->suff;
                   1745:                        efree(gn->path);
                   1746:                        gn->path = estrdup(gn->name);
                   1747:                }
1.1       deraadt  1748:
1.66      espie    1749:                goto sfnd_return;
                   1750:        }
1.2       deraadt  1751:
1.66      espie    1752:        /* If the suffix indicates that the target is a library, mark that in
                   1753:         * the node's type field.  */
                   1754:        if (targ->suff->flags & SUFF_LIBRARY) {
                   1755:                gn->type |= OP_LIB;
                   1756:        }
                   1757:
                   1758:        /* Check for overriding transformation rule implied by sources.  */
                   1759:        if (!Lst_IsEmpty(&gn->children)) {
                   1760:                src = SuffFindCmds(targ, slst);
                   1761:
                   1762:                if (src != NULL) {
                   1763:                        /* Free up all the Src structures in the transformation
                   1764:                         * path up to, but not including, the parent node.  */
                   1765:                        while (bottom && bottom->parent != NULL) {
                   1766:                                (void)Lst_AddNew(slst, bottom);
                   1767:                                bottom = bottom->parent;
                   1768:                        }
                   1769:                        bottom = src;
1.1       deraadt  1770:                }
                   1771:        }
1.5       millert  1772:
1.66      espie    1773:        if (bottom == NULL) {
                   1774:                /* No idea from where it can come -- return now.  */
                   1775:                goto sfnd_abort;
                   1776:        }
                   1777:
                   1778:        /* We now have a list of Src structures headed by 'bottom' and linked
                   1779:         * via their 'parent' pointers. What we do next is create links between
                   1780:         * source and target nodes (which may or may not have been created) and
                   1781:         * set the necessary local variables in each target. The commands for
                   1782:         * each target are set from the commands of the transformation rule
                   1783:         * used to get from the src suffix to the targ suffix. Note that this
                   1784:         * causes the commands list of the original node, gn, to be replaced by
                   1785:         * the commands of the final transformation rule. Also, the unmade
                   1786:         * field of gn is incremented.  Etc.  */
                   1787:        if (bottom->node == NULL) {
                   1788:                bottom->node = Targ_FindNode(bottom->file, TARG_CREATE);
1.1       deraadt  1789:        }
                   1790:
1.66      espie    1791:        for (src = bottom; src->parent != NULL; src = src->parent) {
                   1792:                targ = src->parent;
1.1       deraadt  1793:
1.66      espie    1794:                src->node->suffix = src->suff;
1.5       millert  1795:
1.66      espie    1796:                if (targ->node == NULL) {
                   1797:                        targ->node = Targ_FindNode(targ->file, TARG_CREATE);
                   1798:                }
1.1       deraadt  1799:
1.67    ! espie    1800:                SuffApplyTransform(targ->node, src->node, targ->suff,
1.66      espie    1801:                    src->suff);
1.1       deraadt  1802:
1.66      espie    1803:                if (targ->node != gn) {
                   1804:                        /* Finish off the dependency-search process for any
                   1805:                         * nodes between bottom and gn (no point in questing
                   1806:                         * around the filesystem for their implicit source when
                   1807:                         * it's already known). Note that the node can't have
                   1808:                         * any sources that need expanding, since SuffFindThem
                   1809:                         * will stop on an existing node, so all we need to do
                   1810:                         * is set the standard and System V variables.  */
                   1811:                        targ->node->type |= OP_DEPS_FOUND;
1.1       deraadt  1812:
1.66      espie    1813:                        Varq_Set(PREFIX_INDEX, targ->pref, targ->node);
1.1       deraadt  1814:
1.66      espie    1815:                        Varq_Set(TARGET_INDEX, targ->node->name, targ->node);
                   1816:                }
1.1       deraadt  1817:        }
                   1818:
1.66      espie    1819:        gn->suffix = src->suff;
1.1       deraadt  1820:
1.66      espie    1821:        /* So Dir_MTime doesn't go questing for it...  */
                   1822:        efree(gn->path);
                   1823:        gn->path = estrdup(gn->name);
1.1       deraadt  1824:
1.66      espie    1825:        /* Nuke the transformation path and the Src structures left over in the
                   1826:         * two lists.  */
1.1       deraadt  1827: sfnd_return:
1.66      espie    1828:        if (bottom)
                   1829:                (void)Lst_AddNew(slst, bottom);
1.1       deraadt  1830:
1.66      espie    1831:        while (SuffRemoveSrc(&srcs) || SuffRemoveSrc(&targs))
                   1832:                continue;
1.1       deraadt  1833:
1.66      espie    1834:        Lst_ConcatDestroy(slst, &srcs);
                   1835:        Lst_ConcatDestroy(slst, &targs);
1.1       deraadt  1836: }
1.5       millert  1837:
                   1838:
1.1       deraadt  1839: /*-
                   1840:  *-----------------------------------------------------------------------
                   1841:  * Suff_FindDeps  --
                   1842:  *     Find implicit sources for the target described by the graph node
                   1843:  *     gn
                   1844:  *
                   1845:  * Side Effects:
                   1846:  *     Nodes are added to the graph below the passed-in node. The nodes
                   1847:  *     are marked to have their IMPSRC variable filled in. The
                   1848:  *     PREFIX variable is set for the given node and all its
                   1849:  *     implied children.
                   1850:  *
                   1851:  * Notes:
                   1852:  *     The path found by this target is the shortest path in the
                   1853:  *     transformation graph, which may pass through non-existent targets,
                   1854:  *     to an existing target. The search continues on all paths from the
                   1855:  *     root suffix until a file is found. I.e. if there's a path
                   1856:  *     .o -> .c -> .l -> .l,v from the root and the .l,v file exists but
                   1857:  *     the .c and .l files don't, the search will branch out in
                   1858:  *     all directions from .o and again from all the nodes on the
                   1859:  *     next level until the .l,v node is encountered.
                   1860:  *-----------------------------------------------------------------------
                   1861:  */
                   1862:
                   1863: void
1.51      espie    1864: Suff_FindDeps(GNode *gn)
1.1       deraadt  1865: {
1.5       millert  1866:
1.66      espie    1867:        SuffFindDeps(gn, &srclist);
                   1868:        while (SuffRemoveSrc(&srclist))
                   1869:                continue;
1.1       deraadt  1870: }
                   1871:
                   1872:
                   1873: static void
1.51      espie    1874: SuffFindDeps(GNode *gn, Lst slst)
1.1       deraadt  1875: {
1.66      espie    1876:        if (gn->type & OP_DEPS_FOUND) {
                   1877:                /*
                   1878:                 * If dependencies already found, no need to do it again...
                   1879:                 */
                   1880:                return;
                   1881:        } else {
                   1882:                gn->type |= OP_DEPS_FOUND;
                   1883:        }
1.5       millert  1884:
1.66      espie    1885:        if (DEBUG(SUFF)) {
                   1886:                printf("SuffFindDeps (%s)\n", gn->name);
                   1887:        }
1.5       millert  1888:
1.66      espie    1889:        if (gn->type & OP_ARCHV) {
                   1890:                SuffFindArchiveDeps(gn, slst);
                   1891:        } else if (gn->type & OP_LIB) {
                   1892:                /*
                   1893:                 * If the node is a library, it is the arch module's job to
                   1894:                 * find it and set the TARGET variable accordingly. We merely
                   1895:                 * provide the search path, assuming all libraries end in ".a"
                   1896:                 * (if the suffix hasn't been defined, there's nothing we can
                   1897:                 * do for it, so we just set the TARGET variable to the node's
                   1898:                 * name in order to give it a value).
                   1899:                 */
                   1900:                LstNode ln;
                   1901:                Suff    *s;
1.5       millert  1902:
1.66      espie    1903:                ln = suff_find_by_name(LIBSUFF);
                   1904:                if (ln != NULL) {
                   1905:                        gn->suffix = s = (Suff *)Lst_Datum(ln);
                   1906:                        Arch_FindLib(gn, &s->searchPath);
                   1907:                } else {
                   1908:                        gn->suffix = NULL;
                   1909:                        Varq_Set(TARGET_INDEX, gn->name, gn);
                   1910:                }
                   1911:                /*
                   1912:                 * Because a library (-lfoo) target doesn't follow the standard
                   1913:                 * filesystem conventions, we don't set the regular variables
                   1914:                 * for the thing. .PREFIX is simply made empty...
                   1915:                 */
                   1916:                Varq_Set(PREFIX_INDEX, "", gn);
                   1917:        } else
                   1918:                SuffFindNormalDeps(gn, slst);
1.1       deraadt  1919: }
                   1920:
                   1921: /*-
                   1922:  *-----------------------------------------------------------------------
                   1923:  * Suff_SetNull --
                   1924:  *     Define which suffix is the null suffix.
                   1925:  *
                   1926:  * Side Effects:
                   1927:  *     'suffNull' is altered.
                   1928:  *
                   1929:  * Notes:
                   1930:  *     Need to handle the changing of the null suffix gracefully so the
                   1931:  *     old transformation rules don't just go away.
                   1932:  *-----------------------------------------------------------------------
                   1933:  */
                   1934: void
1.52      espie    1935: Suff_SetNull(const char *name)
1.1       deraadt  1936: {
1.66      espie    1937:        Suff    *s;
                   1938:        LstNode ln;
1.1       deraadt  1939:
1.66      espie    1940:        ln = suff_find_by_name(name);
                   1941:        if (ln != NULL) {
                   1942:                s = (Suff *)Lst_Datum(ln);
                   1943:                if (suffNull != NULL) {
                   1944:                        suffNull->flags &= ~SUFF_NULL;
                   1945:                }
                   1946:                s->flags |= SUFF_NULL;
                   1947:                /*
                   1948:                 * XXX: Here's where the transformation mangling would take
                   1949:                 * place
                   1950:                 */
                   1951:                suffNull = s;
                   1952:        } else {
1.67    ! espie    1953:                Parse_Error(PARSE_WARNING,
1.66      espie    1954:                    "Desired null suffix %s not defined.", name);
1.1       deraadt  1955:        }
                   1956: }
                   1957:
                   1958: /*-
                   1959:  *-----------------------------------------------------------------------
                   1960:  * Suff_Init --
                   1961:  *     Initialize suffixes module
                   1962:  *
                   1963:  * Side Effects:
                   1964:  *     Many
                   1965:  *-----------------------------------------------------------------------
                   1966:  */
                   1967: void
1.51      espie    1968: Suff_Init(void)
1.1       deraadt  1969: {
1.66      espie    1970:        Static_Lst_Init(&sufflist);
1.14      espie    1971: #ifdef CLEANUP
1.66      espie    1972:        Static_Lst_Init(&suffClean);
1.14      espie    1973: #endif
1.66      espie    1974:        Static_Lst_Init(&srclist);
                   1975:        Static_Lst_Init(&transforms);
                   1976:
                   1977:        sNum = 0;
                   1978:        /*
                   1979:         * Create null suffix for single-suffix rules (POSIX). The thing doesn't
                   1980:         * actually go on the suffix list or everyone will think that's its
                   1981:         * suffix.
                   1982:         */
                   1983:        emptySuff = suffNull = emalloc(sizeof(Suff));
1.1       deraadt  1984:
1.66      espie    1985:        suffNull->name =            estrdup("");
                   1986:        suffNull->nameLen =     0;
                   1987:        Lst_Init(&suffNull->searchPath);
                   1988:        Dir_Concat(&suffNull->searchPath, defaultPath);
                   1989:        Lst_Init(&suffNull->children);
                   1990:        Lst_Init(&suffNull->parents);
                   1991:        Lst_Init(&suffNull->ref);
                   1992:        suffNull->sNum =            sNum++;
                   1993:        suffNull->flags =           SUFF_NULL;
1.1       deraadt  1994:
                   1995: }
                   1996:
                   1997:
                   1998: /*-
                   1999:  *----------------------------------------------------------------------
                   2000:  * Suff_End --
                   2001:  *     Cleanup the this module
                   2002:  *
                   2003:  * Side Effects:
                   2004:  *     The memory is free'd.
                   2005:  *----------------------------------------------------------------------
                   2006:  */
                   2007:
1.42      espie    2008: #ifdef CLEANUP
1.1       deraadt  2009: void
1.51      espie    2010: Suff_End(void)
1.1       deraadt  2011: {
1.66      espie    2012:        Lst_Destroy(&sufflist, SuffFree);
                   2013:        Lst_Destroy(&suffClean, SuffFree);
                   2014:        if (suffNull)
                   2015:                SuffFree(suffNull);
                   2016:        Lst_Destroy(&srclist, NOFREE);
                   2017:        Lst_Destroy(&transforms, NOFREE);
1.42      espie    2018: }
1.14      espie    2019: #endif
1.1       deraadt  2020:
                   2021:
                   2022: /********************* DEBUGGING FUNCTIONS **********************/
                   2023:
1.51      espie    2024: static void SuffPrintName(void *s)
1.1       deraadt  2025: {
1.66      espie    2026:        printf("%s ", ((Suff *)s)->name);
1.1       deraadt  2027: }
                   2028:
1.27      espie    2029: static void
1.51      espie    2030: SuffPrintSuff(void *sp)
1.1       deraadt  2031: {
1.66      espie    2032:        Suff    *s = (Suff *)sp;
                   2033:        int     flags;
                   2034:        int     flag;
                   2035:
                   2036:        printf("# `%s' ", s->name);
                   2037:
                   2038:        flags = s->flags;
                   2039:        if (flags) {
                   2040:                fputs(" (", stdout);
                   2041:                while (flags) {
                   2042:                        flag = 1 << (ffs(flags) - 1);
                   2043:                        flags &= ~flag;
                   2044:                        switch (flag) {
                   2045:                        case SUFF_NULL:
                   2046:                                printf("NULL");
                   2047:                                break;
                   2048:                        case SUFF_INCLUDE:
                   2049:                                printf("INCLUDE");
                   2050:                                break;
                   2051:                        case SUFF_LIBRARY:
                   2052:                                printf("LIBRARY");
                   2053:                                break;
                   2054:                        }
                   2055:                        fputc(flags ? '|' : ')', stdout);
                   2056:                }
1.1       deraadt  2057:        }
1.66      espie    2058:        fputc('\n', stdout);
                   2059:        printf("#\tTo: ");
                   2060:        Lst_Every(&s->parents, SuffPrintName);
                   2061:        fputc('\n', stdout);
                   2062:        printf("#\tFrom: ");
                   2063:        Lst_Every(&s->children, SuffPrintName);
                   2064:        fputc('\n', stdout);
                   2065:        printf("#\tSearch Path: ");
                   2066:        Dir_PrintPath(&s->searchPath);
                   2067:        fputc('\n', stdout);
1.1       deraadt  2068: }
                   2069:
1.27      espie    2070: static void
1.51      espie    2071: SuffPrintTrans(void *tp)
1.1       deraadt  2072: {
1.66      espie    2073:        GNode   *t = (GNode *)tp;
1.1       deraadt  2074:
1.66      espie    2075:        printf("%-16s: ", t->name);
                   2076:        Targ_PrintType(t->type);
                   2077:        fputc('\n', stdout);
                   2078:        Lst_Every(&t->commands, Targ_PrintCmd);
                   2079:        fputc('\n', stdout);
1.1       deraadt  2080: }
                   2081:
                   2082: void
1.51      espie    2083: Suff_PrintAll(void)
1.1       deraadt  2084: {
1.66      espie    2085:        printf("#*** Suffixes:\n");
                   2086:        Lst_Every(&sufflist, SuffPrintSuff);
1.1       deraadt  2087:
1.66      espie    2088:        printf("#*** Transformations:\n");
                   2089:        Lst_Every(&transforms, SuffPrintTrans);
1.1       deraadt  2090: }
1.42      espie    2091:
                   2092: #ifdef DEBUG_SRC
                   2093: static void
1.51      espie    2094: PrintAddr(void *a)
1.42      espie    2095: {
1.66      espie    2096:        printf("%lx ", (unsigned long)a);
1.42      espie    2097: }
                   2098: #endif