TCC(TinyC)编译器汉化(中文编译器、汉语编程)之三:词法分析

词法分析.h 源码如下:

/*
 *  功能:预处理,词法分析
 *  只在hexinku.c第7行一个地方引用
 */
#定义 全局_使用
#导入 "zhi.h"

/********************************************************/
/* 全局变量 */

静态_外部 整数型 标识符_标记;
静态_外部 整数型 解析_标记;

静态_外部 结构体 缓冲文件 *file;
静态_外部 整数型 当前取到的源码字符, 单词编码;
静态_外部 恒定值 单词值;
静态_外部 常量 整数型 *宏_ptr;
静态_外部 动态字符串 当前单词字符串;

/* 显示基准信息 */
静态_外部 整数型 单词_识别号;
静态_外部 单词存储结构 **单词表;

/* ------------------------------------------------------------------------- */

静态 单词存储结构 *单词_哈希表[哈希表容量];
静态 字符型 标识符_缓冲[字符串_最大_长度 + 1];
静态 动态字符串 动态字符串_缓冲;
静态 动态字符串 宏_等于_缓冲区;
静态 单词字符串 单词字符串_缓冲;
静态 无符号 字符型 等值_表[256 - CH_文件结尾];
静态 整数型 词法分析_调试_标识符, 词法分析_调试_字符值;
静态 整数型 词法分析_第一次;
静态 整数型 词法分析_表达式;
静态 整数型 词法分析_计数器;
静态 无类型 标识符_打印(常量 字符型 *msg, 常量 整数型 *str);

静态 结构体 微内存分配 *单词字符_分配内存;
静态 结构体 微内存分配 *单词字符串_分配内存;

静态 单词字符串 *宏_堆栈;

静态 常量 字符型 编译_关键词[] = 
#定义 字符(id, str) str "\0"
#导入 "字符.h"
;

/* 双字符符号编号 */
静态 常量 无符号 字符型 双字符符号[] =
{
    '<','=', 双符号_小于等于,
    '>','=', 双符号_大于等于,
    '!','=', 双符号_不等于,
    '&','&', 双符号_逻辑与,
    '|','|', 双符号_逻辑或,
    '+','+', 双符号_自加1,
    '-','-', 双符号_自减1,
    '=','=', 双符号_等于,
    '<','<', 双符号_左位移,
    '>','>', 双符号_右位移,
    '+','=', 双符号_先求和后赋值,
    '-','=', 双符号_先求差后赋值,
    '*','=', 双符号_先求积后赋值,
    '/','=', 双符号_先求商后赋值,
    '%','=', 双符号_先取模后赋值,
    '&','=', 双符号_先求位与后赋值,
    '^','=', 双符号_先求异或后赋值,
    '|','=', 双符号_先求位或后赋值,
    '-','>', 双符号_结构体指针运算符,
    '.','.', 双符号_2个圆点号,
    '#','#', 双符号_2个井号,
    0
};

静态 无类型 取_下个符号_不宏扩展(无类型);
/*跳到下一个标识符*/
静态_函数 无类型 跳过(整数型 c)
{
    如果 (单词编码 != c)
        错误_打印("'%c'(程序中的 \"%s\")应为:''", c, 取_单词字符串(单词编码, &单词值));
    带有宏替换的下个标记();
}

静态_函数 无类型 应为(常量 字符型 *msg)
{
    错误_打印("%s 应为", msg);
}

/* ------------------------------------------------------------------------- */
/* 自定义分配器,用于微小对象 */

#定义 小对象_分配器

#如果未定义 小对象_分配器
#定义 小分配器_释放(al, p) 内存_释放(p)
#定义 小分配器_重新分配(al, p, size) 内存_重分配容量(p, size)
#定义 小分配器_新建(a,b,c)
#定义 小分配器_删除(a)
#否则
#如果 !已定义(内存_调试)
#定义 小分配器_释放(al, p) 小分配器_释放_impl(al, p)
#定义 小分配器_重新分配(al, p, size) 小分配器_重分配_impl(&al, p, size)
#定义 小分配器_调试_参数
#否则
#定义 小分配器_调试 1
#定义 小分配器_释放(al, p) 小分配器_释放_impl(al, p, __FILE__, __LINE__)
#定义 小分配器_重新分配(al, p, size) 小分配器_重分配_impl(&al, p, size, __FILE__, __LINE__)
#定义 小分配器_调试_参数 , 常量 字符型 *file, 整数型 line
#定义 小分配器_调试_文件_长度 40
#结束如果

#定义 单词字符_小分配器_大小     (768 * 1024) /* 表_识别中微小TokenSym的分配器 */
#定义 单词字符串_小分配器_大小     (768 * 1024) /* 微小TokenString实例的分配器 */
#定义 动态字符串_小分配器_大小       (256 * 1024) /* 小型CString实例的分配器。没有使用 */
#定义 单词字符_小分配器_限制    256 /* 倾向于使用唯一的限制来区分分配器调试消息 */
#定义 单词字符串_小分配器_限制    128 /* 32 * 取大小(整数型) */
#定义 动态字符串_小分配器_限制      1024
类型定义 结构体 微内存分配 {
    无符号  limit;
    无符号  size;
    uint8_t *buffer;
    uint8_t *p;
    无符号  数量_allocs;
    结构体 微内存分配 *next, *top;
#如果已定义 小分配器_信息
    无符号  数量_peak;
    无符号  数量_total;
    无符号  数量_missed;
    uint8_t *peak_p;
#结束如果
} 微内存分配;

类型定义 结构体 小分配器_header_t {
    无符号  size;
#如果已定义 小分配器_调试
    整数型     line_num; /* 拒绝line_num用于双重释放检查 */
    字符型    file_name[小分配器_调试_文件_长度 + 1];
#结束如果
} 小分配器_header_t;

/* ------------------------------------------------------------------------- */

静态 微内存分配 *小分配器_新建(微内存分配 **pal, 无符号 limit, 无符号 size)
{
    微内存分配 *al = 内存_初始化(取大小(微内存分配));
    al->p = al->buffer = 内存_申请(size);
    al->limit = limit;
    al->size = size;
    如果 (pal) *pal = al;
    返回 al;
}

静态 无类型 小分配器_删除(微内存分配 *al)
{
    微内存分配 *next;

tail_call:
    如果 (!al)
        返回;
#如果已定义 小分配器_信息
    fprintf(stderr, "limit=%5d, size=%5g MB, 数量_peak=%6d, 数量_total=%8d, 数量_missed=%6d, usage=%5.1f%%\n",
            al->limit, al->size / 1024.0 / 1024.0, al->数量_peak, al->数量_total, al->数量_missed,
            (al->peak_p - al->buffer) * 100.0 / al->size);
#结束如果
#如果已定义 小分配器_调试
    如果 (al->数量_allocs > 0) {
        uint8_t *p;
        fprintf(stderr, "小分配器_调试: 内存泄漏 %d 个数据块 (限制= %d)\n",
                al->数量_allocs, al->limit);
        p = al->buffer;
        判断 (p < al->p) {
            小分配器_header_t *header = (小分配器_header_t *)p;
            如果 (header->line_num > 0) {
                fprintf(stderr, "%s:%d:  %d 个字节的块泄漏\n",
                        header->file_name, header->line_num, header->size);
            }
            p += header->size + 取大小(小分配器_header_t);
        }
#如果 内存_调试-0 == 2
        exit(2);
#结束如果
    }
#结束如果
    next = al->next;
    内存_释放(al->buffer);
    内存_释放(al);
    al = next;
    去向 tail_call;
}

静态 无类型 小分配器_释放_impl(微内存分配 *al, 无类型 *p 小分配器_调试_参数)
{
    如果 (!p)
        返回;
tail_call:
    如果 (al->buffer <= (uint8_t *)p && (uint8_t *)p < al->buffer + al->size) {
#如果已定义 小分配器_调试
        小分配器_header_t *header = (((小分配器_header_t *)p) - 1);
        如果 (header->line_num < 0) {
            fprintf(stderr, "%s:%d: 小分配器_调试: 双重释放块\n",
                    file, line);
            fprintf(stderr, "%s:%d: %d 个字节\n",
                    header->file_name, (整数型)-header->line_num, (整数型)header->size);
        } 否则
            header->line_num = -header->line_num;
#结束如果
        al->数量_allocs--;
        如果 (!al->数量_allocs)
            al->p = al->buffer;
    } 否则 如果 (al->next) {
        al = al->next;
        去向 tail_call;
    }
    否则
        内存_释放(p);
}

静态 无类型 *小分配器_重分配_impl(微内存分配 **pal, 无类型 *p, 无符号 size 小分配器_调试_参数)
{
    小分配器_header_t *header;
    无类型 *ret;
    整数型 is_own;
    无符号 adj_size = (size + 3) & -4;
    微内存分配 *al = *pal;

tail_call:
    is_own = (al->buffer <= (uint8_t *)p && (uint8_t *)p < al->buffer + al->size);
    如果 ((!p || is_own) && size <= al->limit) {
        如果 (al->p - al->buffer + adj_size + 取大小(小分配器_header_t) < al->size) {
            header = (小分配器_header_t *)al->p;
            header->size = adj_size;
#如果已定义 小分配器_调试
            { 整数型 ofs = strlen(file) - 小分配器_调试_文件_长度;
            strncpy(header->file_name, file + (ofs > 0 ? ofs : 0), 小分配器_调试_文件_长度);
            header->file_name[小分配器_调试_文件_长度] = 0;
            header->line_num = line; }
#结束如果
            ret = al->p + 取大小(小分配器_header_t);
            al->p += adj_size + 取大小(小分配器_header_t);
            如果 (is_own) {
                header = (((小分配器_header_t *)p) - 1);
                如果 (p) memcpy(ret, p, header->size);
#如果已定义 小分配器_调试
                header->line_num = -header->line_num;
#结束如果
            } 否则 {
                al->数量_allocs++;
            }
#如果已定义 小分配器_信息
            如果 (al->数量_peak < al->数量_allocs)
                al->数量_peak = al->数量_allocs;
            如果 (al->peak_p < al->p)
                al->peak_p = al->p;
            al->数量_total++;
#结束如果
            返回 ret;
        } 否则 如果 (is_own) {
            al->数量_allocs--;
            ret = 小分配器_重新分配(*pal, 0, size);
            header = (((小分配器_header_t *)p) - 1);
            如果 (p) memcpy(ret, p, header->size);
#如果已定义 小分配器_调试
            header->line_num = -header->line_num;
#结束如果
            返回 ret;
        }
        如果 (al->next) {
            al = al->next;
        } 否则 {
            微内存分配 *bottom = al, *next = al->top ? al->top : al;

            al = 小分配器_新建(pal, next->limit, next->size * 2);
            al->next = next;
            bottom->top = al;
        }
        去向 tail_call;
    }
    如果 (is_own) {
        al->数量_allocs--;
        ret = 内存_申请(size);
        header = (((小分配器_header_t *)p) - 1);
        如果 (p) memcpy(ret, p, header->size);
#如果已定义 小分配器_调试
        header->line_num = -header->line_num;
#结束如果
    } 否则 如果 (al->next) {
        al = al->next;
        去向 tail_call;
    } 否则
        ret = 内存_重分配容量(p, size);
#如果已定义 小分配器_信息
    al->数量_missed++;
#结束如果
    返回 ret;
}

#结束如果 /* 小对象_分配器 */

/* ------------------------------------------------------------------------- */
静态 无类型 动态字符串_重分配内存(动态字符串 *cstr, 整数型 字符串新长度)
{
    整数型 size;

    size = cstr->缓冲区长度;
    如果 (size < 8)
        size = 8;
    判断 (size < 字符串新长度)
        size = size * 2;
    cstr->指向字符串的指针 = 内存_重分配容量(cstr->指向字符串的指针, size);
    cstr->缓冲区长度 = size;
}

静态_内联 无类型 动态字符串_追加单个字符(动态字符串 *cstr, 整数型 当前取到的源码字符)
{
    整数型 size;
    size = cstr->字符串长度 + 1;
    如果 (size > cstr->缓冲区长度)
        动态字符串_重分配内存(cstr, size);
    ((无符号 字符型 *)cstr->指向字符串的指针)[size - 1] = 当前取到的源码字符;
    cstr->字符串长度 = size;
}

静态_函数 无类型 动态字符串_cat(动态字符串 *cstr, 常量 字符型 *str, 整数型 len)
{
    整数型 size;
    如果 (len <= 0)
        len = strlen(str) + 1 + len;
    size = cstr->字符串长度 + len;
    如果 (size > cstr->缓冲区长度)
        动态字符串_重分配内存(cstr, size);
    memmove(((无符号 字符型 *)cstr->指向字符串的指针) + cstr->字符串长度, str, len);
    cstr->字符串长度 = size;
}

/* 增加一个宽字符 */
静态_函数 无类型 动态字符串_追加一个宽字符(动态字符串 *cstr, 整数型 当前取到的源码字符)
{
    整数型 size;
    size = cstr->字符串长度 + 取大小(nwchar_t);
    如果 (size > cstr->缓冲区长度)
        动态字符串_重分配内存(cstr, size);
    *(nwchar_t *)(((无符号 字符型 *)cstr->指向字符串的指针) + size - 取大小(nwchar_t)) = 当前取到的源码字符;
    cstr->字符串长度 = size;
}
静态_函数 无类型 动态字符串_初始化(动态字符串 *cstr)
{
	/*memset(无类型 *s, 整数型 c, 无符号 long n);函数的功能是:将指针变量 s 所指向的前 n 字节的内存单元用一个“整数” c 替换,注意 c 是 整数型 型。s 是 无类型* 型的指针变量,所以它可以为任何类型的数据进行初始化。*/
    memset(cstr, 0, 取大小(动态字符串));
}

静态_函数 无类型 动态字符串_释放(动态字符串 *cstr)
{
    内存_释放(cstr->指向字符串的指针);
    动态字符串_初始化(cstr);
}

/* 将字符串重置为空 */
静态_函数 无类型 动态字符串_重置(动态字符串 *cstr)
{
    cstr->字符串长度 = 0;
}

静态_函数 整数型 动态字符串_打印(动态字符串 *cstr, 常量 字符型 *fmt, ...)
{
    va_list v;
    整数型 len, size;
/*在运行VA_START(va_list ap, last_arg)以后,ap指向第一个可变参数在堆栈的地址。
 * last_arg 是最后一个传递给函数的已知的固定参数,即省略号之前的参数。
 */
    va_start(v, fmt);
    len = vsnprintf(NULL, 0, fmt, v);
    va_end(v);
    size = cstr->字符串长度 + len + 1;
    如果 (size > cstr->缓冲区长度)
        动态字符串_重分配内存(cstr, size);
    va_start(v, fmt);
    vsnprintf((字符型*)cstr->指向字符串的指针 + cstr->字符串长度, size, fmt, v);
    va_end(v);
    cstr->字符串长度 += len;
    返回 len;
}

/* XXX: 统一码 ? */
静态 无类型 添加_字符(动态字符串 *cstr, 整数型 c)
{
    如果 (c == '\'' || c == '\"' || c == '\\') {
        /* XXX: 如果使用char或string可能更精确 */
        动态字符串_追加单个字符(cstr, '\\');
    }
    如果 (c >= 32 && c <= 126) {
        动态字符串_追加单个字符(cstr, c);
    } 否则 {
        动态字符串_追加单个字符(cstr, '\\');
        如果 (c == '\n') {
            动态字符串_追加单个字符(cstr, 'n');
        } 否则 {
            动态字符串_追加单个字符(cstr, '0' + ((c >> 6) & 7));
            动态字符串_追加单个字符(cstr, '0' + ((c >> 3) & 7));
            动态字符串_追加单个字符(cstr, '0' + (c & 7));
        }
    }
}

/* ------------------------------------------------------------------------- */
/* 分配新标识*/
静态 单词存储结构 *标识符_分配新内存(单词存储结构 **pts, 常量 字符型 *str, 整数型 len)
{
    单词存储结构 *ts, **ptable;
    整数型 i;

    如果 (单词_识别号 >= 符号_第一个_匿名) 
        错误_打印("内存已满(符号)");

    /* 必要的时候可以扩展标识符表 */
    i = 单词_识别号 - 符_识别;
    如果 ((i % 符_分配_INCR) == 0) {
        ptable = 内存_重分配容量(单词表, (i + 符_分配_INCR) * 取大小(单词存储结构 *));
        单词表 = ptable;
    }

    ts = 小分配器_重新分配(单词字符_分配内存, 0, 取大小(单词存储结构) + len);
    单词表[i] = ts;
    ts->单词编码 = 单词_识别号++;
    ts->sym_define = NULL;
    ts->sym_label = NULL;
    ts->sym_struct = NULL;
    ts->sym_identifier = NULL;
    ts->len = len;
    ts->hash_next = NULL;
    memcpy(ts->str, str, len);
    ts->str[len] = '\0';
    *pts = ts;
    返回 ts;
}

#定义 符_哈希_初始化 1
#定义 符_哈希_函数(h, c) ((h) + ((h) << 5) + ((h) >> 27) + (c))
/*单词表中查找单词_如不存在就添加它*/
静态_函数 单词存储结构 *单词表_查找(常量 字符型 *str, 整数型 len)
{
    单词存储结构 *单词存储结构, **pts;
    整数型 i;
    无符号 整数型 h;
    
    h = 符_哈希_初始化;
    循环(i=0;i<len;i++)
        h = 符_哈希_函数(h, ((无符号 字符型 *)str)[i]);
    h &= (哈希表容量 - 1);

    pts = &单词_哈希表[h];
    循环(;;) {
    	单词存储结构 = *pts;
        如果 (!单词存储结构)
            跳出;
        如果 (单词存储结构->len == len && !memcmp(单词存储结构->str, str, len))
            返回 单词存储结构;
        pts = &(单词存储结构->hash_next);
    }
    返回 标识符_分配新内存(pts, str, len);
}
静态_函数 常量 字符型 *取_单词字符串(整数型 v, 恒定值 *cv)
{
    字符型 *p;
    整数型 i, len;

    动态字符串_重置(&动态字符串_缓冲);
    p = 动态字符串_缓冲.指向字符串的指针;

    选择(v) {
    分支 常量_整数:
    分支 常量_无符整数:
    分支 常量_长整数:
    分支 常量_无符长整数:
    分支 常量_长长整数:
    分支 常量_无符长长整数:
        /* XXX: 不太精确,但仅对测试有用  */
#如果已定义 _WIN32
        sprintf(p, "%u", (无符号)cv->i);
#否则
        sprintf(p, "%llu", (无符号 long long)cv->i);
#结束如果
        跳出;
    分支 常量_长字符型:
        动态字符串_追加单个字符(&动态字符串_缓冲, 'L');
    分支 常量_字符型:
        动态字符串_追加单个字符(&动态字符串_缓冲, '\'');
        添加_字符(&动态字符串_缓冲, cv->i);
        动态字符串_追加单个字符(&动态字符串_缓冲, '\'');
        动态字符串_追加单个字符(&动态字符串_缓冲, '\0');
        跳出;
    分支 常量_预处理编号:
    分支 常量_预处理字符串:
        返回 (字符型*)cv->str.data;
    分支 常量_长字符串:
        动态字符串_追加单个字符(&动态字符串_缓冲, 'L');
    分支 常量_字符串:
        动态字符串_追加单个字符(&动态字符串_缓冲, '\"');
        如果 (v == 常量_字符串) {
            len = cv->str.size - 1;
            循环(i=0;i<len;i++)
                添加_字符(&动态字符串_缓冲, ((无符号 字符型 *)cv->str.data)[i]);
        } 否则 {
            len = (cv->str.size / 取大小(nwchar_t)) - 1;
            循环(i=0;i<len;i++)
                添加_字符(&动态字符串_缓冲, ((nwchar_t *)cv->str.data)[i]);
        }
        动态字符串_追加单个字符(&动态字符串_缓冲, '\"');
        动态字符串_追加单个字符(&动态字符串_缓冲, '\0');
        跳出;

    分支 常量_浮点型:
        动态字符串_cat(&动态字符串_缓冲, "<float>", 0);
        跳出;
    分支 常量_双精度:
	动态字符串_cat(&动态字符串_缓冲, "<double>", 0);
	跳出;
    分支 常量_长双精度:
	动态字符串_cat(&动态字符串_缓冲, "<long double>", 0);
	跳出;
    分支 常量_行号:
	动态字符串_cat(&动态字符串_缓冲, "<linenumber>", 0);
	跳出;

    /* 上面的标识符具有价值,下面的标识符没有价值 */
    分支 符_LT:
        v = '<';
        去向 addv;
    分支 符_GT:
        v = '>';
        去向 addv;
    分支 符_三个圆点:
        返回 strcpy(p, "...");
    分支 符_A_SHL:
        返回 strcpy(p, "<<=");
    分支 符_A_SAR:
        返回 strcpy(p, ">>=");
    分支 符_文件结尾:
        返回 strcpy(p, "<eof>");
    default:
        如果 (v < 符_识别) {
            /* search in two bytes table */
            常量 无符号 字符型 *q = 双字符符号;
            判断 (*q) {
                如果 (q[2] == v) {
                    *p++ = q[0];
                    *p++ = q[1];
                    *p = '\0';
                    返回 动态字符串_缓冲.指向字符串的指针;
                }
                q += 3;
            }
        如果 (v >= 127) {
            sprintf(动态字符串_缓冲.指向字符串的指针, "<%02x>", v);
            返回 动态字符串_缓冲.指向字符串的指针;
        }
        addv:
            *p++ = v;
            *p = '\0';
        } 否则 如果 (v < 单词_识别号) {
            返回 单词表[v - 符_识别]->str;
        } 否则 如果 (v >= 符号_第一个_匿名) {
            /* 匿名符号的特殊名称 */
            sprintf(p, "L.%u", v - 符号_第一个_匿名);
        } 否则 {
            /* 不应该发生 */
            返回 NULL;
        }
        跳出;
    }
    返回 动态字符串_缓冲.指向字符串的指针;
}

/* 返回当前字符,必要时处理块的结尾 */
静态 整数型 处理_块的结尾(无类型)
{
    缓冲文件 *bf = file;
    整数型 len;

    /* 仅在缓冲区真正结束时尝试读取 */
    如果 (bf->buf_ptr >= bf->buf_end) {
        如果 (bf->fd >= 0) {
#如果 已定义(PARSE_DEBUG)
            len = 1;
#否则
            len = 输入输出_缓冲_大小;
#结束如果
            len = read(bf->fd, bf->buffer, len);
            如果 (len < 0)
                len = 0;
        } 否则 {
            len = 0;
        }
        总_字节数 += len;
        bf->buf_ptr = bf->buffer;
        bf->buf_end = bf->buffer + len;
        *bf->buf_end = CH_缓冲区结尾;
    }
    如果 (bf->buf_ptr < bf->buf_end) {
        返回 bf->buf_ptr[0];
    } 否则 {
        bf->buf_ptr = bf->buf_end;
        返回 CH_文件结尾;
    }
}

静态 内联 无类型 读下个符号处理缓冲区结尾(无类型)
{
    当前取到的源码字符 = *(++(file->buf_ptr));
    /* 缓冲区/文件处理结束 */
    如果 (当前取到的源码字符 == CH_缓冲区结尾)
        当前取到的源码字符 = 处理_块的结尾();
}

/* 处理 '\[\r]\n' */
静态 整数型 处理_转义_无错误(无类型)
{
    判断 (当前取到的源码字符 == '\\') {
        读下个符号处理缓冲区结尾();
        如果 (当前取到的源码字符 == '\n') {
            file->line_num++;
            读下个符号处理缓冲区结尾();
        } 否则 如果 (当前取到的源码字符 == '\r') {
            读下个符号处理缓冲区结尾();
            如果 (当前取到的源码字符 != '\n')
                去向 fail;
            file->line_num++;
            读下个符号处理缓冲区结尾();
        } 否则 {
        fail:
            返回 1;
        }
    }
    返回 0;
}
/**/
静态 无类型 处理_转义(无类型)
{
    如果 (处理_转义_无错误())
        错误_打印("程序中转义 '\\' ");
}

/* 跳过转义符,处理\\ n。 如果输出错误
    转义后不正确的字符 */
静态 整数型 处理_转义1(uint8_t *p)
{
    整数型 c;

    file->buf_ptr = p;
    如果 (p >= file->buf_end) {
        c = 处理_块的结尾();
        如果 (c != '\\')
            返回 c;
        p = file->buf_ptr;
    }
    当前取到的源码字符 = *p;
    如果 (处理_转义_无错误()) {
        如果 (!(解析_标记 & 解析_标记_接受_转义))
            错误_打印("程序中转义 '\\' ");
        *--file->buf_ptr = '\\';
    }
    p = file->buf_ptr;
    c = *p;
    返回 c;
}

/* 仅处理EOB情况,但不能处理转义 */
#定义 仅处理模块结尾_不处理转义(c, p)\
{\
    p++;\
    c = *p;\
    如果 (c == '\\') {\
        file->buf_ptr = p;\
        c = 处理_块的结尾();\
        p = file->buf_ptr;\
    }\
}

/* 处理复杂的转义情况*/
#定义 复杂转义(c, p)\
{\
    p++;\
    c = *p;\
    如果 (c == '\\') {\
        c = 处理_转义1(p);\
        p = file->buf_ptr;\
    }\
}

/* 输入以'\ [\ r] \ n'处理。 请注意,此函数无法处理'\'之后的其他字符,因此您不能在字符串或注释中调用它 */
静态 无类型 仅处理第一个斜杠(无类型)
{
    读下个符号处理缓冲区结尾();
    如果 (当前取到的源码字符 == '\\') 
        处理_转义();
}

/* 单行C ++注释 */
静态 uint8_t *解析_单行_注释(uint8_t *p)
{
    整数型 c;

    p++;
    循环(;;) {
        c = *p;
    redo:
        如果 (c == '\n' || c == CH_文件结尾) {
            跳出;
        } 否则 如果 (c == '\\') {
            file->buf_ptr = p;
            c = 处理_块的结尾();
            p = file->buf_ptr;
            如果 (c == '\\') {
                仅处理模块结尾_不处理转义(c, p);
                如果 (c == '\n') {
                    file->line_num++;
                    仅处理模块结尾_不处理转义(c, p);
                } 否则 如果 (c == '\r') {
                    仅处理模块结尾_不处理转义(c, p);
                    如果 (c == '\n') {
                        file->line_num++;
                        仅处理模块结尾_不处理转义(c, p);
                    }
                }
            } 否则 {
                去向 redo;
            }
        } 否则 {
            p++;
        }
    }
    返回 p;
}

/* C 注释(解释,注释) */
静态 uint8_t *解析_注释(uint8_t *p)
{
    整数型 c;

    p++;
    循环(;;) {
        /* 快速跳过循环 */
        循环(;;) {
            c = *p;
            如果 (c == '\n' || c == '*' || c == '\\')
                跳出;
            p++;
            c = *p;
            如果 (c == '\n' || c == '*' || c == '\\')
                跳出;
            p++;
        }
        /* 现在我们可以处理所有情况 */
        如果 (c == '\n') {
            file->line_num++;
            p++;
        } 否则 如果 (c == '*') {
            p++;
            循环(;;) {
                c = *p;
                如果 (c == '*') {
                    p++;
                } 否则 如果 (c == '/') {
                    去向 end_of_comment;
                } 否则 如果 (c == '\\') {
                    file->buf_ptr = p;
                    c = 处理_块的结尾();
                    p = file->buf_ptr;
                    如果 (c == CH_文件结尾)
                        错误_打印("注释中的文件意外结束");
                    如果 (c == '\\') {
                        /* 跳过 '\[\r]\n', otherwise just 跳过 the stray */
                        判断 (c == '\\') {
                            仅处理模块结尾_不处理转义(c, p);
                            如果 (c == '\n') {
                                file->line_num++;
                                仅处理模块结尾_不处理转义(c, p);
                            } 否则 如果 (c == '\r') {
                                仅处理模块结尾_不处理转义(c, p);
                                如果 (c == '\n') {
                                    file->line_num++;
                                    仅处理模块结尾_不处理转义(c, p);
                                }
                            } 否则 {
                                去向 after_star;
                            }
                        }
                    }
                } 否则 {
                    跳出;
                }
            }
        after_star: ;
        } 否则 {
            /* stray, eob or eof */
            file->buf_ptr = p;
            c = 处理_块的结尾();
            p = file->buf_ptr;
            如果 (c == CH_文件结尾) {
                错误_打印("注释中的文件意外结束");
            } 否则 如果 (c == '\\') {
                p++;
            }
        }
    }
 end_of_comment:
    p++;
    返回 p;
}

静态_函数 整数型 设置_等值数(整数型 c, 整数型 val)
{
    整数型 prev = 等值_表[c - CH_文件结尾];
    等值_表[c - CH_文件结尾] = val;
    返回 prev;
}

#定义 cinp 仅处理第一个斜杠

静态 内联 无类型 跳过_空格(无类型)
{
    判断 (等值_表[当前取到的源码字符 - CH_文件结尾] & IS_SPC)
        cinp();
}

静态 内联 整数型 检查_空格(整数型 t, 整数型 *spc)
{
    如果 (t < 256 && (等值_表[t - CH_文件结尾] & IS_SPC)) {
        如果 (*spc) 
            返回 1;
        *spc = 1;
    } 否则 
        *spc = 0;
    返回 0;
}

静态 uint8_t *解析字符串_不解析转义(uint8_t *p,整数型 sep, 动态字符串 *str)
{
    整数型 c;
    p++;
    循环(;;) {
        c = *p;
        如果 (c == sep) {
            跳出;
        } 否则 如果 (c == '\\') {
            file->buf_ptr = p;
            c = 处理_块的结尾();
            p = file->buf_ptr;
            如果 (c == CH_文件结尾) {
            unterminated_string:
                /* XXX: 指示字符串开头的行号 */
                错误_打印("缺少终止符 %c ", sep);
            } 否则 如果 (c == '\\') {
                /* escape : just 跳过 \[\r]\n */
                仅处理模块结尾_不处理转义(c, p);
                如果 (c == '\n') {
                    file->line_num++;
                    p++;
                } 否则 如果 (c == '\r') {
                    仅处理模块结尾_不处理转义(c, p);
                    如果 (c != '\n')
                        应为("'\n' after '\r'");
                    file->line_num++;
                    p++;
                } 否则 如果 (c == CH_文件结尾) {
                    去向 unterminated_string;
                } 否则 {
                    如果 (str) {
                        动态字符串_追加单个字符(str, '\\');
                        动态字符串_追加单个字符(str, c);
                    }
                    p++;
                }
            }
        } 否则 如果 (c == '\n') {
            file->line_num++;
            去向 添加_字符;
        } 否则 如果 (c == '\r') {
            仅处理模块结尾_不处理转义(c, p);
            如果 (c != '\n') {
                如果 (str)
                    动态字符串_追加单个字符(str, '\r');
            } 否则 {
                file->line_num++;
                去向 添加_字符;
            }
        } 否则 {
        添加_字符:
            如果 (str)
                动态字符串_追加单个字符(str, c);
            p++;
        }
    }
    p++;
    返回 p;
}

/* 跳过预处理。_预处理(预处理)。跳过#否则,#elif或#结束如果。 也跳过
    #如果 /#结束如果 */
静态 无类型 跳过_预处理(无类型)
{
    整数型 a, start_of_line, c, in_warn_or_error;
    uint8_t *p;

    p = file->buf_ptr;
    a = 0;
redo_start:
    start_of_line = 1;
    in_warn_or_error = 0;
    循环(;;) {
    redo_no_start:
        c = *p;
        选择(c) {
        分支 ' ':
        分支 '\t':
        分支 '\f':
        分支 '\v':
        分支 '\r':
            p++;
            去向 redo_no_start;
        分支 '\n':
            file->line_num++;
            p++;
            去向 redo_start;
        分支 '\\':
            file->buf_ptr = p;
            c = 处理_块的结尾();
            如果 (c == CH_文件结尾) {
                应为("#结束如果");
            } 否则 如果 (c == '\\') {
                当前取到的源码字符 = file->buf_ptr[0];
                处理_转义_无错误();
            }
            p = file->buf_ptr;
            去向 redo_no_start;
        /* 跳过字符串 */
        分支 '\"':
        分支 '\'':
            如果 (in_warn_or_error)
                去向 _default;
            p = 解析字符串_不解析转义(p, c, NULL);
            跳出;
        /* 跳过注释 */
        分支 '/':
            如果 (in_warn_or_error)
                去向 _default;
            file->buf_ptr = p;
            当前取到的源码字符 = *p;
            仅处理第一个斜杠();
            p = file->buf_ptr;
            如果 (当前取到的源码字符 == '*') {
                p = 解析_注释(p);
            } 否则 如果 (当前取到的源码字符 == '/') {
                p = 解析_单行_注释(p);
            }
            跳出;
        分支 '#':
            p++;
            如果 (start_of_line) {
                file->buf_ptr = p;
                取_下个符号_不宏扩展();
                p = file->buf_ptr;
                如果 (a == 0 && (单词编码 == 关键字_ELSE || 单词编码 == 关键字_否则 || 单词编码 == 关键字_ELIF || 单词编码 == 关键字_否则如果 || 单词编码 == 关键字_ENDIF || 单词编码 == 关键字_结束如果))
                    去向 the_end;
                如果 (单词编码 == 关键字_IF || 单词编码 == 关键字_如果 || 单词编码 == 关键字_IFDEF || 单词编码 == 关键字_如果已定义 || 单词编码 == 关键字_IFNDEF || 单词编码 == 关键字_如果未定义)
                    a++;
                否则 如果 (单词编码 == 关键字_ENDIF || 单词编码 == 关键字_结束如果)
                    a--;
                否则 如果( 单词编码 == 关键字_ERROR || 单词编码 == 关键字_错误  || 单词编码 == 关键字_WARNING || 单词编码 == 关键字_警告)
                    in_warn_or_error = 1;
                否则 如果 (单词编码 == 符_换行)
                    去向 redo_start;
                否则 如果 (解析_标记 & 解析_标记_汇编_文件)
                    p = 解析_单行_注释(p - 1);
            } 否则 如果 (解析_标记 & 解析_标记_汇编_文件)
                p = 解析_单行_注释(p - 1);
            跳出;
_default:
        default:
            p++;
            跳出;
        }
        start_of_line = 0;
    }
 the_end: ;
    file->buf_ptr = p;
}

#如果 0
/* 返回存储标识符所需的其他“ 整数型”数 。次函数没有被使用*/
静态 内联 整数型 标识符_大小(常量 整数型 *p)
{
    选择(*p) {
        /* 4 字节 */
    分支 常量_整数:
    分支 常量_无符整数:
    分支 常量_字符型:
    分支 常量_长字符型:
    分支 常量_浮点型:
    分支 常量_行号:
        返回 1 + 1;
    分支 常量_字符串:
    分支 常量_长字符串:
    分支 常量_预处理编号:
    分支 常量_预处理字符串:
        返回 1 + ((取大小(动态字符串) + ((动态字符串 *)(p+1))->size + 3) >> 2);
    分支 常量_长整数:
    分支 常量_无符长整数:
	返回 1 + LONG_SIZE / 4;
    分支 常量_双精度:
    分支 常量_长长整数:
    分支 常量_无符长长整数:
        返回 1 + 2;
    分支 常量_长双精度:
        返回 1 + 长双精度_大小 / 4;
    default:
        返回 1 + 0;
    }
}
#结束如果
静态_内联 无类型 单词字符串_处理(单词字符串 *s)
{
    s->str = NULL;
    s->len = s->lastlen = 0;
    s->allocated_len = 0;
    s->最后_行_号 = -1;
}

静态_函数 单词字符串 *单词字符串_分配(无类型)
{
    单词字符串 *str = 小分配器_重新分配(单词字符串_分配内存, 0, 取大小 *str);
    单词字符串_处理(str);
    返回 str;
}

静态_函数 整数型 *单词字符串_复制到新内存地址(单词字符串 *s)
{
    整数型 *str;

    str = 小分配器_重新分配(单词字符串_分配内存, 0, s->len * 取大小(整数型));
    memcpy(str, s->str, s->len * 取大小(整数型));
    返回 str;
}

静态_函数 无类型 单词字符串_释放_字符串(整数型 *str)
{
    小分配器_释放(单词字符串_分配内存, str);
}

静态_函数 无类型 单词字符串_释放(单词字符串 *str)
{
    单词字符串_释放_字符串(str->str);
    小分配器_释放(单词字符串_分配内存, str);
}

静态_函数 整数型 *单词字符串_重分配(单词字符串 *s, 整数型 new_size)
{
    整数型 *str, size;

    size = s->allocated_len;
    如果 (size < 16)
        size = 16;
    判断 (size < new_size)
        size = size * 2;
    如果 (size > s->allocated_len) {
        str = 小分配器_重新分配(单词字符串_分配内存, s->str, size * 取大小(整数型));
        s->allocated_len = size;
        s->str = str;
    }
    返回 s->str;
}

静态_函数 无类型 单词字符串_增加大小(单词字符串 *s, 整数型 t)
{
    整数型 len, *str;

    len = s->len;
    str = s->str;
    如果 (len >= s->allocated_len)
        str = 单词字符串_重分配(s, len + 1);
    str[len++] = t;
    s->len = len;
}

静态_函数 无类型 开始_宏(单词字符串 *str, 整数型 alloc)
{
    str->alloc = alloc;
    str->prev = 宏_堆栈;
    str->prev_ptr = 宏_ptr;
    str->save_line_num = file->line_num;
    宏_ptr = str->str;
    宏_堆栈 = str;
}

静态_函数 无类型 结束_宏(无类型)
{
    单词字符串 *str = 宏_堆栈;
    宏_堆栈 = str->prev;
    宏_ptr = str->prev_ptr;
    file->line_num = str->save_line_num;
    如果 (str->alloc != 0) {
        如果 (str->alloc == 2)
            str->str = NULL; /* 不释放 */
        单词字符串_释放(str);
    }
}

静态 无类型 单词字符串_增加大小2(单词字符串 *s, 整数型 t, 恒定值 *cv)
{
    整数型 len, *str;

    len = s->lastlen = s->len;
    str = s->str;

    /* allocate space 循环 worst 分支 */
    如果 (len + 符_最大_大小 >= s->allocated_len)
        str = 单词字符串_重分配(s, len + 符_最大_大小 + 1);
    str[len++] = t;
    选择(t) {
    分支 常量_整数:
    分支 常量_无符整数:
    分支 常量_字符型:
    分支 常量_长字符型:
    分支 常量_浮点型:
    分支 常量_行号:
#如果 LONG_SIZE == 4
    分支 常量_长整数:
    分支 常量_无符长整数:
#结束如果
        str[len++] = cv->tab[0];
        跳出;
    分支 常量_预处理编号:
    分支 常量_预处理字符串:
    分支 常量_字符串:
    分支 常量_长字符串:
        {
            /* 将字符串插入int数组. */
            size_t 数量_words =
                1 + (cv->str.size + 取大小(整数型) - 1) / 取大小(整数型);
            如果 (len + 数量_words >= s->allocated_len)
                str = 单词字符串_重分配(s, len + 数量_words + 1);
            str[len] = cv->str.size;
            memcpy(&str[len + 1], cv->str.data, cv->str.size);
            len += 数量_words;
        }
        跳出;
    分支 常量_双精度:
    分支 常量_长长整数:
    分支 常量_无符长长整数:
#如果 LONG_SIZE == 8
    分支 常量_长整数:
    分支 常量_无符长整数:
#结束如果
#如果 长双精度_大小 == 8
    分支 常量_长双精度:
#结束如果
        str[len++] = cv->tab[0];
        str[len++] = cv->tab[1];
        跳出;
#如果 长双精度_大小 == 12
    分支 常量_长双精度:
        str[len++] = cv->tab[0];
        str[len++] = cv->tab[1];
        str[len++] = cv->tab[2];
#否则如果 长双精度_大小 == 16
    分支 常量_长双精度:
        str[len++] = cv->tab[0];
        str[len++] = cv->tab[1];
        str[len++] = cv->tab[2];
        str[len++] = cv->tab[3];
#否则如果 长双精度_大小 != 8
#error add long double size support
#结束如果
        跳出;
    default:
        跳出;
    }
    s->len = len;
}

/* 在单词字符串“ *s”中添加当前的解析字符 */
静态_函数 无类型 单词字符串中添加当前解析的字符(单词字符串 *s)
{
    恒定值 cval;

    /* 保存行号信息 */
    如果 (file->line_num != s->最后_行_号) {
        s->最后_行_号 = file->line_num;
        cval.i = s->最后_行_号;
        单词字符串_增加大小2(s, 常量_行号, &cval);
    }
    单词字符串_增加大小2(s, 单词编码, &单词值);
}

/* 从整数数组和增量指针获取标识符. */
静态 内联 无类型 获取_标识符(整数型 *t, 常量 整数型 **pp, 恒定值 *cv)
{
    常量 整数型 *p = *pp;
    整数型 n, *tab;

    tab = cv->tab;
    选择(*t = *p++) {
#如果 LONG_SIZE == 4
    分支 常量_长整数:
#结束如果
    分支 常量_整数:
    分支 常量_字符型:
    分支 常量_长字符型:
    分支 常量_行号:
        cv->i = *p++;
        跳出;
#如果 LONG_SIZE == 4
    分支 常量_无符长整数:
#结束如果
    分支 常量_无符整数:
        cv->i = (无符号)*p++;
        跳出;
    分支 常量_浮点型:
	tab[0] = *p++;
	跳出;
    分支 常量_字符串:
    分支 常量_长字符串:
    分支 常量_预处理编号:
    分支 常量_预处理字符串:
        cv->str.size = *p++;
        cv->str.data = p;
        p += (cv->str.size + 取大小(整数型) - 1) / 取大小(整数型);
        跳出;
    分支 常量_双精度:
    分支 常量_长长整数:
    分支 常量_无符长长整数:
#如果 LONG_SIZE == 8
    分支 常量_长整数:
    分支 常量_无符长整数:
#结束如果
        n = 2;
        去向 copy;
    分支 常量_长双精度:
#如果 长双精度_大小 == 16
        n = 4;
#否则如果 长双精度_大小 == 12
        n = 3;
#否则如果 长双精度_大小 == 8
        n = 2;
#否则
# error add long double size support
#结束如果
    copy:
        执行
            *tab++ = *p++;
        判断 (--n);
        跳出;
    default:
        跳出;
    }
    *pp = p;
}

#如果 0
# 定义 符_GET(t,p,c) 获取_标识符(t,p,c)
#否则
# 定义 符_GET(t,p,c) 执行 { \
    整数型 _t = **(p); \
    如果 (符_有_值(_t)) \
        获取_标识符(t, p, c); \
    否则 \
        *(t) = _t, ++*(p); \
    } 判断 (0)
#结束如果

静态 整数型 宏_等于(常量 整数型 *a, 常量 整数型 *b)
{
    恒定值 cv;
    整数型 t;

    如果 (!a || !b)
        返回 1;

    判断 (*a && *b) {
        /* 第一次预分配macro_equal_buf,下次仅重置位置以开始 */
        动态字符串_重置(&宏_等于_缓冲区);_GET(&t, &a, &cv);
        动态字符串_cat(&宏_等于_缓冲区, 取_单词字符串(t, &cv), 0);_GET(&t, &b, &cv);
        如果 (strcmp(宏_等于_缓冲区.指向字符串的指针, 取_单词字符串(t, &cv)))
            返回 0;
    }
    返回 !(*a || *b);
}

/* 定义处理 */
静态_内联 无类型 宏定义_处理(整数型 v, 整数型 macro_type, 整数型 *str, 符号 *first_arg)
{
    符号 *s, *o;

    o = 宏定义_查找(v);
    s = 符号_推送2(&宏定义符号_堆栈, v, macro_type, 0);
    s->d = str;
    s->next = first_arg;
    单词表[v - 符_识别]->sym_define = s;

    如果 (o && !宏_等于(o->d, s->d))
	zhi_警告("%s 重复定义", 取_单词字符串(v, NULL));
}

/* 没有被定义的定义符号,它的名称仅能设置为零 */
静态_函数 无类型 未宏定义_符号为NULL(符号 *s)
{
    整数型 v = s->v;
    如果 (v >= 符_识别 && v < 单词_识别号)
        单词表[v - 符_识别]->sym_define = NULL;
}

静态_内联 符号 *宏定义_查找(整数型 v)
{
    v -= 符_识别;
    如果 ((无符号)v >= (无符号)(单词_识别号 - 符_识别))
        返回 NULL;
    返回 单词表[v]->sym_define;
}

/* 释放定义堆栈,直到顶部达到“ b” */
静态_函数 无类型 释放_宏定义堆栈(符号 *b)
{
    判断 (宏定义符号_堆栈 != b) {
        符号 *top = 宏定义符号_堆栈;
        宏定义符号_堆栈 = top->prev;
        单词字符串_释放_字符串(top->d);
        未宏定义_符号为NULL(top);
        符号_释放(top);
    }
}

/* 标签查找 */
静态_函数 符号 *标签_查找(整数型 v)
{
    v -= 符_识别;
    如果 ((无符号)v >= (无符号)(单词_识别号 - 符_识别))
        返回 NULL;
    返回 单词表[v]->sym_label;
}

静态_函数 符号 *标签_推送(符号 **ptop, 整数型 v, 整数型 flags)
{
    符号 *s, **ps;
    s = 符号_推送2(ptop, v, 0, 0);
    s->r = flags;
    ps = &单词表[v - 符_识别]->sym_label;
    如果 (ptop == &全局符号_标签_堆栈) {
        /* 修改最上面的本地标识符,以便在弹出时sym_identifier指向“ s” */
        判断 (*ps != NULL)
            ps = &(*ps)->prev_tok;
    }
    s->prev_tok = *ps;
    *ps = s;
    返回 s;
}

/* 弹出标签,直到到达元素的最后一个。 查看是否有未定义的标签。 如果使用'&& label',请定义符号. */
静态_函数 无类型 标签_弹出(符号 **ptop, 符号 *slast, 整数型 keep)
{
    符号 *s, *1;
    循环(s = *ptop; s != slast; s =1) {1 = s->prev;
        如果 (s->r == 标签_被声明) {
            zhi_警告("标签 '%s' 已声明但未使用", 取_单词字符串(s->v, NULL));
        } 否则 如果 (s->r == 标签_正向定义) {
                错误_打印("标签 '%s' 被使用但未定义",
                      取_单词字符串(s->v, NULL));
        } 否则 {
            如果 (s->c) {
                /* 定义相应的符号。 尺寸为1. */
                更新_外部_符号(s, 当前_生成代码_段, s->jnext, 1);
            }
        }
        /* remove label */
        如果 (s->r != 标签_不在范围)
            单词表[s->v - 符_识别]->sym_label = s->prev_tok;
        如果 (!keep)
            符号_释放(s);
        否则
            s->r = 标签_不在范围;
    }
    如果 (!keep)
        *ptop = slast;
}

/* 为zhi -dt -run伪造第n个“ #ifdefined test _...” */
静态 无类型 可能_运行_测试(知心状态机 *s)
{
    常量 字符型 *p;
    如果 (s->包含_堆_ptr != s->包含_堆)
        返回;
    p = 取_单词字符串(单词编码, NULL);
    如果 (0 != memcmp(p, "test_", 5))
        返回;
    如果 (0 != --s->运行_测试)
        返回;
    fprintf(s->预处理输出文件, "\n[%s]\n" + !(s->DX标号 & 32), p), fflush(s->预处理输出文件);
    宏定义_处理(单词编码, 宏_对象, NULL, NULL);
}

/* 评估#如果 /#elif的表达式 */
静态 整数型 预处理_表达式(无类型)
{
    整数型 c, t;
    单词字符串 *str;
    
    str = 单词字符串_分配();
    词法分析_表达式 = 1;
    判断 (单词编码 != 符_换行 && 单词编码 != 符_文件结尾) {
        带有宏替换的下个标记(); /* 做宏替换 */
      redo:
        如果 (单词编码 == 关键字_DEFINED || 单词编码 == 关键字_已定义) {
            取_下个符号_不宏扩展();
            t = 单词编码;
            如果 (t == '(') 
                取_下个符号_不宏扩展();
            如果 (单词编码 < 符_识别)
                应为("identifier");
            如果 (zhi_状态->运行_测试)
                可能_运行_测试(zhi_状态);
            c = 宏定义_查找(单词编码) != 0;
            如果 (t == '(') {
                取_下个符号_不宏扩展();
                如果 (单词编码 != ')')
                    应为("')'");
            }
            单词编码 = 常量_整数;
            单词值.i = c;
        } 否则 如果 (1 && 单词编码 == 符___HAS_INCLUDE) {
            带有宏替换的下个标记();  /* XXX 检查是否正确使用扩展 */
            跳过('(');
            判断 (单词编码 != ')' && 单词编码 != 符_文件结尾)
              带有宏替换的下个标记();
            如果 (单词编码 != ')')
              应为("')'");
            单词编码 = 常量_整数;
            单词值.i = 0;
        } 否则 如果 (单词编码 >= 符_识别) {
            /* 如果未定义宏,则替换为零,检查类似func的宏 */
            t = 单词编码;
            单词编码 = 常量_整数;
            单词值.i = 0;
            单词字符串中添加当前解析的字符(str);
            带有宏替换的下个标记();
            如果 (单词编码 == '(')
                错误_打印("未定义类似函数的宏 '%s' ",
                          取_单词字符串(t, NULL));
            去向 redo;
        }
        单词字符串中添加当前解析的字符(str);
    }
    词法分析_表达式 = 0;
    单词字符串_增加大小(str, -1); /* 模拟文件结尾 */
    单词字符串_增加大小(str, 0);
    /* 现在评估C常数表达式 */
    开始_宏(str, 1);
    带有宏替换的下个标记();
    c = 表达式_常量();
    结束_宏();
    返回 c != 0;
}


/* #define之后解析 */
静态_函数 无类型 解析_宏定义(无类型)
{
    符号 *s, *first, **ps;
    整数型 v, t, varg, is_vaargs, spc;
    整数型 saved_解析_标记 = 解析_标记;

    v = 单词编码;
    如果 (v < 符_识别 || v == 关键字_DEFINED || v == 关键字_已定义)
        错误_打印("无效的宏名称 '%s'", 取_单词字符串(单词编码, &单词值));
    /* XXX: 应该检查是否有相同的宏(ANSI) */
    first = NULL;
    t = 宏_对象;
    /* 我们必须解析整个定义,好像不是在asm模式下一样,尤其是必须忽略带有'#'的行注释。 同样对于函数宏,参数列表也必须不带“。”进行分析。 作为ID字符.  */
    解析_标记 = ((解析_标记 & ~解析_标记_汇编_文件) | 解析_标记_空间);
    /* '(' 必须紧随MACRO_FUNC的宏定义之后 */
    取_下个符号_不宏扩展();
    解析_标记 &= ~解析_标记_空间;
    如果 (单词编码 == '(') {
        整数型 dotid = 设置_等值数('.', 0);
        取_下个符号_不宏扩展();
        ps = &first;
        如果 (单词编码 != ')') 循环 (;;) {
            varg = 单词编码;
            取_下个符号_不宏扩展();
            is_vaargs = 0;
            如果 (varg == 符_三个圆点) {
                varg = 符___VA_ARGS__;
                is_vaargs = 1;
            } 否则 如果 (单词编码 == 符_三个圆点 && gnu_扩展) {
                is_vaargs = 1;
                取_下个符号_不宏扩展();
            }
            如果 (varg < 符_识别)
        bad_list:
                错误_打印("错误的宏参数列表");
            s = 符号_推送2(&宏定义符号_堆栈, varg | 符号_字段, is_vaargs, 0);
            *ps = s;
            ps = &s->next;
            如果 (单词编码 == ')')
                跳出;
            如果 (单词编码 != ',' || is_vaargs)
                去向 bad_list;
            取_下个符号_不宏扩展();
        }
        解析_标记 |= 解析_标记_空间;
        取_下个符号_不宏扩展();
        t = 宏_函数;
        设置_等值数('.', dotid);
    }

    单词字符串_缓冲.len = 0;
    spc = 2;
    解析_标记 |= 解析_标记_接受_转义 | 解析_标记_空间 | 解析_标记_换行符;
    /* 应该对宏定义的主体进行解析,以便像文件模式确定的那样解析标识符(即在asm模式下以'。'为ID字符)。 但是应保留“#”而不是将其视为行注释的引号,因此仍不要在解析_标记中设置ASM_FILE。 */
    判断 (单词编码 != 符_换行 && 单词编码 != 符_文件结尾) {
        /* 删除##周围和'#'之后的空格 */
        如果 (双符号_2个井号 == 单词编码) {
            如果 (2 == spc)
                去向 bad_twosharp;
            如果 (1 == spc)
                --单词字符串_缓冲.len;
            spc = 3;
	    单词编码 = 符_PPJOIN;
        } 否则 如果 ('#' == 单词编码) {
            spc = 4;
        } 否则 如果 (检查_空格(单词编码, &spc)) {
            去向 跳过;
        }
        单词字符串_增加大小2(&单词字符串_缓冲, 单词编码, &单词值);
    跳过:
        取_下个符号_不宏扩展();
    }

    解析_标记 = saved_解析_标记;
    如果 (spc == 1)
        --单词字符串_缓冲.len; /* 删除尾随空间 */
    单词字符串_增加大小(&单词字符串_缓冲, 0);
    如果 (3 == spc)
bad_twosharp:
        错误_打印("'##' 不能出现在宏的任何一端");
    宏定义_处理(v, t, 单词字符串_复制到新内存地址(&单词字符串_缓冲), first);
}

静态 导入文件缓存 *查找_缓存的_导入文件(知心状态机 *状态机1, 常量 字符型 *文件名, 整数型 add)
{
    常量 无符号 字符型 *s;
    无符号 整数型 h;
    导入文件缓存 *e;
    整数型 i;

    h = 符_哈希_初始化;
    s = (无符号 字符型 *) 文件名;
    判断 (*s) {
#如果已定义 _WIN32
        h = 符_哈希_函数(h, toup(*s));
#否则
        h = 符_哈希_函数(h, *s);
#结束如果
        s++;
    }
    h &= (缓存的_导入文件_哈希_大小 - 1);

    i = 状态机1->缓存_包含数_哈希[h];
    循环(;;) {
        如果 (i == 0)
            跳出;
        e = 状态机1->缓存_包含数[i - 1];
        如果 (0 == PATHCMP(e->文件名, 文件名))
            返回 e;
        i = e->hash_next;
    }
    如果 (!add)
        返回 NULL;

    e = 内存_申请(取大小(导入文件缓存) + strlen(文件名));
    strcpy(e->文件名, 文件名);
    e->ifndef_macro = e->once = 0;
    动态数组_追加元素(&状态机1->缓存_包含数, &状态机1->数量_缓存_包含数, e);
    /* 在哈希表中添加 */
    e->hash_next = 状态机1->缓存_包含数_哈希[h];
    状态机1->缓存_包含数_哈希[h] = 状态机1->数量_缓存_包含数;
#如果已定义 导入文件_调试
    printf("添加缓存的 '%s'\n", 文件名);
#结束如果
    返回 e;
}

静态 无类型 语用_解析(知心状态机 *1)
{
    取_下个符号_不宏扩展();
    如果 (单词编码 == 符_push_macro || 单词编码 == 符_pop_macro) {
        整数型 t = 单词编码, v;
        符号 *s;

        如果 (带有宏替换的下个标记(), 单词编码 != '(')
            去向 pragma_err;
        如果 (带有宏替换的下个标记(), 单词编码 != 常量_字符串)
            去向 pragma_err;
        v = 单词表_查找(单词值.str.data, 单词值.str.size - 1)->单词编码;
        如果 (带有宏替换的下个标记(), 单词编码 != ')')
            去向 pragma_err;
        如果 (t == 符_push_macro) {
            判断 (NULL == (s = 宏定义_查找(v)))
                宏定义_处理(v, 0, NULL, NULL);
            s->type.ref = s; /* 设置推送边界 */
        } 否则 {
            循环 (s = 宏定义符号_堆栈; s; s = s->prev)
                如果 (s->v == v && s->type.ref == s) {
                    s->type.ref = NULL;
                    跳出;
                }
        }
        如果 (s)
            单词表[v - 符_识别]->sym_define = s->d ? s : NULL;
        否则
            zhi_警告("不平衡的 #pragma pop_macro");
        词法分析_调试_标识符 = t, 词法分析_调试_字符值 = v;

    } 否则 如果 (单词编码 == 符_once) {
        查找_缓存的_导入文件(1, file->文件名, 1)->once = 词法分析_第一次;

    } 否则 如果 (1->输出_类型 == ZHI_输出_预处理) {
        /* zhi -E:保持语用表保持不变 */
        设为_指定标识符(' ');
        设为_指定标识符(关键字_PRAGMA);
        设为_指定标识符('#');
        设为_指定标识符(符_换行);

    } 否则 如果 (单词编码 == 符_pack) {
        带有宏替换的下个标记();
        跳过('(');
        如果 (单词编码 == 符_汇编_pop) {
            带有宏替换的下个标记();
            如果 (1->包_堆_ptr <=1->包_堆) {
            stk_error:
                错误_打印("超出了堆包");
            }1->包_堆_ptr--;
        } 否则 {
            整数型 val = 0;
            如果 (单词编码 != ')') {
                如果 (单词编码 == 符_汇编_push) {
                    带有宏替换的下个标记();
                    如果 (1->包_堆_ptr >=1->包_堆 + 包_堆栈_大小 - 1)
                        去向 stk_error;1->包_堆_ptr++;
                    跳过(',');
                }
                如果 (单词编码 != 常量_整数)
                    去向 pragma_err;
                val = 单词值.i;
                如果 (val < 1 || val > 16 || (val & (val - 1)) != 0)
                    去向 pragma_err;
                带有宏替换的下个标记();
            }
            *1->包_堆_ptr = val;
        }
        如果 (单词编码 != ')')
            去向 pragma_err;

    } 否则 如果 (单词编码 == 符_comment) {
        字符型 *p; 整数型 t;
        带有宏替换的下个标记();
        跳过('(');
        t = 单词编码;
        带有宏替换的下个标记();
        跳过(',');
        如果 (单词编码 != 常量_字符串)
            去向 pragma_err;
        p = 字符串_宽度加1((字符型 *)单词值.str.data);
        带有宏替换的下个标记();
        如果 (单词编码 != ')')
            去向 pragma_err;
        如果 (t == 符_lib) {
            动态数组_追加元素(&1->语法_库数, &1->数量_语法_库数, p);
        } 否则 {
            如果 (t == 符_option)
                设置编译选项(1, p);
            内存_释放(p);
        }

    } 否则 如果 (1->警告_不支持) {
        zhi_警告("#pragma %s 被忽略", 取_单词字符串(单词编码, &单词值));
    }
    返回;

pragma_err:
    错误_打印(" #pragma 指令格式错误");
    返回;
}

/* 如果文件开头的第一个非空间标识符,则is_bof为true */
静态_函数 无类型 _预处理(整数型 is_bof)
{
    知心状态机 *1 = zhi_状态;
    整数型 i, c, n, saved_解析_标记;
    字符型 buf[1024], *q;
    符号 *s;

    saved_解析_标记 = 解析_标记;
    解析_标记 = 解析_标记_预处理| 解析_标记_标识符_数字| 解析_标记_单词字符串| 解析_标记_换行符| (解析_标记 & 解析_标记_汇编_文件);

    取_下个符号_不宏扩展();
 redo:
    选择(单词编码) {
    分支 关键字_DEFINE:
    分支 关键字_定义:
        词法分析_调试_标识符 = 单词编码;
        取_下个符号_不宏扩展();
        词法分析_调试_字符值 = 单词编码;
        解析_宏定义();
        跳出;
    分支 关键字_UNDEF:
    分支 关键字_取消定义:
        词法分析_调试_标识符 = 单词编码;
        取_下个符号_不宏扩展();
        词法分析_调试_字符值 = 单词编码;
        s = 宏定义_查找(单词编码);
        /* 通过输入无效名称来定义符号 */
        如果 (s)
            未宏定义_符号为NULL(s);
        跳出;
    分支 关键字_INCLUDE:
    分支 关键字_导入:
    分支 关键字_INCLUDE_NEXT:
    分支 关键字_导入_下个:
        当前取到的源码字符 = file->buf_ptr[0];
        /* XXX: 如果注释不正确:以特殊模式使用next_nomacro */
        跳过_空格();
        如果 (当前取到的源码字符 == '<') {
            c = '>';
            去向 read_name;
        } 否则 如果 (当前取到的源码字符 == '\"') {
            c = 当前取到的源码字符;
        read_name:
            读下个符号处理缓冲区结尾();
            q = buf;
            判断 (当前取到的源码字符 != c && 当前取到的源码字符 != '\n' && 当前取到的源码字符 != CH_文件结尾) {
                如果 ((q - buf) < 取大小(buf) - 1)
                    *q++ = 当前取到的源码字符;
                如果 (当前取到的源码字符 == '\\') {
                    如果 (处理_转义_无错误() == 0)
                        --q;
                } 否则
                    读下个符号处理缓冲区结尾();
            }
            *q = '\0';
            仅处理第一个斜杠();
#如果 0
            /* 吃掉所有空格并在包含之后发表评论 */
            /* XXX: 稍微不正确 */
            判断 (ch1 != '\n' && ch1 != CH_文件结尾)
                读下个符号处理缓冲区结尾();
#结束如果
        } 否则 {
	    整数型 len;
            /* 计算出的#导入:将所有内容连接到换行符,结果必须是两种可接受的形式之一。请勿在此处将pp标识符转换为标识符。  */
	    解析_标记 = (解析_标记_预处理
			   | 解析_标记_换行符
			   | (解析_标记 & 解析_标记_汇编_文件));
            带有宏替换的下个标记();
            buf[0] = '\0';
	    判断 (单词编码 != 符_换行) {
		连接_字符串(buf, 取大小(buf), 取_单词字符串(单词编码, &单词值));
		带有宏替换的下个标记();
	    }
	    len = strlen(buf);
	    /* 检查语法并删除'<> |“”'*/
	    如果 ((len < 2 || ((buf[0] != '"' || buf[len-1] != '"') &&
			     (buf[0] != '<' || buf[len-1] != '>'))))
	        错误_打印("'#导入' 之后应该有 \"FILENAME\" 或 <FILENAME>");
	    c = buf[len-1];
	    memmove(buf, buf + 1, len - 2);
	    buf[len - 2] = '\0';
        }

        如果 (1->包含_堆_ptr >=1->包含_堆 + 包含_堆栈_大小)
            错误_打印("#include递归太深");
        /* 将当前文件推送到堆栈 */
        *1->包含_堆_ptr++ = file;
        i = (单词编码 == 关键字_INCLUDE_NEXT || 单词编码 == 关键字_导入_下个) ? file->include_next_index + 1 : 0;
        n = 2 +1->数量_包含_路径 +1->数量_系统包含_路径;
        循环 (; i < n; ++i) {
            字符型 buf1[取大小 file->文件名];
            导入文件缓存 *e;
            常量 字符型 *path;

            如果 (i == 0) {
                /* 检查绝对包含路径 */
                如果 (!IS_ABSPATH(buf))
                    继续;
                buf1[0] = 0;

            } 否则 如果 (i == 1) {
                /* 在文件的目录中搜索“ header.h” */
                如果 (c != '\"')
                    继续;
                /* https://savannah.nongnu.org/bugs/index.php?50847
                 * #line指令损坏了#include搜索路径
                 *  */
                path = file->true_filename;
                复制_字符串(buf1, path, 取_文件基本名(path) - path);

            } 否则 {
                /* 搜索所有包含路径 */
                整数型 j = i - 2, k = j -1->数量_包含_路径;
                path = k < 0 ?1->包含_路径[j] :1->系统包含_路径[k];
                p字符串复制(buf1, 取大小(buf1), path);
                连接_字符串(buf1, 取大小(buf1), "/");
            }

            连接_字符串(buf1, 取大小(buf1), buf);
            e = 查找_缓存的_导入文件(1, buf1, 0);
            如果 (e && (宏定义_查找(e->ifndef_macro) || e->once == 词法分析_第一次)) {
                /* 无需解析包含,因为已定义了“ ifndef宏”(或具有一次#pragma) */
#如果已定义 导入文件_调试
                printf("%s: 跳过缓存的 %s\n", file->文件名, buf1);
#结束如果
                去向 include_done;
            }

            如果 (打开一个新文件(1, buf1) < 0)
                继续;

            file->include_next_index = i;
#如果已定义 导入文件_调试
            printf("%s: 包含 %s\n", file->prev->文件名, file->文件名);
#结束如果
            /* 更新目标部门 */
            如果 (1->生成_依赖) {
                缓冲文件 *bf = file;
                判断 (i == 1 && (bf = bf->prev))
                    i = bf->include_next_index;
                /* 跳过系统导入文件 */
                如果 (n - i >1->数量_系统包含_路径)
                    动态数组_追加元素(&1->目标_依赖, &1->数量_目标_依赖,
                        字符串_宽度加1(buf1));
            }
            /* 添加导入文件调试信息 */
            zhi_调试_导入文件的开头(zhi_状态);
            标识符_标记 |= 符_标记_文件开始前 | 符_标记_行开始前;
            当前取到的源码字符 = file->buf_ptr[0];
            去向 the_end;
        }
        错误_打印("找不到导入文件 '%s' ", buf);
include_done:
        --1->包含_堆_ptr;
        跳出;
    分支 关键字_IFNDEF:
    分支 关键字_如果未定义:
        c = 1;
        去向 do_ifdef;
    分支 关键字_IF:
    分支 关键字_如果:
        c = 预处理_表达式();
        去向 do_if;
    分支 关键字_IFDEF:
    分支 关键字_如果已定义:
        c = 0;
    do_ifdef:
        取_下个符号_不宏扩展();
        如果 (单词编码 < 符_识别)
            错误_打印(" '#如果%sdef' 的无效参数", c ? "n" : "");
        如果 (is_bof) {
            如果 (c) {
#如果已定义 导入文件_调试
                printf("#如果未定义 %s\n", 取_单词字符串(单词编码, NULL));
#结束如果
                file->ifndef_macro = 单词编码;
            }
        }
        c = (宏定义_查找(单词编码) != 0) ^ c;
    do_if:
        如果 (1->如果已宏定义_堆_ptr >=1->如果已宏定义_堆 + 如果定义_堆栈_大小)
            错误_打印("内存已满(如果已定义)");
        *1->如果已宏定义_堆_ptr++ = c;
        去向 test_skip;
    分支 关键字_ELSE:
    分支 关键字_否则:
        如果 (1->如果已宏定义_堆_ptr ==1->如果已宏定义_堆)
            错误_打印("#else不匹配#如果");
        如果 (1->如果已宏定义_堆_ptr[-1] & 2)
            错误_打印("#else之后#否则");
        c = (1->如果已宏定义_堆_ptr[-1] ^= 3);
        去向 test_else;
    分支 关键字_ELIF:
    分支 关键字_否则如果:
        如果 (1->如果已宏定义_堆_ptr ==1->如果已宏定义_堆)
            错误_打印("#elif没有匹配的#如果");
        c =1->如果已宏定义_堆_ptr[-1];
        如果 (c > 1)
            错误_打印("#else之后#否则如果");
        /* 最后的#如果 /#elif表达式为true:我们跳过 */
        如果 (c == 1) {
            c = 0;
        } 否则 {
            c = 预处理_表达式();1->如果已宏定义_堆_ptr[-1] = c;
        }
    test_else:
        如果 (1->如果已宏定义_堆_ptr == file->如果已宏定义_堆_ptr + 1)
            file->ifndef_macro = 0;
    test_skip:
        如果 (!(c & 1)) {
            跳过_预处理();
            is_bof = 0;
            去向 redo;
        }
        跳出;
    分支 关键字_ENDIF:
    分支 关键字_结束如果:
        如果 (1->如果已宏定义_堆_ptr <= file->如果已宏定义_堆_ptr)
            错误_打印("#endif没有匹配的#如果");1->如果已宏定义_堆_ptr--;
        /* “ #ifndef宏”位于文件的开头。 现在,我们检查“ #结束如果”是否恰好在文件末尾 */
        如果 (file->ifndef_macro &&1->如果已宏定义_堆_ptr == file->如果已宏定义_堆_ptr) {
            file->ifndef_macro_saved = file->ifndef_macro;
            /* 如果文件中间还有另一个#如果未定义,则需要将其设置为零以避免错误的匹配 */
            file->ifndef_macro = 0;
            判断 (单词编码 != 符_换行)
                取_下个符号_不宏扩展();
            标识符_标记 |= 符_标记_结束如果;
            去向 the_end;
        }
        跳出;
    分支 常量_预处理编号:
        n = strtoul((字符型*)单词值.str.data, &q, 10);
        去向 _line_num;
    分支 关键字_LINE:
    分支 关键字_行号:
        带有宏替换的下个标记();
        如果 (单词编码 != 常量_整数)
    _line_err:
            错误_打印("错误的#line格式");
        n = 单词值.i;
    _line_num:
        带有宏替换的下个标记();
        如果 (单词编码 != 符_换行) {
            如果 (单词编码 == 常量_字符串) {
                如果 (file->true_filename == file->文件名)
                    file->true_filename = 字符串_宽度加1(file->文件名);
                /* 从真实文件添加目录 */
                p字符串复制(buf, 取大小 buf, file->true_filename);
                *取_文件基本名(buf) = 0;
                连接_字符串(buf, 取大小 buf, (字符型 *)单词值.str.data);
                zhi_调试_备用文件(1, buf);
            } 否则 如果 (解析_标记 & 解析_标记_汇编_文件)
                跳出;
            否则
                去向 _line_err;
            --n;
        }
        如果 (file->fd > 0)
            总_行数 += file->line_num - n;
        file->line_num = n;
        跳出;
    分支 关键字_ERROR:
    分支 关键字_错误:
    分支 关键字_WARNING:
    分支 关键字_警告:
        c = 单词编码;
        当前取到的源码字符 = file->buf_ptr[0];
        跳过_空格();
        q = buf;
        判断 (当前取到的源码字符 != '\n' && 当前取到的源码字符 != CH_文件结尾) {
            如果 ((q - buf) < 取大小(buf) - 1)
                *q++ = 当前取到的源码字符;
            如果 (当前取到的源码字符 == '\\') {
                如果 (处理_转义_无错误() == 0)
                    --q;
            } 否则
                读下个符号处理缓冲区结尾();
        }
        *q = '\0';
        如果 (c == 关键字_ERROR || c == 关键字_错误)
            错误_打印("#error %s", buf);
        否则
            zhi_警告("#warning %s", buf);
        跳出;
    分支 关键字_PRAGMA:
    分支 关键字_杂注:
        语用_解析(1);
        跳出;
    分支 符_换行:
        去向 the_end;
    default:
        /* 忽略“ S”文件中的天然气行注释。 */
        如果 (saved_解析_标记 & 解析_标记_汇编_文件)
            去向 ignore;
        如果 (单词编码 == '!' && is_bof)
            /*'!' 开始时会被忽略以允许使用C脚本。 */
            去向 ignore;
        zhi_警告("忽略未知的预处理指令 #%s", 取_单词字符串(单词编码, &单词值));
    ignore:
        file->buf_ptr = 解析_单行_注释(file->buf_ptr - 1);
        去向 the_end;
    }
    /* 忽略其他预处理命令或#! 对于C脚本 */
    判断 (单词编码 != 符_换行)
        取_下个符号_不宏扩展();
 the_end:
    解析_标记 = saved_解析_标记;
}

静态 无类型 解析_转义_字符串(动态字符串 *outstr, 常量 uint8_t *buf, 整数型 is_long)
{
    整数型 c, n;
    常量 uint8_t *p;

    p = buf;
    循环(;;) {
        c = *p;
        如果 (c == '\0')
            跳出;
        如果 (c == '\\') {
            p++;
            /* 逃逸 */
            c = *p;
            选择(c) {
            分支 '0': 分支 '1': 分支 '2': 分支 '3':
            分支 '4': 分支 '5': 分支 '6': 分支 '7':
                /* 最多三位八进制数字 */
                n = c - '0';
                p++;
                c = *p;
                如果 (isoct(c)) {
                    n = n * 8 + c - '0';
                    p++;
                    c = *p;
                    如果 (isoct(c)) {
                        n = n * 8 + c - '0';
                        p++;
                    }
                }
                c = n;
                去向 add_char_nonext;
            分支 'x':
            分支 'u':
            分支 'U':
                p++;
                n = 0;
                循环(;;) {
                    c = *p;
                    如果 (c >= 'a' && c <= 'f')
                        c = c - 'a' + 10;
                    否则 如果 (c >= 'A' && c <= 'F')
                        c = c - 'A' + 10;
                    否则 如果 (是数字(c))
                        c = c - '0';
                    否则
                        跳出;
                    n = n * 16 + c;
                    p++;
                }
                c = n;
                去向 add_char_nonext;
            分支 'a':
                c = '\a';
                跳出;
            分支 'b':
                c = '\b';
                跳出;
            分支 'f':
                c = '\f';
                跳出;
            分支 'n':
                c = '\n';
                跳出;
            分支 'r':
                c = '\r';
                跳出;
            分支 't':
                c = '\t';
                跳出;
            分支 'v':
                c = '\v';
                跳出;
            分支 'e':
                如果 (!gnu_扩展)
                    去向 invalid_escape;
                c = 27;
                跳出;
            分支 '\'':
            分支 '\"':
            分支 '\\': 
            分支 '?':
                跳出;
            default:
            invalid_escape:
                如果 (c >= '!' && c <= '~')
                    zhi_警告("未知的转义序列: \'\\%c\'", c);
                否则
                    zhi_警告("未知的转义序列: \'\\x%x\'", c);
                跳出;
            }
        } 否则 如果 (is_long && c >= 0x80) {
            /* 假设我们正在处理UTF-8序列 */
            /* 参考:Unicode标准,版本10.0,ch3.9 */

            整数型 cont; /* 连续字节数 */
            整数型 跳过; /* 发生错误时应跳过多少个字节 */
            整数型 i;

            /* 解码前导字节 */
            如果 (c < 0xC2) {
	            跳过 = 1; 去向 invalid_utf8_sequence;
            } 否则 如果 (c <= 0xDF) {
	            cont = 1; n = c & 0x1f;
            } 否则 如果 (c <= 0xEF) {
	            cont = 2; n = c & 0xf;
            } 否则 如果 (c <= 0xF4) {
	            cont = 3; n = c & 0x7;
            } 否则 {
	            跳过 = 1; 去向 invalid_utf8_sequence;
            }

            /* 解码连续字节 */
            循环 (i = 1; i <= cont; i++) {
                整数型 l = 0x80, h = 0xBF;

                /* 调整第二个字节的限制 */
                如果 (i == 1) {
                    选择 (c) {
                    分支 0xE0: l = 0xA0; 跳出;
                    分支 0xED: h = 0x9F; 跳出;
                    分支 0xF0: l = 0x90; 跳出;
                    分支 0xF4: h = 0x8F; 跳出;
                    }
                }

                如果 (p[i] < l || p[i] > h) {
                    跳过 = i; 去向 invalid_utf8_sequence;
                }

                n = (n << 6) | (p[i] & 0x3f);
            }

            /* 前进指针 */
            p += 1 + cont;
            c = n;
            去向 add_char_nonext;

            /* 错误处理 */
        invalid_utf8_sequence:
            zhi_警告("格式错误的UTF-8子序列,开头为: \'\\x%x\'", c);
            c = 0xFFFD;
            p += 跳过;
            去向 add_char_nonext;

        }
        p++;
    add_char_nonext:
        如果 (!is_long)
            动态字符串_追加单个字符(outstr, c);
        否则 {
#如果已定义 ZHI_TARGET_PE
            /* 存储为UTF-16 */
            如果 (c < 0x10000) {
                动态字符串_追加一个宽字符(outstr, c);
            } 否则 {
                c -= 0x10000;
                动态字符串_追加一个宽字符(outstr, (c >> 10) + 0xD800);
                动态字符串_追加一个宽字符(outstr, (c & 0x3FF) + 0xDC00);
            }
#否则
            动态字符串_追加一个宽字符(outstr, c);
#结束如果
        }
    }
    /* 添加结尾 '\0' */
    如果 (!is_long)
        动态字符串_追加单个字符(outstr, '\0');
    否则
        动态字符串_追加一个宽字符(outstr, '\0');
}

静态 无类型 解析_字符串(常量 字符型 *s, 整数型 len)
{
    uint8_t buf[1000], *p = buf;
    整数型 is_long, sep;

    如果 ((is_long = *s == 'L'))
        ++s, --len;
    sep = *s++;
    len -= 2;
    如果 (len >= 取大小 buf)
        p = 内存_申请(len + 1);
    memcpy(p, s, len);
    p[len] = 0;

    动态字符串_重置(&当前单词字符串);
    解析_转义_字符串(&当前单词字符串, p, is_long);
    如果 (p != buf)
        内存_释放(p);

    如果 (sep == '\'') {
        整数型 char_size, i, n, c;
        /* XXX: 使其便携 */
        如果 (!is_long)
            单词编码 = 常量_字符型, char_size = 1;
        否则
            单词编码 = 常量_长字符型, char_size = 取大小(nwchar_t);
        n = 当前单词字符串.字符串长度 / char_size - 1;
        如果 (n < 1)
            错误_打印("空字符常量");
        如果 (n > 1)
            zhi_警告("多字符常量");
        循环 (c = i = 0; i < n; ++i) {
            如果 (is_long)
                c = ((nwchar_t *)当前单词字符串.指向字符串的指针)[i];
            否则
                c = (c << 8) | ((字符型 *)当前单词字符串.指向字符串的指针)[i];
        }
        单词值.i = c;
    } 否则 {
        单词值.str.size = 当前单词字符串.字符串长度;
        单词值.str.data = 当前单词字符串.指向字符串的指针;
        如果 (!is_long)
            单词编码 = 常量_字符串;
        否则
            单词编码 = 常量_长字符串;
    }
}

/* 我们使用64位数字 */
#定义 BN_SIZE 2
静态 无类型 bn_lshift(无符号 整数型 *bn, 整数型 shift, 整数型 or_val)
{
    整数型 i;
    无符号 整数型 v;
    循环(i=0;i<BN_SIZE;i++)
    {
        v = bn[i];
        bn[i] = (v << shift) | or_val;
        or_val = v >> (32 - shift);
    }
}

静态 无类型 bn_零(无符号 整数型 *bn)
{
    整数型 i;
    循环(i=0;i<BN_SIZE;i++) {
        bn[i] = 0;
    }
}

/* 解析空终止字符串'p'中的数字,并以当前标识符返回 */
静态 无类型 解析_数字(常量 字符型 *p)
{
    整数型 b, t, shift, frac_bits, s, exp_val, 当前取到的源码字符;
    字符型 *q;
    无符号 整数型 bn[BN_SIZE];
    double d;

    /* number */
    q = 标识符_缓冲;
    当前取到的源码字符 = *p++;
    t = 当前取到的源码字符;
    当前取到的源码字符 = *p++;
    *q++ = t;
    b = 10;
    如果 (t == '.') {
        去向 float_frac_parse;
    } 否则 如果 (t == '0') {
        如果 (当前取到的源码字符 == 'x' || 当前取到的源码字符 == 'X') {
            q--;
            当前取到的源码字符 = *p++;
            b = 16;
        } 否则 如果 (zhi_状态->zhi_扩展 && (当前取到的源码字符 == 'b' || 当前取到的源码字符 == 'B')) {
            q--;
            当前取到的源码字符 = *p++;
            b = 2;
        }
    }
    /* 解析所有数字。 由于浮点常量,目前无法检查八进制数 */
    判断 (1) {
        如果 (当前取到的源码字符 >= 'a' && 当前取到的源码字符 <= 'f')
            t = 当前取到的源码字符 - 'a' + 10;
        否则 如果 (当前取到的源码字符 >= 'A' && 当前取到的源码字符 <= 'F')
            t = 当前取到的源码字符 - 'A' + 10;
        否则 如果 (是数字(当前取到的源码字符))
            t = 当前取到的源码字符 - '0';
        否则
            跳出;
        如果 (t >= b)
            跳出;
        如果 (q >= 标识符_缓冲 + 字符串_最大_长度) {
        num_too_long:
            错误_打印("数字太长");
        }
        *q++ = 当前取到的源码字符;
        当前取到的源码字符 = *p++;
    }
    如果 (当前取到的源码字符 == '.' ||
        ((当前取到的源码字符 == 'e' || 当前取到的源码字符 == 'E') && b == 10) ||
        ((当前取到的源码字符 == 'p' || 当前取到的源码字符 == 'P') && (b == 16 || b == 2))) {
        如果 (b != 10) {
            /* 注意:strtox应该支持十六进制数字,但是非ISOC99 libcs不支持它,因此我们更愿意手工完成 */
            /* 十六进制或二进制浮点数 */
            /* XXX: 处理溢出 */
            *q = '\0';
            如果 (b == 16)
                shift = 4;
            否则 
                shift = 1;
            bn_零(bn);
            q = 标识符_缓冲;
            判断 (1) {
                t = *q++;
                如果 (t == '\0') {
                    跳出;
                } 否则 如果 (t >= 'a') {
                    t = t - 'a' + 10;
                } 否则 如果 (t >= 'A') {
                    t = t - 'A' + 10;
                } 否则 {
                    t = t - '0';
                }
                bn_lshift(bn, shift, t);
            }
            frac_bits = 0;
            如果 (当前取到的源码字符 == '.') {
                当前取到的源码字符 = *p++;
                判断 (1) {
                    t = 当前取到的源码字符;
                    如果 (t >= 'a' && t <= 'f') {
                        t = t - 'a' + 10;
                    } 否则 如果 (t >= 'A' && t <= 'F') {
                        t = t - 'A' + 10;
                    } 否则 如果 (t >= '0' && t <= '9') {
                        t = t - '0';
                    } 否则 {
                        跳出;
                    }
                    如果 (t >= b)
                        错误_打印("无效数字");
                    bn_lshift(bn, shift, t);
                    frac_bits += shift;
                    当前取到的源码字符 = *p++;
                }
            }
            如果 (当前取到的源码字符 != 'p' && 当前取到的源码字符 != 'P')
                应为("指数");
            当前取到的源码字符 = *p++;
            s = 1;
            exp_val = 0;
            如果 (当前取到的源码字符 == '+') {
                当前取到的源码字符 = *p++;
            } 否则 如果 (当前取到的源码字符 == '-') {
                s = -1;
                当前取到的源码字符 = *p++;
            }
            如果 (当前取到的源码字符 < '0' || 当前取到的源码字符 > '9')
                应为("指数位数");
            判断 (当前取到的源码字符 >= '0' && 当前取到的源码字符 <= '9') {
                exp_val = exp_val * 10 + 当前取到的源码字符 - '0';
                当前取到的源码字符 = *p++;
            }
            exp_val = exp_val * s;
            
            /* 现在我们可以生成数字 */
            /* XXX: 应直接修补浮点数 */
            d = (double)bn[1] * 4294967296.0 + (double)bn[0];
            d = ldexp(d, exp_val - frac_bits);
            t = toup(当前取到的源码字符);
            如果 (t == 'F') {
                当前取到的源码字符 = *p++;
                单词编码 = 常量_浮点型;
                /* float:应该处理溢出 */
                单词值.f = (float)d;
            } 否则 如果 (t == 'L') {
                当前取到的源码字符 = *p++;
#如果已定义 ZHI_TARGET_PE
                单词编码 = 常量_双精度;
                单词值.d = d;
#否则
                单词编码 = 常量_长双精度;
                /* XXX: 不够大 */
                单词值.ld = (long double)d;
#结束如果
            } 否则 {
                单词编码 = 常量_双精度;
                单词值.d = d;
            }
        } 否则 {
            /* 十进制浮点数 */
            如果 (当前取到的源码字符 == '.') {
                如果 (q >= 标识符_缓冲 + 字符串_最大_长度)
                    去向 num_too_long;
                *q++ = 当前取到的源码字符;
                当前取到的源码字符 = *p++;
            float_frac_parse:
                判断 (当前取到的源码字符 >= '0' && 当前取到的源码字符 <= '9') {
                    如果 (q >= 标识符_缓冲 + 字符串_最大_长度)
                        去向 num_too_long;
                    *q++ = 当前取到的源码字符;
                    当前取到的源码字符 = *p++;
                }
            }
            如果 (当前取到的源码字符 == 'e' || 当前取到的源码字符 == 'E') {
                如果 (q >= 标识符_缓冲 + 字符串_最大_长度)
                    去向 num_too_long;
                *q++ = 当前取到的源码字符;
                当前取到的源码字符 = *p++;
                如果 (当前取到的源码字符 == '-' || 当前取到的源码字符 == '+') {
                    如果 (q >= 标识符_缓冲 + 字符串_最大_长度)
                        去向 num_too_long;
                    *q++ = 当前取到的源码字符;
                    当前取到的源码字符 = *p++;
                }
                如果 (当前取到的源码字符 < '0' || 当前取到的源码字符 > '9')
                    应为("指数位数");
                判断 (当前取到的源码字符 >= '0' && 当前取到的源码字符 <= '9') {
                    如果 (q >= 标识符_缓冲 + 字符串_最大_长度)
                        去向 num_too_long;
                    *q++ = 当前取到的源码字符;
                    当前取到的源码字符 = *p++;
                }
            }
            *q = '\0';
            t = toup(当前取到的源码字符);
            errno = 0;
            如果 (t == 'F') {
                当前取到的源码字符 = *p++;
                单词编码 = 常量_浮点型;
                单词值.f = strtof(标识符_缓冲, NULL);
            } 否则 如果 (t == 'L') {
                当前取到的源码字符 = *p++;
#如果已定义 ZHI_TARGET_PE
                单词编码 = 常量_双精度;
                单词值.d = strtod(标识符_缓冲, NULL);
#否则
                单词编码 = 常量_长双精度;
                单词值.ld = strtold(标识符_缓冲, NULL);
#结束如果
            } 否则 {
                单词编码 = 常量_双精度;
                单词值.d = strtod(标识符_缓冲, NULL);
            }
        }
    } 否则 {
        无符号 long long n, n1;
        整数型 lcount, ucount, ov = 0;
        常量 字符型 *p1;

        /* 整数 */
        *q = '\0';
        q = 标识符_缓冲;
        如果 (b == 10 && *q == '0') {
            b = 8;
            q++;
        }
        n = 0;
        判断(1) {
            t = *q++;
            /* 除基数为10/8的错误外,无需检查 */
            如果 (t == '\0')
                跳出;
            否则 如果 (t >= 'a')
                t = t - 'a' + 10;
            否则 如果 (t >= 'A')
                t = t - 'A' + 10;
            否则
                t = t - '0';
            如果 (t >= b)
                错误_打印("无效数字");
            n1 = n;
            n = n * b + t;
            /* 检测溢出 */
            如果 (n1 >= 0x1000000000000000ULL && n / b != n1)
                ov = 1;
        }

        /* 根据常量后缀确定常量类型必须具有的特征(无符号和/或64位) */
        lcount = ucount = 0;
        p1 = p;
        循环(;;) {
            t = toup(当前取到的源码字符);
            如果 (t == 'L') {
                如果 (lcount >= 2)
                    错误_打印("整数常量中的三个 'l'");
                如果 (lcount && *(p - 1) != 当前取到的源码字符)
                    错误_打印("不正确的整数后缀: %s", p1);
                lcount++;
                当前取到的源码字符 = *p++;
            } 否则 如果 (t == 'U') {
                如果 (ucount >= 1)
                    错误_打印("整数常量中的两个 'u'");
                ucount++;
                当前取到的源码字符 = *p++;
            } 否则 {
                跳出;
            }
        }

        /* 确定是否需要64位和/或无符号才能适合 */
        如果 (ucount == 0 && b == 10) {
            如果 (lcount <= (LONG_SIZE == 4)) {
                如果 (n >= 0x80000000U)
                    lcount = (LONG_SIZE == 4) + 1;
            }
            如果 (n >= 0x8000000000000000ULL)
                ov = 1, ucount = 1;
        } 否则 {
            如果 (lcount <= (LONG_SIZE == 4)) {
                如果 (n >= 0x100000000ULL)
                    lcount = (LONG_SIZE == 4) + 1;
                否则 如果 (n >= 0x80000000U)
                    ucount = 1;
            }
            如果 (n >= 0x8000000000000000ULL)
                ucount = 1;
        }

        如果 (ov)
            zhi_警告("整数常量溢出");

        单词编码 = 常量_整数;
	如果 (lcount) {
            单词编码 = 常量_长整数;
            如果 (lcount == 2)
                单词编码 = 常量_长长整数;
	}
	如果 (ucount)
	    ++单词编码; /* 符_CU... */
        单词值.i = n;
    }
    如果 (当前取到的源码字符)
        错误_打印("无效号码\n");
}


#定义 PARSE2(c1, tok1, c2, tok2)              \
    分支 c1:                                    \
        复杂转义(c, p);                            \
        如果 (c == c2) {                          \
            p++;                                \
            单词编码 = tok2;                         \
        } 否则 {                                \
            单词编码 = tok1;                         \
        }                                       \
        跳出;

/* 返回下一个标识符而不进行宏替换 */
静态 内联 无类型 取_下个符号_不宏扩展1(无类型)
{
    整数型 t, c, is_long, len;
    单词存储结构 *ts;
    uint8_t *p, *p1;
    无符号 整数型 h;

    p = file->buf_ptr;
 redo_no_start:
    c = *p;
    选择(c) {
    分支 ' ':
    分支 '\t':
        单词编码 = c;
        p++;
 maybe_space:
        如果 (解析_标记 & 解析_标记_空间)
            去向 keep_标识符_标记;
        判断 (等值_表[*p - CH_文件结尾] & IS_SPC)
            ++p;
        去向 redo_no_start;
    分支 '\f':
    分支 '\v':
    分支 '\r':
        p++;
        去向 redo_no_start;
    分支 '\\':
        /* 首先查看它是否实际上是缓冲区的结尾 */
        c = 处理_转义1(p);
        p = file->buf_ptr;
        如果 (c == '\\')
            去向 parse_simple;
        如果 (c != CH_文件结尾)
            去向 redo_no_start;
        {
            知心状态机 *状态机1 = zhi_状态;
            如果 ((解析_标记 & 解析_标记_换行符)&& !(标识符_标记 & 符_标记_文件结尾))
            {
                标识符_标记 |= 符_标记_文件结尾;
                单词编码 = 符_换行;
                去向 keep_标识符_标记;
            } 否则 如果 (!(解析_标记 & 解析_标记_预处理))
            {
                单词编码 = 符_文件结尾;
            } 否则 如果 (状态机1->如果已宏定义_堆_ptr != file->如果已宏定义_堆_ptr)
            {
                错误_打印("缺少 #结束如果");
            } 否则 如果 (状态机1->包含_堆_ptr == 状态机1->包含_堆)
            {
                /* 没有包括左:文件末尾. */
                单词编码 = 符_文件结尾;
            } 否则 {
                标识符_标记 &= ~符_标记_文件结尾;
                /* 弹出导入文件 */
                
                /* 在文件开始时测试先前的'#结束如果'是否在#ifdef之后 */
                如果 (标识符_标记 & 符_标记_结束如果)
                {
#如果已定义 导入文件_调试
                    printf("#结束如果 %s\n", 取_单词字符串(file->ifndef_macro_saved, NULL));
#结束如果
                    查找_缓存的_导入文件(状态机1, file->文件名, 1)
                        ->ifndef_macro = file->ifndef_macro_saved;
                    标识符_标记 &= ~符_标记_结束如果;
                }

                /* 添加导入文件调试信息的末尾 */
                zhi_调试_导入文件的结尾(zhi_状态);
                /* 弹出包含堆栈 */
                关闭文件();
                状态机1->包含_堆_ptr--;
                p = file->buf_ptr;
                如果 (p == file->buffer)
                    标识符_标记 = 符_标记_文件开始前|符_标记_行开始前;
                去向 redo_no_start;
            }
        }
        跳出;

    分支 '\n':
        file->line_num++;
        标识符_标记 |= 符_标记_行开始前;
        p++;
maybe_newline:
        如果 (0 == (解析_标记 & 解析_标记_换行符))
            去向 redo_no_start;
        单词编码 = 符_换行;
        去向 keep_标识符_标记;

    分支 '#':
        /* XXX: 简化 */
        复杂转义(c, p);
        如果 ((标识符_标记 & 符_标记_行开始前) && 
            (解析_标记 & 解析_标记_预处理)) {
            file->buf_ptr = p;
            _预处理(标识符_标记 & 符_标记_文件开始前);
            p = file->buf_ptr;
            去向 maybe_newline;
        } 否则 {
            如果 (c == '#') {
                p++;
                单词编码 = 双符号_2个井号;
            } 否则 {
                如果 (解析_标记 & 解析_标记_汇编_文件) {
                    p = 解析_单行_注释(p - 1);
                    去向 redo_no_start;
                } 否则 {
                    单词编码 = '#';
                }
            }
        }
        跳出;
    
    /* 不解析asm时,美元可以开始标识符 */
    分支 '$':
        如果 (!(等值_表[c - CH_文件结尾] & IS_ID)|| (解析_标记 & 解析_标记_汇编_文件))
            去向 parse_simple;
    分支 'a': 分支 'b': 分支 'c': 分支 'd':
    分支 'e': 分支 'f': 分支 'g': 分支 'h':
    分支 'i': 分支 'j': 分支 'k': 分支 'l':
    分支 'm': 分支 'n': 分支 'o': 分支 'p':
    分支 'q': 分支 'r': 分支 's': 分支 't':
    分支 'u': 分支 'v': 分支 'w': 分支 'x':
    分支 'y': 分支 'z': 
    分支 'A': 分支 'B': 分支 'C': 分支 'D':
    分支 'E': 分支 'F': 分支 'G': 分支 'H':
    分支 'I': 分支 'J': 分支 'K': 
    分支 'M': 分支 'N': 分支 'O': 分支 'P':
    分支 'Q': 分支 'R': 分支 'S': 分支 'T':
    分支 'U': 分支 'V': 分支 'W': 分支 'X':
    分支 'Y': 分支 'Z': 
    分支 '_':
    parse_ident_fast:
        p1 = p;
        h = 符_哈希_初始化;
        h = 符_哈希_函数(h, c);
        判断 (c = *++p, 等值_表[c - CH_文件结尾] & (IS_ID|IS_NUM))
            h = 符_哈希_函数(h, c);
        len = p - p1;
        如果 (c != '\\') {
            单词存储结构 **pts;

            /* 快速案例:找不到散落的,所以我们有完整的标识符而且我们已经对其进行了哈希处理 */
            h &= (哈希表容量 - 1);
            pts = &单词_哈希表[h];
            循环(;;) {
                ts = *pts;
                如果 (!ts)
                    跳出;
                如果 (ts->len == len && !memcmp(ts->str, p1, len))
                    去向 标识符_found;
                pts = &(ts->hash_next);
            }
            ts = 标识符_分配新内存(pts, (字符型 *) p1, len);
        标识符_found: ;
        } 否则 {
            /* 较慢的情况 */
            动态字符串_重置(&当前单词字符串);
            动态字符串_cat(&当前单词字符串, (字符型 *) p1, len);
            p--;
            复杂转义(c, p);
        parse_ident_slow:
            判断 (等值_表[c - CH_文件结尾] & (IS_ID|IS_NUM))
            {
                动态字符串_追加单个字符(&当前单词字符串, c);
                复杂转义(c, p);
            }
            ts = 单词表_查找(当前单词字符串.指向字符串的指针, 当前单词字符串.字符串长度);
        }
        单词编码 = ts->单词编码;
        跳出;
    分支 'L':
        t = p[1];
        如果 (t != '\\' && t != '\'' && t != '\"') {
            /* 快的方案 */
            去向 parse_ident_fast;
        } 否则 {
            复杂转义(c, p);
            如果 (c == '\'' || c == '\"') {
                is_long = 1;
                去向 str_const;
            } 否则 {
                动态字符串_重置(&当前单词字符串);
                动态字符串_追加单个字符(&当前单词字符串, 'L');
                去向 parse_ident_slow;
            }
        }
        跳出;

    分支 '0': 分支 '1': 分支 '2': 分支 '3':
    分支 '4': 分支 '5': 分支 '6': 分支 '7':
    分支 '8': 分支 '9':
        t = c;
        复杂转义(c, p);
        /* 在第一个数字之后,接受数字,字母“。”。 或以'eEpP'开头的符号 */
    parse_num:
        动态字符串_重置(&当前单词字符串);
        循环(;;) {
            动态字符串_追加单个字符(&当前单词字符串, t);
            如果 (!((等值_表[c - CH_文件结尾] & (IS_ID|IS_NUM))
                  || c == '.'
                  || ((c == '+' || c == '-')
                      && (((t == 'e' || t == 'E')
                            && !(解析_标记 & 解析_标记_汇编_文件
                                /* 0xe + 1是asm中的3个标识符 */
                                && ((字符型*)当前单词字符串.指向字符串的指针)[0] == '0'
                                && toup(((字符型*)当前单词字符串.指向字符串的指针)[1]) == 'X'))
                          || t == 'p' || t == 'P'))))
                跳出;
            t = c;
            复杂转义(c, p);
        }
        /* 我们添加尾随“ \ 0”以简化解析 */
        动态字符串_追加单个字符(&当前单词字符串, '\0');
        单词值.str.size = 当前单词字符串.字符串长度;
        单词值.str.data = 当前单词字符串.指向字符串的指针;
        单词编码 = 常量_预处理编号;
        跳出;

    分支 '.':
        /* 特殊的点处理,因为它也可以以数字开头 */
        复杂转义(c, p);
        如果 (是数字(c)) {
            t = '.';
            去向 parse_num;
        } 否则 如果 ((等值_表['.' - CH_文件结尾] & IS_ID)
                   && (等值_表[c - CH_文件结尾] & (IS_ID|IS_NUM))) {
            *--p = c = '.';
            去向 parse_ident_fast;
        } 否则 如果 (c == '.') {
            复杂转义(c, p);
            如果 (c == '.') {
                p++;
                单词编码 = 符_三个圆点;
            } 否则 {
                *--p = '.'; /* 可能会下溢到file-> unget []中 */
                单词编码 = '.';
            }
        } 否则 {
            单词编码 = '.';
        }
        跳出;
    分支 '\'':
    分支 '\"':
        is_long = 0;
    str_const:
        动态字符串_重置(&当前单词字符串);
        如果 (is_long)
            动态字符串_追加单个字符(&当前单词字符串, 'L');
        动态字符串_追加单个字符(&当前单词字符串, c);
        p = 解析字符串_不解析转义(p, c, &当前单词字符串);
        动态字符串_追加单个字符(&当前单词字符串, c);
        动态字符串_追加单个字符(&当前单词字符串, '\0');
        单词值.str.size = 当前单词字符串.字符串长度;
        单词值.str.data = 当前单词字符串.指向字符串的指针;
        单词编码 = 常量_预处理字符串;
        跳出;

    分支 '<':
        复杂转义(c, p);
        如果 (c == '=') {
            p++;
            单词编码 = 双符号_小于等于;
        } 否则 如果 (c == '<') {
            复杂转义(c, p);
            如果 (c == '=') {
                p++;
                单词编码 = 符_A_SHL;
            } 否则 {
                单词编码 = 双符号_左位移;
            }
        } 否则 {
            单词编码 = 符_LT;
        }
        跳出;
    分支 '>':
        复杂转义(c, p);
        如果 (c == '=') {
            p++;
            单词编码 = 双符号_大于等于;
        } 否则 如果 (c == '>') {
            复杂转义(c, p);
            如果 (c == '=') {
                p++;
                单词编码 = 符_A_SAR;
            } 否则 {
                单词编码 = 双符号_右位移;
            }
        } 否则 {
            单词编码 = 符_GT;
        }
        跳出;
        
    分支 '&':
        复杂转义(c, p);
        如果 (c == '&') {
            p++;
            单词编码 = 双符号_逻辑与;
        } 否则 如果 (c == '=') {
            p++;
            单词编码 = 双符号_先求位与后赋值;
        } 否则 {
            单词编码 = '&';
        }
        跳出;
        
    分支 '|':
        复杂转义(c, p);
        如果 (c == '|') {
            p++;
            单词编码 = 双符号_逻辑或;
        } 否则 如果 (c == '=') {
            p++;
            单词编码 = 双符号_先求位或后赋值;
        } 否则 {
            单词编码 = '|';
        }
        跳出;

    分支 '+':
        复杂转义(c, p);
        如果 (c == '+') {
            p++;
            单词编码 = 双符号_自加1;
        } 否则 如果 (c == '=') {
            p++;
            单词编码 = 双符号_先求和后赋值;
        } 否则 {
            单词编码 = '+';
        }
        跳出;
        
    分支 '-':
        复杂转义(c, p);
        如果 (c == '-') {
            p++;
            单词编码 = 双符号_自减1;
        } 否则 如果 (c == '=') {
            p++;
            单词编码 = 双符号_先求差后赋值;
        } 否则 如果 (c == '>') {
            p++;
            单词编码 = 双符号_结构体指针运算符;
        } 否则 {
            单词编码 = '-';
        }
        跳出;

    PARSE2('!', '!', '=', 双符号_不等于)
    PARSE2('=', '=', '=', 双符号_等于)
    PARSE2('*', '*', '=', 双符号_先求积后赋值)
    PARSE2('%', '%', '=', 双符号_先取模后赋值)
    PARSE2('^', '^', '=', 双符号_先求异或后赋值)
        
        /* 注释或运算符 */
    分支 '/':
        复杂转义(c, p);
        如果 (c == '*') {
            p = 解析_注释(p);
            /* 注释用空格代替 */
            单词编码 = ' ';
            去向 maybe_space;
        } 否则 如果 (c == '/') {
            p = 解析_单行_注释(p);
            单词编码 = ' ';
            去向 maybe_space;
        } 否则 如果 (c == '=') {
            p++;
            单词编码 = 双符号_先求商后赋值;
        } 否则 {
            单词编码 = '/';
        }
        跳出;
        
        /* 单一标识符 */
    分支 '(':
    分支 ')':
    分支 '[':
    分支 ']':
    分支 '{':
    分支 '}':
    分支 ',':
    分支 ';':
    分支 ':':
    分支 '?':
    分支 '~':
    分支 '@': /* 仅用于汇编程序 */
    parse_simple:
        单词编码 = c;
        p++;
        跳出;
    default:
        如果 (c >= 0x80 && c <= 0xFF) /* utf8 identifiers */
	    去向 parse_ident_fast;
        如果 (解析_标记 & 解析_标记_汇编_文件)
            去向 parse_simple;
        错误_打印("无法识别的角色 \\x%02x", c);
        跳出;
    }
    标识符_标记 = 0;
keep_标识符_标记:
    file->buf_ptr = p;
#如果 已定义(PARSE_DEBUG)
    printf("标识符 = %d %s\n", 单词编码, 取_单词字符串(单词编码, &单词值));
#结束如果
}

静态 无类型 宏_替代(
    单词字符串 *tok_str,
    符号 **nested_list,
    常量 整数型 *macro_str
    );

/* 用rgs(字段d)中的值替换macro_str中替换列表中的参数,并返回分配的字符串 */
静态 整数型 *宏_参数_替换(符号 **nested_list, 常量 整数型 *macro_str, 符号 *args)
{
    整数型 t, t0, t1, spc;
    常量 整数型 *st;
    符号 *s;
    恒定值 cval;
    单词字符串 str;
    动态字符串 cstr;

    单词字符串_处理(&str);
    t0 = t1 = 0;
    判断(1) {_GET(&t, &macro_str, &cval);
        如果 (!t)
            跳出;
        如果 (t == '#') {
            /* 串化 */_GET(&t, &macro_str, &cval);
            如果 (!t)
                去向 bad_stringy;
            s = 符号_查找2(args, t);
            如果 (s) {
                动态字符串_初始化(&cstr);
                动态字符串_追加单个字符(&cstr, '\"');
                st = s->d;
                spc = 0;
                判断 (*st >= 0) {_GET(&t, &st, &cval);
                    如果 (t != 符_占位符
                     && t != 符_NOSUBST
                     && 0 == 检查_空格(t, &spc)) {
                        常量 字符型 *s = 取_单词字符串(t, &cval);
                        判断 (*s) {
                            如果 (t == 常量_预处理字符串 && *s != '\'')
                                添加_字符(&cstr, *s);
                            否则
                                动态字符串_追加单个字符(&cstr, *s);
                            ++s;
                        }
                    }
                }
                cstr.字符串长度 -= spc;
                动态字符串_追加单个字符(&cstr, '\"');
                动态字符串_追加单个字符(&cstr, '\0');
#如果已定义 PP_DEBUG
                printf("\nstringize: <%s>\n", (字符型 *)cstr.指向字符串的指针;
#结束如果
                /* 添加字符串 */
                cval.str.size = cstr.字符串长度;
                cval.str.data = cstr.指向字符串的指针;
                单词字符串_增加大小2(&str, 常量_预处理字符串, &cval);
                动态字符串_释放(&cstr);
            } 否则 {
        bad_stringy:
                应为(" '#'后的宏参数");
            }
        } 否则 如果 (t >= 符_识别) {
            s = 符号_查找2(args, t);
            如果 (s) {
                整数型 l0 = str.len;
                st = s->d;
                /* 如果'##'之前或之后存在,则无arg替换 */
                如果 (*macro_str == 符_PPJOIN || t1 == 符_PPJOIN) {
                    /* var arg宏的特殊情况:##如果空的VA_ARGS变量吃掉',' */
                    如果 (t1 == 符_PPJOIN && t0 == ',' && gnu_扩展 && s->type.t) {
                        如果 (*st <= 0) {
                            /* 禁止',''##' */
                            str.len -= 2;
                        } 否则 {
                            /* 取消显示“ ##”并添加变量*/
                            str.len--;
                            去向 add_var;
                        }
                    }
                } 否则 {
            add_var:
		    如果 (!s->next) {
			/* 展开参数令牌并存储它们。 在大多数情况下,如果多次使用,我们还可以重新扩展每个参数,但是如果参数包含__COUNTER__宏,则不能。  */
			单词字符串 str2;
			符号_推送2(&s->next, s->v, s->type.t, 0);
			单词字符串_处理(&str2);
			宏_替代(&str2, nested_list, st);
			单词字符串_增加大小(&str2, 0);
			s->next->d = str2.str;
		    }
		    st = s->next->d;
                }
                循环(;;) {
                    整数型 t2;_GET(&t2, &st, &cval);
                    如果 (t2 <= 0)
                        跳出;
                    单词字符串_增加大小2(&str, t2, &cval);
                }
                如果 (str.len == l0) /* 扩展为空字符串 */
                    单词字符串_增加大小(&str, 符_占位符);
            } 否则 {
                单词字符串_增加大小(&str, t);
            }
        } 否则 {
            单词字符串_增加大小2(&str, t, &cval);
        }
        t0 = t1, t1 = t;
    }
    单词字符串_增加大小(&str, 0);
    返回 str.str;
}

静态 字符型 常量 ab_月份_名称[12][4] =
{
    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};

静态 整数型 粘贴_标识符(整数型 t1, 恒定值 *v1, 整数型 t2, 恒定值 *v2)
{
    动态字符串 cstr;
    整数型 n, ret = 1;

    动态字符串_初始化(&cstr);
    如果 (t1 != 符_占位符)
        动态字符串_cat(&cstr, 取_单词字符串(t1, v1), -1);
    n = cstr.字符串长度;
    如果 (t2 != 符_占位符)
        动态字符串_cat(&cstr, 取_单词字符串(t2, v2), -1);
    动态字符串_追加单个字符(&cstr, '\0');

    打开缓存文件(zhi_状态, ":paste:", cstr.字符串长度);
    memcpy(file->buffer, cstr.指向字符串的指针, cstr.字符串长度);
    标识符_标记 = 0;
    循环 (;;) {
        取_下个符号_不宏扩展1();
        如果 (0 == *file->buf_ptr)
            跳出;
        如果 (是_空格(单词编码))
            继续;
        zhi_警告("粘贴 \"%.*s\" 和 \"%s\" 没有给出有效的预处理标识符", n, (字符型 *)cstr.指向字符串的指针, (字符型*)cstr.指向字符串的指针 + n);
        ret = 0;
        跳出;
    }
    关闭文件();
    动态字符串_释放(&cstr);
    返回 ret;
}

/* 处理“ ##”运算符。 如果未看到“ ##”,则返回NULL。 否则返回结果字符串(必须释放). */
静态 内联 整数型 *宏_俩井(常量 整数型 *ptr0)
{
    整数型 t;
    恒定值 cval;
    单词字符串 macro_str1;
    整数型 start_of_nosubsts = -1;
    常量 整数型 *ptr;

    /* 我们搜索第一个“ ##” */
    循环 (ptr = ptr0;;) {_GET(&t, &ptr, &cval);
        如果 (t == 符_PPJOIN)
            跳出;
        如果 (t == 0)
            返回 NULL;
    }

    单词字符串_处理(&macro_str1);

    //标识符_打印(" $$$", ptr0);
    循环 (ptr = ptr0;;) {_GET(&t, &ptr, &cval);
        如果 (t == 0)
            跳出;
        如果 (t == 符_PPJOIN)
            继续;
        判断 (*ptr == 符_PPJOIN) {
            整数型 t1; 恒定值 cv1;
            /* 给定'a ## b',删除'a'之前的nosubstst */
            如果 (start_of_nosubsts >= 0)
                macro_str1.len = start_of_nosubsts;
            /* 给定'a ## b',删除'b'之前的nosubsts */
            判断 ((t1 = *++ptr) == 符_NOSUBST)
                ;
            如果 (t1 && t1 != 符_PPJOIN) {_GET(&t1, &ptr, &cv1);
                如果 (t != 符_占位符 || t1 != 符_占位符) {
                    如果 (粘贴_标识符(t, &cval, t1, &cv1)) {
                        t = 单词编码, cval = 单词值;
                    } 否则 {
                        单词字符串_增加大小2(&macro_str1, t, &cval);
                        t = t1, cval = cv1;
                    }
                }
            }
        }
        如果 (t == 符_NOSUBST) {
            如果 (start_of_nosubsts < 0)
                start_of_nosubsts = macro_str1.len;
        } 否则 {
            start_of_nosubsts = -1;
        }
        单词字符串_增加大小2(&macro_str1, t, &cval);
    }
    单词字符串_增加大小(&macro_str1, 0);
    //标识符_打印(" ###", macro_str1.str);
    返回 macro_str1.str;
}

/* 从函数宏调用中窥视或读取[ws_str == NULL]下一个标记,如有必要,将宏级别提升到文件*/
静态 整数型 从函数宏调用中_读取下一个标记(符号 **nested_list, 单词字符串 *ws_str)
{
    整数型 t;
    常量 整数型 *p;
    符号 *sa;

    循环 (;;) {
        如果 (宏_ptr) {
            p = 宏_ptr, t = *p;
            如果 (ws_str) {
                判断 (是_空格(t) || 符_换行 == t || 符_占位符 == t)
                    单词字符串_增加大小(ws_str, t), t = *++p;
            }
            如果 (t == 0) {
                结束_宏();
                /* 同样,嵌套定义符号的作用域结尾 */
                sa = *nested_list;
                判断 (sa && sa->v == 0)
                    sa = sa->prev;
                如果 (sa)
                    sa->v = 0;
                继续;
            }
        } 否则 {
            当前取到的源码字符 = 处理_块的结尾();
            如果 (ws_str) {
                判断 (是_空格(当前取到的源码字符) || 当前取到的源码字符 == '\n' || 当前取到的源码字符 == '/') {
                    如果 (当前取到的源码字符 == '/') {
                        整数型 c;
                        uint8_t *p = file->buf_ptr;
                        复杂转义(c, p);
                        如果 (c == '*') {
                            p = 解析_注释(p);
                            file->buf_ptr = p - 1;
                        } 否则 如果 (c == '/') {
                            p = 解析_单行_注释(p);
                            file->buf_ptr = p - 1;
                        } 否则
                            跳出;
                        当前取到的源码字符 = ' ';
                    }
                    如果 (当前取到的源码字符 == '\n')
                        file->line_num++;
                    如果 (!(当前取到的源码字符 == '\f' || 当前取到的源码字符 == '\v' || 当前取到的源码字符 == '\r'))
                        单词字符串_增加大小(ws_str, 当前取到的源码字符);
                    cinp();
                }
            }
            t = 当前取到的源码字符;
        }

        如果 (ws_str)
            返回 t;
        取_下个符号_不宏扩展();
        返回 单词编码;
    }
}

/* 用宏“ s”对当前令牌进行宏替换,并将结果添加到(tok_str,tok_len)。 “ nested_list”是我们为了避免递归而进入的所有宏的列表。 如果不需要替换,则返回非零 */
静态 整数型 宏替换_当前标识符(
    单词字符串 *tok_str,
    符号 **nested_list,
    符号 *s)
{
    符号 *args, *sa, *sa1;
    整数型 parlevel, t, t1, spc;
    单词字符串 str;
    字符型 *cstrval;
    恒定值 cval;
    动态字符串 cstr;
    字符型 buf[32];

    /* 如果符号是宏,则准备替换 */
    /* 特殊宏 */
    如果 (单词编码 == 符___LINE__  || 单词编码 == 符___LINE___CN || 单词编码 == 符___COUNTER__ || 单词编码 == 符___COUNTER___CN) {
        t =(单词编码 == 符___LINE__ || 单词编码 == 符___LINE___CN) ? file->line_num : 词法分析_计数器++;
        snprintf(buf, 取大小(buf), "%d", t);
        cstrval = buf;
        t1 = 常量_预处理编号;
        去向 add_cstr1;
    } 否则 如果 (单词编码 == 符___FILE__ || 单词编码 == 符___FILE___CN) {
        cstrval = file->文件名;
        去向 add_cstr;
    } 否则 如果 (单词编码 == 符___DATE__ || 单词编码 == 符___DATE___CN || 单词编码 == 符___TIME__ || 单词编码 == 符___TIME___CN) {
        time_t ti;
        结构体 tm *tm;

        time(&ti);
        tm = localtime(&ti);
        如果 (单词编码 == 符___DATE__ || 单词编码 == 符___DATE___CN) {
            snprintf(buf, 取大小(buf), "%s %2d %d", 
                     ab_月份_名称[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
        } 否则 {
            snprintf(buf, 取大小(buf), "%02d:%02d:%02d", 
                     tm->tm_hour, tm->tm_min, tm->tm_sec);
        }
        cstrval = buf;
    add_cstr:
        t1 = 常量_字符串;
    add_cstr1:
        动态字符串_初始化(&cstr);
        动态字符串_cat(&cstr, cstrval, 0);
        cval.str.size = cstr.字符串长度;
        cval.str.data = cstr.指向字符串的指针;
        单词字符串_增加大小2(tok_str, t1, &cval);
        动态字符串_释放(&cstr);
    } 否则 如果 (s->d) {
        整数型 saved_解析_标记 = 解析_标记;
	整数型 *joined_str = NULL;
        整数型 *mstr = s->d;

        如果 (s->type.t == 宏_函数) {
            /* 宏名称和参数列表之间的空格 */
            单词字符串 ws_str;
            单词字符串_处理(&ws_str);

            spc = 0;
            解析_标记 |= 解析_标记_空间 | 解析_标记_换行符
                | 解析_标记_接受_转义;

            /* 从参数流中获取下一个标记 */
            t = 从函数宏调用中_读取下一个标记(nested_list, &ws_str);
            如果 (t != '(') {
                /* 毕竟不是宏替换,请恢复宏令牌以及我们已阅读的所有空白。故意不合并空白以保留换行符。 */
                解析_标记 = saved_解析_标记;
                单词字符串_增加大小(tok_str, 单词编码);
                如果 (解析_标记 & 解析_标记_空间) {
                    整数型 i;
                    循环 (i = 0; i < ws_str.len; i++)
                        单词字符串_增加大小(tok_str, ws_str.str[i]);
                }
                单词字符串_释放_字符串(ws_str.str);
                返回 0;
            } 否则 {
                单词字符串_释放_字符串(ws_str.str);
            }
	    执行 {
		取_下个符号_不宏扩展(); /* eat '(' */
	    } 判断 (单词编码 == 符_占位符 || 是_空格(单词编码));

            /* 参数宏 */
            args = NULL;
            sa = s->next;
            /* 注意:允许使用空参数,除非没有参数 */
            循环(;;) {
                执行 {
                    从函数宏调用中_读取下一个标记(nested_list, NULL);
                } 判断 (是_空格(单词编码) || 符_换行 == 单词编码);
    empty_arg:
                /* 处理'()'实例 */
                如果 (!args && !sa && 单词编码 == ')')
                    跳出;
                如果 (!sa)
                    错误_打印("宏 '%s' 与过多的参数一起使用",
                          取_单词字符串(s->v, 0));
                单词字符串_处理(&str);
                parlevel = spc = 0;
                /* 注意:非零sa-> t表示VA_ARGS */
                判断 ((parlevel > 0 || 
                        (单词编码 != ')' && 
                         (单词编码 != ',' || sa->type.t)))) {
                    如果 (单词编码 == 符_文件结尾 || 单词编码 == 0)
                        跳出;
                    如果 (单词编码 == '(')
                        parlevel++;
                    否则 如果 (单词编码 == ')')
                        parlevel--;
                    如果 (单词编码 == 符_换行)
                        单词编码 = ' ';
                    如果 (!检查_空格(单词编码, &spc))
                        单词字符串_增加大小2(&str, 单词编码, &单词值);
                    从函数宏调用中_读取下一个标记(nested_list, NULL);
                }
                如果 (parlevel)
                    应为(")");
                str.len -= spc;
                单词字符串_增加大小(&str, -1);
                单词字符串_增加大小(&str, 0);
                sa1 = 符号_推送2(&args, sa->v & ~符号_字段, sa->type.t, 0);
                sa1->d = str.str;
                sa = sa->next;
                如果 (单词编码 == ')') {
                    /* gcc var args的特殊情况:如果省略,则添加一个空的var arg参数*/
                    如果 (sa && sa->type.t && gnu_扩展)
                        去向 empty_arg;
                    跳出;
                }
                如果 (单词编码 != ',')
                    应为(",");
            }
            如果 (sa) {
                错误_打印("宏 '%s' 使用的参数太少",
                      取_单词字符串(s->v, 0));
            }

            /* 现在替换每个arg */
            mstr = 宏_参数_替换(nested_list, mstr, args);
            /* 内存_释放 */
            sa = args;
            判断 (sa) {
                sa1 = sa->prev;
                单词字符串_释放_字符串(sa->d);
                如果 (sa->next) {
                    单词字符串_释放_字符串(sa->next->d);
                    符号_释放(sa->next);
                }
                符号_释放(sa);
                sa = sa1;
            }
            解析_标记 = saved_解析_标记;
        }

        符号_推送2(nested_list, s->v, 0, 0);
        解析_标记 = saved_解析_标记;
        joined_str = 宏_俩井(mstr);
        宏_替代(tok_str, nested_list, joined_str ? joined_str : mstr);

        /* 弹出嵌套定义的符号 */
        sa1 = *nested_list;
        *nested_list = sa1->prev;
        符号_释放(sa1);
	如果 (joined_str)
	    单词字符串_释放_字符串(joined_str);
        如果 (mstr != s->d)
            单词字符串_释放_字符串(mstr);
    }
    返回 0;
}

/* 对macro_str进行宏替换,并将结果添加到(tok_str,tok_len)。 “ nested_list”是我们为了避免递归而进入的所有宏的列表。 */
静态 无类型 宏_替代(
    单词字符串 *tok_str,
    符号 **nested_list,
    常量 整数型 *macro_str
    )
{
    符号 *s;
    整数型 t, spc, nosubst;
    恒定值 cval;
    
    spc = nosubst = 0;

    判断 (1) {_GET(&t, &macro_str, &cval);
        如果 (t <= 0)
            跳出;

        如果 (t >= 符_识别 && 0 == nosubst) {
            s = 宏定义_查找(t);
            如果 (s == NULL)
                去向 no_subst;

            /* 如果嵌套替换,则不执行任何操作 */
            如果 (符号_查找2(*nested_list, t)) {
                /* 并将其标记为符_NOSUBST,因此不会再次被替换 */
                单词字符串_增加大小2(tok_str, 符_NOSUBST, NULL);
                去向 no_subst;
            }

            {
                单词字符串 *str = 单词字符串_分配();
                str->str = (整数型*)macro_str;
                开始_宏(str, 2);

                单词编码 = t;
                宏替换_当前标识符(tok_str, nested_list, s);

                如果 (宏_堆栈 != str) {
                    /* 通过读取函数宏参数已完成 */
                    跳出;
                }

                macro_str = 宏_ptr;
                结束_宏 ();
            }
            如果 (tok_str->len)
                spc = 是_空格(t = tok_str->str[tok_str->lastlen]);
        } 否则 {
no_subst:
            如果 (!检查_空格(t, &spc))
                单词字符串_增加大小2(tok_str, t, &cval);

            如果 (nosubst) {
                如果 (nosubst > 1 && (spc || (++nosubst == 3 && t == '(')))
                    继续;
                nosubst = 0;
            }
            如果 (t == 符_NOSUBST)
                nosubst = 1;
        }
        /* 由于宏替换,GCC支持“def” */
        如果 ((t == 关键字_DEFINED || t == 关键字_已定义)  && 词法分析_表达式)
            nosubst = 2;
    }
}

/* 返回下一个标记而不进行宏替换。 可以从宏_ptr缓冲区读取输入 */
静态 无类型 取_下个符号_不宏扩展(无类型)
{
    整数型 t;
    如果 (宏_ptr) {
 redo:
        t = *宏_ptr;
        如果 (符_有_值(t)) {
            获取_标识符(&单词编码, &宏_ptr, &单词值);
            如果 (t == 常量_行号) {
                file->line_num = 单词值.i;
                去向 redo;
            }
        } 否则 {
            宏_ptr++;
            如果 (t < 符_识别) {
                如果 (!(解析_标记 & 解析_标记_空间)
                    && (等值_表[t - CH_文件结尾] & IS_SPC))
                    去向 redo;
            }
            单词编码 = t;
        }
    } 否则 {
        取_下个符号_不宏扩展1();
    }
}

/* 返回带有宏替换的下一个标记 */
静态_函数 无类型 带有宏替换的下个标记(无类型)
{
    整数型 t;
 redo:
    取_下个符号_不宏扩展();
    t = 单词编码;
    如果 (宏_ptr) {
        如果 (!符_有_值(t)) {
            如果 (t == 符_NOSUBST || t == 符_占位符) {
                /* 丢弃预处理器标记 */
                去向 redo;
            } 否则 如果 (t == 0) {
                /* 宏结尾或获取令牌字符串 */
                结束_宏();
                去向 redo;
            } 否则 如果 (t == '\\') {
                如果 (!(解析_标记 & 解析_标记_接受_转义))
                    错误_打印("程序中流浪 '\\' ");
            }
            返回;
        }
    } 否则 如果 (t >= 符_识别 && (解析_标记 & 解析_标记_预处理)) {
        /* 如果从文件读取,请尝试替换宏 */
        符号 *s = 宏定义_查找(t);
        如果 (s) {
            符号 *nested_list = NULL;
            单词字符串_缓冲.len = 0;
            宏替换_当前标识符(&单词字符串_缓冲, &nested_list, s);
            单词字符串_增加大小(&单词字符串_缓冲, 0);
            开始_宏(&单词字符串_缓冲, 0);
            去向 redo;
        }
        返回;
    }
    /* 将预处理器标识符转换为C标识符 */
    如果 (t == 常量_预处理编号) {
        如果  (解析_标记 & 解析_标记_标识符_数字)
            解析_数字((字符型 *)单词值.str.data);
    } 否则 如果 (t == 常量_预处理字符串) {
        如果 (解析_标记 & 解析_标记_单词字符串)
            解析_字符串((字符型 *)单词值.str.data, 单词值.str.size - 1);
    }
}

/* 推回当前令牌并将当前令牌设置为“ last_tok”。 仅处理标签的标识符大小写. */
静态_内联 无类型 设为_指定标识符(整数型 last_tok)
{

    单词字符串 *str = 单词字符串_分配();
    单词字符串_增加大小2(str, 单词编码, &单词值);
    单词字符串_增加大小(str, 0);
    开始_宏(str, 1);
    单词编码 = last_tok;
}

静态 无类型 zhi_预定义(动态字符串 *cstr)
{
    动态字符串_cat(cstr,
#如果 已定义 ZHI_TARGET_X86_64
#如果未定义 ZHI_TARGET_PE
    /* va_list的GCC兼容定义。 这应该与我们的lib / hexinku1.c中的声明同步 */
    "类型定义 结构体{\n"
    "无符号 gp_offset,fp_offset;\n"
    "共用体{\n"
    "无符号 overflow_offset;\n"
    "字符型*overflow_arg_area;\n"
    "};\n"
    "字符型*reg_save_area;\n"
    "}__builtin_va_list[1];\n"
    "无类型*__va_arg(__builtin_va_list ap,整数型 arg_type,整数型 size,整数型 align);\n"
    "#定义 __builtin_va_start(ap,last) (*(ap)=*(__builtin_va_list)((字符型*)__builtin_frame_address(0)-24))\n"
    "#定义 __builtin_va_arg(ap,t) (*(t*)(__va_arg(ap,__builtin_va_arg_types(t),取大小(t),__alignof__(t))))\n"
    "#定义 __builtin_va_copy(dest,src) (*(dest)=*(src))\n"
#否则 /* ZHI_TARGET_PE */
    "类型定义 字符型*__builtin_va_list;\n"
    "#定义 __builtin_va_arg(ap,t) ((取大小(t)>8||(取大小(t)&(取大小(t)-1)))?**(t**)((ap+=8)-8):*(t*)((ap+=8)-8))\n"
    "#定义 __builtin_va_copy(dest,src) (dest)=(src)\n"
#结束如果
#否则如果 已定义 ZHI_TARGET_ARM
    "类型定义 字符型*__builtin_va_list;\n"
    "#定义 _zhi_alignof(type) ((整数型)&((结构体{字符型 c;type x;}*)0)->x)\n"
    "#定义 _zhi_align(addr,type) (((无符号)addr+_zhi_alignof(type)-1)&~(_zhi_alignof(type)-1))\n"
    "#定义 __builtin_va_start(ap,last) (ap=((字符型*)&(last))+((取大小(last)+3)&~3))\n"
    "#定义 __builtin_va_arg(ap,type) (ap=(无类型*)((_zhi_align(ap,type)+取大小(type)+3)&~3),*(type*)(ap-((取大小(type)+3)&~3)))\n"
    "#定义 __builtin_va_copy(dest,src) (dest)=(src)\n"
#否则如果 已定义 ZHI_TARGET_ARM64
    "类型定义 结构体{\n"
    "无类型*__stack,*__gr_top,*__vr_top;\n"
    "整数型 __gr_offs,__vr_offs;\n"
    "}__builtin_va_list;\n"
    "#定义 __builtin_va_copy(dest,src) (dest)=(src)\n"
#否则如果 已定义 ZHI_TARGET_RISCV64
    "类型定义 字符型*__builtin_va_list;\n"
    "#定义 __va_reg_size (__riscv_xlen>>3)\n"
    "#定义 _zhi_align(addr,type) (((无符号 long)addr+__alignof__(type)-1)&-(__alignof__(type)))\n"
    "#定义 __builtin_va_arg(ap,type) (*(取大小(type)>(2*__va_reg_size)?*(type**)((ap+=__va_reg_size)-__va_reg_size):(ap=(va_list)(_zhi_align(ap,type)+(取大小(type)+__va_reg_size-1)&-__va_reg_size),(type*)(ap-((取大小(type)+__va_reg_size-1)&-__va_reg_size)))))\n"
    "#定义 __builtin_va_copy(dest,src) (dest)=(src)\n"
#否则 /* ZHI_TARGET_I386 */
    "类型定义 字符型*__builtin_va_list;\n"
    "#定义 __builtin_va_start(ap,last) (ap=((字符型*)&(last))+((取大小(last)+3)&~3))\n"
    "#定义 __builtin_va_arg(ap,t) (*(t*)((ap+=(取大小(t)+3)&~3)-((取大小(t)+3)&~3)))\n"
    "#定义 __builtin_va_copy(dest,src) (dest)=(src)\n"
#结束如果
    "#定义 __builtin_va_end(ap) (无类型)(ap)\n"
    , -1);
}

静态_函数 无类型 开始_预处理(知心状态机 *状态机1, 整数型 is_asm)
{
    动态字符串 cstr;

    词法分析_开始(状态机1);

    状态机1->包含_堆_ptr = 状态机1->包含_堆;
    状态机1->如果已宏定义_堆_ptr = 状态机1->如果已宏定义_堆;
    file->如果已宏定义_堆_ptr = 状态机1->如果已宏定义_堆_ptr;
    词法分析_表达式 = 0;
    词法分析_计数器 = 0;
    词法分析_调试_标识符 = 词法分析_调试_字符值 = 0;
    词法分析_第一次++;
    状态机1->包_堆[0] = 0;
    状态机1->包_堆_ptr = 状态机1->包_堆;

    设置_等值数('$', !is_asm && 状态机1->允许_在标识符中使用美元符号 ? IS_ID : 0);
    设置_等值数('.', is_asm ? IS_ID : 0);

    动态字符串_初始化(&cstr);
    如果 (状态机1->命令行_定义.字符串长度)
        动态字符串_cat(&cstr, 状态机1->命令行_定义.指向字符串的指针, 状态机1->命令行_定义.字符串长度);
    动态字符串_打印(&cstr, "#定义 __BASE_FILE__ \"%s\"\n", file->文件名);
    如果 (is_asm)
        动态字符串_打印(&cstr, "#定义 __ASSEMBLER__ 1\n");
    如果 (状态机1->输出_类型 == ZHI_输出_内存中运行)
        动态字符串_打印(&cstr, "#定义 __ZHI_RUN__ 1\n");
    如果 (!is_asm && 状态机1->输出_类型 != ZHI_输出_预处理)
        zhi_预定义(&cstr);
    如果 (状态机1->命令行_包含.字符串长度)
        动态字符串_cat(&cstr, 状态机1->命令行_包含.指向字符串的指针, 状态机1->命令行_包含.字符串长度);
    //printf("%s\n", (字符型*)cstr.data);
    *状态机1->包含_堆_ptr++ = file;
    打开缓存文件(状态机1, "<command line>", cstr.字符串长度);
    memcpy(file->buffer, cstr.指向字符串的指针, cstr.字符串长度);
    动态字符串_释放(&cstr);

    解析_标记 = is_asm ? 解析_标记_汇编_文件 : 0;
    标识符_标记 = 符_标记_行开始前 | 符_标记_文件开始前;
}

/* 从错误/ setjmp中清除 */
静态_函数 无类型 结束_预处理(知心状态机 *状态机1)
{
    判断 (宏_堆栈)
        结束_宏();
    宏_ptr = NULL;
    判断 (file)
        关闭文件();
    zhi词法_删除(状态机1);
}

静态_函数 无类型 词法分析_开始(知心状态机 *s)
{
    整数型 i, c;
    常量 字符型 *p, *r;

    /* 初始化是id表 */
    循环(i = CH_文件结尾; i<128; i++)
        设置_等值数(i,
            是_空格(i) ? IS_SPC
            :id(i) ? IS_ID
            : 是数字(i) ? IS_NUM
            : 0);

    循环(i = 128; i<256; i++)
        设置_等值数(i, IS_ID);

    /* 初始化分配器 */
    小分配器_新建(&单词字符_分配内存, 单词字符_小分配器_限制, 单词字符_小分配器_大小);
    小分配器_新建(&单词字符串_分配内存, 单词字符串_小分配器_限制, 单词字符串_小分配器_大小);

    memset(单词_哈希表, 0, 哈希表容量 * 取大小(单词存储结构 *));
    memset(s->缓存_包含数_哈希, 0, 取大小 s->缓存_包含数_哈希);

    动态字符串_初始化(&动态字符串_缓冲);
    动态字符串_重分配内存(&动态字符串_缓冲, 字符串_最大_长度);
    单词字符串_处理(&单词字符串_缓冲);
    单词字符串_重分配(&单词字符串_缓冲, 单词字符串_最大_长度);

    单词_识别号 = 符_识别;
    p = 编译_关键词;
    判断 (*p) {
        r = p;
        循环(;;) {
            c = *r++;
            如果 (c == '\0')
                跳出;
        }
        单词表_查找(p, r - p - 1);
        p = r;
    }

    /* 我们为一些特殊的宏添加了虚拟定义,以加快测试速度,并具有有效的define() */
    宏定义_处理(符___LINE__, 宏_对象, NULL, NULL);
    宏定义_处理(符___FILE__, 宏_对象, NULL, NULL);
    宏定义_处理(符___DATE__, 宏_对象, NULL, NULL);
    宏定义_处理(符___TIME__, 宏_对象, NULL, NULL);
    宏定义_处理(符___COUNTER__, 宏_对象, NULL, NULL);
}

静态_函数 无类型 zhi词法_删除(知心状态机 *s)
{
    整数型 i, n;

    动态数组_重分配容量(&s->缓存_包含数, &s->数量_缓存_包含数);

    /* 释放标识符 */
    n = 单词_识别号 - 符_识别;
    如果 (n > 总_idents)
        总_idents = n;
    循环(i = 0; i < n; i++)
        小分配器_释放(单词字符_分配内存, 单词表[i]);
    内存_释放(单词表);
    单词表 = NULL;

    /* 释放静态缓冲区 */
    动态字符串_释放(&当前单词字符串);
    动态字符串_释放(&动态字符串_缓冲);
    动态字符串_释放(&宏_等于_缓冲区);
    单词字符串_释放_字符串(单词字符串_缓冲.str);

    /* 释放分配器 */
    小分配器_删除(单词字符_分配内存);
    单词字符_分配内存 = NULL;
    小分配器_删除(单词字符串_分配内存);
    单词字符串_分配内存 = NULL;
}

/* ------------------------------------------------------------------------- */

静态 无类型 标识符_打印(常量 字符型 *msg, 常量 整数型 *str)
{
    FILE *fp;
    整数型 t, s = 0;
    恒定值 cval;

    fp = zhi_状态->预处理输出文件;
    fprintf(fp, "%s", msg);
    判断 (str) {_GET(&t, &str, &cval);
	如果 (!t)
	    跳出;
	fprintf(fp, " %s" + s, 取_单词字符串(t, &cval)), s = 1;
    }
    fprintf(fp, "\n");
}

静态 无类型 词法_行(知心状态机 *状态机1, 缓冲文件 *f, 整数型 level)
{
    整数型 d = f->line_num - f->line_ref;

    如果 (状态机1->DX标号 & 4)
	返回;

    如果 (状态机1->P标号 == LINE_MACRO_OUTPUT_FORMAT_NONE) {
        ;
    } 否则 如果 (level == 0 && f->line_ref && d < 8) {
	判断 (d > 0)
	    fputs("\n", 状态机1->预处理输出文件), --d;
    } 否则 如果 (状态机1->P标号 == LINE_MACRO_OUTPUT_FORMAT_STD) {
	fprintf(状态机1->预处理输出文件, "#line %d \"%s\"\n", f->line_num, f->文件名);
    } 否则 {
	fprintf(状态机1->预处理输出文件, "# %d \"%s\"%s\n", f->line_num, f->文件名,
	    level > 0 ? " 1" : level < 0 ? " 2" : "");
    }
    f->line_ref = f->line_num;
}

静态 无类型 宏定义_打印(知心状态机 *状态机1, 整数型 v)
{
    FILE *fp;
    符号 *s;

    s = 宏定义_查找(v);
    如果 (NULL == s || NULL == s->d)
        返回;

    fp = 状态机1->预处理输出文件;
    fprintf(fp, "#定义 %s", 取_单词字符串(v, NULL));
    如果 (s->type.t == 宏_函数) {
        符号 *a = s->next;
        fprintf(fp,"(");
        如果 (a)
            循环 (;;) {
                fprintf(fp,"%s", 取_单词字符串(a->v & ~符号_字段, NULL));
                如果 (!(a = a->next))
                    跳出;
                fprintf(fp,",");
            }
        fprintf(fp,")");
    }
    标识符_打印("", s->d);
}

静态 无类型 词法_调试_宏定义(知心状态机 *状态机1)
{
    整数型 v, t;
    常量 字符型 *vs;
    FILE *fp;

    t = 词法分析_调试_标识符;
    如果 (t == 0)
        返回;

    file->line_num--;
    词法_行(状态机1, file, 0);
    file->line_ref = ++file->line_num;

    fp = 状态机1->预处理输出文件;
    v = 词法分析_调试_字符值;
    vs = 取_单词字符串(v, NULL);
    如果 (t == 关键字_DEFINE || t == 关键字_定义) {
        宏定义_打印(状态机1, v);
    } 否则 如果 (t == 关键字_UNDEF || t == 关键字_取消定义) {
        fprintf(fp, "#取消定义 %s\n", vs);
    } 否则 如果 (t == 符_push_macro) {
        fprintf(fp, "#pragma push_macro(\"%s\")\n", vs);
    } 否则 如果 (t == 符_pop_macro) {
        fprintf(fp, "#pragma pop_macro(\"%s\")\n", vs);
    }
    词法分析_调试_标识符 = 0;
}

静态 无类型 词法_调试_内置(知心状态机 *状态机1)
{
    整数型 v;
    循环 (v = 符_识别; v < 单词_识别号; ++v)
        宏定义_打印(状态机1, v);
}

/* 在标记a和b之间添加一个空格,以避免不必要的文本粘贴 */
静态 整数型 词法_添加_空格(整数型 a, 整数型 b)
{
    返回 'E' == a ? '+' == b || '-' == b
        : '+' == a ? 双符号_自加1 == b || '+' == b
        : '-' == a ? 双符号_自减1 == b || '-' == b
        : a >= 符_识别 ? b >= 符_识别
	: a == 常量_预处理编号 ? b >= 符_识别
        : 0;
}

/* 也许像0x1e这样的十六进制 */
静态 整数型 词法_检查_he0xE(整数型 t, 常量 字符型 *p)
{
    如果 (t == 常量_预处理编号 && toup(strchr(p, 0)[-1]) == 'E')
        返回 'E';
    返回 t;
}

/* 预处理当前文件 */
静态_函数 整数型 预处理_源文件(知心状态机 *状态机1)
{
    缓冲文件 **iptr;
    整数型 标识符_seen, spcs, level;
    常量 字符型 *p;
    字符型 white[400];

    解析_标记 = 解析_标记_预处理 | (解析_标记 & 解析_标记_汇编_文件) | 解析_标记_换行符 | 解析_标记_空间 | 解析_标记_接受_转义;
    如果 (状态机1->P标号 == LINE_MACRO_OUTPUT_FORMAT_P10)
        解析_标记 |= 解析_标记_标识符_数字, 状态机1->P标号 = 1;

#如果已定义 PP_BENCH
    /* 用于PP基准 */
    执行 带有宏替换的下个标记(); 判断 (单词编码 != 符_文件结尾);
    返回 0;
#结束如果

    如果 (状态机1->DX标号 & 1) {
        词法_调试_内置(状态机1);
        状态机1->DX标号 &= ~1;
    }

    标识符_seen = 符_换行, spcs = 0, level = 0;
    如果 (file->prev)
        词法_行(状态机1, file->prev, level++);
    词法_行(状态机1, file, level);
    循环 (;;) {
        iptr = 状态机1->包含_堆_ptr;
        带有宏替换的下个标记();
        如果 (单词编码 == 符_文件结尾)
            跳出;

        level = 状态机1->包含_堆_ptr - iptr;
        如果 (level) {
            如果 (level > 0)
                词法_行(状态机1, *iptr, 0);
            词法_行(状态机1, file, level);
        }
        如果 (状态机1->DX标号 & 7) {
            词法_调试_宏定义(状态机1);
            如果 (状态机1->DX标号 & 4)
                继续;
        }

        如果 (是_空格(单词编码)) {
            如果 (spcs < 取大小 white - 1)
                white[spcs++] = 单词编码;
            继续;
        } 否则 如果 (单词编码 == 符_换行) {
            spcs = 0;
            如果 (标识符_seen == 符_换行)
                继续;
            ++file->line_ref;
        } 否则 如果 (标识符_seen == 符_换行) {
            词法_行(状态机1, file, 0);
        } 否则 如果 (spcs == 0 && 词法_添加_空格(标识符_seen, 单词编码)) {
            white[spcs++] = ' ';
        }

        white[spcs] = 0, fputs(white, 状态机1->预处理输出文件), spcs = 0;
        fputs(p = 取_单词字符串(单词编码, &单词值), 状态机1->预处理输出文件);
        标识符_seen = 词法_检查_he0xE(单词编码, p);
    }
    返回 0;
}

/* ------------------------------------------------------------------------- */

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知语言

您的鼓励是我从事编译器汉化动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值