Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1320772
  • 博文数量: 179
  • 博客积分: 4141
  • 博客等级: 中将
  • 技术积分: 2083
  • 用 户 组: 普通用户
  • 注册时间: 2009-03-21 20:04
文章存档

2024年(1)

2019年(13)

2016年(1)

2014年(16)

2011年(8)

2010年(25)

2009年(115)

分类: 嵌入式

2009-03-21 22:01:57

函数流程


  1. /*
  2.  * Expand all single-line macro calls made in the given line.
  3.  * Return the expanded version of the line. The original is deemed
  4.  * to be destroyed in the process. (In reality we'll just move
  5.  * Tokens from input to output a lot of the time, rather than
  6.  * actually bothering to destroy and replicate.)
  7.  */
  8. static Token *expand_smacro(Token * tline)
  9. {
  10.     Token *t, *tt, *mstart, **tail, *thead;
  11.     SMacro *head = NULL, *m;
  12.     Token **params;
  13.     int *paramsize;
  14.     int nparam, sparam, brackets, rescan;
  15.     Token *org_tline = tline;
  16.     Context *ctx;
  17.     char *mname;

  18.     /*
  19.      * Trick: we should avoid changing the start token pointer since it can
  20.      * be contained in "next" field of other token. Because of this
  21.      * we allocate a copy of first token and work with it; at the end of
  22.      * routine we copy it back
  23.      */
  24.     if (org_tline) {
  25.         tline = new_Token(org_tline->next, org_tline->type, org_tline->text, 0);
  26.         tline->mac = org_tline->mac;
  27.         nasm_free(org_tline->text);
  28.         org_tline->text = NULL;
  29.     }

  30.   again:
  31.     tail = &thead;
  32.     thead = NULL;

  33.     while (tline)
  34.     { /* main token loop */
  35.         if ((mname = tline->text))
  36.         {
  37.             /* 获取与tline->text相关的宏 */
  38.             /* if this token is a local macro, look in local context */
  39.             if (tline->type == TOK_ID || tline->type == TOK_PREPROC_ID)
  40.                 ctx = get_ctx(mname, TRUE);
  41.             else
  42.                 ctx = NULL;
  43.             if (!ctx)
  44.                 head = smacros[hash(mname)];
  45.             else
  46.                 head = ctx->localmac;
  47.             /*
  48.              * We've hit an identifier. As in is_mmacro below, we first
  49.              * check whether the identifier is a single-line macro at
  50.              * all, then think about checking for parameters if
  51.              * necessary.
  52.              */
  53.             for (m = head; m; m = m->next)
  54.             {
  55.                 if (!mstrcmp(m->name, mname, m->casesense))
  56.                     break;
  57.             }

  58.             /* 如果存在与tline->text相关的宏 */
  59.             if (m)
  60.             {
  61.                 mstart = tline;
  62.                 params = NULL;
  63.                 paramsize = NULL;
  64.                 if (m->nparam == 0)
  65.                 {
  66.                     /*
  67.                      * Simple case: the macro is parameterless. Discard the
  68.                      * one token that the macro call took, and push the
  69.                      * expansion back on the to-do stack.
  70.                      */
  71.                     if (!m->expansion)
  72.                     {
  73.                         /* 处理Nasm预先定义的宏__FILE__ */
  74.                         if (!strcmp("__FILE__", m->name))
  75.                         {
  76.                             long num = 0;
  77.                             src_get(&num, &(tline->text));
  78.                             nasm_quote(&(tline->text));
  79.                             tline->type = TOK_STRING;
  80.                             continue;
  81.                         }
  82.                         /* 处理Nasm预先定义的宏__LINE__ */
  83.                         if (!strcmp("__LINE__", m->name))
  84.                         {
  85.                             nasm_free(tline->text);
  86.                             make_tok_num(tline, src_get_linnum());
  87.                             continue;
  88.                         }
  89.                         /* 空宏 */
  90.                         tline = delete_Token(tline);
  91.                         continue;
  92.                     }
  93.                 }
  94.                 else
  95.                 {
  96.                     /*
  97.                      * Complicated case: at least one macro with this name
  98.                      * exists and takes parameters. We must find the
  99.                      * parameters in the call, count them, find the SMacro
  100.                      * that corresponds to that form of the macro call, and
  101.                      * substitute for the parameters when we expand. What a
  102.                      * pain.
  103.                      */
  104.                     /* tline = tline->next;
  105.                        skip_white_(tline); */
  106.                     do {
  107.                         t = tline->next;
  108.                         /* ????? */
  109.                         while (tok_type_(t, TOK_SMAC_END)) {
  110.                             t->mac->in_progress = FALSE;
  111.                             t->text = NULL;
  112.                             t = tline->next = delete_Token(t);
  113.                         }
  114.                         tline = t;
  115.                     } while (tok_type_(tline, TOK_WHITESPACE));
  116.                     if (!tok_is_(tline, "("))
  117.                     {
  118.                         /*
  119.                          * This macro wasn't called with parameters: ignore
  120.                          * the call. (Behaviour borrowed from gnu cpp.)
  121.                          */
  122.                         tline = mstart;
  123.                         m = NULL;
  124.                     }
  125.                     else /* '(',处理宏参数 */
  126.                     {
  127.                         int paren = 0;
  128.                         int white = 0;
  129.                         brackets = 0;
  130.                         nparam = 0;
  131.                         sparam = PARAM_DELTA;
  132.                         params = nasm_malloc(sparam * sizeof(Token *));
  133.                         params[0] = tline->next;
  134.                         paramsize = nasm_malloc(sparam * sizeof(int));
  135.                         paramsize[0] = 0;
  136.                         /* 正式处理宏参数,将宏参数放入params中,并且计算宏参数的个数 */
  137.                         while (TRUE) { /* parameter loop */
  138.                             /*
  139.                              * For some unusual expansions
  140.                              * which concatenates function call
  141.                              */
  142.                             t = tline->next;
  143.                             /* ????? */
  144.                             while (tok_type_(t, TOK_SMAC_END)) {
  145.                                 t->mac->in_progress = FALSE;
  146.                                 t->text = NULL;
  147.                                 t = tline->next = delete_Token(t);
  148.                             }
  149.                             tline = t;

  150.                             if (!tline) {
  151.                                 error(ERR_NONFATAL, "macro call expects terminating `)'");
  152.                                 break;
  153.                             }
  154.                             if (tline->type == TOK_WHITESPACE && brackets <= 0) {
  155.                                 if (paramsize[nparam])
  156.                                     white++;
  157.                                 else
  158.                                     params[nparam] = tline->next;
  159.                                 continue; /* parameter loop */
  160.                             }
  161.                             if (tline->type == TOK_OTHER && tline->text[1] == 0) /* 判断是否是单字符 */
  162.                             {
  163.                                 char ch = tline->text[0];
  164.                                 if (ch == ',' && !paren && brackets <= 0) { /* 处理完一个参数 */
  165.                                     if (++nparam >= sparam) { /* 如果原有的数据不够,重新分配缓存 */
  166.                                         sparam += PARAM_DELTA;
  167.                                         params = nasm_realloc(params, sparam * sizeof(Token *));
  168.                                         paramsize = nasm_realloc(paramsize, sparam * sizeof(int));
  169.                                     }
  170.                                     params[nparam] = tline->next;
  171.                                     paramsize[nparam] = 0;
  172.                                     white = 0;
  173.                                     continue; /* parameter loop */
  174.                                 }
  175.                                 if (ch == '{' && (brackets > 0 || (brackets == 0 && !paramsize[nparam])))
  176.                                 {
  177.                                     if (!(brackets++)) {
  178.                                         params[nparam] = tline->next; /* 去掉'{' */
  179.                                         continue; /* parameter loop */
  180.                                     }
  181.                                 }
  182.                                 if (ch == '}' && brackets > 0)
  183.                                     if (--brackets == 0) {
  184.                                         brackets = -1; /* 单行宏参数中不能使用'{''}',去掉 '}' */
  185.                                         continue; /* parameter loop */
  186.                                     }
  187.                                 if (ch == '(' && !brackets)
  188.                                     paren++;
  189.                                 if (ch == ')' && brackets <= 0)
  190.                                     if (--paren < 0)
  191.                                         break;
  192.                             }
  193.                             if (brackets < 0) {
  194.                                 brackets = 0;
  195.                                 error(ERR_NONFATAL, "braces do not enclose all of macro parameter");
  196.                             }
  197.                             paramsize[nparam] += white + 1;
  198.                             white = 0;
  199.                         } /* parameter loop */
  200.                         nparam++;
  201.                         while (m && (m->nparam != nparam || mstrcmp(m->name, mname, m->casesense))) /* 处理同名宏不同参数的情况,找到相应的宏 */
  202.                             m = m->next;
  203.                         if (!m)
  204.                             error(ERR_WARNING | ERR_WARN_MNP, "macro `%s' exists, but not taking %d parameters", mstart->text, nparam);
  205.                     }
  206.                 }
  207.                 if (m && m->in_progress)
  208.                     m = NULL;
  209.                 if (!m) { /* in progess or didn't find '(' or wrong nparam */
  210.                     /*
  211.                      * Design question: should we handle !tline, which
  212.                      * indicates missing ')' here, or expand those
  213.                      * macros anyway, which requires the (t) test a few
  214.                      * lines down?
  215.                      */
  216.                     nasm_free(params);
  217.                     nasm_free(paramsize);
  218.                     tline = mstart;
  219.                 } else {
  220.                     /*
  221.                      * Expand the macro: we are placed on the last token of the
  222.                      * call, so that we can easily split the call from the
  223.                      * following tokens. We also start by pushing an SMAC_END
  224.                      * token for the cycle removal.
  225.                      */
  226.                     t = tline;
  227.                     if (t) {
  228.                         tline = t->next;
  229.                         t->next = NULL;
  230.                     }
  231.                     tt = new_Token(tline, TOK_SMAC_END, NULL, 0);
  232.                     tt->mac = m;
  233.                     m->in_progress = TRUE;
  234.                     tline = tt;
  235.                     /* 真实的参数扩展 */
  236.                     for (t = m->expansion; t; t = t->next) {
  237.                         if (t->type >= TOK_SMAC_PARAM) {
  238.                             Token *pcopy = tline, **ptail = &pcopy;
  239.                             Token *ttt, *pt;
  240.                             int i;

  241.                             ttt = params[t->type - TOK_SMAC_PARAM]; /* 获取实参 */
  242.                             for (i = paramsize[t->type - TOK_SMAC_PARAM]; --i >= 0;) {
  243.                                 pt = *ptail = new_Token(tline, ttt->type, ttt->text, 0);
  244.                                 ptail = &pt->next;
  245.                                 ttt = ttt->next;
  246.                             }
  247.                             tline = pcopy;
  248.                         } else {
  249.                             tt = new_Token(tline, t->type, t->text, 0);
  250.                             tline = tt;
  251.                         }
  252.                     }

  253.                     /*
  254.                      * Having done that, get rid of the macro call, and clean
  255.                      * up the parameters.
  256.                      */
  257.                     nasm_free(params);
  258.                     nasm_free(paramsize);
  259.                     free_tlist(mstart);
  260.                     continue; /* main token loop */
  261.                 }
  262.             }
  263.         }

  264.         if (tline->type == TOK_SMAC_END) {
  265.             tline->mac->in_progress = FALSE;
  266.             tline = delete_Token(tline);
  267.         } else {
  268.             t = *tail = tline;
  269.             tline = tline->next;
  270.             t->mac = NULL;
  271.             t->next = NULL;
  272.             tail = &t->next;
  273.         }
  274.     }

  275.     /*
  276.      * Now scan the entire line and look for successive TOK_IDs that resulted
  277.      * after expansion (they can't be produced by tokenise()). The successive
  278.      * TOK_IDs should be concatenated.
  279.      * Also we look for %+ tokens and concatenate the tokens before and after
  280.      * them (without white spaces in between).
  281.      */
  282.     t = thead;
  283.     rescan = 0;
  284.     while (t) {
  285.         while (t && t->type != TOK_ID && t->type != TOK_PREPROC_ID)
  286.             t = t->next;
  287.         if (!t || !t->next)
  288.             break;
  289.         /*
  290.          * %define ADD(a,b) ((a) + (b))
  291.          * %define ADD(a,b,c) ((a %+ DD(1,2)) + (b) + (c))
  292.          *
  293.          * [bits 32]
  294.          * _start:
  295.          * mov eax,ADD(1,3)
  296.          * mov eax,ADD(A,2,3)
  297.          */
  298.         if (t->next->type == TOK_ID ||
  299.             t->next->type == TOK_PREPROC_ID ||
  300.             t->next->type == TOK_NUMBER) {
  301.             char *p = nasm_strcat(t->text, t->next->text);
  302.             nasm_free(t->text);
  303.             t->next = delete_Token(t->next);
  304.             t->text = p;
  305.             rescan = 1;
  306.         } else if (t->next->type == TOK_WHITESPACE && t->next->next &&
  307.                    t->next->next->type == TOK_PREPROC_ID &&
  308.                    strcmp(t->next->next->text, "%+") == 0) {
  309.             /* free the next whitespace, the %+ token and next whitespace */
  310.             int i;
  311.             for (i = 1; i <= 3; i++) {
  312.                 if (!t->next
  313.                     || (i != 2 && t->next->type != TOK_WHITESPACE))
  314.                     break;
  315.                 t->next = delete_Token(t->next);
  316.             } /* endfor */
  317.         } else
  318.             t = t->next;
  319.     }
  320.     /* If we concatenaded something, re-scan the line for macros */
  321.     if (rescan) {
  322.         tline = thead;
  323.         goto again;
  324.     }

  325.     if (org_tline) {
  326.         if (thead) {
  327.             *org_tline = *thead;
  328.             /* since we just gave text to org_line, don't free it */
  329.             thead->text = NULL;
  330.             delete_Token(thead);
  331.         } else {
  332.             /* the expression expanded to empty line;
  333.                we can't return NULL for some reasons
  334.                we just set the line to a single WHITESPACE token. */
  335.             memset(org_tline, 0, sizeof(*org_tline));
  336.             org_tline->text = NULL;
  337.             org_tline->type = TOK_WHITESPACE;
  338.         }
  339.         thead = org_tline;
  340.     }

  341.     return thead;
  342. }


阅读(2087) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~