/*
 *	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)
 */

#include <stdio.h>
#include "h.h"

#ifdef unix
#include <sys/errno.h>
#endif
#ifdef eon
#include <sys/err.h>
#endif
#ifdef os9
#include <errno.h>
#endif
#ifdef amiga
#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)
    register int    argc;
    register char **argv;
{
    register char  *p;		/* For argument processing  */
    int 	    estat = 0;	/* For question  */
    register struct name *np;
    void	    prt(), circh();


    myname = (argc-- < 1) ? "make" : *argv++;

    while ((argc > 0) && (**argv == '-')) {
	argc--; 		/* One less to process	*/
	p = *argv++;		/* Now processing this one  */

	while (*++p != '\0') {
	    switch (*p) {
	    case 'f':           /* Alternate file name  */
		if (*++p == '\0') {
		    if (argc-- <= 0)
			usage();
		    p = *argv++;
		}
		makefile = p;
		goto end_of_args;
#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;
	    default:		/* Wrong option  */
		usage();
	    }
	}
end_of_args:;
    }

#ifdef amiga
    if ((ifd = fopen("s:builtins.make", "r")) != (FILE *) 0) {
	input(ifd);
	fclose(ifd);
    } else
#endif
    makerules();

#ifdef eon
    if (initalloc(memspace) == 0xffff)	/* Must get memory for alloc  */
	fatal("Cannot initalloc memory");
#endif

    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
#ifdef amiga
	if (errno != ENOENT)
	    fatal("Can't open %s; error %02x", DEFN1, errno);
#endif
#ifdef DEFN2
	if ((ifd == (FILE *) 0)
	    && ((ifd = fopen(DEFN2, "r")) == (FILE *) 0))
	    fatal("Can't open %s", DEFN2);
#else
	else
	    fatal("Can't open %s", DEFN1);
#endif
    } else if (strcmp(makefile, "-") == 0)      /* Can use stdin as makefile  */
	ifd = stdin;
    else if ((ifd = fopen(makefile, "r")) == (FILE *) 0)
	fatal("Can't open %s", makefile);

    setmacro("$", "$");

    while (argc && (p = index(*argv, '='))) {
	char		c;

	c = *p;
	*p = '\0';
	setmacro(*argv, p + 1);
	*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);
}


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);
}

#ifdef amiga	/*OIS*0.80*/

/*
 * The Amiga case-insensitive filing system needs a case-insensitive
 * filename comparison. Since strcmp() in this make is only applied to
 * filenames, we simply replace it.
 * Unfortunately, this also affects .PRECIOUS, .IGNORE, .SUFFIXES and
 * .SILENT. Therefore, we need a hack, but that costs space, so we don't.
 */

int lower(c)
register unsigned int c;
{
    if (c >= 'A' && c <= 'Z')
	return c - 'A' + 'a';

    return c;
}

int stricmp(first, second)	/* Case-insensitive strcmp() */
register unsigned char *first, *second;
{
    register int cmp;

    while (!(cmp = lower(*first++) - lower(*second++))) {
	if (!first[-1]) return 0;
    }

    return (cmp < 0) ? -1 : 1;
}

/* Manx and PDC allow you to leave out Workbench code */

_wb_parse(){}

#endif
