Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator) (06/04/90)
Submitted-by: huver@amgraf.uucp Posting-number: Volume 90, Issue 177 Archive-name: unix/pdmake/part01 I took the PDmake that Steve Walton ported to Amiga, and enhanced it a bit. Many attempts were made to contact Steve, but all failed (no mail bounce, absolutely nothing came back from him). So here it is, the complete thing. Note there was no version number at all in the PDmake distribution. If this is your first time seeing such buzzword as "PDmake", you should read the fles README, README.amiga first. #!/bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 1 (of 2)." # Contents: Changes.new README README.amiga an assign_macro.c check.c # h.h input.c macro.c main.c make.n makefile reader.c # Wrapped by tadguy@xanth on Sun Jun 3 20:20:41 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'Changes.new' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Changes.new'\" else echo shar: Extracting \"'Changes.new'\" \(3328 characters\) sed "s/^X//" >'Changes.new' <<'END_OF_FILE' XApril 18, 1990 X--huver hu ...!uunet!amgraf!huver -or- huver%amgraf@uunet.uu.net X X XI took the PDmake that Steve Walton ported to Amiga, and enhanced it a bit. XMany attempts were made to contact Steve, but all failed (no mail bounce, Xabsolutely nothing came back from him). So here it is, the complete thing. XNote there was no version number at all in the PDmake distribution. If this Xis your first time seeing such buzzword as "PDmake", you should read the Xfles README, README.amiga first, and then come back here. X XMy changes include: X X * Define suffixes .asm, .a, .s to all be assembler source files. X X * Added macros LD, LDFLAGS and LDLIBS so a linker can be invoked. For X Manx compiler system: X X LD = ln # linker program name X LDFLAGS = X LDLIBS = -lc # link with c.lib library X X * Add internal suffix .~ to generate an executable from a found source X file. The match order looks for assembler suffixes before .c suffix. X X * Run without a makefile present; i.e. a command line: X X make "CCFLGS=+L" foo X X runs the following actions (with Manx 3.6a): X X cc +L foo.c X ln -o foo foo.o -lc X X if foo.c is found in the current directory (note: the "-o" in linker X command above is not LDFLAGS, it comes from built-in rules; see rules.c). X This type of operation works only as indicated above (one source file X that is self-contained). Not a big deal, but it lets you get your simple X stand-alone tester made without overworking your fingers. X X * Instead of stopping at a target that Make doesn't know how to make, it X now issues an error message and continues on. So: X X make "CCFLAGS=+L" foo bar X X make: Don't know how to make foo. X X cc +L bar.c X ln -o bar bar.o -lc X X would still make "bar" in the event that no foo.* is found. X X * Corrected errors in handling '#' comment marker in the makefile. Such X comment mark can appear anywhere, from it to the first end-of-line is X all skipped. Likewise, there was problem in the backslash continuation X handling. The Makefile included with this distribution contains comment X lines placed on purpose, to illustrate what I mean here. X X * Added "-?" option to list all options. X XOtherwise, the original features Steve Walton put in are left intact. XAs far as I can tell, nothing should break under Manx 5.0 compiler. X X XMissing "feaures": X X 1. This Make definitely has no such concept as "being run from WB". X X 2. It cannot call itself to travel down a directory tree (no MAKE macro X and certainly no MFLAGS environmental variable). X X 3. It does not support object libraries. X XNotes to those of you who do not use Manx compiler: X X This make was written to use MANX's fexec() call to invoke commands (and X get their exit status back). I have no idea how other compilers do this. X X To take advantage of the source-to-executable action, you need to have X at least LD macro defined in "rules.c" (toward the end) -- having LDFLAGS X and LDLIBS defined wouldn't hurt, but may prove to be inconvenient. Edit X rules.c, go to the end and back up to where "#ifdef amiga" is at. Look for X things that I did (they are marked by comments with "--hu"), use them as X templates to set up command rules for make to call your compiler/linker. X X XYour comments are welcome, but don't expect me to be your Amiga PDmake Xsupport, though. END_OF_FILE if test 3328 -ne `wc -c <'Changes.new'`; then echo shar: \"'Changes.new'\" unpacked with wrong size! fi # end of 'Changes.new' fi if test -f 'README' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'README'\" else echo shar: Extracting \"'README'\" \(1803 characters\) sed "s/^X//" >'README' <<'END_OF_FILE' XFollowing is a repost of the public domain 'make' that I posted Xto net.sources a couple of months ago. I have fixed a few bugs, and Xadded some more features, and the resulting changes amounted to Xabout as much text as the whole program (hence the repost). X XFor those that missed the net.sources posting, this is a public domain Xre-implementation of the UNIX make program. There is no manual included; Xfor documentation, refer to a UNIX manual, or the source. X XHere is a list of the changes made: X Xi) If '-' (ignore) or '@' (silent) where used at the start X of a command, their effect was not turned off for the following X commands. Xii) A special target (.SUFFIXES, .PRECIOUS) or a rule (.c.o, .a.o), X if first in the file would be taken as the default target. X This resulted in error messages like "Don't know how to X make .c", because things like .SUFFIXES were being made. X This was further complicated by --- Xiii) Special target lines with no dependents (ie. .SUFFIXES:\n) X were not clearing out the existing dependents like X they should. Xiv) Default rules could not be redefined because of the error X checking for commands being defined twice. Now you are X allowed to define a target beinging with '.', having X no dependents with commands. Xv) The -q option didn't do the time comparison correctly, X or clear the variable used to keep track of this. Thus X it didn't work very well. Xvi) The syntax ${..} for macro's supported by UNIX make was X not supported. Xvii) There wuz a couple of spelling errors. Xviii) When make checked for implicit rules on targets without X a suffix, there were problems. (Note: The ~ feature of X UNIX make wasn't and still isn't supported) Xix) The -n option did not print @ lines like it was supposed to. Xx) :: added. (See UNIX manual) Xxi) $? added. (see UNIX manual) END_OF_FILE if test 1803 -ne `wc -c <'README'`; then echo shar: \"'README'\" unpacked with wrong size! fi # end of 'README' fi if test -f 'README.amiga' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'README.amiga'\" else echo shar: Extracting \"'README.amiga'\" \(4397 characters\) sed "s/^X//" >'README.amiga' <<'END_OF_FILE' XThis program is the public domain Make program which appeared on Xmod.sources, Volume 7, number 91. I have ported it to the Amiga under XManx Aztec C version 3.40a. This short document assumes you know XMake, and simply points out the Amiga specific features of the Xprogram. The supported switches are listed in the comment block at Xthe beginning of module main.c. I offer no apologies for the fact that XI ran the code through "indent -i4 -nfc1" on the 4.3BSD system at work Xbefore I started working on it. X The program has been compiled under Manx Aztec C Version 3.40. XIt uses Manx's fexecv() function to execute commands and get Xtheir return value, and the Manx dos_packet() function to send an XAmigaDOS packet to the file system for touch'ing purposes. Lattice Xrecompilers need to change these (at least). Peculiar features Xof the Amiga version are: X X(1) The Amiga-specific sections of the code are #ifdef'd on the symbol X amiga (note the lower case). I endorse Fred Fish's effort to X have system and compiler-supplied #define's in lower case to X ensure no collisions with user-supplied ones. X(2) The file rules.c, routine makerules(), contains the definitions of X the default built-in rules. For the Amiga, these are equivalent to X the Makefile: X X CC = cc X CFLAGS = X AS = as X AFLAGS = X X .c.o: X $(CC) $(CFLAGS) $< X .s.o: X $(AS) $(AFLAGS) -o $@ $< X X (indented for clarity only). Thus, one could conceivably do: X make CC=lc CFLAGS= AS=asm X to run this make under Lattice C. X(3) If the file S:builtins.make exists, its contents are read in X instead of the built-in rules defined in makerules(). Thus, you X can use different default rules on different disks and change X the default rules without recompiling make. X(4) A Control-D typed during execution of a command by make will cause X an abort with exit status 1 AFTER the completion of that command. X Control-C is an immediate abort, as you might expect. X(5) Not really Amiga specific, but worth mentioning, is that characters X special both to the local operating system (such as : in AmigaDOS) and X to make may be used in the makefile by preceding them with \ X to temporarily override their special meaning. For example, to tell X make that RAM:foo depends on AC:foo.c, write: X X RAM\:foo : AC\:foo.c X X(6) The Aztec fexecv() function, which is used by make to execute its X commands, only works on programs in directories stored along the X AmigaDOS PATH, so make sure your PATH includes the appropriate X directories. X X Finally, I added one new feature in the non-machine-specific code: Xthe name of the makefile can be a single dash "-", in which case a Xmakefile is read from the standard input. X About the only feature of "real" make missing here is the Xsemicolon construct which allows a pair of lines such as the .c.o: Xrule and command above to be written as one line, viz: X .c.o: ; $(CC) $(CFLAGS) $< X XEnjoy! Bug reports in the Amiga-specific stuff should be directed to Xme; others should go to caret@fairlight.OZ, the author of the rest of it. XBy the way, this code is superior to the Manx-supplied make--more switches Xand a better parser; in fact, this make will handle the Makefile for XMicroGnuEmacs while Manx make chokes on the ln command. X X Steve Walton X ametek!walton@csvax.caltech.edu (ARPA) X WALTON@CALTECH (BITNET) X ...!ucbvax!sun!megatest!ametek!walton X XSome notes by Olaf Seibert, KosmoSoft: X XI adapted this version of make to PDC, and enhanced it a little. In Xparticular, if a line end with a backslash, the following newline and Xleading white space of the next line are now ignored. Previously, the Xnewline was merely turned into a space. Also, comparison of filenames now Xis case-insignificant. Makefiles need not be internally consistent in the Xcase of filenames. Also, the builtin rules are slightly different, for use Xwith PDC. X X CC = ccx -c X CFLAGS = X AS = ccx -c X AFLAGS = X X .c.o: X $(CC) $(CFLAGS) $< X .s.o: X $(AS) $(AFLAGS) $< X X /*OIS*0.80*/ X XI took out the \: feature, which worked only in target names, and not in Xprerequisite files. Instead, I added a more rational interpretation of Xcolons. There is now at most one colon possible in a target name, which may Xnot contain any spaces. X XI incorporared a few bug fixes relating to $< and $*, from the minix newsgroup. XI added a new feature: the .PATH special target. See manual. X END_OF_FILE if test 4397 -ne `wc -c <'README.amiga'`; then echo shar: \"'README.amiga'\" unpacked with wrong size! fi # end of 'README.amiga' fi if test -f 'an' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'an'\" else echo shar: Extracting \"'an'\" \(2210 characters\) sed "s/^X//" >'an' <<'END_OF_FILE' X.* X.* Macro package for NRO in KosmoSoft version X.* X.nr h 5 @" header indent X.nr i 10 @" normal text indent X.nr s @ni-@nh @" section heading indent (to the LEFT) X.* X.de TH X.in @nh;.rm 80-@nh;.he |$0($1)|$2|$0($1)| X.fo |$3|-#-|$4| X.in @ni;.rm 80-@ni X.ta +0 +5 X.en X.* Paragraph X.de PP X.sp 1;.ne 2;.ti +5 X.en X.* Bulleted Paragraph. Needs .RE after last para. X.* Must be last on line. Relies on first tab stop. X.de BP X.br;.in @ni+5;.ti -3;o@t@@ X.en X.* Section Heading X.de SH X.sp 1;.ne 3;.ti -@@ns;.bo "$0 $1 $2 $3 $4 $6 $6 $7 $8 $9 X.br X.en X.* SubSection X.de SS X.br;.ne 2;.ti -@@ns+1/2;$0 $1 $2 $3 $4 $5 $6 $7 $8 $9 X.br X.en X.* Relative indent Start X.de RS X.in +0$0 X.en X.* Relative indent End X.de RE X.in @ni X.en X.* Italics X.de I X.it 1 X$0 $1 $2 $3 $4 $5 $6 $7 $8 $9 X.en X.* Bold X.de B X.bo 1 X$0 $1 $2 $3 $4 $5 $6 $7 $8 $9 X.en X.* Underline X.de U X.ul 1 X$0 $1 $2 $3 $4 $5 $6 $7 $8 $9 X.en X.* UC X.de UC X.* Empty X.en X.* Italics and Roman X.de IR X.if !''$0' .it "$0 X.if !''$1' $1 X.if !''$2' .it "$2 X.if !''$3' $3 X.if !''$4' .it "$4 X.if !''$5' $5 X.if !''$6' .it "$6 X.if !''$7' $7 X.if !''$8' .it "$8 X.if !''$9' $9 X.en X.* Roman and Italic X.de RI X.if !''$0' $0 X.if !''$1' .it "$1 X.if !''$2' $2 X.if !''$3' .it "$3 X.if !''$4' $4 X.if !''$5' .it "$5 X.if !''$6' $6 X.if !''$7' .it "$7 X.if !''$8' $8 X.if !''$9' .it "$9 X.en X.* Bold and Roman X.de BR X.if !''$0' .bo "$0 X.if !''$1' $1 X.if !''$2' .bo "$2 X.if !''$3' $3 X.if !''$4' .bo "$4 X.if !''$5' $5 X.if !''$6' .bo "$6 X.if !''$7' $7 X.if !''$8' .bo "$8 X.if !''$9' $9 X.en X.* Bold and Italic X.de BI X.if !''$0' .bo "$0 X.if !''$1' .it "$1 X.if !''$2' .bo "$2 X.if !''$3' .it "$3 X.if !''$4' .bo "$4 X.if !''$5' .it "$5 X.if !''$6' .bo "$6 X.if !''$7' .it "$7 X.if !''$8' .bo "$8 X.if !''$9' .it "$9 X.en X.* Italic and Bold X.de IB X.if !''$0' .it "$0 X.if !''$1' .bo "$1 X.if !''$2' .it "$2 X.if !''$3' .bo "$3 X.if !''$4' .it "$4 X.if !''$5' .bo "$5 X.if !''$6' .it "$6 X.if !''$7' .bo "$7 X.if !''$8' .it "$8 X.if !''$9' .bo "$9 X.en X.* Italic and Roman X.de IR X.if !''$0' .it "$0 X.if !''$1' $1 X.if !''$2' .it "$2 X.if !''$3' $3 X.if !''$4' .it "$4 X.if !''$5' $5 X.if !''$6' .it "$6 X.if !''$7' $7 X.if !''$8' .it "$8 X.if !''$9' $9 X.en X.* SMall, do nothing X.de SM X$0 $1 $2 $3 $4 $5 $6 $7 $8 $9 X.en END_OF_FILE if test 2210 -ne `wc -c <'an'`; then echo shar: \"'an'\" unpacked with wrong size! fi # end of 'an' fi if test -f 'assign_macro.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'assign_macro.c'\" else echo shar: Extracting \"'assign_macro.c'\" \(1157 characters\) sed "s/^X//" >'assign_macro.c' <<'END_OF_FILE' X#include <stdio.h> X#include <string.h> X#include <ctype.h> X X/* 02/12/90 -- hu: X * New utility function for make to process a macro assignment string. X * Uses standard C string/ctype functions so it is not machine dependent. X * Called by input() and main(). X*/ Xvoid Xassign_macro (s) Xchar *s; /* s must be pre-checked for the presence of '=' */ X{ X char *name, *val; X register char *p, *q; X char svp, svq; X int use_empty = 0; X X /* bypass leading space */ X while (isspace (*s)) s++; X name = s; X X /* find the = char */ X p = strchr (s, '='); X if (p == name) return; X val = p + 1; X X if (*(p-1) == '\\') { X if ((p - 1) == name) return; X p--; X } X p--; X while (isspace(*p)) p--; X p++; X svp = *p; X *p = '\0'; X X /* now check the value part, we just need to see if null string */ X q = val; X while (*q != '\0' && isspace(*q)) q++; X if (*q == '\0') use_empty = 1; X else { X val = q; X q = val + strlen(val) - 1; X if (isspace(*q)) while (isspace(*q)) q--; X q++; X svq = *q; X *q = '\0'; X } X X if (use_empty) setmacro (name, " "); X else setmacro (name, val); X X /* restore original chars that we replaced with null */ X *p = svp; X if (use_empty == 0) *q = svq; X} END_OF_FILE if test 1157 -ne `wc -c <'assign_macro.c'`; then echo shar: \"'assign_macro.c'\" unpacked with wrong size! fi # end of 'assign_macro.c' fi if test -f 'check.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'check.c'\" else echo shar: Extracting \"'check.c'\" \(2152 characters\) sed "s/^X//" >'check.c' <<'END_OF_FILE' X/* X * Check structures for make. X */ X X#include <stdio.h> X#include "h.h" X X X/* X * Prints out the structures as defined in memory. Good for check X * that you make file does what you want (and for debugging make). X */ Xvoid Xprt() X{ X register struct name *np; X register struct depend *dp; X register struct line *lp; X register struct cmd *cp; X register struct macro *mp; X X X for (mp = macrohead; mp; mp = mp->m_next) X fprintf(stderr, "%s = %s\n", mp->m_name, mp->m_val); X X fputc('\n', stderr); X X for (np = namehead.n_next; np; np = np->n_next) { X if (np->n_flag & N_DOUBLE) X fprintf(stderr, "%s::\n", np->n_name); X else X fprintf(stderr, "%s:\n", np->n_name); X if (np == firstname) X fprintf(stderr, "(MAIN NAME)\n"); X for (lp = np->n_line; lp; lp = lp->l_next) { X fputc(':', stderr); X for (dp = lp->l_dep; dp; dp = dp->d_next) X fprintf(stderr, " %s", dp->d_name->n_name); X fputc('\n', stderr); X X for (cp = lp->l_cmd; cp; cp = cp->c_next) X#ifdef os9 X fprintf(stderr, "- %s\n", cp->c_cmd); X#else X fprintf(stderr, "-\t%s\n", cp->c_cmd); X#endif X fputc('\n', stderr); X } X fputc('\n', stderr); X } X} X X X/* X * Recursive routine that does the actual checking. X */ Xvoid Xcheck(np) X struct name *np; X{ X register struct depend *dp; X register struct line *lp; X X X if (np->n_flag & N_MARK) X fatal("Circular dependency from %s", np->n_name); X X np->n_flag |= N_MARK; X X for (lp = np->n_line; lp; lp = lp->l_next) X for (dp = lp->l_dep; dp; dp = dp->d_next) X check(dp->d_name); X X np->n_flag &= ~N_MARK; X} X X X/* X * Look for circular dependancies. X * ie. X * a: b X * b: a X * is a circular dep X */ Xvoid Xcirch() X{ X register struct name *np; X X X for (np = namehead.n_next; np; np = np->n_next) X check(np); X} X X X/* X * Check the target .PRECIOUS, and mark its dependentd as precious X */ Xvoid Xprecious() X{ X register struct depend *dp; X register struct line *lp; X register struct name *np; X X X if (!((np = newname(".PRECIOUS"))->n_flag & N_TARG)) X return; X X for (lp = np->n_line; lp; lp = lp->l_next) X for (dp = lp->l_dep; dp; dp = dp->d_next) X dp->d_name->n_flag |= N_PREC; X} END_OF_FILE if test 2152 -ne `wc -c <'check.c'`; then echo shar: \"'check.c'\" unpacked with wrong size! fi # end of 'check.c' fi if test -f 'h.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'h.h'\" else echo shar: Extracting \"'h.h'\" \(2546 characters\) sed "s/^X//" >'h.h' <<'END_OF_FILE' X/* X * Include header for make X */ X X X#ifndef uchar X#ifdef os9 X#define uchar char X#define void int X#define fputc putc X#else X#define uchar unsigned char X#endif X#endif X X#define bool uchar X#define time_t long X#define TRUE (1) X#define FALSE (0) X#define max(a,b) ((a)>(b)?(a):(b)) X X#define DEFN1 "makefile" /* Default names */ X#ifdef unix X#define DEFN2 "Makefile" X#endif X#ifdef eon X#define DEFN2 "Makefile" X#endif X X#ifdef amiga X#define strcmp stricmp X#endif X X/* os9 is case insensitive */ X X#define LZ (1024) /* Line size */ X X X X/* X * A name. This represents a file, either to be made, or existant X */ X Xstruct name { X struct name *n_next; /* Next in the list of names */ X char *n_name; /* Called */ X struct line *n_line; /* Dependencies */ X time_t n_time; /* Modify time of this name */ X uchar n_flag; /* Info about the name */ X}; X X#define N_MARK 0x01 /* For cycle check */ X#define N_DONE 0x02 /* Name looked at */ X#define N_TARG 0x04 /* Name is a target */ X#define N_PREC 0x08 /* Target is precious */ X#define N_DOUBLE 0x10 /* Double colon target */ X X/* X * Definition of a target line. X */ Xstruct line { X struct line *l_next; /* Next line (for ::) */ X struct depend *l_dep; /* Dependents for this line */ X struct cmd *l_cmd; /* Commands for this line */ X}; X X X/* X * List of dependents for a line X */ Xstruct depend { X struct depend *d_next; /* Next dependent */ X struct name *d_name; /* Name of dependent */ X}; X X X/* X * Commands for a line X */ Xstruct cmd { X struct cmd *c_next; /* Next command line */ X char *c_cmd; /* Command line */ X}; X X X/* X * Macro storage X */ Xstruct macro { X struct macro *m_next; /* Next variable */ X char *m_name; /* Called ... */ X char *m_val; /* Its value */ X uchar m_flag; /* Infinite loop check */ X}; X Xextern char *myname; Xextern struct name namehead; Xextern struct macro *macrohead; Xextern struct name *firstname; Xextern bool silent; Xextern bool ignore; Xextern bool rules; Xextern bool dotouch; Xextern bool quest; Xextern bool domake; Xextern char str1[]; Xextern char str2[]; Xextern int lineno; X Xchar *fgets(); Xchar *index(); Xchar *rindex(); Xchar *malloc(); Xextern int errno; X Xchar *getmacro(); Xstruct macro *setmacro(); Xvoid input(); Xvoid error(); Xvoid fatal(); Xint make(); Xstruct name *newname(); Xstruct depend *newdep(); Xstruct cmd *newcmd(); Xvoid newline(); Xchar *suffix(); Xvoid touch(); Xvoid makerules(); Xchar *gettok(); Xvoid precious(); END_OF_FILE if test 2546 -ne `wc -c <'h.h'`; then echo shar: \"'h.h'\" unpacked with wrong size! fi # end of 'h.h' fi if test -f 'input.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'input.c'\" else echo shar: Extracting \"'input.c'\" \(7073 characters\) sed "s/^X//" >'input.c' <<'END_OF_FILE' X/* X * Parse a makefile X */ X X X#include <stdio.h> X#include <ctype.h> X#include "h.h" X X Xstruct name namehead; Xstruct name *firstname; X Xchar str1[LZ]; /* General store */ Xchar str2[LZ]; X X X/* X * Intern a name. Return a pointer to the name struct X */ Xstruct name * Xnewname(name) X char *name; X{ X register struct name *rp; X register struct name *rrp; X register char *cp; X X X for X ( X rp = namehead.n_next, rrp = &namehead; X rp; X rp = rp->n_next, rrp = rrp->n_next X ) X if (strcmp(name, rp->n_name) == 0) X return rp; X X if ((rp = (struct name *) malloc(sizeof(struct name))) X == (struct name *) 0) X fatal("No memory for name"); X rrp->n_next = rp; X rp->n_next = (struct name *) 0; X if ((cp = malloc((unsigned) strlen(name) + 1)) == (char *) 0) X fatal("No memory for name"); X strcpy(cp, name); X rp->n_name = cp; X rp->n_line = (struct line *) 0; X rp->n_time = (time_t) 0; X rp->n_flag = 0; X X return rp; X} X X/* X * Delete the last created name. X */ X Xdelname(np) Xstruct name *np; X{ X if (namehead.n_next == np) { X namehead.n_next = np->n_next; X free(np); X } X} X X/* X * Add a dependant to the end of the supplied list of dependants. X * Return the new head pointer for that list. X */ Xstruct depend * Xnewdep(np, dp) X struct name *np; X struct depend *dp; X{ X register struct depend *rp; X register struct depend *rrp; X X X if ((rp = (struct depend *) malloc(sizeof(struct depend))) X == (struct depend *) 0) X fatal("No memory for dependant"); X rp->d_next = (struct depend *) 0; X rp->d_name = np; X X if (dp == (struct depend *) 0) X return rp; X X for (rrp = dp; rrp->d_next; rrp = rrp->d_next); X X rrp->d_next = rp; X X return dp; X} X X X/* X * Add a command to the end of the supplied list of commands. X * Return the new head pointer for that list. X */ Xstruct cmd * Xnewcmd(str, cp) X char *str; X struct cmd *cp; X{ X register struct cmd *rp; X register struct cmd *rrp; X register char *rcp; X X X if (rcp = rindex(str, '\n')) X *rcp = '\0'; /* Loose newline */ X X while (isspace(*str)) X str++; X X if (*str == '\0') /* If nothing left, the exit */ X return (struct cmd *) 0; X X if ((rp = (struct cmd *) malloc(sizeof(struct cmd))) X == (struct cmd *) 0) X fatal("No memory for command"); X rp->c_next = (struct cmd *) 0; X if ((rcp = malloc((unsigned) strlen(str) + 1)) == (char *) 0) X fatal("No memory for command"); X strcpy(rcp, str); X rp->c_cmd = rcp; X X if (cp == (struct cmd *) 0) X return rp; X X for (rrp = cp; rrp->c_next; rrp = rrp->c_next); X X rrp->c_next = rp; X X return cp; X} X X X/* X * Add a new 'line' of stuff to a target. This check to see X * if commands already exist for the target. If flag is set, X * the line is a double colon target. X * X * Kludges: X * i) If the new name begins with a '.', and there are no dependents, X * then the target must cease to be a target. This is for .SUFFIXES. X * ii) If the new name begins with a '.', with no dependents and has X * commands, then replace the current commands. This is for X * redefining commands for a default rule. X * Neither of these free the space used by dependents or commands, X * since they could be used by another target. X */ Xvoid Xnewline(np, dp, cp, flag) X struct name *np; X struct depend *dp; X struct cmd *cp; X bool flag; X{ X bool hascmds = FALSE; /* Target has commands */ X register struct line *rp; X register struct line *rrp; X X X /* Handle the .SUFFIXES case */ X if (np->n_name[0] == '.' && !dp && !cp) { X for (rp = np->n_line; rp; rp = rrp) { X rrp = rp->l_next; X free((char *) rp); X } X np->n_line = (struct line *) 0; X np->n_flag &= ~N_TARG; X return; X } X /* This loop must happen since rrp is used later. */ X for X ( X rp = np->n_line, rrp = (struct line *) 0; X rp; X rrp = rp, rp = rp->l_next X ) X if (rp->l_cmd) X hascmds = TRUE; X X if (hascmds && cp && !(np->n_flag & N_DOUBLE)) X /* Handle the implicit rules redefinition case */ X if (np->n_name[0] == '.' && dp == (struct depend *) 0) { X np->n_line->l_cmd = cp; X return; X } else X error("Commands defined twice for target %s", np->n_name); X if (np->n_flag & N_TARG) X if (!(np->n_flag & N_DOUBLE) != !flag) /* like xor */ X error("Inconsistent rules for target %s", np->n_name); X X if ((rp = (struct line *) malloc(sizeof(struct line))) X == (struct line *) 0) X fatal("No memory for line"); X rp->l_next = (struct line *) 0; X rp->l_dep = dp; X rp->l_cmd = cp; X X if (rrp) X rrp->l_next = rp; X else X np->n_line = rp; X X np->n_flag |= N_TARG; X if (flag) X np->n_flag |= N_DOUBLE; X} X X X/* X * Parse input from the makefile, and construct a tree structure X * of it. X */ Xvoid Xinput(fd) X FILE *fd; X{ X char *p; /* General */ X char *q; X struct name *np; X struct depend *dp; X struct cmd *cp; X bool dbl, getline(); X X X if (getline(str1, LZ, fd)) /* Read the first line */ X return; X X for (;;) { X if (str1[0] == '\t' || str1[0] == ' ') /* Rules without targets */ X error("Rules not allowed here"); X X p = str1; X X while (isspace(*p)) /* Find first target */ X p++; X X /* -- hu: if = exists in string, hand the string to assign_macro() */ X if ((q = index(p, '=')) != NULL) { X assign_macro (p); X if (getline(str1, LZ, fd)) return; X continue; X } X X expand(str1); X p = str1; X#if 0 X while (((q = index(p, ':')) != (char *) 0) && X (p != q) && (q[-1] == '\\')) { /* Find dependents */ X register char *a; X X a = q - 1; /* Del \ chr; move rest back */ X p = q; X while (*a++ = *q++); X } X#else X q = index(p, ':'); X#endif X X if (q == (char *) 0) X error("No targets provided"); X X /* Added by OIS to allow at most one : in target names */ X X { X register char *a = q; X X while (*++a) { X if (*a == ' ' || *a == '\t') { X /* Found no more colons. Must have been first one. */ X break; X } X if (*a == ':') { X /* Found second colon. This must be the separator. */ X if (a != q+1) /* No double colon */ X q = a; X break; X } X } X } X X *q++ = '\0'; /* Separate targets and dependents */ X X if (*q == ':') { /* Double colon */ X dbl = 1; X q++; X } else X dbl = 0; X X for (dp = (struct depend *) 0; ((p = gettok(&q)) != (char *) 0);) X /* get list of dep's */ X { X np = newname(p); /* Intern name */ X dp = newdep(np, dp);/* Add to dep list */ X } X X *((q = str1) + strlen(str1) + 1) = '\0'; X /* Need two nulls for gettok (Remember separation) */ X X cp = (struct cmd *) 0; X if (getline(str2, LZ, fd) == FALSE) { /* Get commands */ X while (str2[0] == '\t' || str2[0] == ' ') { /*OIS*0.80*/ X cp = newcmd(&str2[0], cp); X if (getline(str2, LZ, fd)) X break; X } X } X while ((p = gettok(&q)) != (char *) 0) { /* Get list of targ's */ X np = newname(p); /* Intern name */ X newline(np, dp, cp, dbl); X if (!firstname && p[0] != '.') X firstname = np; X } X X if (feof(fd)) /* EOF? */ X return; X X strcpy(str1, str2); X } X} END_OF_FILE if test 7073 -ne `wc -c <'input.c'`; then echo shar: \"'input.c'\" unpacked with wrong size! fi # end of 'input.c' fi if test -f 'macro.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'macro.c'\" else echo shar: Extracting \"'macro.c'\" \(2582 characters\) sed "s/^X//" >'macro.c' <<'END_OF_FILE' X/* X * Macro control for make X */ X X X#include "h.h" X#undef strcmp /*OIS*0.80*/ X Xstruct macro *macrohead; X X Xstruct macro * Xgetmp(name) X register char *name; X{ X register struct macro *rp; X X for (rp = macrohead; rp; rp = rp->m_next) X if (strcmp(name, rp->m_name) == 0) X return rp; X return (struct macro *) 0; X} X X Xchar * Xgetmacro(name) X char *name; X{ X struct macro *mp; X X if (mp = getmp(name)) X return mp->m_val; X else X return ""; X} X X Xstruct macro * Xsetmacro(name, val) X char *name; X char *val; X{ X register struct macro *rp; X register char *cp; X X X /* Replace macro definition if it exists */ X for (rp = macrohead; rp; rp = rp->m_next) X if (strcmp(name, rp->m_name) == 0) { X free(rp->m_val); /* Free space from old */ X break; X } X if (!rp) { /* If not defined, allocate space for new */ X if ((rp = (struct macro *) malloc(sizeof(struct macro))) X == (struct macro *) 0) X fatal("No memory for macro"); X X rp->m_next = macrohead; X macrohead = rp; X rp->m_flag = FALSE; X X if ((cp = malloc((unsigned) strlen(name) + 1)) == (char *) 0) X fatal("No memory for macro"); X strcpy(cp, name); X rp->m_name = cp; X } X if ((cp = malloc((unsigned) strlen(val) + 1)) == (char *) 0) X fatal("No memory for macro"); X strcpy(cp, val); /* Copy in new value */ X rp->m_val = cp; X X return rp; X} X X X/* X * Do the dirty work for expand X */ Xvoid Xdoexp(to, from, len, buf) X char **to; X char *from; X int *len; X char *buf; X{ X register char *rp; X register char *p; X register char *q; X register struct macro *mp; X X X rp = from; X p = *to; X while (*rp) { X if (*rp != '$') { X *p++ = *rp++; X (*len)--; X } else { X q = buf; X if (*++rp == '{') X while (*++rp && *rp != '}') X *q++ = *rp; X else if (*rp == '(') X while (*++rp && *rp != ')') X *q++ = *rp; X else if (!*rp) { X *p++ = '$'; X break; X } else X *q++ = *rp; X *q = '\0'; X if (*rp) X rp++; X if (!(mp = getmp(buf))) X mp = setmacro(buf, ""); X if (mp->m_flag) X fatal("Infinitely recursive macro %s", mp->m_name); X mp->m_flag = TRUE; X *to = p; X doexp(to, mp->m_val, len, buf); X p = *to; X mp->m_flag = FALSE; X } X if (*len <= 0) X error("Expanded line too long"); /*OIS*0.80*/ X } X *p = '\0'; X *to = p; X} X X X/* X * Expand any macros in str. X */ Xvoid Xexpand(str) X char *str; X{ X static char a[LZ]; X static char b[LZ]; X char *p = str; X int len = LZ - 1; X X strcpy(a, str); X doexp(&p, a, &len, b); X} END_OF_FILE if test 2582 -ne `wc -c <'macro.c'`; then echo shar: \"'macro.c'\" unpacked with wrong size! fi # end of 'macro.c' fi if test -f 'main.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'main.c'\" else echo shar: Extracting \"'main.c'\" \(6566 characters\) sed "s/^X//" >'main.c' <<'END_OF_FILE' X/* X * make [-f makefile] [-ins] [target(s) ...] X * X * (Better than EON mk but not quite as good as UNIX make) X * X * -f makefile name X * -i ignore exit status X * -n Pretend to make X * -p Print all macros & targets X * -q Question up-to-dateness of target. Return exit status 1 if not X * -r Don't not use inbuilt rules X * -s Make silently X * -t Touch files instead of making them X * -m Change memory requirements (EON only) X */ X X#include <stdio.h> X#include "h.h" X X#ifdef unix X#include <sys/errno.h> X#endif X#ifdef eon X#include <sys/err.h> X#endif X#ifdef os9 X#include <errno.h> X#endif X#ifdef amiga X#include <errno.h> X#endif X X#ifdef eon X#define MEMSPACE (16384) X#endif X X Xchar *myname; Xchar *makefile; /* The make file */ X#ifdef eon Xunsigned memspace = MEMSPACE; X#endif X XFILE *ifd; /* Input file desciptor */ Xbool domake = TRUE; /* Go through the motions option */ Xbool ignore = FALSE; /* Ignore exit status option */ Xbool silent = FALSE; /* Silent option */ Xbool print = FALSE; /* Print debuging information */ Xbool rules = TRUE; /* Use inbuilt rules */ Xbool dotouch = FALSE;/* Touch files instead of making */ Xbool quest = FALSE; /* Question up-to-dateness of file */ X X Xvoid Xmain(argc, argv) X register int argc; X register char **argv; X{ X register char *p; /* For argument processing */ X int estat = 0; /* For question */ X register struct name *np; X void prt(), circh(); X X myname = (argc-- < 1) ? "make" : *argv++; X X while ((argc > 0) && (**argv == '-')) { X argc--; /* One less to process */ X p = *argv++; /* Now processing this one */ X X while (*++p != '\0') { X switch (*p) { X case 'f': /* Alternate file name */ X if (*++p == '\0') { X if (argc-- <= 0) X usage(); X p = *argv++; X } X makefile = p; X goto end_of_args; X#ifdef eon X case 'm': /* Change space requirements */ X if (*++p == '\0') { X if (argc-- <= 0) X usage(); X p = *argv++; X } X memspace = atoi(p); X goto end_of_args; X#endif X case 'n': /* Pretend mode */ X domake = FALSE; X break; X case 'i': /* Ignore fault mode */ X ignore = TRUE; X break; X case 's': /* Silent about commands */ X silent = TRUE; X break; X case 'p': X print = TRUE; X break; X case 'r': X rules = FALSE; X break; X case 't': X dotouch = TRUE; X break; X case 'q': X quest = TRUE; X break; X default: /* Wrong option */ X usage(); X } X } Xend_of_args:; X } X X#ifdef amiga X if ((ifd = fopen("s:builtins.make", "r")) != (FILE *) 0) { X input(ifd); X fclose(ifd); X } else X#endif X makerules(); X X#ifdef eon X if (initalloc(memspace) == 0xffff) /* Must get memory for alloc */ X fatal("Cannot initalloc memory"); X#endif X X if (! makefile) { /* If no file, then use default */ X if ((ifd = fopen(DEFN1, "r")) == (FILE *) 0) X#ifdef eon X if (errno != ER_NOTF) X fatal("Can't open %s; error %02x", DEFN1, errno); X#endif X#ifdef unix X if (errno != ENOENT) X fatal("Can't open %s; error %02x", DEFN1, errno); X#endif X#ifdef amiga X if (errno != ENOENT) X fatal("Can't open %s; error %02x", DEFN1, errno); X#endif X#ifdef DEFN2 X if ((ifd == (FILE *) 0) X && ((ifd = fopen(DEFN2, "r")) == (FILE *) 0)) X fatal("Can't open %s", DEFN2); X#else X /* -- hu: do nothing so we may process command line later */ X#endif X } else if (strcmp(makefile, "-") == 0) /* Can use stdin as makefile */ X ifd = stdin; X else if ((ifd = fopen(makefile, "r")) == (FILE *) 0) X ; /* -- hu: again, no makefile is fine here */ X X /* -- hu: if valid makefile exists, read it in now */ X if (ifd != (FILE *)0) { X input(ifd); /* Input all the gunga */ X fclose(ifd); /* Finished with makefile */ X } X lineno = 0; /* Any calls to error now print no line X * number */ X X setmacro ("$", "$"); X X /* -- hu: overwrite/add command line macro assignments */ X while (argc && (p = index(*argv, '='))) { X assign_macro(*argv); X argv++; X argc--; X } X X if (print) X prt(); /* Print out structures */ X X np = newname(".SILENT"); X if (np->n_flag & N_TARG) X silent = TRUE; X X np = newname(".IGNORE"); X if (np->n_flag & N_TARG) X ignore = TRUE; X X precious(); X X /* Check circles in target definitions */ X if (! firstname) circh(); X X /* -- hu: no command line arg, if target defined from makefile, do it */ X if (argc == 0) { X if (! firstname) estat = make(firstname, 0); X } X else /* treat command line args as targets to make */ X while (argc--) { X if (!print && !silent && strcmp(*argv, "love") == 0) { X if (strcmp(myname, "make") == 0) /* -- hu: humor them */ X printf("With me?\n"); X else printf("Not War!\n"); X } X else estat |= make(newname(*argv++), 0); X } X X if (quest) exit (estat); X else exit (0); X} X X Xusage() X{ X fprintf(stderr, X"Usage: %s [-f makefile] [-inpqrst] [macro=val ...] [target(s) ...]\n", myname); X fprintf(stderr,"\n"); X fprintf(stderr," -f file Use `file' instead of `M/makefile'\n"); X fprintf(stderr," -i Ignore invoked command errors (continue regardless)\n"); X fprintf(stderr," -n No make (just print actions to be taken)\n"); X fprintf(stderr," -p Print all macros & targets\n"); X fprintf(stderr," -q Check if target is up-to-date. Exit 1 if not\n"); X fprintf(stderr," -r Don't use built-in rules\n"); X fprintf(stderr," -s Make silently\n"); X fprintf(stderr," -t Touch needed files instead of making them\n"); X#ifdef eon X fprintf(stderr," -m Change memory requirements (EON only)\n"); X#endif X exit(1); X} X X Xvoid Xfatal(msg, a1, a2, a3, a4, a5, a6) X char *msg; X{ X fprintf(stderr, "%s: ", myname); X fprintf(stderr, msg, a1, a2, a3, a4, a5, a6); X fputc('\n', stderr); X exit(1); X} X X#ifdef amiga /*OIS*0.80*/ X X/* X * The Amiga case-insensitive filing system needs a case-insensitive X * filename comparison. Since strcmp() in this make is only applied to X * filenames, we simply replace it. X * Unfortunately, this also affects .PRECIOUS, .IGNORE, .SUFFIXES and X * .SILENT. Therefore, we need a hack, but that costs space, so we don't. X */ X Xint lower(c) Xregister unsigned int c; X{ X if (c >= 'A' && c <= 'Z') X return c - 'A' + 'a'; X X return c; X} X Xint stricmp(first, second) /* Case-insensitive strcmp() */ Xregister unsigned char *first, *second; X{ X register int cmp; X X while (!(cmp = lower(*first++) - lower(*second++))) { X if (!first[-1]) return 0; X } X X return (cmp < 0) ? -1 : 1; X} X X/* Manx and PDC allow you to leave out Workbench code */ X X_wb_parse(){} X X#endif END_OF_FILE if test 6566 -ne `wc -c <'main.c'`; then echo shar: \"'main.c'\" unpacked with wrong size! fi # end of 'main.c' fi if test -f 'make.n' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'make.n'\" else echo shar: Extracting \"'make.n'\" \(7344 characters\) sed "s/^X//" >'make.n' <<'END_OF_FILE' X.so an X.de HP X.ti -5 X.en X.TH MAKE 1 "AMIGA Programmer's Manual" X.SH NAME Xmake - maintain program groups X.SH SYNTAX Xmake [ -f makefile ] [ option ] ... file ... X.SH DESCRIPTION X.I Make Xexecutes commands in X.I makefile Xto update one or more target X.I names. Name Xis typically a program. If no -f option Xis present, `makefile' and `Makefile' are tried in order. XIf X.I makefile Xis `-', the standard input is taken. More than one -f option may appear. X X.I Make Xupdates a target if it depends on prerequisite files that have been Xmodified since the target was last modified, or if the target does not Xexist. X X.I Makefile Xcontains a sequence of entries that specify dependencies. The first line of Xan entry is a blank-separated list of targets, then a colon, then a list of Xprerequisite files. Text following a semicolon, and all following lines Xthat begin with a tab, are shell commands to be executed to update the Xtarget. If a name appears on the left of more than one `colon' line, then Xit depends on all of the names on the right of the colon on those lines, Xbut only one command sequence may be specified for it. If a name appears on Xa line with a double colon :: then the command sequence following that line Xis performed only if the name is out of date with respect to the names to Xthe right of the double colon, and is not affected by other double colon Xlines on which that name may appear. X XTwo special forms of a name are recognized. A name like X.I a(b) Xmeans the file named X.I b Xstored in the archive named X.I a. XA name like X.I a((b)) Xmeans the file stored in archive a containing the entry point X.I b. X XSharp and newline surround comments. X XThe following makefile says that `pgm' depends on two files `a.o' and X`b.o', and that they in turn depend on `.c' files and a common file `incl'. X X pgm: a.o b.o X cc a.o b.o -lm -o pgm X a.o: incl a.c X cc -c a.c X b.o: incl b.c X cc -c b.c X X.I Makefile Xentries of the form X X string1 = string2 X Xare macro definitions. Subsequent appearances of X.I $(string1) Xor X.I ${string1} Xare replaced by X.I string2. XIf X.I string1 Xis a single character, the parentheses or braces are optional. X X.I Make Xinfers prerequisites for files for which X.I makefile Xgives no construction commands. For example, a `.c' file may be inferred as Xprerequisite for a `.o' file and be compiled to produce the `.o' file. Thus Xthe preceding example can be done more briefly: X X pgm: a.o b.o X cc a.o b.o -lm -o pgm X a.o b.o: incl X XPrerequisites are inferred according to selected suffixes listed as the X`prerequisites' for the special name `.SUFFIXES'; multiple lists Xaccumulate; an empty list clears what came before. Order is significant; Xthe first possible name for which both a file and a rule as described in Xthe next paragraph exist is inferred. The default list is X X .SUFFIXES: .out .o .c .e .r .f .y .l .s .p X XThe rule to create a file with suffix X.I s2 Xthat depends on a similarly named file with suffix X.I s1 Xis specified as an entry for the `target' X.I s1s2. XIn such an entry, the special macro $* stands for the target name with Xsuffix deleted, $@@ for the full target name, $< for the complete list of Xprerequisites, and $? for the list of prerequisites that are out of date. XFor example, a rule for making optimized `.o' files from `.c' files is X X .c.o: ; cc -c -O -o $@@ $*.c X XCertain macros are used by the default inference rules to communicate Xoptional arguments to any resulting compilations. In particular, `CFLAGS' Xis used for X.I cc(1) Xoptions, `FFLAGS' for X.I f77(1) Xoptions, `PFLAGS' for X.I pc(1) Xoptions, and `LFLAGS' and `YFLAGS' for X.I lex Xand X.I yacc(1) Xoptions. In addition, the macro `MFLAGS' is filled in with the initial Xcommand line options supplied to X.I make. XThis simplifies maintaining a hierarchy of makefiles as one may then invoke X.I make Xon makefiles in subdirectories and pass along useful options such as -k. X XCommand lines are executed one at a time, each by its own shell. A line is Xprinted when it is executed unless the special target `.SILENT' is in X.I makefile, Xor the first character of the command is `@@'. X XCommands returning nonzero status (see X.I intro(1)) Xcause X.I make Xto terminate unless the special target `.IGNORE' is in X.I makefile Xor the command begins with <tab><hyphen>. X XInterrupt and quit cause the target to be deleted unless the target is a Xdirectory or depends on the special name `.PRECIOUS'. X XOther options: X X.RS +5 X.HP X-i@tEquivalent to the special entry `.IGNORE:'. X X.HP X-k@tWhen a command returns nonzero status, abandon work on the current Xentry, but continue on branches that do not depend on the current entry. X X.HP X-n@tTrace and print, but do not execute the commands needed to update the Xtargets. X X.HP X-t@tTouch, i.e. update the modified date of targets, without executing any Xcommands. X X.HP X-r@tEquivalent to an initial special entry `.SUFFIXES:' with no list. X X.HP X-s@tEquivalent to the special entry `.SILENT:'. X X.HP X-q@tQuestion up-to-dateness of target. Return exit status 1 if not; Xotherwise, return 0. X X.HP X-r@tDon't use built-in rules. X.RE X.SH FILES Xmakefile, Makefile X.SH "SEE ALSO" Xsh(1), touch(1), f77(1), pc(1) X.br XS. I. Feldman X.I "Make - A Program for Maintaining Computer Programs" X.SH BUGS XSome commands return nonzero status inappropriately. Use -i Xto overcome the difficulty. XCommands that are directly executed by the shell, notably X.I cd(1), Xare ineffectual across newlines in X.I make. X.SH "AMIGA VERSION" XNot all of the above applies to the Amiga version of X.I make. XIn particular, the default rules and suffixes are different. X XOmissions: X.br XLibraries and the related notation are not implemented. X.br XThe -k option is not supported. X.br XThe `;' construct is not implemented. X.br XThe remarks related to X.I MFLAGS, lex(1), yacc(1), f77(1) Xand X.I pc(1) Xdo not apply. X.br X$< and $? are not exactly as specified: $< is ONE prerequisite that is out Xof date (including path name), and $? is ALL prerequisites (without path Xnames). X XAdditions: X.br XIf a file X.I s:builtins.make Xexists, this file is used instead of the built-in rules. X.br XFilenames are not case-significant. Unfortunately, this also applies to the Xspecial target names .PRECIOUS, .IGNORE and .SILENT. These can also be Xspecified as .Precious, or .iGnOrE. X.br X.I Cd Xcommands are effective. X.br XComment characters (#) may be escaped with a backslash (\). X.br XAt most 1 colon is allowed in a target file name (for including device Xnames). In that case, the trailing colon must follow the target name Ximmediately, without any intervening white space. Spaces in the names are Xnot allowed. X.br XA new special target name has been added: X.it "@.PATH. XAny prerequisite names for X.it "@.PATH Xare used for finding source files for implicit rules. You name one or more Xdirectories, and if the source file for an implicit rule cannot be found Xin the current directory, each of the the given pathnames is prepended (in Xthe order given) to the source name, until the file is found. X XFor instance, the Makefile X X .PATH: src/ include/ src/old X X pgm: pgm.o X Xwill look (according to the .c.o rule) for pgm.c, src/pgm.c, include/pgm.c Xand src/oldpgm.c, in that order. Of course, due to other implicit rules, Xother files (with other suffixes) may be tried as well. END_OF_FILE if test 7344 -ne `wc -c <'make.n'`; then echo shar: \"'make.n'\" unpacked with wrong size! fi # end of 'make.n' fi if test -f 'makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'makefile'\" else echo shar: Extracting \"'makefile'\" \(580 characters\) sed "s/^X//" >'makefile' <<'END_OF_FILE' X# Makefile for PDmake (to use MANX 3.6a compiler/linker) X# X# +L so integers are 32-bit long. X# X# (I wish people who release makefiles will pick this up as a habit: note X# what your various option flags mean, so that those who don't use the same X# compiler as you can still understand what is happening. -huver) X XCFLAGS=+L -Damiga -Dmanx #-Dpdc XCC=cc X XOBJS = main.o make.o rules.o reader.o \ X # comment embeded in continuation X input.o macro.o assign_macro.o check.o X Xm: $(OBJS) X ln -o m $(OBJS) -lc X Xclean: $(OBJS) X delete $(OBJS) X Xman: make.n an X nro >make.man make.n END_OF_FILE if test 580 -ne `wc -c <'makefile'`; then echo shar: \"'makefile'\" unpacked with wrong size! fi # end of 'makefile' fi if test -f 'reader.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'reader.c'\" else echo shar: Extracting \"'reader.c'\" \(2516 characters\) sed "s/^X//" >'reader.c' <<'END_OF_FILE' X/* X * Read in makefile X */ X X X#include <stdio.h> X#include <ctype.h> X#include "h.h" X X Xint lineno; X X X/* X * Syntax error handler. Print message, with line number, and exits. X */ Xvoid Xerror(msg, a1, a2, a3) X char *msg; X{ X fprintf(stderr, "%s: ", myname); X fprintf(stderr, msg, a1, a2, a3); X if (lineno) X fprintf(stderr, " near line %d", lineno); X fputc('\n', stderr); X exit(1); X} X X X/* X * Read a line into the supplied buffer of length 'size'. Remove X * comments, ignore blank lines. Deal with quoted (\) #, and X * quoted newlines. If EOF return TRUE. X * X * -hu: "Deal with quoted #"? What the bloody heck is that? '#' is a X * comment introducer, from it to end-of-line should be ignored. X */ Xbool Xgetline (str, size, fd) Xchar *str; Xint size; XFILE *fd; X{ X register char *p; X register char *q; /*OIS*0.80*/ X register char *buf; X int pos = 0; X X size--; /* disccount one byte for null terminator */ X X for (;;) { X X if ((size - pos) <= 0) error ("Line too long"); X buf = str + pos; X if (fgets(buf, size - pos, fd) == NULL) X return TRUE; /* EOF */ X X lineno++; X if ((p = index(buf, '\n')) == NULL) error("Line too long"); X X /* strip out comment */ X if ((p = index(buf, '#')) != NULL) { X if (p == buf) continue; X *p = '\0'; X } X X /* empty line ? */ X for (p = buf; isspace(*p); p++); X if (*p == '\0') continue; X X /* compress leading spaces from continued line(s) */ X if (pos && p != buf) X for (q = buf; (*q = *p) != '\0'; q++, p++); X X /* look at last char */ X p = buf + strlen(buf) - 1; X X /* skip trailing white spaces -- we know now the line isn't empty */ X while ( isspace (*p)) p--; X X /* backslash continuation? */ X if (*p == '\\') { X /* compress whitespaces before \ char */ X p--; X while (isspace(*p)) p--; X *++p = ' '; /* replace with single space */ X pos = (++p) - str; /* go read more */ X continue; X } X *++p = '\n'; X return FALSE; /* a valid line is read in */ X } X} X X X/* X * Get a word from the current line, surounded by white space. X * return a pointer to it. String returned has no white spaces X * in it. X */ Xchar * Xgettok(ptr) X register char **ptr; /*OIS*0.80*/ X{ X register char *p; X X X while (isspace(**ptr)) /* Skip spaces */ X (*ptr)++; X X if (**ptr == '\0') /* Nothing after spaces */ X return NULL; X X p = *ptr; /* word starts here */ X X while ((**ptr != '\0') && (!isspace(**ptr))) X (*ptr)++; /* Find end of word */ X X *(*ptr)++ = '\0'; /* Terminate it */ X X return (p); X} END_OF_FILE if test 2516 -ne `wc -c <'reader.c'`; then echo shar: \"'reader.c'\" unpacked with wrong size! fi # end of 'reader.c' fi echo shar: End of archive 1 \(of 2\). cp /dev/null ark1isdone MISSING="" for I in 1 2 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked both archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Mail submissions (sources or binaries) to <amiga@cs.odu.edu>. Mail comments to the moderator at <amiga-request@cs.odu.edu>. Post requests for sources, and general discussion to comp.sys.amiga.