home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / historic / v941.tgz / icon.v941src.tar / icon.v941src / src / preproc / macro.c < prev    next >
C/C++ Source or Header  |  2001-12-12  |  18KB  |  660 lines

  1. /*
  2.  * This file contains various functions for dealing with macros.
  3.  */
  4. #include "../preproc/preproc.h"
  5. #include "../preproc/ptoken.h"
  6. #include "../preproc/pproto.h"
  7.  
  8. /*
  9.  * Prototypes for static functions.
  10.  */
  11. static struct macro     **m_find      (char *mname);
  12. static int            eq_id_lst   (struct id_lst *lst1, struct id_lst *lst2);
  13. static int            eq_tok_lst  (struct tok_lst *lst1, struct tok_lst *lst2);
  14. static int            parm_indx   (char *id, struct macro *m);
  15. static void            cpy_str     (char *ldelim, char *image,
  16.                                         char *rdelim, struct str_buf *sbuf);
  17. static struct token      *stringize   (struct token *trigger,
  18.                                         struct mac_expand *me);
  19. static struct paste_lsts *paste_parse (struct token *t,
  20.                                         struct mac_expand *me);
  21. static int               *cpy_image   (struct token *t, int *s);
  22.  
  23. #define MacTblSz 149
  24. #define MHash(x) (((unsigned int)(unsigned long)(x)) % MacTblSz)
  25.  
  26. static struct macro *m_table[MacTblSz];    /* hash table of macros */
  27.  
  28. int max_recurse;
  29.  
  30. /*
  31.  * Some string to put in the string table:
  32.  */
  33. static char *line_mac = "__LINE__";
  34. static char *file_mac = "__FILE__";
  35. static char *date_mac = "__DATE__";
  36. static char *time_mac = "__TIME__";
  37. static char *rcrs_mac = "__RCRS__";
  38. static char *defined = "defined";
  39.  
  40. /*
  41.  * m_find - return return location of pointer to where macro belongs in
  42.  *  macro table. If the macro is not in the table, the pointer at the
  43.  *  location is NULL.
  44.  */
  45. static struct macro **m_find(mname)
  46. char *mname;
  47.    {
  48.    struct macro **mpp;
  49.  
  50.    for (mpp = &m_table[MHash(mname)]; *mpp != NULL && (*mpp)->mname != mname;
  51.       mpp = &(*mpp)->next)
  52.       ;
  53.    return mpp;
  54.    }
  55.  
  56. /*
  57.  * eq_id_lst - check to see if two identifier lists contain the same identifiers
  58.  *  in the same order.
  59.  */
  60. static int eq_id_lst(lst1, lst2)
  61. struct id_lst *lst1;
  62. struct id_lst *lst2;
  63.    {
  64.    if (lst1 == lst2)
  65.       return 1;
  66.    if (lst1 == NULL || lst2 == NULL)
  67.       return 0;
  68.    if (lst1->id != lst2->id)
  69.       return 0;
  70.    return eq_id_lst(lst1->next, lst2->next);
  71.    }
  72.  
  73. /*
  74.  * eq_tok_lst - check to see if 2 token lists contain the same tokens
  75.  *  in the same order. All white space tokens are considered equal.
  76.  */
  77. static int eq_tok_lst(lst1, lst2)
  78. struct tok_lst *lst1;
  79. struct tok_lst *lst2;
  80.    {
  81.    if (lst1 == lst2)
  82.       return 1;
  83.    if (lst1 == NULL || lst2 == NULL)
  84.       return 0;
  85.    if (lst1->t->tok_id != lst2->t->tok_id)
  86.       return 0;
  87.    if (lst1->t->tok_id != WhiteSpace && lst1->t->tok_id != PpDirEnd &&
  88.         lst1->t->image != lst2->t->image)
  89.       return 0;
  90.    return eq_tok_lst(lst1->next, lst2->next);
  91.    }
  92.  
  93. /*
  94.  * init_macro - initialize this module, setting up standard macros.
  95.  */
  96. void init_macro()
  97.    {
  98.    int i;
  99.    struct macro **mpp;
  100.    struct token *t;
  101.    time_t tv;
  102.    char *s, *tval;
  103.    static char *time_buf;
  104.    static char *date_buf;
  105.    static short first_time = 1;
  106.  
  107.    if (first_time) {
  108.       first_time = 0;
  109.       /*
  110.        * Add names of standard macros to sting table.
  111.        */
  112.       line_mac = spec_str(line_mac);
  113.       file_mac = spec_str(file_mac);
  114.       date_mac = spec_str(date_mac);
  115.       time_mac = spec_str(time_mac);
  116.       rcrs_mac = spec_str(rcrs_mac);
  117.       defined = spec_str(defined);
  118.       }
  119.    else {
  120.       /*
  121.        * Free macro definitions from the file processed.
  122.        */
  123.       for (i = 0; i < MacTblSz; ++i)
  124.          free_m_lst(m_table[i]);
  125.       }
  126.  
  127.    for (i = 0; i < MacTblSz; ++i)
  128.       m_table[i] = NULL;
  129.  
  130.    /*
  131.     * __LINE__ and __FILE__ are macros that require special processing
  132.     *  when they are processed. Indicate that.
  133.     */
  134.    mpp = m_find(line_mac);
  135.    *mpp = new_macro(line_mac, SpecMac, 0, NULL, NULL);
  136.  
  137.    mpp = m_find(file_mac);
  138.    *mpp = new_macro(file_mac, SpecMac, 0, NULL, NULL);
  139.  
  140.    /*
  141.     * __TIME__ and __DATE__ must be initialized to the current time and
  142.     *  date.
  143.     */
  144.    time(&tv);
  145.    tval = ctime(&tv);
  146.    date_buf = alloc(12);
  147.    time_buf = alloc(9);
  148.    s = date_buf;
  149.    for (i = 4; i <= 10; ++i)
  150.       *s++ = tval[i];
  151.    for (i = 20; i <= 23; ++i)
  152.       *s++ = tval[i];
  153.    *s = '\0';
  154.    s = time_buf;
  155.    for (i = 11; i <= 18; ++i)
  156.       *s++ = tval[i];
  157.    *s = '\0';
  158.    date_buf = spec_str(date_buf);
  159.    time_buf = spec_str(time_buf);
  160.  
  161.    t = new_token(StrLit, date_buf, "", 0);
  162.    mpp = m_find(date_mac);
  163.    *mpp = new_macro(date_mac, FixedMac, 0, NULL, new_t_lst(t));
  164.  
  165.    t = new_token(StrLit, time_buf, "", 0);
  166.    mpp = m_find(time_mac);
  167.    *mpp = new_macro(time_mac, FixedMac, 0, NULL, new_t_lst(t));
  168.  
  169.    /*
  170.     * __RCRS__ is a special macro to indicate the allowance of
  171.     *  recursive macros. It is not ANSI-standard. Initialize it
  172.     *  to "1".
  173.     */
  174.    mpp = m_find(rcrs_mac);
  175.    *mpp = new_macro(rcrs_mac, NoArgs, 0, NULL, new_t_lst(copy_t(one_tok)));
  176.    max_recurse = 1;
  177.    }
  178.  
  179. /*
  180.  * m_install - install a macro.
  181.  */
  182. void m_install(mname, category, multi_line, prmlst, body)
  183. struct token *mname;    /* name of macro */
  184. int multi_line;        /* flag indicating if this is a multi-line macro */
  185. int category;        /* # parms, or NoArgs if it is object-like macro */
  186. struct id_lst *prmlst;    /* parameter list */
  187. struct tok_lst *body;    /* replacement list */
  188.    {
  189.    struct macro **mpp;
  190.    char *s;
  191.  
  192.    if (mname->image == defined)
  193.       errt1(mname, "'defined' may not be the subject of #define");
  194.  
  195.    /*
  196.     * The special macro __RCRS__ may only be defined as a single integer
  197.     *  token and must be an object-like macro.
  198.     */
  199.    if (mname->image == rcrs_mac) {
  200.       if (body == NULL || body->t->tok_id != PpNumber || body->next != NULL)
  201.          errt1(mname, "__RCRS__ must be a decimal integer");
  202.       if (category != NoArgs)
  203.          errt1(mname, "__RSCS__ may have no arguments");
  204.       max_recurse = 0;
  205.       for (s = body->t->image; *s != '\0'; ++s) {
  206.          if (*s >= '0' && *s <= '9')
  207.             max_recurse = max_recurse * 10 + (*s - '0');
  208.          else
  209.             errt1(mname, "__RCRS__ must be a decimal integer");
  210.          }
  211.       }
  212.  
  213.    mpp = m_find(mname->image);
  214.    if (*mpp == NULL)
  215.       *mpp = new_macro(mname->image, category, multi_line, prmlst, body);
  216.     else {
  217.       /*
  218.        * The macro is already defined. Make sure it is identical (up to
  219.        *  white space) to this definition.
  220.        */
  221.       if (!((*mpp)->category == category && eq_id_lst((*mpp)->prmlst, prmlst) &&
  222.            eq_tok_lst((*mpp)->body, body)))
  223.          errt2(mname, "invalid redefinition of macro ", mname->image);
  224.       free_id_lst(prmlst);
  225.       free_t_lst(body);
  226.       }
  227.    }
  228.  
  229. /*
  230.  * m_delete - delete a macro.
  231.  */
  232. void m_delete(mname)
  233. struct token *mname;
  234.    {
  235.    struct macro **mpp, *mp;
  236.  
  237.    if (mname->image == defined)
  238.       errt1(mname, "'defined' may not be the subject of #undef");
  239.  
  240.    /*
  241.     * Undefining __RCRS__ allows unlimited macro recursion (non-ANSI
  242.     *  standard feature.
  243.     */
  244.    if (mname->image == rcrs_mac)
  245.       max_recurse = -1;
  246.  
  247.    /*
  248.     * Make sure undefining this macro is allowed, and free storage
  249.     *  associate with it.
  250.     */
  251.    mpp = m_find(mname->image);
  252.    if (*mpp != NULL) {
  253.       mp = *mpp;
  254.       if (mp->category == FixedMac || mp->category == SpecMac)
  255.          errt2(mname, mname->image, " may not be the subject of #undef");
  256.       *mpp = mp->next;
  257.       free_m(mp);
  258.       }
  259.    }
  260.  
  261. /*
  262.  * m_lookup - lookup a macro name. Return pointer to macro, if it is defined;
  263.  *  return NULL, if it is not. This routine sets the definition for macros
  264.  *  whose definitions various from place to place.
  265.  */
  266. struct macro *m_lookup(id)
  267. struct token *id;
  268.    {
  269.    struct macro *m;
  270.    static char buf[20];
  271.  
  272.    m = *m_find(id->image);
  273.    if (m != NULL && m->category == SpecMac)
  274.       if (m->mname == line_mac) {  /* __LINE___ */
  275.          sprintf(buf, "%d", id->line);
  276.          m->body = new_t_lst(new_token(PpNumber, buf, id->fname,
  277.             id->line));
  278.          }
  279.       else if (m->mname == file_mac) /* __FILE__ */
  280.          m->body = new_t_lst(new_token(StrLit, id->fname, id->fname,
  281.             id->line));
  282.    return m;
  283.    }
  284.  
  285. /*
  286.  * parm_indx - see if a name is a paramter to the given macro.
  287.  */
  288. static int parm_indx(id, m)
  289. char *id;
  290. struct macro *m;
  291.    {
  292.    struct id_lst *idlst;
  293.    int i;
  294.  
  295.    for (i = 0, idlst = m->prmlst; i < m->category; i++, idlst = idlst->next)
  296.       if (id == idlst->id)
  297.          return i;
  298.    return -1;
  299.    }
  300.  
  301. /*
  302.  * cpy_str - copy a string into a string buffer, adding delimiters.
  303.  */
  304. static void cpy_str(ldelim, image, rdelim, sbuf)
  305. char *ldelim;
  306. char *image;
  307. char *rdelim;
  308. struct str_buf *sbuf;
  309.    {
  310.    register char *s;
  311.  
  312.    for (s = ldelim; *s != '\0'; ++s)
  313.       AppChar(*sbuf, *s);
  314.  
  315.    for (s = image; *s != '\0'; ++s) {
  316.       if (*s == '\\' || *s == '"')
  317.          AppChar(*sbuf, '\\');
  318.       AppChar(*sbuf, *s);
  319.       }
  320.  
  321.    for (s = rdelim; *s != '\0'; ++s)
  322.       AppChar(*sbuf, *s);
  323.    }
  324.  
  325. /*
  326.  * stringize - create a stringized version of a token.
  327.  */
  328. static struct token *stringize(trigger, me)
  329. struct token *trigger;
  330. struct mac_expand *me;
  331.    {
  332.    register struct token *t;
  333.    struct tok_lst *arg;
  334.    struct str_buf *sbuf;
  335.    char *s;
  336.    int indx;
  337.  
  338.    /*
  339.     * Get the next token from the macro body. It must be a macro parameter;
  340.     *  retrieve the raw tokens for the corresponding argument.
  341.     */
  342.    if (me->rest_bdy == NULL)
  343.       errt1(trigger, "the # operator must have an argument");
  344.    t = me->rest_bdy->t;
  345.    me->rest_bdy = me->rest_bdy->next;
  346.    if (t->tok_id == Identifier)
  347.       indx = parm_indx(t->image, me->m);
  348.    else
  349.       indx = -1;
  350.    if (indx == -1)
  351.       errt1(t, "the # operator may only be applied to a macro argument");
  352.    arg = me->args[indx];
  353.  
  354.    /*
  355.     * Copy the images for the argument tokens into a string buffer. Note
  356.     *  that the images of string and character literals lack quotes; these
  357.     *  must be escaped in the stringized value.
  358.     */
  359.    sbuf = get_sbuf();
  360.    while (arg != NULL) {
  361.       t = arg->t;
  362.       if (t->tok_id == WhiteSpace)
  363.          AppChar(*sbuf, ' ');
  364.       else if (t->tok_id == StrLit)
  365.          cpy_str("\\\"", t->image, "\\\"", sbuf);
  366.       else if (t->tok_id == LStrLit)
  367.          cpy_str("L\\\"", t->image, "\\\"", sbuf);
  368.       else if (t->tok_id == CharConst)
  369.          cpy_str("'", t->image, "'", sbuf);
  370.       else if (t->tok_id == LCharConst)
  371.          cpy_str("L'", t->image, "'", sbuf);
  372.       else
  373.          for (s = t->image; *s != '\0'; ++s)
  374.             AppChar(*sbuf, *s);
  375.       arg = arg->next;
  376.       }
  377.  
  378.    /*
  379.     * Created the token for the stringized argument.
  380.     */
  381.    t = new_token(StrLit, str_install(sbuf), trigger->fname, trigger->line);
  382.    t->flag |= trigger->flag & LineChk;
  383.    rel_sbuf(sbuf);
  384.    return t;
  385.    }
  386.  
  387. /*
  388.  * paste_parse - parse an expression involving token pasting operators (and
  389.  *  stringizing operators). Return a list of token lists. Each token list
  390.  *  is from a token pasting operand, with operands that are macro parameters
  391.  *  replaced by their corresponding argument (this is why a list of tokens
  392.  *  is needed for each operand). Any needed stringizing is done as the list
  393.  *  is created.
  394.  */
  395. static struct paste_lsts *paste_parse(t, me)
  396. struct token *t;
  397. struct mac_expand *me;
  398.    {
  399.    struct token *t1;
  400.    struct token *trigger = NULL;
  401.    struct tok_lst *lst;
  402.    struct paste_lsts *plst;
  403.    int indx;
  404.  
  405.    if (me->rest_bdy == NULL || me->rest_bdy->t->tok_id != PpPaste)
  406.       plst = NULL;  /* we have reached the end of the pasting expression */
  407.    else {
  408.       /*
  409.        * The next token is a pasting operator. Copy it an move on to the
  410.        *  operand.
  411.        */
  412.       trigger = copy_t(me->rest_bdy->t);
  413.       me->rest_bdy = me->rest_bdy->next;
  414.       if (me->rest_bdy == NULL)
  415.          errt1(t, "the ## operator must not appear at the end of a macro");
  416.       t1 = me->rest_bdy->t;
  417.       me->rest_bdy = me->rest_bdy->next;
  418.  
  419.       /*
  420.        * See if the operand is a stringizing operation.
  421.        */
  422.       if (t1->tok_id == '#')
  423.          t1 = stringize(t1, me);
  424.       else
  425.          t1 = copy_t(t1);
  426.       plst = paste_parse(t1, me); /* get any further token pasting */
  427.       }
  428.  
  429.    /*
  430.     * If the operand is a macro parameter, replace it by the corresponding
  431.     *  argument, otherwise make the operand into a 1-element token list.
  432.     */
  433.    indx = -1;
  434.    if (t->tok_id == Identifier)
  435.       indx = parm_indx(t->image, me->m);
  436.    if (indx == -1)
  437.       lst = new_t_lst(t);
  438.    else {
  439.       lst = me->args[indx];
  440.       free_t(t);
  441.       }
  442.  
  443.    /*
  444.     * Ignore emtpy arguments when constructing the pasting list.
  445.     */
  446.    if (lst == NULL)
  447.       return plst;
  448.    else
  449.       return new_plsts(trigger, lst, plst);
  450.    }
  451.  
  452. /*
  453.  * cpy_image - copy the image of a token into a character buffer adding
  454.  *  delimiters if it is a string or character literal.
  455.  */
  456. static int *cpy_image(t, s)
  457. struct token *t;
  458. int *s;          /* the string buffer can contain EOF */
  459.    {
  460.    register char *s1;
  461.  
  462.    switch (t->tok_id) {
  463.       case StrLit:
  464.          *s++ = '"';
  465.          break;
  466.       case LStrLit:
  467.          *s++ = 'L';
  468.          *s++ = '"';
  469.          break;
  470.       case CharConst:
  471.          *s++ = '\'';
  472.          break;
  473.       case LCharConst:
  474.          *s++ = 'L';
  475.          *s++ = '\'';
  476.          break;
  477.       }
  478.  
  479.    s1 = t->image;
  480.    while (*s1 != '\0')
  481.       *s++ = *s1++;
  482.  
  483.    switch (t->tok_id) {
  484.       case StrLit:
  485.       case LStrLit:
  486.          *s++ = '"';
  487.          break;
  488.       case CharConst:
  489.       case LCharConst:
  490.          *s++ = '\'';
  491.          break;
  492.       }
  493.  
  494.    return s;
  495.    }
  496.  
  497. /*
  498.  * paste - return the next token from a source which pastes tokens. The
  499.  *   source may represent a series of token pasting operators.
  500.  */
  501. struct token *paste()
  502.    {
  503.    struct token *t;
  504.    struct token *t1;
  505.    struct token *trigger;
  506.    struct paste_lsts *plst;
  507.    union src_ref ref;
  508.    int i;
  509.    int *s;
  510.  
  511.    plst = src_stack->u.plsts;
  512.  
  513.    /*
  514.     * If the next token of the current list is not the one to be pasted,
  515.     *  just return it.
  516.     */
  517.    t = copy_t(plst->tlst->t);
  518.    plst->tlst = plst->tlst->next;
  519.    if (plst->tlst != NULL)
  520.       return t;
  521.  
  522.    /*
  523.     * We have the last token from the current list. If there is another
  524.     *  list, this token must be pasted to the first token of that list.
  525.     *  Make the next list the current one and get its first token.
  526.     */
  527.    trigger = plst->trigger;
  528.    plst = plst->next;
  529.    free_plsts(src_stack->u.plsts);
  530.    src_stack->u.plsts = plst;
  531.    if (plst == NULL) {
  532.       pop_src();
  533.       return t;
  534.       }
  535.    t1 = next_tok();
  536.  
  537.    /*
  538.     * Paste tokens by creating a character source with the images of the
  539.     *  two tokens concatenated.
  540.     */
  541.    ref.cs = new_cs(trigger->fname, NULL,
  542.       (int)strlen(t->image) + (int)strlen(t1->image) + 7);
  543.    push_src(CharSrc, &ref);
  544.    s = cpy_image(t, ref.cs->char_buf);
  545.    s = cpy_image(t1, s);
  546.    *s = EOF;
  547.  
  548.    /*
  549.     * Treat all characters of the new source as if they come from the
  550.     *  location of the token pasting.
  551.     */
  552.    for (i = 0; i < (s - ref.cs->char_buf + 1); ++i)
  553.       *(ref.cs->line_buf) = trigger->line;
  554.    ref.cs->last_char = s;
  555.    ref.cs->dir_state = Reset;
  556.    first_char = ref.cs->char_buf;
  557.    next_char = first_char;
  558.    last_char = ref.cs->last_char;
  559.  
  560.    return next_tok(); /* first token from pasted images */
  561.    }
  562.  
  563. /*
  564.  * mac_tok - return the next token from a source which is a macro.
  565.  */
  566. struct token *mac_tok()
  567.    {
  568.    struct mac_expand *me;
  569.    register struct token *t, *t1;
  570.    struct paste_lsts *plst;
  571.    union src_ref ref;
  572.    int line_check;
  573.    int indx;
  574.    int line;
  575.    char *fname;
  576.  
  577.    me = src_stack->u.me; /* macro, current position, and arguments */
  578.  
  579.    /*
  580.     * Get the next token from the macro body.
  581.     */
  582.    if (me->rest_bdy == NULL)
  583.       return NULL;
  584.    t = me->rest_bdy->t;
  585.    me->rest_bdy = me->rest_bdy->next;
  586.  
  587.    /*
  588.     * If this token is a stringizing operator, try stringizing the next
  589.     *  token.
  590.     */
  591.    if (t->tok_id == '#')
  592.       t = stringize(t, me);
  593.    else
  594.       t = copy_t(t);
  595.  
  596.    if (me->rest_bdy != NULL && me->rest_bdy->t->tok_id == PpPaste) {
  597.       /*
  598.        * We have found token pasting. If there is a series of such operators,
  599.        *  make them all into one token pasting source and push it on
  600.        *  the source stack.
  601.        */
  602.       if (t->flag & LineChk) {
  603.          line_check = 1;
  604.          line = t->line;
  605.          fname = t->fname;
  606.          }
  607.       else
  608.          line_check = 0;
  609.       plst = paste_parse(t, me);
  610.       if (plst != NULL) {
  611.          ref.plsts = plst;
  612.          push_src(PasteLsts, &ref);
  613.          }
  614.       t1 = next_tok();
  615.       if (line_check && !(t1->flag & LineChk)) {
  616.          t1->flag |= LineChk;
  617.          t1->line = line;
  618.          t1->fname = fname;
  619.          }
  620.       return t1;
  621.       }
  622.    else if (t->tok_id == Identifier &&
  623.      (indx = parm_indx(t->image, me->m)) != -1) {
  624.       /*
  625.        * We have found a parameter. Push a token source for the corresponding
  626.        *  argument, that is, replace the parameter with its definition.
  627.        */
  628.       ref.tlst = me->exp_args[indx];
  629.       push_src(TokLst, &ref);
  630.       if (t->flag & LineChk) {
  631.          line = t->line;
  632.          fname = t->fname;
  633.          t1 = next_tok();
  634.          if (!(t1->flag & LineChk)) {
  635.             /*
  636.              * The parameter name token is significant with respect to
  637.              *  outputting #line directives but the first argument token
  638.              *  is not. Pretend the argument has the same line number as the
  639.              *  parameter name.
  640.              */
  641.             t1->flag |= LineChk;
  642.             t1->line = line;
  643.             t1->fname = fname;
  644.             }
  645.          free_t(t);
  646.          return t1;
  647.          }
  648.       else {
  649.          free_t(t);
  650.          return next_tok();
  651.          }
  652.       }
  653.    else {
  654.       /*
  655.        * This is an ordinary token, nothing further is needed here.
  656.        */
  657.       return t;
  658.       }
  659.    }
  660.