home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
216.lha
/
PdMake
/
make.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-02-15
|
9KB
|
370 lines
/*
* Do the actual making for make
*/
#include <stdio.h>
#ifdef unix
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/errno.h>
#endif
#include "h.h"
#ifdef MCH_AMIGA
/* test if timestamp is NULL */
null_time(t) TimeStamp *t;
{ return !(t->t[0] || t->t[1] || t->t[2]);
}
/* cmp_time(t1,t2) - compare two timestamps
returns >0 if (t1 > t2)
0 if (t1 = t2)
<0 if (t1 < t2)
*/
cmp_time(t1,t2) TimeStamp *t1,*t2;
{ long l;
if (l = t1->t[0] - t2->t[0]) return l;
if (l = t1->t[1] - t2->t[1]) return l;
return t1->t[2]-t2->t[2];
}
TimeStamp time_zero = { 0,0,0 }; /* a null timestamp */
TimeStamp time_one = { 0,0,1 }; /* a mostly null timestamp */
#endif
/* DJ notes -
is the idea of alternate shells applicaple here? Do we want this make
to support things like ARexx?
Currently there's no support for such in the code...
*/
/*
* Exec a shell that returns exit status correctly (/bin/esh).
*/
int
dosh(string, shell)
char * string;
char * shell;
{ return xsystem(string);
}
/*
* Do commands to make a target
*/
void
docmds1(np, lp)
struct name *np;
struct line *lp;
{
bool ssilent;
bool signore;
int estat;
register char *q;
register char *p;
char *shell;
register struct cmd *cp;
/* shell code is commented out for now */
#if 0
if (*(shell = getmacro("SHELL")) == '\0') /* if no shell defined */
#ifdef unix
shell = "/bin/sh"; /* use default shell */
#else
shell = NULL; /* use normal shell */
#endif
#endif
for (cp = lp->l_cmd; cp; cp = cp->c_next) /* for each command in line */
{
strcpy(str1, cp->c_cmd); /* get command string */
expand(str1); /* expand macros */
q = str1; /* string pointer */
ssilent = silent; /* get 'silent' flag */
signore = ignore; /* get 'ignore' flag */
while ((*q == '@') || (*q == '-'))
{ if (*q == '@') /* Specific silent */
ssilent = TRUE; /* silence this command */
else /* Specific ignore */
signore = TRUE; /* ignore return code */
q++; /* Not part of the command */
}
if (!domake) ssilent = 0; /* not silent if no make */
if (!ssilent) fputs(" ", stdout); /* put out a tab */
for (p=q; *p; p++)
{ if (*p == '\n' && p[1] != '\0') /* if a carriage return */
{ *p = ' '; /* make it a space */
if (!ssilent) /* and if not silent */
fputs("\\\n", stdout); /* print a slash */
}
else if (!ssilent) /* if not silent */
putchar(*p); /* print the character */
}
if (!ssilent) /* if not silent */
putchar('\n'); /* print a newline */
if (!domake) return; /* return if pretending */
/* Get the shell to execute it */
if ((estat = dosh(q, shell)) != 0) /* if an error code */
{
/* add some more status stuff in here, like 'Interrupted', etc. */
if (estat == -1) /* -1 = couldn't execute */
fatal("Couldn't execute %s", shell);
else
{ printf("%s: Error code %d", myname, estat);
if (signore) /* if ignore command return */
fputs(" (Ignored)\n", stdout); /* then indicate so */
else /* otherwise */
{ putchar('\n'); /* newline */
if (!(np->n_flag & N_PREC)) /* delete target file ?? */
if (unlink(np->n_name) == 0)
printf("%s: '%s' removed.\n", myname, np->n_name);
exit(estat);
}
}
}
}
}
docmds(np)
struct name *np;
{
register struct line *lp;
for (lp = np->n_line; lp; lp = lp->l_next) /* for each line in the entry */
docmds1(np, lp); /* do the command */
}
/*
* 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 fd;
if (stat(np->n_name, &info) < 0)
{
if (errno != ENOENT)
fatal("Can't open %s; error %d", np->n_name, errno);
np->n_time = 0L;
}
else
np->n_time = info.st_mtime;
#endif
#ifdef MCH_AMIGA
{ if (!GetFileDate(np->n_name,&np->n_time))
{ if (IoErr()==205) np->n_time = time_zero;
else fatal("Can't get date for file %s", np->n_name);
}
}
#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
long a[2];
a[0] = a[1] = time(0);
if (utime(np->n_name, &a[0]) < 0)
printf("%s: '%s' not touched - non-existant\n",
myname, np->n_name);
#endif
#ifdef MCH_AMIGA
/* insert a SetFileDate function here */
#endif
}
}
/* from PAMAKE */
#if 0
/*
* Clear the dynamic dep flag for all deps of this target,
* in case this dep is used again for another target
*/
void cleardynflag(np)
struct name *np;
{ register struct depend *dp;
register struct line *lp;
for (lp = np->n_line; lp; lp = lp->l_next)
for (dp = lp->l_dep; dp; dp = dp->d_next)
dp->d_name->n_flag &= ~N_DYND;
}
/*
* Display the timestamp
*/
void dodisp(name,t)
char *name;
time_t t; /* fix */
{
if (t < 10)
printf("... %s Timestamp %ld\n",name,t);
else
printf("... %s Timestamp %s",name,ctime(&t));
}
#endif
/*
* Recursive routine to make a target.
*/
int make(np, level)
struct name *np; /* name pointer */
int level; /* how many levels down */
{ register struct depend *dp; /* dependancy */
register struct line *lp;
register struct depend *qdp;
TimeStamp dtime;
bool didsomething = 0;
dtime = time_zero;
#if 0
/* from PAMAKE */
if (np->n_flag & N_DONE)
{
if ( display ) dodisp(np->n_name,np->n_time);
return 0;
}
#endif
if (np->n_flag & N_DONE) return 0; /* if we already did this... */
if (null_time(&np->n_time)) /* if time == time_zero */
modtime(np); /* get modtime of this file */
/* if ( display ) dodisp(np->n_name,&np->n_time); */ /* from PAMAKE */
if (rules) /* if using inbuilt rules */
{ for (lp = np->n_line; lp; lp = lp->l_next) /* search line list of entry */
if (lp->l_cmd) break; /* if line has a command, then do it */
if (!lp) dyndep(np); /* else look for a dynamic dependancy */
}
/* if at this point the file doesn't exist, and it's not a target,
then no way to tell how to make it.
*/
if (!(np->n_flag & N_TARG) && null_time(&np->n_time))
fatal("Don't know how to make %s", np->n_name);
/* for each entry for the name, for each depndancy in the line */
for (qdp = NULL, lp = np->n_line; lp; lp = lp->l_next)
{
for (dp = lp->l_dep; dp; dp = dp->d_next)
{
make(dp->d_name, level+1); /* try making it */
/* if the file is earlier than the dependancy, make it a
dependant (on a temp list) */
if (cmp_time(&np->n_time,&dp->d_name->n_time) < 0)
qdp = newdep(dp->d_name, qdp);
/* our time is MAX(our time,dependant's time) */
if (cmp_time(&dtime,&dp->d_name->n_time) < 0)
dtime = dp->d_name->n_time;
}
if (!quest && (np->n_flag & N_DOUBLE) && cmp_time(&np->n_time,&dtime) < 0)
{ make1(np, lp, qdp); /* free()'s qdp */
dtime = time_one;
qdp = (struct depend *)0;
didsomething++;
}
}
np->n_flag |= N_DONE; /* mark as done */
if (quest) /* if 'question up-to-date' */
{ TimeStamp t; /* temp time variable */
t = np->n_time; /* old time of file */
DateStamp(&np->n_time); /* new time of file = current time */
/* cleardynflag(np); */ /* from PAMAKE */
return (cmp_time(&t,&dtime) < 0); /* return comparison */
}
else if (makeall || cmp_time(&np->n_time,&dtime) < 0 && !(np->n_flag & N_DOUBLE))
{
/* here's the actual part that starts commands executing (normally) */
make1(np, (struct line *)0, qdp); /* free()'s qdp */
DateStamp(&np->n_time); /* np's time is now current time */
}
else if (level == 0 && !didsomething)
printf("%s: '%s' is up to date\n", myname, np->n_name);
/* cleardynflag(np); */ /* from PAMAKE */
return 0;
}
/* DJ notes:
Frees all dependancy structures (What good that does, I'm not sure).
Builds a macro called '?' which is the names of all the dependancies.
Then executes each command in np.
*/
make1(np, lp, qdp)
register struct depend *qdp;
struct line *lp;
struct name *np;
{ register struct depend *dp;
if (dotouch) /* if 'touch' flag */
touch(np); /* touch the file */
else
{ strcpy(str1, ""); /* intialize string var */
for (dp = qdp; dp; dp = qdp) /* for each dependancy */
{ if (strlen(str1)) /* if not the first name */
strcat(str1, " "); /* add a space */
strcat(str1, dp->d_name->n_name); /* concatenate the depndancy name */
qdp = dp->d_next; /* address of next dependancy */
free(dp); /* free dependancy */
}
setmacro("?", str1); /* set '?' as name of deps */
setmacro("@", np->n_name); /* and '@' as name of self */
if (lp) /* lp set if doing a :: rule */
docmds1(np, lp); /* do a specific line */
else docmds(np); /* do all lines for that name */
}
}