home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
216.lha
/
PdMake
/
macro.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-02-15
|
8KB
|
290 lines
/*
* 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