/************************************************************************* * * m a k e : r u l e s . c * * Control of the implicit suffix rules *======================================================================== * Edition history * * # Date Comments By * --- -------- ---------------------------------------------------- --- * 1 ?? ?? * 2 01.07.89 $<,$* bugs fixed, impl. r. ending in expl. r. added RAL * 3 23.08.89 suffix as macro, testname intr., algorithem to find * source dep. made more intelligent (see Readme3) RAL * 4 30.08.89 indention changed PSH,RAL * 5 03.09.89 fixed LZ eliminated RAL * 6 07.09.89 rules of type '.c', .DEFAULT added, dep. search impr.RAL * ------------ Version 2.0 released ------------------------------- RAL * 2.1 22.02.91 table-driven implicit rules, SOFTRULES for TOS TRH * 2.2 11.12.91 OOPS! implicit rules should be read BEFORE environment * macros are set, so reinstate make_rules(). TRH *************************************************************************/ #include "h.h" /* * 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,pbasename,pinputname) struct name *np; char **pbasename; /* Name without suffix */ char **pinputname; { register char *p; register char *q; register char *suff; /* Old suffix */ struct name *op = (struct name *)0,*optmp; /* New dependent */ struct name *sp; /* Suffix */ struct line *lp,*nlp; struct depend *dp,*ndp; struct cmd *cmdp; char *newsuff; bool depexists = FALSE; p = str1; q = np->n_name; suff = suffix(q); while (*q && (q < suff || !suff)) *p++ = *q++; *p = '\0'; if ((*pbasename = malloc(strlen(str1)+1)) == (char *)0 ) nomem("basename"); strcpy(*pbasename,str1); if ( !suff) suff = p - str1 + *pbasename; /* set suffix to nullstring */ if (!((sp = newname(".SUFFIXES"))->n_flag & N_TARG)) return FALSE; /* search all .SUFFIXES lines */ for (lp = sp->n_line; lp; lp = lp->l_next) /* try all suffixes */ for (dp = lp->l_dep; dp; dp = dp->d_next) { /* compose implicit rule name (.c.o)...*/ newsuff = dp->d_name->n_name; while (strlen(suff)+strlen(newsuff)+1 >= str1s.len) strrealloc(&str1s); p = str1; q = newsuff; while (*p++ = *q++) ; p--; q = suff; while (*p++ = *q++) ; /* look if the rule exists */ sp = newname(str1); if (sp->n_flag & N_TARG) { /* compose resulting dependency name */ while (strlen(*pbasename) + strlen(newsuff)+1 >= str1s.len) strrealloc(&str1s); q = *pbasename; p = str1; while (*p++ = *q++) ; p--; q = newsuff; while (*p++ = *q++) ; /* test if dependency file or an explicit rule exists */ if ((optmp= testname(str1)) != (struct name *)0) { /* store first possible dependency as default */ if ( op == (struct name *)0) { op = optmp; cmdp = sp->n_line->l_cmd; } /* check if testname is an explicit dependency */ for ( nlp=np->n_line; nlp; nlp=nlp->l_next) { for( ndp=nlp->l_dep; ndp; ndp=ndp->d_next) { if ( strcmp( ndp->d_name->n_name, str1) == 0) { op = optmp; cmdp = sp->n_line->l_cmd; ndp = (struct depend *) 0; goto found2; } depexists = TRUE; } } /* if no explicit dependencies : accept testname */ if (!depexists) goto found; } } } if ( op == (struct name *)0) { if( np->n_flag & N_TARG) { /* DEFAULT handling */ if (!((sp = newname(".DEFAULT"))->n_flag & N_TARG)) return FALSE; if (!(sp->n_line)) return FALSE; cmdp = sp->n_line->l_cmd; for ( nlp=np->n_line; nlp; nlp=nlp->l_next) { if ( ndp=nlp->l_dep) { op = ndp->d_name; ndp = (struct depend *)0; goto found2; } } newline(np, (struct depend *)0, cmdp, 0); *pinputname = (char *)0; *pbasename = (char *)0; return TRUE; } else return FALSE; } found: ndp = newdep(op, (struct depend *)0); found2: newline(np, ndp, cmdp, 0); *pinputname = op->n_name; return TRUE; } /* * Make the default rules */ void makerules() { #ifndef RULETABLE struct cmd *cp; struct name *np; struct depend *dp; #ifdef eon setmacro("BDSCC", "asm"); /* setmacro("BDSCFLAGS", ""); */ cp = newcmd("$(BDSCC) $(BDSCFLAGS) -n $<", (struct cmd *)0); np = newname(".c.o"); newline(np, (struct depend *)0, cp, 0); setmacro("CC", "c"); setmacro("CFLAGS", "-O"); cp = newcmd("$(CC) $(CFLAGS) -c $<", (struct cmd *)0); np = newname(".c.obj"); newline(np, (struct depend *)0, cp, 0); setmacro("M80", "asm -n"); /* setmacro("M80FLAGS", ""); */ cp = newcmd("$(M80) $(M80FLAGS) $<", (struct cmd *)0); np = newname(".mac.o"); newline(np, (struct depend *)0, cp, 0); setmacro("AS", "zas"); /* setmacro("ASFLAGS", ""); */ 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 #ifdef tos #define unix #endif /* * Some of the UNIX implicit rules */ #ifdef unix setmacro("CC", "cc"); setmacro("CFLAGS", "-O"); #ifdef MINIXPC cp = newcmd("$(CC) -S $(CFLAGS) $<", (struct cmd *)0); np = newname(".c.s"); #else cp = newcmd("$(CC) -c $(CFLAGS) $<", (struct cmd *)0); np = newname(".c.o"); #endif MINIXPC newline(np, (struct depend *)0, cp, 0); #ifdef MINIXPC cp = newcmd("$(CC) $(CFLAGS) -i -o $@ $<", (struct cmd *)0); #else cp = newcmd("$(CC) $(CFLAGS) -o $@ $<", (struct cmd *)0); #endif MINIXPC np = newname(".c"); newline(np, (struct depend *)0, cp, 0); setmacro("AS", "as"); cp = newcmd("$(AS) -o $@ $<", (struct cmd *)0); np = newname(".s.o"); newline(np, (struct depend *)0, cp, 0); setmacro("YACC", "yacc"); /*setmacro("YFLAGS", ""); */ 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); #ifdef MINIXPC cp = newcmd("$(CC) $(CFLAGS) -S y.tab.c", cp); cp = newcmd("mv y.tab.s $@", cp); np = newname(".y.s"); #else cp = newcmd("$(CC) $(CFLAGS) -c y.tab.c", cp); cp = newcmd("mv y.tab.o $@", cp); np = newname(".y.o"); #endif MINIXPC cp = newcmd("rm y.tab.c", cp); newline(np, (struct depend *)0, cp, 0); setmacro("FLEX", "flex"); cp = newcmd("$(FLEX) $(FLEX_FLAGS) $<", (struct cmd *)0); cp = newcmd("mv lex.yy.c $@", cp); np = newname(".l.c"); newline(np, (struct depend *)0, cp, 0); cp = newcmd("$(FLEX) $(FLEX_FLAGS) $<", (struct cmd *)0); #ifdef MINIXPC cp = newcmd("$(CC) $(CFLAGS) -S lex.yy.s", cp); cp = newcmd("mv lex.yy.s $@", cp); np = newname(".l.s"); #else cp = newcmd("$(CC) $(CFLAGS) -c lex.yy.c", cp); cp = newcmd("mv lex.yy.o $@", cp); np = newname(".l.o"); #endif MINIXPC cp = newcmd("rm lex.yy.c", cp); newline(np, (struct depend *)0, cp, 0); np = newname(".o"); dp = newdep(np, (struct depend *)0); np = newname(".s"); 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 unix #ifdef os9 /* * Fairlight use an enhanced version of the C sub-system. * They have a specialised macro pre-processor. */ setmacro("CC", "cc"); setmacro("CFLAGS", "-z"); 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 /* os9 */ #else /* RULETABLE */ input(stdout); /* cheat! reads builtin rule-base only, and fails on first read attempt on stdout. */ /* {{The royal way would be to read from /dev/null, but unfortunately that is also system-dependent...}} */ #endif /* RULETABLE */ } /* TRH table-driven implicit rule base is SO much easier to maintain... */ #ifdef RULETABLE #ifndef SOFTRULES char *builtin[] = { #ifdef eon ".SUFFIXES=.as .obj .c .o .mac", "BDSCC=asm", /* "BDSCFLAGS=", */ ".c.o:\n\ $(BDSCC) $(BDSCFLAGS) -n $<", "CC=c", "CFLAGS=-O", ".c.obj:\n\ $(CC) $(CFLAGS) -c $<", "M80=asm -n", /* "M80FLAGS=", */ ".mac.o:\n\ $(M80) $(M80FLAGS) $<", "AS=zas", /* "ASFLAGS=", */ ".as.obj:\n\ $(ZAS) $(ASFLAGS) -o $@ $<", #endif /* eon */ #if __TURBOC__ && __MSDOS__ /* [TRH 10-Apr-92] added C++ rules */ # undef MSDOS # undef unix ".SUFFIXES: .exe .o .obj .asm .c .cpp", "AS=tasm", "CC=bcc", "RC=rc", "LD=tlink", "RM=rm", "CP=cp", "MV=mv", "AFLAGS=", "CFLAGS=", "LDFLAGS=", "RCFLAGS=", "LOADLIBES=", ".c.obj .c.o .cpp.obj .cpp.o:\n\ $(CC) $(CFLAGS) -c -o$@ $<", ".asm.obj:\n\ $(AS) $(AFLAGS) $<", ".c.exe .cpp.exe .obj.exe .o.exe:\n\ $(CC) $(CFLAGS) $(LDFLAGS) -e$@ $< $(LOADLIBES)", #endif /* __TURBOC__ && __MSDOS__ */ #ifdef MSDOS # undef unix ".SUFFIXES: .exe .o .obj .asm .c .cpp", "AS=masm", "CC=cl", "RC=rc", "LD=link", "RM=rm", "CP=cp", "MV=mv", "AFLAGS=", "CFLAGS=-AS", "LDFLAGS=", "RCFLAGS=", "LOADLIBES=", ".c.obj .c.o .cpp.obj .cpp.o:\n\ $(CC) $(CFLAGS) -c -Fo$@ $<", ".asm.obj:\n\ $(AS) $(AFLAGS) $<;", ".c.exe .cpp.exe .obj.exe .o.exe:\n\ $(CC) $(CFLAGS) $(LDFLAGS) $< $(LOADLIBES)", #endif /* MSDOS */ #ifdef tos # define unix #endif #ifdef unix ".SUFFIXES: .o .s .c .y .l", #ifdef BISON "YACC=bison -y", "YFLAGS=", #else "YACC=yacc", "YFLAGS=", #endif #ifdef FLEX "LEX=flex", "LFLAGS=", #else "LEX=lex", "LFLAGS=", #endif "CC=cc", "AS=as", "CFLAGS=", "LOADLIBES=", #ifdef MINIXPC "LDFLAGS=-i", ".c.s:\n\ $(CC) $(CFLAGS) -S $<", ".y.s:\n\ $(YACC) $(YFLAGS) $<\n\ $(CC) $(CFLAGS) -S y.tab.c\n\ mv y.tab.s $@\n\ @-rm y.tab.c", ".l.s:\n\ $(LEX) $(LFLAGS) $<\n\ $(CC) $(CFLAGS) -S lex.yy.c\n\ mv lex.yy.s $@\n\ @-rm lex.yy.c", #else /* !MINIXPC */ "LDFLAGS=", ".c.o:\n\ $(CC) $(CFLAGS) -c $<", ".s.o:\n\ $(AS) -o $@ $<", ".y.o:\n\ $(YACC) $(YFLAGS) $<\n\ $(CC) $(CFLAGS) -c y.tab.c\n\ mv y.tab.o $@\n\ @-rm y.tab.c", ".l.o:\n\ $(LEX) $(LFLAGS) $<\n\ $(CC) $(CFLAGS) -c lex.yy.c\n\ mv lex.yy.o $@\n\ @-rm lex.yy.c", #endif /* MINIXPC */ ".y.c:\n\ $(YACC) $(YFLAGS) $<\n\ mv y.tab.c $@", ".l.c:\n\ $(LEX) $(LFLAGS) $<\n\ mv lex.yy.c $@", ".s .c .o:\n\ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LOADLIBES)", ".y:\n\ $(YACC) $(YFLAGS) $<\n\ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ y.tab.c $(LOADLIBES) -ly\n\ @-rm y.tab.c", ".l:\n\ $(LEX) $(LFLAGS) $<\n\ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ lex.yy.c $(LOADLIBES) -ll\n\ @-rm lex.yy.c", #endif /* unix */ #ifdef os9 /* * Fairlight use an enhanced version of the C sub-system. * They have a specialised macro pre-processor. */ "CC=cc", "CFLAGS=-z", ".c.r .ca.r .a.r .o.r .mc.r .mca.r .ma.r .mo.r:\n\ $(CC) $(CFLAGS) -r $<", ".SUFFIXES: .r .mc .mca .c .ca .ma .mo .o .a" #endif /* os9 */ NULL /* terminated with a NULL pointer */ }; #else /* SOFTRULES */ /* guarantee minimum size for rule base buffer */ # if (SOFTRULES - 1024 < 0) # define SOFTRULES 1024 # endif char rule_buf[SOFTRULES] = "junk:\n\ @$(ECHO) 'run \"make -f -c\" to install default rules'"; char *builtin[] = { "CP=cp", "RM=rm", "ECHO=echo", rule_buf, NULL }; /* load a new set of default rules (from the make file) */ void load_rules(fd) register FILE *fd; { register int c; register char * p = rule_buf; register int size_left = sizeof(rule_buf); while ((c = getc(fd)) != EOF) { if (--size_left == 0) { fatal("%s (max %d bytes)", "No space for default rules", sizeof(rule_buf)); } *p++ = c; } *p = '\0'; } /* load_rules */ /* patch default rule base back to executable * this is *very* system- and compiler dependent. * and is currently only supported from the TOS Lattice/Turbo compiler. */ #ifdef TRHTOS # define SZ_BASEPAGE 0x100 # define SZ_EXEC_HEADER 0x1C #else "SOFTRULES not supported" /* this causes an error (not all compilers support #error directive yet) */ #endif #ifdef __TURBOC__ # define _pbase _BasPag #endif extern void *_pbase; /* * [TRH] There IS a way to dig the name of the program out of the system. * I do not know how `official' it is, but it works all TOS ROM versions * up to and including 1.4. (I guess Atari will send its death squads * after me because of this:-) The dirty work is done by my extended * startup module, which extracts the executable's name and puts a pointer * to it in the variable _pname. * (If you do not use that startup mudule, we just make an educated guess * about the program's name.) */ char *_pname; void patch_rules() { register long base = (long) _pbase + SZ_BASEPAGE - SZ_EXEC_HEADER; register FILE *fd, *tty; int answer; if (_pname == NULL) _pname = "make.ttp"; /* ask confirmation */ if ((tty = fopen("con:", "r+")) == NULL) fatal("cannot open tty", (char *)0, 0); fprintf(tty, "Patch default rules in \"%s\", are you sure? ", _pname); answer = getc(tty); fclose(tty); if (strchr("yYjJ", answer)) { if ((fd = fopen(_pname, "rb+")) && fseek(fd, (long) rule_buf - base, 0) == 0 && fwrite(rule_buf, sizeof(rule_buf), 1, fd) == 1 && fclose (fd) == 0) { fatal("Default rules replaced", (char *)0, 0); } else { fatal("Cannot replace default rules", (char *)0, 0); } } } /* patch_rules */ #endif /* SOFTRULES */ /* * Get the next line from the implicit rule base. * return FALSE if the rule base has been read completely. */ bool rule_gets(buf, size) char *buf; register int size; { register char *s, *d; static char **rule_p; /* where we were left in rule base */ static char *rule_cp; /* where we were left in rule line */ /* (can contain embedded newlines) */ if (!rule_p) { /* once-only initialisation */ rule_p = builtin; rule_cp = *rule_p++; } if ((s = rule_cp) == (char *)0) return FALSE; d = buf; /* skip until end of buffer, or newline, or end-of-string reached. * size is decremented first to leave room for terminating null-byte. * PRE: size > 1 */ while ((--size > 0) && ((*d = *s++) != '\0') && (*d++ != '\n')) ; if (*--s == '\0') { /* end of string reached */ *d++ = '\n'; /* implicit newline */ rule_cp = *rule_p++; /* next string from array */ } else { rule_cp = ++s; /* remember where we left off */ } *d = '\0'; return TRUE; } #endif /* RULETABLE */