Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/17/84 chuqui version 1.9 3/12/85; site unisoft.UUCP Path: utzoo!watmath!clyde!bonnie!akgua!gatech!seismo!lll-crg!lll-lcc!unisoft!fnf From: fnf@unisoft.UUCP Newsgroups: net.micro.amiga Subject: make for amiga (part 2 of 2) Message-ID: <610@unisoft.UUCP> Date: Wed, 4-Dec-85 20:25:58 EST Article-I.D.: unisoft.610 Posted: Wed Dec 4 20:25:58 1985 Date-Received: Sat, 7-Dec-85 04:14:59 EST Distribution: net Organization: UniSoft Systems, Berkeley Lines: 2237 #--------CUT---------CUT---------CUT---------CUT--------# ######################################################### # # # This is a shell archive file. To extract files: # # # # 1) Make a directory for the files. # # 2) Write a file, such as "file.shar", containing # # this archive file into the directory. # # 3) Type "sh file.shar". Do not use csh. # # # ######################################################### # # echo Extracting macro.c: sed 's/^Z//' >macro.c <<\STUNKYFLUFF Z#include Z#include "make.h" Z Z/* Z * Macro processing Z */ Z Z/* Z * Perform macro substitution from 'orig' to 'dest'. Z * Return number of macro substitutions made. Z * A macro reference is in one of two forms: Z * (macro-name) Z * or Z * Z * "" expands to a single '' Z */ Z Zmexpand (orig, dest, destsiz, macchar) Zchar *orig; Zchar *dest; Zint destsiz; Zchar macchar; Z{ Z register char *s; Z register char *d; Z auto char mname[STRSIZ]; Z register int di; Z register int count; Z /* MACRO *m; */ Z Z DBUG_ENTER ("mexpand"); Z di = count = 0; Z for (s = orig; *s;) { Z if (*s == macchar) { Z if (*++s == macchar) { Z if (di < destsiz - 1) { Z dest[di++] = *s++; Z } Z continue; Z } Z if (!*s) { Z break; Z } Z d = mname; Z if (*s != '(') { Z *d++ = *s++; Z } else { Z for (++s; *s && *s != ')';) { Z *d++ = *s++; Z } Z if (*s != ')') { Z puts ("Missed matching ')'"); Z } else { Z ++s; Z } Z } Z *d = 0; Z if ((d = gmacro (mname)) == NULL) { Z#ifdef VAXVMS || MSDOS Z /* Preserve old behavior. Someone else can remove it */ Z /* if desired. The prefered behavior, at least for */ Z /* unix types, is to simply ignore undefined macros. */ Z /* Fred Fish, 28-Nov-85 */ Z fputs ("Undefined macro: ", stderr); Z fputs (mname, stderr); Z fputc ('\n', stderr); Z#endif Z } else { Z while (*d && di < (destsiz - 1)) { Z dest[di++] = *d++; Z } Z ++count; Z } Z } else if (di < destsiz - 1) { Z dest[di++] = *s++; Z } Z } Z dest[di] = 0; Z DBUG_3 ("mac", "expanded %d macros", count); Z DBUG_RETURN (count); Z} Z Z/* Z * Define a macro. Z * Give the macro called 'name' the string expansion 'def'. Z * Old macro-names are superseded, NOT replaced. Z */ Z Zvoid defmac (name, def) Zchar *name; Zchar *def; Z{ Z register MACRO *m; Z Z DBUG_ENTER ("defmac"); Z DBUG_4 ("mdef", "define macro '%s' to be '%s'", name, def); Z if ((m = (MACRO *) Calloc (1, sizeof (MACRO))) == (MACRO *) NULL) { Z allerr (); Z } Z if ((m -> mname = (char *) Calloc (1, strlen (name) + 1)) == NULL) { Z allerr (); Z } Z if ((m -> mvalue = (char *) Calloc (1, strlen (def) + 1)) == NULL) { Z allerr (); Z } Z strcpy (m -> mname, name); Z strcpy (m -> mvalue, def); Z m -> mnext = mroot; Z mroot = m; Z DBUG_VOID_RETURN; Z} Z Z Z/* Z * undefmac - undefine a macro. Z * Return 0 if macro was successfully undefined, -1 if not found. Z */ Z Zint undefmac (name) Zchar *name; Z{ Z register MACRO *m = mroot; Z register MACRO *prev = (MACRO *) NULL; Z int result = -1; Z extern void free (); Z Z DBUG_ENTER ("undefmac"); Z DBUG_3 ("mundef", "undefine macro '%s'", name); Z while (m != (MACRO *) NULL && !STRSAME (name, m -> mname)) { Z prev = m; Z m = m -> mnext; Z } Z if (m != (MACRO *) NULL) { Z result = 0; Z if (prev == (MACRO *) NULL) { Z mroot = m -> mnext; Z } else { Z prev -> mnext = m -> mnext; Z } Z free (m -> mname); Z free (m -> mvalue); Z free (m); Z } Z DBUG_RETURN (result); Z} Z Z Z/* Z * Lookup a macro called 'name'. Z * Return a pointer to its definition, Z * or NULL if it does not exist. Z */ Z Zchar *gmacro (name) Zchar *name; Z{ Z register MACRO *m; Z register char *def = NULL; Z Z DBUG_ENTER ("gmacro"); Z DBUG_3 ("mname", "look up macro '%s'", name); Z for (m = mroot; m != (MACRO *) NULL; m = m -> mnext) { Z if (STRSAME (name, m -> mname)) { Z def = m -> mvalue; Z DBUG_3 ("mexp", "found expansion '%s'", def); Z break; Z } Z } Z DBUG_RETURN (def); Z} STUNKYFLUFF set `sum macro.c` if test 49948 != $1 then echo macro.c: Checksum error. Is: $1, should be: 49948. fi # # echo Extracting make.c: sed 's/^Z//' >make.c <<\STUNKYFLUFF Z#include Z#include Z#include "make.h" Z Z/* Z * MAKE - Maintain separate source files Z * Z * SYNOPSIS Z * MK [-f file] [-a] [-n] [-d] [-i] [-k] [name] ... Z * f: use 'file' instead of default makefile Z * a: assume all modules are obsolete (recompile everything) Z * n: don't recompile, just list steps to recompile Z * d: debugging (print tree, file info) Z * i: ignore return statuses from execution Z * k: if errors occur, propagate error status up tree; continue. Z * name: module name to recompile Z * Z * AUTHOR Z * Landon M. Dyer, Atari Inc. Z * Z * INCREDIBLY HACKED OVER BY Z * Eric C. Brown University of Utah. Z * Fred Fish, UniSoft Systems Inc (for Commodore AMIGA) Z * Z * HACKS Z * Added object library support (dummy names that inherit dates) Z * Added source library support (real parents) Z * Added direct execution capability. Z * Removed script file. Z * Added support for my macro based debugging package (fnf) Z * Ran through "indent" to change formatting (fnf) Z */ Z Z#define INIT "~INIT" /* initialization macro */ Z#define DEINIT "~DEINIT" /* de-init macro */ Z#define BEFORE "~BEFORE" /* the per-root 'startup' method */ Z#define AFTER "~AFTER" /* the per-root 'wrapup' method */ Z Zchar *mfiles[] = { /* default makefiles */ Z "makefile", Z "Makefile", Z Z#ifdef VAXVMS Z "[-]makefile", Z "sys$login:makefile", Z#endif Z Z#ifdef MSDOS Z "..\makefile", Z#endif Z "" Z}; Z ZMACRO *mroot = (MACRO *) NULL; /* root of macro-list */ ZFILENODE *froot = (FILENODE *) NULL; /* root of filenode-list */ ZFILENODE *firstf = (FILENODE *) NULL; /* the very first filenode */ Z Zchar *modnames[MAXMODS]; /* module-names mentioned in commandline */ Zint execstat = 0; /* nonzero if started executing */ Zint modcount = 0; /* #of module-names */ Zint debug = 0; /* nonzero: turn on debugging */ Zint obsolete = 0; /* nonzero: every file should be recompiled */ Zint noscript = 0; /* nonzero: print methods on stdout */ Zint ignore_errors = 0; /* nonzero: ignore error return codes */ Zint prop_errors = 0; /* nonzero: propagate error status up tree */ ZDATE bigbang; /* a date, the very earliest possible */ ZDATE endoftime; /* a date, the very last possible */ Z Z/* Z * The following are used to save macro definitions given on the Z * command line. In the unix make, it is very common to override Z * a definition in the makefile via a definition on the command line. Z * However, this make expands macros in each line as they are read, Z * which conflicts with the need to wait until the entire file is read Z * before adding command line macros to the table (to override those Z * from the file). Thus the code needs to be modified to delay macro Z * expansions until the last minute, before shipping the line off to Z * be executed. The alternative is to implement a macro locking or Z * precedence scheme. Either solution requires more work than I can Z * do at the moment. Fred Fish 28-Nov-85 Z */ Zchar *cmdmacros[MAXCMDMACS]; /* Macro defs given on command line */ Zint cmdmcount = 0; /* Number of macro defs on command line */ Z Zstatic void fparse (); Zstatic void yankdependents (); Zstatic void addmanydepend (); Zstatic void determ (); Zstatic void recomp (); Z Zmain (argc, argv) Zint argc; Zchar *argv[]; Z{ Z register int arg; Z register int i; Z register char *mfile = NULL; Z extern DATE adate (); Z extern void initrootdates (); Z extern void prtree (); Z Z DBUG_ENTER ("main"); Z ENABLE_ABORT; Z initrootdates (); Z for (arg = 1; arg < argc; ++arg) { Z if (*argv[arg] == '-') { Z switch (tolower (argv[arg][1])) { Z case '#': Z DBUG_PUSH (&argv[arg][2]); Z break; Z case 'f': Z if (++arg >= argc) { Z fputs ("-f needs filename argument.\n", stderr); Z DBUG_RETURN (1); Z } Z mfile = argv[arg]; Z break; Z case 'a': Z obsolete = 1; Z break; Z case 'n': Z noscript = 1; Z break; Z case 'd': Z debug = 1; Z break; Z case 'i': Z ignore_errors = 1; Z break; Z case 'k': Z prop_errors = 1; Z break; Z default: Z fputs ("Unknown switch: ", stderr); Z fputc (argv[arg][1], stderr); Z fputc ('\n', stderr); Z break; Z } Z } else { Z if (strchr (argv[arg], '=') != NULL) { Z if (cmdmcount < MAXCMDMACS) { Z cmdmacros[cmdmcount++] = argv[arg]; Z } else { Z fputs ("Too many command line macros.\n", stderr); Z DBUG_RETURN (1); Z } Z } else { Z if (modcount < MAXMODS) { Z modnames[modcount++] = argv[arg]; Z } else { Z fputs ("Too many module names.\n", stderr); Z DBUG_RETURN (1); Z } Z } Z } Z } Z if (mfile != NULL) { Z if (fmake (mfile) == -1) { Z fputs ("Cannot open makefile '", stderr); Z fputs (mfile, stderr); Z fputs ("'.\n", stderr); Z } Z } else { Z for (i = 0; *mfiles[i]; ++i) { Z if (fmake (mfiles[i]) != -1) { Z break; Z } Z } Z if (!*mfiles[i]) { Z fputs ("Cannot open makefile.\n", stderr); Z } Z } Z if (debug) { Z prtree (); Z } Z DBUG_RETURN (0); Z} Z Z Z/* Z * Construct dependency tree from the makefile 'fn'. Z * Figure out what has to be recompiled, and write a script file to do that. Z */ Z Zfmake (fn) Zchar *fn; Z{ Z FILE * fp; Z Z DBUG_ENTER ("fmake"); Z if ((fp = fopen (fn, "r")) == (FILE *) NULL) { Z DBUG_RETURN (-1); Z } Z fparse (fp); Z determ (); Z fclose (fp); Z DBUG_RETURN (0); Z} Z Z Z/* Z * Parse the input file, defining macros and building the dependency tree. Z */ Z Zstatic void fparse (fp) ZFILE *fp; Z{ Z auto char ibuf[STRSIZ]; Z auto char ebuf[STRSIZ]; Z auto char *strp; Z register char *tok1; Z register char *tok2; Z register char *s; Z extern char *fgets (); Z register FILENODE *lastf = (FILENODE *)NULL; Z extern FILENODE *addfile (); Z extern void defmac (); Z extern void AddToLibrary (); Z extern void escape (); Z extern void addmeth (); Z Z DBUG_ENTER ("fparse"); Z for (;;) { Z if (fgets (ibuf, STRSIZ, fp) == NULL) { Z break; Z } Z DBUG_3 ("inline", "got line '%s'", ibuf); Z mexpand (ibuf, ebuf, STRSIZ, MACCHAR); Z escape (ebuf, COMCHAR); Z s = ebuf + strlen (ebuf) - 1; /* clobber last newline in string */ Z if (s >= ebuf && *s == '\n') { Z *s = '\0'; Z } Z DBUG_3 ("inline2", "after macro and excape processing is '%s'", ebuf); Z if (ebuf[0] == '\t' || ebuf[0] == ' ') { Z DBUG_2 ("meth", "looks like a method line to me"); Z addmeth (lastf, ebuf); Z continue; Z } Z strp = ebuf; Z if ((tok1 = token (&strp)) == NULL) { Z continue; Z } Z if ((tok2 = token (&strp)) != NULL) { Z if (STRSAME (tok2, DEFMAC)) { Z DBUG_2 ("mac", "looks like a macro definition to me"); Z if (*strp) { Z defmac (tok1, strp); Z } Z#if VAXVMS || MSDOS Z /* Preserve old behavior. Unix and amiga behavior is */ Z /* to never undefine any macros, in the sense used here. */ Z /* This also allows macros with null expansions, which */ Z /* are very useful. Fred Fish */ Z if (!*strp) { Z if (undefmac (tok1) < 0) { Z fputs ("Can't undefine macro '", stderr); Z fputs (tok1, stderr); Z fputs ("'.\n", stderr); Z } Z } Z#endif Z continue; Z } else if (STRSAME (tok2, DEPEND)) { Z DBUG_2 ("mac", "looks like a dependency line to me"); Z addmeth (lastf, gmacro (AFTER)); /* terminate last method */ Z lastf = filenode (tok1); /* init lastf */ Z if (firstf == (FILENODE *) NULL) { Z firstf = lastf; Z } Z lastf -> fmake = NULL; Z addmeth (lastf, gmacro (BEFORE)); Z lastf -> fflag |= ROOTP; Z addmanydepend (strp, lastf); Z continue; Z#ifndef FUNNYLIBS Z } else if (STRSAME (tok2, ISLIB)) { Z addmeth (lastf, gmacro (AFTER)); Z lastf = filenode (tok1); Z if (firstf == (FILENODE *) NULL) { Z firstf = lastf; Z } Z lastf -> fmake = NULL; Z addmeth (lastf, gmacro (BEFORE)); Z lastf -> fflag |= LIBRARY; Z lastf -> fflag |= ROOTP; Z Z AddToLibrary (lastf); Z /* no archives here */ Z /* archives and libraries are mutually exclusive */ Z while ((tok1 = token (&strp)) != NULL) { Z (void) addfile (lastf, tok1); Z } Z continue; Z#endif Z } else { Z DBUG_2 ("uh", "what kinda line is this?"); Z addmanydepend (strp, lastf); Z } Z } Z } Z addmeth (lastf, gmacro (AFTER)); Z DBUG_VOID_RETURN; Z} Z Z/* Z * scan tokens from strbuf and search for libraries and archives. Z * libraries look like foo [ bar baz mumble ] Z * archives look like foo ( bar baz mumble ) Z * in either case, bar, baz, and mumble have parents of foo. Z * foo is added to the parentlist, if not already on the list. Z * bar, baz, and mumble are added to the dependency list of depend. Z * the command *cannot* be split across newlines without causing errors. Z * if you don't like that, well, life's a bitch and then you die. Z */ Z Zstatic void addmanydepend (strbuf, depend) Zchar *strbuf; ZFILENODE *depend; Z{ Z register char *tok1; Z register char *tok2; Z register FILENODE *parent; Z register FILENODE *child; Z extern FILENODE *addfile (); Z extern FILENODE *addparent (); Z extern void exit (); Z Z DBUG_ENTER ("addmanydepend"); Z DBUG_4 ("dep", "add dependencies '%s' to '%s'", strbuf, depend -> fname); Z tok1 = token (&strbuf); Z if (tok1 == NULL) { Z DBUG_VOID_RETURN; Z } Z tok2 = token (&strbuf); Z while (tok2 != NULL) { Z#ifdef FUNNYLIBS Z if (STRSAME (tok2, BGNLIB)) { Z parent = addparent (tok1); /* add tok1 to parent list */ Z for (tok1 = token (&strbuf); /* skip over token in tok2 */ Z tok1 != NULL && strcmp (tok1, ENDLIB); /* go eol or end */ Z tok1 = token (&strbuf)) { /* get next token */ Z if (tok1 == NULL) { Z fputs ("MAKE: Error in library defn.\n", stderr); Z exit (2); Z } Z child = addfile (depend, tok1); Z child -> fflag = LIBRARY; Z child -> parent = parent; Z } /* for */ Z tok1 = token (&strbuf); Z tok2 = token (&strbuf); Z continue; /* the while */ Z } /* if islib */ Z#endif Z if (STRSAME (tok2, BGNARC)) { Z parent = addparent (tok1); /* add tok1 to parent list */ Z for (tok1 = token (&strbuf); /* skip over token in tok2 */ Z tok1 != NULL && strcmp (tok1, ENDARC); /* go eol or end */ Z tok1 = token (&strbuf)) { /* get next token */ Z if (tok1 == NULL) { Z fputs ("MAKE: Error in archive defn.\n", stderr); Z exit (2); Z } Z child = addfile (depend, tok1); Z child -> fflag = ARCHIVE; Z child -> parent = parent; Z } /* for */ Z tok1 = token (&strbuf);/* get current token */ Z tok2 = token (&strbuf);/* get lookahead token */ Z continue; /* the while */ Z } /* if isarc */ Z else { /* nothing special -- */ Z (void) addfile (depend, tok1);/* add dependency */ Z tok1 = tok2; /* shift token */ Z tok2 = token (&strbuf); Z } Z } /* while */ Z if (tok2 == NULL && tok1 != NULL) { /* last token = not special */ Z (void) addfile (depend, tok1); Z } Z DBUG_VOID_RETURN; Z} Z Z/* Z * Determine sequence of recompiles from the creation dates. Z * If have anything to recompile, then create a script file full of commands. Z */ Z Zstatic void determ () Z{ Z register FILENODE *f; Z register int i; Z register char *m; Z extern void cleanuparchives (); Z Z DBUG_ENTER ("determ"); Z if (firstf == (FILENODE *) NULL) { /* empty tree */ Z puts ("No changes."); Z DBUG_VOID_RETURN; Z } Z if (modcount == 0) { Z examine (firstf, endoftime); Z } else { Z for (i = 0; i < modcount; ++i) { Z if ((f = gfile (modnames[i])) == (FILENODE *) NULL) { Z fputs ("Don't know how to make ", stderr); Z fputs (modnames[i], stderr); Z fputs (".\n", stderr); Z continue; Z } Z if ((f -> fflag & ROOTP) == 0) { Z fputc ('\'', stderr); Z fputs (f -> fname, stderr); Z fputs ("' is not a root!\n", stderr); Z continue; Z } Z examine (f, endoftime); Z } Z } Z if (execstat) { Z if ((m = gmacro (DEINIT)) != NULL) { Z execute (m, noscript); Z } Z cleanuparchives (); Z } else { Z puts ("No changes."); Z } Z DBUG_VOID_RETURN; Z} Z Z Z/* Z * Examine filenode 'fnd' and see if it has to be recompiled. Z * 'date' is the last-touched date of the node's father Z * (or 'endoftime' if its a root file.) Z * Root files with NO dependencies are assumed not to be up to date. Z */ Z Zexamine (fnd, date) ZFILENODE *fnd; ZDATE date; Z{ Z register int rebuildp = 0; Z register int rval; Z register int errcode = 0; Z register NODE *n; Z extern void getdate (); Z extern char *printdate (); Z Z DBUG_ENTER ("examine"); Z DBUG_3 ("ex", "parent node date '%s'", printdate (date)); Z DBUG_3 ("ex", "examine node '%s'", fnd -> fname); Z getdate (fnd); Z DBUG_3 ("ex", "modification date '%s'", printdate (fnd -> fdate)); Z DBUG_3 ("ex", "parent node date '%s'", printdate (date)); Z if (fnd -> fnode == (NODE *) NULL && fnd -> fflag & ROOTP) { Z DBUG_2 ("root", "node, is rootnode with no dependents, rebuild"); Z rebuildp = 1; Z } else { /* see if dependents need to be recompiled */ Z for (n = fnd -> fnode; n != (NODE *) NULL; n = n -> nnext) { Z if ((rval = examine (n -> nfile, fnd -> fdate)) != 0) { Z if (rval == ERROR) { Z errcode = ERROR;/* if error occurred, propagate up */ Z fnd -> fflag |= ERROR; Z fputs ("Couldn't remake ", stderr); Z fputs (fnd -> fname, stderr); Z fputs (" because of errors.\n", stderr); Z } Z rebuildp = 1; Z } Z } Z } Z DBUG_3 ("ex", "parent node date '%s'", printdate (date)); Z DBUG_3 ("rebuildp", "rebuild flag is %d", rebuildp); Z /* if ancestor recompiled or root, recompile, */ Z /* but not if error in ancestor */ Z if (rebuildp && (fnd -> fflag & ERROR) == 0) { Z DBUG_3 ("rebuild", "'%s' needs remaking", fnd -> fname); Z recomp (fnd); Z if (fnd -> fflag & ERROR) { Z DBUG_3 ("err", "got an error remaking %s", fnd -> fname); Z DBUG_RETURN (ERROR); Z } Z } Z DBUG_3 ("ex", "current node date now '%s'", printdate (fnd -> fdate)); Z DBUG_3 ("ex", "parent node date '%s'", printdate (date)); Z if (obsolete || laterdt (fnd -> fdate, date) >= 0) { Z DBUG_2 ("date", "looks like parent needs remaking now"); Z rebuildp = 1; Z } Z if (errcode) { Z DBUG_RETURN (errcode); Z } else { Z DBUG_RETURN (rebuildp); Z } Z} Z Z/* Z * Make sure a filenode gets recompiled. Z */ Z Zstatic void recomp (f) ZFILENODE *f; Z{ Z register char *m; Z Z DBUG_ENTER ("recomp"); Z if (!execstat) { Z execstat = 1; Z if ((m = gmacro (INIT)) != NULL) { Z execute (m, noscript); Z } Z } Z if (f -> fflag & REBUILT) { Z DBUG_VOID_RETURN; Z } Z if (!noscript) { /* don't extract if printing steps */ Z yankdependents (f); Z } Z if (f -> fmake != NULL) { Z if (execute (f -> fmake, noscript) != 0) { Z if (!ignore_errors && !prop_errors) { Z exit (2); Z } else if (prop_errors) { Z f -> fflag |= ERROR; Z } Z } Z } Z f -> fflag |= REBUILT; Z DBUG_VOID_RETURN; Z} Z Zstatic void yankdependents (fnd) ZFILENODE *fnd; Z{ Z register NODE *n; Z extern int extract (); Z Z DBUG_ENTER ("yankdependents"); Z for (n = fnd -> fnode; n != (NODE *) NULL; n = n -> nnext) { Z#ifdef YANKDESCENDANTS Z yankdependents (n -> nfile); Z#endif Z DBUG_3 ("dep", "yanking %s", n -> nfile -> fname); Z DBUG_3 ("dep", "flags %d", n -> nfile -> fflag); Z if ((n -> nfile -> fflag & ARCHIVE) && ((n -> nfile -> fflag & EXTRACT) == 0)) { Z /* if archived and not extracted */ Z fputs ("Extracting ", stdout); Z puts (n -> nfile -> fname); Z if (!noscript) { Z#ifdef LAR Z if (extract (n -> nfile) == FAILURE) { Z fputs ("Extract failed -- I think I'll die now.\n", stderr); Z exit (1); Z } Z#else Z fputs ("No support for archives, bye!\n", stderr); Z exit (1); Z#endif Z } Z n -> nfile -> fflag |= EXTRACT; Z } Z } Z DBUG_VOID_RETURN; Z} Z Z/* Z * Complain about being out of memory, and then die. Z */ Z Zallerr () Z{ Z fputs ("Can't alloc -- no space left (I give up!)\n", stderr); Z exit (1); Z} STUNKYFLUFF set `sum make.c` if test 20207 != $1 then echo make.c: Checksum error. Is: $1, should be: 20207. fi # # echo Extracting make.h: sed 's/^Z//' >make.h <<\STUNKYFLUFF Z/* #define VAXVMS 1 */ /* uncomment for VAX/VMS */ Z/* #define MSDOS 1 */ /* uncomment for MSDOS */ Z Z/* NOTE: other two supported systems, "unix" and "AMIGA" have these symbols */ Z/* built into the preprocessor. Redefining them may cause problems, or at */ Z/* least irritating warning messages. */ Z Z#if VAXVMS Z# define ESCCHAR `\\` /* ok to use backslash on VMS */ Z#endif Z Z#ifdef MSDOS Z# define ESCCHAR '`' /* since pathname char is backslash (yech) */ Z#endif Z Z#if unix || AMIGA Z# define ESCCHAR '\\' Z#endif Z Z#define EOS '\000' /* End of string character */ Z Z#define MACCHAR '$' /* macro-definition char */ Z#define COMCHAR '#' /* comment char */ Z#define DEFMAC "=" /* macro-definition token */ Z#define DEPEND ":" /* dependency-definition token */ Z Z#ifdef FUNNYLIBS Z# define BGNLIB "[" /* start library token */ Z# define ENDLIB "]" /* end library token */ Z#else Z# define ISLIB "|" /* Library definition token */ Z#endif Z Z#define BGNARC "(" /* start archive token */ Z#define ENDARC ")" /* end archive token */ Z Z#define DEBUG (0) Z#define STRSIZ (1024) /* Size of input buffer */ Z#define MAXMODS (50) /* Max number of targets on command line */ Z#define MAXCMDMACS (16) /* Max number of macro defs on command line */ Z Z#if DEBUG Z# define NOREALEXECUTE /* if set, don't really execute commands */ Z# define NOREALEXTRACT /* if set, don't really extract files */ Z# define NOREALDELETE /* if set, don't really delete files */ Z#endif Z Z#define SUCCEED (0) Z#define FAILURE (-1) Z Z/* file attributes */ Z Z#define REBUILT 0x01 /* file has been reconstructed */ Z#define ROOTP 0x02 /* file was named on left side of DEPEND */ Z#define LIBRARY 0x04 /* file is library; inherit parent's time */ Z#define ARCHIVE 0x08 /* file is archive; search through parent */ Z /* archive directory for time */ Z#define EXTRACT 0x10 /* extract from archive when rebuilding */ Z#define ERROR 0x20 /* error occurred while rebuilding */ Z Z#ifdef VAXVMS Zstruct date_str { Z unsigned ds_low; Z unsigned ds_high; Z}; Ztypedef struct date_str *DATE; Z#endif Z Z#ifdef MSDOS Z# ifndef FA_ARCH Z# include Z# endif Z typedef struct ftime *DATE; Z#endif Z Z#ifdef unix Z typedef long *DATE; Z#endif Z Z#ifdef AMIGA Z# include Z typedef struct DateStamp *DATE; Z#endif Z Z#ifdef DBUG Z# include Z#else Z# define DBUG_ENTER(a1) Z# define DBUG_RETURN(a1) return(a1) Z# define DBUG_VOID_RETURN return Z# define DBUG_EXECUTE(keyword,a1) Z# define DBUG_2(keyword,format) Z# define DBUG_3(keyword,format,a1) Z# define DBUG_4(keyword,format,a1,a2) Z# define DBUG_5(keyword,format,a1,a2,a3) Z# define DBUG_PUSH(a1) Z# define DBUG_POP() Z# define DBUG_PROCESS(a1) Z# define DBUG_FILE (stderr) Z# define DBUG_SETJMP setjmp Z# define DBUG_LONGJMP longjmp Z#endif Z Zstruct node { Z struct filenode *nfile; /* this node's file */ Z struct node *nnext; /* the next node */ Z}; Ztypedef struct node NODE; Z Z Zstruct filenode { Z char *fname; /* the filename */ Z char *fmake; /* remake string for file */ Z DATE fdate; /* last modification date */ Z NODE *fnode; /* files this file depends on */ Z char fflag; /* magic flag bits */ Z struct filenode *parent; /* pointer to parent for archives,libraries */ Z struct filenode *fnext; /* the next file */ Z}; Ztypedef struct filenode FILENODE; Z Z Zstruct macro { Z char *mname; /* the macro's name */ Z char *mvalue; /* the macro's definition */ Z struct macro *mnext; /* the next macro */ Z}; Ztypedef struct macro MACRO; Z Z Zextern long *Calloc (); /* Private gateway to system calloc() */ Zextern MACRO *mroot; Zextern FILENODE *froot; Zextern DATE bigbang; /* Far, far in the past */ Zextern DATE endoftime; /* Far, far in the future */ Zchar *gmacro (); ZFILENODE *gfile (); ZFILENODE *filenode (); Zchar *token (); Z Z#if unix || AMIGA Z# define _open open Z# define _close close Z# define _read read Z# define _write write Z#endif Z Z/* Z * On the Amiga, we must do an explicit check for an abort at various Z * places of interest. To avoid #ifdefs all through the code, define Z * some macros that just expand to null on other systems. Z * Z */ Z Z#ifdef AMIGA Z void Check_Abort (); Z extern int Enable_Abort; /* Enable abort on CNTL-C */ Z# define ENABLE_ABORT (Enable_Abort = 1) Z# define DISABLE_ABORT (Enable_Abort = 0) Z# define CHECK_ABORT Check_Abort(); Z#else Z# define CHECK_ABORT /* Null expansions */ Z# define ENABLE_ABORT Z# define DISABLE_ABORT Z#endif /* AMIGA */ Z Z/* Z * Some useful macros to make things slightly less error prone. Z */ Z Z#define STRSAME(a,b) (strcmp(a,b)==0) /* Strings are the same */ Z STUNKYFLUFF set `sum make.h` if test 05045 != $1 then echo make.h: Checksum error. Is: $1, should be: 05045. fi # # echo Extracting make.man: sed 's/^Z//' >make.man <<\STUNKYFLUFF ZMAKE(I) 3/10/84 MAKE(I) Z Z Z ZNAME Z MAKE - maintain multiple source files (VAX/VMS and MSDOS 2.0) Z Z ZSYNOPSIS Z MAKE [-N] [-A] [-D] [-I] [-K] [-F makefile] [name ...] Z Z ZDESCRIPTION Z MAKE is a utility inspired by the Unix(tm) command of the same Z name. MAKE helps maintain programs that are constructed from Z many files. MAKE processes a "makefile", a file which describes Z how to build a program from its source files, and produces a Z script file containing the commands necessary to recompile the Z program. Z Z Be careful: this MAKE is NOT compatible with Unix(tm) MAKE! Z Z The 'N' option causes MAKE to print out the steps it would follow Z in order to rebuild the program. The 'A' option tells MAKE to Z assume that all files are obsolete, and that everything should be Z recompiled. The 'I' option tells MAKE to ignore any error statuses Z returned when MAKE executes a program. The 'K' option tells MAKE Z to continue compiling anything that does not depend on an entry Z that had an error during the compilation. The 'F' option, followed Z by a filename, can be used to specify a makefile other than the Z default one. Z Z If no names are specified in the commandline, the first dependency Z in the makefile is examined. Otherwise, the specified root names Z are brought up to date. Z Z The default makefiles are: Z Z for VAX/VMS: MAKEFILE Z [-]MAKEFILE Z SYS$LOGIN:MAKEFILE Z Z for MSDOS: MAKEFILE Z ..\MAKEFILE Z Z If the first makefile cannot be found, MAKE attempts to use the Z next one. If no makefile is ever found, MAKE prints a diagnostic Z and aborts. Z ZTHE MAKEFILE Z Comments begin with '#' and extend to the end of the line. A Z '#' (or almost any other character) may be escaped with the escape Z character (backslash (\) on VMS, backquote (`) on MSDOS). An escape Z character may be typed by doubling it (\\ or ``). The standard Z Unix escape codes are recognized (\n, \r, \t, \b, \f, `n, `r, `t, Z `b and `f). Z Z A makefile is a list of dependencies and library definitions. A Z dependency consists of a root name, a colon, and zero or more names Z of dependent files. (The colon MUST be preceeded by whitespace.) Z For instance, in: Z Z make.exe : make.obj parsedir.obj file.obj macro.obj mk.h Z Z the file 'make.exe' depends on five other files. A library definition Z consists of a root name, a vertical bar (|), and zero or more names of Z library entry points. (The vertical bar MUST be preceded by Z whitespace.) For instance, in: Z Z ibm.lib | ibmtext ibmsound ibmkeys ibmser ibm_com Z Z the file 'ibm.lib' has five entry points. Library definitions are Z useful for updating libraries without maintaining copies of the object Z files for the source files. The library entry points have the same Z date and time as the library itself, and so if the entry depend on the Z proper source files, all modified source files will be recompiled Z whenever necessary. Z Z A dependent file may be a member of an ARCHIVE. An ARCHIVE is a Z collection of files with date and time stamps. An example of an Z archive definition is: Z Z make.obj : make.lar ( make.c make.h ) Z Z In this definition, make.c and make.h are members of the archive Z make.lar. If make.obj must be rebuilt and either make.c or make.h Z is not found in the current directory, they will be copied out of Z the archive, compiled, and deleted at the end of the make session. Z Z Archive definitions are meaningless in a library definition, and so Z should not be used. Z Z A root name with an empty dependency, as in: Z Z print : Z Z is assumed NEVER up to date, and will always be recompiled. Z Z The dependency list or library definition may be continued on Z successive lines: Z Z bigfile.exe : one.obj two.obj three.obj four.obj Z five.obj six.obj gronk.obj freeple.obj scuzzy.lnk Z frog.txt greeble.out Z Z OR Z Z msdos.lib | alloc char_io disk_io file_io exec filesize Z freedisk freemem insert mouse port_io randg syscall Z sysclock sysint textsf timer ttime ucsd ucsdhelp unix Z Z Any number of 'method' lines may follow a dependency. Method lines Z begin with an ascii tab. When a file is to be rebuilt, MAKE Z executes these method lines (minus the tab). Z For example, in: Z Z make.exe : make.obj parsedir.obj file.obj macro.obj mk.h Z $link make, parsedir, file, macro Z $write sys$output "Just another version of MAKE ..." Z $purge Z Z the three lines following the dependency make up the method for Z recompiling (or in this case, re-linking) the file 'make.exe'. Z Z Library definitions may have method lines. These methods will Z *always* be executed, since the entry points have the same date Z as the library. Z Z If the macro "~INIT" is defined, its text will be executed first. Z If the macro "~DEINIT" is defined, its text will be executed last. Z By defining these two macros, it is possible to configure the shell Z enviroment: Z Z ~INIT = $set term/nowrap\n$on error then goto err_handler Z ~DEINIT = $set term/wrap\n$exit\$err_handler:\n Z ~DEINIT = #(~DEINIT)$type err.log\n$exit Z Z will be executed as: Z Z $set term/nowrap Z $on error then goto err_handler Z . Z . Z $set term/wrap Z $exit Z $err_handler: Z $type err.log Z $exit Z Z When a root's method is defined, the value of the macro "~BEFORE" Z is prefixed to the method, and the value of the macro "~AFTER" is Z appended to it. Z Z Frequently one wants to maintain more than one program with a single Z makefile. In this case, a "master dependency" can appear first in Z the file: Z Z allOfMyToolsAndHorribleHacks : cat peek poke.exe grunge Z cat : cat.exe Z cat.exe : .... Z (stuff for CAT.EXE) Z peek : peek.exe Z peek.exe : (stuff for PEEK.EXE) Z poke.exe : (stuff for POKE.EXE) Z grunge : grunge.com Z grunge.com : (stuff for grung) Z Z In other words, make will bring everything up to date that is somehow Z connected to the first dependency (its assumed that the incredibly Z lengthy filename specified in this example won't actually exist). Z ZMACROS Z A macro is defined by a line of the form (the '=' MUST be surrounded Z by whitespace): Z Z = Z Z A macro may be deleted by assigning an empty value to it. Macros Z may be redefined, but old definitions stay around. If a macro is Z redefined, and the redefinition is later deleted, the first definition Z will take effect: Z Z MAC = first ! MAC = "first" Z MAC = second ! MAC = "second" Z MAC = #(MAC) third ! MAC = "second third" Z MAC = ! MAC = "second" Z MAC = ! MAC = "first" Z MAC = ! MAC has no definition Z Z A macro may be referenced in two ways: Z Z # or #(macro-name) Z Z The first way only works if the macro's name is a single character. Z If the macro's name is longer than one character, it must be Z enclosed in parenthesis. ['#' may be escaped by doubling it ("##".)] Z For example, in: Z Z G = mk.h mk1.h Z OBJS = make.obj file.obj parsedir.obj macro.obj Z BOTH = #(OBJS) #G Z Z make.exe : #(OBJS) #G Z make.exe : #(BOTH) Z make.exe : mk.h mk1.h make.obj file.obj parsedir.obj macro.obj Z $write sys$output "This is a number sign --> ##" Z Z after macro expansion, the three dependencies will appear identical Z and the two '#'s in the last line will turn into one '#'. Z ZUNIX(tm) MAKE AND THIS ONE Z They are NOT the same. Do not expect Unix makefiles to work with Z this MAKE, even if you change the pathnames. There are some major Z differences between this version and the standard Unix(tm) MAKE: Z Z 1. The Unix(tm) comment character is '#', VAX/VMS's is '!'. Z Z 2. The Unix(tm) macro-expansion character is '$'. While this would Z have been easy to leave the same, the '$' character is used so Z often in VAX/VMS command-lines that I thought it best to change Z it to '#'. Z Z 3. Multiple root names are not allowed. Unix(tm) MAKE accepts lines Z of the form: Z Z name1 name2 : depend1 depend2 Z Z but this one doesn't. Z Z 4. There is no equivalent of double-colon ("::".) Z Z 5. There is no equivalent of .SUFFIXES, or the corresponding special Z macros. Z ZSAMPLE MAKEFILE Z ! Z ! VAX/VMS MAKE Z ! Landon Dyer Z ! Z H = make.h Z FILES = #H, make.c, macro.c, token.c, parsedir.c, file.c Z DOCUMENTATION = distr.mem make.man makefile. make.com Z Z make.exe : make.obj macro.obj token.obj parsedir.obj file.obj Z $link make.obj, macro, token, parsedir, file Z $purge Z Z make.obj : make.c #H Z $cc make.c Z Z macro.obj : macro.c #H Z $cc macro Z Z token.obj : token.c #H Z $cc token Z Z parsedir.obj : parsedir.c #H Z $cc parsedir Z Z file.obj : file.c Z $cc file Z Z ! Z ! Print files associated with MAKE Z ! Z print : Z $print make.man, #(FILES), make.com, makefile. Z Z ! Z ! Type out source to MAKE Z ! Z type : Z $type #(FILES), make.com, makefile. Z Z ! Z ! Make backup of source files. Z ! Z BACKUP = [.bak] Z backup : Z $copy #(FILES) #(BACKUP) Z $copy make.man, make.com, makefile. #(BACKUP) Z Z ! Z ! Collect MAKE into a distribution file. Z ! Z collect : Z $collect collect distr.mem make.man makefile make.com make.h - Z make.c macro.c token.c parsedir.c file.c Z Z ZAUTHOR Z Landon Dyer G.DYER@SU-SCORE.ARPA Z 175 Calvert Dr. #F-211 BASHFL::DYER (Atari Coinop) Z Cupertino, CA 95014 Z ZMODIFIED BY Z Eric C. Brown brownc@utah-cs.arpa Z 1302 Austin Hall ...!harpo!utah-cs!brownc Z University of Utah, SLC, UT 84112 STUNKYFLUFF set `sum make.man` if test 17762 != $1 then echo make.man: Checksum error. Is: $1, should be: 17762. fi # # echo Extracting osdate.c: sed 's/^Z//' >osdate.c <<\STUNKYFLUFF Z/* Z; OSDATE - return file's creation-date (called from Lattice), or -1 Z; if can't find the file. Z; Synopsis: Z; int osdate(filename, time1, time2) Z; char *filename; Z; int *time1, *time2; Z; Z*/ Z Z#include "lar.h" Z#define FILERR (-1) Z#include "make.h" Z Zstatic void getftime (); Zextern char *printdate (); Z ZDATE osdate (filename, success) Zchar *filename; Zint *success; Z{ Z extern DATE adate (); Z auto DATE newdate; Z#ifndef AMIGA Z register int handle; Z#endif Z Z DBUG_ENTER ("osdate"); Z#ifdef AMIGA Z newdate = adate (); Z getftime (filename, newdate, success); Z#else Z if ((handle = _open (filename, O_RDONLY)) == FILERR) { Z *success = FAILURE; Z newdate = (DATE) NULL; Z } else { Z newdate = adate (); Z getftime (handle, newdate); Z _close (handle); Z *success = SUCCEED; Z } Z#endif Z DBUG_RETURN (newdate); Z} Z Zstruct ludir ldir[MAXFILES]; Zint nslots; Zextern char *getname (); Z ZDATE getarchdate (archname, filename) Zchar *archname; Zchar *filename; Z{ Z register fildesc lfd; Z register int i; Z register struct ludir *lptr; Z union timing { Z DATE ftimeptr; Z long *longptr; Z } unionptr; Z extern DATE adate (); Z auto DATE newdate; Z register char *realname; Z extern void cant (); Z Z DBUG_ENTER ("getarchdate"); Z DBUG_4 ("ard", "looking for %s inside %s", filename, archname); Z if ((lfd = _open (archname, O_RDONLY)) == FILERR) { Z cant (archname); Z } Z getdir (lfd); Z for (i = 1, lptr = ldir + 1; i < nslots; i++, lptr++) { Z if (lptr -> l_stat != ACTIVE) { Z continue; Z } Z realname = getname ((char *) lptr -> l_name, (char *) lptr -> l_ext); Z if (strcmp (realname, filename) != 0) { Z continue; Z } Z DBUG_3 ("ard", "found name %s", realname); Z DBUG_3 ("ard", "time %lx", lwtol (lptr -> l_datetime)); Z newdate = adate (); Z unionptr.ftimeptr = newdate; Z *(unionptr.longptr) = lwtol (lptr -> l_datetime); Z break; Z } Z (void) _close (lfd); Z DBUG_3 ("ard", "date is %s", printdate (newdate)); Z DBUG_RETURN (newdate); Z} Z Z#ifdef LAR Zcopyfile (archname, filename) Zchar *archname; Zchar *filename; Z{ Z register int i; Z register struct ludir *lptr; Z register fildesc lfd; Z register fildesc ofd; Z union timer timeunion; Z extern int errno; Z register char *realname; Z auto char outname[64]; Z register char *tmpptr; Z extern char *strrchr (); Z extern void cant (); Z Z DBUG_ENTER ("copyfile"); Z DBUG_4 ("cpf", "looking for %s inside %s", filename, archname); Z if ((lfd = _open (archname, O_RDWR)) == FILERR) { Z cant (archname); Z } Z getdir (lfd); Z for (i = 1, lptr = &ldir[1]; i < nslots; i++, lptr++) { Z if (lptr -> l_stat != ACTIVE) { Z continue; Z } Z realname = getname (lptr -> l_name, lptr -> l_ext); Z if (strcmp (realname, filename) != 0) { Z continue; Z } Z /* generate real filename */ Z tmpptr = strrchr (archname, '/'); /* should be path chr */ Z if (tmpptr != NULL) { Z i = (int) (tmpptr - archname); Z i++; Z DBUG_3 ("tmpptr", "tmpptr was not NULL; i is %d", i); Z strncpy (outname, archname, i); Z } else { Z DBUG_2 ("tmpptr", "tmpptr was NULL"); Z i = 0; Z *outname = '\0'; Z } Z strcat (outname, realname); Z DBUG_3 ("outn", "got it; about to extract %s", outname); Z ofd = _creat (outname, 0); Z if (ofd == FILERR) { Z fputs (outname, stderr); Z fputs (" - can't create\n", stderr); Z DBUG_VOID_RETURN; Z } else { Z (void) lseek (lfd, (long) lwtol (lptr -> l_off), 0); Z acopy (lfd, ofd, lwtol (lptr -> l_len)); Z timeunion.realtime = lwtol (lptr -> l_datetime); Z if (ofd != fileno (stdout)) { Z (void) setftime (ofd, &(timeunion.ftimep)); Z (void) _close (ofd); Z } Z break; /* exit after copy */ Z } Z } Z (void) _close (lfd); Z DBUG_VOID_RETURN; Z} Z Zstatic void acopy (fdi, fdo, nbytes) /* copy nbytes from fdi to fdo */ Zfildesc fdi; Zfildesc fdo; Zlong nbytes; Z{ Z register int btr; Z register int retval; Z char blockbuf[BLOCK]; Z Z for (btr = (nbytes > BLOCK) ? BLOCK : (int) nbytes; btr > 0; Z nbytes -= BLOCK, btr = (nbytes > BLOCK) ? BLOCK : (int) nbytes) { Z if ((retval = _read (fdi, blockbuf, btr)) != btr) { Z if (retval == 0) { Z error ("Premature EOF\n"); Z } Z if (retval == FILERR) { Z error ("Can't read"); Z } Z } Z if ((retval = _write (fdo, blockbuf, btr)) != btr) { Z if (retval == FILERR) { Z error ("Write Error"); Z } Z } Z } Z} Z#endif /* LAR */ Z Z#ifdef unix Z#include Z#include Z Zstatic void getftime (handle, date) Zint handle; ZDATE date; Z{ Z struct stat statb; Z Z DBUG_ENTER ("getftime"); Z fstat (handle, &statb); Z *date = statb.st_mtime; Z DBUG_3 ("date", "got date %lu", *date); Z DBUG_VOID_RETURN; Z} Z#endif Z Z#ifdef AMIGA Z#include Z#include Z Zstatic void getftime (filename, date, success) Zchar *filename; ZDATE date; Zint *success; Z{ Z struct FileInfoBlock *fib; Z struct FileLock *lockp; Z int status = FAILURE; Z extern struct FileLock *Lock (); Z Z DBUG_ENTER ("getftime"); Z lockp = Lock (filename, ACCESS_READ); Z if (lockp != NULL) { Z fib = (struct FileInfoBlock *) Calloc (1, sizeof (struct FileInfoBlock)); Z DBUG_3 ("fib", "fib = %x", fib); Z if (fib == NULL) { Z allerr (); Z } else { Z if (Examine (lockp, fib)) { Z DBUG_3 ("date", "file '%s'", filename); Z DBUG_3 ("date", "date is %s", printdate (&(fib -> fib_Date))); Z date -> ds_Days = fib -> fib_Date.ds_Days; Z date -> ds_Minute = fib -> fib_Date.ds_Minute; Z date -> ds_Tick = fib -> fib_Date.ds_Tick; Z status = SUCCEED; Z } else { Z fprintf (stderr, "Examine() failed!\n"); Z } Z free (fib); Z UnLock (lockp); Z } Z } Z *success = status; Z DBUG_VOID_RETURN; Z} Z#endif STUNKYFLUFF set `sum osdate.c` if test 50612 != $1 then echo osdate.c: Checksum error. Is: $1, should be: 50612. fi # # echo Extracting parsedir.c: sed 's/^Z//' >parsedir.c <<\STUNKYFLUFF Z#include Z#include "make.h" Z Z#ifdef VAXVMS Z# include Z#endif Z Zextern DATE bigbang; Zextern DATE endoftime; Z Zchar *printdate (); Z Z/* Z * Get a file's creation date. Z * Z * First try for a normal file, then library, then archive. Z */ Z Zvoid getdate (f) ZFILENODE *f; Z{ Z extern int isonlibrary (); Z extern int isanarchive (); Z Z DBUG_ENTER ("getdate"); Z if (f -> fdate == (DATE) NULL) { Z if (filedate (f) != SUCCEED) { Z if (isonlibrary (f) != SUCCEED) { Z if (isanarchive (f) != SUCCEED) { Z if ((f -> fflag & ROOTP) == 0) { Z fprintf (stderr, "Can't get date for file '%s'\n", Z f -> fname); Z f -> fdate = endoftime; Z } else { Z f -> fdate = bigbang; Z } Z } Z } Z } Z } Z DBUG_VOID_RETURN; Z} Z Z Z#ifdef VAXVMS Z/* Z * filedate - return file's creation date (VAX/VMS only.) Z * Returns -1 if file cannot be found, 0 if succesful. Z */ Zfiledate (fnd) ZFILENODE *fnd; Z{ Z register unsigned *datetime; Z static DATE adate (); Z register struct FAB *fptr; Z register struct XABDAT *dptr; Z Z fptr = Calloc (1, sizeof (struct FAB)); /* allocate FAB and XABDAT */ Z dptr = Calloc (1, sizeof (struct XABDAT)); Z if (fptr == NULL || dptr == NULL) { Z allerr (); Z } Z *fptr = cc $ rms_fab; /* initialize FAB and XABDAT */ Z *dptr = cc $ rms_xabdat; Z fptr -> fab $ l_xab = (char *) dptr;/* FAB -> XABDAT */ Z fptr -> fab $ l_fna = fnd -> fname;/* setup filename */ Z fptr -> fab $ b_fns = strlen (fnd -> fname); Z if (sys$open (fptr) != RMS$_NORMAL || /* open the file */ Z sys$display (fptr) != RMS$_NORMAL) { /* get XABDAT info */ Z return (-1) Z } Z datetime = &(dptr -> xab$q_cdt); /* record 64-bit date */ Z fnd -> fdate = adate (datetime[0], datetime[1]); Z sys$close (fptr); /* close the file */ Z free (dptr); /* clean up and return */ Z free (fptr); Z return (0); Z} Z Z/* Z * laterdt - compare two dates. Z * Return -1, 0 or 1 if date1 < date2, date1 == date2, or date1 > date2 Z */ Z Zlaterdt (date1, date2) ZDATE date1, date2; Z{ Z if (date1 -> ds_high > date2 -> ds_high || Z (date1 -> ds_high >= date2 -> ds_high && Z date1 -> ds_low > date2 -> ds_low)) { Z return (1); Z } else if (date1 -> ds_high == date2 -> ds_high && Z date1 -> ds_low == date2 -> ds_low) Z return (0); Z } else { Z return (-1); Z } Z} Z Z Z/* Z * adate - allocate a date with the given time Z */ Z ZDATE adate (time1, time2) Zunsigned time1; Zunsigned time2; Z{ Z auto DATE d; Z Z if ((d = (DATE) Calloc (1, sizeof (struct date_str))) == NULL) { Z allerr (); Z } Z d -> ds_low = time1; Z d -> ds_high = time2; Z return (d); Z} Z Zinitrootdates () Z{ Z bigbang = adate (0, 0); /* init root dates */ Z endoftime = adate (~0, ~0); Z} Z Zchar *printdate (fdate) ZDATE fdate; Z{ Z static char *buffer[64]; Z Z sprintf (buffer, "( %u, %u )", Z (f -> fdate != NULL) ? (f -> fdate) -> ds_high : 0, Z (f -> fdate != NULL) ? (f -> fdate) -> ds_low : 0); Z return (buffer); Z} Z#endif Z Z Z#ifdef MSDOS Z Z/* Z * filedate - return file's creation date (MSDOS only.) Z * Returns -1 if file cannot be found, 0 if successful Z */ Z Zfiledate (fnd) ZFILENODE *fnd; Z{ Z extern DATE osdate (); Z auto DATE newdate; Z auto int success; Z Z success = FAILURE; Z newdate = osdate (fnd -> fname, &success); Z if (success == FAILURE) { Z return (FAILURE); Z } Z fnd -> fdate = newdate; Z fnd -> fflag |= EXTRACT; /* don't extract this file again */ Z return (SUCCEED); Z} Z Z/* Z * laterdt - compare two dates. Z * Return -1, 0 or 1 if date1 < date2, date1 == date2, or date1 > date2 Z */ Z Zlaterdt (date1, date2) ZDATE date1; ZDATE date2; Z{ Z if (date1 -> ft_year > date2 -> ft_year) { Z return (1); Z } Z if (date1 -> ft_year < date2 -> ft_year) { Z return (-1); Z } Z /* years are equal */ Z if (date1 -> ft_month > date2 -> ft_month) { Z return (1); Z } Z if (date1 -> ft_month < date2 -> ft_month) { Z return (-1); Z } Z /* months are equal */ Z if (date1 -> ft_day > date2 -> ft_day) { Z return (1); Z } Z if (date1 -> ft_day < date2 -> ft_day) { Z return (-1); Z } Z /* days are equal */ Z if (date1 -> ft_hour > date2 -> ft_hour) { Z return (1); Z } Z if (date1 -> ft_hour < date2 -> ft_hour) { Z return (-1); Z } Z /* hours are equal */ Z if (date1 -> ft_min > date2 -> ft_min) { Z return (1); Z } Z if (date1 -> ft_min < date2 -> ft_min) { Z return (-1); Z } Z /* minutes are equal */ Z if (date1 -> ft_tsec > date2 -> ft_tsec) { Z return (1); Z } Z if (date1 -> ft_tsec < date2 -> ft_tsec) { Z return (-1); Z } Z /* everything is equal */ Z return (0); Z} Z Z/* Z * adate - allocate a date struct to be filled out later. Z */ Z ZDATE adate () Z{ Z auto DATE d; Z Z if ((d = (DATE) Calloc (1, sizeof (struct ftime))) == (DATE) NULL) { Z allerr (); Z } Z return (d); Z} Z Zinitrootdates () Z{ /* init root dates */ Z bigbang = adate (); Z bigbang -> ft_tsec = 0; Z bigbang -> ft_min = 0; Z bigbang -> ft_hour = 0; Z bigbang -> ft_day = 1; Z bigbang -> ft_month = 1; Z bigbang -> ft_year = 0; Z endoftime = adate (); Z endoftime- > ft_tsec = 29; Z endoftime- > ft_min = 59; Z endoftime- > ft_hour = 23; Z endoftime- > ft_day = 31; Z endoftime- > ft_month = 11; Z endoftime- > ft_year = 127; Z} Z Zchar *printdate (fdate) ZDATE fdate; Z{ Z auto char buf[10]; Z Z#ifdef NOTYETCONVERTED Z fputs ("( ", stdout); Z itoa (fdate- > ft_hour, buf); Z fputs (buf, stdout); Z fputc (':', stdout); Z itoa (fdate- > ft_min, buf); Z fputs (buf, stdout); Z fputc (':', stdout); Z itoa (fdate- > ft_tsec, buf); Z fputs (buf, stdout); Z fputs (", ", stdout); Z itoa (fdate- > ft_month, buf); Z fputs (buf, stdout); Z fputc ('-', stdout); Z itoa (fdate- > ft_day, buf); Z fputs (buf, stdout); Z fputc ('-', stdout); Z itoa (fdate- > ft_year + 80, buf); Z fputs (buf, stdout); Z puts (" )"); Z#else Z return (""); Z#endif Z} Z#endif Z Z#ifdef unix Z Z/* Z * filedate - return file's creation date (unix only.) Z * Returns -1 if file cannot be found, 0 if successful Z */ Z Zfiledate (fnd) ZFILENODE *fnd; Z{ Z extern DATE osdate (); Z auto DATE newdate; Z auto int success = FAILURE; Z Z DBUG_ENTER ("filedate"); Z DBUG_3 ("date", "find date for '%s'", fnd -> fname); Z newdate = osdate (fnd -> fname, &success); Z DBUG_3 ("date", "has date %s", printdate (newdate)); Z if (success != FAILURE) { Z fnd -> fdate = newdate; Z fnd -> fflag |= EXTRACT; /* do not extract this file again */ Z success = SUCCEED; Z } Z DBUG_RETURN (success); Z} Z Z/* Z * laterdt - compare two dates. Z * Return -1, 0 or 1 if date1 < date2, date1 == date2, or date1 > date2 Z */ Z Zlaterdt (date1, date2) ZDATE date1; ZDATE date2; Z{ Z int result; Z Z DBUG_ENTER ("laterdt"); Z DBUG_4 ("dcmp", "compare %lu vs %lu", *date1, *date2); Z if (*date1 > *date2) { Z result = 1; Z } else if (*date1 < *date2) { Z result = -1; Z } else { Z result = 0; Z } Z DBUG_3 ("dcmp", "result is %d", result); Z DBUG_RETURN (result); Z} Z Z/* Z * adate - allocate a date struct to be filled out later. Z */ Z ZDATE adate () Z{ Z auto DATE d; Z Z DBUG_ENTER ("adate"); Z if ((d = (DATE) Calloc (1, sizeof (long))) == (DATE) NULL) { Z allerr (); Z } Z DBUG_RETURN (d); Z} Z Zvoid initrootdates () Z{ /* init root dates */ Z DBUG_ENTER ("initrootdates"); Z bigbang = adate (); Z *bigbang = 0; Z endoftime = adate (); Z *endoftime = ~0; Z DBUG_VOID_RETURN; Z} Z Zchar *printdate (fdate) ZDATE fdate; Z{ Z static char datebuf[64]; Z Z if (fdate == NULL) { Z sprintf (datebuf, ""); Z } else { Z sprintf (datebuf, "%lu", *fdate); Z } Z return (datebuf); Z} Z Z#endif Z Z#ifdef AMIGA Z Z/* Z * filedate - return file's creation date (Amiga only.) Z * Returns -1 if file cannot be found, 0 if successful Z */ Z Zfiledate (fnd) ZFILENODE *fnd; Z{ Z extern DATE osdate (); Z auto DATE newdate; Z auto int success = FAILURE; Z Z DBUG_ENTER ("filedate"); Z newdate = osdate (fnd -> fname, &success); Z if (success == SUCCEED) { Z DBUG_3 ("fdate", "found date for '%s'", fnd -> fname); Z fnd -> fdate = newdate; Z fnd -> fflag |= EXTRACT; /* don't extract this file again */ Z } Z DBUG_RETURN (success); Z} Z Z/* Z * laterdt - compare two dates. Z * Return -1, 0 or 1 if date1 < date2, date1 == date2, or date1 > date2 Z */ Z Zint laterdt (date1, date2) ZDATE date1; ZDATE date2; Z{ Z register int result; Z Z DBUG_ENTER ("laterdt"); Z DBUG_3 ("dcmp", "compare date1 %s", printdate (date1)); Z DBUG_3 ("dcmp", "with date2 %s", printdate (date2)); Z if (date1 -> ds_Days > date2 -> ds_Days) { Z result = 1; Z } else if (date1 -> ds_Days < date2 -> ds_Days) { Z result = -1; Z } else { Z if (date1 -> ds_Minute > date2 -> ds_Minute) { Z result = 1; Z } else if (date1 -> ds_Minute < date2 -> ds_Minute) { Z result = -1; Z } else { Z if (date1 -> ds_Tick > date2 -> ds_Tick) { Z result = 1; Z } if (date1 -> ds_Tick < date2 -> ds_Tick) { Z result = -1; Z } else { Z result = 0; Z } Z } Z } Z DBUG_3 ("dcmp", "result is %d", result); Z DBUG_RETURN (result); Z} Z Z/* Z * adate - allocate a date struct to be filled out later. Z */ Z ZDATE adate () Z{ Z auto DATE d; Z Z DBUG_ENTER ("adate"); Z if ((d = (DATE) Calloc (1, sizeof (struct DateStamp))) == (DATE) NULL) { Z allerr (); Z } Z DBUG_RETURN (d); Z} Z Zvoid initrootdates () Z{ /* init root dates */ Z DBUG_ENTER ("initrootdates"); Z bigbang = adate (); Z bigbang -> ds_Days = 0; Z bigbang -> ds_Minute = 0; Z bigbang -> ds_Tick = 0; Z endoftime = adate (); Z endoftime -> ds_Days = ~0; Z endoftime -> ds_Minute = ~0; Z endoftime -> ds_Tick = ~0; Z DBUG_VOID_RETURN; Z} Z Zchar *printdate (fdate) ZDATE fdate; Z{ Z static char datebuf[64]; Z Z if (fdate == NULL) { Z sprintf (datebuf, ""); Z } else { Z sprintf (datebuf, "days:%lu min:%lu ticks:%lu", fdate -> ds_Days, Z fdate -> ds_Minute, fdate -> ds_Tick); Z } Z return (datebuf); Z} Z#endif STUNKYFLUFF set `sum parsedir.c` if test 17360 != $1 then echo parsedir.c: Checksum error. Is: $1, should be: 17360. fi # # echo Extracting readme: sed 's/^Z//' >readme <<\STUNKYFLUFF Z Z Z Z ZLast month I wrote a version of the Unix(tm) utility MAKE. It runs under ZVAX/VMS and MSDOS 2.0. I am placing it in the public domain, and it is yours Zfor the asking. You may copy it, or give it away. You can make any changes Zyou like to it. All I ask is that you DO NOT TRY TO SELL IT. Z ZAnyway, there is now a MAKE for MSDOS. It is free, and it works pretty well. ZI'm giving it away because it might do the world some good. Who knows? Z ZCaveat: this version of MAKE is NOT compatible with the Unix(tm) version. ZSome differences are explained in the documentation. Most of the problem stems Zfrom the fact that I've never had a chance to use the original version of MAKE, Zand the documentation I've seen on it has been poor. My idea of what a make Zprogram should do is almost certainly different from what you Unix(tm) hackers Zare used to. Well, hell -- the software is worth what you paid for it. Have Zfun. Z ZIn order to get MAKE running on your system, you need to: Z Z 1. Read the documentation file MAKE.MAN. (Yes, read the Z directions.) Z Z 2. Edit the file MAKE.H to represent your system (VAX/VMS or Z MSDOS 2.0.) Z Z 3. Recompile the source code by following the script file Z CMAKE.COM (for VAX/VMS) or CMAKE.BAT (for MSDOS 2.0.) Z Z VAX/VMS requires the DEC C compiler; MSDOS 2.0 requires Z Lattice C (or another C compiler of comparable quality) Z and the Macro Assembler. Z Z 4. Test out MAKE by running it on itself. (Make a backup Z first!) Z Z Z Z Good luck, Z Z Landon Dyer (G.DYER @ SU-SCORE) Z Z Z Z Z STUNKYFLUFF set `sum readme` if test 53184 != $1 then echo readme: Checksum error. Is: $1, should be: 53184. fi # # echo Extracting sys.c: sed 's/^Z//' >sys.c <<\STUNKYFLUFF Z/* Z * Routines which provide a single entry point to system routines, Z * for easier debugging and porting. Z */ Z Z#include Z#include "make.h" Z Z/* Z * The system calls malloc()/calloc() really return a pointer suitable Z * for use to store any object (satisfies worst case alignment Z * restrictions). As such, it should really have been declared as Z * anything BUT "char *". Z * Z * Also, this gives us the opportunity to verify that the memory Z * allocator really does align things properly. Z * Z * Note that we choose to make calloc () the standard memory Z * allocator, rather than malloc (), because it has a potentially Z * bigger "bite" (total is product of two ints, rather than a Z * single int). Z */ Z Zlong *Calloc (nelem, elsize) Zunsigned int nelem; Zunsigned int elsize; Z{ Z extern char *calloc (); Z long *newmem; Z long total; Z Z DBUG_ENTER ("malloc"); Z DBUG_4 ("mem1", "allocate %u elements of %u bytes", nelem, elsize); Z DBUG_3 ("mem2", "total of %ul bytes", total = nelem * elsize); Z newmem = (long *) calloc (nelem, elsize); Z if ((((int)newmem) % 4) != 0) { Z fprintf (stderr, "urk -- Calloc screwed up!\n"); Z } Z DBUG_3 ("mem", "allocated at %x", newmem); Z DBUG_RETURN (newmem); Z} Z Z#ifdef AMIGA Z Zint system (cmd) Zchar *cmd; Z{ Z int status = -1; Z extern int Execute (); Z Z DBUG_ENTER ("system"); Z if (Execute (cmd, 0 ,0)) { Z status = 0; /* Really should get exit status! */ Z } Z DBUG_RETURN (status); Z} Z Z#endif /* AMIGA */ STUNKYFLUFF set `sum sys.c` if test 58319 != $1 then echo sys.c: Checksum error. Is: $1, should be: 58319. fi # # echo Extracting token.c: sed 's/^Z//' >token.c <<\STUNKYFLUFF Z#include Z#include Z#include "make.h" Z Zstatic char *stripwh (); Z Z/* Z * Get next token from the string. Return a pointer to it, or NULL. Z * Adjust pointer to point to next part of string. Z * The string is modified. Z * A token consists of any number of non-white characters. Z */ Z Zchar *token (strpp) Zchar **strpp; Z{ Z register char *s; Z register char *beg = NULL; Z Z DBUG_ENTER ("token"); Z DBUG_3 ("tok", "get next token from '%s'", *strpp); Z (void) stripwh (strpp); Z if (**strpp) { Z beg = s = *strpp; Z while (*s && !isspace (*s)) { Z ++s; Z } Z if (*s) { Z *s++ = '\0'; Z } Z *strpp = s; Z DBUG_3 ("tok", "found token '%s'", beg); Z } Z DBUG_RETURN (beg); Z} Z Z Z/* Z * Parse character escape-sequences in a line of text. Z * = Z * n = newline, and so on Z * = Z * The string is truncated at the first non-escaped occurance of 'comchar'. Z */ Z Zvoid escape (str, comchar) Zchar *str; Zchar comchar; Z{ Z register char *d; Z register char c; Z Z DBUG_ENTER ("escape"); Z for (d = str; *str && *str != comchar; ++str) { Z if (*str == ESCCHAR && *(str + 1)) { Z switch ((c = *++str)) { Z case ESCCHAR: Z *d++ = ESCCHAR; Z break; Z case 'n': Z *d++ = '\n'; Z break; Z case 'r': Z *d++ = '\r'; Z break; Z case 't': Z *d++ = '\t'; Z break; Z case 'b': Z *d++ = '\b'; Z break; Z case 'f': Z *d++ = '\f'; Z break; Z default: Z *d++ = c; Z break; Z } Z } else { Z *d++ = *str; Z } Z } Z *d++ = 0; Z DBUG_VOID_RETURN; Z} Z Zstatic char *stripwh (strpp) Zchar **strpp; Z{ Z register char *s; Z Z s = *strpp; Z while (isspace (*s)) { Z ++s; Z } Z return (*strpp = s); Z} STUNKYFLUFF set `sum token.c` if test 46598 != $1 then echo token.c: Checksum error. Is: $1, should be: 46598. fi echo ALL DONE BUNKY! exit 0