void run_gnode_parallel(GNode *gn) { char *cmd; gn->built_status = MADE; /* XXX don't bother freeing cmd, we're dead anyways ! */ while ((cmd = Lst_DeQueue(&gn->expanded)) != NULL) { if (setup_and_run_command(cmd, gn, Lst_IsEmpty(&gn->expanded)) == 0) break; } /* Normally, we don't reach this point, unless the last command * ignores error, in which case we interpret the status ourselves. */ switch(gn->built_status) { case MADE: exit(0); case ERROR: exit(1); default: fprintf(stderr, "Could not run gnode, returned %d\n", gn->built_status); exit(1); } }
void Compat_Run(Lst targs) /* List of target nodes to re-create */ { GNode *gn = NULL; /* Current root target */ int errors; /* Number of targets not remade due to errors */ /* For each entry in the list of targets to create, call CompatMake on * it to create the thing. CompatMake will leave the 'built_status' * field of gn in one of several states: * UPTODATE gn was already up-to-date * MADE gn was recreated successfully * ERROR An error occurred while gn was being * created * ABORTED gn was not remade because one of its * inferiors could not be made due to errors. */ errors = 0; while ((gn = (GNode *)Lst_DeQueue(targs)) != NULL) { CompatMake(gn, NULL); if (gn->built_status == UPTODATE) printf("`%s' is up to date.\n", gn->name); else if (gn->built_status == ABORTED) { printf("`%s' not remade because of errors.\n", gn->name); errors++; } } /* If the user has defined a .END target, run its commands. */ if (errors == 0) run_gnode(end_node); }
/*********************************************************************** * AllocPrefix *********************************************************************** * SYNOPSIS: Allocate a new Prefix record * CALLED BY: EXTERNAL * RETURN: The Prefix * with only the generation field set. * SIDE EFFECTS: * * STRATEGY: * * REVISION HISTORY: * Name Date Description * ---- ---- ----------- * ardeb 10/ 9/89 Initial Revision * ***********************************************************************/ Prefix * AllocPrefix() { Prefix *pp; if (Lst_IsEmpty(freePrefixes)) { pp = (Prefix *)malloc(sizeof(Prefix)); pp->generation = 0; } else { pp = (Prefix *)Lst_DeQueue(freePrefixes); } return(pp); }
static int run_prepared_gnode(GNode *gn) { char *cmd; gn->built_status = MADE; while ((cmd = Lst_DeQueue(&gn->expanded)) != NULL) { if (setup_and_run_command(cmd, gn, 0) == 0) break; free(cmd); } free(cmd); if (got_signal) handle_compat_interrupts(gn); return gn->built_status; }
/*- *----------------------------------------------------------------------- * Dir_Init -- * initialize things for this module * * Results: * none * * Side Effects: * some directories may be opened. *----------------------------------------------------------------------- */ void Dir_Init () { dirSearchPath = Lst_Init (FALSE); openDirectories = Lst_Init (FALSE); Hash_InitTable(&mtimes, 0); /* * Since the Path structure is placed on both openDirectories and * the path we give Dir_AddDir (which in this case is openDirectories), * we need to remove "." from openDirectories and what better time to * do it than when we have to fetch the thing anyway? */ Dir_AddDir (openDirectories, "."); dot = (Path *) Lst_DeQueue (openDirectories); /* * We always need to have dot around, so we increment its reference count * to make sure it's not destroyed. */ dot->refCount += 1; }
/*- *----------------------------------------------------------------------- * Arch_ParseArchive -- * Parse the archive specification in the given line and find/create * the nodes for the specified archive members, placing their nodes * on the given list. * * Input: * linePtr Pointer to start of specification * nodeLst Lst on which to place the nodes * ctxt Context in which to expand variables * * Results: * SUCCESS if it was a valid specification. The linePtr is updated * to point to the first non-space after the archive spec. The * nodes for the members are placed on the given list. * * Side Effects: * Some nodes may be created. The given list is extended. * *----------------------------------------------------------------------- */ ReturnStatus Arch_ParseArchive(char **linePtr, Lst nodeLst, GNode *ctxt) { char *cp; /* Pointer into line */ GNode *gn; /* New node */ char *libName; /* Library-part of specification */ char *memName; /* Member-part of specification */ char *nameBuf; /* temporary place for node name */ char saveChar; /* Ending delimiter of member-name */ Boolean subLibName; /* TRUE if libName should have/had * variable substitution performed on it */ libName = *linePtr; subLibName = FALSE; for (cp = libName; *cp != '(' && *cp != '\0'; cp++) { if (*cp == '$') { /* * Variable spec, so call the Var module to parse the puppy * so we can safely advance beyond it... */ int length; void *freeIt; char *result; result = Var_Parse(cp, ctxt, VARF_UNDEFERR|VARF_WANTRES, &length, &freeIt); free(freeIt); if (result == var_Error) { return(FAILURE); } else { subLibName = TRUE; } cp += length-1; } } *cp++ = '\0'; if (subLibName) { libName = Var_Subst(NULL, libName, ctxt, VARF_UNDEFERR|VARF_WANTRES); } for (;;) { /* * First skip to the start of the member's name, mark that * place and skip to the end of it (either white-space or * a close paren). */ Boolean doSubst = FALSE; /* TRUE if need to substitute in memName */ while (*cp != '\0' && *cp != ')' && isspace ((unsigned char)*cp)) { cp++; } memName = cp; while (*cp != '\0' && *cp != ')' && !isspace ((unsigned char)*cp)) { if (*cp == '$') { /* * Variable spec, so call the Var module to parse the puppy * so we can safely advance beyond it... */ int length; void *freeIt; char *result; result = Var_Parse(cp, ctxt, VARF_UNDEFERR|VARF_WANTRES, &length, &freeIt); free(freeIt); if (result == var_Error) { return(FAILURE); } else { doSubst = TRUE; } cp += length; } else { cp++; } } /* * If the specification ends without a closing parenthesis, * chances are there's something wrong (like a missing backslash), * so it's better to return failure than allow such things to happen */ if (*cp == '\0') { printf("No closing parenthesis in archive specification\n"); return (FAILURE); } /* * If we didn't move anywhere, we must be done */ if (cp == memName) { break; } saveChar = *cp; *cp = '\0'; /* * XXX: This should be taken care of intelligently by * SuffExpandChildren, both for the archive and the member portions. */ /* * If member contains variables, try and substitute for them. * This will slow down archive specs with dynamic sources, of course, * since we'll be (non-)substituting them three times, but them's * the breaks -- we need to do this since SuffExpandChildren calls * us, otherwise we could assume the thing would be taken care of * later. */ if (doSubst) { char *buf; char *sacrifice; char *oldMemName = memName; size_t sz; memName = Var_Subst(NULL, memName, ctxt, VARF_UNDEFERR|VARF_WANTRES); /* * Now form an archive spec and recurse to deal with nested * variables and multi-word variable values.... The results * are just placed at the end of the nodeLst we're returning. */ sz = strlen(memName)+strlen(libName)+3; buf = sacrifice = bmake_malloc(sz); snprintf(buf, sz, "%s(%s)", libName, memName); if (strchr(memName, '$') && strcmp(memName, oldMemName) == 0) { /* * Must contain dynamic sources, so we can't deal with it now. * Just create an ARCHV node for the thing and let * SuffExpandChildren handle it... */ gn = Targ_FindNode(buf, TARG_CREATE); if (gn == NULL) { free(buf); return(FAILURE); } else { gn->type |= OP_ARCHV; (void)Lst_AtEnd(nodeLst, gn); } } else if (Arch_ParseArchive(&sacrifice, nodeLst, ctxt)!=SUCCESS) { /* * Error in nested call -- free buffer and return FAILURE * ourselves. */ free(buf); return(FAILURE); } /* * Free buffer and continue with our work. */ free(buf); } else if (Dir_HasWildcards(memName)) { Lst members = Lst_Init(FALSE); char *member; size_t sz = MAXPATHLEN, nsz; nameBuf = bmake_malloc(sz); Dir_Expand(memName, dirSearchPath, members); while (!Lst_IsEmpty(members)) { member = (char *)Lst_DeQueue(members); nsz = strlen(libName) + strlen(member) + 3; if (sz > nsz) nameBuf = bmake_realloc(nameBuf, sz = nsz * 2); snprintf(nameBuf, sz, "%s(%s)", libName, member); free(member); gn = Targ_FindNode(nameBuf, TARG_CREATE); if (gn == NULL) { free(nameBuf); return (FAILURE); } else { /* * We've found the node, but have to make sure the rest of * the world knows it's an archive member, without having * to constantly check for parentheses, so we type the * thing with the OP_ARCHV bit before we place it on the * end of the provided list. */ gn->type |= OP_ARCHV; (void)Lst_AtEnd(nodeLst, gn); } } Lst_Destroy(members, NULL); free(nameBuf); } else { size_t sz = strlen(libName) + strlen(memName) + 3; nameBuf = bmake_malloc(sz); snprintf(nameBuf, sz, "%s(%s)", libName, memName); gn = Targ_FindNode(nameBuf, TARG_CREATE); free(nameBuf); if (gn == NULL) { return (FAILURE); } else { /* * We've found the node, but have to make sure the rest of the * world knows it's an archive member, without having to * constantly check for parentheses, so we type the thing with * the OP_ARCHV bit before we place it on the end of the * provided list. */ gn->type |= OP_ARCHV; (void)Lst_AtEnd(nodeLst, gn); } } if (doSubst) { free(memName); } *cp = saveChar; } /* * If substituted libName, free it now, since we need it no longer. */ if (subLibName) { free(libName); } /* * We promised the pointer would be set up at the next non-space, so * we must advance cp there before setting *linePtr... (note that on * entrance to the loop, cp is guaranteed to point at a ')') */ do { cp++; } while (*cp != '\0' && isspace ((unsigned char)*cp)); *linePtr = cp; return (SUCCESS); }
/*- *----------------------------------------------------------------------- * Compat_Run -- * Initialize this mode and start making. * * Input: * targs List of target nodes to re-create * * Results: * None. * * Side Effects: * Guess what? * *----------------------------------------------------------------------- */ void Compat_Run(Lst targs) { GNode *gn = NULL;/* Current root target */ int errors; /* Number of targets not remade due to errors */ Compat_Init(); if (bmake_signal(SIGINT, SIG_IGN) != SIG_IGN) { bmake_signal(SIGINT, CompatInterrupt); } if (bmake_signal(SIGTERM, SIG_IGN) != SIG_IGN) { bmake_signal(SIGTERM, CompatInterrupt); } if (bmake_signal(SIGHUP, SIG_IGN) != SIG_IGN) { bmake_signal(SIGHUP, CompatInterrupt); } if (bmake_signal(SIGQUIT, SIG_IGN) != SIG_IGN) { bmake_signal(SIGQUIT, CompatInterrupt); } ENDNode = Targ_FindNode(".END", TARG_CREATE); ENDNode->type = OP_SPECIAL; /* * If the user has defined a .BEGIN target, execute the commands attached * to it. */ if (!queryFlag) { gn = Targ_FindNode(".BEGIN", TARG_NOCREATE); if (gn != NULL) { Compat_Make(gn, gn); if (gn->made == ERROR) { PrintOnError(gn, "\n\nStop."); exit(1); } } } /* * Expand .USE nodes right now, because they can modify the structure * of the tree. */ Make_ExpandUse(targs); /* * For each entry in the list of targets to create, call Compat_Make on * it to create the thing. Compat_Make will leave the 'made' field of gn * in one of several states: * UPTODATE gn was already up-to-date * MADE gn was recreated successfully * ERROR An error occurred while gn was being created * ABORTED gn was not remade because one of its inferiors * could not be made due to errors. */ errors = 0; while (!Lst_IsEmpty (targs)) { gn = (GNode *)Lst_DeQueue(targs); Compat_Make(gn, gn); if (gn->made == UPTODATE) { printf("`%s' is up to date.\n", gn->name); } else if (gn->made == ABORTED) { printf("`%s' not remade because of errors.\n", gn->name); errors += 1; } } /* * If the user has defined a .END target, run its commands. */ if (errors == 0) { Compat_Make(ENDNode, ENDNode); if (gn->made == ERROR) { PrintOnError(gn, "\n\nStop."); exit(1); } } }