Trailing-Edge
-
PDP-10 Archives
-
SRI_NIC_PERM_FS_1_19910112
-
c/user/make/make.c
There are no other files named make.c in the archive.
/*
* Do the actual making for make
*/
#include "h.h"
#ifdef EON
#include <sys/stat.h>
#include <sys/err.h>
#endif
#ifdef KCC_20
#include <sys/stat.h>
#include <errno.h>
#endif
#ifdef MSC
#include <sys/stat.h>
#include <errno.h>
#endif
#ifdef OS9
#include <time.h>
#include <os9.h>
#include <modes.h>
#include <direct.h>
#include <errno.h>
#endif
#ifdef UNIX
#include <sys/stat.h>
#include <sys/errno.h>
#endif
#ifdef VMS
#include <stat.h>
#include <errno.h>
#endif
/*
* 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;
{
#ifdef EON
int number;
return ((number = execl(shell, shell,"-c", string, 0)) == -1) ?
-1: /* couldn't start the shell */
wait(number); /* return its exit status */
#endif
#ifdef KCC_20
return (system(string));
#endif
#ifdef MSC
return (system(string));
#endif
#ifdef OS9
int number, pid, status;
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
return (system(string));
#endif
#ifdef VMS
return (system(string));
#endif
}
/*
* Do commands to make a target
*/
void
docmd2(np, lp)
NAMEP np;
LINEP lp;
{
bool ssilent;
bool signore;
int estat;
register char * q;
register char * p;
char * shell;
register CMDP cp;
if (*(shell = getmacro("SHELL")) == '\0')
#ifdef EON
shell = ":bin/esh";
#endif
#ifdef KCC_20
shell = "SYSTEM:EXEC.EXE";
#endif
#ifdef MSC
shell = getenv("COMSPEC");
if (shell == (char*)NULL)
shell = "command.com";
#endif
#ifdef OS9
shell = "shell";
#endif
#ifdef UNIX
shell = "/bin/sh";
#endif
#ifdef VMS
shell = "SYS$SYSTEM:DCL.EXE";
#endif
for (cp = lp->l_cmd; cp; cp = cp->c_next)
{
strcpy(str1, cp->c_cmd);
expand(str1);
q = str1;
ssilent = silent;
signore = ignore;
while ((*q == '@') || (*q == '-'))
{
if (*q == '@') /* Specific silent */
ssilent = TRUE;
else /* Specific ignore */
signore = TRUE;
q++; /* Not part of the command */
}
if (!domake)
ssilent = 0;
if (!ssilent)
fputs(" ", stdout);
for (p=q; *p; p++)
{
if (*p == '\n' && p[1] != '\0')
{
*p = ' ';
if (!ssilent)
fputs(MORE, stdout);
}
else if (!ssilent)
putchar((char)*p);
}
if (!ssilent)
putchar('\n');
if (domake)
{ /* Get the shell to execute it */
if ((estat = dosh(q, shell)) != 0)
{
if (estat == -1)
fatal("Couldn't execute %s", shell);
else
{
printf("%s: Error code %d", myname, estat);
if (signore)
fputs(" (Ignored)\n", stdout);
else
{
putchar('\n');
if (!(np->n_flag & N_PREC))
if (unlink(np->n_name) == 0)
printf("%s: `%s' removed.\n", myname, np->n_name);
EXIT(estat);
}
}
}
}
}
}
void
docmds(np)
NAMEP np;
{
register LINEP lp;
for (lp = np->n_line; lp; lp = lp->l_next)
docmd2(np, lp);
}
#ifdef OS9
/*
* Some stuffing around to get the modified time of a file
* in an os9 file system
*/
getmdate(fd, tbp)
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 accurate 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 linear
*/
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
*/
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)
NAMEP np;
{
#ifdef EON
struct stat info;
int fd;
errno = 0; /* clear error code in case of left-over value */
if ((fd = open(np->n_name, 0)) < 0)
{
if (errno != ER_NOTF)
fatal("Can't open %s; error %02x", np->n_name, errno);
np->n_time = (time_t)0;
}
else if (getstat(fd, &info) < 0)
fatal("Can't getstat %s; error %02x", np->n_name, errno);
else
np->n_time = info.st_mod;
close(fd);
#endif
#ifdef KCC_20
struct stat info;
errno = 0; /* clear error code in case of left-over value */
if (stat(np->n_name, &info) < 0)
{
if (errno == 0)
errno = ENOENT; /* KCC doesn't set errno if file does not exist */
if (errno != ENOENT)
fatal("Can't open %s; error %d", np->n_name, errno);
np->n_time = (time_t)0;
}
else
np->n_time = info.st_mtime;
#endif
#ifdef MSC
struct stat info;
errno = 0; /* clear error code in case of left-over value */
if (stat(np->n_name, &info) < 0)
{
if (errno != ENOENT)
fatal("Can't open %s; error %d", np->n_name, errno);
np->n_time = (time_t)0;
}
else
np->n_time = info.st_mtime;
#endif
#ifdef OS9
struct sgtbuf info;
int fd;
errno = 0; /* clear error code in case of left-over value */
if ((fd = open(np->n_name, 0)) < 0)
{
if (errno != E_PNNF)
fatal("Can't open %s; error %02x", np->n_name, errno);
np->n_time = (time_t)0;
}
else if (getmdate(fd, &info) < 0)
fatal("Can't getstat %s; error %02x", np->n_name, errno);
else
np->n_time = cnvtime(&info);
close(fd);
#endif
#ifdef UNIX
struct stat info;
errno = 0; /* clear error code in case of left-over value */
if (stat(np->n_name, &info) < 0)
{
if (errno != ENOENT)
fatal("Can't open %s; error %d", np->n_name, errno);
np->n_time = (time_t)0;
}
else
np->n_time = info.st_mtime;
#endif
#ifdef VMS
struct stat info;
errno = 0; /* clear error code in case of left-over value */
if (stat(np->n_name, &info) < 0)
{ /* stat() in VMS C 2.0 (VMS 4.4) does not set errno, sigh... */
if (errno && (errno != ENOENT))
fatal("Can't open %s; error %d", np->n_name, errno);
np->n_time = (time_t)0;
}
else
np->n_time = info.st_mtime;
#endif
if (debug)
{
fprintf(stderr,"TIME(%s) = %ld\n",np->n_name,(long)np->n_time);
}
}
/*
* Update the mod time of a file to now.
*/
void
touch(np)
NAMEP np;
{
if (!domake || !silent)
printf(" touch(%s)\n", np->n_name);
if (domake)
{
#ifdef EON
char c;
int fd;
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 KCC_20
static int first = 1;
if (first)
printf("touch not implemented for KCC-20 (no utime())\n");
first = 0;
#endif
#ifdef MSC
struct utimbuf a[2];
a[0].modtime = a[1].modtime = time((time_t*)NULL);
if (utime(np->n_name, &a[0]) < 0)
printf("%s: `%s' not touched - non-existant\n",
myname, np->n_name);
#endif
#ifdef OS9
int fd;
/*
* 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
#ifdef UNIX
long a[2];
a[0] = a[1] = time((time_t*)NULL);
if (utime(np->n_name, &a[0]) < 0)
printf("%s: `%s' not touched - non-existant\n",
myname, np->n_name);
#endif
#ifdef VMS
static int first = 1;
if (first)
printf("touch not implemented for VMS (no utime())\n");
first = 0;
#endif
}
}
/*
* Recursive routine to make a target.
*/
int
make(np, level)
NAMEP np;
int level;
{
register DEPENDP dp;
register LINEP lp;
register DEPENDP qdp;
time_t dtime = 1;
bool didsomething = 0;
if (np->n_flag & N_DONE)
return 0;
if (!np->n_time)
modtime(np); /* Gets modtime of this file */
if (debug)
{
fprintf(stderr,"MAKE(%s,%d):\tTIME(%ld)\n",np->n_name,(int)level,
(long)np->n_time);
}
if (rules)
{
for (lp = np->n_line; lp; lp = lp->l_next)
if (lp->l_cmd)
break;
if (!lp)
(void)dyndep(np);
}
if (!(np->n_flag & N_TARG) && np->n_time == (time_t)0)
fatal("Don't know how to make %s", np->n_name);
for (qdp = NULL_DEPENDP, lp = np->n_line; lp; lp = lp->l_next)
{
for (dp = lp->l_dep; dp; dp = dp->d_next)
{
(void)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 (!quest && (np->n_flag & N_DOUBLE) && (np->n_time < dtime))
{
make1(np, lp, qdp); /* free()'s qdp */
dtime = 1;
qdp = NULL_DEPENDP;
didsomething++;
}
}
np->n_flag |= N_DONE;
if (quest)
{
long t;
t = np->n_time;
time(&np->n_time);
return t < dtime;
}
else if (np->n_time < dtime && !(np->n_flag & N_DOUBLE))
{
if (debug)
{
fprintf(stderr,"\tTIME(%ld) < %ld\n",
(long)np->n_time,(long)dtime);
}
make1(np, NULL_LINEP, qdp); /* free()'s qdp */
/* WRONG!! Must not change dependent time to current time. Otherwise target
will always be found older than its dependents.
time(&np->n_time);
Get real modification time instead!! */
modtime(np);
}
else if (level == 0 && !didsomething)
printf("%s: `%s' is up to date\n", myname, np->n_name);
return 0;
}
void
make1(np, lp, qdp)
register DEPENDP qdp;
LINEP lp;
NAMEP np;
{
register DEPENDP dp;
if (debug)
{
fprintf(stderr,"MAKE1(%s):\tTIME(%ld)\tCMD(%s%s)\n",np->n_name,
(long)np->n_time,
((lp != NULL_LINEP) && (lp->l_cmd != NULL_CMDP) &&
(lp->l_cmd->c_cmd != NULL_CHARP)) ? lp->l_cmd->c_cmd : "",
((lp != NULL_LINEP) && (lp->l_cmd != NULL_CMDP) &&
(lp->l_cmd->c_next != NULL_CMDP)) ? " etc." : "");
}
if (dotouch)
touch(np);
else
{
strcpy(str1, "");
for (dp = qdp; dp; dp = qdp)
{
if (strlen(str1))
strcat(str1, " ");
strcat(str1, dp->d_name->n_name);
qdp = dp->d_next;
free((char *)dp);
}
(void)setmacro("?", str1);
(void)setmacro("@", np->n_name);
if (lp) /* lp set if doing a :: rule */
docmd2(np, lp);
else
docmds(np);
}
}