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

1.1     ! espie       1: /*     $OpenBSD$ */
        !             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 "config.h"
        !            48: #include "defines.h"
        !            49: #include "direxpand.h"
        !            50: #include "engine.h"
        !            51: #include "arch.h"
        !            52: #include "expandchildren.h"
        !            53: #include "var.h"
        !            54: #include "targ.h"
        !            55: #include "lst.h"
        !            56: #include "gnode.h"
        !            57: #include "suff.h"
        !            58:
        !            59: static void ExpandChildren(LstNode, GNode *);
        !            60: static void ExpandVarChildren(LstNode, GNode *, GNode *);
        !            61: static void ExpandWildChildren(LstNode, GNode *, GNode *);
        !            62:
        !            63: void
        !            64: LinkParent(GNode *cgn, GNode *pgn)
        !            65: {
        !            66:        Lst_AtEnd(&cgn->parents, pgn);
        !            67:        if (!has_been_built(cgn))
        !            68:                pgn->children_left++;
        !            69:        else if ( ! (cgn->type & (OP_EXEC|OP_USE))) {
        !            70:                if (cgn->built_status == REBUILT)
        !            71:                        pgn->child_rebuilt = true;
        !            72:                (void)Make_TimeStamp(pgn, cgn);
        !            73:        }
        !            74: }
        !            75:
        !            76: static void
        !            77: ExpandVarChildren(LstNode after, GNode *cgn, GNode *pgn)
        !            78: {
        !            79:        GNode *gn;              /* New source 8) */
        !            80:        char *cp;               /* Expanded value */
        !            81:        LIST members;
        !            82:
        !            83:
        !            84:        if (DEBUG(SUFF))
        !            85:                printf("Expanding \"%s\"...", cgn->name);
        !            86:
        !            87:        cp = Var_Subst(cgn->name, &pgn->localvars, true);
        !            88:        if (cp == NULL) {
        !            89:                printf("Problem substituting in %s", cgn->name);
        !            90:                printf("\n");
        !            91:                return;
        !            92:        }
        !            93:
        !            94:        Lst_Init(&members);
        !            95:
        !            96:        if (cgn->type & OP_ARCHV) {
        !            97:                /*
        !            98:                 * Node was an archive(member) target, so we want to call
        !            99:                 * on the Arch module to find the nodes for us, expanding
        !           100:                 * variables in the parent's context.
        !           101:                 */
        !           102:                const char *sacrifice = (const char *)cp;
        !           103:
        !           104:                (void)Arch_ParseArchive(&sacrifice, &members, &pgn->localvars);
        !           105:        } else {
        !           106:                /* Break the result into a vector of strings whose nodes
        !           107:                 * we can find, then add those nodes to the members list.
        !           108:                 * Unfortunately, we can't use brk_string because it
        !           109:                 * doesn't understand about variable specifications with
        !           110:                 * spaces in them...  */
        !           111:                const char *start, *cp2;
        !           112:
        !           113:                for (start = cp; *start == ' ' || *start == '\t'; start++)
        !           114:                        continue;
        !           115:                for (cp2 = start; *cp2 != '\0';) {
        !           116:                        if (ISSPACE(*cp2)) {
        !           117:                                /* White-space -- terminate element, find the
        !           118:                                 * node, add it, skip any further spaces.  */
        !           119:                                gn = Targ_FindNodei(start, cp2, TARG_CREATE);
        !           120:                                cp2++;
        !           121:                                Lst_AtEnd(&members, gn);
        !           122:                                while (ISSPACE(*cp2))
        !           123:                                        cp2++;
        !           124:                                /* Adjust cp2 for increment at start of loop,
        !           125:                                 * but set start to first non-space.  */
        !           126:                                start = cp2;
        !           127:                        } else if (*cp2 == '$')
        !           128:                                /* Start of a variable spec -- contact variable
        !           129:                                 * module to find the end so we can skip over
        !           130:                                 * it.  */
        !           131:                                Var_ParseSkip(&cp2, &pgn->localvars);
        !           132:                        else if (*cp2 == '\\' && cp2[1] != '\0')
        !           133:                                /* Escaped something -- skip over it.  */
        !           134:                                cp2+=2;
        !           135:                        else
        !           136:                                cp2++;
        !           137:            }
        !           138:
        !           139:            if (cp2 != start) {
        !           140:                    /* Stuff left over -- add it to the list too.  */
        !           141:                    gn = Targ_FindNodei(start, cp2, TARG_CREATE);
        !           142:                    Lst_AtEnd(&members, gn);
        !           143:            }
        !           144:        }
        !           145:        /* Add all elements of the members list to the parent node.  */
        !           146:        while ((gn = Lst_DeQueue(&members)) != NULL) {
        !           147:                if (DEBUG(SUFF))
        !           148:                        printf("%s...", gn->name);
        !           149:                if (Lst_Member(&pgn->children, gn) == NULL) {
        !           150:                        Lst_Append(&pgn->children, after, gn);
        !           151:                        after = Lst_Adv(after);
        !           152:                        LinkParent(gn, pgn);
        !           153:                }
        !           154:        }
        !           155:        /* Free the result.  */
        !           156:        free(cp);
        !           157:        if (DEBUG(SUFF))
        !           158:                printf("\n");
        !           159: }
        !           160:
        !           161: static void
        !           162: ExpandWildChildren(LstNode after, GNode *cgn, GNode *pgn)
        !           163: {
        !           164:        char *cp;       /* Expanded value */
        !           165:
        !           166:        LIST exp;       /* List of expansions */
        !           167:        Lst path;       /* Search path along which to expand */
        !           168:
        !           169:        if (DEBUG(SUFF))
        !           170:                printf("Wildcard expanding \"%s\"...", cgn->name);
        !           171:
        !           172:        /* Find a path along which to expand the word: if
        !           173:         * the word has a known suffix, use the path for that suffix,
        !           174:         * otherwise use the default path. */
        !           175:        path = find_best_path(cgn->name);
        !           176:
        !           177:        /* Expand the word along the chosen path. */
        !           178:        Lst_Init(&exp);
        !           179:        Dir_Expand(cgn->name, path, &exp);
        !           180:
        !           181:        /* Fetch next expansion off the list and find its GNode.  */
        !           182:        while ((cp = Lst_DeQueue(&exp)) != NULL) {
        !           183:                GNode *gn;              /* New source 8) */
        !           184:                if (DEBUG(SUFF))
        !           185:                        printf("%s...", cp);
        !           186:                gn = Targ_FindNode(cp, TARG_CREATE);
        !           187:
        !           188:                /* If gn isn't already a child of the parent, make it so and
        !           189:                 * up the parent's count of children to build.  */
        !           190:                if (Lst_Member(&pgn->children, gn) == NULL) {
        !           191:                        Lst_Append(&pgn->children, after, gn);
        !           192:                        after = Lst_Adv(after);
        !           193:                        LinkParent(gn, pgn);
        !           194:                }
        !           195:        }
        !           196:
        !           197:        if (DEBUG(SUFF))
        !           198:                printf("\n");
        !           199: }
        !           200:
        !           201: /*-
        !           202:  *-----------------------------------------------------------------------
        !           203:  * ExpandChildren --
        !           204:  *     Expand the names of any children of a given node that contain
        !           205:  *     variable invocations or file wildcards into actual targets.
        !           206:  *
        !           207:  * Side Effects:
        !           208:  *     The expanded node is removed from the parent's list of children,
        !           209:  *     and the parent's children to build counter is decremented,
        !           210:  *      but other nodes may be added.
        !           211:  *-----------------------------------------------------------------------
        !           212:  */
        !           213: static void
        !           214: ExpandChildren(LstNode ln, /* LstNode of child, so we can replace it */
        !           215:     GNode *pgn)
        !           216: {
        !           217:        GNode   *cgn = Lst_Datum(ln);
        !           218:
        !           219:        /* First do variable expansion -- this takes precedence over wildcard
        !           220:         * expansion. If the result contains wildcards, they'll be gotten to
        !           221:         * later since the resulting words are tacked on to the end of the
        !           222:         * children list.  */
        !           223:        if (strchr(cgn->name, '$') != NULL)
        !           224:                ExpandVarChildren(ln, cgn, pgn);
        !           225:        else if (Dir_HasWildcards(cgn->name))
        !           226:                ExpandWildChildren(ln, cgn, pgn);
        !           227:        else
        !           228:            /* Third case: nothing to expand.  */
        !           229:                return;
        !           230:
        !           231:        /* Since the source was expanded, remove it from the list of children to
        !           232:         * keep it from being processed.  */
        !           233:        pgn->children_left--;
        !           234:        Lst_Remove(&pgn->children, ln);
        !           235: }
        !           236:
        !           237: void
        !           238: expand_children_from(GNode *parent, LstNode from)
        !           239: {
        !           240:        LstNode np, ln;
        !           241:
        !           242:        for (ln = from; ln != NULL; ln = np) {
        !           243:                np = Lst_Adv(ln);
        !           244:                ExpandChildren(ln, parent);
        !           245:        }
        !           246: }