home *** CD-ROM | disk | FTP | other *** search
- /***************************************************************\
- * *
- * PDMAKE, Atari ST version *
- * *
- * Adapted from mod.sources Vol 7 Issue 71, 1986-12-03. *
- * *
- * This port makes extensive use of the original net.sources *
- * port by Jwahar Bammi. *
- * *
- * Ton van Overbeek *
- * Email: TPC862@ESTEC.BITNET *
- * TPC862%ESTEC.BITNET@WISCVM.WISC.EDU (ARPA) *
- * ...!mcvax!tpc862%estec.bitnet (UUCP Europe) *
- * ...!ucbvax!tpc862%estec.bitnet (UUCP U.S.A.) *
- * 71450,3537 (CompuServe) *
- * *
- \***************************************************************/
-
- /*
- * Parse a makefile
- */
-
-
- #include <stdio.h>
- #include <ctype.h>
- #include "h.h"
-
-
- struct name namehead;
- struct name * firstname;
-
- char str1[LZ]; /* General store */
- char str2[LZ];
-
-
- /*
- * Intern a name. Return a pointer to the name struct
- */
- struct name *
- newname(name)
- char *name;
- {
- register struct name *rp;
- register struct name *rrp;
- register char *cp;
-
- for (
- rp = namehead.n_next, rrp = &namehead;
- rp;
- rp = rp->n_next, rrp = rrp->n_next
- ) {
- if (strcmp(name, rp->n_name) == 0)
- return rp;
- }
-
- if ((rp = (struct name *)malloc(sizeof (struct name )))
- == (struct name *)0)
- fatal("No memory for name");
- rrp->n_next = rp;
- rp->n_next = (struct name *)0;
- if ((cp = malloc(strlen(name) + 1)) == (char *)0)
- fatal("No memory for name");
- strcpy(cp, name);
- rp->n_name = cp;
- rp->n_line = (struct line *)0;
- rp->n_time = (time_t)0;
- rp->n_flag = 0;
-
- return rp;
- }
-
-
- /*
- * Add a dependent to the end of the supplied list of dependents.
- * Return the new head pointer for that list.
- */
- struct depend *
- newdep(np, dp)
- struct name *np;
- struct depend *dp;
- {
- register struct depend *rp;
- register struct depend *rrp;
-
-
- if ((rp = (struct depend *)malloc(sizeof (struct depend )))
- == (struct depend *)0)
- fatal("No memory for dependant");
- rp->d_next = (struct depend *)0;
- rp->d_name = np;
-
- if (dp == (struct depend *)0)
- return rp;
-
- for (rrp = dp; rrp->d_next; rrp = rrp->d_next)
- ;
-
- rrp->d_next = rp;
-
- return dp;
- }
-
-
- /*
- * Add a command to the end of the supplied list of commands.
- * Return the new head pointer for that list.
- */
- struct cmd *
- newcmd(str, cp)
- char *str;
- struct cmd *cp;
- {
- register struct cmd *rp;
- register struct cmd *rrp;
- register char *rcp;
-
- if (rcp = strrchr(str, '\n'))
- *rcp = '\0'; /* Lose newline */
-
- while (isspace(*str))
- str++;
-
- if (*str == '\0') /* If nothing left, then exit */
- return;
-
- if ((rp = (struct cmd *)malloc(sizeof (struct cmd )))
- == (struct cmd *)0)
- fatal("No memory for command");
- rp->c_next = (struct cmd *)0;
- if ((rcp = malloc(strlen(str) + 1)) == (char *)0)
- fatal("No memory for command");
- strcpy(rcp, str);
- rp->c_cmd = rcp;
-
- if (cp == (struct cmd *)0)
- return rp;
-
- for (rrp = cp; rrp->c_next; rrp = rrp->c_next)
- ;
-
- rrp->c_next = rp;
-
- return cp;
- }
-
-
- /*
- * Add a new 'line' of stuff to a target. This check to see
- * if commands already exist for the target. If flag is set,
- * the line is a double colon target.
- *
- * Kludges:
- * i) If the new name begins with a '.', and there are no dependents,
- * then the target must cease to be a target. This is for .SUFFIXES.
- * ii) If the new name begins with a '.', with no dependents and has
- * commands, then replace the current commands. This is for
- * redefining commands for a default rule.
- * Neither of these free the space used by dependents or commands,
- * since they could be used by another target.
- */
- void
- newline(np, dp, cp, flag)
- struct name *np;
- struct depend *dp;
- struct cmd *cp;
- {
- bool hascmds = FALSE; /* Target has commands */
- register struct line *rp;
- register struct line *rrp;
-
-
- /* Handle the .SUFFIXES case */
- if (np->n_name[0] == '.' && !dp && !cp) {
- for (rp = np->n_line; rp; rp = rrp) {
- rrp = rp->l_next;
- free(rp);
- }
- np->n_line = (struct line *)0;
- np->n_flag &= ~N_TARG;
- return;
- }
-
- /* This loop must happen since rrp is used later. */
- for (
- rp = np->n_line, rrp = (struct line *)0;
- rp;
- rrp = rp, rp = rp->l_next
- )
- if (rp->l_cmd)
- hascmds = TRUE;
-
- if (hascmds && cp && !(np->n_flag & N_DOUBLE))
- /* Handle the implicit rules redefinition case */
- if (np->n_name[0] == '.' && dp == (struct depend *)0) {
- np->n_line->l_cmd = cp;
- return;
- } else
- error("Commands defined twice for target %s", np->n_name);
- if (np->n_flag & N_TARG)
- if (!(np->n_flag & N_DOUBLE) != !flag) /* like xor */
- error("Inconsistent rules for target %s", np->n_name);
-
- if ((rp = (struct line *)malloc(sizeof (struct line )))
- == (struct line *)0)
- fatal("No memory for line");
- rp->l_next = (struct line *)0;
- rp->l_dep = dp;
- rp->l_cmd = cp;
-
- if (rrp)
- rrp->l_next = rp;
- else
- np->n_line = rp;
-
- np->n_flag |= N_TARG;
- if (flag)
- np->n_flag |= N_DOUBLE;
- }
-
-
- /*
- * Parse input from the makefile, and construct a tree structure
- * of it.
- */
- void
- input(fd)
- FILE * fd;
- {
- char *p; /* General */
- char *q;
- struct name *np;
- struct depend *dp;
- struct cmd *cp;
- bool dbl;
-
-
- if (getline(str1, fd)) /* Read the first line */
- return;
-
- for (;;) {
- if (*str1 == '\t') /* Rules without targets */
- error("Rules not allowed here");
-
- p = str1;
-
- while (isspace(*p)) /* Find first target */
- p++;
-
- while (((q = strchr(p, '=')) != (char *)0) &&
- (p != q) && (q[-1] == '\\')) /* Find value */ {
- register char * a;
-
- a = q - 1; /* Del \ chr; move rest back */
- p = q;
- while (*a++ = *q++)
- ;
- }
-
- if (q != (char *)0) {
- register char * a;
-
- *q++ = '\0'; /* Separate name and val */
- while (isspace(*q))
- q++;
- if (p = strrchr(q, '\n'))
- *p = '\0';
-
- p = str1;
- if ((a = gettok(&p)) == (char *)0)
- error("No macro name");
-
- setmacro(a, q);
-
- if (getline(str1, fd))
- return;
- continue;
- }
-
- expand(str1);
- p = str1;
-
- while (((q = strchr(p, ':')) != (char *)0) &&
- (p != q) && (q[-1] == '\\')) { /* Find dependents */
- register char * a;
-
- a = q - 1; /* Del \ chr; move rest back */
- p = q;
- while (*a++ = *q++)
- ;
- }
-
- if (q == (char *)0)
- error("No targets provided");
-
- *q++ = '\0'; /* Separate targets and dependents */
-
- if (*q == ':') { /* Double colon */
- dbl = 1;
- q++;
- } else
- dbl = 0;
-
- /* get list of dep's */
- for (dp=(struct depend *)0; ((p = gettok(&q)) != (char *)0); ) {
- np = newname(p); /* Intern name */
- dp = newdep(np, dp); /* Add to dep list */
- }
-
- *((q = str1) + strlen(str1) + 1) = '\0';
- /* Need two nulls for gettok (Remember separation) */
-
- cp = (struct cmd *)0;
- if (getline(str2, fd) == FALSE) /* Get commands */ {
- while (*str2 == '\t') {
- cp = newcmd(&str2[0], cp);
- if (getline(str2, fd))
- break;
- }
- }
-
- /* Get list targ's */
- while ((p = gettok(&q)) != (char *)0) {
- np = newname(p); /* Intern name */
- newline(np, dp, cp, dbl);
- if (!firstname && p[0] != '.')
- firstname = np;
- }
-
- if (feof(fd)) /* EOF? */
- return;
-
- strcpy(str1, str2);
- }
- }
-