home *** CD-ROM | disk | FTP | other *** search
Text File | 1984-06-29 | 25.7 KB | 1,291 lines |
- \b readme
-
-
-
- Last month I wrote a version of the Unix(tm) utility MAKE. It runs under
- VAX/VMS and MSDOS 2.0. I am placing it in the public domain, and it is yours
- for the asking. You may copy it, or give it away. You can make any changes
- you like to it. All I ask is that you DO NOT TRY TO SELL IT.
-
- Anyway, there is now a MAKE for MSDOS. It is free, and it works pretty well.
- I'm giving it away because it might do the world some good. Who knows?
-
- Caveat: this version of MAKE is NOT compatible with the Unix(tm) version.
- Some differences are explained in the documentation. Most of the problem stems
- from the fact that I've never had a chance to use the original version of MAKE,
- and the documentation I've seen on it has been poor. My idea of what a make
- program should do is almost certainly different from what you Unix(tm) hackers
- are used to. Well, hell -- the software is worth what you paid for it. Have
- fun.
-
- In order to get MAKE running on your system, you need to:
-
- 1. Read the documentation file MAKE.MAN. (Yes, read the
- directions.)
-
- 2. Edit the file MAKE.H to represent your system (VAX/VMS or
- MSDOS 2.0.)
-
- 3. Recompile the source code by following the script file
- CMAKE.COM (for VAX/VMS) or CMAKE.BAT (for MSDOS 2.0.)
-
- VAX/VMS requires the DEC C compiler; MSDOS 2.0 requires
- Lattice C (or another C compiler of comparable quality)
- and the Macro Assembler.
-
- 4. Test out MAKE by running it on itself. (Make a backup
- first!)
-
-
-
- Good luck,
-
- Landon Dyer (G.DYER @ SU-SCORE)
-
-
-
-
-
- \e readme
- \b make.man
- MAKE(I) 3/10/84 MAKE(I)
-
-
-
- NAME
- MAKE - maintain multiple source files (VAX/VMS and MSDOS 2.0)
-
-
- SYNOPSIS
- MAKE [-N] [-A] [-F makefile] [name ...]
-
-
- DESCRIPTION
- MAKE is a utility inspired by the Unix(tm) command of the same
- name. MAKE helps maintain programs that are constructed from
- many files. MAKE processes a "makefile", a file which describes
- how to build a program from its source files, and produces a
- script file containing the commands necessary to recompile the
- program.
-
- Be careful: this MAKE is NOT compatible with Unix(tm) MAKE!
-
- The 'N' option causes MAKE to print out the steps it would follow
- in order to rebuild the program. The 'A' option tells MAKE to
- assume that all files are obsolete, and that everything should be
- recompiled. The 'F' option, followed by a filename, can be used
- to specify a makefile other than the default one.
-
- If no names are specified in the commandline, the first dependency
- in the makefile is examined. Otherwise, the specified root names
- are brought up to date.
-
- The default makefiles are:
-
- for VAX/VMS: MAKEFILE
- [-]MAKEFILE
- SYS$LOGIN:MAKEFILE
-
- for MSDOS: MAKEFILE
- ..\MAKEFILE
-
- If the first makefile cannot be found, MAKE attempts to use the
- next one. If no makefile is ever found, MAKE prints a diagnostic
- and aborts.
-
-
-
-
-
- THE MAKEFILE
- Comments begin with '!' and extend to the end of the line. A
- '!' (or almost any other character) may be escaped with the escape
- character (backslash (\) on VMS, backquote (`) on MSDOS). An escape
- character may be typed by doubling it (\\ or ``). The standard
- Unix escape codes are recognized (\n, \r, \t, \b, \f, `n, `r, `t,
- `b and `f).
-
- A makefile is a list of dependencies. A dependency consists of
- a root name, a colon, and zero or more names of dependent files.
- (The colon MUST be preceeded by whitespace.) For instance, in:
-
- make.exe : make.obj parsedir.obj file.obj macro.obj mk.h
-
- the file 'make.exe' depends on five other files. A root name
- with an empty dependency, as in:
-
- print :
-
- is assumed NEVER up to date, and will always be recompiled.
-
- The dependency list may be continued on successive lines:
-
- bigfile.exe : one.obj two.obj three.obj four.obj
- five.obj six.obj gronk.obj freeple.obj scuzzy.lnk
- frog.txt greeble.out
-
- Any number of 'method' lines may follow a dependency. Method lines
- begin with an ascii tab. When a file is to be recompiled, MAKE
- copies these method lines (minus the tab) to the script file.
- For example, in:
-
- make.exe : make.obj parsedir.obj file.obj macro.obj mk.h
- $link make, parsedir, file, macro
- $write sys$output "Just another version of MAKE ..."
- $purge
-
- the three lines following the dependency make up the method for
- recompiling (or in this case, re-linking) the file 'make.exe'.
-
- If the macro "~INIT" is defined, its text will appear first in the
- script file. If the macro "~DEINIT" is defined, its text will
- appear last in the script file. By defining these two macros, it
- is possible to configure the shell enviroment:
-
- ~INIT = $set term/nowrap\n$on error then goto err_handler
- ~DEINIT = $set term/wrap\n$exit\$err_handler:\n
- ~DEINIT = #(~DEINIT)$type err.log\n$exit
-
- will expand (in the script file) to:
-
- $set term/nowrap
- $on error then goto err_handler
- .
- .
- $set term/wrap
- $exit
- $err_handler:
- $type err.log
- $exit
-
- When a root's method is defined, the value of the macro "~BEFORE"
- is prefixed to the method, and the value of the macro "~AFTER" is
- appended to it.
-
- Frequently one wants to maintain more than one program with a single
- makefile. In this case, a "master dependency" can appear first in
- the file:
-
- allOfMyToolsAndHorribleHacks : cat peek poke.exe grunge
- cat : cat.exe
- cat.exe : ....
- (stuff for CAT.EXE)
- peek : peek.exe
- peek.exe : (stuff for PEEK.EXE)
- poke.exe : (stuff for POKE.EXE)
- grunge : grunge.com
- grunge.com : (stuff for grung)
-
- In other words, make will bring everything up to date that is somehow
- connected to the first dependency (its assumed that the incredibly
- lengthy filename specified in this example won't actually exist).
-
-
-
-
-
-
-
-
-
- MACROS
- A macro is defined by a line of the form (the '=' MUST be surrounded
- by whitespace):
-
- <macro-name> = <macro-body>
-
- A macro may be deleted by assigning an empty value to it. Macros
- may be redefined, but old definitions stay around. If a macro is
- redefined, and the redefinition is later deleted, the first definition
- will take effect:
-
- MAC = first ! MAC = "first"
- MAC = second ! MAC = "second"
- MAC = #(MAC) third ! MAC = "second third"
- MAC = ! MAC = "second"
- MAC = ! MAC = "first"
- MAC = ! MAC has no definition
-
- A macro may be referenced in two ways:
-
- #<char> or #(macro-name)
-
- The first way only works if the macro's name is a single character.
- If the macro's name is longer than one character, it must be
- enclosed in parenthesis. ['#' may be escaped by doubling it ("##".)]
- For example, in:
-
- G = mk.h mk1.h
- OBJS = make.obj file.obj parsedir.obj macro.obj
- BOTH = #(OBJS) #G
-
- make.exe : #(OBJS) #G
- make.exe : #(BOTH)
- make.exe : mk.h mk1.h make.obj file.obj parsedir.obj macro.obj
- $write sys$output "This is a number sign --> ##"
-
- after macro expansion, the three dependencies will appear identical
- and the two '#'s in the last line will turn into one '#'.
-
-
-
-
-
-
-
-
-
-
- UNIX(tm) MAKE AND THIS ONE
- They are NOT the same. Do not expect Unix makefiles to work with
- this MAKE, even if you change the pathnames. There are some major
- differences between this version and the standard Unix(tm) MAKE:
-
- 1. The Unix(tm) comment character is '#', VAX/VMS's is '!'.
-
- 2. The Unix(tm) macro-expansion character is '$'. While this would
- have been easy to leave the same, the '$' character is used so
- often in VAX/VMS command-lines that I thought it best to change
- it to '#'.
-
- 3. Multiple root names are not allowed. Unix(tm) MAKE accepts lines
- of the form:
-
- name1 name2 : depend1 depend2
-
- but this one doesn't.
-
- 4. There is no equivalent of double-colon ("::".)
-
- 5. There is no equivalent of .SUFFIXES, or the corresponding special
- macros.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- SAMPLE MAKEFILE
- !
- ! VAX/VMS MAKE
- ! Landon Dyer
- !
- H = make.h
- FILES = #H, make.c, macro.c, token.c, parsedir.c, file.c
- DOCUMENTATION = distr.mem make.man makefile. make.com
-
- make.exe : make.obj macro.obj token.obj parsedir.obj file.obj
- $link make.obj, macro, token, parsedir, file
- $purge
-
- make.obj : make.c #H
- $cc make.c
-
- macro.obj : macro.c #H
- $cc macro
-
- token.obj : token.c #H
- $cc token
-
- parsedir.obj : parsedir.c #H
- $cc parsedir
-
- file.obj : file.c
- $cc file
-
- !
- ! Print files associated with MAKE
- !
- print :
- $print make.man, #(FILES), make.com, makefile.
-
- !
- ! Type out source to MAKE
- !
- type :
- $type #(FILES), make.com, makefile.
-
- !
- ! Make backup of source files.
- !
- BACKUP = [.bak]
- backup :
- $copy #(FILES) #(BACKUP)
- $copy make.man, make.com, makefile. #(BACKUP)
-
- !
- ! Collect MAKE into a distribution file.
- !
- collect :
- $collect collect distr.mem make.man makefile make.com make.h -
- make.c macro.c token.c parsedir.c file.c
-
-
- AUTHOR
- Landon Dyer G.DYER@SU-SCORE.ARPA
- 175 Calvert Dr. #F-211 BASHFL::DYER (Atari Coinop)
- Cupertino, CA 95014
- \e make.man
- \b makefile
- !
- ! MSDOS Make utility
- ! (compile with Lattice C version 2.0)
- !
-
- CLIB = \bin\lcs
- COBJ = \bin\cs
- H = make.h
- FILES = #H make.c macro.c token.c parsedir.c file.c osdate.asm
- DOCUMENTATION = readme make.man makefile
-
- makeexe.exe : make.obj macro.obj token.obj parsedir.obj file.obj osdate.obj
- link #(COBJ) make macro token parsedir file osdate,makeexe,,#(CLIB)
-
- make.obj : make.c #H
- lc1 make
- lc2 make
-
- macro.obj : macro.c #H
- lc1 macro
- lc2 macro
-
- token.obj : token.c #H
- lc1 token
- lc2 token
-
- parsedir.obj : parsedir.c #H
- lc1 parsedir
- lc2 parsedir
-
- file.obj : file.c
- lc1 file
- lc2 file
-
- osdate.obj : osdate.asm
- masm osdate;
-
- !
- ! Print files associated with MAKE
- !
- print :
- print make.man #(FILES) makefile
-
-
- !
- ! collect source and documentation files
- !
- collect :
- collect -o make.col @make.lis
-
-
- !
- ! copy to distribution disk (on A:)
- !
- distribution :
- copy readme a:
- copy make.man a:
- copy makefile a:
- copy make.bat a:
- copy make.c a:
- copy macro.c a:
- copy token.c a:
- copy parsedir.c a:
- copy file.c a:
- copy osdate.asm a:
- copy cmake.bat a:
- copy make.lis a:
- copy makeexe.exe a:
- \e makefile
- \b make.bat
- echo off
- if exist make$$$$.bat del make$$$$.bat
- makeexe %1 %2 %3 %4 %5 %6 %7 %8 %9
- if exist make$$$$.bat make$$$$.bat
- \e make.bat
- \b make.c
- #include <stdio.h>
- #include <ctype.h>
- #include "make.h"
-
- /*
- * MAKE - Maintain seperate source files
- *
- * SYNOPSIS
- * MK [-f file] [-a] [-n] [-d] [name] ...
- * f: use 'file' instead of default makefile
- * a: assume all modules are obsolete (recompile everything)
- * n: don't recompile, just list steps to recompile
- * d: debugging (print tree, file info)
- * name: module name to recompile
- *
- * 'secret' options (not to be used by humans):
- * -ofile 'file' is the script file to write to
- *
- * AUTHOR
- * Landon M. Dyer, Atari Inc.
- *
- */
-
- #define SCRIPTFILE "make$$$$.bat" /* (default) script-listing file */
- #define INIT "~INIT" /* initialization macro */
- #define DEINIT "~DEINIT" /* de-init macro */
- #define BEFORE "~BEFORE" /* the per-root 'startup' method */
- #define AFTER "~AFTER" /* the per-root 'wrapup' method */
-
-
- char *mfiles[] = { /* default makefiles */
- "makefile",
-
- #ifdef VAXVMS
- "[-]makefile",
- "sys$login:makefile",
- #endif
-
- #ifdef MSDOS
- "..\makefile",
- #endif
- ""
- };
-
-
- MACRO *mroot = NULL; /* root of macro-list */
- FILENODE *froot = NULL; /* root of filenode-list */
- FILENODE *firstf = NULL; /* the very first filenode */
- FILE *mkfp = NULL; /* script file */
- char *modnames[MAXMODS]; /* module-names mentioned in commandline */
- int modcount = 0; /* #of module-names */
- int debug = 0; /* nonzero: turn on debugging */
- int obsolete = 0; /* nonzero: every file should be recompiled */
- int noscript = 0; /* nonzero: print methods on standard output */
- char *scriptf = SCRIPTFILE; /* default script file */
- DATE bigbang; /* a date, the very earliest possible */
- DATE endoftime; /* a date, the very last possible */
-
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- int arg, i;
- char *mfile = NULL;
- DATE adate();
-
- bigbang = adate(0, 0); /* init root dates */
- endoftime = adate(~0, ~0);
-
- for(arg = 1; arg < argc; ++arg)
- if(*argv[arg] == '-') switch(tolower(argv[arg][1]))
- {
- case 'f':
- if(++arg >= argc)
- {
- fprintf(stderr, "-f needs filename argument.\n")
- ;
- return;
- }
- mfile = argv[arg];
- break;
-
- case 'a':
- obsolete = 1;
- break;
-
- case 'n':
- noscript = 1;
- break;
-
- case 'd':
- debug = 1;
- break;
-
- case 'o':
- scriptf = argv[arg] + 2;
- break;
-
- default:
- fprintf(stderr, "Unknown switch: %c\n", argv[arg][1]);
- break;
- } else if(modcount < MAXMODS)
- modnames[modcount++] = argv[arg];
- else
- {
- fprintf(stderr, "Too many module names.\n");
- return;
- }
-
- if(mfile != NULL)
- {
- if(fmake(mfile) == -1)
- fprintf(stderr, "Cannot open makefile '%s'.\n", mfile);
- } else {
- for(i = 0; *mfiles[i]; ++i)
- if(fmake(mfiles[i]) != -1) break;
- if(!*mfiles[i])
- fprintf(stderr, "Cannot open makefile.\n");
- }
-
- if(debug) prtree();
- }
-
-
- /*
- * Construct dependency tree from the makefile 'fn'.
- * Figure out what has to be recompiled, and write a script file to do that.
- */
- fmake(fn)
- char *fn;
- {
- FILE *fp;
-
- if((fp = fopen(fn, "r")) == NULL) return -1;
-
- fparse(fp);
- determ();
-
- fclose(fp);
- return 0;
- }
-
-
- /*
- * Parse the input file, defining macros and building the dependency tree.
- */
- fparse(fp)
- FILE *fp;
- {
- char ibuf[STRSIZ], ebuf[STRSIZ];
- char *strp, *tok1, *tok2, *s;
- FILENODE *lastf = NULL;
- FILENODE *sf;
-
- for(;;)
- {
- if(fgets(ibuf, STRSIZ, fp) == NULL) break;
- mexpand(ibuf, ebuf, STRSIZ, MACCHAR);
- escape(ebuf, COMCHAR);
-
- /* clobber last newline in string */
- s = ebuf + strlen(ebuf) - 1;
- if(s >= ebuf && *s == '\n') *s = '\0';
-
- if(*ebuf == '\t')
- {
- addmeth(lastf, ebuf+1);
- continue;
- }
-
- strp = ebuf;
- if((tok1 = token(&strp)) == NULL) continue;
- if((tok2 = token(&strp)) != NULL)
- if(!strcmp(tok2, DEFMAC))
- {
- if(*strp) defmac(tok1, strp);
- else if(undefmac(tok1) < 0)
- fprintf(stderr,
- "Can't undefine macro '%s'\n", tok1);
- continue;
- }
- else if(!strcmp(tok2, DEPEND))
- {
- addmeth(lastf, gmacro(AFTER));
-
- lastf = filenode(tok1);
- if(firstf == NULL) firstf = lastf;
- lastf->fmake = NULL;
-
- addmeth(lastf, gmacro(BEFORE));
-
- lastf->fflag |= ROOTP;
- while((tok1 = token(&strp)) != NULL)
- addfile(lastf, tok1);
- continue;
- }
- else addfile(lastf, tok2);
-
- do {
- addfile(lastf, tok1);
- } while((tok1 = token(&strp)) != NULL);
- }
-
- addmeth(lastf, gmacro(AFTER));
- }
-
-
- /*
- * Determine sequence of recompiles from the creation dates.
- * If there is anything to recompile, then create a script file full of commands
- .
- */
- determ()
- {
- FILENODE *f;
- int i;
- char *m;
-
- if(firstf == NULL) /* empty tree */
- {
- printf("No changes.\n");
- return;
- }
-
- if(modcount == 0) examine(firstf, endoftime);
- else for(i = 0; i < modcount; ++i)
- {
- if((f = gfile(modnames[i])) == NULL)
- {
- fprintf(stderr, "Can't find root '%s'.\n", modnames[i]);
- continue;
- }
-
- if(f->fflag & ROOTP == 0)
- {
- fprintf(stderr, "'%s' is not a root!\n", f->fname);
- continue;
- }
- examine(f, endoftime);
- }
-
- if(mkfp != NULL)
- {
- if((m = gmacro(DEINIT)) != NULL)
- {
- fputs(m, mkfp);
- fputc('\n', mkfp);
- }
- fclose(mkfp);
- } else printf("No changes.\n");
- }
-
-
- /*
- * Examine filenode 'fnd' and see if it has to be recompiled.
- * 'date' is the last-touched date of the node's father
- * (or 'endoftime' if its a root file.)
- * Root files with NO dependencies are assumed not to be up to date.
- */
- examine(fnd, date)
- FILENODE *fnd;
- DATE date;
- {
- int rebuildp = 0;
- NODE *n;
-
- getdate(fnd);
- if(fnd->fnode == NULL && fnd->fflag & ROOTP)
- rebuildp = 1;
- else for(n = fnd->fnode; n != NULL; n = n->nnext)
- if(examine(n->nfile, fnd->fdate)) rebuildp = 1;
-
- if(rebuildp) recomp(fnd);
- if(obsolete || laterdt(fnd->fdate, date) >= 0)
- rebuildp = 1;
- return rebuildp;
- }
-
-
- /*
- * Make sure a filenode gets recompiled.
- */
- recomp(f)
- FILENODE *f;
- {
- FILENODE *sf;
- char *m;
-
- if(mkfp == NULL)
- {
- if(noscript) mkfp = stdout;
- else if((mkfp = fopen(scriptf, "w")) == NULL)
- fprintf(stderr, "Cannot create: '%s'\n", scriptf);
-
- if((m = gmacro(INIT)) != NULL)
- {
- fputs(m, mkfp);
- fputc('\n', mkfp);
- }
- }
-
- if(f->fflag & REBUILT) return;
- if(f->fmake != NULL) fputs(f->fmake, mkfp);
- f->fflag |= REBUILT;
- }
-
-
- /*
- * Complain about being out of memory, and then die.
- */
- allerr() {
- fprintf(stderr, "Can't alloc -- no space left (I give up!)\n");
- exit(1);
- }
- \e make.c
- \b macro.c
- #include <stdio.h>
- #include "make.h"
-
- /*
- * Macro processing
- */
-
-
- /*
- * Perform macro substitution from 'orig' to 'dest'.
- * Return number of macro substitutions made.
- * A macro reference is in one of two forms:
- * <MACCHAR>(macro-name)
- * or <MACCHAR><single-character>
- *
- * "<MACCHAR><MACCHAR>" expands to a single '<MACCHAR>'
- */
- mexpand(orig, dest, destsiz, macchar)
- char *orig, *dest;
- int destsiz;
- char macchar;
- {
- char *s, *d, mname[STRSIZ];
- int di, count;
- MACRO *m;
-
- di = count = 0;
- for(s=orig; *s;)
- if(*s == macchar)
- {
- if(*++s == macchar)
- {
- if(di < destsiz-1) dest[di++] = *s++;
- continue;
- }
-
- if(!*s) break;
- d = mname;
- if(*s != '(') *d++ = *s++;
- else
- {
- for(++s; *s && *s!=')';) *d++ = *s++;
- if(*s != ')') puts("Missed matching ')'");
- else ++s;
- }
- *d = 0;
- if((d = gmacro(mname)) == NULL)
- fprintf(stderr, "Undefined macro: %s\n", mname);
- else
- {
- while(*d && di < (destsiz - 1))
- dest[di++] = *d++;
- ++count;
- }
- } else if(di < destsiz-1)
- dest[di++] = *s++;
-
- dest[di]=0;
- return count;
- }
-
-
- /*
- * Define a macro.
- * Give the macro called 'name' the string expansion 'def'.
- * Old macro-names are superseded, NOT replaced.
- * Return ERROR if can't define the macro.
- */
- defmac(name, def)
- char *name, *def;
- {
- MACRO *m;
-
- if((m = (MACRO *)malloc(sizeof(MACRO))) == NULL) allerr();
- if((m->mname = (char *)malloc(strlen(name)+1)) == NULL) allerr();
- if((m->mvalue = (char *)malloc(strlen(def)+1)) == NULL) allerr();
-
- strcpy(m->mname, name);
- strcpy(m->mvalue, def);
- m->mnext = mroot;
- mroot = m;
- }
-
-
- /*
- * undefmac - undefine a macro.
- * Return 0 if macro was succesfully undefined, -1 if not found.
- */
- undefmac(name)
- char *name;
- {
- MACRO *m = mroot;
- MACRO *prev = NULL;
-
- while(m != NULL && strcmp(name, m->mname))
- {
- prev = m;
- m = m->mnext;
- }
-
- if(m == NULL) return -1;
- if(prev == NULL) mroot = m->mnext;
- else prev->mnext = m->mnext;
-
- free(m->mname);
- free(m->mvalue);
- free(m);
- return 0;
- }
-
-
- /*
- * Lookup a macro called 'name'.
- * Return a pointer to its definition,
- * or NULL if it does not exist.
- */
- char *gmacro(name)
- char *name;
- {
- MACRO *m;
-
- for(m=mroot; m != NULL; m=m->mnext)
- if(!strcmp(name, m->mname)) return m->mvalue;
- return NULL;
- }
- \e macro.c
- \b token.c
- #include <stdio.h>
- #include <ctype.h>
- #include "make.h"
-
- /*
- * Get next token from the string. Return a pointer to it, or NULL.
- * Adjust pointer to point to next part of string.
- * The string is modified.
- * A token consists of any number of non-white characters.
- */
- char *token(strpp)
- char **strpp;
- {
- char *s, *beg;
-
- stripwh(strpp);
- if(!**strpp) return NULL;
-
- beg = s = *strpp;
- while(*s && !isspace(*s)) ++s;
- if(*s) *s++ = '\0';
- *strpp = s;
- return beg;
- }
-
-
- /*
- * Parse character escape-sequences in a line of text.
- * <EscChar><EscChar> = <EscChar>
- * <EscChar>n = newline, and so on
- * <EscChar><char> = <char>
- * The string is truncated at the first non-escaped occurance of 'comchar'.
- */
- escape(str, comchar)
- char *str, comchar;
- {
- char *d, c;
-
- for(d = str; *str && *str != comchar; ++str)
- if(*str == ESCCHAR && *(str + 1)) switch((c = *++str))
- {
- case ESCCHAR:
- *d++ = ESCCHAR;
- break;
-
- case 'n':
- *d++ = '\n';
- break;
-
- case 'r':
- *d++ = '\r';
- break;
-
- case 't':
- *d++ = '\t';
- break;
-
- case 'b':
- *d++ = '\b';
- break;
-
- case 'f':
- *d++ = '\f';
- break;
-
- default:
- *d++ = c;
- break;
- } else *d++ = *str;
-
- *d++ = 0;
- }
-
-
- stripwh(strpp)
- char **strpp;
- {
- char *s;
-
- s = *strpp;
- while(isspace(*s)) ++s;
- return (*strpp = s);
- }
- \e token.c
- \b parsedir.c
- #include <stdio.h>
- #include "make.h"
- #ifdef VAXVMS
- #include <rms.h>
- #endif
-
-
- /*
- * Get a file's creation date.
- */
- int getdate(f)
- FILENODE *f;
- {
- if(f->fdate != NULL || filedate(f) != -1) return;
-
- if(f->fflag & ROOTP == 0)
- {
- fprintf(stderr, "Can't get date for file '%s'\n", f->fname);
- f->fdate = endoftime;
- } else f->fdate = bigbang;
- return;
- }
-
-
- #ifdef VAXVMS
- /*
- * filedate - return file's creation date (VAX/VMS only.)
- * Returns -1 if file cannot be found, 0 if succesful.
- */
- filedate(fnd)
- FILENODE *fnd;
- {
- unsigned *datetime;
- DATE adate();
- struct FAB *fptr;
- struct XABDAT *dptr;
-
- fptr = malloc(sizeof(struct FAB)); /* allocate FAB and XABDAT */
- dptr = malloc(sizeof(struct XABDAT));
- if(fptr == NULL || dptr == NULL) allerr();
- *fptr = cc$rms_fab; /* initialize FAB and XABDAT */
- *dptr = cc$rms_xabdat;
- fptr->fab$l_xab = (char *) dptr; /* FAB -> XABDAT */
-
- fptr->fab$l_fna = fnd->fname; /* setup filename */
- fptr->fab$b_fns = strlen(fnd->fname);
-
- if(sys$open(fptr) != RMS$_NORMAL || /* open the file */
- sys$display(fptr) != RMS$_NORMAL) /* get XABDAT info */
- return -1;
-
- datetime = &(dptr->xab$q_cdt); /* record 64-bit date */
- fnd->fdate = adate(datetime[0], datetime[1]);
-
- sys$close(fptr); /* close the file */
-
- free(dptr); /* clean up and return */
- free(fptr);
- return 0;
- }
- #endif
-
-
- #ifdef MSDOS
- /*
- * filedate - return file's creation date (MSDOS only.)
- * Returns -1 if file cannot be found, 0 if successful
- */
- filedate(fnd)
- FILENODE *fnd;
- {
- unsigned date, time;
- DATE adate();
-
- if(osdate(fnd->fname, &time, &date) == -1) return -1;
- fnd->fdate = adate(time, date);
- }
- #endif
-
-
- /*
- * laterdt - compare two dates.
- * Return -1, 0 or 1 if date1 < date2, date1 == date2, or date1 > date2
- */
- laterdt(date1, date2)
- DATE date1, date2;
- {
- if(date1->ds_high > date2->ds_high ||
- (date1->ds_high >= date2->ds_high &&
- date1->ds_low > date2->ds_low)) return 1;
- else if(date1->ds_high == date2->ds_high &&
- date1->ds_low == date2->ds_low) return 0;
- else return -1;
- }
-
-
- /*
- * adate - allocate a date with the given time
- */
- DATE adate(time1, time2)
- unsigned time1, time2;
- {
- DATE d;
-
- if((d = (DATE)malloc(sizeof(struct date_str))) == NULL) allerr();
- d->ds_low = time1;
- d->ds_high = time2;
- return d;
-
- }
- \e parsedir.c
- \b file.c
- #include <stdio.h>
- #include "make.h"
-
-
- /*
- * Return file-node for 'fname'.
- * If it doesn't exist, then create one.
- */
- FILENODE *filenode(fname)
- char *fname;
- {
- FILENODE *f, *afnode(), *gfile();
-
- if((f = gfile(fname)) == NULL)
- f = afnode(fname);
- return f;
- }
-
-
- /*
- * Add a dependency to the node 'fnd'.
- * 'fnd' will depend on 'fname'.
- */
- addfile(fnd, fname)
- FILENODE *fnd;
- char *fname;
- {
- NODE *n;
- FILENODE *f;
-
- if(fnd == NULL) /* punt if no root file */
- {
- fprintf(stderr, "No current root, can't add dependency '%s'\n",
- fname);
- return;
- }
-
- f = filenode(fname);
- if((n = (NODE *)malloc(sizeof(NODE))) == NULL) allerr();
- n->nnext = fnd->fnode;
- fnd->fnode = n;
- n->nfile = f;
- }
-
-
- /*
- * Add a line of method-text to the node 'fnode'.
- */
- addmeth(fnode, methtext)
- FILENODE *fnode;
- char *methtext;
- {
- int len;
- char *new;
-
- if(fnode == NULL || methtext == NULL) return;
-
- len = strlen(methtext) + 2;
- if(fnode->fmake == NULL)
- {
- if((fnode->fmake = (char *)malloc(1)) == NULL) allerr();
- *(fnode->fmake) = 0;
- }
- len += strlen(fnode->fmake);
-
- /* Lattice C doesn't have 'realloc()', so this kludges around it: */
- if((new = (char *)malloc(len)) == NULL) allerr();
- strcpy(new, fnode->fmake);
- free(fnode->fmake);
- fnode->fmake = new;
-
- strcat(fnode->fmake, methtext);
- len = strlen(fnode->fmake);
- if(len && fnode->fmake[len - 1] != '\n')
- strcat(fnode->fmake, "\n");
- }
-
-
- /*
- * Get a filenode for the file called 'fn'.
- * Returns NULL if the node doesn't exist.
- */
- FILENODE *gfile(fn)
- char *fn;
- {
- FILENODE *f;
-
- for(f = froot; f != NULL; f = f->fnext)
- if(!strcmp(fn, f->fname)) return f;
- return NULL;
- }
-
-
- /*
- * Alloc space for a new file node.
- */
- FILENODE *afnode(name)
- char *name;
- {
- FILENODE *f;
-
- for(f=froot; f; f=f->fnext)
- if(!strcmp(name, f->fname)) return f;
-
- if((f = (FILENODE *)malloc(sizeof(FILENODE))) == NULL) allerr();
- if((f->fname = (char *)malloc(strlen(name)+1)) == NULL) allerr();
- strcpy(f->fname, name);
- f->fmake = NULL;
- f->fnode = NULL;
- f->fdate = NULL;
- f->fflag = 0;
-
- f->fnext = froot;
- froot = f;
- return f;
- }
-
-
- /*
- * Print dependency tree.
- */
- prtree()
- {
- FILENODE *f;
- NODE *n;
-
- for(f = froot; f != NULL; f = f->fnext)
- {
- printf("%s%s%s (%u, %u)\n",
- f->fname,
- (f->fflag & ROOTP) ? " (root)" : "",
- (f->fflag & REBUILT) ? " (rebuilt)" : "",
- (f->fdate != NULL) ? (f->fdate)->ds_high : 0,
- (f->fdate != NULL) ? (f->fdate)->ds_low : 0);
- if(f->fmake != NULL)
- printf("%s", f->fmake);
- for(n = f->fnode; n != NULL; n = n->nnext)
- printf("\t%s\n", (n->nfile)->fname);
- puts("");
- }
- }
- \e file.c
- \b osdate.asm
- dos = 21h
-
- arg1 = 4 ; lattice argument indexes
- arg2 = arg1+2
- arg3 = arg2+2
-
- pgroup group prog
- prog segment byte public 'prog'
- public osdate
- assume cs:pgroup
-
- ;
- ;------
- ; OSDATE - return file's creation-date (called from Lattice), or -1
- ; if can't find the file.
- ; Synopsis:
- ; int osdate(filename, time1, time2)
- ; char *filename;
- ; int *time1, *time2;
- ;
- osdate proc near
- push bp
- mov bp,sp
-
- ;--- Open the file
- mov dx,[bp+arg1]
- xor al,al
- mov ah,3dh
- int dos
- jc osd$err ; can't, so complain
-
- ;--- Get file's creation date and time
- mov bx,ax ; get handle's date info
- xor al,al
- mov ah,57h
- int dos
- jc osd$cls ; "can't happen" (but close it)
-
- ;--- Install date/time info into caller's variables
- mov si,[bp+arg2] ; *arg2 = time (least significant)
- mov [si],cx
- mov si,[bp+arg3] ; *arg3 = date (most significant)
- mov [si],dx
-
- ;--- Close file & return (ok)
- mov ah,3eh
- int dos
- xor ax,ax
- pop bp
- ret
-
- ;--- Close file & return error condition
- osd$cls:
- mov ah,3eh
- int dos
- osd$err:
- mov ax,-1
- pop bp
- ret
- osdate endp
-
- prog ends
- end
- \e osdate.asm
- \b cmake.bat
- lc1 make
- lc2 make
- lc1 macro
- lc2 macro
- lc1 token
- lc2 token
- lc1 parsedir
- lc2 parsedir
- lc1 file
- lc2 file
- masm afind1st;
- link c:c make macro token parsedir file afind1st,make;
- \e cmake.bat
- \b make.lis
- readme make.man makefile make.bat make.c macro.c token.c
- parsedir.c file.c osdate.asm cmake.bat make.lis
- \e make.lis
-