Пример #1
0
/*-
 *---------------------------------------------------------------------
 * ParseDoOp  --
 *	Apply the parsed operator to the given target node. Used in a
 *	Array_Find call by ParseDoDependency once all targets have
 *	been found and their operator parsed. If the previous and new
 *	operators are incompatible, a major error is taken.
 *
 * Side Effects:
 *	The type field of the node is altered to reflect any new bits in
 *	the op.
 *---------------------------------------------------------------------
 */
static int
ParseDoOp(GNode **gnp, unsigned int op)
{
	GNode *gn = *gnp;
	/*
	 * If the dependency mask of the operator and the node don't match and
	 * the node has actually had an operator applied to it before, and the
	 * operator actually has some dependency information in it, complain.
	 */
	if (((op & OP_OPMASK) != (gn->type & OP_OPMASK)) &&
	    !OP_NOP(gn->type) && !OP_NOP(op)) {
		Parse_Error(PARSE_FATAL, 
		    "Inconsistent dependency operator for target %s\n"
		    "\t(was %s%s, now %s%s)",
		    gn->name, gn->name, operator_string(gn->type), 
		    gn->name, operator_string(op));
		return 0;
	}

	if (op == OP_DOUBLEDEP && ((gn->type & OP_OPMASK) == OP_DOUBLEDEP)) {
		/* If the node was the object of a :: operator, we need to
		 * create a new instance of it for the children and commands on
		 * this dependency line. The new instance is placed on the
		 * 'cohorts' list of the initial one (note the initial one is
		 * not on its own cohorts list) and the new instance is linked
		 * to all parents of the initial instance.  */
		GNode *cohort;
		LstNode ln;

		cohort = Targ_NewGN(gn->name);
		/* Duplicate links to parents so graph traversal is simple.
		 * Perhaps some type bits should be duplicated?
		 *
		 * Make the cohort invisible as well to avoid duplicating it
		 * into other variables. True, parents of this target won't
		 * tend to do anything with their local variables, but better
		 * safe than sorry.  */
		for (ln = Lst_First(&gn->parents); ln != NULL; ln = Lst_Adv(ln))
			ParseLinkSrc((GNode *)Lst_Datum(ln), cohort);
		cohort->type = OP_DOUBLEDEP|OP_INVISIBLE;
		Lst_AtEnd(&gn->cohorts, cohort);

		/* Replace the node in the targets list with the new copy */
		*gnp = cohort;
		gn = cohort;
	}
	/* We don't want to nuke any previous flags (whatever they were) so we
	 * just OR the new operator into the old.  */
	gn->type |= op;
	return 1;
}
Пример #2
0
static void
TargPrintNode(GNode *gn, bool full)
{
	if (OP_NOP(gn->type))
		return;
	switch((gn->special & SPECIAL_MASK)) {
	case SPECIAL_SUFFIXES:
	case SPECIAL_PHONY:
	case SPECIAL_ORDER:
	case SPECIAL_NOTHING:
	case SPECIAL_MAIN:
	case SPECIAL_IGNORE:
		return;
	default:
		break;
	}
	if (full) {
		printf("# %d unmade prerequisites\n", gn->unmade);
		if (! (gn->type & (OP_JOIN|OP_USE|OP_EXEC))) {
			if (!is_out_of_date(gn->mtime)) {
				printf("# last modified %s: %s\n",
				      time_to_string(&gn->mtime),
				      status_to_string(gn));
			} else if (gn->built_status != UNKNOWN) {
				printf("# non-existent (maybe): %s\n",
				    status_to_string(gn));
			} else {
				printf("# unmade\n");
			}
		}
	}
	if (!Lst_IsEmpty(&gn->parents)) {
		printf("# parent targets: ");
		Lst_Every(&gn->parents, TargPrintName);
		fputc('\n', stdout);
	}
	if (gn->impliedsrc)
		printf("# implied prerequisite: %s\n", gn->impliedsrc->name);

	printf("%-16s", gn->name);
	switch (gn->type & OP_OPMASK) {
	case OP_DEPENDS:
		printf(": "); break;
	case OP_FORCE:
		printf("! "); break;
	case OP_DOUBLEDEP:
		printf(":: "); break;
	}
	Targ_PrintType(gn->type);
	Lst_Every(&gn->children, TargPrintName);
	fputc('\n', stdout);
	Lst_Every(&gn->commands, Targ_PrintCmd);
	printf("\n\n");
	if (gn->type & OP_DOUBLEDEP) {
		LstNode ln;

		for (ln = Lst_First(&gn->cohorts); ln != NULL; ln = Lst_Adv(ln))
			TargPrintNode((GNode *)Lst_Datum(ln), full);
	}
}
Пример #3
0
/*-
 *-----------------------------------------------------------------------
 * CondDoCommands --
 *	See if the given node exists and is an actual target with commands
 *	associated with it.
 *
 * Results:
 *	TRUE if the node exists as a target and has commands associated with
 *	it and FALSE if it does not.
 *
 * Side Effects:
 *	None.
 *
 *-----------------------------------------------------------------------
 */
static Boolean
CondDoCommands(int argLen MAKE_ATTR_UNUSED, const char *arg)
{
    GNode   *gn;

    gn = Targ_FindNode(arg, TARG_NOCREATE);
    return (gn != NULL) && !OP_NOP(gn->type) && !Lst_IsEmpty(gn->commands);
}
Пример #4
0
/*-
 *-----------------------------------------------------------------------
 * CondDoTarget --
 *	See if the given node exists and is an actual target.
 *
 * Results:
 *	TRUE if the node exists as a target and FALSE if it does not.
 *
 * Side Effects:
 *	None.
 *
 *-----------------------------------------------------------------------
 */
static Boolean
CondDoTarget(int argLen MAKE_ATTR_UNUSED, const char *arg)
{
    GNode   *gn;

    gn = Targ_FindNode(arg, TARG_NOCREATE);
    return (gn != NULL) && !OP_NOP(gn->type);
}
Пример #5
0
/*-
 *-----------------------------------------------------------------------
 * CondDoTargetWithCommands --
 *	See if the given node exists and has commands.
 *
 * Results:
 *	true if the node is complete and false if it does not.
 *-----------------------------------------------------------------------
 */
static bool
CondDoTargetWithCommands(struct Name *arg)
{
	GNode *gn;

	gn = Targ_FindNodei(arg->s, arg->e, TARG_NOCREATE);
	if (gn != NULL && !OP_NOP(gn->type) && (gn->type & OP_HAS_COMMANDS))
		return true;
	else
		return false;
}
Пример #6
0
/*-
 *-----------------------------------------------------------------------
 * CondDoTarget --
 *	See if the given node exists and is an actual target.
 *
 * Results:
 *	true if the node exists as a target and false if it does not.
 *-----------------------------------------------------------------------
 */
static bool
CondDoTarget(struct Name *arg)
{
	GNode *gn;

	gn = Targ_FindNodei(arg->s, arg->e, TARG_NOCREATE);
	if (gn != NULL && !OP_NOP(gn->type))
		return true;
	else
		return false;
}
Пример #7
0
/*-
 *-----------------------------------------------------------------------
 * TargPrintOnlySrc --
 *	Print only those targets that are just a source.
 *
 * Results:
 *	0.
 *
 * Side Effects:
 *	The name of each file is printed preceeded by #\t
 *
 *-----------------------------------------------------------------------
 */
static int
TargPrintOnlySrc(ClientData gnCD, ClientData unused)
{
    GNode *gn = (GNode *)gnCD;

    if (OP_NOP(gn->type)) {
	printf("#\t%s [%s]\n", gn->name->data,
		  gn->path ? gn->path->data : gn->name->data);
    }
    return (0);
}
Пример #8
0
static void
TargPrintOnlySrc(GNode *gn)
{
	if (OP_NOP(gn->type) && gn->special == SPECIAL_NONE &&
	    !(gn->type & OP_DUMMY)) {
	    	if (gn->path != NULL)
			printf("#\t%s [%s]\n", gn->name, 
			    strcmp(gn->path, gn->name) == 0 ? "=" : gn->path);
		else
			printf("#\t%s\n", gn->name);
    	}
}
Пример #9
0
bool
Job_CheckCommands(GNode *gn)
{
    /* Alter our type to tell if errors should be ignored or things
     * should not be printed so setup_and_run_command knows what to do.
     */
    if (Targ_Ignore(gn))
        gn->type |= OP_IGNORE;
    if (Targ_Silent(gn))
        gn->type |= OP_SILENT;

    if (OP_NOP(gn->type) && Lst_IsEmpty(&gn->commands) &&
            (gn->type & OP_LIB) == 0) {
        /*
         * No commands. Look for .DEFAULT rule from which we might infer
         * commands
         */
        if ((gn->type & OP_NODEFAULT) == 0 &&
                (DEFAULT->type & OP_DUMMY) == 0 &&
                !Lst_IsEmpty(&DEFAULT->commands)) {
            /*
             * Make only looks for a .DEFAULT if the node was never
             * the target of an operator, so that's what we do too.
             * If a .DEFAULT was given, we substitute its commands
             * for gn's commands and set the IMPSRC variable to be
             * the target's name The DEFAULT node acts like a
             * transformation rule, in that gn also inherits any
             * attributes or sources attached to .DEFAULT itself.
             */
            Make_HandleUse(DEFAULT, gn);
            Var(IMPSRC_INDEX, gn) = Var(TARGET_INDEX, gn);
        } else if (is_out_of_date(Dir_MTime(gn))) {
            /*
             * The node wasn't the target of an operator we have no
             * .DEFAULT rule to go on and the target doesn't
             * already exist. There's nothing more we can do for
             * this branch.
             */
            return false;
        }
    }
    return true;
}
Пример #10
0
Файл: arch.c Проект: 0mp/freebsd
/*-
 *-----------------------------------------------------------------------
 * Arch_LibOODate --
 *	Decide if a node with the OP_LIB attribute is out-of-date. Called
 *	from Make_OODate to make its life easier.
 *
 *	There are several ways for a library to be out-of-date that are
 *	not available to ordinary files. In addition, there are ways
 *	that are open to regular files that are not available to
 *	libraries. A library that is only used as a source is never
 *	considered out-of-date by itself. This does not preclude the
 *	library's modification time from making its parent be out-of-date.
 *	A library will be considered out-of-date for any of these reasons,
 *	given that it is a target on a dependency line somewhere:
 *	    Its modification time is less than that of one of its
 *	    	  sources (gn->mtime < gn->cmgn->mtime).
 *	    Its modification time is greater than the time at which the
 *	    	  make began (i.e. it's been modified in the course
 *	    	  of the make, probably by archiving).
 *	    The modification time of one of its sources is greater than
 *		  the one of its RANLIBMAG member (i.e. its table of contents
 *	    	  is out-of-date). We don't compare of the archive time
 *		  vs. TOC time because they can be too close. In my
 *		  opinion we should not bother with the TOC at all since
 *		  this is used by 'ar' rules that affect the data contents
 *		  of the archive, not by ranlib rules, which affect the
 *		  TOC.
 *
 * Input:
 *	gn		The library's graph node
 *
 * Results:
 *	TRUE if the library is out-of-date. FALSE otherwise.
 *
 * Side Effects:
 *	The library will be hashed if it hasn't been already.
 *
 *-----------------------------------------------------------------------
 */
Boolean
Arch_LibOODate(GNode *gn)
{
    Boolean 	  oodate;

    if (gn->type & OP_PHONY) {
	oodate = TRUE;
    } else if (OP_NOP(gn->type) && Lst_IsEmpty(gn->children)) {
	oodate = FALSE;
    } else if ((!Lst_IsEmpty(gn->children) && gn->cmgn == NULL) ||
	       (gn->mtime > now) ||
	       (gn->cmgn != NULL && gn->mtime < gn->cmgn->mtime)) {
	oodate = TRUE;
    } else {
#ifdef RANLIBMAG
	struct ar_hdr  	*arhPtr;    /* Header for __.SYMDEF */
	int 	  	modTimeTOC; /* The table-of-contents's mod time */

	arhPtr = ArchStatMember(gn->path, UNCONST(RANLIBMAG), FALSE);

	if (arhPtr != NULL) {
	    modTimeTOC = (int)strtol(arhPtr->AR_DATE, NULL, 10);

	    if (DEBUG(ARCH) || DEBUG(MAKE)) {
		fprintf(debug_file, "%s modified %s...", RANLIBMAG, Targ_FmtTime(modTimeTOC));
	    }
	    oodate = (gn->cmgn == NULL || gn->cmgn->mtime > modTimeTOC);
	} else {
	    /*
	     * A library w/o a table of contents is out-of-date
	     */
	    if (DEBUG(ARCH) || DEBUG(MAKE)) {
		fprintf(debug_file, "No t.o.c....");
	    }
	    oodate = TRUE;
	}
#else
	oodate = FALSE;
#endif
    }
    return (oodate);
}
Пример #11
0
void
Make_DoAllVar(GNode *gn)
{
    GNode *child;
    LstNode ln;
    BUFFER allsrc, oodate;
    char *target;
    bool do_oodate;
    int oodate_count, allsrc_count = 0;

    oodate_count = 0;
    allsrc_count = 0;

    for (ln = Lst_First(&gn->children); ln != NULL; ln = Lst_Adv(ln)) {
        child = (GNode *)Lst_Datum(ln);
        if ((child->type & (OP_EXEC|OP_USE|OP_INVISIBLE)) != 0)
            continue;
        if (OP_NOP(child->type) ||
                (target = Var(TARGET_INDEX, child)) == NULL) {
            /*
             * this node is only source; use the specific pathname
             * for it
             */
            target = child->path != NULL ? child->path :
                     child->name;
        }

        /*
         * It goes in the OODATE variable if the parent is younger than
         * the child or if the child has been modified more recently
         * than the start of the make.  This is to keep make from
         * getting confused if something else updates the parent after
         * the make starts (shouldn't happen, I know, but sometimes it
         * does). In such a case, if we've updated the kid, the parent
         * is likely to have a modification time later than that of the
         * kid and anything that relies on the OODATE variable will be
         * hosed.
         */
        do_oodate = false;
        if (gn->type & OP_JOIN) {
            if (child->built_status == MADE)
                do_oodate = true;
        } else if (is_strictly_before(gn->mtime, child->mtime) ||
                   (!is_strictly_before(child->mtime, now) &&
                    child->built_status == MADE))
            do_oodate = true;
        if (do_oodate) {
            oodate_count++;
            if (oodate_count == 1)
                Var(OODATE_INDEX, gn) = target;
            else {
                if (oodate_count == 2) {
                    Buf_Init(&oodate, 0);
                    Buf_AddString(&oodate,
                                  Var(OODATE_INDEX, gn));
                }
                Buf_AddSpace(&oodate);
                Buf_AddString(&oodate, target);
            }
        }
        allsrc_count++;
        if (allsrc_count == 1)
            Var(ALLSRC_INDEX, gn) = target;
        else {
            if (allsrc_count == 2) {
                Buf_Init(&allsrc, 0);
                Buf_AddString(&allsrc,
                              Var(ALLSRC_INDEX, gn));
            }
            Buf_AddSpace(&allsrc);
            Buf_AddString(&allsrc, target);
        }
    }

    if (allsrc_count > 1)
        Var(ALLSRC_INDEX, gn) = Buf_Retrieve(&allsrc);
    if (oodate_count > 1)
        Var(OODATE_INDEX, gn) = Buf_Retrieve(&oodate);

    if (gn->impliedsrc)
        Var(IMPSRC_INDEX, gn) = Var(TARGET_INDEX, gn->impliedsrc);

    if (gn->type & OP_JOIN)
        Var(TARGET_INDEX, gn) = Var(ALLSRC_INDEX, gn);
}
Пример #12
0
/*-
 *-----------------------------------------------------------------------
 * TargPrintNode --
 *	print the contents of a node
 *-----------------------------------------------------------------------
 */
static int
TargPrintNode (ClientData gnCD, ClientData pass)
{
    GNode *gn = (GNode *)gnCD;

    if (!OP_NOP(gn->type)) {
	printf("#\n# Target %s assigned in %s\n",
	       gn->name->data,
	       gn->makefilename ?
	       gn->makefilename->data
	       : "(unknown makefile)");
	if (gn == mainTarg) {
	    printf("# *** MAIN TARGET ***\n");
	}
	if ((int)pass == 2) {
	    if (gn->unmade) {
		printf("# %d unmade children\n", gn->unmade);
	    } else {
		printf("# No unmade children\n");
	    }
	    if (! (gn->type & (OP_JOIN|OP_USE|OP_EXEC))) {
		if (gn->mtime != 0) {
		    printf("# last modified %s: %s\n",
			      Targ_FmtTime(gn->mtime),
			      (gn->made == UNMADE ? "unmade" :
			       (gn->made == MADE ? "made" :
				(gn->made == UPTODATE ? "up-to-date" :
				 "error when made"))));
		} else if (gn->made != UNMADE) {
		    printf("# non-existent (maybe): %s\n",
			      (gn->made == MADE ? "made" :
			       (gn->made == UPTODATE ? "up-to-date" :
				(gn->made == ERROR ? "error when made" :
				 "aborted"))));
		} else {
		    printf("# unmade\n");
		}
	    }
	    if (!Lst_IsEmpty (gn->iParents)) {
		printf("# implicit parents: ");
		Lst_ForEach (gn->iParents, TargPrintName, (ClientData)0);
		putc ('\n', stdout);
	    }
	}
	if (!Lst_IsEmpty (gn->parents)) {
	    printf("# parents: ");
	    Lst_ForEach (gn->parents, TargPrintName, (ClientData)0);
	    putc ('\n', stdout);
	}
	
	printf("%-16s", gn->name->data);
	switch (gn->type & OP_OPMASK) {
	    case OP_DEPENDS:
		printf(": "); break;
	    case OP_FORCE:
		printf("! "); break;
	    case OP_DOUBLEDEP:
		printf(":: "); break;
	}
	Targ_PrintType (gn->type);
	Lst_ForEach (gn->children, TargPrintName, (ClientData)0);
	putc ('\n', stdout);
	Lst_ForEach (gn->commands, Targ_PrintCmd, (ClientData)0);
	printf("\n\n");
	if (gn->type & OP_DOUBLEDEP) {
	    Lst_ForEach (gn->cohorts, TargPrintNode, pass);
	}
    }
    return (0);
}