/* * Do the actual making for make */ #include #ifdef unix #include #include #include #endif #ifdef eon #include #include #endif #ifdef os9 #include #include #include #include #include #endif #ifdef amiga #include #include #include #include #include #include #include #endif #include "h.h" /* * 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 amiga char *av[3], *s, *p; int i; p = s = malloc((unsigned) strlen(string) + 1); strcpy(p, string); /* make a copy of the string */ i = 0; av[0] = gettok(&p); /* get first argument */ av[1] = p; /* get rest of command line */ av[2] = NULL; if (fexecv(av[0], av) == -1) fatal("couldn't execute command '%s', error return %02x\n", av[0], errno); number = wait(); free(s); return number; #endif #ifdef unix return system(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 } /* * 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; #ifdef amiga long SetSignal(); #endif if (*(shell = getmacro("SHELL")) == '\0') #ifdef eon shell = ":bin/esh"; #endif #ifdef unix shell = "/bin/sh"; #endif #ifdef os9 shell = "shell"; #endif #ifdef amiga shell = NULL; #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("\\\n", stdout); } else if (!ssilent) putchar(*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); } } } #ifdef amiga if ((SetSignal(0L, SIGBREAKF_CTRL_D) & SIGBREAKF_CTRL_D) != 0) { fputs("make: abort due to ^D\n", stdout); exit(1); } #endif } } } docmds(np) struct name *np; { register struct line *lp; for (lp = np->n_line; lp; lp = lp->l_next) docmds1(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 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 */ 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 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 eon struct stat info; int fd; 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 = 0L; } 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 os9 struct sgtbuf info; int fd; 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 = 0L; } 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 amiga struct FileInfoBlock *fib; struct Lock *myLock; long ioErr; fib = (struct FileInfoBlock *) malloc((unsigned) sizeof(struct FileInfoBlock)); if ((myLock = Lock(np->n_name, ACCESS_READ)) == NULL) { if ((ioErr = IoErr()) != ERROR_OBJECT_NOT_FOUND) fatal("Can't Lock '%s'; error %3ld", np->n_name, ioErr); np->n_time = 0L; } else if (!Examine(myLock, fib)) { UnLock(myLock); fatal("Can't Examine '%s'; error %3ld", np->n_name, IoErr()); } else { np->n_time = fib->fib_Date.ds_Tick/TICKS_PER_SECOND + 60*fib->fib_Date.ds_Minute + 86400*fib->fib_Date.ds_Days; UnLock(myLock); } free((char *) fib); #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 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 #ifdef amiga struct MsgPort *task; ULONG dateStamp[3]; struct Lock *lock, *plock; UBYTE *pointer; if(!(pointer= (UBYTE *)AllocMem(64L,MEMF_PUBLIC))) fatal("Can't get 64 bytes for pointer"); if(!(task=(struct MsgPort *)DeviceProc(np->n_name))) { printf("%s: can't get MsgPort for '%s'\n", myname, np->n_name); FreeMem((void *) pointer, 64L); return; } if(!(lock = Lock(np->n_name,SHARED_LOCK))) { printf("%s: '%s' not touched - non-existant\n", myname, np->n_name); FreeMem((void *) pointer, 64L); return; } plock = ParentDir(lock); UnLock(lock); strcpy((pointer + 1),np->n_name); *pointer = strlen(np->n_name); dos_packet(task, ACTION_SET_DATE, NULL, plock, (ULONG) &pointer[0] >> 2, (ULONG) DateStamp(dateStamp), 0L, 0L, 0L); UnLock(plock); FreeMem((void *) pointer, 64L); #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 dtime = 1, time(); bool didsomething = 0; if (np->n_flag & N_DONE) return 0; if (!np->n_time) modtime(np); /* Gets modtime of this file */ if (rules) { for (lp = np->n_line; lp; lp = lp->l_next) if (lp->l_cmd) break; if (!lp) dyndep(np); } if (!(np->n_flag & N_TARG) && np->n_time == 0L) fatal("Don't know how to make %s", np->n_name); for (qdp = (struct depend *) 0, 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); 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 = (struct depend *) 0; 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)) { make1(np, (struct line *) 0, qdp); /* free()'s qdp */ time(&np->n_time); } else if (level == 0 && !didsomething) printf("%s: '%s' is up to date\n", myname, np->n_name); return 0; } make1(np, lp, qdp) register struct depend *qdp; struct line *lp; struct name *np; { register struct depend *dp; 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(dp); } setmacro("?", str1); setmacro("@", np->n_name); if (lp) /* lp set if doing a :: rule */ docmds1(np, lp); else docmds(np); } } #ifdef amiga /* * Replace the Aztec-provided time function with one which returns something * easy to find and compare, namely the number of seconds since the Amiga's * reference date. This is the same thing returned by modtime() above. */ time_t time(v) time_t *v; { long t[3]; DateStamp(t); t[0] = t[2]/TICKS_PER_SECOND + 60*t[1] + 86400*t[0]; if (v) *v = t[0]; return t[0]; } #endif