/* * make [-f makefile] [-nprst] [macro=val ...] [target(s) ...] * * (Better than EON mk & old CPM make but not quite as good as UNIX make) * * -f makefile name * -i don't 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 - N/A under CP/M */ #include "c:stdio.h" /* c: is my ramdisk */ #include "c:fcntl.h" #include "h.h" char Usage1[]=" -f makefile name\n\ -i don't ignore exit status\n\ -n Pretend to make\n\ -p Print all macros & targets\n\ -r Do not use inbuilt rules\n\ -s Make silently\n\ -t Touch files instead of making them\n"; #define MEMSPACE (16384) /* superfluous under cp/m */ char * myname; char * makefile; /* The make file */ unsigned memspace = MEMSPACE; extern FILE *execfile; FILE * ifd; /* Input file desciptor */ bool domake = TRUE; /* Go through the motions option */ bool ignore = TRUE; /* 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) char ** argv; int argc; { register char * p; /* For argument processing */ int estat; /* For question */ register struct name * np; /* * CP/M makes all command line junque upper case. All things * being equal, I'd rather they be all forced lower. So I will. * * I have also forced everything in the makefile to lower case, * so everything should be case insensitive. */ for (estat = argc ; --estat > 0 ;) { strlower(argv[estat]); } unlink(MAKERUN); /* delete possible existing make-submit file */ myname = (argc-- < 1) ? "make" : *argv++; /* * CP/M can't do argv[0] (OS limitation), so we don't know who we are. */ myname = "make"; while ((argc > 0) && (**argv == '-')) { argc--; /* One less to process */ p = *argv++; /* Now processing this one */ while (*++p != '\0') { /* * Elaborate switch not really needed, but I * hacked this in before I made all argv parameters * lower case (for cp/m). */ switch( isupper(*p) ? tolower (*p) : *p ) { case 'f': /* Alternate file name */ if (*++p == '\0') { if (argc-- <= 0) usage(); p = *argv++; } makefile = p; goto end_of_args; case 'm': /* Change space requirements */ if (*++p == '\0') { if (argc-- <= 0) usage(); p = *argv++; } memspace = atoi(p); goto end_of_args; case 'n': /* Pretend mode */ domake = FALSE; break; case 'i': /* Ignore fault mode */ ignore = FALSE; 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:; } /* if (initalloc(memspace) == 0xffff) Must get memory for alloc fatal("Cannot initalloc memory"); */ if (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 && ((ifd = fopen(DEFN2, "r")) == (FILE *)0)) { fatal("Can't open %s or %s; error %02x", DEFN1,DEFN2, errno); } } else if ((ifd = fopen(makefile, "r")) == (FILE *)0) fatal("Can't open %s", makefile); if (rules) makerules(); 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 (!domake) silent = FALSE; 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 (execfile == NULL) { exit(0); /* no file made, must be up to date! */ } /* * The "trick" algorithm used for CP/M (which can't execute * commands while "make" is running) is that dosh() really * puts commands into a submit file MAKERUN, then after * the make is "done", that submit file is chained-to (below). * The first code-line below enters the submit file's last command * to delete itself (so this chaining trick is mostly transparent. * * -mdk */ dosh("era ",MAKERUN); /* have the submit file delete itself */ dosh("\n",""); fclose(execfile); /* close the writing to this file */ bdos(108,0); /* Reset CP/M Program return code */ strcpy((char *)0x80,MAKERUN); /* load submit file name into DMA buf*/ bdos(47,0xff); /* chain to the generated submit file */ /* if (quest) exit(estat); else exit(0); */ } usage() { fprintf(stderr, "Usage: %s [-f makefile] [-nprst] [macro=val ...] [target(s) ...]\n%s", myname,Usage1); exit(1); } void fatal(msg, a1, a2, a3) char *msg; { fprintf(stderr, "%s: ", myname); fprintf(stderr, msg, a1, a2, a3); fputc('\n', stderr); exit(1); } strlower(string) char *string; { register char *pointer; char c; for (pointer = string ; (c=*pointer) != '\0' ; pointer++ ) { if (isupper(c)) *pointer = tolower(c); } }