[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.81

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