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

2019年(31)

2016年(1)

2014年(16)

2011年(8)

2010年(25)

2009年(115)

分类: 嵌入式

2009-03-21 21:55:39

Preprocessor预处理器的数据结构关系: 


/*

 * Store the definition of a single-line macro.

 */


struct SMacro {

    SMacro *next;

    char *name;

    int casesense;

    int nparam;

    int in_progress;

    Token *expansion;

};



/*

 * Store the definition of a multi-line macro. This is also used to

 * store the interiors of `%rep...%endrep' blocks, which are

 * effectively self-re-invoking multi-line macros which simply

 * don't have a name or bother to appear in the hash tables. %rep

 * blocks are signified by having a NULL `name' field.

 *

 * In a MMacro describing a `%rep' block, the `in_progress' field

 * isn't merely boolean, but gives the number of repeats left to

 * run.

 *

 * The `next' field is used for storing MMacros in hash tables; the

 * `next_active' field is for stacking them on istk entries.

 *

 * When a MMacro is being expanded, `params', `iline', `nparam',

 * `paramlen', `rotate' and `unique' are local to the invocation.

 */


struct MMacro {

    MMacro *next;

    char *name;

    int casesense;

    int nparam_min, nparam_max;

    int plus; /* is the last parameter greedy? */

    int nolist; /* is this macro listing-inhibited? */

    int in_progress;

    Token *dlist; /* All defaults as one list */

    Token **defaults; /* Parameter default pointers */

    int ndefs; /* number of default parameters */

    Line *expansion;



    MMacro *next_active;

    MMacro *rep_nest; /* used for nesting %rep */

    Token **params; /* actual parameters */

    Token *iline; /* invocation line */

    int nparam, rotate, *paramlen;

    unsigned long unique;

    int lineno; /* Current line number on expansion */

};



/*

 * The context stack is composed of a linked list of these.

 */


struct Context {

    Context *next;

    SMacro *localmac;

    char *name;

    unsigned long number;

};



/*

 * This is the internal form which we break input lines up into.

 * Typically stored in linked lists.

 *

 * Note that `type' serves a double meaning: TOK_SMAC_PARAM is not

 * necessarily used as-is, but is intended to denote the number of

 * the substituted parameter. So in the definition

 *

 * %define a(x,y) ( (x) & ~(y) )

 *

 * the token representing `x' will have its type changed to

 * TOK_SMAC_PARAM, but the one representing `y' will be

 * TOK_SMAC_PARAM+1.

 *

 * TOK_INTERNAL_STRING is a dirty hack: it's a single string token

 * which doesn't need quotes around it. Used in the pre-include

 * mechanism as an alternative to trying to find a sensible type of

 * quote to use on the filename we were passed.

 */


struct Token {

    Token *next;

    char *text;

    SMacro *mac; /* associated macro for TOK_SMAC_END */

    int type;

};

enum {

    TOK_WHITESPACE = 1, TOK_COMMENT, TOK_ID, TOK_PREPROC_ID, TOK_STRING,

    TOK_NUMBER, TOK_SMAC_END, TOK_OTHER, TOK_SMAC_PARAM,

    TOK_INTERNAL_STRING

};



/*

 * Multi-line macro definitions are stored as a linked list of

 * these, which is essentially a container to allow several linked

 * lists of Tokens.

 *

 * Note that in this module, linked lists are treated as stacks

 * wherever possible. For this reason, Lines are _pushed_ on to the

 * `expansion' field in MMacro structures, so that the linked list,

 * if walked, would give the macro lines in reverse order; this

 * means that we can walk the list when expanding a macro, and thus

 * push the lines on to the `expansion' field in _istk_ in reverse

 * order (so that when popped back off they are in the right

 * order). It may seem cockeyed, and it relies on my design having

 * an even number of steps in, but it works...

 *

 * Some of these structures, rather than being actual lines, are

 * markers delimiting the end of the expansion of a given macro.

 * This is for use in the cycle-tracking and %rep-handling code.

 * Such structures have `finishes' non-NULL, and `first' NULL. All

 * others have `finishes' NULL, but `first' may still be NULL if

 * the line is blank.

 */


struct Line {

    Line *next;

    MMacro *finishes;

    Token *first;

};



/*

 * To handle an arbitrary level of file inclusion, we maintain a

 * stack (ie linked list) of these things.

 */


struct Include {

    Include *next;

    FILE *fp;

    Cond *conds;

    Line *expansion;

    char *fname;

    int lineno, lineinc;

    MMacro *mstk; /* stack of active macros/reps */

};



/*

 * Include search path. This is simply a list of strings which get

 * prepended, in turn, to the name of an include file, in an

 * attempt to find the file if it's not in the current directory.

 */


struct IncPath {

    IncPath *next;

    char *path;

};



/*

 * Conditional assembly: we maintain a separate stack of these for

 * each level of file inclusion. (The only reason we keep the

 * stacks separate is to ensure that a stray `%endif' in a file

 * included from within the true branch of a `%if' won't terminate

 * it and cause confusion: instead, rightly, it'll cause an error.)

 */


struct Cond {

    Cond *next;

    int state;

};


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