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

Annotation of src/usr.bin/make/expandchildren.c, Revision 1.4

1.4     ! jsg         1: /*     $OpenBSD: expandchildren.c,v 1.3 2023/09/04 11:35:11 espie Exp $ */
1.1       espie       2: /*     $NetBSD: suff.c,v 1.13 1996/11/06 17:59:25 christos Exp $       */
                      3:
                      4: /*
                      5:  * Copyright (c) 1988, 1989, 1990, 1993
                      6:  *     The Regents of the University of California.  All rights reserved.
                      7:  * Copyright (c) 1989 by Berkeley Softworks
                      8:  * All rights reserved.
                      9:  *
                     10:  * This code is derived from software contributed to Berkeley by
                     11:  * Adam de Boor.
                     12:  *
                     13:  * Redistribution and use in source and binary forms, with or without
                     14:  * modification, are permitted provided that the following conditions
                     15:  * are met:
                     16:  * 1. Redistributions of source code must retain the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer.
                     18:  * 2. Redistributions in binary form must reproduce the above copyright
                     19:  *    notice, this list of conditions and the following disclaimer in the
                     20:  *    documentation and/or other materials provided with the distribution.
                     21:  * 3. Neither the name of the University nor the names of its contributors
                     22:  *    may be used to endorse or promote products derived from this software
                     23:  *    without specific prior written permission.
                     24:  *
                     25:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     26:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     27:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     28:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     29:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     30:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     31:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     32:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     33:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     34:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     35:  * SUCH DAMAGE.
                     36:  */
                     37:
                     38: /*-
                     39:  * expandchildren.c --
                     40:  *     Dealing with final children expansion before building stuff
                     41:  */
                     42:
                     43: #include <ctype.h>
                     44: #include <stdio.h>
                     45: #include <stdlib.h>
                     46: #include <string.h>
                     47: #include "defines.h"
                     48: #include "direxpand.h"
                     49: #include "engine.h"
                     50: #include "arch.h"
                     51: #include "expandchildren.h"
                     52: #include "var.h"
                     53: #include "targ.h"
                     54: #include "lst.h"
                     55: #include "gnode.h"
                     56: #include "suff.h"
                     57:
                     58: static void ExpandChildren(LstNode, GNode *);
                     59: static void ExpandVarChildren(LstNode, GNode *, GNode *);
                     60: static void ExpandWildChildren(LstNode, GNode *, GNode *);
                     61:
                     62: void
                     63: LinkParent(GNode *cgn, GNode *pgn)
                     64: {
                     65:        Lst_AtEnd(&cgn->parents, pgn);
                     66:        if (!has_been_built(cgn))
                     67:                pgn->children_left++;
1.2       espie      68:        else if ( ! (cgn->type & OP_USE)) {
1.1       espie      69:                if (cgn->built_status == REBUILT)
                     70:                        pgn->child_rebuilt = true;
                     71:                (void)Make_TimeStamp(pgn, cgn);
                     72:        }
                     73: }
                     74:
                     75: static void
                     76: ExpandVarChildren(LstNode after, GNode *cgn, GNode *pgn)
                     77: {
                     78:        GNode *gn;              /* New source 8) */
                     79:        char *cp;               /* Expanded value */
                     80:        LIST members;
                     81:
                     82:
                     83:        if (DEBUG(SUFF))
                     84:                printf("Expanding \"%s\"...", cgn->name);
                     85:
                     86:        cp = Var_Subst(cgn->name, &pgn->localvars, true);
                     87:        if (cp == NULL) {
                     88:                printf("Problem substituting in %s", cgn->name);
                     89:                printf("\n");
                     90:                return;
                     91:        }
                     92:
                     93:        Lst_Init(&members);
                     94:
                     95:        if (cgn->type & OP_ARCHV) {
                     96:                /*
                     97:                 * Node was an archive(member) target, so we want to call
                     98:                 * on the Arch module to find the nodes for us, expanding
                     99:                 * variables in the parent's context.
                    100:                 */
                    101:                const char *sacrifice = (const char *)cp;
                    102:
                    103:                (void)Arch_ParseArchive(&sacrifice, &members, &pgn->localvars);
                    104:        } else {
                    105:                /* Break the result into a vector of strings whose nodes
                    106:                 * we can find, then add those nodes to the members list.
                    107:                 * Unfortunately, we can't use brk_string because it
                    108:                 * doesn't understand about variable specifications with
                    109:                 * spaces in them...  */
                    110:                const char *start, *cp2;
                    111:
                    112:                for (start = cp; *start == ' ' || *start == '\t'; start++)
                    113:                        continue;
                    114:                for (cp2 = start; *cp2 != '\0';) {
                    115:                        if (ISSPACE(*cp2)) {
                    116:                                /* White-space -- terminate element, find the
                    117:                                 * node, add it, skip any further spaces.  */
                    118:                                gn = Targ_FindNodei(start, cp2, TARG_CREATE);
                    119:                                cp2++;
                    120:                                Lst_AtEnd(&members, gn);
                    121:                                while (ISSPACE(*cp2))
                    122:                                        cp2++;
                    123:                                /* Adjust cp2 for increment at start of loop,
                    124:                                 * but set start to first non-space.  */
                    125:                                start = cp2;
                    126:                        } else if (*cp2 == '$')
                    127:                                /* Start of a variable spec -- contact variable
                    128:                                 * module to find the end so we can skip over
                    129:                                 * it.  */
                    130:                                Var_ParseSkip(&cp2, &pgn->localvars);
                    131:                        else if (*cp2 == '\\' && cp2[1] != '\0')
                    132:                                /* Escaped something -- skip over it.  */
                    133:                                cp2+=2;
                    134:                        else
                    135:                                cp2++;
1.4     ! jsg       136:                }
1.1       espie     137:
1.4     ! jsg       138:                if (cp2 != start) {
        !           139:                        /* Stuff left over -- add it to the list too.  */
        !           140:                        gn = Targ_FindNodei(start, cp2, TARG_CREATE);
        !           141:                        Lst_AtEnd(&members, gn);
        !           142:                }
1.1       espie     143:        }
                    144:        /* Add all elements of the members list to the parent node.  */
                    145:        while ((gn = Lst_DeQueue(&members)) != NULL) {
                    146:                if (DEBUG(SUFF))
                    147:                        printf("%s...", gn->name);
                    148:                if (Lst_Member(&pgn->children, gn) == NULL) {
                    149:                        Lst_Append(&pgn->children, after, gn);
                    150:                        after = Lst_Adv(after);
                    151:                        LinkParent(gn, pgn);
                    152:                }
                    153:        }
                    154:        /* Free the result.  */
                    155:        free(cp);
                    156:        if (DEBUG(SUFF))
                    157:                printf("\n");
                    158: }
                    159:
                    160: static void
                    161: ExpandWildChildren(LstNode after, GNode *cgn, GNode *pgn)
                    162: {
                    163:        char *cp;       /* Expanded value */
                    164:
                    165:        LIST exp;       /* List of expansions */
                    166:        Lst path;       /* Search path along which to expand */
                    167:
                    168:        if (DEBUG(SUFF))
                    169:                printf("Wildcard expanding \"%s\"...", cgn->name);
                    170:
                    171:        /* Find a path along which to expand the word: if
                    172:         * the word has a known suffix, use the path for that suffix,
                    173:         * otherwise use the default path. */
                    174:        path = find_best_path(cgn->name);
                    175:
                    176:        /* Expand the word along the chosen path. */
                    177:        Lst_Init(&exp);
                    178:        Dir_Expand(cgn->name, path, &exp);
                    179:
                    180:        /* Fetch next expansion off the list and find its GNode.  */
                    181:        while ((cp = Lst_DeQueue(&exp)) != NULL) {
                    182:                GNode *gn;              /* New source 8) */
                    183:                if (DEBUG(SUFF))
                    184:                        printf("%s...", cp);
                    185:                gn = Targ_FindNode(cp, TARG_CREATE);
                    186:
                    187:                /* If gn isn't already a child of the parent, make it so and
                    188:                 * up the parent's count of children to build.  */
                    189:                if (Lst_Member(&pgn->children, gn) == NULL) {
                    190:                        Lst_Append(&pgn->children, after, gn);
                    191:                        after = Lst_Adv(after);
                    192:                        LinkParent(gn, pgn);
                    193:                }
                    194:        }
                    195:
                    196:        if (DEBUG(SUFF))
                    197:                printf("\n");
                    198: }
                    199:
                    200: /*-
                    201:  *-----------------------------------------------------------------------
                    202:  * ExpandChildren --
                    203:  *     Expand the names of any children of a given node that contain
                    204:  *     variable invocations or file wildcards into actual targets.
                    205:  *
                    206:  * Side Effects:
                    207:  *     The expanded node is removed from the parent's list of children,
                    208:  *     and the parent's children to build counter is decremented,
                    209:  *      but other nodes may be added.
                    210:  *-----------------------------------------------------------------------
                    211:  */
                    212: static void
                    213: ExpandChildren(LstNode ln, /* LstNode of child, so we can replace it */
                    214:     GNode *pgn)
                    215: {
                    216:        GNode   *cgn = Lst_Datum(ln);
                    217:
                    218:        /* First do variable expansion -- this takes precedence over wildcard
                    219:         * expansion. If the result contains wildcards, they'll be gotten to
                    220:         * later since the resulting words are tacked on to the end of the
                    221:         * children list.  */
                    222:        if (strchr(cgn->name, '$') != NULL)
                    223:                ExpandVarChildren(ln, cgn, pgn);
                    224:        else if (Dir_HasWildcards(cgn->name))
                    225:                ExpandWildChildren(ln, cgn, pgn);
                    226:        else
                    227:            /* Third case: nothing to expand.  */
                    228:                return;
                    229:
                    230:        /* Since the source was expanded, remove it from the list of children to
                    231:         * keep it from being processed.  */
                    232:        pgn->children_left--;
                    233:        Lst_Remove(&pgn->children, ln);
                    234: }
                    235:
                    236: void
                    237: expand_children_from(GNode *parent, LstNode from)
                    238: {
                    239:        LstNode np, ln;
                    240:
                    241:        for (ln = from; ln != NULL; ln = np) {
                    242:                np = Lst_Adv(ln);
                    243:                ExpandChildren(ln, parent);
                    244:        }
                    245: }