TCC(TinyC)编译器汉化(中文编译器、汉语编程)之三:词法分析
程序员文章站
2022-03-30 20:41:08
...
词法分析.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, ¯o_str, &cval);
如果 (!t)
跳出;
如果 (t == '#') {
/* 串化 */
符_GET(&t, ¯o_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;
}
单词字符串_处理(¯o_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(¯o_str1, t, &cval);
t = t1, cval = cv1;
}
}
}
}
如果 (t == 符_NOSUBST) {
如果 (start_of_nosubsts < 0)
start_of_nosubsts = macro_str1.len;
} 否则 {
start_of_nosubsts = -1;
}
单词字符串_增加大小2(¯o_str1, t, &cval);
}
单词字符串_增加大小(¯o_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, ¯o_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;
}
/* ------------------------------------------------------------------------- */
推荐阅读
-
TCC(TinyC)编译器汉化(中文编译器、汉语编程)之四:语法分析上
-
TCC(TinyC)编译器汉化(中文编译器、汉语编程)之三:词法分析
-
TCC(TinyC)编译器汉化(中文编译器、汉语编程)之二:字符(token)汉化
-
TCC(TinyC)编译器汉化(中文编译器、汉语编程)之九:核心库源码
-
TCC(TinyC)编译器汉化(中文编译器、汉语编程)之七:中间语言生成器
-
TCC(TinyC)编译器汉化(中文编译器、汉语编程)之六:中间操作码
-
TCC(TinyC)编译器汉化(中文编译器、汉语编程)之八:汇编处理
-
TCC(TinyC)编译器汉化(中文编译器、汉语编程)之一:主文件汉化
-
TCC(TinyC)编译器汉化(中文编译器、汉语编程)之五:语法分析下