minix/commands/make/main.c
2005-04-21 14:53:53 +00:00

289 lines
7.2 KiB
C
Executable file

/*************************************************************************
*
* m a k e : m a i n . c
*
*========================================================================
* Edition history
*
* # Date Comments By
* --- -------- ---------------------------------------------------- ---
* 1 ?? ??
* 2 01.07.89 strcmp(makefile,..) only if makefile a valid ptr. RAL
* 3 23.08.89 initname() added RAL
* 4 30.08.89 argument parsing impr., indention ch., macro fl. add.PSH,RAL
* 5 03.09.89 k-option added, initname -> init changed RAL
* 6 06.09.89 environment, MAKEFLAGS, e,d,a options added, RAL
* 7 09.09.89 tos support added, fatal args added, fopen makefile PHH,RAL
* 8 17.09.89 setoptions fixed for __STDC__ RAL
* ------------ Version 2.0 released ------------------------------- RAL
*
*************************************************************************/
/*
* make:
*
* -a try to guess undefined ambiguous macros (*,<)
* -d print debugging info
* -e environment macro def. overwrite makefile def.
* -f makefile name
* -i ignore exit status
* -k continue on errors
* -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)
*/
#define EXTERN
#define INIT(x) = x
#define INITARRAY
#include "h.h"
static char version[]= "2.0";
static FILE *ifd; /* Input file desciptor */
static char *ptrmakeflags;
/* There must be enough 'space' for all possible flags ! */
static char makeflags[] = "MAKEFLAGS= ";
void main(argc, argv)
int argc;
char **argv;
{
register char *p; /* For argument processing */
int estat = 0; /* For question */
register struct name *np;
struct macro *mp;
int targc; /* temporary for multiple scans */
char **targv;
char **nargv; /* for removing items from argv */
char **envp; /* enivironment ptr */
ptrmakeflags = &makeflags[10];
myname = (argc-- < 1) ? "make" : *argv++;
#ifdef tos
myname = "Make";
#endif
targc = argc;
targv = nargv = argv;
while (targc--) {
if((p = strchr(*targv, '=')) != (char *)NULL) {
*p = '\0';
mp = setmacro(*targv, p + 1);
mp->m_flag |= M_OVERRIDE;
--argc;
} else
*nargv++ = *targv;
++targv;
}
targc = argc;
targv = nargv = argv;
while (targc--) {
if (**targv == '-') {
--argc;
p = *targv++;
while (*++p != '\0') {
switch(mylower(*p)) {
case 'f': /* Alternate file name */
if (*++p == '\0') {
--argc;
if (targc-- == 0)
usage();
p = *targv++;
}
makefile = p;
goto end_of_args;
#ifdef eon
case 'm': /* Change space requirements */
if (*++p == '\0') {
--argc;
if (targc-- <= 0)
usage();
p = *targv++;
}
memspace = atoi(p);
goto end_of_args;
#endif
default :
setoption(*p);
break;
}
}
end_of_args:;
} else
*nargv++ = *targv++;
}
/* evaluate and update environment MAKEFLAGS */
if((p =getenv("MAKEFLAGS")) != (char *)0)
while(*p) setoption(*p++);
for( p = ptrmakeflags; !isspace((int)*p); p++) ;
*p = '\0';
putenv(makeflags);
#ifdef eon
if (initalloc(memspace) == 0xffff) /* Must get memory for alloc */
fatal("Cannot initalloc memory",(char *)0,0);
#endif
if (makefile && strcmp(makefile, "-") == 0) /* use stdin as makefile */
ifd = stdin;
else if (!makefile) { /* If no file, then use default */
if ((ifd = fopen(makefile = DEFN1, "r")) == (FILE *)0) {
if (errno != MNOENT || !DEFN2)
fatal("Can't open %s: %s", DEFN1, errno);
else if ((ifd = fopen(makefile = DEFN2, "r")) == (FILE *)0)
fatal("Can't open %s: %s", DEFN2, errno);
}
}
else if ((ifd = fopen(makefile, "r")) == (FILE *)0)
fatal("Can't open %s: %s", makefile, errno);
init();
makerules();
mp = setmacro("MAKE", myname);
mp->m_flag |= M_MAKE;
setmacro("$", "$");
/* set environment macros */
envp = environ; /* get actual environment ptr. */
while (*envp) {
if((p = strchr(*envp, '=')) != (char *)NULL) {
*p = '\0';
mp = setmacro(*envp, p + 1);
*p = '=';
if (useenv) mp->m_flag |= M_OVERRIDE;
} else
fatal("invalid environment: %s",*envp,0);
++envp;
}
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",(char *)0,0);
circh(); /* Check circles in target definitions */
if (!argc)
estat = make(firstname, 0);
else
while (argc--) {
estat |= make(newname(*argv++), 0);
}
if (quest)
exit(estat);
else
exit(0);
}
#ifdef __STDC__
void setoption(char option)
#else
void setoption(option)
char option;
#endif
{
register char *c;
option = mylower(option);
switch(option) {
case 'n': /* Pretend mode */
domake = FALSE;
break;
case 'i': /* Ignore fault mode */
ignore = TRUE;
break;
case 'k': /* Continue on errror */
conterr = 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 'e':
useenv = TRUE;
break;
case 'd':
dbginfo = TRUE;
break;
case 'a':
ambigmac = TRUE;
break;
default: /* Wrong option */
usage();
}
for( c = ptrmakeflags; !isspace((int)*c); c++)
if ( *c == option) return;
*c = option;
}
void usage()
{
fprintf(stderr, "Syntax: %s [{options | macro=val | target}]\n", myname);
fprintf(stderr, "Function: maintaining computer programs V%s\n",version);
fprintf(stderr, "Options : -a : try to guess undefined ambiguous macros (*,<)\n");
fprintf(stderr, " -d : print debugging information\n");
fprintf(stderr, " -e : environment macro def. overwrite makefile def.\n");
fprintf(stderr, " -f filename : makefile name (default: makefile, Makefile)\n");
fprintf(stderr, " -i : ignore exit status of executed commands\n");
fprintf(stderr, " -k : continue with unrelated branches on errors\n");
fprintf(stderr, " -n : pretend to make\n");
fprintf(stderr, " -p : print all macros & targets\n");
fprintf(stderr, " -q : question up-to-dateness of target\n");
fprintf(stderr, " -r : don't use inbuilt rules\n");
fprintf(stderr, " -s : make silently\n");
fprintf(stderr, " -t : touch files instead of making them\n");
fprintf(stderr, "Environment: MAKEFLAGS\n");
exit(1);
}
void fatal(msg, a1, a2)
char *msg;
char *a1;
int a2;
{
fprintf(stderr, "%s: ", myname);
fprintf(stderr, msg, a1, strerror(a2));
fputc('\n', stderr);
exit(1);
}