--- /dev/null
+Makefile
+README
+check.c
+h.h
+input.c
+macro.c
+main.c
+make.c
+reader.c
+rules.c
--- /dev/null
+# Makefile for make!
+EMHOME=../..
+
+OBJS = check.o input.o macro.o main.o \
+ make.o reader.o rules.o
+# unix not defined under Xenix ???
+CFLAGS = -Dunix
+
+all: make
+
+install: make
+ cp make $(EMHOME)/bin/make
+
+cmp: make
+ cmp make $(EMHOME)/bin/make
+
+clean:
+ rm -f *.o make
+
+pr:
+ @pr README Makefile h.h main.c check.c input.c macro.c make.c reader.c rules.c
+
+opr:
+ make pr ^ opr
+
+make: $(OBJS)
+ $(CC) -i -o make $(OBJS)
+
+$(OBJS): h.h
--- /dev/null
+Following is a repost of the public domain 'make' that I posted
+to net.sources a couple of months ago. I have fixed a few bugs, and
+added some more features, and the resulting changes amounted to
+about as much text as the whole program (hence the repost).
+
+For those that missed the net.sources posting, this is a public domain
+re-implementation of the UNIX make program. There is no manual included;
+for documentation, refer to a UNIX manual, or the source.
+
+Here is a list of the changes made:
+
+i) If '-' (ignore) or '@' (silent) where used at the start
+ of a command, their effect was not turned off for the following
+ commands.
+ii) A special target (.SUFFIXES, .PRECIOUS) or a rule (.c.o, .a.o),
+ if first in the file would be taken as the default target.
+ This resulted in error messages like "Don't know how to
+ make .c", because things like .SUFFIXES were being made.
+ This was further complicated by ---
+iii) Special target lines with no dependents (ie. .SUFFIXES:\n)
+ were not clearing out the existing dependents like
+ they should.
+iv) Default rules could not be redefined because of the error
+ checking for commands being defined twice. Now you are
+ allowed to define a target beinging with '.', having
+ no dependents with commands.
+v) The -q option didn't do the time comparison correctly,
+ or clear the variable used to keep track of this. Thus
+ it didn't work very well.
+vi) The syntax ${..} for macro's supported by UNIX make was
+ not supported.
+vii) There wuz a couple of spelling errors.
+viii) When make checked for implicit rules on targets without
+ a suffix, there were problems. (Note: The ~ feature of
+ UNIX make wasn't and still isn't supported)
+ix) The -n option did not print @ lines like it was supposed to.
+x) :: added. (See UNIX manual)
+xi) $? added. (see UNIX manual)
+
+Hacked further by Ceriel Jacobs to make it work better. Use this "make" to
+install ACK under Microsoft Xenix V3.2. Some of the makefiles are just too
+big for the Xenix "make". Strange, they work on a PDP-11 ...
--- /dev/null
+/*
+ * Check structures for make.
+ *
+ * $Header$
+ */
+
+#include <stdio.h>
+#include "h.h"
+
+
+/*
+ * Prints out the structures as defined in memory. Good for check
+ * that you make file does what you want (and for debugging make).
+ */
+void
+prt()
+{
+ register struct name * np;
+ register struct depend * dp;
+ register struct line * lp;
+ register struct cmd * cp;
+ register struct macro * mp;
+
+
+ for (mp = macrohead; mp; mp = mp->m_next)
+ fprintf(stderr, "%s = %s\n", mp->m_name, mp->m_val);
+
+ fputc('\n', stderr);
+
+ for (np = namehead.n_next; np; np = np->n_next)
+ {
+ if (np->n_flag & N_DOUBLE)
+ fprintf(stderr, "%s::\n", np->n_name);
+ else
+ fprintf(stderr, "%s:\n", np->n_name);
+ if (np == firstname)
+ fprintf(stderr, "(MAIN NAME)\n");
+ for (lp = np->n_line; lp; lp = lp->l_next)
+ {
+ fputc(':', stderr);
+ for (dp = lp->l_dep; dp; dp = dp->d_next)
+ fprintf(stderr, " %s", dp->d_name->n_name);
+ fputc('\n', stderr);
+
+ for (cp = lp->l_cmd; cp; cp = cp->c_next)
+#ifdef os9
+ fprintf(stderr, "- %s\n", cp->c_cmd);
+#else
+ fprintf(stderr, "-\t%s\n", cp->c_cmd);
+#endif
+ fputc('\n', stderr);
+ }
+ fputc('\n', stderr);
+ }
+}
+
+
+/*
+ * Recursive routine that does the actual checking.
+ */
+void
+check(np)
+struct name * np;
+{
+ register struct depend * dp;
+ register struct line * lp;
+
+
+ if (np->n_flag & N_MARK)
+ fatal("Circular dependency from %s", np->n_name);
+
+ np->n_flag |= N_MARK;
+
+ for (lp = np->n_line; lp; lp = lp->l_next)
+ for (dp = lp->l_dep; dp; dp = dp->d_next)
+ check(dp->d_name);
+
+ np->n_flag &= ~N_MARK;
+}
+
+
+/*
+ * Look for circular dependancies.
+ * ie.
+ * a: b
+ * b: a
+ * is a circular dep
+ */
+void
+circh()
+{
+ register struct name * np;
+
+
+ for (np = namehead.n_next; np; np = np->n_next)
+ check(np);
+}
+
+
+/*
+ * Check the target .PRECIOUS, and mark its dependentd as precious
+ */
+void
+precious()
+{
+ register struct depend * dp;
+ register struct line * lp;
+ register struct name * np;
+
+
+ if (!((np = newname(".PRECIOUS"))->n_flag & N_TARG))
+ return;
+
+ for (lp = np->n_line; lp; lp = lp->l_next)
+ for (dp = lp->l_dep; dp; dp = dp->d_next)
+ dp->d_name->n_flag |= N_PREC;
+}
--- /dev/null
+/*
+ * Include header for make
+ *
+ * $Header$
+ */
+
+
+#ifndef uchar
+#ifdef os9
+#define uchar char
+#define void int
+#define fputc putc
+#else
+#define uchar unsigned char
+#endif
+#endif
+
+#define bool int
+#define time_t long
+#define TRUE (1)
+#define FALSE (0)
+#define max(a,b) ((a)>(b)?(a):(b))
+
+#define DEFN1 "makefile" /* Default names */
+#ifdef unix
+#define DEFN2 "Makefile"
+#endif
+#ifdef eon
+#define DEFN2 "Makefile"
+#endif
+/* os9 is case insensitive */
+
+#define LZ (2048) /* Line size */
+
+
+
+/*
+ * A name. This represents a file, either to be made, or existant
+ */
+
+struct name
+{
+ struct name * n_next; /* Next in the list of names */
+ char * n_name; /* Called */
+ struct line * n_line; /* Dependencies */
+ time_t n_time; /* Modify time of this name */
+ uchar n_flag; /* Info about the name */
+};
+
+#define N_MARK 0x01 /* For cycle check */
+#define N_DONE 0x02 /* Name looked at */
+#define N_TARG 0x04 /* Name is a target */
+#define N_PREC 0x08 /* Target is precious */
+#define N_DOUBLE 0x10 /* Double colon target */
+
+/*
+ * Definition of a target line.
+ */
+struct line
+{
+ struct line * l_next; /* Next line (for ::) */
+ struct depend * l_dep; /* Dependents for this line */
+ struct cmd * l_cmd; /* Commands for this line */
+};
+
+
+/*
+ * List of dependents for a line
+ */
+struct depend
+{
+ struct depend * d_next; /* Next dependent */
+ struct name * d_name; /* Name of dependent */
+};
+
+
+/*
+ * Commands for a line
+ */
+struct cmd
+{
+ struct cmd * c_next; /* Next command line */
+ char * c_cmd; /* Command line */
+};
+
+
+/*
+ * Macro storage
+ */
+struct macro
+{
+ struct macro * m_next; /* Next variable */
+ char * m_name; /* Called ... */
+ char * m_val; /* Its value */
+ uchar m_flag; /* Infinite loop check */
+ uchar m_prio; /* 5 levels:
+ - 0 for internal ($(CC), etc)
+ - 1 (reserved for environment)
+ - 2 for makefile
+ - 3 for command line
+ - 4 for special ($*,$<, etc)
+ */
+};
+
+extern char * myname;
+extern struct name namehead;
+extern struct macro * macrohead;
+extern struct name * firstname;
+extern bool silent;
+extern bool ignore;
+extern bool rules;
+extern bool dotouch;
+extern bool quest;
+extern bool domake;
+extern char str1[];
+extern char str2[];
+extern int lineno;
+
+char * fgets();
+char * index();
+char * rindex();
+char * malloc();
+char * strcpy();
+char * strcat();
+extern int errno;
+
+void circh();
+char * getmacro();
+struct macro * setmacro();
+void input();
+void error();
+void expand();
+void fatal();
+int make();
+void modtime();
+struct name * newname();
+struct depend * newdep();
+struct cmd * newcmd();
+void newline();
+void prt();
+char * suffix();
+void touch();
+void makerules();
+char * gettok();
+void precious();
--- /dev/null
+/*
+ * Parse a makefile
+ *
+ * $Header$
+ */
+
+
+#include <stdio.h>
+#include <ctype.h>
+#include "h.h"
+
+
+struct name namehead;
+struct name * firstname;
+
+char str1[LZ]; /* General store */
+char str2[LZ];
+
+
+/*
+ * Intern a name. Return a pointer to the name struct
+ */
+struct name *
+newname(name)
+char * name;
+{
+ register struct name * rp;
+ register struct name * rrp;
+ register char * cp;
+
+
+ for
+ (
+ rp = namehead.n_next, rrp = &namehead;
+ rp;
+ rp = rp->n_next, rrp = rrp->n_next
+ )
+ if (strcmp(name, rp->n_name) == 0)
+ return rp;
+
+ if ((rp = (struct name *)malloc(sizeof (struct name)))
+ == (struct name *)0)
+ fatal("No memory for name");
+ rrp->n_next = rp;
+ rp->n_next = (struct name *)0;
+ if ((cp = malloc((unsigned)(strlen(name)+1))) == (char *)0)
+ fatal("No memory for name");
+ strcpy(cp, name);
+ rp->n_name = cp;
+ rp->n_line = (struct line *)0;
+ rp->n_time = (time_t)0;
+ rp->n_flag = 0;
+
+ return rp;
+}
+
+
+/*
+ * Add a dependant to the end of the supplied list of dependants.
+ * Return the new head pointer for that list.
+ */
+struct depend *
+newdep(np, dp)
+struct name * np;
+struct depend * dp;
+{
+ register struct depend * rp;
+ register struct depend * rrp;
+
+
+ if ((rp = (struct depend *)malloc(sizeof (struct depend)))
+ == (struct depend *)0)
+ fatal("No memory for dependant");
+ rp->d_next = (struct depend *)0;
+ rp->d_name = np;
+
+ if (dp == (struct depend *)0)
+ return rp;
+
+ for (rrp = dp; rrp->d_next; rrp = rrp->d_next)
+ ;
+
+ rrp->d_next = rp;
+
+ return dp;
+}
+
+
+/*
+ * Add a command to the end of the supplied list of commands.
+ * Return the new head pointer for that list.
+ */
+struct cmd *
+newcmd(str, cp)
+char * str;
+struct cmd * cp;
+{
+ register struct cmd * rp;
+ register struct cmd * rrp;
+ register char * rcp;
+
+
+ if (rcp = rindex(str, '\n'))
+ *rcp = '\0'; /* Loose newline */
+
+ while (isspace(*str))
+ str++;
+
+ if (*str == '\0') /* If nothing left, the exit */
+ return 0;
+
+ if ((rp = (struct cmd *)malloc(sizeof (struct cmd)))
+ == (struct cmd *)0)
+ fatal("No memory for command");
+ rp->c_next = (struct cmd *)0;
+ if ((rcp = malloc((unsigned)(strlen(str)+1))) == (char *)0)
+ fatal("No memory for command");
+ strcpy(rcp, str);
+ rp->c_cmd = rcp;
+
+ if (cp == (struct cmd *)0)
+ return rp;
+
+ for (rrp = cp; rrp->c_next; rrp = rrp->c_next)
+ ;
+
+ rrp->c_next = rp;
+
+ return cp;
+}
+
+
+/*
+ * Add a new 'line' of stuff to a target. This check to see
+ * if commands already exist for the target. If flag is set,
+ * the line is a double colon target.
+ *
+ * Kludges:
+ * i) If the new name begins with a '.', and there are no dependents,
+ * then the target must cease to be a target. This is for .SUFFIXES.
+ * ii) If the new name begins with a '.', with no dependents and has
+ * commands, then replace the current commands. This is for
+ * redefining commands for a default rule.
+ * Neither of these free the space used by dependents or commands,
+ * since they could be used by another target.
+ */
+void
+newline(np, dp, cp, flag)
+struct name * np;
+struct depend * dp;
+struct cmd * cp;
+{
+ bool hascmds = FALSE; /* Target has commands */
+ register struct line * rp;
+ register struct line * rrp;
+
+
+ /* Handle the .SUFFIXES case */
+ if (! strcmp(np->n_name, ".SUFFIXES") && !dp && !cp)
+ {
+ for (rp = np->n_line; rp; rp = rrp)
+ {
+ rrp = rp->l_next;
+ free((char *)rp);
+ }
+ np->n_line = (struct line *)0;
+ np->n_flag &= ~N_TARG;
+ return;
+ }
+
+ /* This loop must happen since rrp is used later. */
+ for
+ (
+ rp = np->n_line, rrp = (struct line *)0;
+ rp;
+ rrp = rp, rp = rp->l_next
+ )
+ if (rp->l_cmd)
+ hascmds = TRUE;
+
+ if (hascmds && cp && !(np->n_flag & N_DOUBLE))
+ /* Handle the implicit rules redefinition case */
+ if (np->n_name[0] == '.' && dp == (struct depend *)0)
+ {
+ np->n_line->l_cmd = cp;
+ return;
+ }
+ else
+ error("Commands defined twice for target %s", np->n_name);
+ if (np->n_flag & N_TARG)
+ if (!(np->n_flag & N_DOUBLE) != !flag) /* like xor */
+ error("Inconsistent rules for target %s", np->n_name);
+
+ if ((rp = (struct line *)malloc(sizeof (struct line)))
+ == (struct line *)0)
+ fatal("No memory for line");
+ rp->l_next = (struct line *)0;
+ rp->l_dep = dp;
+ rp->l_cmd = cp;
+
+ if (rrp)
+ rrp->l_next = rp;
+ else
+ np->n_line = rp;
+
+ np->n_flag |= N_TARG;
+ if (flag)
+ np->n_flag |= N_DOUBLE;
+}
+
+
+/*
+ * Parse input from the makefile, and construct a tree structure
+ * of it.
+ */
+void
+input(fd)
+FILE * fd;
+{
+ char * p; /* General */
+ char * q;
+ struct name * np;
+ struct depend * dp;
+ struct cmd * cp;
+ bool dbl;
+
+
+ if (getline(str1, fd)) /* Read the first line */
+ return;
+
+ for(;;)
+ {
+#ifdef os9
+ if (*str1 == ' ') /* Rules without targets */
+#else
+ if (*str1 == '\t') /* Rules without targets */
+#endif
+ error("Rules not allowed here");
+
+ p = str1;
+
+ while (isspace(*p)) /* Find first target */
+ p++;
+
+ while (((q = index(p, '=')) != (char *)0) &&
+ (p != q) && (q[-1] == '\\')) /* Find value */
+ {
+ register char * a;
+
+ a = q - 1; /* Del \ chr; move rest back */
+ p = q;
+ while(*a++ = *q++)
+ ;
+ }
+
+ if (q != (char *)0)
+ {
+ register char * a;
+
+ *q++ = '\0'; /* Separate name and val */
+ while (isspace(*q))
+ q++;
+ if (p = rindex(q, '\n'))
+ *p = '\0';
+
+ p = str1;
+ if ((a = gettok(&p)) == (char *)0)
+ error("No macro name");
+
+ setmacro(a, q, 2);
+
+ if (getline(str1, fd))
+ return;
+ continue;
+ }
+
+ expand(str1);
+ p = str1;
+
+ while (((q = index(p, ':')) != (char *)0) &&
+ (p != q) && (q[-1] == '\\')) /* Find dependents */
+ {
+ register char * a;
+
+ a = q - 1; /* Del \ chr; move rest back */
+ p = q;
+ while(*a++ = *q++)
+ ;
+ }
+
+ if (q == (char *)0)
+ error("No targets provided");
+
+ *q++ = '\0'; /* Separate targets and dependents */
+
+ if (*q == ':') /* Double colon */
+ {
+ dbl = 1;
+ q++;
+ }
+ else
+ dbl = 0;
+
+ for (dp = (struct depend *)0; ((p = gettok(&q)) != (char *)0);)
+ /* get list of dep's */
+ {
+ np = newname(p); /* Intern name */
+ dp = newdep(np, dp); /* Add to dep list */
+ }
+
+ *((q = str1) + strlen(str1) + 1) = '\0';
+ /* Need two nulls for gettok (Remember separation) */
+
+ cp = (struct cmd *)0;
+ if (getline(str2, fd) == FALSE) /* Get commands */
+ {
+#ifdef os9
+ while (*str2 == ' ')
+#else
+ while (*str2 == '\t')
+#endif
+ {
+ cp = newcmd(&str2[0], cp);
+ if (getline(str2, fd))
+ break;
+ }
+ }
+
+ while ((p = gettok(&q)) != (char *)0) /* Get list of targ's */
+ {
+ np = newname(p); /* Intern name */
+ newline(np, dp, cp, dbl);
+ if (!firstname && p[0] != '.')
+ firstname = np;
+ }
+
+ if (feof(fd)) /* EOF? */
+ return;
+
+ strcpy(str1, str2);
+ }
+}
--- /dev/null
+/*
+ * Macro control for make
+ *
+ * $Header$
+ */
+
+
+#include "h.h"
+
+
+struct macro * macrohead;
+
+
+struct macro *
+getmp(name)
+char * name;
+{
+ register struct macro * rp;
+
+ for (rp = macrohead; rp; rp = rp->m_next)
+ if (strcmp(name, rp->m_name) == 0)
+ return rp;
+ return (struct macro *)0;
+}
+
+
+char *
+getmacro(name)
+char * name;
+{
+ struct macro * mp;
+
+ if (mp = getmp(name))
+ return mp->m_val;
+ else
+ return "";
+}
+
+
+struct macro *
+setmacro(name, val, prio)
+char * name;
+char * val;
+{
+ register struct macro * rp;
+ register char * cp;
+
+
+ /* Replace macro definition if it exists */
+ for (rp = macrohead; rp; rp = rp->m_next)
+ if (strcmp(name, rp->m_name) == 0)
+ {
+ if (prio < rp->m_prio)
+ return rp;
+ free(rp->m_val); /* Free space from old */
+ break;
+ }
+
+ if (!rp) /* If not defined, allocate space for new */
+ {
+ if ((rp = (struct macro *)malloc(sizeof (struct macro)))
+ == (struct macro *)0)
+ fatal("No memory for macro");
+
+ rp->m_next = macrohead;
+ macrohead = rp;
+ rp->m_flag = FALSE;
+
+ if ((cp = malloc((unsigned)(strlen(name)+1))) == (char *)0)
+ fatal("No memory for macro");
+ strcpy(cp, name);
+ rp->m_name = cp;
+ }
+
+ if ((cp = malloc((unsigned)(strlen(val)+1))) == (char *)0)
+ fatal("No memory for macro");
+ strcpy(cp, val); /* Copy in new value */
+ rp->m_val = cp;
+ rp->m_prio = prio;
+
+ return rp;
+}
+
+#define MBUFSIZ 128
+
+/*
+ * Do the dirty work for expand
+ */
+void
+doexp(to, from, len, buf)
+char ** to;
+char * from;
+int * len;
+char * buf;
+{
+ register char * rp;
+ register char * p;
+ register char * q;
+ register struct macro * mp;
+
+
+ rp = from;
+ p = *to;
+ while (*rp)
+ {
+ if (*rp != '$')
+ {
+ *p++ = *rp++;
+ (*len)--;
+ }
+ else
+ {
+ q = buf;
+ if (*++rp == '{')
+ while (*++rp && *rp != '}') {
+ if (q < &buf[MBUFSIZ-1]) *q++ = *rp;
+ }
+ else if (*rp == '(')
+ while (*++rp && *rp != ')') {
+ if (q < &buf[MBUFSIZ-1]) *q++ = *rp;
+ }
+ else if (!*rp)
+ {
+ *p++ = '$';
+ break;
+ }
+ else
+ *q++ = *rp;
+ *q = '\0';
+ if (*rp)
+ rp++;
+ if (!(mp = getmp(buf)))
+ mp = setmacro(buf, "", 2);
+ if (mp->m_flag)
+ fatal("Infinitely recursive macro %s", mp->m_name);
+ mp->m_flag = TRUE;
+ *to = p;
+ doexp(to, mp->m_val, len, buf);
+ p = *to;
+ mp->m_flag = FALSE;
+ }
+ if (*len <= 0)
+ error("Expanded line too line");
+ }
+ *p = '\0';
+ *to = p;
+}
+
+
+/*
+ * Expand any macros in str.
+ */
+void
+expand(str)
+char * str;
+{
+ char *a;
+ static char b[MBUFSIZ]; /* temp storage for macroname */
+ char * p = str;
+ int len = LZ-1;
+
+ a = malloc((unsigned)(strlen(str)+1));
+ if (!a) fatal("No memory for expand");
+ strcpy(a, str);
+ doexp(&p, a, &len, b);
+ free(a);
+}
--- /dev/null
+/*
+ * make [-f makefile] [-ins] [target(s) ...]
+ *
+ * (Better than EON mk but not quite as good as UNIX make)
+ *
+ * -f makefile name
+ * -i ignore exit status
+ * -n Pretend to make
+ * -p Print all macros & targets
+ * -q Question up-to-dateness of target. Return exit status 1 if not
+ * -r Don't not use inbuilt rules
+ * -s Make silently
+ * -t Touch files instead of making them
+ * -m Change memory requirements (EON only)
+ * -k For the time being: accept but ignore
+ *
+ * $Header$
+ */
+
+#include <stdio.h>
+#include "h.h"
+
+#ifdef unix
+#include <errno.h>
+#endif
+#ifdef eon
+#include <sys/err.h>
+#endif
+#ifdef os9
+#include <errno.h>
+#endif
+
+
+#ifdef eon
+#define MEMSPACE (16384)
+#endif
+
+
+char * myname;
+char * makefile; /* The make file */
+#ifdef eon
+unsigned memspace = MEMSPACE;
+#endif
+
+FILE * ifd; /* Input file desciptor */
+bool domake = TRUE; /* Go through the motions option */
+bool ignore = FALSE; /* Ignore exit status option */
+bool silent = FALSE; /* Silent option */
+bool print = FALSE; /* Print debuging information */
+bool rules = TRUE; /* Use inbuilt rules */
+bool dotouch = FALSE;/* Touch files instead of making */
+bool quest = FALSE; /* Question up-to-dateness of file */
+
+
+void
+main(argc, argv)
+int argc;
+char ** argv;
+{
+ register char * p; /* For argument processing */
+ int estat = 0; /* For question */
+ register struct name * np;
+ int nargc = 0;
+ char **nargv;
+ int fflag = 0;
+
+
+ myname = (argc-- < 1) ? "make" : *argv++;
+ nargv = argv;
+
+ while (argc > 0)
+ {
+ argc--; /* One less to process */
+ p = *argv++; /* Now processing this one */
+
+ if (*p == '-') while (*++p != '\0')
+ {
+ switch(*p)
+ {
+ case 'f': /* Alternate file name */
+ fflag = 1;
+ break;
+#ifdef eon
+ case 'm': /* Change space requirements */
+ if (*++p == '\0')
+ {
+ if (argc-- <= 0)
+ usage();
+ p = *argv++;
+ }
+ memspace = atoi(p);
+ goto end_of_args;
+#endif
+ case 'n': /* Pretend mode */
+ domake = FALSE;
+ break;
+ case 'i': /* Ignore fault mode */
+ ignore = TRUE;
+ break;
+ case 's': /* Silent about commands */
+ silent = TRUE;
+ break;
+ case 'p':
+ print = TRUE;
+ break;
+ case 'r':
+ rules = FALSE;
+ break;
+ case 't':
+ dotouch = TRUE;
+ break;
+ case 'q':
+ quest = TRUE;
+ break;
+ case 'k':
+ break;
+ default: /* Wrong option */
+ usage();
+ }
+ }
+ else {
+ if (fflag) {
+ if (argc <= 0) usage();
+ makefile = p;
+ fflag = 0;
+ }
+ else {
+ nargc++;
+ *nargv++ = p;
+ }
+ }
+ end_of_args:;
+ }
+ argv = nargv - nargc;
+ argc = nargc;
+
+#ifdef eon
+ if (initalloc(memspace) == 0xffff) /* Must get memory for alloc */
+ fatal("Cannot initalloc memory");
+#endif
+
+ if (makefile && strcmp(makefile, "-") == 0) /* Can use stdin as makefile */
+ ifd = stdin;
+ else
+ if (!makefile) /* If no file, then use default */
+ {
+ if ((ifd = fopen(DEFN1, "r")) == (FILE *)0)
+#ifdef eon
+ if (errno != ER_NOTF)
+ fatal("Can't open %s; error %02x", DEFN1, errno);
+#endif
+#ifdef unix
+ if (errno != ENOENT)
+ fatal("Can't open %s; error %02x", DEFN1, errno);
+#endif
+#ifndef os9
+ if ((ifd == (FILE *)0)
+ && ((ifd = fopen(DEFN2, "r")) == (FILE *)0))
+ fatal("Can't open %s", DEFN2);
+#else
+ fatal("Can't open %s", DEFN1);
+#endif
+ }
+ else
+ if ((ifd = fopen(makefile, "r")) == (FILE *)0)
+ fatal("Can't open %s", makefile);
+
+ makerules();
+
+ setmacro("$", "$", 4);
+
+ while (argc && (p = index(*argv, '=')))
+ {
+ char c;
+
+ c = *p;
+ *p = '\0';
+ setmacro(*argv, p+1, 3);
+ *p = c;
+
+ argv++;
+ argc--;
+ }
+
+ input(ifd); /* Input all the gunga */
+ fclose(ifd); /* Finished with makefile */
+ lineno = 0; /* Any calls to error now print no line number */
+
+ if (print)
+ prt(); /* Print out structures */
+
+ np = newname(".SILENT");
+ if (np->n_flag & N_TARG)
+ silent = TRUE;
+
+ np = newname(".IGNORE");
+ if (np->n_flag & N_TARG)
+ ignore = TRUE;
+
+ precious();
+
+ if (!firstname)
+ fatal("No targets defined");
+
+ circh(); /* Check circles in target definitions */
+
+ if (!argc)
+ estat = make(firstname, 0);
+ else while (argc--)
+ {
+ if (!print && !silent && strcmp(*argv, "love") == 0)
+ printf("Not war!\n");
+ estat |= make(newname(*argv++), 0);
+ }
+
+ if (quest)
+ exit(estat);
+ else
+ exit(0);
+}
+
+
+usage()
+{
+ fprintf(stderr, "Usage: %s [-f makefile] [-inpqrst] [macro=val ...] [target(s) ...]\n", myname);
+ exit(1);
+}
+
+
+/*VARARGS1*/
+void
+fatal(msg, a1, a2, a3, a4, a5, a6)
+char *msg;
+{
+ fprintf(stderr, "%s: ", myname);
+ fprintf(stderr, msg, a1, a2, a3, a4, a5, a6);
+ fputc('\n', stderr);
+ exit(1);
+}
+
+char *
+index(s, c)
+ register char *s, c;
+{
+ while (*s)
+ if (*s++ == c)
+ return --s;
+ return (char *)0;
+}
+
+char *
+rindex(str, chr)
+ register char *str, chr;
+{
+ register char *retptr = 0;
+
+ while (*str)
+ if (*str++ == chr)
+ retptr = &str[-1];
+ return retptr;
+}
--- /dev/null
+/*
+ * Do the actual making for make
+ *
+ * $Header$
+ */
+
+#include <stdio.h>
+#ifdef unix
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#endif
+#ifdef eon
+#include <sys/stat.h>
+#include <sys/err.h>
+#endif
+#ifdef os9
+#include <time.h>
+#include <os9.h>
+#include <modes.h>
+#include <direct.h>
+#include <errno.h>
+#endif
+#include "h.h"
+
+
+
+/*
+ * Exec a shell that returns exit status correctly (/bin/esh).
+ * The standard EON shell returns the process number of the last
+ * async command, used by the debugger (ugg).
+ * [exec on eon is like a fork+exec on unix]
+ */
+int
+dosh(string, shell)
+char * string;
+char * shell;
+{
+ int number;
+
+#ifdef unix
+ return system(string);
+#endif
+#ifdef eon
+ return ((number = execl(shell, shell,"-c", string, 0)) == -1) ?
+ -1: /* couldn't start the shell */
+ wait(number); /* return its exit status */
+#endif
+#ifdef os9
+ int status, pid;
+
+ strcat(string, "\n");
+ if ((number = os9fork(shell, strlen(string), string, 0, 0, 0)) == -1)
+ return -1; /* Couldn't start a shell */
+ do
+ {
+ if ((pid = wait(&status)) == -1)
+ return -1; /* child already died!?!? */
+ } while (pid != number);
+
+ return status;
+#endif
+}
+
+
+/*
+ * Do commands to make a target
+ */
+void
+docmds1(np, lp)
+struct name * np;
+struct line * lp;
+{
+ bool ssilent;
+ bool signore;
+ int estat;
+ register char * q;
+ register char * p;
+ char * shell;
+ register struct cmd * cp;
+
+
+ if (*(shell = getmacro("SHELL")) == '\0')
+#ifdef eon
+ shell = ":bin/esh";
+#endif
+#ifdef unix
+ shell = "/bin/sh";
+#endif
+#ifdef os9
+ shell = "shell";
+#endif
+
+ for (cp = lp->l_cmd; cp; cp = cp->c_next)
+ {
+ strcpy(str1, cp->c_cmd);
+ expand(str1);
+ q = str1;
+ ssilent = silent;
+ signore = ignore;
+ while ((*q == '@') || (*q == '-'))
+ {
+ if (*q == '@') /* Specific silent */
+ ssilent = TRUE;
+ else /* Specific ignore */
+ signore = TRUE;
+ q++; /* Not part of the command */
+ }
+
+ if (!domake)
+ ssilent = 0;
+
+ if (!ssilent)
+ fputs(" ", stdout);
+
+ for (p=q; *p; p++)
+ {
+ if (*p == '\n' && p[1] != '\0')
+ {
+ *p = ' ';
+ if (!ssilent)
+ fputs("\\\n", stdout);
+ }
+ else if (!ssilent)
+ putchar(*p);
+ }
+ if (!ssilent) {
+ putchar('\n');
+ fflush(stdout);
+ }
+
+ if (domake)
+ { /* Get the shell to execute it */
+ if ((estat = dosh(q, shell)) != 0)
+ {
+ if (estat == -1)
+ fatal("Couldn't execute %s", shell);
+ else
+ {
+ printf("%s: Error code %d", myname, estat);
+ if (signore)
+ fputs(" (Ignored)\n", stdout);
+ else
+ {
+ putchar('\n');
+ if (!(np->n_flag & N_PREC))
+ if (unlink(np->n_name) == 0)
+ printf("%s: '%s' removed.\n", myname, np->n_name);
+ exit(1);
+ }
+ }
+ fflush(stdout);
+ }
+ }
+ }
+}
+
+
+docmds(np)
+struct name * np;
+{
+ register struct line * lp;
+
+
+ for (lp = np->n_line; lp; lp = lp->l_next)
+ docmds1(np, lp);
+}
+
+
+#ifdef os9
+/*
+ * Some stuffing around to get the modified time of a file
+ * in an os9 file system
+ */
+getmdate(fd, tbp)
+struct sgtbuf * tbp;
+{
+ struct registers regs;
+ static struct fildes fdbuf;
+
+
+ regs.rg_a = fd;
+ regs.rg_b = SS_FD;
+ regs.rg_x = &fdbuf;
+ regs.rg_y = sizeof (fdbuf);
+
+ if (_os9(I_GETSTT, ®s) == -1)
+ {
+ errno = regs.rg_b & 0xff;
+ return -1;
+ }
+ if (tbp)
+ {
+ _strass(tbp, fdbuf.fd_date, sizeof (fdbuf.fd_date));
+ tbp->t_second = 0; /* Files are only acurate to mins */
+ }
+ return 0;
+}
+
+
+/*
+ * Kludge routine to return an aproximation of how many
+ * seconds since 1980. Dates will be in order, but will not
+ * be lineer
+ */
+time_t
+cnvtime(tbp)
+struct sgtbuf *tbp;
+{
+ long acc;
+
+
+ acc = tbp->t_year - 80; /* Baseyear is 1980 */
+ acc = acc * 12 + tbp->t_month;
+ acc = acc * 31 + tbp->t_day;
+ acc = acc * 24 + tbp->t_hour;
+ acc = acc * 60 + tbp->t_minute;
+ acc = acc * 60 + tbp->t_second;
+
+ return acc;
+}
+
+
+/*
+ * Get the current time in the internal format
+ */
+time(tp)
+time_t * tp;
+{
+ struct sgtbuf tbuf;
+
+
+ if (getime(&tbuf) < 0)
+ return -1;
+
+ if (tp)
+ *tp = cnvtime(&tbuf);
+
+ return 0;
+}
+#endif
+
+
+/*
+ * Get the modification time of a file. If the first
+ * doesn't exist, it's modtime is set to 0.
+ */
+void
+modtime(np)
+struct name * np;
+{
+#ifdef unix
+ struct stat info;
+
+
+ if (stat(np->n_name, &info) < 0)
+ {
+ if (errno != ENOENT)
+ fatal("Can't open %s; error %d", np->n_name, errno);
+
+ np->n_time = 0L;
+ }
+ else
+ np->n_time = info.st_mtime;
+#endif
+#ifdef eon
+ struct stat info;
+ int fd;
+
+
+ if ((fd = open(np->n_name, 0)) < 0)
+ {
+ if (errno != ER_NOTF)
+ fatal("Can't open %s; error %02x", np->n_name, errno);
+
+ np->n_time = 0L;
+ }
+ else if (getstat(fd, &info) < 0)
+ fatal("Can't getstat %s; error %02x", np->n_name, errno);
+ else
+ np->n_time = info.st_mod;
+
+ close(fd);
+#endif
+#ifdef os9
+ struct sgtbuf info;
+ int fd;
+
+
+ if ((fd = open(np->n_name, 0)) < 0)
+ {
+ if (errno != E_PNNF)
+ fatal("Can't open %s; error %02x", np->n_name, errno);
+
+ np->n_time = 0L;
+ }
+ else if (getmdate(fd, &info) < 0)
+ fatal("Can't getstat %s; error %02x", np->n_name, errno);
+ else
+ np->n_time = cnvtime(&info);
+
+ close(fd);
+#endif
+}
+
+
+/*
+ * Update the mod time of a file to now.
+ */
+void
+touch(np)
+struct name * np;
+{
+ char c;
+ int fd;
+
+
+ if (!domake || !silent)
+ printf(" touch(%s)\n", np->n_name);
+
+ if (domake)
+ {
+#ifdef unix
+ long a[2];
+ long time();
+
+ a[0] = a[1] = time((long *)0);
+ if (utime(np->n_name, &a[0]) < 0)
+ printf("%s: '%s' not touched - non-existant\n",
+ myname, np->n_name);
+#endif
+#ifdef eon
+ if ((fd = open(np->n_name, 0)) < 0)
+ printf("%s: '%s' not touched - non-existant\n",
+ myname, np->n_name);
+ else
+ {
+ uread(fd, &c, 1, 0);
+ uwrite(fd, &c, 1);
+ }
+ close(fd);
+#endif
+#ifdef os9
+ /*
+ * Strange that something almost as totally useless
+ * as this is easy to do in os9!
+ */
+ if ((fd = open(np->n_name, S_IWRITE)) < 0)
+ printf("%s: '%s' not touched - non-existant\n",
+ myname, np->n_name);
+ close(fd);
+#endif
+ }
+}
+
+
+/*
+ * Recursive routine to make a target.
+ */
+int
+make(np, level)
+struct name * np;
+int level;
+{
+ register struct depend * dp;
+ register struct line * lp;
+ register struct depend * qdp;
+ time_t dtime = 1;
+ bool didsomething = 0;
+ int dynamic = 0;
+
+
+ if (np->n_flag & N_DONE)
+ return 0;
+
+ if (!np->n_time)
+ modtime(np); /* Gets modtime of this file */
+
+ if (rules)
+ {
+ for (lp = np->n_line; lp; lp = lp->l_next)
+ if (lp->l_cmd)
+ break;
+ if (!lp) {
+ dyndep(np);
+ dynamic = 1;
+ }
+ }
+
+ if (!(np->n_flag & N_TARG) && np->n_time == 0L)
+ fatal("Don't know how to make %s", np->n_name);
+
+ for (qdp = (struct depend *)0, lp = np->n_line; lp; lp = lp->l_next)
+ {
+ for (dp = lp->l_dep; dp; dp = dp->d_next)
+ {
+ char *sv = 0;
+ if (dynamic) {
+ char *s = getmacro("<");
+
+ if (s) {
+ sv = malloc((unsigned)(strlen(s)+1));
+ if (!sv) {
+ fatal("no space for saved $<");
+ }
+ strcpy(sv, s);
+ }
+ }
+ make(dp->d_name, level+1);
+ if (dynamic && sv) {
+ setmacro("<", sv, 4);
+ free(sv);
+ }
+ if (np->n_time < dp->d_name->n_time)
+ qdp = newdep(dp->d_name, qdp);
+ dtime = max(dtime, dp->d_name->n_time);
+ }
+ if (!quest && (np->n_flag & N_DOUBLE) && (np->n_time < dtime))
+ {
+ make1(np, lp, qdp); /* free()'s qdp */
+ dtime = 1;
+ qdp = (struct depend *)0;
+ didsomething++;
+ }
+ }
+
+ np->n_flag |= N_DONE;
+
+ if (quest)
+ {
+ long t;
+
+ t = np->n_time;
+ time(&np->n_time);
+ return t < dtime;
+ }
+ else if (np->n_time < dtime && !(np->n_flag & N_DOUBLE))
+ {
+ make1(np, (struct line *)0, qdp); /* free()'s qdp */
+ time(&np->n_time);
+ }
+ else if (level == 0 && !didsomething)
+ printf("%s: '%s' is up to date\n", myname, np->n_name);
+ return 0;
+}
+
+
+make1(np, lp, qdp)
+register struct depend * qdp;
+struct line * lp;
+struct name * np;
+{
+ register struct depend * dp;
+ register char *p;
+ char *rindex();
+
+
+ if (dotouch)
+ touch(np);
+ else
+ {
+ strcpy(str1, "");
+ for (dp = qdp; dp; dp = qdp)
+ {
+ if (strlen(str1))
+ strcat(str1, " ");
+ strcat(str1, dp->d_name->n_name);
+ qdp = dp->d_next;
+ free((char *)dp);
+ }
+ setmacro("?", str1, 4);
+ setmacro("@", np->n_name, 4);
+ p = rindex(np->n_name, '.');
+ if (p) *p = 0;
+ setmacro("*", np->n_name, 4);
+ if (p) *p = '.';
+ if (lp) /* lp set if doing a :: rule */
+ docmds1(np, lp);
+ else
+ docmds(np);
+ }
+}
--- /dev/null
+/*
+ * Read in makefile
+ *
+ * $Header$
+ */
+
+
+#include <stdio.h>
+#include <ctype.h>
+#include "h.h"
+
+
+int lineno;
+
+
+/*
+ * Syntax error handler. Print message, with line number, and exits.
+ */
+/*VARARGS1*/
+void
+error(msg, a1, a2, a3)
+char * msg;
+{
+ fprintf(stderr, "%s: ", myname);
+ fprintf(stderr, msg, a1, a2, a3);
+ if (lineno)
+ fprintf(stderr, " near line %d", lineno);
+ fputc('\n', stderr);
+ exit(1);
+}
+
+
+/*
+ * Read a line into the supplied string of length LZ. Remove
+ * comments, ignore blank lines. Deal with quoted (\) #, and
+ * quoted newlines. If EOF return TRUE.
+ */
+bool
+getline(str, fd)
+char * str;
+FILE * fd;
+{
+ register char * p;
+ char * q;
+ int pos = 0;
+
+
+ for (;;)
+ {
+ if (fgets(str+pos, LZ-pos, fd) == (char *)0)
+ return TRUE; /* EOF */
+
+ lineno++;
+
+ if ((p = index(str+pos, '\n')) == (char *)0)
+ error("Line too long");
+
+ if (p[-1] == '\\')
+ {
+ p[-1] = '\n';
+ pos = p - str;
+ continue;
+ }
+
+ p = str;
+ while (((q = index(p, '#')) != (char *)0) &&
+ (p != q) && (q[-1] == '\\'))
+ {
+ char *a;
+
+ a = q - 1; /* Del \ chr; move rest back */
+ p = q;
+ while (*a++ = *q++)
+ ;
+ }
+ if (q != (char *)0)
+ {
+ q[0] = '\n';
+ q[1] = '\0';
+ }
+
+ p = str;
+ while (isspace(*p)) /* Checking for blank */
+ p++;
+
+ if (*p != '\0')
+ return FALSE;
+ pos = 0;
+ }
+}
+
+
+/*
+ * Get a word from the current line, surounded by white space.
+ * return a pointer to it. String returned has no white spaces
+ * in it.
+ */
+char *
+gettok(ptr)
+char **ptr;
+{
+ register char * p;
+
+
+ while (isspace(**ptr)) /* Skip spaces */
+ (*ptr)++;
+
+ if (**ptr == '\0') /* Nothing after spaces */
+ return NULL;
+
+ p = *ptr; /* word starts here */
+
+ while ((**ptr != '\0') && (!isspace(**ptr)))
+ (*ptr)++; /* Find end of word */
+
+ *(*ptr)++ = '\0'; /* Terminate it */
+
+ return(p);
+}
--- /dev/null
+/*
+ * Control of the implicit suffix rules
+ *
+ * $Header$
+ */
+
+
+#include "h.h"
+
+
+/*
+ * Return a pointer to the suffix of a name
+ */
+char *
+suffix(name)
+char * name;
+{
+ return rindex(name, '.');
+}
+
+
+/*
+ * Dynamic dependency. This routine applies the suffis rules
+ * to try and find a source and a set of rules for a missing
+ * target. If found, np is made into a target with the implicit
+ * source name, and rules. Returns TRUE if np was made into
+ * a target.
+ */
+bool
+dyndep(np)
+struct name * np;
+{
+ register char * p;
+ register char * q;
+ register char * suff; /* Old suffix */
+ register char * basename; /* Name without suffix */
+ struct name * op; /* New dependent */
+ struct name * sp; /* Suffix */
+ struct line * lp;
+ struct depend * dp;
+ char * newsuff;
+
+
+ p = str1;
+ q = np->n_name;
+ if (!(suff = suffix(q)))
+ return FALSE; /* No suffix */
+ while (q < suff)
+ *p++ = *q++;
+ *p = '\0';
+ basename = setmacro("*", str1, 4)->m_val;
+
+ if (!((sp = newname(".SUFFIXES"))->n_flag & N_TARG))
+ return FALSE;
+
+ for (lp = sp->n_line; lp; lp = lp->l_next)
+ for (dp = lp->l_dep; dp; dp = dp->d_next)
+ {
+ newsuff = dp->d_name->n_name;
+ if (strlen(suff)+strlen(newsuff)+1 >= LZ)
+ fatal("Suffix rule too long");
+ p = str1;
+ q = newsuff;
+ while (*p++ = *q++)
+ ;
+ p--;
+ q = suff;
+ while (*p++ = *q++)
+ ;
+ sp = newname(str1);
+ if (sp->n_flag & N_TARG)
+ {
+ p = str1;
+ q = basename;
+ if (strlen(basename) + strlen(newsuff)+1 >= LZ)
+ fatal("Implicit name too long");
+ while (*p++ = *q++)
+ ;
+ p--;
+ q = newsuff;
+ while (*p++ = *q++)
+ ;
+ op = newname(str1);
+ if (!op->n_time)
+ modtime(op);
+ if (op->n_time || (op->n_flag & N_TARG))
+ {
+ dp = newdep(op, (struct depend *)0);
+ newline(np, dp, sp->n_line->l_cmd, 0);
+ setmacro("<", op->n_name, 4);
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+
+/*
+ * Make the default rules
+ */
+void
+makerules()
+{
+ struct cmd * cp;
+ struct name * np;
+ struct depend * dp;
+
+
+#ifdef eon
+ setmacro("BDSCC", "asm", 0);
+ /* setmacro("BDSCFLAGS", "", 0); */
+ cp = newcmd("$(BDSCC) $(BDSCFLAGS) -n $<", (struct cmd *)0);
+ np = newname(".c.o");
+ newline(np, (struct depend *)0, cp, 0);
+
+ setmacro("CC", "c", 0);
+ setmacro("CFLAGS", "-O", 0);
+ cp = newcmd("$(CC) $(CFLAGS) -c $<", (struct cmd *)0);
+ np = newname(".c.obj");
+ newline(np, (struct depend *)0, cp, 0);
+
+ setmacro("M80", "asm -n", 0);
+ /* setmacro("M80FLAGS", "", 0); */
+ cp = newcmd("$(M80) $(M80FLAGS) $<", (struct cmd *)0);
+ np = newname(".mac.o");
+ newline(np, (struct depend *)0, cp, 0);
+
+ setmacro("AS", "zas", 0);
+ /* setmacro("ASFLAGS", "", 0); */
+ cp = newcmd("$(ZAS) $(ASFLAGS) -o $@ $<", (struct cmd *)0);
+ np = newname(".as.obj");
+ newline(np, (struct depend *)0, cp, 0);
+
+ np = newname(".as");
+ dp = newdep(np, (struct depend *)0);
+ np = newname(".obj");
+ dp = newdep(np, dp);
+ np = newname(".c");
+ dp = newdep(np, dp);
+ np = newname(".o");
+ dp = newdep(np, dp);
+ np = newname(".mac");
+ dp = newdep(np, dp);
+ np = newname(".SUFFIXES");
+ newline(np, dp, (struct cmd *)0, 0);
+#endif
+
+/*
+ * Some of the UNIX implicit rules
+ */
+#ifdef unix
+ setmacro("CC", "cc", 0);
+ setmacro("CFLAGS", "-O", 0);
+#ifdef MINIX
+ cp = newcmd("$(CC) $(CFLAGS) -S $<", (struct cmd *)0);
+ np = newname(".c.s");
+#else
+ cp = newcmd("$(CC) $(CFLAGS) -c $<", (struct cmd *)0);
+ np = newname(".c.o");
+#endif MINIX
+ newline(np, (struct depend *)0, cp, 0);
+
+ setmacro("AS", "as", 0);
+ cp = newcmd("$(AS) -o $@ $<", (struct cmd *)0);
+ np = newname(".s.o");
+ newline(np, (struct depend *)0, cp, 0);
+
+ setmacro("YACC", "yacc", 0);
+ /* setmacro("YFLAGS", "", 0); */
+ cp = newcmd("$(YACC) $(YFLAGS) $<", (struct cmd *)0);
+ cp = newcmd("mv y.tab.c $@", cp);
+ np = newname(".y.c");
+ newline(np, (struct depend *)0, cp, 0);
+
+ cp = newcmd("$(YACC) $(YFLAGS) $<", (struct cmd *)0);
+ cp = newcmd("$(CC) $(CFLAGS) -c y.tab.c", cp);
+ cp = newcmd("rm y.tab.c", cp);
+ cp = newcmd("mv y.tab.o $@", cp);
+ np = newname(".y.o");
+ newline(np, (struct depend *)0, cp, 0);
+
+ setmacro("LEX", "lex", 0);
+ /* setmacro("LFLAGS", "", 0); */
+ cp = newcmd("$(LEX) $(LFLAGS) $<", (struct cmd *)0);
+ cp = newcmd("mv lex.yy.c $@", cp);
+ np = newname(".l.c");
+ newline(np, (struct depend *)0, cp, 0);
+
+ cp = newcmd("$(LEX) $(LFLAGS) $<", (struct cmd *)0);
+ cp = newcmd("$(CC) $(CFLAGS) -c lex.yy.c", cp);
+ cp = newcmd("rm lex.yy.c", cp);
+ cp = newcmd("mv lex.yy.o $@", cp);
+ np = newname(".l.o");
+ newline(np, (struct depend *)0, cp, 0);
+
+ np = newname(".s");
+ dp = newdep(np, (struct depend *)0);
+ np = newname(".o");
+ dp = newdep(np, dp);
+ np = newname(".c");
+ dp = newdep(np, dp);
+ np = newname(".y");
+ dp = newdep(np, dp);
+ np = newname(".l");
+ dp = newdep(np, dp);
+ np = newname(".SUFFIXES");
+ newline(np, dp, (struct cmd *)0, 0);
+#endif
+#ifdef os9
+/*
+ * Fairlight use an enhanced version of the C sub-system.
+ * They have a specialised macro pre-processor.
+ */
+ setmacro("CC", "cc", 0);
+ setmacro("CFLAGS", "-z", 0);
+ cp = newcmd("$(CC) $(CFLAGS) -r $<", (struct cmd *)0);
+
+ np = newname(".c.r");
+ newline(np, (struct depend *)0, cp, 0);
+ np = newname(".ca.r");
+ newline(np, (struct depend *)0, cp, 0);
+ np = newname(".a.r");
+ newline(np, (struct depend *)0, cp, 0);
+ np = newname(".o.r");
+ newline(np, (struct depend *)0, cp, 0);
+ np = newname(".mc.r");
+ newline(np, (struct depend *)0, cp, 0);
+ np = newname(".mca.r");
+ newline(np, (struct depend *)0, cp, 0);
+ np = newname(".ma.r");
+ newline(np, (struct depend *)0, cp, 0);
+ np = newname(".mo.r");
+ newline(np, (struct depend *)0, cp, 0);
+
+ np = newname(".r");
+ dp = newdep(np, (struct depend *)0);
+ np = newname(".mc");
+ dp = newdep(np, dp);
+ np = newname(".mca");
+ dp = newdep(np, dp);
+ np = newname(".c");
+ dp = newdep(np, dp);
+ np = newname(".ca");
+ dp = newdep(np, dp);
+ np = newname(".ma");
+ dp = newdep(np, dp);
+ np = newname(".mo");
+ dp = newdep(np, dp);
+ np = newname(".o");
+ dp = newdep(np, dp);
+ np = newname(".a");
+ dp = newdep(np, dp);
+ np = newname(".SUFFIXES");
+ newline(np, dp, (struct cmd *)0, 0);
+#endif
+}