Initial revision
authorceriel <none@none>
Fri, 22 Jul 1988 19:01:13 +0000 (19:01 +0000)
committerceriel <none@none>
Fri, 22 Jul 1988 19:01:13 +0000 (19:01 +0000)
util/make/.distr [new file with mode: 0644]
util/make/Makefile [new file with mode: 0644]
util/make/README [new file with mode: 0644]
util/make/check.c [new file with mode: 0644]
util/make/h.h [new file with mode: 0644]
util/make/input.c [new file with mode: 0644]
util/make/macro.c [new file with mode: 0644]
util/make/main.c [new file with mode: 0644]
util/make/make.c [new file with mode: 0644]
util/make/reader.c [new file with mode: 0644]
util/make/rules.c [new file with mode: 0644]

diff --git a/util/make/.distr b/util/make/.distr
new file mode 100644 (file)
index 0000000..97e95bf
--- /dev/null
@@ -0,0 +1,10 @@
+Makefile
+README
+check.c
+h.h
+input.c
+macro.c
+main.c
+make.c
+reader.c
+rules.c
diff --git a/util/make/Makefile b/util/make/Makefile
new file mode 100644 (file)
index 0000000..1e98ebc
--- /dev/null
@@ -0,0 +1,29 @@
+# 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
diff --git a/util/make/README b/util/make/README
new file mode 100644 (file)
index 0000000..2c8d12f
--- /dev/null
@@ -0,0 +1,42 @@
+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 ...
diff --git a/util/make/check.c b/util/make/check.c
new file mode 100644 (file)
index 0000000..2951c40
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ *     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;
+}
diff --git a/util/make/h.h b/util/make/h.h
new file mode 100644 (file)
index 0000000..1dcab89
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ *     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();
diff --git a/util/make/input.c b/util/make/input.c
new file mode 100644 (file)
index 0000000..3e4b88e
--- /dev/null
@@ -0,0 +1,342 @@
+/*
+ *     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);
+       }
+}
diff --git a/util/make/macro.c b/util/make/macro.c
new file mode 100644 (file)
index 0000000..5c4b76d
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ *     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);
+}
diff --git a/util/make/main.c b/util/make/main.c
new file mode 100644 (file)
index 0000000..68a31c4
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ *     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;
+}
diff --git a/util/make/make.c b/util/make/make.c
new file mode 100644 (file)
index 0000000..c28520b
--- /dev/null
@@ -0,0 +1,482 @@
+/*
+ *     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, &regs) == -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);
+       }
+}
diff --git a/util/make/reader.c b/util/make/reader.c
new file mode 100644 (file)
index 0000000..f015442
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ *     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);
+}
diff --git a/util/make/rules.c b/util/make/rules.c
new file mode 100644 (file)
index 0000000..e2d7dfa
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+ *     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
+}