/*
 *	Control of the implicit suffix rules
 */


#include "h.h"
#ifndef NULL
#define NULL ((void *) 0)
#endif

/*
 * Return a pointer to the suffix of a name
 */
char	       *
suffix(name)
    char	   *name;
{
    return rindex(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.
 */
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  */
    register char  *basename;	/* Name without suffix	*/
    struct name    *op; 	/* New dependent  */
    struct name    *sp; 	/* Suffix  */
    struct line    *lp;
    struct depend  *dp;
    struct name    *pathnp;	/* .PATH */
    struct line    *pathlp;
    struct depend  *pathdp;
    struct depend  *pathdp1;
    char	   *newsuff;
    char	   *path;
    void	    modtime();


    p = str1;
    q = np->n_name;
    if (!(suff = suffix(q)))
	return FALSE;		/* No suffix */
    while (q < suff)
	*p++ = *q++;
    *p = '\0';
    if ((*pbasename = basename = malloc(strlen(str1)+1)) == NULL)
	fatal("No memory for basename");
    strcpy(*pbasename, str1);

    if (!((sp = newname(".SUFFIXES"))->n_flag & N_TARG))
	return FALSE;

    if (!((pathnp = newname(".PATH"))->n_flag & N_TARG))
	pathnp = NULL;

    if ((pathnp) && (pathlp = pathnp->n_line))
	pathdp = pathlp->l_dep;
    else
	pathdp = NULL;

    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;   /* .c .o .asm etc */
	    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);     /* Form for example .c.o */
	    if (sp->n_flag & N_TARG) {
		path = "";
		pathdp1 = pathdp;
	nextpath:
		p = str1;
		if (strlen(path) + strlen(basename) + strlen(newsuff) + 2 >= LZ)
		    fatal("Implicit name too long");
		q = path;
		while (*p++ = *q++);    /* copy path */
		p--;
		q = basename;
		while (*p++ = *q++);    /* copy basename */
		p--;
		q = newsuff;
		while (*p++ = *q++);    /* copy new suffix */
		op = newname(str1);
		if (!op->n_line && !op->n_time)
		    modtime(op);
		if (op->n_line || op->n_time) {     /* file exists? */
		    dp = newdep(op, NULL);
		    newline(np, dp, sp->n_line->l_cmd, 0);
		    *pinputname = op->n_name;	/* $< = path/basename.suffix */
		    return TRUE;
		} else {
		    delname(op);        /* Forget non-existing file */
		    if (pathdp1) {      /* But is there a path? */
			path = pathdp1->d_name->n_name;
			pathdp1 = pathdp1->d_next;
			goto nextpath;
		    }
		}
	    }
	}
    return FALSE;
}


/*
 *	Make the default rules
 */
void
makerules()
{
    register struct cmd     *cp;    /*OIS*0.80*/
    register struct name    *np;    /*OIS*0.80*/
    register struct depend  *dp;    /*OIS*0.80*/


#ifdef eon
    setmacro("BDSCC", "asm");
    /* setmacro("BDSCFLAGS", "");        */
    cp = newcmd("$(BDSCC) $(BDSCFLAGS) -n $<", 0);
    np = newname(".c.o");
    newline(np, 0, cp, 0);

    setmacro("CC", "c");
    setmacro("CFLAGS", "-O");
    cp = newcmd("$(CC) $(CFLAGS) -c $<", 0);
    np = newname(".c.obj");
    newline(np, 0, cp, 0);

    setmacro("M80", "asm -n");
    /* setmacro("M80FLAGS", "");         */
    cp = newcmd("$(M80) $(M80FLAGS) $<", 0);
    np = newname(".mac.o");
    newline(np, 0, cp, 0);

    setmacro("AS", "zas");
    /* setmacro("ASFLAGS", "");  */
    cp = newcmd("$(ZAS) $(ASFLAGS) -o $@ $<", 0);
    np = newname(".as.obj");
    newline(np, 0, cp, 0);

    np = newname(".as");
    dp = newdep(np, 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, 0, 0);
#endif

/*
 *	Some of the UNIX implicit rules
 */
#ifdef unix
    setmacro("CC", "cc");
    setmacro("CFLAGS", "-O");
#ifdef MINIXPC
    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 MINIXPC
    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

#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 $<", 0);

    np = newname(".c.r");
    newline(np, 0, cp, 0);
    np = newname(".ca.r");
    newline(np, 0, cp, 0);
    np = newname(".a.r");
    newline(np, 0, cp, 0);
    np = newname(".o.r");
    newline(np, 0, cp, 0);
    np = newname(".mc.r");
    newline(np, 0, cp, 0);
    np = newname(".mca.r");
    newline(np, 0, cp, 0);
    np = newname(".ma.r");
    newline(np, 0, cp, 0);
    np = newname(".mo.r");
    newline(np, 0, cp, 0);

    np = newname(".r");
    dp = newdep(np, 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, 0, 0);
#endif

#ifdef amiga

#ifdef pdc	/*OIS*0.80*/
    static char ccx_c[] = "ccx -c";

    setmacro("CC", ccx_c);
#else
    setmacro("CC", "cc");
#endif
    cp = newcmd("$(CC) $(CFLAGS) $<", NULL);
    np = newname(".c.o");
    newline(np, NULL, cp, 0);

#ifdef pdc	/*OIS*0.80*/
    setmacro("AS", ccx_c);
    cp = newcmd("$(AS) $(AFLAGS) $<", NULL);        /*OIS*0.80*/
#else
    setmacro("AS", "as");
    cp = newcmd("$(AS) $(AFLAGS) -o $@ $<", NULL);  /*OIS*0.80*/
#endif
    np = newname(".s.o");
    newline(np, NULL, cp, NULL);

    np = newname(".o");
    dp = newdep(np, NULL);
    np = newname(".s");
    dp = newdep(np, dp);
    np = newname(".c");
    dp = newdep(np, dp);
    np = newname(".SUFFIXES");
    newline(np, dp, NULL, 0);
#endif
}
