home *** CD-ROM | disk | FTP | other *** search
- /*
- * 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((unsigned) 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;
- }
-
- /*
- * Delete the last created name.
- */
-
- delname(np)
- struct name *np;
- {
- if (namehead.n_next == np) {
- namehead.n_next = np->n_next;
- free(np);
- }
- }
-
- /*
- * Add a dependant to the end of the supplied list of dependants.
- * 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 = rindex(str, '\n'))
- *rcp = '\0'; /* Loose newline */
-
- while (isspace(*str))
- str++;
-
- if (*str == '\0') /* If nothing left, the exit */
- return (struct cmd *) 0;
-
- 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((unsigned) 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 flag;
- {
- 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((char *) 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, getline();
-
-
- if (getline(str1, fd)) /* Read the first line */
- return;
-
- for (;;) {
- if (str1[0] == '\t' || str1[0] == ' ') /* Rules without targets */
- error("Rules not allowed here");
-
- p = str1;
-
- while (isspace(*p)) /* Find first target */
- p++;
-
- while (((q = index(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 = rindex(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;
-
- #if 0
- while (((q = index(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++);
- }
- #else
- q = index(p, ':');
- #endif
-
- if (q == (char *) 0)
- error("No targets provided");
-
- /* Added by OIS to allow at most one : in target names */
-
- {
- register char *a = q;
-
- while (*++a) {
- if (*a == ' ' || *a == '\t') {
- /* Found no more colons. Must have been first one. */
- break;
- }
- if (*a == ':') {
- /* Found second colon. This must be the separator. */
- if (a != q+1) /* No double colon */
- q = a;
- break;
- }
- }
- }
-
- *q++ = '\0'; /* Separate targets and dependents */
-
- if (*q == ':') { /* Double colon */
- dbl = 1;
- q++;
- } else
- dbl = 0;
-
- for (dp = (struct depend *) 0; ((p = gettok(&q)) != (char *) 0);)
- /* get list of dep's */
- {
- 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[0] == '\t' || str2[0] == ' ') { /*OIS*0.80*/
- cp = newcmd(&str2[0], cp);
- if (getline(str2, fd))
- break;
- }
- }
- while ((p = gettok(&q)) != (char *) 0) { /* Get list of targ's */
- np = newname(p); /* Intern name */
- newline(np, dp, cp, dbl);
- if (!firstname && p[0] != '.')
- firstname = np;
- }
-
- if (feof(fd)) /* EOF? */
- return;
-
- strcpy(str1, str2);
- }
- }
-