Better ANSI C compatibility and portability:

+ Addition of function prototypes and include files.
+ Change function definitions to ANSI C style.
+ Initial support for CMake
This commit is contained in:
carl 2019-02-19 00:39:39 +08:00
parent 10717cc791
commit 910643ccbb
10 changed files with 1118 additions and 1411 deletions

23
util/make/CMakeLists.txt Normal file
View file

@ -0,0 +1,23 @@
cmake_minimum_required (VERSION 2.6)
project (ack-make)
set(SRC
check.c
input.c
macro.c
make.c
main.c
reader.c
rules.c
h.h
)
# The following should be added if utime.h and unistd.h are
# available.
# add_definitions(-Dunix)
add_executable(${PROJECT_NAME} ${SRC})
install(TARGETS ${PROJECT_NAME} DESTINATION bin)

View file

@ -40,3 +40,6 @@ 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 ...
Made it almost ISO C90 and POSIX portable by Carl Eric Codere, and
also made it safer by using correct datatypes on some library calls.

View file

@ -7,64 +7,13 @@
#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;
static void check(struct name *np)
{
register struct depend * dp;
register struct line * lp;
register struct depend * dp;
register struct line * lp;
if (np->n_flag & N_MARK)
fatal("Circular dependency from %s", np->n_name);
@ -75,10 +24,51 @@ struct name * np;
for (dp = lp->l_dep; dp; dp = dp->d_next)
check(dp->d_name);
np->n_flag &= ~N_MARK;
np->n_flag &= (uchar)~N_MARK;
}
/*
* 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(void)
{
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)
fprintf(stderr, "-\t%s\n", cp->c_cmd);
fputc('\n', stderr);
}
fputc('\n', stderr);
}
}
/*
* Look for circular dependancies.
* ie.
@ -86,27 +76,22 @@ struct name * np;
* b: a
* is a circular dep
*/
void
circh()
void circh(void)
{
register struct name * np;
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()
void precious(void)
{
register struct depend * dp;
register struct line * lp;
register struct name * np;
register struct depend * dp;
register struct line * lp;
register struct name * np;
if (!((np = newname(".PRECIOUS"))->n_flag & N_TARG))
return;

View file

@ -1,145 +1,127 @@
/*
* Include header for make
* Include header for make
*
* $Header$
* $Header$
*/
#ifndef uchar
#ifdef os9
#define uchar char
#define void int
#define fputc putc
#else
#define uchar unsigned char
#endif
#define uchar unsigned char
#endif
#define bool int
#define time_t long
#define TRUE (1)
#define FALSE (0)
#define max(a,b) ((a)>(b)?(a):(b))
#include <time.h>
#define DEFN1 "makefile" /* Default names */
#ifdef unix
#define DEFN2 "Makefile"
#endif
#ifdef eon
#define DEFN2 "Makefile"
#endif
/* os9 is case insensitive */
#define bool int
#define TRUE (1)
#define FALSE (0)
#define LZ (2048) /* Line size */
#define DEFN1 "makefile" /* Default names */
#define DEFN2 "Makefile"
#define LZ (2048) /* Line size */
/*
* A name. This represents a file, either to be made, or existant
* 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 */
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 */
#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.
* Definition of a target line.
*/
struct 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 */
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
* List of dependents for a line
*/
struct depend
struct depend
{
struct depend * d_next; /* Next dependent */
struct name * d_name; /* Name of dependent */
struct depend * d_next; /* Next dependent */
struct name * d_name; /* Name of dependent */
};
/*
* Commands for a line
* Commands for a line
*/
struct cmd
struct cmd
{
struct cmd * c_next; /* Next command line */
char * c_cmd; /* Command line */
struct cmd * c_next; /* Next command line */
char * c_cmd; /* Command line */
};
/*
* Macro storage
* Macro storage
*/
struct macro
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)
*/
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;
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();
void circh(void);
char * getmacro(char* name);
struct macro * setmacro(char* name, char* val, int prio);
void input(FILE *fd);
void error(char *msg, char* a1);
void expand(char *str);
void fatal(char* msg, char* value);
bool dyndep(struct name *np);
int make(struct name *np, int level);
void modtime(struct name *np);
struct name *newname(char *name);
struct depend *newdep(struct name *np, struct depend *dp);
struct cmd *newcmd(char *str, struct cmd *cp);
void newline(struct name *np, struct depend *dp, struct cmd *cp, int flag);
void prt(void);
char *suffix(char *name);
void touch(struct name *np);
void makerules(void);
char *gettok(char **ptr);
void precious(void);
bool mgetline(char* str, FILE* fd);

View file

@ -1,80 +1,67 @@
/*
* Parse a makefile
* Parse a makefile
*
* $Header$
* $Header$
*/
#include <stdio.h>
#include <ctype.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include "h.h"
struct name namehead;
struct name * firstname;
struct name namehead;
struct name * firstname;
char str1[LZ]; /* General store */
char str2[LZ];
char str1[LZ]; /* General store */
char str2[LZ];
/*
* Intern a name. Return a pointer to the name struct
* Intern a name. Return a pointer to the name struct
*/
struct name *
newname(name)
char * name;
struct name *newname(char *name)
{
register struct name * rp;
register struct name * rrp;
register char * cp;
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
)
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");
if ((rp = (struct name *) malloc(sizeof(struct name))) == (struct name *) 0)
fatal("No memory for name",NULL);
rrp->n_next = rp;
rp->n_next = (struct name *)0;
if ((cp = malloc((unsigned)(strlen(name)+1))) == (char *)0)
fatal("No memory for name");
rp->n_next = (struct name *) 0;
if ((cp = malloc((unsigned) (strlen(name) + 1))) == (char *) 0)
fatal("No memory for name",NULL);
strcpy(cp, name);
rp->n_name = cp;
rp->n_line = (struct line *)0;
rp->n_time = (time_t)0;
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.
* 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;
struct depend *newdep(struct name *np, struct depend *dp)
{
register struct depend * rp;
register struct depend * rrp;
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;
if ((rp = (struct depend *) malloc(sizeof(struct depend)))
== (struct depend *) 0)
fatal("No memory for dependant",NULL);
rp->d_next = (struct depend *) 0;
rp->d_name = np;
if (dp == (struct depend *)0)
if (dp == (struct depend *) 0)
return rp;
for (rrp = dp; rrp->d_next; rrp = rrp->d_next)
@ -85,40 +72,34 @@ struct depend * dp;
return dp;
}
/*
* Add a command to the end of the supplied list of commands.
* Return the new head pointer for that list.
* 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;
struct cmd *newcmd(char *str, struct cmd *cp)
{
register struct cmd * rp;
register struct cmd * rrp;
register char * rcp;
register struct cmd * rp;
register struct cmd * rrp;
register char * rcp;
if (rcp = rindex(str, '\n'))
*rcp = '\0'; /* Loose newline */
if ((rcp = strrchr(str, '\n')))
*rcp = '\0'; /* Loose newline */
while (isspace(*str))
str++;
if (*str == '\0') /* If nothing left, the exit */
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");
if ((rp = (struct cmd *) malloc(sizeof(struct cmd))) == (struct cmd *) 0)
fatal("No memory for command",NULL);
rp->c_next = (struct cmd *) 0;
if ((rcp = malloc((unsigned) (strlen(str) + 1))) == (char *) 0)
fatal("No memory for command",NULL);
strcpy(rcp, str);
rp->c_cmd = rcp;
if (cp == (struct cmd *)0)
if (cp == (struct cmd *) 0)
return rp;
for (rrp = cp; rrp->c_next; rrp = rrp->c_next)
@ -129,58 +110,48 @@ struct cmd * cp;
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.
* 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.
* 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;
void newline(struct name *np, struct depend *dp, struct cmd *cp, int flag)
{
bool hascmds = FALSE; /* Target has commands */
register struct line * rp;
register struct line * rrp;
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)
if (!strcmp(np->n_name, ".SUFFIXES") && !dp && !cp)
{
for (rp = np->n_line; rp; rp = rrp)
{
rrp = rp->l_next;
free((char *)rp);
free((char *) rp);
}
np->n_line = (struct line *)0;
np->n_flag &= ~N_TARG;
np->n_line = (struct line *) 0;
np->n_flag &= (uchar)~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
)
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)
if (np->n_name[0] == '.' && dp == (struct depend *) 0)
{
np->n_line->l_cmd = cp;
return;
@ -188,13 +159,12 @@ struct cmd * cp;
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 */
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;
if ((rp = (struct line *) malloc(sizeof(struct line))) == (struct line *) 0)
fatal("No memory for line",NULL);
rp->l_next = (struct line *) 0;
rp->l_dep = dp;
rp->l_cmd = cp;
@ -208,68 +178,60 @@ struct cmd * cp;
np->n_flag |= N_DOUBLE;
}
/*
* Parse input from the makefile, and construct a tree structure
* of it.
* Parse input from the makefile, and construct a tree structure
* of it.
*/
void
input(fd)
FILE * fd;
void input(FILE *fd)
{
char * p; /* General */
char * q;
struct name * np;
struct depend * dp;
struct cmd * cp;
bool dbl;
char * p; /* General */
char * q;
struct name * np;
struct depend * dp;
struct cmd * cp;
bool dbl;
if (getline(str1, fd)) /* Read the first line */
if (mgetline(str1, fd)) /* Read the first line */
return;
for(;;)
for (;;)
{
#ifdef os9
if (*str1 == ' ') /* Rules without targets */
#else
if (*str1 == '\t') /* Rules without targets */
#endif
error("Rules not allowed here");
if (*str1 == '\t') /* Rules without targets */
error("Rules not allowed here", NULL );
p = str1;
while (isspace(*p)) /* Find first target */
while (isspace(*p)) /* Find first target */
p++;
while (((q = index(p, '=')) != (char *)0) &&
(p != q) && (q[-1] == '\\')) /* Find value */
while (((q = strchr(p, '=')) != (char *) 0) && (p != q)
&& (q[-1] == '\\')) /* Find value */
{
register char * a;
register char * a;
a = q - 1; /* Del \ chr; move rest back */
a = q - 1; /* Del \ chr; move rest back */
p = q;
while(*a++ = *q++)
while ((*a++ = *q++))
;
}
if (q != (char *)0)
if (q != (char *) 0)
{
register char * a;
register char * a;
*q++ = '\0'; /* Separate name and val */
*q++ = '\0'; /* Separate name and val */
while (isspace(*q))
q++;
if (p = rindex(q, '\n'))
if ((p = strrchr(q, '\n')))
*p = '\0';
p = str1;
if ((a = gettok(&p)) == (char *)0)
error("No macro name");
if ((a = gettok(&p)) == (char *) 0)
error("No macro name", NULL );
setmacro(a, q, 2);
if (getline(str1, fd))
if (mgetline(str1, fd))
return;
continue;
}
@ -277,23 +239,23 @@ FILE * fd;
expand(str1);
p = str1;
while (((q = index(p, ':')) != (char *)0) &&
(p != q) && (q[-1] == '\\')) /* Find dependents */
while (((q = strchr(p, ':')) != (char *) 0) && (p != q)
&& (q[-1] == '\\')) /* Find dependents */
{
register char * a;
register char * a;
a = q - 1; /* Del \ chr; move rest back */
a = q - 1; /* Del \ chr; move rest back */
p = q;
while(*a++ = *q++)
while ((*a++ = *q++))
;
}
if (q == (char *)0)
error("No targets provided");
if (q == (char *) 0)
error("No targets provided", NULL );
*q++ = '\0'; /* Separate targets and dependents */
*q++ = '\0'; /* Separate targets and dependents */
if (*q == ':') /* Double colon */
if (*q == ':') /* Double colon */
{
dbl = 1;
q++;
@ -301,40 +263,36 @@ FILE * fd;
else
dbl = 0;
for (dp = (struct depend *)0; ((p = gettok(&q)) != (char *)0);)
/* get list of dep's */
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 */
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) */
/* Need two nulls for gettok (Remember separation) */
cp = (struct cmd *)0;
if (getline(str2, fd) == FALSE) /* Get commands */
cp = (struct cmd *) 0;
if (mgetline(str2, fd) == FALSE) /* Get commands */
{
#ifdef os9
while (*str2 == ' ')
#else
while (*str2 == '\t')
#endif
{
cp = newcmd(&str2[0], cp);
if (getline(str2, fd))
if (mgetline(str2, fd))
break;
}
}
while ((p = gettok(&q)) != (char *)0) /* Get list of targ's */
while ((p = gettok(&q)) != (char *) 0) /* Get list of targ's */
{
np = newname(p); /* Intern name */
np = newname(p); /* Intern name */
newline(np, dp, cp, dbl);
if (!firstname && p[0] != '.')
firstname = np;
}
if (feof(fd)) /* EOF? */
if (feof(fd)) /* EOF? */
return;
strcpy(str1, str2);

View file

@ -1,167 +1,156 @@
/*
* Macro control for make
* Macro control for make
*
* $Header$
* $Header$
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "h.h"
struct macro * macrohead;
struct macro * macrohead;
struct macro *
getmp(name)
char * name;
static struct macro *getmp(char *name)
{
register struct macro * rp;
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;
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;
char * getmacro(char* name)
{
struct macro * mp;
struct macro * mp;
if (mp = getmp(name))
return mp->m_val;
else
return "";
if ((mp = getmp(name)))
return mp->m_val;
else
return "";
}
struct macro *
setmacro(name, val, prio)
char * name;
char * val;
struct macro * setmacro(char* name, char* val, int prio)
{
register struct macro * rp;
register char * cp;
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;
}
/* 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");
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",NULL);
rp->m_next = macrohead;
macrohead = rp;
rp->m_flag = FALSE;
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(name)+1))) == (char *)0)
fatal("No memory for macro",NULL);
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;
if ((cp = malloc((unsigned)(strlen(val)+1))) == (char *)0)
fatal("No memory for macro",NULL);
strcpy(cp, val); /* Copy in new value */
rp->m_val = cp;
rp->m_prio = (uchar)prio;
return rp;
return rp;
}
#define MBUFSIZ 128
#define MBUFSIZ 128
/*
* Do the dirty work for expand
* Do the dirty work for expand
*/
void
doexp(to, from, len, buf)
char ** to;
char * from;
int * len;
char * buf;
static void doexp(char **to, char* from, int* len, char* buf)
{
register char * rp;
register char * p;
register char * q;
register struct macro * mp;
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;
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", NULL);
}
*p = '\0';
*to = p;
}
/*
* Expand any macros in str.
* Expand any macros in str.
*/
void
expand(str)
char * str;
void expand(char *str)
{
char *a;
static char b[MBUFSIZ]; /* temp storage for macroname */
char * p = str;
int len = LZ-1;
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);
a = malloc((unsigned)(strlen(str)+1));
if (!a) fatal("No memory for expand",NULL);
strcpy(a, str);
doexp(&p, a, &len, b);
free(a);
}

View file

@ -1,261 +1,204 @@
/*
* make [-f makefile] [-ins] [target(s) ...]
* make [-f makefile] [-ins] [target(s) ...]
*
* (Better than EON mk but not quite as good as UNIX make)
* (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
* -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$
* $Header$
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "h.h"
#ifdef unix
#include <errno.h>
#endif
char * myname;
char * makefile; /* The make file */
#ifdef eon
#include <sys/err.h>
#endif
#ifdef os9
#include <errno.h>
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 */
#ifdef eon
#define MEMSPACE (16384)
#endif
static void usage(void);
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;
int main(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;
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;
myname = (argc-- < 1) ? "make" : *argv++;
nargv = argv;
while (argc > 0)
{
argc--; /* One less to process */
p = *argv++; /* Now processing this one */
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;
if (*p == '-') while (*++p != '\0')
{
switch(*p)
{
case 'f': /* Alternate file name */
fflag = 1;
break;
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);
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")) == NULL)
if ((ifd == NULL)
&& ((ifd = fopen(DEFN2, "r")) == NULL))
fatal("Can't open %s", DEFN2);
}
else
if ((ifd = fopen(makefile, "r")) == NULL)
fatal("Can't open %s", makefile);
makerules();
makerules();
setmacro("$", "$", 4);
setmacro("$", "$", 4);
while (argc && (p = index(*argv, '=')))
{
char c;
while (argc && (p = strchr(*argv, '=')))
{
char c;
c = *p;
*p = '\0';
setmacro(*argv, p+1, 3);
*p = c;
c = *p;
*p = '\0';
setmacro(*argv, p+1, 3);
*p = c;
argv++;
argc--;
}
argv++;
argc--;
}
input(ifd); /* Input all the gunga */
fclose(ifd); /* Finished with makefile */
lineno = 0; /* Any calls to error now print no line number */
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 */
if (print)
prt(); /* Print out structures */
np = newname(".SILENT");
if (np->n_flag & N_TARG)
silent = TRUE;
np = newname(".SILENT");
if (np->n_flag & N_TARG)
silent = TRUE;
np = newname(".IGNORE");
if (np->n_flag & N_TARG)
ignore = TRUE;
np = newname(".IGNORE");
if (np->n_flag & N_TARG)
ignore = TRUE;
precious();
precious();
if (!firstname)
fatal("No targets defined");
if (!firstname)
fatal("No targets defined",NULL);
circh(); /* Check circles in target definitions */
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 (!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);
if (quest)
exit(estat);
else
exit(0);
return 0;
}
usage()
static void usage(void)
{
fprintf(stderr, "Usage: %s [-f makefile] [-inpqrst] [macro=val ...] [target(s) ...]\n", myname);
exit(1);
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;
void fatal(char *msg, char* value)
{
fprintf(stderr, "%s: ", myname);
fprintf(stderr, msg, a1, a2, a3, a4, a5, a6);
fputc('\n', stderr);
exit(1);
if (value != NULL)
{
fprintf(stderr, "%s: ", myname);
fprintf(stderr, msg, value);
} else
{
fprintf(stderr, "%s: ", myname);
fprintf(stderr, msg);
}
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;
}

View file

@ -1,482 +1,308 @@
/*
* Do the actual making for make
* Do the actual making for make
*
* $Header$
* $Header$
*/
#include <stdio.h>
#ifdef unix
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
/* UNIX specific */
#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
#ifndef unix
#define unix
#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>
#if defined(__MINGW32__) || defined(__MINGW64__)
#ifndef unix
#define unix
#endif
#endif
#ifdef unix
#include <unistd.h>
#include <utime.h>
#endif
#include "h.h"
void docmds(struct name *np);
#ifndef max
#define max(a,b) ((a)>(b)?(a):(b))
#endif
/*
* 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]
* 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;
static int dosh(char *string, char *shell)
{
int number;
return system(string);
}
/*
* Do commands to make a target
*/
static void docmds1(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 unix
return system(string);
shell = "/bin/sh";
#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;
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 */
}
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);
if (!domake)
ssilent = 0;
return status;
#endif
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 (remove(np->n_name) == 0)
printf("%s: '%s' removed.\n", myname, np->n_name);
exit(1);
}
}
fflush(stdout);
}
}
}
}
void docmds(struct name *np)
{
register struct line * lp;
for (lp = np->n_line; lp; lp = lp->l_next)
docmds1(np, lp);
}
/*
* Do commands to make a target
* Get the modification time of a file. If the first
* doesn't exist, it's modtime is set to 0.
*/
void
docmds1(np, lp)
struct name * np;
struct line * lp;
void modtime(struct name *np)
{
bool ssilent;
bool signore;
int estat;
register char * q;
register char * p;
char * shell;
register struct cmd * cp;
struct stat info;
if (stat(np->n_name, &info) < 0)
{
if (errno != ENOENT)
fatal("Can't open %s", np->n_name);
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;
np->n_time = 0L;
}
else
np->n_time = info.st_mtime;
}
/*
* Kludge routine to return an aproximation of how many
* seconds since 1980. Dates will be in order, but will not
* be lineer
* Update the mod time of a file to now.
*/
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;
void touch(struct name *np)
{
#ifdef unix
struct stat info;
if (!domake || !silent)
printf(" touch(%s)\n", np->n_name);
if (domake)
{
struct utimbuf a;
time_t timeval;
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;
a.actime = a.modtime = time(&timeval);
if (utime(np->n_name, &a) < 0)
printf("%s: '%s' not touched - non-existant\n",
myname, np->n_name);
}
#endif
#ifdef eon
struct stat info;
int fd;
}
static void make1(struct name *np, struct line *lp, struct depend *qdp)
{
register struct depend * dp;
register char *p;
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
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 = strrchr(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);
}
}
/*
* Update the mod time of a file to now.
* Recursive routine to make a target.
*/
void
touch(np)
struct name * np;
int make(struct name *np, int level)
{
char c;
int fd;
register struct depend * dp;
register struct line * lp;
register struct depend * qdp;
time_t dtime = 1;
bool didsomething = 0;
int dynamic = 0;
if (!domake || !silent)
printf(" touch(%s)\n", np->n_name);
if (np->n_flag & N_DONE)
return 0;
if (domake)
{
#ifdef unix
long a[2];
long time();
if (!np->n_time)
modtime(np); /* Gets modtime of this file */
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
}
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 $<",NULL);
}
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;
}
/*
* 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);
}
}

View file

@ -1,119 +1,121 @@
/*
* Read in makefile
* Read in makefile
*
* $Header$
* $Header$
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <ctype.h>
#include "h.h"
int lineno;
int lineno;
/*
* Syntax error handler. Print message, with line number, and exits.
* Syntax error handler. Print message, with line number, and exits.
*/
/*VARARGS1*/
void
error(msg, a1, a2, a3)
char * msg;
void error(char *msg, char* a1)
{
fprintf(stderr, "%s: ", myname);
fprintf(stderr, msg, a1, a2, a3);
if (lineno)
fprintf(stderr, " near line %d", lineno);
fputc('\n', stderr);
exit(1);
fprintf(stderr, "%s: ", myname);
if (a1 != NULL)
{
fprintf(stderr, msg, a1);
} else
{
fprintf(stderr, "%s",msg);
}
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.
* 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;
bool mgetline(char* str, FILE* fd)
{
register char * p;
char * q;
int pos = 0;
register char * p;
char * q;
int pos = 0;
for (;;)
{
if (fgets(str+pos, LZ-pos, fd) == (char *)0)
return TRUE; /* EOF */
for (;;)
{
if (fgets(str+pos, LZ-pos, fd) == (char *)0)
return TRUE; /* EOF */
lineno++;
lineno++;
if ((p = index(str+pos, '\n')) == (char *)0)
error("Line too long");
if ((p = strchr(str+pos, '\n')) == (char *)0)
error("Line too long", NULL);
if (p[-1] == '\\')
{
p[-1] = '\n';
pos = p - str;
continue;
}
if (p[-1] == '\\')
{
p[-1] = '\n';
pos = p - str;
continue;
}
p = str;
while (((q = index(p, '#')) != (char *)0) &&
(p != q) && (q[-1] == '\\'))
{
char *a;
p = str;
while (((q = strchr(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';
}
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++;
p = str;
while (isspace(*p)) /* Checking for blank */
p++;
if (*p != '\0')
return FALSE;
pos = 0;
}
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.
* 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;
char *gettok(char **ptr)
{
register char * p;
register char * p;
while (isspace(**ptr)) /* Skip spaces */
(*ptr)++;
while (isspace(**ptr)) /* Skip spaces */
(*ptr)++;
if (**ptr == '\0') /* Nothing after spaces */
return NULL;
if (**ptr == '\0') /* Nothing after spaces */
return NULL;
p = *ptr; /* word starts here */
p = *ptr; /* word starts here */
while ((**ptr != '\0') && (!isspace(**ptr)))
(*ptr)++; /* Find end of word */
while ((**ptr != '\0') && (!isspace(**ptr)))
(*ptr)++; /* Find end of word */
*(*ptr)++ = '\0'; /* Terminate it */
*(*ptr)++ = '\0'; /* Terminate it */
return(p);
return(p);
}

View file

@ -1,257 +1,253 @@
/*
* Control of the implicit suffix rules
* Control of the implicit suffix rules
*
* $Header$
* $Header$
*/
#include <string.h>
#include <stdio.h>
#include "h.h"
/*
* Return a pointer to the suffix of a name
* Return a pointer to the suffix of a name
*/
char *
suffix(name)
char * name;
char *suffix(char *name)
{
return rindex(name, '.');
return strrchr(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.
* 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;
bool dyndep(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;
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;
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;
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;
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",NULL);
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",NULL);
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
* Make the default rules
*/
void
makerules()
void makerules(void)
{
struct cmd * cp;
struct name * np;
struct depend * dp;
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("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("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("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);
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);
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
* Some of the UNIX implicit rules
*/
#ifdef unix
setmacro("CC", "cc", 0);
setmacro("CFLAGS", "-O", 0);
setmacro("CC", "cc", 0);
setmacro("CFLAGS", "-O", 0);
#ifdef MINIX
cp = newcmd("$(CC) $(CFLAGS) -S $<", (struct cmd *)0);
np = newname(".c.s");
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);
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("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);
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);
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);
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);
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);
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.
* 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);
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(".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);
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
}