Exemple #1
0
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);
    }
}
Exemple #2
0
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);
}
Exemple #3
0
/***********************************************************************
 *				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);
}
Exemple #4
0
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;
}
Exemple #5
0
/*-
 *-----------------------------------------------------------------------
 * 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;
}
Exemple #6
0
/*-
 *-----------------------------------------------------------------------
 * 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);
}
Exemple #7
0
/*-
 *-----------------------------------------------------------------------
 * 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);
	}
    }
}