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

  1. /*
  2.  *     Macro control for make
  3.  */
  4.  
  5. /* Extensively revised by DJ. */
  6.  
  7. #include <stdio.h>
  8. #include "h.h"
  9.  
  10. struct macro        *macrohead = NULL;
  11.  
  12. /* macro expansion variables [private structure] */
  13.  
  14. struct expand_vars {
  15.     char                    *dest;            /* where to put characters */
  16.     long                    remaining;        /* space remaining in dest line */
  17.     char                    macro_name[LZ];    /* place to hold unexpanded macroname */
  18. };
  19.  
  20. #if 0
  21. struct macro *getmp(name)
  22.     char                    *name;
  23. {    register struct macro    *rp;
  24.     char                    env_val[256];
  25.  
  26.     for (rp = macrohead; rp; rp = rp->m_next)
  27.         if (strcmp(name, rp->m_name) == 0)
  28.             return rp;
  29.  
  30.     /* if we can't find a macro by that name, then
  31.         look for an environment variable by that name.
  32.         Note that we'll probably need to convert to upper case?
  33.     */
  34.  
  35.     if (get_env(name,env_val,256)) return setmacro(name,env_val);
  36.  
  37.     /* no macro by that name was found, return 0 */
  38.  
  39.     return NULL;
  40. }
  41.  
  42.  
  43. /* get a macro, return either the value string, or a null string */
  44.  
  45. char *getmacro(name) char *name;
  46. {    struct macro        *mp;
  47.  
  48.     if (mp = getmp(name)) return mp->m_val;
  49.     else return "";
  50. }
  51. #endif
  52.  
  53. bool get_macro_value(name,buf,maxlen,mp)
  54.     char                    *name, *buf;
  55.     long                    maxlen;
  56.     struct macro            **mp;
  57. {    register struct macro    *macPtr;
  58.  
  59.     if (mp) *mp = NULL;                                    /* return ptr to macro */
  60.  
  61.     if (efirst && get_env(name,buf,maxlen))                /* look for env var */
  62.         return TRUE;                                    /* if found, return */
  63.  
  64.     for (macPtr = macrohead; macPtr; macPtr = macPtr->m_next)    /* search maclist */
  65.     {    if (match(name,macPtr->m_name))                    /* if found */
  66.         {    strncpy(buf,macPtr->m_val,maxlen);            /* copy macro to buf */
  67.             if (mp) *mp = macPtr;                        /* return ptr to macro */
  68.             return TRUE;                                /* return found */
  69.         }
  70.     }
  71.  
  72.     if (!efirst && get_env(name,buf,maxlen))            /* look for env var */
  73.         return TRUE;                                    /* if found, return */
  74.  
  75.     return NULL;                /* no macro by that name was found, return 0 */
  76. }
  77.  
  78. /* set macro to new value */
  79.  
  80. struct macro *setmacro(name, val)
  81.     char        *name;
  82.     char        *val;
  83. {
  84.     register struct macro     *rp;
  85.     register char            *cp;
  86.  
  87.             /*  Replace macro definition if it exists  */
  88.     for (rp = macrohead; rp; rp = rp->m_next)
  89.         if (strcmp(name, rp->m_name) == 0)
  90.         {    free(rp->m_val);     /* Free space from old definition */
  91.             break;
  92.         }
  93.  
  94.     if (!rp)         /*  If not defined, allocate space for new  */
  95.     {
  96.         if ((rp = (struct macro *)malloc(sizeof (struct macro)))
  97.                     == (struct macro *)0)
  98.             fatal("No memory for macro");
  99.  
  100.         rp->m_next = macrohead;
  101.         macrohead = rp;
  102.         rp->m_flag = FALSE;
  103.  
  104.         if ((cp = malloc(strlen(name)+1)) == (char *)0)
  105.             fatal("No memory for macro");
  106.         strcpy(cp, name);
  107.         rp->m_name = cp;
  108.     }
  109.  
  110.     if ((cp = malloc(strlen(val)+1)) == (char *)0)
  111.         fatal("No memory for macro");
  112.     strcpy(cp, val);         /*  Copy in new value  */
  113.     rp->m_val = cp;
  114.  
  115.     return rp;
  116. }
  117.  
  118. /* starting from source, copy characters into 'dest' until character 'search'
  119.     is encountered, or end of line is encountered. Null terminate dest.
  120.     return address of next source character after search.
  121.         added by DJ.
  122. */
  123.  
  124. char *Capture(dest,source,search) char *dest, *source, search;
  125. {    while (*source && *source != search)
  126.         *dest++ = *source++;
  127.     *dest++ = '\0';
  128.     if (!*source) return NULL;
  129.     return source+1;
  130. }
  131.  
  132. /* for now, I'm taking the position that enviroment variables cannot themselves
  133.     contain macros, since the possibility of infinitely recursive macros might
  134.     arise.
  135. */
  136.  
  137. void doexp(source,exp) register char *source; struct expand_vars *exp;
  138. {    register char            *p;                    /* put pointer */
  139.     char                    *mname = exp->macro_name;
  140.  
  141.     p = exp->dest;                                /* get put pointer */
  142.  
  143.     while (source && *source)                    /* while stuff to read */
  144.     {    if (*source != '$')                        /* if dollar sign not found yet */
  145.         {    *p++ = *source++;                    /* copy string */
  146.             exp->remaining--;                    /* decrement remaining length */
  147.         }
  148.         else
  149.         {    char            macro_value[256];    /* place to stick macro value */
  150.             struct macro     *mp;                /* pointer to macro */
  151.  
  152.             source++;                            /* bump source by 1 */
  153.  
  154.                 /* cases are ${mmmm}, $(mmmm), $n [like $@,$<] and $ [no macro] */
  155.  
  156.             if (*source == '{') source = Capture(mname,source+1,'}');
  157.             else if (*source == '(') source = Capture(mname,source+1,')');
  158.             else if (*source == '\0') { *p++ = '$'; break; }
  159.             else { mname[0] = *source++; mname[1] = '\0'; }
  160.  
  161.             if (!get_macro_value(mname,macro_value,256,&mp))
  162.             {    mp = setmacro(mname,"");        /* if not found, init to "" */
  163.                 macro_value[0] = '\0';            /* copy '\0' to value string */
  164.             }
  165.  
  166.             if (!mp)                            /* if it was an env var */
  167.             {    char *mv = macro_value;            /* just copy string, no expand */
  168.                 while (exp->remaining-- && *mv) *p++ = *mv++;
  169.                 if (exp->remaining <= 0) break;
  170.             }
  171.             else                                /* it was an internal macro */
  172.             {    if (mp->m_flag & M_LOOPCHK)        /* if 'nesting' flag set */
  173.                     fatal("Infinitely recursive macro %s",mp->m_name);
  174.                 mp->m_flag |= M_LOOPCHK;        /* set 'nesting' flag */
  175.  
  176.                 exp->dest = p;                    /* update dest pointer */
  177.                 doexp(macro_value,exp);            /* expand this line into 'to' */
  178.                 p = exp->dest;                    /* get dest pointer */
  179.                 mp->m_flag &= (~M_LOOPCHK);        /* reset 'nesting' flag */
  180.             }
  181.         }
  182.         if (exp->remaining <= 0) error("Expanded line too long");
  183.     }
  184.     *p = '\0';                                    /* null terminate string */
  185.     exp->dest = p;
  186. }
  187.  
  188. /*
  189.  *     Expand any macros in str.
  190.  */
  191. void expand(str) char *str;                        /* string to expand */
  192. {    struct expand_vars        evars;                /* expansion variables */
  193.     static char                source[LZ];            /* buffer to hold source */
  194.  
  195.     strcpy(source, str);                        /* copy str to source */
  196.     evars.dest = str;                            /* where to put result */
  197.     evars.remaining = LZ-1;                        /* length of result, max */
  198.     doexp(source,&evars);                        /* expand string */
  199. }
  200.  
  201.  
  202. #if 0
  203. /*
  204.  *     Do the dirty work for expand
  205.  */
  206. void doexp(to, from, len, buf)
  207.     char                    **to;
  208.     char                    *from;
  209.     int                        *len;
  210.     char                    *buf;
  211. {    register char            *rp;
  212.     register char            *p;
  213.     register char            *q;
  214.     struct macro             *mp;
  215.     char                    macro_value[256];
  216.  
  217.     rp = from;
  218.     p = *to;
  219.     while (*rp)
  220.     {    if (*rp != '$')                    /* if dollar sign not found yet */
  221.         {    *p++ = *rp++;                /* copy string */
  222.             (*len)--;                    /* decrement remaining length */
  223.         }
  224.         else
  225.         {    q = buf;                            /* init pointer to buffer */
  226.             if (*++rp == '{')                    /* capture {nnn} in buf */
  227.                 while (*++rp && *rp != '}')
  228.                     *q++ = *rp;
  229.             else if (*rp == '(')                /* capture (nnn) in buf */
  230.                 while (*++rp && *rp != ')')
  231.                     *q++ = *rp;
  232.             else if (!*rp)                        /* else if end of string */
  233.             {    *p++ = '$';                        /* put '$' in 'to' string */
  234.                 break;                            /* and quit */
  235.             }
  236.             else *q++ = *rp;                    /* else just put '$' in buf */
  237.  
  238.             *q = '\0';                            /* null terminate buf */
  239.             if (*rp) rp++;                        /* skip over delimiter */
  240.  
  241. #if 1
  242.  
  243. /* for now, I'm taking the position that enviroment variables cannot themselves
  244.     contain macros, since the possibility of infinitely recursive macros might
  245.     arise.
  246. */
  247.  
  248.             if (!get_macro_value(buf,macro_value,256,&mp))
  249.             {    mp = setmacro(buf,"");            /* if not found, init to "" */
  250.                 macro_value[0] = '\0';            /* copy '\0' to value string */
  251.             }
  252.  
  253.             if (!mp)                            /* if it was an env var */
  254.             {    char *mv = macro_value;            /* just copy string, no expand */
  255.                 while ((*len)-- && *mv) *p++ = *mv++;
  256.                 if (*len <= 0) break;
  257.             }
  258.             else                                /* it was an internal macro */
  259.             {    if (mp->m_flag)                    /* if 'nesting' flag set */
  260.                     fatal("Infinitely recursive macro %s",mp->m_name);
  261.                 mp->m_flag = TRUE;                /* set 'nesting' flag */
  262.  
  263.                 *to = p;                        /* where to append from */
  264.                 doexp(to, macro_value, len, buf);    /* expand this line into 'to' */
  265.                 p = *to;                        /* and then keep expanding this */
  266.                 mp->m_flag = FALSE;                /* reset 'nesting' flag */
  267.             }
  268. #else
  269. /* old method */
  270.  
  271.             if (!(mp = getmp(buf)))                /* mp = macro */
  272.                 mp = setmacro(buf,"");            /* if not found, init to "" */
  273.  
  274.             if (mp->m_flag)                        /* if 'nesting' flag set */
  275.                 fatal("Infinitely recursive macro %s",mp->m_name);
  276.             mp->m_flag = TRUE;                    /* set 'nesting' flag */
  277.             *to = p;
  278.             doexp(to, mp->m_val, len, buf);        /* expand this line into 'to' */
  279.             p = *to;                            /* and then keep expanding this */
  280.             mp->m_flag = FALSE;                    /* reset 'nesting' flag */
  281. #endif
  282.         }
  283.         if (*len <= 0) error("Expanded line too long");
  284.     }
  285.     *p = '\0';
  286.     *to = p;
  287. }
  288. #endif
  289.  
  290.