home *** CD-ROM | disk | FTP | other *** search
- /*
- * Macro control for make
- */
-
- /* Extensively revised by DJ. */
-
- #include <stdio.h>
- #include "h.h"
-
- struct macro *macrohead = NULL;
-
- /* macro expansion variables [private structure] */
-
- struct expand_vars {
- char *dest; /* where to put characters */
- long remaining; /* space remaining in dest line */
- char macro_name[LZ]; /* place to hold unexpanded macroname */
- };
-
- #if 0
- struct macro *getmp(name)
- char *name;
- { register struct macro *rp;
- char env_val[256];
-
- for (rp = macrohead; rp; rp = rp->m_next)
- if (strcmp(name, rp->m_name) == 0)
- return rp;
-
- /* if we can't find a macro by that name, then
- look for an environment variable by that name.
- Note that we'll probably need to convert to upper case?
- */
-
- if (get_env(name,env_val,256)) return setmacro(name,env_val);
-
- /* no macro by that name was found, return 0 */
-
- return NULL;
- }
-
-
- /* get a macro, return either the value string, or a null string */
-
- char *getmacro(name) char *name;
- { struct macro *mp;
-
- if (mp = getmp(name)) return mp->m_val;
- else return "";
- }
- #endif
-
- bool get_macro_value(name,buf,maxlen,mp)
- char *name, *buf;
- long maxlen;
- struct macro **mp;
- { register struct macro *macPtr;
-
- if (mp) *mp = NULL; /* return ptr to macro */
-
- if (efirst && get_env(name,buf,maxlen)) /* look for env var */
- return TRUE; /* if found, return */
-
- for (macPtr = macrohead; macPtr; macPtr = macPtr->m_next) /* search maclist */
- { if (match(name,macPtr->m_name)) /* if found */
- { strncpy(buf,macPtr->m_val,maxlen); /* copy macro to buf */
- if (mp) *mp = macPtr; /* return ptr to macro */
- return TRUE; /* return found */
- }
- }
-
- if (!efirst && get_env(name,buf,maxlen)) /* look for env var */
- return TRUE; /* if found, return */
-
- return NULL; /* no macro by that name was found, return 0 */
- }
-
- /* set macro to new value */
-
- struct macro *setmacro(name, val)
- char *name;
- char *val;
- {
- register struct macro *rp;
- register char *cp;
-
- /* Replace macro definition if it exists */
- for (rp = macrohead; rp; rp = rp->m_next)
- if (strcmp(name, rp->m_name) == 0)
- { free(rp->m_val); /* Free space from old definition */
- break;
- }
-
- if (!rp) /* If not defined, allocate space for new */
- {
- if ((rp = (struct macro *)malloc(sizeof (struct macro)))
- == (struct macro *)0)
- fatal("No memory for macro");
-
- rp->m_next = macrohead;
- macrohead = rp;
- rp->m_flag = FALSE;
-
- if ((cp = malloc(strlen(name)+1)) == (char *)0)
- fatal("No memory for macro");
- strcpy(cp, name);
- rp->m_name = cp;
- }
-
- if ((cp = malloc(strlen(val)+1)) == (char *)0)
- fatal("No memory for macro");
- strcpy(cp, val); /* Copy in new value */
- rp->m_val = cp;
-
- return rp;
- }
-
- /* starting from source, copy characters into 'dest' until character 'search'
- is encountered, or end of line is encountered. Null terminate dest.
- return address of next source character after search.
- added by DJ.
- */
-
- char *Capture(dest,source,search) char *dest, *source, search;
- { while (*source && *source != search)
- *dest++ = *source++;
- *dest++ = '\0';
- if (!*source) return NULL;
- return source+1;
- }
-
- /* for now, I'm taking the position that enviroment variables cannot themselves
- contain macros, since the possibility of infinitely recursive macros might
- arise.
- */
-
- void doexp(source,exp) register char *source; struct expand_vars *exp;
- { register char *p; /* put pointer */
- char *mname = exp->macro_name;
-
- p = exp->dest; /* get put pointer */
-
- while (source && *source) /* while stuff to read */
- { if (*source != '$') /* if dollar sign not found yet */
- { *p++ = *source++; /* copy string */
- exp->remaining--; /* decrement remaining length */
- }
- else
- { char macro_value[256]; /* place to stick macro value */
- struct macro *mp; /* pointer to macro */
-
- source++; /* bump source by 1 */
-
- /* cases are ${mmmm}, $(mmmm), $n [like $@,$<] and $ [no macro] */
-
- if (*source == '{') source = Capture(mname,source+1,'}');
- else if (*source == '(') source = Capture(mname,source+1,')');
- else if (*source == '\0') { *p++ = '$'; break; }
- else { mname[0] = *source++; mname[1] = '\0'; }
-
- if (!get_macro_value(mname,macro_value,256,&mp))
- { mp = setmacro(mname,""); /* if not found, init to "" */
- macro_value[0] = '\0'; /* copy '\0' to value string */
- }
-
- if (!mp) /* if it was an env var */
- { char *mv = macro_value; /* just copy string, no expand */
- while (exp->remaining-- && *mv) *p++ = *mv++;
- if (exp->remaining <= 0) break;
- }
- else /* it was an internal macro */
- { if (mp->m_flag & M_LOOPCHK) /* if 'nesting' flag set */
- fatal("Infinitely recursive macro %s",mp->m_name);
- mp->m_flag |= M_LOOPCHK; /* set 'nesting' flag */
-
- exp->dest = p; /* update dest pointer */
- doexp(macro_value,exp); /* expand this line into 'to' */
- p = exp->dest; /* get dest pointer */
- mp->m_flag &= (~M_LOOPCHK); /* reset 'nesting' flag */
- }
- }
- if (exp->remaining <= 0) error("Expanded line too long");
- }
- *p = '\0'; /* null terminate string */
- exp->dest = p;
- }
-
- /*
- * Expand any macros in str.
- */
- void expand(str) char *str; /* string to expand */
- { struct expand_vars evars; /* expansion variables */
- static char source[LZ]; /* buffer to hold source */
-
- strcpy(source, str); /* copy str to source */
- evars.dest = str; /* where to put result */
- evars.remaining = LZ-1; /* length of result, max */
- doexp(source,&evars); /* expand string */
- }
-
-
- #if 0
- /*
- * Do the dirty work for expand
- */
- void doexp(to, from, len, buf)
- char **to;
- char *from;
- int *len;
- char *buf;
- { register char *rp;
- register char *p;
- register char *q;
- struct macro *mp;
- char macro_value[256];
-
- rp = from;
- p = *to;
- while (*rp)
- { if (*rp != '$') /* if dollar sign not found yet */
- { *p++ = *rp++; /* copy string */
- (*len)--; /* decrement remaining length */
- }
- else
- { q = buf; /* init pointer to buffer */
- if (*++rp == '{') /* capture {nnn} in buf */
- while (*++rp && *rp != '}')
- *q++ = *rp;
- else if (*rp == '(') /* capture (nnn) in buf */
- while (*++rp && *rp != ')')
- *q++ = *rp;
- else if (!*rp) /* else if end of string */
- { *p++ = '$'; /* put '$' in 'to' string */
- break; /* and quit */
- }
- else *q++ = *rp; /* else just put '$' in buf */
-
- *q = '\0'; /* null terminate buf */
- if (*rp) rp++; /* skip over delimiter */
-
- #if 1
-
- /* for now, I'm taking the position that enviroment variables cannot themselves
- contain macros, since the possibility of infinitely recursive macros might
- arise.
- */
-
- if (!get_macro_value(buf,macro_value,256,&mp))
- { mp = setmacro(buf,""); /* if not found, init to "" */
- macro_value[0] = '\0'; /* copy '\0' to value string */
- }
-
- if (!mp) /* if it was an env var */
- { char *mv = macro_value; /* just copy string, no expand */
- while ((*len)-- && *mv) *p++ = *mv++;
- if (*len <= 0) break;
- }
- else /* it was an internal macro */
- { if (mp->m_flag) /* if 'nesting' flag set */
- fatal("Infinitely recursive macro %s",mp->m_name);
- mp->m_flag = TRUE; /* set 'nesting' flag */
-
- *to = p; /* where to append from */
- doexp(to, macro_value, len, buf); /* expand this line into 'to' */
- p = *to; /* and then keep expanding this */
- mp->m_flag = FALSE; /* reset 'nesting' flag */
- }
- #else
- /* old method */
-
- if (!(mp = getmp(buf))) /* mp = macro */
- mp = setmacro(buf,""); /* if not found, init to "" */
-
- if (mp->m_flag) /* if 'nesting' flag set */
- fatal("Infinitely recursive macro %s",mp->m_name);
- mp->m_flag = TRUE; /* set 'nesting' flag */
- *to = p;
- doexp(to, mp->m_val, len, buf); /* expand this line into 'to' */
- p = *to; /* and then keep expanding this */
- mp->m_flag = FALSE; /* reset 'nesting' flag */
- #endif
- }
- if (*len <= 0) error("Expanded line too long");
- }
- *p = '\0';
- *to = p;
- }
- #endif
-
-