780 lines
18 KiB
C
780 lines
18 KiB
C
|
/*************************************************************************
|
||
|
*
|
||
|
* m a k e : m a k e . c
|
||
|
*
|
||
|
* Do the actual making for make plus system dependent stuff
|
||
|
*========================================================================
|
||
|
* Edition history
|
||
|
*
|
||
|
* # Date Comments By
|
||
|
* --- -------- ---------------------------------------------------- ---
|
||
|
* 1 ?? ??
|
||
|
* 2 01.07.89 $<,$* bugs fixed RAL
|
||
|
* 3 23.08.89 (time_t)time((time_t*)0) bug fixed, N_EXISTS added RAL
|
||
|
* 4 30.08.89 leading sp. in cmd. output eliminated, indention ch. PSH,RAL
|
||
|
* 5 03.09.89 :: time fixed, error output -> stderr, N_ERROR intr.
|
||
|
* fixed LZ elimintaed RAL
|
||
|
* 6 07.09.89 implmacro, DF macros,debug stuff added RAL
|
||
|
* 7 09.09.89 tos support added PHH,RAL
|
||
|
* 8 17.09.89 make1 arg. fixed, N_EXEC introduced RAL
|
||
|
* ------------ Version 2.0 released ------------------------------- RAL
|
||
|
* 18.05.90 fixed -n bug with silent rules. (Now echos them.) PAN
|
||
|
*
|
||
|
*************************************************************************/
|
||
|
|
||
|
#include "h.h"
|
||
|
#include <sys/wait.h>
|
||
|
#include <unistd.h>
|
||
|
|
||
|
_PROTOTYPE(static void tellstatus, (FILE *out, char *name, int status));
|
||
|
|
||
|
static bool execflag;
|
||
|
|
||
|
/*
|
||
|
* Exec a shell that returns exit status correctly (/bin/esh).
|
||
|
* The standard EON shell returns the process number of the last
|
||
|
* async command, used by the debugger (ugg).
|
||
|
* [exec on eon is like a fork+exec on unix]
|
||
|
*/
|
||
|
int dosh(string, shell)
|
||
|
char *string;
|
||
|
char *shell;
|
||
|
{
|
||
|
int number;
|
||
|
|
||
|
#ifdef unix
|
||
|
return system(string);
|
||
|
#endif
|
||
|
#ifdef tos
|
||
|
return Tosexec(string);
|
||
|
#endif
|
||
|
#ifdef eon
|
||
|
return ((number = execl(shell, shell,"-c", string, 0)) == -1) ?
|
||
|
-1: /* couldn't start the shell */
|
||
|
wait(number); /* return its exit status */
|
||
|
#endif
|
||
|
#ifdef os9
|
||
|
int status, pid;
|
||
|
|
||
|
strcat(string, "\n");
|
||
|
if ((number = os9fork(shell, strlen(string), string, 0, 0, 0)) == -1)
|
||
|
return -1; /* Couldn't start a shell */
|
||
|
do {
|
||
|
if ((pid = wait(&status)) == -1)
|
||
|
return -1; /* child already died!?!? */
|
||
|
} while (pid != number);
|
||
|
|
||
|
return status;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifdef unix
|
||
|
/*
|
||
|
* Make a file look very outdated after an error trying to make it.
|
||
|
* Don't remove, this keeps hard links intact. (kjb)
|
||
|
*/
|
||
|
int makeold(name) char *name;
|
||
|
{
|
||
|
struct utimbuf a;
|
||
|
|
||
|
a.actime = a.modtime = 0; /* The epoch */
|
||
|
|
||
|
return utime(name, &a);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
static void tellstatus(out, name, status)
|
||
|
FILE *out;
|
||
|
char *name;
|
||
|
int status;
|
||
|
{
|
||
|
char cwd[PATH_MAX];
|
||
|
|
||
|
fprintf(out, "%s in %s: ",
|
||
|
name, getcwd(cwd, sizeof(cwd)) == NULL ? "?" : cwd);
|
||
|
|
||
|
if (WIFEXITED(status)) {
|
||
|
fprintf(out, "Exit code %d", WEXITSTATUS(status));
|
||
|
} else {
|
||
|
fprintf(out, "Signal %d%s",
|
||
|
WTERMSIG(status), status & 0x80 ? " - core dumped" : "");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Do commands to make a target
|
||
|
*/
|
||
|
void docmds1(np, lp)
|
||
|
struct name *np;
|
||
|
struct line *lp;
|
||
|
{
|
||
|
register char *q;
|
||
|
register char *p;
|
||
|
register struct cmd *cp;
|
||
|
bool ssilent;
|
||
|
bool signore;
|
||
|
int estat;
|
||
|
char *shell;
|
||
|
|
||
|
|
||
|
if (*(shell = getmacro("SHELL")) == '\0')
|
||
|
#ifdef eon
|
||
|
shell = ":bin/esh";
|
||
|
#endif
|
||
|
#ifdef unix
|
||
|
shell = "/bin/sh";
|
||
|
#endif
|
||
|
#ifdef os9
|
||
|
shell = "shell";
|
||
|
#endif
|
||
|
#ifdef tos
|
||
|
shell = "DESKTOP"; /* TOS has no shell */
|
||
|
#endif
|
||
|
|
||
|
for (cp = lp->l_cmd; cp; cp = cp->c_next) {
|
||
|
execflag = TRUE;
|
||
|
strcpy(str1, cp->c_cmd);
|
||
|
expmake = FALSE;
|
||
|
expand(&str1s);
|
||
|
q = str1;
|
||
|
ssilent = silent;
|
||
|
signore = ignore;
|
||
|
while ((*q == '@') || (*q == '-')) {
|
||
|
if (*q == '@') /* Specific silent */
|
||
|
ssilent = TRUE;
|
||
|
else /* Specific ignore */
|
||
|
signore = TRUE;
|
||
|
if (!domake) putchar(*q); /* Show all characters. */
|
||
|
q++; /* Not part of the command */
|
||
|
}
|
||
|
|
||
|
for (p=q; *p; p++) {
|
||
|
if (*p == '\n' && p[1] != '\0') {
|
||
|
*p = ' ';
|
||
|
if (!ssilent || !domake)
|
||
|
fputs("\\\n", stdout);
|
||
|
}
|
||
|
else if (!ssilent || !domake)
|
||
|
putchar(*p);
|
||
|
}
|
||
|
if (!ssilent || !domake)
|
||
|
putchar('\n');
|
||
|
|
||
|
if (domake || expmake) { /* Get the shell to execute it */
|
||
|
fflush(stdout);
|
||
|
if ((estat = dosh(q, shell)) != 0) {
|
||
|
if (estat == -1)
|
||
|
fatal("Couldn't execute %s", shell,0);
|
||
|
else if (signore) {
|
||
|
tellstatus(stdout, myname, estat);
|
||
|
printf(" (Ignored)\n");
|
||
|
} else {
|
||
|
tellstatus(stderr, myname, estat);
|
||
|
fprintf(stderr, "\n");
|
||
|
if (!(np->n_flag & N_PREC))
|
||
|
#ifdef unix
|
||
|
if (makeold(np->n_name) == 0)
|
||
|
fprintf(stderr,"%s: made '%s' look old.\n", myname, np->n_name);
|
||
|
#else
|
||
|
if (unlink(np->n_name) == 0)
|
||
|
fprintf(stderr,"%s: '%s' removed.\n", myname, np->n_name);
|
||
|
#endif
|
||
|
if (!conterr) exit(estat != 0);
|
||
|
np->n_flag |= N_ERROR;
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void docmds(np)
|
||
|
struct name *np;
|
||
|
{
|
||
|
register struct line *lp;
|
||
|
|
||
|
for (lp = np->n_line; lp; lp = lp->l_next)
|
||
|
docmds1(np, lp);
|
||
|
}
|
||
|
|
||
|
#ifdef tos
|
||
|
/*
|
||
|
* execute the command submitted by make,
|
||
|
* needed because TOS has no internal shell,
|
||
|
* so we use Pexec to do the job
|
||
|
* v 1.1 of 10/sep/89 by yeti
|
||
|
*/
|
||
|
|
||
|
#define DELM1 ';'
|
||
|
#define DELM2 ' '
|
||
|
#define DELM3 ','
|
||
|
|
||
|
int Tosexec(string)
|
||
|
char *string;
|
||
|
{
|
||
|
register char *help, *help2, c;
|
||
|
register unsigned char l=1;
|
||
|
char progname[80], command[255], plain[15];
|
||
|
static char **envp,*env;
|
||
|
register int error,i;
|
||
|
|
||
|
/* generate strange TOS environment (RAL) */
|
||
|
for ( i = 0, envp = environ; *envp; envp++) i += strlen(*envp) +1;
|
||
|
if ((env = malloc(i+1)) == (char *)0)
|
||
|
fatal("No memory for TOS environment",(char *)0,0);
|
||
|
for ( envp = environ, help = env; *envp; envp++) {
|
||
|
strcpy ( help, *envp);
|
||
|
while ( *(help++)) ;
|
||
|
}
|
||
|
*help = '\0';
|
||
|
|
||
|
help = progname;
|
||
|
while((*help++=*string++) != ' '); /* progname is command name */
|
||
|
*--help = '\0';
|
||
|
|
||
|
l = strlen(string); /* build option list */
|
||
|
command[0] = l; /* TOS likes it complicated */
|
||
|
strcpy(&command[1],string);
|
||
|
if ((error = (int) Pexec(0,progname,command,env)) != -33) {
|
||
|
free(env);
|
||
|
return(error);
|
||
|
}
|
||
|
|
||
|
/* could'nt find program, try to search the PATH */
|
||
|
if((help=strrchr(progname,'\\')) != (char *) 0) /* just the */
|
||
|
strcpy(plain,++help); /* name */
|
||
|
else if((help=strrchr(progname,'/')) != (char *) 0)
|
||
|
strcpy(plain,++help);
|
||
|
else if((help=strrchr(progname,':')) != (char *) 0)
|
||
|
strcpy(plain,++help);
|
||
|
else
|
||
|
strcpy(plain,progname);
|
||
|
|
||
|
if(*(help=getmacro("PATH")) == '\0') {
|
||
|
free(env);
|
||
|
return(-33);
|
||
|
}
|
||
|
c = 1;
|
||
|
while(c)
|
||
|
{ help2 = &progname[-1];
|
||
|
i = 0;
|
||
|
while((c=*help++) != '\0' && i<80 && c != DELM1
|
||
|
&& c != DELM2 && c != DELM3)
|
||
|
*++help2 = c, i++;
|
||
|
*++help2 = '\\';
|
||
|
strcpy(++help2,plain);
|
||
|
if((error=(int) Pexec(0,progname,command,env))!=-33) {
|
||
|
free(env);
|
||
|
return(error);
|
||
|
}
|
||
|
}
|
||
|
free(env);
|
||
|
return(-33);
|
||
|
}
|
||
|
|
||
|
|
||
|
/* (stolen from ZOO -- thanks to Rahul Dehsi)
|
||
|
Function mstonix() accepts an MSDOS format date and time and returns
|
||
|
a **IX format time. No adjustment is done for timezone.
|
||
|
*/
|
||
|
|
||
|
time_t mstonix (date, time)
|
||
|
unsigned int date, time;
|
||
|
{
|
||
|
int year, month, day, hour, min, sec, daycount;
|
||
|
time_t longtime;
|
||
|
/* no. of days to beginning of month for each month */
|
||
|
static int dsboy[12] = { 0, 31, 59, 90, 120, 151, 181, 212,
|
||
|
243, 273, 304, 334};
|
||
|
|
||
|
if (date == 0 && time == 0) /* special case! */
|
||
|
return (0L);
|
||
|
|
||
|
/* part of following code is common to zoolist.c */
|
||
|
year = (((unsigned int) date >> 9) & 0x7f) + 1980;
|
||
|
month = ((unsigned int) date >> 5) & 0x0f;
|
||
|
day = date & 0x1f;
|
||
|
|
||
|
hour = ((unsigned int) time >> 11)& 0x1f;
|
||
|
min = ((unsigned int) time >> 5) & 0x3f;
|
||
|
sec = ((unsigned int) time & 0x1f) * 2;
|
||
|
|
||
|
/* DEBUG and leap year fixes thanks to Mark Alexander <uunet!amdahl!drivax!alexande>*/
|
||
|
#ifdef DEBUG
|
||
|
printf ("mstonix: year=%d month=%d day=%d hour=%d min=%d sec=%d\n",
|
||
|
year, month, day, hour, min, sec);
|
||
|
#endif
|
||
|
/* Calculate days since 1970/01/01 */
|
||
|
daycount = 365 * (year - 1970) + /* days due to whole years */
|
||
|
(year - 1969) / 4 + /* days due to leap years */
|
||
|
dsboy[month-1] + /* days since beginning of this year */
|
||
|
day-1; /* days since beginning of month */
|
||
|
|
||
|
if (year % 4 == 0 &&
|
||
|
year % 400 != 0 && month >= 3) /* if this is a leap year and month */
|
||
|
daycount++; /* is March or later, add a day */
|
||
|
|
||
|
/* Knowing the days, we can find seconds */
|
||
|
longtime = daycount * 24L * 60L * 60L +
|
||
|
hour * 60L * 60L + min * 60 + sec;
|
||
|
return (longtime);
|
||
|
}
|
||
|
#endif /* tos */
|
||
|
|
||
|
#ifdef os9
|
||
|
/*
|
||
|
* Some stuffing around to get the modified time of a file
|
||
|
* in an os9 file system
|
||
|
*/
|
||
|
void getmdate(fd, tbp)
|
||
|
int fd;
|
||
|
struct sgtbuf *tbp;
|
||
|
{
|
||
|
struct registers regs;
|
||
|
static struct fildes fdbuf;
|
||
|
|
||
|
|
||
|
regs.rg_a = fd;
|
||
|
regs.rg_b = SS_FD;
|
||
|
regs.rg_x = &fdbuf;
|
||
|
regs.rg_y = sizeof (fdbuf);
|
||
|
|
||
|
if (_os9(I_GETSTT, ®s) == -1) {
|
||
|
errno = regs.rg_b & 0xff;
|
||
|
return -1;
|
||
|
}
|
||
|
if (tbp)
|
||
|
{
|
||
|
_strass(tbp, fdbuf.fd_date, sizeof (fdbuf.fd_date));
|
||
|
tbp->t_second = 0; /* Files are only acurate to mins */
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Kludge routine to return an aproximation of how many
|
||
|
* seconds since 1980. Dates will be in order, but will not
|
||
|
* be lineer
|
||
|
*/
|
||
|
time_t cnvtime(tbp)
|
||
|
struct sgtbuf *tbp;
|
||
|
{
|
||
|
long acc;
|
||
|
|
||
|
acc = tbp->t_year - 80; /* Baseyear is 1980 */
|
||
|
acc = acc * 12 + tbp->t_month;
|
||
|
acc = acc * 31 + tbp->t_day;
|
||
|
acc = acc * 24 + tbp->t_hour;
|
||
|
acc = acc * 60 + tbp->t_minute;
|
||
|
acc = acc * 60 + tbp->t_second;
|
||
|
|
||
|
return acc;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Get the current time in the internal format
|
||
|
*/
|
||
|
void time(tp)
|
||
|
time_t *tp;
|
||
|
{
|
||
|
struct sgtbuf tbuf;
|
||
|
|
||
|
|
||
|
if (getime(&tbuf) < 0)
|
||
|
return -1;
|
||
|
|
||
|
if (tp)
|
||
|
*tp = cnvtime(&tbuf);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Get the modification time of a file. If the first
|
||
|
* doesn't exist, it's modtime is set to 0.
|
||
|
*/
|
||
|
void modtime(np)
|
||
|
struct name *np;
|
||
|
{
|
||
|
#ifdef unix
|
||
|
struct stat info;
|
||
|
int r;
|
||
|
|
||
|
if (is_archive_ref(np->n_name)) {
|
||
|
r = archive_stat(np->n_name, &info);
|
||
|
} else {
|
||
|
r = stat(np->n_name, &info);
|
||
|
}
|
||
|
if (r < 0) {
|
||
|
if (errno != ENOENT)
|
||
|
fatal("Can't open %s: %s", np->n_name, errno);
|
||
|
|
||
|
np->n_time = 0L;
|
||
|
np->n_flag &= ~N_EXISTS;
|
||
|
} else {
|
||
|
np->n_time = info.st_mtime;
|
||
|
np->n_flag |= N_EXISTS;
|
||
|
}
|
||
|
#endif
|
||
|
#ifdef tos
|
||
|
struct DOSTIME fm;
|
||
|
int fd;
|
||
|
|
||
|
if((fd=Fopen(np->n_name,0)) < 0) {
|
||
|
np->n_time = 0L;
|
||
|
np->n_flag &= ~N_EXISTS;
|
||
|
}
|
||
|
else {
|
||
|
Fdatime(&fm,fd,0);
|
||
|
Fclose(fd);
|
||
|
np->n_time = mstonix((unsigned int)fm.date,(unsigned int)fm.time);
|
||
|
np->n_flag |= N_EXISTS;
|
||
|
}
|
||
|
#endif
|
||
|
#ifdef eon
|
||
|
struct stat info;
|
||
|
int fd;
|
||
|
|
||
|
if ((fd = open(np->n_name, 0)) < 0) {
|
||
|
if (errno != ER_NOTF)
|
||
|
fatal("Can't open %s: %s", np->n_name, errno);
|
||
|
|
||
|
np->n_time = 0L;
|
||
|
np->n_flag &= ~N_EXISTS;
|
||
|
}
|
||
|
else if (getstat(fd, &info) < 0)
|
||
|
fatal("Can't getstat %s: %s", np->n_name, errno);
|
||
|
else {
|
||
|
np->n_time = info.st_mod;
|
||
|
np->n_flag |= N_EXISTS;
|
||
|
}
|
||
|
|
||
|
close(fd);
|
||
|
#endif
|
||
|
#ifdef os9
|
||
|
struct sgtbuf info;
|
||
|
int fd;
|
||
|
|
||
|
if ((fd = open(np->n_name, 0)) < 0) {
|
||
|
if (errno != E_PNNF)
|
||
|
fatal("Can't open %s: %s", np->n_name, errno);
|
||
|
|
||
|
np->n_time = 0L;
|
||
|
np->n_flag &= ~N_EXISTS;
|
||
|
}
|
||
|
else if (getmdate(fd, &info) < 0)
|
||
|
fatal("Can't getstat %s: %s", np->n_name, errno);
|
||
|
else {
|
||
|
np->n_time = cnvtime(&info);
|
||
|
np->n_flag |= N_EXISTS;
|
||
|
}
|
||
|
|
||
|
close(fd);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Update the mod time of a file to now.
|
||
|
*/
|
||
|
void touch(np)
|
||
|
struct name *np;
|
||
|
{
|
||
|
char c;
|
||
|
int fd;
|
||
|
|
||
|
if (!domake || !silent) printf("touch(%s)\n", np->n_name);
|
||
|
|
||
|
if (domake) {
|
||
|
#ifdef unix
|
||
|
struct utimbuf a;
|
||
|
|
||
|
a.actime = a.modtime = time((time_t *)NULL);
|
||
|
if (utime(np->n_name, &a) < 0)
|
||
|
printf("%s: '%s' not touched - non-existant\n",
|
||
|
myname, np->n_name);
|
||
|
#endif
|
||
|
#ifdef tos
|
||
|
struct DOSTIME fm;
|
||
|
int fd;
|
||
|
|
||
|
if((fd=Fopen(np->n_name,0)) < 0) {
|
||
|
printf("%s: '%s' not touched - non-existant\n",
|
||
|
myname, np->n_name);
|
||
|
}
|
||
|
else {
|
||
|
fm.date = Tgetdate();
|
||
|
fm.time = Tgettime();
|
||
|
Fdatime(&fm,fd,1);
|
||
|
Fclose(fd);
|
||
|
}
|
||
|
#endif
|
||
|
#ifdef eon
|
||
|
if ((fd = open(np->n_name, 0)) < 0)
|
||
|
printf("%s: '%s' not touched - non-existant\n",
|
||
|
myname, np->n_name);
|
||
|
else
|
||
|
{
|
||
|
uread(fd, &c, 1, 0);
|
||
|
uwrite(fd, &c, 1);
|
||
|
}
|
||
|
close(fd);
|
||
|
#endif
|
||
|
#ifdef os9
|
||
|
/*
|
||
|
* Strange that something almost as totally useless
|
||
|
* as this is easy to do in os9!
|
||
|
*/
|
||
|
if ((fd = open(np->n_name, S_IWRITE)) < 0)
|
||
|
printf("%s: '%s' not touched - non-existant\n",
|
||
|
myname, np->n_name);
|
||
|
close(fd);
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Recursive routine to make a target.
|
||
|
*/
|
||
|
int make(np, level)
|
||
|
struct name *np;
|
||
|
int level;
|
||
|
{
|
||
|
register struct depend *dp;
|
||
|
register struct line *lp;
|
||
|
register struct depend *qdp;
|
||
|
time_t now, t, dtime = 0;
|
||
|
bool dbgfirst = TRUE;
|
||
|
char *basename = (char *) 0;
|
||
|
char *inputname = (char *) 0;
|
||
|
|
||
|
if (np->n_flag & N_DONE) {
|
||
|
if(dbginfo) dbgprint(level,np,"already done");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
modtime(np); /* Gets modtime of this file */
|
||
|
|
||
|
while (time(&now) == np->n_time) {
|
||
|
/* Time of target is equal to the current time. This bothers us, because
|
||
|
* we can't tell if it needs to be updated if we update a file it depends
|
||
|
* on within a second. So wait a second. (A per-second timer is too
|
||
|
* coarse for today's fast machines.)
|
||
|
*/
|
||
|
sleep(1);
|
||
|
}
|
||
|
|
||
|
if (rules) {
|
||
|
for (lp = np->n_line; lp; lp = lp->l_next)
|
||
|
if (lp->l_cmd)
|
||
|
break;
|
||
|
if (!lp)
|
||
|
dyndep(np,&basename,&inputname);
|
||
|
}
|
||
|
|
||
|
if (!(np->n_flag & (N_TARG | N_EXISTS))) {
|
||
|
fprintf(stderr,"%s: Don't know how to make %s\n", myname, np->n_name);
|
||
|
if (conterr) {
|
||
|
np->n_flag |= N_ERROR;
|
||
|
if (dbginfo) dbgprint(level,np,"don't know how to make");
|
||
|
return 0;
|
||
|
}
|
||
|
else exit(1);
|
||
|
}
|
||
|
|
||
|
for (qdp = (struct depend *)0, lp = np->n_line; lp; lp = lp->l_next) {
|
||
|
for (dp = lp->l_dep; dp; dp = dp->d_next) {
|
||
|
if(dbginfo && dbgfirst) {
|
||
|
dbgprint(level,np," {");
|
||
|
dbgfirst = FALSE;
|
||
|
}
|
||
|
make(dp->d_name, level+1);
|
||
|
if (np->n_time < dp->d_name->n_time)
|
||
|
qdp = newdep(dp->d_name, qdp);
|
||
|
dtime = max(dtime, dp->d_name->n_time);
|
||
|
if (dp->d_name->n_flag & N_ERROR) np->n_flag |= N_ERROR;
|
||
|
if (dp->d_name->n_flag & N_EXEC ) np->n_flag |= N_EXEC;
|
||
|
}
|
||
|
if (!quest && (np->n_flag & N_DOUBLE) &&
|
||
|
(np->n_time < dtime || !( np->n_flag & N_EXISTS))) {
|
||
|
execflag = FALSE;
|
||
|
make1(np, lp, qdp, basename, inputname); /* free()'s qdp */
|
||
|
dtime = 0;
|
||
|
qdp = (struct depend *)0;
|
||
|
if(execflag) np->n_flag |= N_EXEC;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
np->n_flag |= N_DONE;
|
||
|
|
||
|
if (quest) {
|
||
|
t = np->n_time;
|
||
|
np->n_time = now;
|
||
|
return (t < dtime);
|
||
|
}
|
||
|
else if ((np->n_time < dtime || !( np->n_flag & N_EXISTS))
|
||
|
&& !(np->n_flag & N_DOUBLE)) {
|
||
|
execflag = FALSE;
|
||
|
make1(np, (struct line *)0, qdp, basename, inputname); /* free()'s qdp */
|
||
|
np->n_time = now;
|
||
|
if ( execflag) np->n_flag |= N_EXEC;
|
||
|
}
|
||
|
else if ( np->n_flag & N_EXEC ) {
|
||
|
np->n_time = now;
|
||
|
}
|
||
|
|
||
|
if (dbginfo) {
|
||
|
if(dbgfirst) {
|
||
|
if(np->n_flag & N_ERROR)
|
||
|
dbgprint(level,np,"skipped because of error");
|
||
|
else if(np->n_flag & N_EXEC)
|
||
|
dbgprint(level,np,"successfully made");
|
||
|
else dbgprint(level,np,"is up to date");
|
||
|
}
|
||
|
else {
|
||
|
if(np->n_flag & N_ERROR)
|
||
|
dbgprint(level,(struct name *)0,"} skipped because of error");
|
||
|
else if(np->n_flag & N_EXEC)
|
||
|
dbgprint(level,(struct name *)0,"} successfully made");
|
||
|
else dbgprint(level,(struct name *)0,"} is up to date");
|
||
|
}
|
||
|
}
|
||
|
if (level == 0 && !(np->n_flag & N_EXEC))
|
||
|
printf("%s: '%s' is up to date\n", myname, np->n_name);
|
||
|
|
||
|
if(basename)
|
||
|
free(basename);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
void make1(np, lp, qdp, basename, inputname)
|
||
|
struct name *np;
|
||
|
struct line *lp;
|
||
|
register struct depend *qdp;
|
||
|
char *basename;
|
||
|
char *inputname;
|
||
|
{
|
||
|
register struct depend *dp;
|
||
|
|
||
|
|
||
|
if (dotouch)
|
||
|
touch(np);
|
||
|
else if (!(np->n_flag & N_ERROR)) {
|
||
|
strcpy(str1, "");
|
||
|
|
||
|
if(!inputname) {
|
||
|
inputname = str1; /* default */
|
||
|
if (ambigmac) implmacros(np,lp,&basename,&inputname);
|
||
|
}
|
||
|
setDFmacro("<",inputname);
|
||
|
|
||
|
if(!basename)
|
||
|
basename = str1;
|
||
|
setDFmacro("*",basename);
|
||
|
|
||
|
for (dp = qdp; dp; dp = qdp) {
|
||
|
if (strlen(str1))
|
||
|
strcat(str1, " ");
|
||
|
strcat(str1, dp->d_name->n_name);
|
||
|
qdp = dp->d_next;
|
||
|
free(dp);
|
||
|
}
|
||
|
setmacro("?", str1);
|
||
|
setDFmacro("@", np->n_name);
|
||
|
|
||
|
if (lp) /* lp set if doing a :: rule */
|
||
|
docmds1(np, lp);
|
||
|
else
|
||
|
docmds(np);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void implmacros(np,lp, pbasename,pinputname)
|
||
|
struct name *np;
|
||
|
struct line *lp;
|
||
|
char **pbasename; /* Name without suffix */
|
||
|
char **pinputname;
|
||
|
{
|
||
|
struct line *llp;
|
||
|
register char *p;
|
||
|
register char *q;
|
||
|
register char *suff; /* Old suffix */
|
||
|
int baselen;
|
||
|
struct depend *dp;
|
||
|
bool dpflag = FALSE;
|
||
|
|
||
|
/* get basename out of target name */
|
||
|
p = str2;
|
||
|
q = np->n_name;
|
||
|
suff = suffix(q);
|
||
|
while ( *q && (q < suff || !suff)) *p++ = *q++;
|
||
|
*p = '\0';
|
||
|
if ((*pbasename = (char *) malloc(strlen(str2)+1)) == (char *)0 )
|
||
|
fatal("No memory for basename",(char *)0,0);
|
||
|
strcpy(*pbasename,str2);
|
||
|
baselen = strlen(str2);
|
||
|
|
||
|
if ( lp)
|
||
|
llp = lp;
|
||
|
else
|
||
|
llp = np->n_line;
|
||
|
|
||
|
while (llp) {
|
||
|
for (dp = llp->l_dep; dp; dp = dp->d_next) {
|
||
|
if( strncmp(*pbasename,dp->d_name->n_name,baselen) == 0) {
|
||
|
*pinputname = dp->d_name->n_name;
|
||
|
return;
|
||
|
}
|
||
|
if( !dpflag) {
|
||
|
*pinputname = dp->d_name->n_name;
|
||
|
dpflag = TRUE;
|
||
|
}
|
||
|
}
|
||
|
if (lp) break;
|
||
|
llp = llp->l_next;
|
||
|
}
|
||
|
|
||
|
#if NO_WE_DO_WANT_THIS_BASENAME
|
||
|
free(*pbasename); /* basename ambiguous or no dependency file */
|
||
|
*pbasename = (char *)0;
|
||
|
#endif
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void dbgprint(level,np,comment)
|
||
|
int level;
|
||
|
struct name *np;
|
||
|
char *comment;
|
||
|
{
|
||
|
char *timep;
|
||
|
|
||
|
if(np) {
|
||
|
timep = ctime(&np->n_time);
|
||
|
timep[24] = '\0';
|
||
|
fputs(&timep[4],stdout);
|
||
|
}
|
||
|
else fputs(" ",stdout);
|
||
|
fputs(" ",stdout);
|
||
|
while(level--) fputs(" ",stdout);
|
||
|
if (np) {
|
||
|
fputs(np->n_name,stdout);
|
||
|
if (np->n_flag & N_DOUBLE) fputs(" :: ",stdout);
|
||
|
else fputs(" : ",stdout);
|
||
|
}
|
||
|
fputs(comment,stdout);
|
||
|
putchar((int)'\n');
|
||
|
fflush(stdout);
|
||
|
return;
|
||
|
}
|
||
|
|