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

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