语法分析下半部分源码如下:

        分支 符_REGPARM1:分支 符_REGPARM2:跳过('(');n = 表达式_常量();如果 (n > 3) n = 3;否则 如果 (n < 0)n = 0;如果 (n > 0)ad->f.函数_调用 = 函数_快速调用1 + n - 1;跳过(')');跳出;分支 符_快速调用1:分支 符_快速调用2:分支 符_快速调用3:ad->f.函数_调用 = 函数_快速调用W;跳出;
#结束如果分支 符_MODE:跳过('(');选择(单词编码) {分支 符_MODE_DI:ad->attr_mode = VT_长长整数 + 1;跳出;分支 符_MODE_QI:ad->attr_mode = VT_字节 + 1;跳出;分支 符_MODE_HI:ad->attr_mode = VT_短整数 + 1;跳出;分支 符_MODE_SI:分支 符_MODE_word:ad->attr_mode = VT_整数 + 1;跳出;default:zhi_警告("__mode__(%s) not supported\n", 取_单词字符串(单词编码, NULL));跳出;}带有宏替换的下个标记();跳过(')');跳出;分支 符_DLLEXPORT:ad->a.dllexport = 1;跳出;分支 符_NODECORATE:ad->a.nodecorate = 1;跳出;分支 符_DLLIMPORT:ad->a.dllimport = 1;跳出;default:如果 (zhi_状态->警告_不支持)zhi_警告("'%s' attribute ignored", 取_单词字符串(t, NULL));/* 跳过 parameters */如果 (单词编码 == '(') {整数型 parenthesis = 0;执行 {如果 (单词编码 == '(') parenthesis++;否则 如果 (单词编码 == ')') parenthesis--;带有宏替换的下个标记();} 判断 (parenthesis && 单词编码 != -1);}跳出;}如果 (单词编码 != ',')跳出;带有宏替换的下个标记();}跳过(')');跳过(')');去向 redo;
}静态 符号 * 查找_域 (C类型 *type, 整数型 v, 整数型 *cumofs)
{符号 *s = type->ref;v |= 符号_字段;判断 ((s = s->next) != NULL) {如果 ((s->v & 符号_字段) &&(s->type.t & VT_基本类型) == VT_结构体 &&(s->v & ~符号_字段) >= 符号_第一个_匿名) {符号 *ret = 查找_域 (&s->type, v, cumofs);如果 (ret) {*cumofs += s->c;返回 ret;}}如果 (s->v == v)跳出;}返回 s;
}静态 无类型 结构体_布局(C类型 *type, 属性定义 *ad)
{整数型 size, align, maxalign, offset, c, bit_pos, bit_size;整数型 packed, a, bt, prevbt, prev_bit_size;整数型 pcc = !zhi_状态->模拟_对齐位域MS算法;整数型 pragma_pack = *zhi_状态->包_堆_ptr;符号 *f;maxalign = 1;offset = 0;c = 0;bit_pos = 0;prevbt = VT_结构体; /* make it never match */prev_bit_size = 0;//#定义 BF_DEBUG循环 (f = type->ref->next; f; f = f->next) {如果 (f->type.t & VT_位域)bit_size = BIT_大小(f->type.t);否则bit_size = -1;size = 类型_大小(&f->type, &align);a = f->a.aligned ? 1 << (f->a.aligned - 1) : 0;packed = 0;如果 (pcc && bit_size == 0) {/* in pcc mode, packing does not affect zero-width bitfields */} 否则 {/* in pcc mode, attribute packed overrides 如果 set. */如果 (pcc && (f->a.packed || ad->a.packed))align = packed = 1;/* pragma pack overrides align 如果 lesser and packs bitfields always */如果 (pragma_pack) {packed = 1;如果 (pragma_pack < align)align = pragma_pack;/* in pcc mode pragma pack also overrides individual align */如果 (pcc && pragma_pack < a)a = 0;}}/* some individual align was specified */如果 (a)align = a;如果 (type->ref->type.t == VT_共用体) {如果 (pcc && bit_size >= 0)size = (bit_size + 7) >> 3;offset = 0;如果 (size > c)c = size;} 否则 如果 (bit_size < 0) {如果 (pcc)c += (bit_pos + 7) >> 3;c = (c + align - 1) & -align;offset = c;如果 (size > 0)c += size;bit_pos = 0;prevbt = VT_结构体;prev_bit_size = 0;} 否则 {/* A bit-field.  Layout is more complicated.  There are twooptions: PCC (GCC) compatible and MS compatible */如果 (pcc) {/* In PCC layout a bit-field is placed adjacent to thepreceding bit-fields, except 如果:- it has zero-width- an individual alignment was given- it would overflow its base type container andthere is no packing */如果 (bit_size == 0) {new_field:c = (c + ((bit_pos + 7) >> 3) + align - 1) & -align;bit_pos = 0;} 否则 如果 (f->a.aligned) {去向 new_field;} 否则 如果 (!packed) {整数型 a8 = align * 8;整数型 ofs = ((c * 8 + bit_pos) % a8 + bit_size + a8 - 1) / a8;如果 (ofs > size / align)去向 new_field;}/* in pcc mode, long long bitfields have type 整数型 如果 they fit */如果 (size == 8 && bit_size <= 32)f->type.t = (f->type.t & ~VT_基本类型) | VT_整数, size = 4;判断 (bit_pos >= align * 8)c += align, bit_pos -= align * 8;offset = c;/* In PCC layout named bit-fields influence the alignmentof the containing 结构体 using the base types alignment,except 循环 packed fields (which here have correct align).  */如果 (f->v & 符号_第一个_匿名// && bit_size // ??? gcc on ARM/rpi does that)align = 1;} 否则 {bt = f->type.t & VT_基本类型;如果 ((bit_pos + bit_size > size * 8)|| (bit_size > 0) == (bt != prevbt)) {c = (c + align - 1) & -align;offset = c;bit_pos = 0;/* In MS bitfield mode a bit-field run always usesat least as many bits as the underlying type.To start a new run it's also required that thisor the last bit-field had non-zero width.  */如果 (bit_size || prev_bit_size)c += size;}/* In MS layout the records alignment is normallyinfluenced by the field, except 循环 a zero-widthfield at the start of a run (but by further zero-widthfields it is again).  */如果 (bit_size == 0 && prevbt != bt)align = 1;prevbt = bt;prev_bit_size = bit_size;}f->type.t = (f->type.t & ~(0x3f << VT_结构体_转换))| (bit_pos << VT_结构体_转换);bit_pos += bit_size;}如果 (align > maxalign)maxalign = align;#如果已定义 BF_DEBUGprintf("set field %s offset %-2d size %-2d align %-2d",取_单词字符串(f->v & ~符号_字段, NULL), offset, size, align);如果 (f->type.t & VT_位域) {printf(" pos %-2d bits %-2d",BIT_POS(f->type.t),BIT_大小(f->type.t));}printf("\n");
#结束如果f->c = offset;f->r = 0;}如果 (pcc)c += (bit_pos + 7) >> 3;/* 存储 size and alignment */a = bt = ad->a.aligned ? 1 << (ad->a.aligned - 1) : 1;如果 (a < maxalign)a = maxalign;type->ref->r = a;如果 (pragma_pack && pragma_pack < maxalign && 0 == pcc) {/* can happen 如果 individual align 循环 some member was given.  Inthis 分支 MSVC ignores maxalign when aligning the size */a = pragma_pack;如果 (a < bt)a = bt;}c = (c + a - 1) & -a;type->ref->c = c;#如果已定义 BF_DEBUGprintf("结构体 size %-2d align %-2d\n\n", c, a), fflush(stdout);
#结束如果/* check whether we can access bitfields by their type */循环 (f = type->ref->next; f; f = f->next) {整数型 s, px, cx, c0;C类型 t;如果 (0 == (f->type.t & VT_位域))继续;f->type.ref = f;f->auxtype = -1;bit_size = BIT_大小(f->type.t);如果 (bit_size == 0)继续;bit_pos = BIT_POS(f->type.t);size = 类型_大小(&f->type, &align);如果 (bit_pos + bit_size <= size * 8 && f->c + size <= c)继续;/* try to access the field using a different type */c0 = -1, s = align = 1;t.t = VT_字节;循环 (;;) {px = f->c * 8 + bit_pos;cx = (px >> 3) & -align;px = px - (cx << 3);如果 (c0 == cx)跳出;s = (px + bit_size + 7) >> 3;如果 (s > 4) {t.t = VT_长长整数;} 否则 如果 (s > 2) {t.t = VT_整数;} 否则 如果 (s > 1) {t.t = VT_短整数;} 否则 {t.t = VT_字节;}s = 类型_大小(&t, &align);c0 = cx;}如果 (px + bit_size <= s * 8 && cx + s <= c) {/* update offset and bit position */f->c = cx;bit_pos = px;f->type.t = (f->type.t & ~(0x3f << VT_结构体_转换))| (bit_pos << VT_结构体_转换);如果 (s != size)f->auxtype = t.t;
#如果已定义 BF_DEBUGprintf("FIX field %s offset %-2d size %-2d align %-2d ""pos %-2d bits %-2d\n",取_单词字符串(f->v & ~符号_字段, NULL),cx, s, align, px, bit_size);
#结束如果} 否则 {/* fall back to 加载/存储 single-byte wise */f->auxtype = VT_结构体;
#如果已定义 BF_DEBUGprintf("FIX field %s : 加载 byte-wise\n",取_单词字符串(f->v & ~符号_字段, NULL));
#结束如果}}
}/* 枚举/结构体/共用体 声明. u is VT_枚举/VT_结构体/VT_共用体 */
静态 无类型 结构_声明(C类型 *type, 整数型 u)
{整数型 v, c, size, align, flexible;整数型 bit_size, bsize, bt;符号 *s, *ss, **ps;属性定义 ad, ad1;C类型 type1, btype;memset(&ad, 0, 取大小 ad);带有宏替换的下个标记();解析_属性(&ad);如果 (单词编码 != '{') {v = 单词编码;带有宏替换的下个标记();/* 结构体 already 已定义 ? 返回 it */如果 (v < 符_识别)应为("结构体/共用体/枚举 名称");s = 结构体_查询(v);如果 (s && (s->符号_范围 == 局部_范围 || 单词编码 != '{')) {如果 (u == s->type.t)去向 do_decl;如果 (u == VT_枚举 && 是_枚举(s->type.t))去向 do_decl;错误_打印("'%s'重新定义", 取_单词字符串(v, NULL));}} 否则 {v = 匿名符号索引++;}/* Record the original 枚举/结构体/共用体 标识符.  */type1.t = u == VT_枚举 ? u | VT_整数 | VT_无符号 : u;type1.ref = NULL;/* we put an undefined size 循环 结构体/共用体 */s = 符号_压入栈(v | 符号_结构体, &type1, 0, -1);s->r = 0; /* default alignment is zero as gcc */
do_decl:type->t = s->type.t;type->ref = s;如果 (单词编码 == '{') {带有宏替换的下个标记();如果 (s->c != -1)错误_打印("结构体/共用体/枚举 already 已定义");s->c = -2;/* cannot be empty *//* non empty enums are not allowed */ps = &s->next;如果 (u == VT_枚举) {long long ll = 0, pl = 0, nl = 0;C类型 t;t.ref = s;/* 枚举 symbols have 静态 storage */t.t = VT_整数|VT_静态|VT_枚举_变长;循环(;;) {v = 单词编码;如果 (v < 符_没识别)应为("identifier");ss = 符号_查询(v);如果 (ss && !局部符号_堆栈)错误_打印("redefinition of enumerator '%s'",取_单词字符串(v, NULL));带有宏替换的下个标记();如果 (单词编码 == '=') {带有宏替换的下个标记();ll = 表达式_常量64();}ss = 符号_压入栈(v, &t, VT_VC常量, 0);ss->enum_val = ll;*ps = ss, ps = &ss->next;如果 (ll < nl)nl = ll;如果 (ll > pl)pl = ll;如果 (单词编码 != ',')跳出;带有宏替换的下个标记();ll++;/* NOTE: we accept a trailing comma */如果 (单词编码 == '}')跳出;}跳过('}');/* set integral type of the 枚举 */t.t = VT_整数;如果 (nl >= 0) {如果 (pl != (无符号)pl)t.t = (LONG_SIZE==8 ? VT_长长整数|VT_长整数 : VT_长长整数);t.t |= VT_无符号;} 否则 如果 (pl != (整数型)pl || nl != (整数型)nl)t.t = (LONG_SIZE==8 ? VT_长长整数|VT_长整数 : VT_长长整数);s->type.t = type->t = t.t | VT_枚举;s->c = 0;/* set type 循环 枚举 members */循环 (ss = s->next; ss; ss = ss->next) {ll = ss->enum_val;如果 (ll == (整数型)ll) /* default is 整数型 如果 it fits */继续;如果 (t.t & VT_无符号) {ss->type.t |= VT_无符号;如果 (ll == (无符号)ll)继续;}ss->type.t = (ss->type.t & ~VT_基本类型)| (LONG_SIZE==8 ? VT_长长整数|VT_长整数 : VT_长长整数);}} 否则 {c = 0;flexible = 0;判断 (单词编码 != '}') {如果 (!解析_基本类型(&btype, &ad1)) {跳过(';');继续;}判断 (1) {如果 (flexible)错误_打印("flexible array member '%s' not at the end of 结构体",取_单词字符串(v, NULL));bit_size = -1;v = 0;type1 = btype;如果 (单词编码 != ':') {如果 (单词编码 != ';')类型_声明(&type1, &ad1, &v, 类型_直接);如果 (v == 0) {如果 ((type1.t & VT_基本类型) != VT_结构体)应为("identifier");否则 {整数型 v = btype.ref->v;如果 (!(v & 符号_字段) && (v & ~符号_结构体) < 符号_第一个_匿名) {如果 (zhi_状态->允许_匿名联合和结构 == 0)应为("identifier");}}}如果 (类型_大小(&type1, &align) < 0) {如果 ((u == VT_结构体) && (type1.t & VT_数组) && c)flexible = 1;否则错误_打印("field '%s' has incomplete type",取_单词字符串(v, NULL));}如果 ((type1.t & VT_基本类型) == VT_函数 ||(type1.t & VT_基本类型) == VT_无类型 ||(type1.t & VT_存储))错误_打印("invalid type 循环 '%s'", 取_单词字符串(v, NULL));}如果 (单词编码 == ':') {带有宏替换的下个标记();bit_size = 表达式_常量();/* XXX: handle v = 0 分支 循环 messages */如果 (bit_size < 0)错误_打印("negative width in bit-field '%s'", 取_单词字符串(v, NULL));如果 (v && bit_size == 0)错误_打印("zero width 循环 bit-field '%s'", 取_单词字符串(v, NULL));解析_属性(&ad1);}size = 类型_大小(&type1, &align);如果 (bit_size >= 0) {bt = type1.t & VT_基本类型;如果 (bt != VT_整数 && bt != VT_字节 && bt != VT_短整数 &&bt != VT_逻辑 &&bt != VT_长长整数)错误_打印("bitfields must have scalar type");bsize = size * 8;如果 (bit_size > bsize) {错误_打印("width of '%s' exceeds its type",取_单词字符串(v, NULL));} 否则 如果 (bit_size == bsize&& !ad.a.packed && !ad1.a.packed) {/* no need 循环 bit fields */;} 否则 如果 (bit_size == 64) {错误_打印("field width 64 not implemented");} 否则 {type1.t = (type1.t & ~VT_结构体_掩码)| VT_位域| (bit_size << (VT_结构体_转换 + 6));}}如果 (v != 0 || (type1.t & VT_基本类型) == VT_结构体) {/* Remember we've seen a real field to check循环 placement of flexible array member. */c = 1;}/* If member is a 结构体 or bit-field, enforceplacing into the 结构体 (as anonymous).  */如果 (v == 0 &&((type1.t & VT_基本类型) == VT_结构体 ||bit_size >= 0)) {v = 匿名符号索引++;}如果 (v) {ss = 符号_压入栈(v | 符号_字段, &type1, 0, 0);ss->a = ad1.a;*ps = ss;ps = &ss->next;}如果 (单词编码 == ';' || 单词编码 == 符_文件结尾)跳出;跳过(',');}跳过(';');}跳过('}');解析_属性(&ad);如果 (ad.cleanup_func) {zhi_警告("attribute '__cleanup__' ignored on type");}结构体_布局(type, &ad);}}
}静态 无类型 符号_的_属性(属性定义 *ad, 符号 *s)
{合并_符号属性(&ad->a, &s->a);合并_函数属性(&ad->f, &s->f);
}/*将类型限定符添加到类型。 如果类型是数组,则将限定符添加到元素类型,并进行复制,因为它可能是typedef。 */
静态 无类型 解析_基本类型_合规(C类型 *type, 整数型 qualifiers)
{判断 (type->t & VT_数组) {type->ref = 符号_压入栈(符号_字段, &type->ref->type, 0, type->ref->c);type = &type->ref->type;}type->t |= qualifiers;
}/* 如果没有类型声明,则返回0。 否则,返回基本类型并跳过它。*/
静态 整数型 解析_基本类型(C类型 *type, 属性定义 *ad)
{整数型 t, u, bt, st, type_found, typespec_found, g, n;符号 *s;C类型 type1;memset(ad, 0, 取大小(属性定义));type_found = 0;typespec_found = 0;t = VT_整数;bt = st = -1;type->ref = NULL;判断(1) {选择(单词编码) {分支 关键字_EXTENSION:/* currently, we really ignore extension */带有宏替换的下个标记();继续;/* basic types */分支 关键字_CHAR:分支 关键字_字符型:u = VT_字节;basic_type:带有宏替换的下个标记();basic_type1:如果 (u == VT_短整数 || u == VT_长整数) {如果 (st != -1 || (bt != -1 && bt != VT_整数))tmbt: 错误_打印("too many basic types");st = u;} 否则 {如果 (bt != -1 || (st != -1 && u != VT_整数))去向 tmbt;bt = u;}如果 (u != VT_整数)t = (t & ~(VT_基本类型|VT_长整数)) | u;typespec_found = 1;跳出;分支 关键字_VOID:分支 关键字_无类型:u = VT_无类型;去向 basic_type;分支 关键字_SHORT:分支 关键字_短整数型:u = VT_短整数;去向 basic_type;分支 关键字_INT:分支 关键字_整数型:u = VT_整数;去向 basic_type;分支 关键字_ALIGNAS:{ 整数型 n;属性定义 ad1;带有宏替换的下个标记();跳过('(');memset(&ad1, 0, 取大小(属性定义));如果 (解析_基本类型(&type1, &ad1)) {类型_声明(&type1, &ad1, &n, 类型_抽象);如果 (ad1.a.aligned)n = 1 << (ad1.a.aligned - 1);否则类型_大小(&type1, &n);} 否则 {n = 表达式_常量();如果 (n <= 0 || (n & (n - 1)) != 0)错误_打印("对齐方式必须是两个的正幂");}跳过(')');ad->a.aligned = 精确_对数2p1(n);}继续;分支 关键字_LONG:分支 关键字_长整数型:如果 ((t & VT_基本类型) == VT_双精度) {t = (t & ~(VT_基本类型|VT_长整数)) | VT_长双精度;} 否则 如果 ((t & (VT_基本类型|VT_长整数)) == VT_长整数) {t = (t & ~(VT_基本类型|VT_长整数)) | VT_长长整数;} 否则 {u = VT_长整数;去向 basic_type;}带有宏替换的下个标记();跳出;
#如果已定义 ZHI_TARGET_ARM64分支 关键字_UINT128:分支 关键字_无整128:/* GCC的__uint128_t出现在某些Linux标头文件数中。 使它成为long double的代名词,以获取正确的大小和对齐方式。 */u = VT_长双精度;去向 basic_type;
#结束如果分支 关键字_BOOL:分支 关键字_逻辑型:u = VT_逻辑;去向 basic_type;分支 关键字_FLOAT:分支 关键字_浮点型:u = VT_浮点;去向 basic_type;分支 关键字_DOUBLE:分支 关键字_双精度浮点型:如果 ((t & (VT_基本类型|VT_长整数)) == VT_长整数) {t = (t & ~(VT_基本类型|VT_长整数)) | VT_长双精度;} 否则 {u = VT_双精度;去向 basic_type;}带有宏替换的下个标记();跳出;分支 关键字_ENUM:分支 关键字_枚举:结构_声明(&type1, VT_枚举);basic_type2:u = type1.t;type->ref = type1.ref;去向 basic_type1;分支 关键字_STRUCT:分支 关键字_结构体:结构_声明(&type1, VT_结构体);去向 basic_type2;分支 关键字_UNION:分支 关键字_共用体:结构_声明(&type1, VT_共用体);去向 basic_type2;/* type modifiers */分支 关键字_CONST1:分支 关键字_CONST2:分支 关键字_CONST3:分支 关键字_常量:type->t = t;解析_基本类型_合规(type, VT_常量);t = type->t;带有宏替换的下个标记();跳出;分支 关键字_VOLATILE1:分支 关键字_VOLATILE2:分支 关键字_VOLATILE3:分支 关键字_易变:type->t = t;解析_基本类型_合规(type, VT_易变);t = type->t;带有宏替换的下个标记();跳出;分支 关键字_SIGNED1:分支 关键字_SIGNED2:分支 关键字_SIGNED3:分支 关键字_有符号:如果 ((t & (VT_显式符号|VT_无符号)) == (VT_显式符号|VT_无符号))错误_打印("有符号和无符号修饰符");t |= VT_显式符号;带有宏替换的下个标记();typespec_found = 1;跳出;分支 关键字_REGISTER:分支 关键字_寄存器:分支 关键字_AUTO:分支 关键字_自动:分支 关键字_RESTRICT1:分支 关键字_RESTRICT2:分支 关键字_RESTRICT3:分支 关键字_限定:带有宏替换的下个标记();跳出;分支 关键字_UNSIGNED:分支 关键字_无符号:如果 ((t & (VT_显式符号|VT_无符号)) == VT_显式符号)错误_打印("有符号和无符号修饰符");t |= VT_显式符号 | VT_无符号;带有宏替换的下个标记();typespec_found = 1;跳出;/* 存储 */分支 关键字_EXTERN:分支 关键字_外部:g = VT_外部;去向 storage;分支 关键字_STATIC:分支 关键字_静态:g = VT_静态;去向 storage;分支 关键字_TYPEDEF:分支 关键字_别名:g = VT_别名;去向 storage;storage:如果 (t & (VT_外部|VT_静态|VT_别名) & ~g)错误_打印("多个存储类别");t |= g;带有宏替换的下个标记();跳出;分支 关键字_INLINE1:分支 关键字_INLINE2:分支 关键字_INLINE3:分支 关键字_内联:t |= VT_内联;带有宏替换的下个标记();跳出;分支 符_NORETURN3:带有宏替换的下个标记();ad->f.func_noreturn = 1;跳出;/* GNUC属性 */分支 关键字_ATTRIBUTE1:分支 关键字_ATTRIBUTE2:分支 关键字_属性:解析_属性(ad);如果 (ad->attr_mode) {u = ad->attr_mode -1;t = (t & ~(VT_基本类型|VT_长整数)) | u;}继续;/* GNUC类型 */分支 关键字_TYPEOF1:分支 关键字_TYPEOF2:分支 关键字_TYPEOF3:分支 关键字_取类型:带有宏替换的下个标记();解析_表达式_类型(&type1);/* 删除除typedef外的所有存储修饰符 */type1.t &= ~(VT_存储&~VT_别名);如果 (type1.ref)符号_的_属性(ad, type1.ref);去向 basic_type2;default:如果 (typespec_found)去向 the_end;s = 符号_查询(单词编码);如果 (!s || !(s->type.t & VT_别名))去向 the_end;n = 单词编码, 带有宏替换的下个标记();如果 (单词编码 == ':' && !in_通用) {/* 忽略是否是标签 */设为_指定标识符(n);去向 the_end;}t &= ~(VT_基本类型|VT_长整数);u = t & ~(VT_常量 | VT_易变), t ^= u;type->t = (s->type.t & ~VT_别名) | u;type->ref = s->type.ref;如果 (t)解析_基本类型_合规(type, t);t = type->t;/* 从typedef获取属性 */符号_的_属性(ad, s);typespec_found = 1;st = bt = -2;跳出;}type_found = 1;}
the_end:如果 (zhi_状态->字符串_无符号) {如果 ((t & (VT_显式符号|VT_基本类型)) == VT_字节)t |= VT_无符号;}/* VT_LONG仅用作VT_INT / VT_LLONG的修饰符 */bt = t & (VT_基本类型|VT_长整数);如果 (bt == VT_长整数)t |= LONG_SIZE == 8 ? VT_长长整数 : VT_整数;
#如果已定义 ZHI_TARGET_PE如果 (bt == VT_长双精度)t = (t & ~(VT_基本类型|VT_长整数)) | (VT_双精度|VT_长整数);
#结束如果type->t = t;返回 type_found;
}/* 转换函数参数类型(数组到指针,函数到函数指针) */
静态 内联 无类型 转换_函数参数_类型(C类型 *pt)
{/* 删除const和volatile限定词(XXX:const可用于指示const函数参数 */pt->t &= ~(VT_常量 | VT_易变);/* 数组必须根据ANSI C转换为指针*/pt->t &= ~VT_数组;如果 ((pt->t & VT_基本类型) == VT_函数) {修改类型_指针类型(pt);}
}静态_函数 无类型 解析_汇编_字符串(动态字符串 *astr)
{跳过('(');解析_多_字符串(astr, "字符串常量");
}/* 解析一个汇编标签并返回标识符 */
静态 整数型 在字符串_查找_汇编标签并解析(无类型)
{整数型 v;动态字符串 astr;带有宏替换的下个标记();解析_汇编_字符串(&astr);跳过(')');
#如果已定义 ASM_DEBUGprintf("汇编_alias: \"%s\"\n", (字符型 *)astr.指向字符串的指针);
#结束如果v = 单词表_查找(astr.指向字符串的指针, astr.字符串长度 - 1)->单词编码;动态字符串_释放(&astr);返回 v;
}静态 整数型 post_函数类型(C类型 *type, 属性定义 *ad, 整数型 storage, 整数型 td)
{整数型 n, l, t1, arg_size, align, unused_align;符号 **plast, *s, *first;属性定义 ad1;C类型 pt;如果 (单词编码 == '(') {/* 函数类型或递归声明符(如果是,则返回) */带有宏替换的下个标记();如果 (td && !(td & 类型_抽象))返回 0;如果 (单词编码 == ')')l = 0;否则 如果 (解析_基本类型(&pt, &ad1))l = 函数_新;否则 如果 (td) {合并_属性 (ad, &ad1);返回 0;} 否则l = 函数_旧;first = NULL;plast = &first;arg_size = 0;如果 (l) {循环(;;) {/* 读取参数名称并计算偏移量 */如果 (l != 函数_旧) {如果 ((pt.t & VT_基本类型) == VT_无类型 && 单词编码 == ')')跳出;类型_声明(&pt, &ad1, &n, 类型_直接 | 类型_抽象);如果 ((pt.t & VT_基本类型) == VT_无类型)错误_打印("参数声明为void");} 否则 {n = 单词编码;如果 (n < 符_没识别)应为("identifier");pt.t = VT_无类型; /* 无效的类型 */pt.ref = NULL;带有宏替换的下个标记();}转换_函数参数_类型(&pt);arg_size += (类型_大小(&pt, &align) + 指针_大小 - 1) / 指针_大小;s = 符号_压入栈(n | 符号_字段, &pt, 0, 0);*plast = s;plast = &s->next;如果 (单词编码 == ')')跳出;跳过(',');如果 (l == 函数_新 && 单词编码 == 符_三个圆点) {l = 函数_省略;带有宏替换的下个标记();跳出;}如果 (l == 函数_新 && !解析_基本类型(&pt, &ad1))错误_打印("无效的类型");}} 否则/* 如果没有参数,则使用旧型原型 */l = 函数_旧;跳过(')');/* NOTE: 常量 is ignored in returned type as it has a specialmeaning in gcc / C++ */type->t &= ~VT_常量; /* some ancient pre-K&R C allows a function to 返回 an arrayand the array brackets to be put after the arguments, such that "整数型 c()[]" means something like "整数型[] c()" */如果 (单词编码 == '[') {带有宏替换的下个标记();跳过(']'); /* only handle simple "[]" */修改类型_指针类型(type);}/* we push a anonymous symbol which will contain the function prototype */ad->f.func_args = arg_size;ad->f.func_type = l;s = 符号_压入栈(符号_字段, type, 0, 0);s->a = ad->a;s->f = ad->f;s->next = first;type->t = VT_函数;type->ref = s;} 否则 如果 (单词编码 == '[') {整数型 saved_nocode_wanted = 不需要_代码生成;/* array definition */带有宏替换的下个标记();判断 (1) {/* XXX The optional type-quals and 静态 should only be acceptedin parameter decls.  The '*' as well, and then even onlyin prototypes (not function defs).  */选择 (单词编码) {分支 关键字_RESTRICT1: 分支 关键字_RESTRICT2: 分支 关键字_RESTRICT3: 分支 关键字_限定:分支 关键字_CONST1:分支 关键字_常量:分支 关键字_VOLATILE1:分支 关键字_易变:分支 关键字_STATIC:分支 '*':带有宏替换的下个标记();继续;default:跳出;}跳出;}n = -1;t1 = 0;如果 (单词编码 != ']') {如果 (!局部符号_堆栈 || (storage & VT_静态))压入整数常量(表达式_常量());否则 {/* VLAs (which can only happen with 局部符号_堆栈 && !VT_静态)length must always be evaluated, even under 不需要_代码生成,so that its size slot is initialized (e.g. under 取大小or typeof).  */不需要_代码生成 = 0;通用表达式();}如果 ((栈顶值->r & (VT_值掩码 | VT_LVAL | VT_符号)) == VT_VC常量) {n = 栈顶值->c.i;如果 (n < 0)错误_打印("invalid array size");} 否则 {如果 (!是_整数_型(栈顶值->type.t & VT_基本类型))错误_打印("size of variable length array should be an integer");n = 0;t1 = VT_变长数组;}}跳过(']');/* parse next post type */post_函数类型(type, ad, storage, 0);如果 ((type->t & VT_基本类型) == VT_函数)错误_打印("declaration of an array of functions");如果 ((type->t & VT_基本类型) == VT_无类型|| 类型_大小(type, &unused_align) < 0)错误_打印("declaration of an array of incomplete type elements");t1 |= type->t & VT_变长数组;如果 (t1 & VT_变长数组) {如果 (n < 0)错误_打印("need explicit inner array size in VLAs");局部变量索引 -= 类型_大小(&int_type, &align);局部变量索引 &= -align;n = 局部变量索引;vla_运行时_类型_大小(type, &align);通用_操作('*');vset(&int_type, VT_LOCAL|VT_LVAL, n);vswap();将栈顶值_存储在堆栈左值();}如果 (n != -1)弹出堆栈值();不需要_代码生成 = saved_nocode_wanted;/* we push an anonymous symbol which will contain the arrayelement type */s = 符号_压入栈(符号_字段, type, 0, n);type->t = (t1 ? VT_变长数组 : VT_数组) | VT_指针;type->ref = s;}返回 1;
}/* 解析类型声明符(基本类型除外),并以'type'返回类型。 'td'是一个位掩码,指示需要哪种类型的声明。*  “类型”应包含基本类型。 “ ad”是基本类型的属性定义。 可以通过类型_声明()进行修改。*  如果此(可能是抽象的)声明符是一个指针链,则它返回指向类型的最里面的指针(等于* type,但是是一个不同的指针),*  否则返回类型本身,该类型用于递归调用。  */
静态 C类型 *类型_声明(C类型 *type, 属性定义 *ad, 整数型 *v, 整数型 td)
{C类型 *post, *ret;整数型 qualifiers, storage;/* 递归类型,先删除存储位,然后再应用*/storage = type->t & VT_存储;type->t &= ~VT_存储;post = ret = type;判断 (单词编码 == '*') {qualifiers = 0;redo:带有宏替换的下个标记();选择(单词编码) {分支 关键字_CONST1:分支 关键字_CONST2:分支 关键字_CONST3:分支 关键字_常量:qualifiers |= VT_常量;去向 redo;分支 关键字_VOLATILE1:分支 关键字_VOLATILE2:分支 关键字_VOLATILE3:分支 关键字_易变:qualifiers |= VT_易变;去向 redo;分支 关键字_RESTRICT1:分支 关键字_RESTRICT2:分支 关键字_RESTRICT3:分支 关键字_限定:去向 redo;/* XXX: clarify attribute handling */分支 关键字_ATTRIBUTE1:分支 关键字_ATTRIBUTE2:分支 关键字_属性:解析_属性(ad);跳出;}修改类型_指针类型(type);type->t |= qualifiers;如果 (ret == type)/* innermost pointed to type is the one 循环 the first derivation */ret = 指定的_类型(type);}如果 (单词编码 == '(') {/* This is possibly a parameter type list 循环 abstract declarators('整数型 ()'), use post_函数类型 循环 testing this.  */如果 (!post_函数类型(type, ad, 0, td)) {/* It's not, so it's a nested declarator, and the post operationsapply to the innermost pointed to type (如果 any).  *//* XXX: this is not correct to modify 'ad' at this point, butthe syntax is not clear */解析_属性(ad);post = 类型_声明(type, ad, v, td);跳过(')');} 否则去向 abstract;} 否则 如果 (单词编码 >= 符_识别 && (td & 类型_直接)) {/* type identifier */*v = 单词编码;带有宏替换的下个标记();} 否则 {abstract:如果 (!(td & 类型_抽象))应为("identifier");*v = 0;}post_函数类型(post, ad, storage, 0);解析_属性(ad);type->t |= storage;返回 ret;
}/* 完全错误检查和绑定检查的间接访问 */
静态_函数 无类型 间接的(无类型)
{如果 ((栈顶值->type.t & VT_基本类型) != VT_指针) {如果 ((栈顶值->type.t & VT_基本类型) == VT_函数)返回;应为("pointer");}如果 (栈顶值->r & VT_LVAL)将rc寄存器值存储在栈顶值中(寄存器类_整数);栈顶值->type = *指定的_类型(&栈顶值->type);/* Arrays and functions are never lvalues */如果 (!(栈顶值->type.t & (VT_数组| VT_变长数组))&& (栈顶值->type.t & VT_基本类型) != VT_函数) {栈顶值->r |= VT_LVAL;/* 如果 bound checking, the referenced pointer must be checked */
#如果已定义 配置_ZHI_边界检查如果 (zhi_状态->执行_边界_检查器)栈顶值->r |= VT_强制边界检查;
#结束如果}
}/* 将参数传递给函数并进行类型检查和转换 */
静态 无类型 参数传给函数_并进行类型检查和转换(符号 *func, 符号 *arg)
{整数型 func_type;C类型 type;func_type = func->f.func_type;如果 (func_type == 函数_旧 ||(func_type == 函数_省略 && arg == NULL)) {/* default casting : only need to convert float to double */如果 ((栈顶值->type.t & VT_基本类型) == VT_浮点) {通用_转换_s(VT_双精度);} 否则 如果 (栈顶值->type.t & VT_位域) {type.t = 栈顶值->type.t & (VT_基本类型 | VT_无符号);type.ref = 栈顶值->type.ref;通用_转换(&type);} 否则 如果 (栈顶值->r & VT_强制转换) {强制_字符型短整型_转换();}} 否则 如果 (arg == NULL) {错误_打印("too many arguments to function");} 否则 {type = arg->type;type.t &= ~VT_常量; /* need to 执行 that to avoid false warning */通用_指定类型_转换(&type);}
}/*解析表达式并返回其类型,而没有任何副作用。 */
静态 无类型 解析表达式_返回类型(C类型 *type, 无类型 (*expr_fn)(无类型))
{不需要_代码生成++;expr_fn();*type = 栈顶值->type;弹出堆栈值();不需要_代码生成--;
}/* 解析类型为'(type)'或'(expr)'的表达式并返回其类型 */
静态 无类型 解析_表达式_类型(C类型 *type)
{整数型 n;属性定义 ad;跳过('(');如果 (解析_基本类型(type, &ad)) {类型_声明(type, &ad, &n, 类型_抽象);} 否则 {解析表达式_返回类型(type, 通用表达式);}跳过(')');
}静态 无类型 解析_指定类型(C类型 *type)
{属性定义 ad;整数型 n;如果 (!解析_基本类型(type, &ad)) {应为("type");}类型_声明(type, &ad, &n, 类型_抽象);
}静态 无类型 解析_内置_参数(整数型 nc, 常量 字符型 *args)
{字符型 c, sep = '(';C类型 t;如果 (nc)不需要_代码生成++;带有宏替换的下个标记();判断 ((c = *args++)) {跳过(sep);sep = ',';选择 (c) {分支 'e': 等于_表达式(); 继续;分支 't': 解析_指定类型(&t); 压入指定类型常量(&t); 继续;default: 错误_打印("internal error"); 跳出;}}跳过(')');如果 (nc)不需要_代码生成--;
}静态_函数 无类型 一元(无类型)
{整数型 n, t, align, size, r, sizeof_caller;C类型 type;符号 *s;属性定义 ad;/* 生成行号信息 */如果 (zhi_状态->执行_调试)zhi_调试_行(zhi_状态);sizeof_caller = in_大小;in_大小 = 0;type.ref = NULL;/* XXX: GCC 2.95.3不会生成表,尽管这里应该更好 */tok_next:选择(单词编码) {分支 关键字_EXTENSION:带有宏替换的下个标记();去向 tok_next;分支 常量_长字符型:
#如果已定义 ZHI_TARGET_PEt = VT_短整数|VT_无符号;去向 push_tokc;
#结束如果分支 常量_整数:分支 常量_字符型: t = VT_整数;push_tokc:type.t = t;vsetc(&type, VT_VC常量, &单词值);带有宏替换的下个标记();跳出;分支 常量_无符整数:t = VT_整数 | VT_无符号;去向 push_tokc;分支 常量_长长整数:t = VT_长长整数;去向 push_tokc;分支 常量_无符长长整数:t = VT_长长整数 | VT_无符号;去向 push_tokc;分支 常量_浮点型:t = VT_浮点;去向 push_tokc;分支 常量_双精度:t = VT_双精度;去向 push_tokc;分支 常量_长双精度:t = VT_长双精度;去向 push_tokc;分支 常量_长整数:t = (LONG_SIZE == 8 ? VT_长长整数 : VT_整数) | VT_长整数;去向 push_tokc;分支 常量_无符长整数:t = (LONG_SIZE == 8 ? VT_长长整数 : VT_整数) | VT_长整数 | VT_无符号;去向 push_tokc;分支 符___FUNCTION__:分支 符___FUNCTION___CN:如果 (!gnu_扩展)去向 标识符_识别ifier;/* fall thru */分支 符___函数__:分支 符___函数___CN:{无类型 *ptr;整数型 len;/* special function name identifier */len = strlen(函数名称) + 1;/* generate 字符型[len] type */type.t = VT_字节;修改类型_指针类型(&type);type.t |= VT_数组;type.ref->c = len;将引用_推送到_节偏移量(&type, 初始化数据_部分, 初始化数据_部分->数据_偏移, len);如果 (!不需要_静态数据输出) {ptr = 段_ptr_添加(初始化数据_部分, len);memcpy(ptr, 函数名称, len);}带有宏替换的下个标记();}跳出;分支 常量_长字符串:
#如果已定义 ZHI_TARGET_PEt = VT_短整数 | VT_无符号;
#否则t = VT_整数;
#结束如果去向 str_init;分支 常量_字符串:/* string parsing */t = VT_字节;如果 (zhi_状态->字符串_无符号)t = VT_字节 | VT_无符号;str_init:如果 (zhi_状态->警告_写字符串)t |= VT_常量;type.t = t;修改类型_指针类型(&type);type.t |= VT_数组;memset(&ad, 0, 取大小(属性定义));声明_初始化_分配(&type, &ad, VT_VC常量, 2, 0, 0);跳出;分支 '(':带有宏替换的下个标记();/* cast ? */如果 (解析_基本类型(&type, &ad)) {类型_声明(&type, &ad, &n, 类型_抽象);跳过(')');/* check ISOC99 compound literal */如果 (单词编码 == '{') {/* data is allocated locally by default */如果 (全局_分配复合字符)r = VT_VC常量;否则r = VT_LOCAL;/* all except arrays are lvalues */如果 (!(type.t & VT_数组))r |= VT_LVAL;memset(&ad, 0, 取大小(属性定义));声明_初始化_分配(&type, &ad, r, 1, 0, 0);} 否则 {如果 (sizeof_caller) {压入指定类型常量(&type);返回;}一元();通用_转换(&type);}} 否则 如果 (单词编码 == '{') {整数型 saved_nocode_wanted = 不需要_代码生成;如果 (需要_常量 && !(不需要_代码生成 & 未评估的子表达式))错误_打印("expected constant");/* save all registers */保存_寄存器最多n个堆栈条目(0);/* statement expression : we 执行 not accept 跳出/继续inside as GCC does.  We 执行 retain the 不需要_代码生成 state,as statement expressions can't ever be entered from theoutside, so any reactivation of code emission (from labelsor loop heads) can be disabled again after the end of it. */块(1);不需要_代码生成 = saved_nocode_wanted;跳过(')');} 否则 {通用表达式();跳过(')');}跳出;分支 '*':带有宏替换的下个标记();一元();间接的();跳出;分支 '&':带有宏替换的下个标记();一元();/* functions names must be treated as function pointers,except 循环 一元 '&' and 取大小. Since we consider thatfunctions are not lvalues, we only have to handle itthere and in function calls. *//* arrays can also be used although they are not lvalues */如果 ((栈顶值->type.t & VT_基本类型) != VT_函数 &&!(栈顶值->type.t & VT_数组))测试_左值();如果 (栈顶值->sym)栈顶值->sym->a.addrtaken = 1;修改类型_指针类型(&栈顶值->type);获取栈顶值地址();跳出;分支 '!':带有宏替换的下个标记();一元();生成_测试_零(双符号_等于);跳出;分支 '~':带有宏替换的下个标记();一元();压入整数常量(-1);通用_操作('^');跳出;分支 '+':带有宏替换的下个标记();一元();如果 ((栈顶值->type.t & VT_基本类型) == VT_指针)错误_打印("pointer not accepted 循环 一元 plus");/* In order to force cast, we add zero, except 循环 floating pointwhere we really need an noop (otherwise -0.0 will be transformedinto +0.0).  */如果 (!是_浮点型(栈顶值->type.t)) {压入整数常量(0);通用_操作('+');}跳出;分支 关键字_SIZEOF:分支 关键字_获取大小:分支 关键字_ALIGNOF1:分支 关键字_ALIGNOF2:分支 关键字_ALIGNOF3:分支 关键字_对齐:t = 单词编码;带有宏替换的下个标记();in_大小++;解析表达式_返回类型(&type, 一元); /* Perform a in_大小 = 0; */s = NULL;如果 (栈顶值[1].r & VT_符号)s = 栈顶值[1].sym; /* hack: accessing previous 栈顶值 */size = 类型_大小(&type, &align);如果 (s && s->a.aligned)align = 1 << (s->a.aligned - 1);如果 (t == 关键字_SIZEOF || t == 关键字_获取大小) {如果 (!(type.t & VT_变长数组)) {如果 (size < 0)错误_打印("取大小 applied to an incomplete type");压入目标地址类型常量(size);} 否则 {vla_运行时_类型_大小(&type, &align);}} 否则 {压入目标地址类型常量(align);}栈顶值->type.t |= VT_无符号;跳出;分支 符_builtin_expect:/* __builtin_expect is a no-op 循环 now */解析_内置_参数(0, "ee");弹出堆栈值();跳出;分支 符_builtin_types_compatible_p:解析_内置_参数(0, "tt");栈顶值[-1].type.t &= ~(VT_常量 | VT_易变);栈顶值[0].type.t &= ~(VT_常量 | VT_易变);n = 是_兼容_类型(&栈顶值[-1].type, &栈顶值[0].type);栈顶值 -= 2;压入整数常量(n);跳出;分支 符_builtin_choose_expr:{int64_t c;带有宏替换的下个标记();跳过('(');c = 表达式_常量64();跳过(',');如果 (!c) {不需要_代码生成++;}等于_表达式();如果 (!c) {弹出堆栈值();不需要_代码生成--;}跳过(',');如果 (c) {不需要_代码生成++;}等于_表达式();如果 (c) {弹出堆栈值();不需要_代码生成--;}跳过(')');}跳出;分支 符_builtin_constant_p:解析_内置_参数(1, "e");n = (栈顶值->r & (VT_值掩码 | VT_LVAL | VT_符号)) == VT_VC常量;栈顶值--;压入整数常量(n);跳出;分支 符_builtin_frame_address:分支 符_builtin_return_address:{整数型 tok1 = 单词编码;整数型 level;带有宏替换的下个标记();跳过('(');如果 (单词编码 != 常量_整数) {错误_打印("%s 只接受正整数",tok1 == 符_builtin_return_address ?"__builtin_return_address" :"__builtin_frame_address");}level = (uint32_t)单词值.i;带有宏替换的下个标记();跳过(')');type.t = VT_无类型;修改类型_指针类型(&type);vset(&type, VT_LOCAL, 0);       /* 局部框架 */判断 (level--) {#如果已定义 ZHI_TARGET_RISCV64压入整数常量(2*指针_大小);通用_操作('-');
#结束如果修改类型_指针类型(&栈顶值->type);间接的();                    /* -> 父框架 */}如果 (tok1 == 符_builtin_return_address) {// 假定返回地址刚好在堆栈上的帧指针上方
#如果已定义 ZHI_TARGET_ARM压入整数常量(2*指针_大小);通用_操作('+');
#否则如果 已定义 ZHI_TARGET_RISCV64压入整数常量(指针_大小);通用_操作('-');
#否则压入整数常量(指针_大小);通用_操作('+');
#结束如果修改类型_指针类型(&栈顶值->type);间接的();}}跳出;
#如果已定义 ZHI_TARGET_RISCV64分支 符_builtin_va_start:解析_内置_参数(0, "ee");r = 栈顶值->r & VT_值掩码;如果 (r == VT_LLOCAL)r = VT_LOCAL;如果 (r != VT_LOCAL)错误_打印("__builtin_va_start expects a local variable");生成_va_开始();将栈顶值_存储在堆栈左值();跳出;
#结束如果
#如果已定义 ZHI_TARGET_X86_64
#如果已定义 ZHI_TARGET_PE分支 符_builtin_va_start:解析_内置_参数(0, "ee");r = 栈顶值->r & VT_值掩码;如果 (r == VT_LLOCAL)r = VT_LOCAL;如果 (r != VT_LOCAL)错误_打印("__builtin_va_start expects a local variable");栈顶值->r = r;栈顶值->type = 字符_指针_类型;栈顶值->c.i += 8;将栈顶值_存储在堆栈左值();跳出;
#否则分支 符_builtin_va_arg_types:解析_内置_参数(0, "t");压入整数常量(分类_x86_64_va_arg(&栈顶值->type));vswap();弹出堆栈值();跳出;
#结束如果
#结束如果#如果已定义 ZHI_TARGET_ARM64分支 符_builtin_va_start: {解析_内置_参数(0, "ee");//xx check types生成_va_开始();压入整数常量(0);栈顶值->type.t = VT_无类型;跳出;}分支 符_builtin_va_arg: {解析_内置_参数(0, "et");type = 栈顶值->type;弹出堆栈值();//xx check types生成_va_参数(&type);栈顶值->type = type;跳出;}分支 符___arm64_clear_cache: {解析_内置_参数(0, "ee");生成_清理_缓存();压入整数常量(0);栈顶值->type.t = VT_无类型;跳出;}
#结束如果/* pre operations */分支 双符号_自加1:分支 双符号_自减1:t = 单词编码;带有宏替换的下个标记();一元();inc(0, t);跳出;分支 '-':带有宏替换的下个标记();一元();t = 栈顶值->type.t & VT_基本类型;如果 (是_浮点型(t)) {/* In IEEE negate(x) isn't subtract(0,x), but rathersubtract(-0, x).  */压入指定类型常量(&栈顶值->type);如果 (t == VT_浮点)栈顶值->c.f = -1.0 * 0.0;否则 如果 (t == VT_双精度)栈顶值->c.d = -1.0 * 0.0;否则栈顶值->c.ld = -1.0 * 0.0;} 否则压入整数常量(0);vswap();通用_操作('-');跳出;分支 双符号_逻辑与:如果 (!gnu_扩展)去向 标识符_识别ifier;带有宏替换的下个标记();/* allow to take the address of a label */如果 (单词编码 < 符_没识别)应为("label identifier");s = 标签_查找(单词编码);如果 (!s) {s = 标签_推送(&全局符号_标签_堆栈, 单词编码, 标签_正向定义);} 否则 {如果 (s->r == 标签_被声明)s->r = 标签_正向定义;}如果 (!s->type.t) {s->type.t = VT_无类型;修改类型_指针类型(&s->type);s->type.t |= VT_静态;}压入符号值(&s->type, s);带有宏替换的下个标记();跳出;分支 关键字_GENERIC:{C类型 controlling_type;整数型 has_default = 0;整数型 has_match = 0;整数型 learn = 0;单词字符串 *str = NULL;整数型 saved_const_wanted = 需要_常量;带有宏替换的下个标记();跳过('(');需要_常量 = 0;解析表达式_返回类型(&controlling_type, 等于_表达式);controlling_type.t &= ~(VT_常量 | VT_易变 | VT_数组);如果 ((controlling_type.t & VT_基本类型) == VT_函数)修改类型_指针类型(&controlling_type);需要_常量 = saved_const_wanted;循环 (;;) {learn = 0;跳过(',');如果 (单词编码 == 关键字_DEFAULT || 单词编码 == 关键字_默认) {如果 (has_default)错误_打印("太多的‘默认’");has_default = 1;如果 (!has_match)learn = 1;带有宏替换的下个标记();} 否则 {属性定义 ad_tmp;整数型 itmp;C类型 cur_type;in_通用++;解析_基本类型(&cur_type, &ad_tmp);in_通用--;类型_声明(&cur_type, &ad_tmp, &itmp, 类型_抽象);如果 (比较_2个类型(&controlling_type, &cur_type, 0)) {如果 (has_match) {错误_打印("类型匹配两次");}has_match = 1;learn = 1;}}跳过(':');如果 (learn) {如果 (str)单词字符串_释放(str);跳过_或_保存_块(&str);} 否则 {跳过_或_保存_块(NULL);}如果 (单词编码 == ')')跳出;}如果 (!str) {字符型 buf[60];字符串_的_类型(buf, 取大小 buf, &controlling_type, NULL);错误_打印("类型 '%s' 与任何关联都不匹配", buf);}开始_宏(str, 1);带有宏替换的下个标记();等于_表达式();如果 (单词编码 != 符_文件结尾)应为(",");结束_宏();带有宏替换的下个标记();跳出;}// special qnan , snan and infinity values分支 符___NAN__:n = 0x7fc00000;
special_math_val:压入整数常量(n);栈顶值->type.t = VT_浮点;带有宏替换的下个标记();跳出;分支 符___SNAN__:n = 0x7f800001;去向 special_math_val;分支 符___INF__:n = 0x7f800000;去向 special_math_val;default:标识符_识别ifier:t = 单词编码;带有宏替换的下个标记();如果 (t < 符_没识别)应为("identifier");s = 符号_查询(t);如果 (!s || 是_汇编_符号(s)) {常量 字符型 *name = 取_单词字符串(t, NULL);如果 (单词编码 != '(')错误_打印("'%s' 未声明", name);/* 循环 simple function calls, we tolerate undeclaredexternal reference to 整数型() function */如果 (zhi_状态->警告_隐式函数声明
#如果已定义 ZHI_TARGET_PE/* people must be warned about using undeclared WINAPI functions(which usually start with uppercase letter) */|| (name[0] >= 'A' && name[0] <= 'Z')
#结束如果)zhi_警告("函数 '%s'是隐式声明", name);s = 外部_全局_符号(t, &函数_旧_类型);}r = s->r;/* A symbol that has a register is a local register variable,which starts out as VT_LOCAL value.  */如果 ((r & VT_值掩码) < VT_VC常量)r = (r & ~VT_值掩码) | VT_LOCAL;vset(&s->type, r, s->c);/* Point to s as backpointer (even without r&VT_符号).Will be used by at least the x86 内联 asm parser 循环regvars.  */栈顶值->sym = s;如果 (r & VT_符号) {栈顶值->c.i = 0;} 否则 如果 (r == VT_VC常量 && 是_枚举_变长(s->type.t)) {栈顶值->c.i = s->enum_val;}跳出;}/* post operations */判断 (1) {如果 (单词编码 == 双符号_自加1 || 单词编码 == 双符号_自减1) {inc(1, 单词编码);带有宏替换的下个标记();} 否则 如果 (单词编码 == '.' || 单词编码 == 双符号_结构体指针运算符 || 单词编码 == 常量_双精度) {整数型 qualifiers, cumofs = 0;/* field */ 如果 (单词编码 == 双符号_结构体指针运算符) 间接的();qualifiers = 栈顶值->type.t & (VT_常量 | VT_易变);测试_左值();获取栈顶值地址();/* 应为 pointer on structure */如果 ((栈顶值->type.t & VT_基本类型) != VT_结构体)应为("结构体 or 共用体");如果 (单词编码 == 常量_双精度)应为("field name");带有宏替换的下个标记();如果 (单词编码 == 常量_整数 || 单词编码 == 常量_无符整数)应为("field name");s = 查找_域(&栈顶值->type, 单词编码, &cumofs);如果 (!s)错误_打印("找不到字段: %s",  取_单词字符串(单词编码 & ~符号_字段, &单词值));/* add field offset to pointer */栈顶值->type = 字符_指针_类型; /* change type to '字符型 *' */压入整数常量(cumofs + s->c);通用_操作('+');/* change type to field type, and set to lvalue */栈顶值->type = s->type;栈顶值->type.t |= qualifiers;/* an array is never an lvalue */如果 (!(栈顶值->type.t & VT_数组)) {栈顶值->r |= VT_LVAL;
#如果已定义 配置_ZHI_边界检查/* 如果 bound checking, the referenced pointer must be checked */如果 (zhi_状态->执行_边界_检查器)栈顶值->r |= VT_强制边界检查;
#结束如果}带有宏替换的下个标记();} 否则 如果 (单词编码 == '[') {带有宏替换的下个标记();通用表达式();通用_操作('+');间接的();跳过(']');} 否则 如果 (单词编码 == '(') {堆栈值 ret;符号 *sa;整数型 数量_args, ret_nregs, ret_align, regsize, variadic;/* function call  */如果 ((栈顶值->type.t & VT_基本类型) != VT_函数) {/* pointer test (no array accepted) */如果 ((栈顶值->type.t & (VT_基本类型 | VT_数组)) == VT_指针) {栈顶值->type = *指定的_类型(&栈顶值->type);如果 ((栈顶值->type.t & VT_基本类型) != VT_函数)去向 错误_函数;} 否则 {错误_函数:应为("函数 指针");}} 否则 {栈顶值->r &= ~VT_LVAL; /* no lvalue */}/* get 返回 type */s = 栈顶值->type.ref;带有宏替换的下个标记();sa = s->next; /* first parameter */数量_args = regsize = 0;ret.r2 = VT_VC常量;/* compute first implicit argument 如果 a structure is returned */如果 ((s->type.t & VT_基本类型) == VT_结构体) {variadic = (s->f.func_type == 函数_省略);ret_nregs = gfunc_sret(&s->type, variadic, &ret.type,&ret_align, &regsize);如果 (ret_nregs <= 0) {/* get some space 循环 the returned structure */size = 类型_大小(&s->type, &align);
#如果已定义 ZHI_TARGET_ARM64/* On arm64, a small 结构体 is 返回 in registers.It is much easier to write it to memory 如果 we knowthat we are allowed to write some extra bytes, soround the allocated space up to a power of 2: */如果 (size < 16)判断 (size & (size - 1))size = (size | (size - 1)) + 1;
#结束如果局部变量索引 = (局部变量索引 - size) & -align;ret.type = s->type;ret.r = VT_LOCAL | VT_LVAL;/* pass it as '整数型' to avoid structure arg passingproblems */vseti(VT_LOCAL, 局部变量索引);ret.c = 栈顶值->c;如果 (ret_nregs < 0)栈顶值--;否则数量_args++;}} 否则 {ret_nregs = 1;ret.type = s->type;}如果 (ret_nregs > 0) {/* 返回 in register */ret.c.i = 0;将函数_返回寄存器_放入堆栈值(&ret, ret.type.t);}如果 (单词编码 != ')') {循环(;;) {等于_表达式();参数传给函数_并进行类型检查和转换(s, sa);数量_args++;如果 (sa)sa = sa->next;如果 (单词编码 == ')')跳出;跳过(',');}}如果 (sa)错误_打印("函数的参数太少");跳过(')');
#如果已定义 配置_ZHI_边界检查如果 (zhi_状态->执行_边界_检查器 &&(数量_args == 1 || 数量_args == 2) &&(栈顶值[-数量_args].r & VT_符号) &&(栈顶值[-数量_args].sym->v == 符_setjmp ||栈顶值[-数量_args].sym->v == 符__setjmp
#如果未定义 ZHI_TARGET_PE|| 栈顶值[-数量_args].sym->v == 符_sigsetjmp|| 栈顶值[-数量_args].sym->v == 符___sigsetjmp
#结束如果)) {推送对_全局符号V_的引用(&函数_旧_类型, 符___bound_setjmp);vpushv(栈顶值 - 数量_args);如果 (数量_args == 2)vpushv(栈顶值 - 数量_args);具体地址函数_调用(数量_args);}
#结束如果具体地址函数_调用(数量_args);如果 (ret_nregs < 0) {vsetc(&ret.type, ret.r, &ret.c);
#如果已定义 ZHI_TARGET_RISCV64arch_transfer_ret_regs(1);
#结束如果} 否则 {/* 返回 value */循环 (r = ret.r + ret_nregs + !ret_nregs; r-- > ret.r;) {vsetc(&ret.type, r, &ret.c);栈顶值->r2 = ret.r2; /* Loop only happens when r2 is VT_VC常量 */}/* handle packed 结构体 返回 */如果 (((s->type.t & VT_基本类型) == VT_结构体) && ret_nregs) {整数型 addr, offset;size = 类型_大小(&s->type, &align);/* We're writing whole regs often, make sure there's enoughspace.  Assume register size is power of 2.  */如果 (regsize > align)align = regsize;局部变量索引 = (局部变量索引 - size) & -align;addr = 局部变量索引;offset = 0;循环 (;;) {vset(&ret.type, VT_LOCAL | VT_LVAL, addr + offset);vswap();将栈顶值_存储在堆栈左值();栈顶值--;如果 (--ret_nregs == 0)跳出;offset += regsize;}vset(&s->type, VT_LOCAL | VT_LVAL, addr);}/* Promote 字符型/short 返回 values. This is matters only循环 calling function that were not compiled by ZHI andonly on some architectures.  For those where it doesn'tmatter we 应为 things to be already promoted to 整数型,but not larger.  */t = s->type.t & VT_基本类型;如果 (t == VT_字节 || t == VT_短整数 || t == VT_逻辑) {#如果已定义 PROMOTE_RET栈顶值->r |= BFVAL(VT_强制转换, 1);
#否则栈顶值->type.t = VT_整数;
#结束如果}}如果 (s->f.func_noreturn)代码_关();} 否则 {跳出;}}
}#如果未定义 优先级_解析器 /* 原始的自上而下的解析器 */静态 无类型 表达式_prod(无类型)
{整数型 t;一元();判断 ((t = 单词编码) == '*' || t == '/' || t == '%') {带有宏替换的下个标记();一元();通用_操作(t);}
}静态 无类型 表达式_sum(无类型)
{整数型 t;表达式_prod();判断 ((t = 单词编码) == '+' || t == '-') {带有宏替换的下个标记();表达式_prod();通用_操作(t);}
}静态 无类型 表达式_转换(无类型)
{整数型 t;表达式_sum();判断 ((t = 单词编码) == 双符号_左位移 || t == 双符号_右位移) {带有宏替换的下个标记();表达式_sum();通用_操作(t);}
}静态 无类型 表达式_cmp(无类型)
{整数型 t;表达式_转换();判断 (((t = 单词编码) >= 符号_ULE && t <= 符_GT) ||t == 符号_ULT || t == 符号_UGE){带有宏替换的下个标记();表达式_转换();通用_操作(t);}
}静态 无类型 表达式_cmpeq(无类型)
{整数型 t;表达式_cmp();判断 ((t = 单词编码) == 双符号_等于 || t == 双符号_不等于) {带有宏替换的下个标记();表达式_cmp();通用_操作(t);}
}静态 无类型 表达式_位与(无类型)
{表达式_cmpeq();判断 (单词编码 == '&') {带有宏替换的下个标记();表达式_cmpeq();通用_操作('&');}
}静态 无类型 表达式_异或(无类型)
{表达式_位与();判断 (单词编码 == '^') {带有宏替换的下个标记();表达式_位与();通用_操作('^');}
}静态 无类型 表达式_位或(无类型)
{表达式_异或();判断 (单词编码 == '|') {带有宏替换的下个标记();表达式_异或();通用_操作('|');}
}静态 无类型 表达式_逻辑与或(整数型 op);静态 无类型 表达式_逻辑与(无类型)
{表达式_位或();如果 (单词编码 == 双符号_逻辑与)表达式_逻辑与或(单词编码);
}静态 无类型 表达式_逻辑或(无类型)
{表达式_逻辑与();如果 (单词编码 == 双符号_逻辑或)表达式_逻辑与或(单词编码);
}# 定义 表达式_逻辑与或_下一个(op) op == 双符号_逻辑与 ? 表达式_位或() : 表达式_逻辑与()
#否则 /* 已定义 优先级_解析器 */
# 定义 表达式_逻辑与或_下一个(op) 一元(), 表达式_中缀(优先权(op) + 1)
# 定义 表达式_逻辑或() 一元(), 表达式_中缀(1)静态 整数型 优先权(整数型 单词编码)
{选择 (单词编码) {分支 双符号_逻辑或: 返回 1;分支 双符号_逻辑与: 返回 2;分支 '|': 返回 3;分支 '^': 返回 4;分支 '&': 返回 5;分支 双符号_等于: 分支 双符号_不等于: 返回 6;relat: 分支 符号_ULT: 分支 符号_UGE: 返回 7;分支 双符号_左位移: 分支 双符号_右位移: 返回 8;分支 '+': 分支 '-': 返回 9;分支 '*': 分支 '/': 分支 '%': 返回 10;default:如果 (单词编码 >= 符号_ULE && 单词编码 <= 符_GT)去向 relat;返回 0;}
}
静态 无符号 字符型 优先权数组[256];
静态 无类型 初始化_优先权(无类型)
{整数型 i;循环 (i = 0; i < 256; i++)优先权数组[i] = 优先权(i);
}
#定义 优先权(i) ((无符号)i < 256 ? 优先权数组[i] : 0)静态 无类型 表达式_逻辑与或(整数型 op);静态 无类型 表达式_中缀(整数型 p)
{整数型 t = 单词编码, p2;判断 ((p2 = 优先权(t)) >= p) {如果 (t == 双符号_逻辑或 || t == 双符号_逻辑与) {表达式_逻辑与或(t);} 否则 {带有宏替换的下个标记();一元();如果 (优先权(单词编码) > p2)表达式_中缀(p2 + 1);通用_操作(t);}t = 单词编码;}
}
#结束如果/* 假设栈顶值是在条件上下文中使用的值(即与零比较),如果为假,则返回0;如果为true,则返回1,如果不能静态确定,* 则返回-1。  */
静态 整数型 条件_3种返回值(无类型)
{整数型 c = -1;如果 ((栈顶值->r & (VT_值掩码 | VT_LVAL)) == VT_VC常量 &&(!(栈顶值->r & VT_符号) || !栈顶值->sym->a.weak)) {vdup();通用_转换_s(VT_逻辑);c = 栈顶值->c.i;弹出堆栈值();}返回 c;
}静态 无类型 表达式_逻辑与或(整数型 op)
{整数型 t = 0, cc = 1, f = 0, i = op == 双符号_逻辑与, c;循环(;;) {c = f ? i : 条件_3种返回值();如果 (c < 0)保存_寄存器最多n个堆栈条目(1), cc = 0;否则 如果 (c != i)不需要_代码生成++, f = 1;如果 (单词编码 != op)跳出;如果 (c < 0)t = 生成值测试(i, t);否则弹出堆栈值();带有宏替换的下个标记();表达式_逻辑与或_下一个(op);}如果 (cc || f) {弹出堆栈值();压入整数常量(i ^ f);生成符号(t);不需要_代码生成 -= f;} 否则 {gvtst_set(i, t);}
}静态 整数型 是_条件_布尔(堆栈值 *sv)
{如果 ((sv->r & (VT_值掩码 | VT_LVAL | VT_符号)) == VT_VC常量&& (sv->type.t & VT_基本类型) == VT_整数)返回 (无符号)sv->c.i < 2;如果 (sv->r == VT_CMP)返回 1;返回 0;
}静态 无类型 条件_表达式(无类型)
{整数型 tt, u, r1, r2, rc, t1, t2, islv, c, g;堆栈值 sv;C类型 type;整数型 ncw_prev;表达式_逻辑或();如果 (单词编码 == '?') {带有宏替换的下个标记();c = 条件_3种返回值();g = (单词编码 == ':' && gnu_扩展);tt = 0;如果 (!g) {如果 (c < 0) {保存_寄存器最多n个堆栈条目(1);tt = 生成值测试(1, 0);} 否则 {弹出堆栈值();}} 否则 如果 (c < 0) {/* needed to avoid having different registers saved ineach branch */保存_寄存器最多n个堆栈条目(1);堆栈转为寄存器并复制到另一个寄存器();tt = 生成值测试(0, 0);}ncw_prev = 不需要_代码生成;如果 (c == 0)不需要_代码生成++;如果 (!g)通用表达式();如果 (c < 0 && 栈顶值->r == VT_CMP) {t1 = 生成值测试(0, 0);压入整数常量(0);gvtst_set(0, t1);将rc寄存器值存储在栈顶值中(寄存器类_整数);}如果 ((栈顶值->type.t & VT_基本类型) == VT_函数)修改类型_指针类型(&栈顶值->type);sv = *栈顶值; /* save value to handle it later */栈顶值--; /* no 弹出堆栈值 so that FP stack is not flushed */如果 (g) {u = tt;} 否则 如果 (c < 0) {u = 生成跳转到标签(0);生成符号(tt);} 否则u = 0;不需要_代码生成 = ncw_prev;如果 (c == 1)不需要_代码生成++;跳过(':');条件_表达式();如果 (c < 0 && 是_条件_布尔(栈顶值) && 是_条件_布尔(&sv)) {如果 (sv.r == VT_CMP) {t1 = sv.jtrue;t2 = u;} 否则 {t1 = 生成值测试(0, 0);t2 = 生成跳转到标签(0);生成符号(u);vpushv(&sv);}gvtst_set(0, t1);gvtst_set(1, t2);不需要_代码生成 = ncw_prev;//  zhi_警告("two conditions 条件_表达式");返回;}如果 ((栈顶值->type.t & VT_基本类型) == VT_函数)修改类型_指针类型(&栈顶值->type);/* cast operands to correct type according to ISOC rules */如果 (!结合_类型(&type, &sv, 栈顶值, '?'))类型_不兼容_错误(&sv.type, &栈顶值->type,"type mismatch in conditional expression (have '%s' and '%s')");/* keep structs lvalue by transforming `(expr ? a : b)` to `*(expr ? &a : &b)` sothat `(expr ? a : b).mem` does not error  with "lvalue expected" */islv = (栈顶值->r & VT_LVAL) && (sv.r & VT_LVAL) && VT_结构体 == (type.t & VT_基本类型);/* now we convert second operand */如果 (c != 1) {通用_转换(&type);如果 (islv) {修改类型_指针类型(&栈顶值->type);获取栈顶值地址();} 否则 如果 (VT_结构体 == (栈顶值->type.t & VT_基本类型))获取栈顶值地址();}rc = 返回类型t的_通用寄存器类(type.t);/* 循环 long longs, we use fixed registers to avoid havingto handle a complicated move */如果 (使用_两个单词的_类型(type.t))rc = 返回类型t的函数_返回寄存器(type.t);tt = r2 = 0;如果 (c < 0) {r2 = 将rc寄存器值存储在栈顶值中(rc);tt = 生成跳转到标签(0);}生成符号(u);不需要_代码生成 = ncw_prev;/* this is horrible, but we must also convert firstoperand */如果 (c != 0) {*栈顶值 = sv;通用_转换(&type);如果 (islv) {修改类型_指针类型(&栈顶值->type);获取栈顶值地址();} 否则 如果 (VT_结构体 == (栈顶值->type.t & VT_基本类型))获取栈顶值地址();}如果 (c < 0) {r1 = 将rc寄存器值存储在栈顶值中(rc);移动_寄存器(r2, r1, islv ? VT_指针 : type.t);栈顶值->r = r2;生成符号(tt);}如果 (islv)间接的();}
}静态 无类型 等于_表达式(无类型)
{整数型 t;条件_表达式();如果 ((t = 单词编码) == '=' || 符_ASSIGN(t)) {测试_左值();带有宏替换的下个标记();如果 (t == '=') {等于_表达式();} 否则 {vdup();等于_表达式();通用_操作(符_ASSIGN_OP(t));}将栈顶值_存储在堆栈左值();}
}静态_函数 无类型 通用表达式(无类型)
{判断 (1) {等于_表达式();如果 (单词编码 != ',')跳出;弹出堆栈值();带有宏替换的下个标记();}
}/* 解析一个常量表达式并在栈顶值中返回值。  */
静态 无类型 表达式_常量1(无类型)
{需要_常量++;不需要_代码生成 += 未评估的子表达式 + 1;条件_表达式();不需要_代码生成 -= 未评估的子表达式 + 1;需要_常量--;
}/* parse an integer constant and 返回 its value. */
静态 内联 int64_t 表达式_常量64(无类型)
{int64_t c;表达式_常量1();如果 ((栈顶值->r & (VT_值掩码 | VT_LVAL | VT_符号)) != VT_VC常量)应为("常量表达式");c = 栈顶值->c.i;弹出堆栈值();返回 c;
}/* parse an integer constant and 返回 its value.Complain 如果 it doesn't fit 32bit (signed or 无符号).  */
静态_函数 整数型 表达式_常量(无类型)
{整数型 c;int64_t wc = 表达式_常量64();c = wc;如果 (c != wc && (无符号)c != wc)错误_打印("常量超过32位");返回 c;
}/* ------------------------------------------------------------------------- */
/* 返回 from function */#如果未定义 ZHI_TARGET_ARM64
静态 无类型 生成函数_返回值(C类型 *func_type)
{如果 ((func_type->t & VT_基本类型) == VT_结构体) {C类型 type, ret_type;整数型 ret_align, ret_nregs, regsize;ret_nregs = gfunc_sret(func_type, 当前函数_可变参数, &ret_type,&ret_align, &regsize);如果 (ret_nregs < 0) {#如果已定义 ZHI_TARGET_RISCV64arch_transfer_ret_regs(0);
#结束如果} 否则 如果 (0 == ret_nregs) {/* 如果 returning structure, must copy it to implicitfirst pointer arg 位置 */type = *func_type;修改类型_指针类型(&type);vset(&type, VT_LOCAL | VT_LVAL, 函数_vc);间接的();vswap();/* copy structure value to pointer */将栈顶值_存储在堆栈左值();} 否则 {/* returning structure packed into registers */整数型 size, addr, align, rc;size = 类型_大小(func_type,&align);如果 ((栈顶值->r != (VT_LOCAL | VT_LVAL) ||(栈顶值->c.i & (ret_align-1)))&& (align & (ret_align-1))) {局部变量索引 = (局部变量索引 - size) & -ret_align;addr = 局部变量索引;type = *func_type;vset(&type, VT_LOCAL | VT_LVAL, addr);vswap();将栈顶值_存储在堆栈左值();弹出堆栈值();vset(&ret_type, VT_LOCAL | VT_LVAL, addr);}栈顶值->type = ret_type;rc = 返回类型t的函数_返回寄存器(ret_type.t);如果 (ret_nregs == 1)将rc寄存器值存储在栈顶值中(rc);否则 {循环 (;;) {vdup();将rc寄存器值存储在栈顶值中(rc);弹出堆栈值();如果 (--ret_nregs == 0)跳出;/* We assume that when a structure is returned in multipleregisters, their classes are consecutive values of thesuite s(n) = 2^n */rc <<= 1;栈顶值->c.i += regsize;}}}} 否则 {将rc寄存器值存储在栈顶值中(返回类型t的函数_返回寄存器(func_type->t));}栈顶值--; /* NOT 弹出堆栈值() because on x86 it would flush the fp stack */
}
#结束如果静态 无类型 检查_函数_返回值(无类型)
{如果 ((当前函数_返回类型.t & VT_基本类型) == VT_无类型)返回;如果 ((!strcmp (函数名称, "main")||!strcmp (函数名称, "主函数"))&& (当前函数_返回类型.t & VT_基本类型) == VT_整数){/* main默认返回0 */压入整数常量(0);通用_指定类型_转换(&当前函数_返回类型);生成函数_返回值(&当前函数_返回类型);} 否则{zhi_警告("函数可能不返回任何值: '%s'", 函数名称);}
}/* ------------------------------------------------------------------------- */
/* 选择/分支 */静态 整数型 分支_对比(常量 无类型 *pa, 常量 无类型 *pb)
{int64_t a = (*(结构体 分支_t**) pa)->v1;int64_t b = (*(结构体 分支_t**) pb)->v1;返回 a < b ? -1 : a > b;
}静态 无类型 gtst_addr(整数型 t, 整数型 a)
{生成符号_地址(生成值测试(0, t), a);
}静态 无类型 生成分支(结构体 分支_t **base, 整数型 len, 整数型 *bsym)
{结构体 分支_t *p;整数型 e;整数型 ll = (栈顶值->type.t & VT_基本类型) == VT_长长整数;判断 (len > 8) {/* binary search */p = base[len/2];vdup();如果 (ll)压入长长整数(p->v2);否则压入整数常量(p->v2);通用_操作(双符号_小于等于);e = 生成值测试(1, 0);vdup();如果 (ll)压入长长整数(p->v1);否则压入整数常量(p->v1);通用_操作(双符号_大于等于);gtst_addr(0, p->sym); /* v1 <= x <= v2 *//* x < v1 */生成分支(base, len/2, bsym);/* x > v2 */生成符号(e);e = len/2 + 1;base += e; len -= e;}/* linear scan */判断 (len--) {p = *base++;vdup();如果 (ll)压入长长整数(p->v2);否则压入整数常量(p->v2);如果 (p->v1 == p->v2) {通用_操作(双符号_等于);gtst_addr(0, p->sym);} 否则 {通用_操作(双符号_小于等于);e = 生成值测试(1, 0);vdup();如果 (ll)压入长长整数(p->v1);否则压入整数常量(p->v1);通用_操作(双符号_大于等于);gtst_addr(0, p->sym);生成符号(e);}}*bsym = 生成跳转到标签(*bsym);
}/* ------------------------------------------------------------------------- */
/* __attribute__((cleanup(fn))) */静态 无类型 尝试_调用_范围_清理(符号 *stop)
{符号 *cls = 当前_范围->cl.s;循环 (; cls != stop; cls = cls->ncl) {符号 *fs = cls->next;符号 *vs = cls->prev_tok;压入符号值(&fs->type, fs);vset(&vs->type, vs->r, vs->c);栈顶值->sym = vs;修改类型_指针类型(&栈顶值->type);获取栈顶值地址();具体地址函数_调用(1);}
}静态 无类型 尝试_调用_去向_清理(符号 *cleanupstate)
{符号 *oc, *cc;整数型 ocd, ccd;如果 (!当前_范围->cl.s)返回;/* search NCA of both cleanup chains given parents and initial depth */ocd = cleanupstate ? cleanupstate->v & ~符号_字段 : 0;循环 (ccd = 当前_范围->cl.n, oc = cleanupstate; ocd > ccd; --ocd, oc = oc->ncl);循环 (cc = 当前_范围->cl.s; ccd > ocd; --ccd, cc = cc->ncl);循环 (; cc != oc; cc = cc->ncl, oc = oc->ncl, --ccd);尝试_调用_范围_清理(cc);
}/* call 'func' 循环 each __attribute__((cleanup(func))) */
静态 无类型 块_清理(结构体 范围 *o)
{整数型 jmp = 0;符号 *g, **pg;循环 (pg = &待定_去向; (g = *pg) && g->c > o->cl.n;) {如果 (g->prev_tok->r & 标签_正向定义) {符号 *pcl = g->next;如果 (!jmp)jmp = 生成跳转到标签(0);生成符号(pcl->jnext);尝试_调用_范围_清理(o->cl.s);pcl->jnext = 生成跳转到标签(0);如果 (!o->cl.n)去向 remove_pending;g->c = o->cl.n;pg = &g->prev;} 否则 {remove_pending:*pg = g->prev;符号_释放(g);}}生成符号(jmp);尝试_调用_范围_清理(o->cl.s);
}/* ------------------------------------------------------------------------- */
/* VLA */静态 无类型 vla_还原(整数型 局部变量索引)
{如果 (局部变量索引)生成_vla_sp_恢复(局部变量索引);
}静态 无类型 vla_离开(结构体 范围 *o)
{如果 (o->vla.num < 当前_范围->vla.num)vla_还原(o->vla.局部变量索引);
}/* ------------------------------------------------------------------------- */
/* local scopes */无类型 新_范围(结构体 范围 *o)
{/* copy and link previous 范围 */*o = *当前_范围;o->prev = 当前_范围;当前_范围 = o;/* record local declaration stack position */o->lstk = 局部符号_堆栈;o->llstk = 局部符号_标签_堆栈;++局部_范围;如果 (zhi_状态->执行_调试)zhi_调试_stabn(N_LBRAC, 输出代码索引 - func_ind);
}无类型 上一个_范围(结构体 范围 *o, 整数型 is_expr)
{vla_离开(o->prev);如果 (o->cl.s != o->prev->cl.s)块_清理(o->prev);/* pop locally 已定义 labels */标签_弹出(&局部符号_标签_堆栈, o->llstk, is_expr);/* In the is_expr 分支 (a statement expression is finished here),栈顶值 might refer to symbols on the 局部符号_堆栈.  Either via thetype or via 栈顶值->sym.  We can't pop those nor any that in turnmight be referred to.  To make it easier we don't roll backany symbols in that 分支; some upper level call to 块() will执行 that.  We 执行 have to remove such symbols from the lookuptables, though.  符号_弹出 will 执行 that.  *//* pop locally 已定义 symbols */弹出_局部_符号(&局部符号_堆栈, o->lstk, is_expr, 0);当前_范围 = o->prev;--局部_范围;如果 (zhi_状态->执行_调试)zhi_调试_stabn(N_RBRAC, 输出代码索引 - func_ind);
}/* leave a 范围 via 跳出/继续(/去向) */
无类型 离开_范围(结构体 范围 *o)
{如果 (!o)返回;尝试_调用_范围_清理(o->cl.s);vla_离开(o);
}/* ------------------------------------------------------------------------- */
/* call 块 from '循环 执行 判断' loops */静态 无类型 循环块(整数型 *bsym, 整数型 *csym)
{结构体 范围 *lo = 循环_范围, *co = 当前_范围;整数型 *b = co->bsym, *c = co->csym;如果 (csym) {co->csym = csym;循环_范围 = co;}co->bsym = bsym;块(0);co->bsym = b;如果 (csym) {co->csym = c;循环_范围 = lo;}
}静态 无类型 块(整数型 is_expr)
{整数型 a, b, c, d, e, t;结构体 范围 o;符号 *s;如果 (is_expr) {/* 默认返回值为(无类型) */压入整数常量(0);栈顶值->type.t = VT_无类型;}again:t = 单词编码, 带有宏替换的下个标记();如果 (t == 关键字_IF || t == 关键字_如果) {跳过('(');通用表达式();跳过(')');a = 生成值测试(1, 0);块(0);如果 (单词编码 == 关键字_ELSE || 单词编码 == 关键字_否则) {d = 生成跳转到标签(0);生成符号(a);带有宏替换的下个标记();块(0);生成符号(d); /* patch 否则 jmp */} 否则 {生成符号(a);}} 否则 如果 (t == 关键字_WHILE || t == 关键字_判断) {d = 返回代码索引();跳过('(');通用表达式();跳过(')');a = 生成值测试(1, 0);b = 0;循环块(&a, &b);生成跳转到_固定地址(d);生成符号_地址(b, d);生成符号(a);} 否则 如果 (t == '{') {新_范围(&o);/* handle local labels declarations */判断 (单词编码 == 关键字_LABEL || 单词编码 == 关键字_标签) {执行 {带有宏替换的下个标记();如果 (单词编码 < 符_没识别)应为("label identifier");标签_推送(&局部符号_标签_堆栈, 单词编码, 标签_被声明);带有宏替换的下个标记();} 判断 (单词编码 == ',');跳过(';');}判断 (单词编码 != '}') {声明(VT_LOCAL);如果 (单词编码 != '}') {如果 (is_expr)弹出堆栈值();块(is_expr);}}上一个_范围(&o, is_expr);如果 (局部_范围)带有宏替换的下个标记();否则 如果 (!不需要_代码生成)检查_函数_返回值();} 否则 如果 (t == 关键字_RETURN || t == 关键字_返回) {b = (当前函数_返回类型.t & VT_基本类型) != VT_无类型;如果 (单词编码 != ';') {通用表达式();如果 (b) {通用_指定类型_转换(&当前函数_返回类型);} 否则 {如果 (栈顶值->type.t != VT_无类型)zhi_警告("无类型 function returns a value");栈顶值--;}} 否则 如果 (b) {zhi_警告("'返回' with no value");b = 0;}离开_范围(根_范围);如果 (b)生成函数_返回值(&当前函数_返回类型);跳过(';');/* jump unless last stmt in top-level 块 */如果 (单词编码 != '}' || 局部_范围 != 1)返回符号 = 生成跳转到标签(返回符号);代码_关();} 否则 如果 (t == 关键字_BREAK || t == 关键字_跳出) {/* compute jump */如果 (!当前_范围->bsym)错误_打印("cannot 跳出");如果 (当前_选择 && 当前_范围->bsym == 当前_选择->bsym)离开_范围(当前_选择->范围);否则离开_范围(循环_范围);*当前_范围->bsym = 生成跳转到标签(*当前_范围->bsym);跳过(';');} 否则 如果 (t == 关键字_CONTINUE || t == 关键字_继续) {/* compute jump */如果 (!当前_范围->csym)错误_打印("cannot 继续");离开_范围(循环_范围);*当前_范围->csym = 生成跳转到标签(*当前_范围->csym);跳过(';');} 否则 如果 (t == 关键字_FOR || t == 关键字_循环) {新_范围(&o);跳过('(');如果 (单词编码 != ';') {/* c99 循环-loop init 声明? */如果 (!声明0(VT_LOCAL, 1, NULL)) {/* no, regular 循环-loop init expr */通用表达式();弹出堆栈值();}}跳过(';');a = b = 0;c = d = 返回代码索引();如果 (单词编码 != ';') {通用表达式();a = 生成值测试(1, 0);}跳过(';');如果 (单词编码 != ')') {e = 生成跳转到标签(0);d = 返回代码索引();通用表达式();弹出堆栈值();生成跳转到_固定地址(c);生成符号(e);}跳过(')');循环块(&a, &b);生成跳转到_固定地址(d);生成符号_地址(b, d);生成符号(a);上一个_范围(&o, 0);} 否则 如果 (t == 关键字_DO || t ==关键字_执行) {a = b = 0;d = 返回代码索引();循环块(&a, &b);生成符号(b);如果(单词编码 == 关键字_WHILE)/*此处只能用tok而不能用t*/{跳过(关键字_WHILE);}否则 如果(单词编码 == 关键字_判断){跳过(关键字_判断);}跳过('(');通用表达式();跳过(')');跳过(';');c = 生成值测试(0, 0);生成符号_地址(c, d);生成符号(a);} 否则 如果 (t == 关键字_SWITCH || t == 关键字_选择) {结构体 选择结构体 *sw;sw = 内存_初始化(取大小 *sw);sw->bsym = &a;sw->范围 = 当前_范围;sw->prev = 当前_选择;当前_选择 = sw;跳过('(');通用表达式();跳过(')');sw->sv = *栈顶值--; /* save 选择 value */a = 0;b = 生成跳转到标签(0); /* jump to first 分支 */循环块(&a, NULL);a = 生成跳转到标签(a); /* add implicit 跳出 *//* 分支 lookup */生成符号(b);qsort(sw->p, sw->n, 取大小(无类型*), 分支_对比);循环 (b = 1; b < sw->n; b++)如果 (sw->p[b - 1]->v2 >= sw->p[b]->v1)错误_打印("重复的分支值");/* Our 选择 table sorting is signed, so the comparedvalue needs to be as well when it's 64bit.  */vpushv(&sw->sv);如果 ((栈顶值->type.t & VT_基本类型) == VT_长长整数)栈顶值->type.t &= ~VT_无符号;将rc寄存器值存储在栈顶值中(寄存器类_整数);d = 0, 生成分支(sw->p, sw->n, &d);弹出堆栈值();如果 (sw->默认_符号)生成符号_地址(d, sw->默认_符号);否则生成符号(d);/* 跳出 label */生成符号(a);动态数组_重分配容量(&sw->p, &sw->n);当前_选择 = sw->prev;内存_释放(sw);} 否则 如果 (t == 关键字_CASE || t == 关键字_分支) {结构体 分支_t *cr = 内存_申请(取大小(结构体 分支_t));如果 (!当前_选择)应为("选择");cr->v1 = cr->v2 = 表达式_常量64();如果 (gnu_扩展 && 单词编码 == 符_三个圆点) {带有宏替换的下个标记();cr->v2 = 表达式_常量64();如果 (cr->v2 < cr->v1)zhi_警告("empty 分支 range");}cr->sym = 返回代码索引();动态数组_追加元素(&当前_选择->p, &当前_选择->n, cr);跳过(':');is_expr = 0;去向 block_after_label;} 否则 如果 (t == 关键字_DEFAULT || t == 关键字_默认) {如果 (!当前_选择)应为("选择");如果 (当前_选择->默认_符号)错误_打印("too many 'default'");当前_选择->默认_符号 = 返回代码索引();跳过(':');is_expr = 0;去向 block_after_label;} 否则 如果 (t == 关键字_GOTO || t == 关键字_去向) {vla_还原(根_范围->vla.局部变量索引);如果 (单词编码 == '*' && gnu_扩展) {/* computed 去向 */带有宏替换的下个标记();通用表达式();如果 ((栈顶值->type.t & VT_基本类型) != VT_指针)应为("pointer");g去向();} 否则 如果 (单词编码 >= 符_没识别) {s = 标签_查找(单词编码);/* put forward definition 如果 needed */如果 (!s)s = 标签_推送(&全局符号_标签_堆栈, 单词编码, 标签_正向定义);否则 如果 (s->r == 标签_被声明)s->r = 标签_正向定义;如果 (s->r & 标签_正向定义) {/* start new 去向 chain 循环 cleanups, linked via label->next */如果 (当前_范围->cl.s && !不需要_代码生成) {符号_推送2(&待定_去向, 符号_字段, 0, 当前_范围->cl.n);待定_去向->prev_tok = s;s = 符号_推送2(&s->next, 符号_字段, 0, 0);待定_去向->next = s;}s->jnext = 生成跳转到标签(s->jnext);} 否则 {尝试_调用_去向_清理(s->cleanupstate);生成跳转到_固定地址(s->jnext);}带有宏替换的下个标记();} 否则 {应为("label identifier");}跳过(';');} 否则 如果 (t == 关键字_asm1 || t == 关键字_asm2 || t == 关键字_asm3 || t == 关键字_汇编) {汇编_指令字符串();} 否则 {如果 (单词编码 == ':' && t >= 符_没识别) {/* label 分支 */带有宏替换的下个标记();s = 标签_查找(t);如果 (s) {如果 (s->r == 标签_定义)错误_打印("duplicate label '%s'", 取_单词字符串(s->v, NULL));s->r = 标签_定义;如果 (s->next) {符号 *pcl; /* pending cleanup 去向 */循环 (pcl = s->next; pcl; pcl = pcl->prev)生成符号(pcl->jnext);符号_弹出(&s->next, NULL, 0);} 否则生成符号(s->jnext);} 否则 {s = 标签_推送(&全局符号_标签_堆栈, t, 标签_定义);}s->jnext = 返回代码索引();s->cleanupstate = 当前_范围->cl.s;block_after_label:vla_还原(当前_范围->vla.局部变量索引);/* we accept this, but it is a mistake */如果 (单词编码 == '}') {zhi_警告("deprecated use of label at end of compound statement");} 否则 {去向 again;}} 否则 {/* expression 分支 */如果 (t != ';') {设为_指定标识符(t);如果 (is_expr) {弹出堆栈值();通用表达式();} 否则 {通用表达式();弹出堆栈值();}跳过(';');}}}
}/* This skips over a stream of 标识符s containing balanced {} and ()pairs, stopping at outer ',' ';' and '}' (or matching '}' 如果 we startedwith a '{').  If STR then allocates and stores the skipped 标识符sin *STR.  This doesn't check 如果 () and {} are nested correctly,i.e. "({)}" is accepted.  */
静态 无类型 跳过_或_保存_块(单词字符串 **str)
{整数型 braces = 单词编码 == '{';整数型 level = 0;如果 (str)*str = 单词字符串_分配();判断 ((level > 0 || (单词编码 != '}' && 单词编码 != ',' && 单词编码 != ';' && 单词编码 != ')'))) {整数型 t;如果 (单词编码 == 符_文件结尾) {如果 (str || level > 0)错误_打印("unexpected end of file");否则跳出;}如果 (str)单词字符串中添加当前解析的字符(*str);t = 单词编码;带有宏替换的下个标记();如果 (t == '{' || t == '(') {level++;} 否则 如果 (t == '}' || t == ')') {level--;如果 (level == 0 && braces && t == '}')跳出;}}如果 (str) {单词字符串_增加大小(*str, -1);单词字符串_增加大小(*str, 0);}
}#定义 EXPR_CONST 1
#定义 EXPR_ANY   2静态 无类型 解析_初始化_元素(整数型 解析表达式_返回类型)
{整数型 saved_global_expr;选择(解析表达式_返回类型) {分支 EXPR_CONST:/* compound literals must be allocated globally in this 分支 */saved_global_expr = 全局_分配复合字符;全局_分配复合字符 = 1;表达式_常量1();全局_分配复合字符 = saved_global_expr;/* NOTE: symbols are accepted, as well as lvalue 循环 anon symbols(compound literals).  */如果 (((栈顶值->r & (VT_值掩码 | VT_LVAL)) != VT_VC常量&& ((栈顶值->r & (VT_符号|VT_LVAL)) != (VT_符号|VT_LVAL)|| 栈顶值->sym->v < 符号_第一个_匿名))
#如果已定义 ZHI_TARGET_PE|| ((栈顶值->r & VT_符号) && 栈顶值->sym->a.dllimport)
#结束如果)错误_打印("initializer element is not constant");跳出;分支 EXPR_ANY:等于_表达式();跳出;}
}/* 将零用于基于变量的init */
静态 无类型 将0_用于变量的初始化(段 *sec, 无符号 long c, 整数型 size)
{如果 (sec) {/* 无事可做,因为全局变量已经设置为零 */} 否则 {推送对_全局符号V_的引用(&函数_旧_类型, 符_memset);vseti(VT_LOCAL, c);
#如果已定义 ZHI_TARGET_ARM压入目标地址类型常量(size);压入整数常量(0);
#否则压入整数常量(0);压入目标地址类型常量(size);
#结束如果具体地址函数_调用(3);}
}#定义 DIF_FIRST     1
#定义 DIF_SIZE_ONLY 2
#定义 DIF_HAVE_ELEM 4/* t是数组或结构类型。 c是数组或结构地址。 cur_field是指向当前字段的指针,对于数组,“ c”成员包含当前起始索引。*  “标志”与声明_初始化器中的一样。 “ al”包含当前容器的已初始化长度(从c开始)。 这将返回它的新长度。  */
静态 整数型 声明_指示符(C类型 *type, 段 *sec, 无符号 long c,符号 **cur_field, 整数型 flags, 整数型 al)
{符号 *s, *f;整数型 index, index_last, align, l, 数量_elems, elem_size;无符号 long corig = c;elem_size = 0;数量_elems = 1;如果 (flags & DIF_HAVE_ELEM)去向 no_designator;如果 (gnu_扩展 && 单词编码 >= 符_没识别) {l = 单词编码, 带有宏替换的下个标记();如果 (单词编码 == ':')去向 struct_field;设为_指定标识符(l);}/* NOTE: we only support ranges 循环 last designator */判断 (数量_elems == 1 && (单词编码 == '[' || 单词编码 == '.')) {如果 (单词编码 == '[') {如果 (!(type->t & VT_数组))应为("array type");带有宏替换的下个标记();index = index_last = 表达式_常量();如果 (单词编码 == 符_三个圆点 && gnu_扩展) {带有宏替换的下个标记();index_last = 表达式_常量();}跳过(']');s = type->ref;如果 (index < 0 || (s->c >= 0 && index_last >= s->c) ||index_last < index)错误_打印("invalid index");如果 (cur_field)(*cur_field)->c = index_last;type = 指定的_类型(type);elem_size = 类型_大小(type, &align);c += index * elem_size;数量_elems = index_last - index + 1;} 否则 {整数型 cumofs;带有宏替换的下个标记();l = 单词编码;struct_field:带有宏替换的下个标记();如果 ((type->t & VT_基本类型) != VT_结构体)应为("结构体/共用体 type");cumofs = 0;f = 查找_域(type, l, &cumofs);如果 (!f)应为("field");如果 (cur_field)*cur_field = f;type = &f->type;c += cumofs + f->c;}cur_field = NULL;}如果 (!cur_field) {如果 (单词编码 == '=') {带有宏替换的下个标记();} 否则 如果 (!gnu_扩展) {应为("=");}} 否则 {no_designator:如果 (type->t & VT_数组) {index = (*cur_field)->c;如果 (type->ref->c >= 0 && index >= type->ref->c)错误_打印("index too large");type = 指定的_类型(type);c += index * 类型_大小(type, &align);} 否则 {f = *cur_field;判断 (f && (f->v & 符号_第一个_匿名) && (f->type.t & VT_位域))*cur_field = f = f->next;如果 (!f)错误_打印("too many field init");type = &f->type;c += f->c;}}/* must put zero in holes (note that doing it that wayensures that it even works with designators) */如果 (!(flags & DIF_SIZE_ONLY) && c - corig > al)将0_用于变量的初始化(sec, corig + al, c - corig - al);声明_初始化器(type, sec, c, flags & ~DIF_FIRST);/* XXX: make it more general */如果 (!(flags & DIF_SIZE_ONLY) && 数量_elems > 1) {无符号 long c_end;uint8_t *src, *dst;整数型 i;如果 (!sec) {vset(type, VT_LOCAL|VT_LVAL, c);循环 (i = 1; i < 数量_elems; i++) {vset(type, VT_LOCAL|VT_LVAL, c + elem_size * i);vswap();将栈顶值_存储在堆栈左值();}弹出堆栈值();} 否则 如果 (!不需要_静态数据输出) {c_end = c + 数量_elems * elem_size;如果 (c_end > sec->data_allocated)节_重新分配内存(sec, c_end);src = sec->data + c;dst = src;循环(i = 1; i < 数量_elems; i++) {dst += elem_size;memcpy(dst, src, elem_size);}}}c += 数量_elems * 类型_大小(type, &align);如果 (c - corig > al)al = c - corig;返回 al;
}/* 将值或表达式直接存储在全局数据或本地数组中 */
静态 无类型 将值或表达式_直接存储在全局数据或本地数组中(C类型 *type, 段 *sec, 无符号 long c)
{整数型 bt;无类型 *ptr;C类型 dtype;dtype = *type;dtype.t &= ~VT_常量; /* need to 执行 that to avoid false warning */如果 (sec) {整数型 size, align;/* XXX: not portable *//* XXX: generate error 如果 incorrect relocation */通用_指定类型_转换(&dtype);bt = type->t & VT_基本类型;如果 ((栈顶值->r & VT_符号)&& bt != VT_指针&& bt != VT_函数&& (bt != (指针_大小 == 8 ? VT_长长整数 : VT_整数)|| (type->t & VT_位域))&& !((栈顶值->r & VT_VC常量) && 栈顶值->sym->v >= 符号_第一个_匿名))错误_打印("initializer element is not computable at 加载 time");如果 (不需要_静态数据输出) {栈顶值--;返回;}size = 类型_大小(type, &align);段_保留(sec, c + size);ptr = sec->data + c;/* XXX: make code faster ? */如果 ((栈顶值->r & (VT_符号|VT_VC常量)) == (VT_符号|VT_VC常量) &&栈顶值->sym->v >= 符号_第一个_匿名 &&/* XXX This rejects compound literals like'(无类型 *){ptr}'.  The problem is that '&sym' isrepresented the same way, which would be ruled outby the 符号_第一个_匿名 check above, but also '"string"'in '字符型 *p = "string"' is represented the samewith the type being VT_指针 and the symbol being ananonymous one.  That is, there's no difference in 栈顶值between '(无类型 *){x}' and '&(无类型 *){x}'.  Ignorepointer typed entities here.  Hopefully no real codewill ever use compound literals with scalar type.  */(栈顶值->type.t & VT_基本类型) != VT_指针) {/* These come from compound literals, memcpy stuff over.  */段 *ssec;ELF符号 *esym;ElfW_Rel *rel;esym = elf符号(栈顶值->sym);ssec = zhi_状态->段数[esym->st_shndx];memmove (ptr, ssec->data + esym->st_value + (整数型)栈顶值->c.i, size);如果 (ssec->重定位) {/* We need to copy over all memory contents, and thatincludes relocations.  Use the fact that relocs arecreated it order, so look from the end of relocsuntil we hit one before the copied region.  */整数型 num_relocs = ssec->重定位->数据_偏移 / 取大小(*rel);rel = (ElfW_Rel*)(ssec->重定位->data + ssec->重定位->数据_偏移);判断 (num_relocs--) {rel--;如果 (rel->r_offset >= esym->st_value + size)继续;如果 (rel->r_offset < esym->st_value)跳出;/* Note: 如果 the same fields are initialized multipletimes (possible with designators) then we possiblyadd multiple relocations 循环 the same offset here.That would lead to wrong code, the last 重定位 needsto win.  We clean this up later after the wholeinitializer is parsed.  */使_elf_重定位目标地址(单词表_部分, sec,c + rel->r_offset - esym->st_value,ELFW(R_TYPE)(rel->r_info),ELFW(R_SYM)(rel->r_info),
#如果 指针_大小 == 8rel->r_addend
#否则0
#结束如果);}}} 否则 {如果 (type->t & VT_位域) {整数型 bit_pos, bit_size, bits, n;无符号 字符型 *p, v, m;bit_pos = BIT_POS(栈顶值->type.t);bit_size = BIT_大小(栈顶值->type.t);p = (无符号 字符型*)ptr + (bit_pos >> 3);bit_pos &= 7, bits = 0;判断 (bit_size) {n = 8 - bit_pos;如果 (n > bit_size)n = bit_size;v = 栈顶值->c.i >> bits << bit_pos;m = ((1 << n) - 1) << bit_pos;*p = (*p & ~m) | (v & m);bits += n, bit_size -= n, bit_pos = 0, ++p;}} 否则选择(bt) {/* XXX: 在交叉编译时,我们假设每种类型在主机和目标上的表示都相同,这对于长double而言可能是错误的 */分支 VT_逻辑:栈顶值->c.i = 栈顶值->c.i != 0;分支 VT_字节:*(字符型 *)ptr |= 栈顶值->c.i;跳出;分支 VT_短整数:*(short *)ptr |= 栈顶值->c.i;跳出;分支 VT_浮点:*(float*)ptr = 栈顶值->c.f;跳出;分支 VT_双精度:*(double *)ptr = 栈顶值->c.d;跳出;分支 VT_长双精度:
#如果 已定义 ZHI_IS_NATIVE_387如果 (取大小 (long double) >= 10) /* zero pad ten-byte LD */memcpy(ptr, &栈顶值->c.ld, 10);
#如果已定义 __TINYC__否则 如果 (取大小 (long double) == 取大小 (double))__asm__("fldl %1\nfstpt %0\n" : "=m" (*ptr) : "m" (栈顶值->c.ld));
#结束如果否则 如果 (栈顶值->c.ld == 0.0);否则
#结束如果如果 (取大小(long double) == 长双精度_大小)*(long double*)ptr = 栈顶值->c.ld;否则 如果 (取大小(double) == 长双精度_大小)*(double *)ptr = (double)栈顶值->c.ld;否则错误_打印("can't cross compile long double constants");跳出;
#如果 指针_大小 != 8分支 VT_长长整数:*(long long *)ptr |= 栈顶值->c.i;跳出;
#否则分支 VT_长长整数:
#结束如果分支 VT_指针:{目标地址_类型 val = 栈顶值->c.i;
#如果 指针_大小 == 8如果 (栈顶值->r & VT_符号)添加新的重定位项(sec, 栈顶值->sym, c, R_DATA_PTR, val);否则*(目标地址_类型 *)ptr |= val;
#否则如果 (栈顶值->r & VT_符号)段部分符号重定位(sec, 栈顶值->sym, c, R_DATA_PTR);*(目标地址_类型 *)ptr |= val;
#结束如果跳出;}default:{整数型 val = 栈顶值->c.i;
#如果 指针_大小 == 8如果 (栈顶值->r & VT_符号)添加新的重定位项(sec, 栈顶值->sym, c, R_DATA_PTR, val);否则*(整数型 *)ptr |= val;
#否则如果 (栈顶值->r & VT_符号)段部分符号重定位(sec, 栈顶值->sym, c, R_DATA_PTR);*(整数型 *)ptr |= val;
#结束如果跳出;}}}栈顶值--;} 否则 {vset(&dtype, VT_LOCAL|VT_LVAL, c);vswap();将栈顶值_存储在堆栈左值();弹出堆栈值();}
}/* 't' contains the type and storage info. 'c' is the offset of theobject in section 'sec'. If 'sec' is NULL, it means stack basedallocation. 'flags & DIF_FIRST' is true 如果 array '{' must be read (multidimension implicit array init handling). 'flags & DIF_SIZE_ONLY' is true 如果size only evaluation is wanted (only 循环 arrays). */
静态 无类型 声明_初始化器(C类型 *type, 段 *sec, 无符号 long c, 整数型 flags)
{整数型 len, n, no_oblock, i;整数型 size1, align1;符号 *s, *f;符号 indexsym;C类型 *t1;如果 (!(flags & DIF_HAVE_ELEM) && 单词编码 != '{' &&/* In 分支 of strings we have special handling 循环 arrays, sodon't consume them as initializer value (which would commit themto some anonymous symbol).  */单词编码 != 常量_长字符串 && 单词编码 != 常量_字符串 &&!(flags & DIF_SIZE_ONLY)) {解析_初始化_元素(!sec ? EXPR_ANY : EXPR_CONST);flags |= DIF_HAVE_ELEM;}如果 ((flags & DIF_HAVE_ELEM) &&!(type->t & VT_数组) &&/* Use i_c_parameter_t, to strip toplevel qualifiers.The source type might have VT_常量 set, which isof course assignable to non-常量 elements.  */是_兼容_不合格的_类型(type, &栈顶值->type)) {将值或表达式_直接存储在全局数据或本地数组中(type, sec, c);} 否则 如果 (type->t & VT_数组) {s = type->ref;n = s->c;t1 = 指定的_类型(type);size1 = 类型_大小(t1, &align1);no_oblock = 1;如果 (((flags & DIF_FIRST) && 单词编码 != 常量_长字符串 && 单词编码 != 常量_字符串) ||单词编码 == '{') {如果 (单词编码 != '{')错误_打印("character array initializer must be a literal,"" optionally enclosed in braces");跳过('{');no_oblock = 0;}/* only parse strings here 如果 correct type (otherwise: handlethem as ((w)字符型 *) expressions */如果 ((单词编码 == 常量_长字符串 &&
#如果已定义 ZHI_TARGET_PE(t1->t & VT_基本类型) == VT_短整数 && (t1->t & VT_无符号)
#否则(t1->t & VT_基本类型) == VT_整数
#结束如果) || (单词编码 == 常量_字符串 && (t1->t & VT_基本类型) == VT_字节)) {整数型 nb;len = 0;动态字符串_重置(&初始字符串);如果 (size1 != (单词编码 == 常量_字符串 ? 1 : 取大小(nwchar_t)))错误_打印("unhandled string literal merging");判断 (单词编码 == 常量_字符串 || 单词编码 == 常量_长字符串) {如果 (初始字符串.字符串长度)初始字符串.字符串长度 -= size1;如果 (单词编码 == 常量_字符串)len += 单词值.str.size;否则len += 单词值.str.size / 取大小(nwchar_t);len--;动态字符串_cat(&初始字符串, 单词值.str.data, 单词值.str.size);带有宏替换的下个标记();}如果 (单词编码 != ')' && 单词编码 != '}' && 单词编码 != ',' && 单词编码 != ';'&& 单词编码 != 符_文件结尾) {/* Not a lone literal but part of a bigger expression.  */设为_指定标识符(size1 == 1 ? 常量_字符串 : 常量_长字符串);单词值.str.size = 初始字符串.字符串长度;单词值.str.data = 初始字符串.指向字符串的指针;indexsym.c = 0;f = &indexsym;去向 do_init_list;}nb = len;如果 (n >= 0 && len > n)nb = n;如果 (!(flags & DIF_SIZE_ONLY)) {如果 (len > nb)zhi_警告("initializer-string 循环 array is too long");/* in order to go faster 循环 common 分支 (字符型string in global variable, we handle itspecifically */如果 (sec && size1 == 1) {如果 (!不需要_静态数据输出)memcpy(sec->data + c, 初始字符串.指向字符串的指针, nb);} 否则 {循环(i=0;i<nb;i++) {如果 (size1 == 1)当前取到的源码字符 = ((无符号 字符型 *)初始字符串.指向字符串的指针)[i];否则当前取到的源码字符 = ((nwchar_t *)初始字符串.指向字符串的指针)[i];压入整数常量(当前取到的源码字符);将值或表达式_直接存储在全局数据或本地数组中(t1, sec, c + i * size1);}}}/* only add trailing zero 如果 enough storage (nowarning in this 分支 since it is standard) */如果 (n < 0 || len < n) {如果 (!(flags & DIF_SIZE_ONLY)) {压入整数常量(0);将值或表达式_直接存储在全局数据或本地数组中(t1, sec, c + (len * size1));}len++;}len *= size1;} 否则 {indexsym.c = 0;f = &indexsym;do_init_list:len = 0;判断 (单词编码 != '}' || (flags & DIF_HAVE_ELEM)) {len = 声明_指示符(type, sec, c, &f, flags, len);flags &= ~DIF_HAVE_ELEM;如果 (type->t & VT_数组) {++indexsym.c;/* special test 循环 multi dimensional arrays (may notbe strictly correct 如果 designators are used at thesame time) */如果 (no_oblock && len >= n*size1)跳出;} 否则 {如果 (s->type.t == VT_共用体)f = NULL;否则f = f->next;如果 (no_oblock && f == NULL)跳出;}如果 (单词编码 == '}')跳出;跳过(',');}}/* put zeros at the end */如果 (!(flags & DIF_SIZE_ONLY) && len < n*size1)将0_用于变量的初始化(sec, c + len, n*size1 - len);如果 (!no_oblock)跳过('}');/* patch type size 如果 needed, which happens only 循环 array types */如果 (n < 0)s->c = size1 == 1 ? len : ((len + size1 - 1)/size1);} 否则 如果 ((type->t & VT_基本类型) == VT_结构体) {size1 = 1;no_oblock = 1;如果 ((flags & DIF_FIRST) || 单词编码 == '{') {跳过('{');no_oblock = 0;}s = type->ref;f = s->next;n = s->c;去向 do_init_list;} 否则 如果 (单词编码 == '{') {如果 (flags & DIF_HAVE_ELEM)跳过(';');带有宏替换的下个标记();声明_初始化器(type, sec, c, flags & ~DIF_HAVE_ELEM);跳过('}');} 否则 如果 ((flags & DIF_SIZE_ONLY)) {/* If we supported only ISO C we wouldn't have to accept callingthis on anything than an array 如果 DIF_SIZE_ONLY (and even thenonly on the outermost level, so no recursion would be needed),because initializing a flex array member isn't supported.But GNU C supports it, so we need to recurse even intosubfields of structs and arrays when DIF_SIZE_ONLY is set.  *//* just 跳过 expression */跳过_或_保存_块(NULL);} 否则 {如果 (!(flags & DIF_HAVE_ELEM)) {/* This should happen only when we haven't parsedthe init element above 循环 fear of committing astring constant to memory too early.  */如果 (单词编码 != 常量_字符串 && 单词编码 != 常量_长字符串)应为("string constant");解析_初始化_元素(!sec ? EXPR_ANY : EXPR_CONST);}将值或表达式_直接存储在全局数据或本地数组中(type, sec, c);}
}/* parse an initializer 循环 type 't' 如果 'has_init' is non zero, andallocate space in local or global data space ('r' is eitherVT_LOCAL or VT_VC常量). If 'v' is non zero, then an associatedvariable 'v' of 范围 '范围' is declared before initializersare parsed. If 'v' is zero, then a reference to the new objectis put in the value stack. If 'has_init' is 2, a special parsingis done to handle string constants. */
静态 无类型 声明_初始化_分配(C类型 *type, 属性定义 *ad, 整数型 r,整数型 has_init, 整数型 v, 整数型 范围)
{整数型 size, align, addr;单词字符串 *init_str = NULL;段 *sec;符号 *flexible_array;符号 *sym = NULL;整数型 saved_nocode_wanted = 不需要_代码生成;
#如果已定义 配置_ZHI_边界检查整数型 bcheck = zhi_状态->执行_边界_检查器 && !不需要_静态数据输出;
#结束如果/* Always allocate 静态 or global variables */如果 (v && (r & VT_值掩码) == VT_VC常量)不需要_代码生成 |= 0x80000000;flexible_array = NULL;如果 ((type->t & VT_基本类型) == VT_结构体) {符号 *field = type->ref->next;如果 (field) {判断 (field->next)field = field->next;如果 (field->type.t & VT_数组&& field->type.ref->c < 0)flexible_array = field;}}size = 类型_大小(type, &align);/* If unknown size, we must evaluate it beforeevaluating initializers becauseinitializers can generate global data too(e.g. string pointers or ISOC99 compoundliterals). It also simplifies localinitializers handling */如果 (size < 0 || (flexible_array && has_init)) {如果 (!has_init) 错误_打印("unknown type size");/* get all init string */如果 (has_init == 2) {init_str = 单词字符串_分配();/* only get strings */判断 (单词编码 == 常量_字符串 || 单词编码 == 常量_长字符串) {单词字符串中添加当前解析的字符(init_str);带有宏替换的下个标记();}单词字符串_增加大小(init_str, -1);单词字符串_增加大小(init_str, 0);} 否则 {跳过_或_保存_块(&init_str);}设为_指定标识符(0);/* compute size */开始_宏(init_str, 1);带有宏替换的下个标记();声明_初始化器(type, NULL, 0, DIF_FIRST | DIF_SIZE_ONLY);/* prepare second initializer parsing */宏_ptr = init_str->str;带有宏替换的下个标记();/* 如果 still unknown size, error */size = 类型_大小(type, &align);如果 (size < 0) 错误_打印("unknown type size");}/* If there's a flex member and it was used in the initializeradjust size.  */如果 (flexible_array &&flexible_array->type.ref->c > 0)size += flexible_array->type.ref->c* 指定类型的_大小(&flexible_array->type);/* take into account specified alignment 如果 bigger */如果 (ad->a.aligned) {整数型 speca = 1 << (ad->a.aligned - 1);如果 (speca > align)align = speca;} 否则 如果 (ad->a.packed) {align = 1;}如果 (!v && 不需要_静态数据输出)size = 0, align = 1;如果 ((r & VT_值掩码) == VT_LOCAL) {sec = NULL;
#如果已定义 配置_ZHI_边界检查如果 (bcheck && v) {/* add padding between stack variables 循环 bound checking */局部变量索引--;}
#结束如果局部变量索引 = (局部变量索引 - size) & -align;addr = 局部变量索引;
#如果已定义 配置_ZHI_边界检查如果 (bcheck && v) {/* add padding between stack variables 循环 bound checking */局部变量索引--;}
#结束如果如果 (v) {/* local variable */
#如果已定义 配置_ZHI_汇编如果 (ad->汇编_label) {整数型 reg = 汇编_解析_注册变量(ad->汇编_label);如果 (reg >= 0)r = (r & ~VT_值掩码) | reg;}
#结束如果sym = 符号_压入栈(v, type, r, addr);如果 (ad->cleanup_func) {符号 *cls = 符号_推送2(&清理_所有,符号_字段 | ++当前_范围->cl.n, 0, 0);cls->prev_tok = sym;cls->next = ad->cleanup_func;cls->ncl = 当前_范围->cl.s;当前_范围->cl.s = cls;}sym->a = ad->a;} 否则 {/* push local reference */vset(type, r, addr);}} 否则 {如果 (v && 范围 == VT_VC常量) {/* see 如果 the symbol was already 已定义 */sym = 符号_查询(v);如果 (sym) {合并_其他存储属性(sym, ad, type);/* we accept several definitions of the same global variable. */如果 (!has_init && sym->c && elf符号(sym)->st_shndx != SHN_UNDEF)去向 no_alloc;}}/* allocate symbol in corresponding section */sec = ad->section;如果 (!sec) {如果 (has_init)sec = 初始化数据_部分;否则 如果 (zhi_状态->不使用通用符号)sec = 未初始化数据_部分;}如果 (sec) {addr = 返回_节_对齐偏移量(sec, size, align);
#如果已定义 配置_ZHI_边界检查/* add padding 如果 bound check */如果 (bcheck)返回_节_对齐偏移量(sec, 1, 1);
#结束如果} 否则 {addr = align; /* SHN_COMMON is special, symbol value is align */sec = 通用_部分;}如果 (v) {如果 (!sym) {sym = 符号_压入栈(v, type, r | VT_符号, 0);合并_其他存储属性(sym, ad, NULL);}/* update symbol definition */更新_外部_符号(sym, sec, addr, size);} 否则 {/* push global reference */将引用_推送到_节偏移量(type, sec, addr, size);sym = 栈顶值->sym;栈顶值->r |= r;}#如果已定义 配置_ZHI_边界检查/* handles bounds now because the symbol must be 已定义before 循环 the relocation */如果 (bcheck) {目标地址_类型 *bounds_ptr;添加新的重定位项(全局边界_部分, sym, 全局边界_部分->数据_偏移, R_DATA_PTR, 0);/* then add global bound info */bounds_ptr = 段_ptr_添加(全局边界_部分, 2 * 取大小(目标地址_类型));bounds_ptr[0] = 0; /* relocated */bounds_ptr[1] = size;}
#结束如果}如果 (type->t & VT_变长数组) {整数型 a;如果 (不需要_静态数据输出)去向 no_alloc;/* save current stack pointer */如果 (根_范围->vla.局部变量索引 == 0) {结构体 范围 *v = 当前_范围;生成_vla_sp_保存(局部变量索引 -= 指针_大小);执行 v->vla.局部变量索引 = 局部变量索引; 判断 ((v = v->prev));}vla_运行时_类型_大小(type, &a);生成_vla_分配(type, a);
#如果 已定义 ZHI_TARGET_PE && 已定义 ZHI_TARGET_X86_64/* on _WIN64, because of the function args scratch area, theresult of alloca differs from RSP and is returned in RAX.  */生成_vla_结果(addr), addr = (局部变量索引 -= 指针_大小);
#结束如果生成_vla_sp_保存(addr);当前_范围->vla.局部变量索引 = addr;当前_范围->vla.num++;} 否则 如果 (has_init) {size_t oldreloc_offset = 0;如果 (sec && sec->重定位)oldreloc_offset = sec->重定位->数据_偏移;声明_初始化器(type, sec, addr, DIF_FIRST);如果 (sec && sec->重定位)压缩_多_重定位(sec, oldreloc_offset);/* patch flexible array member size back to -1, *//* 循环 possible subsequent similar declarations */如果 (flexible_array)flexible_array->type.ref->c = -1;}no_alloc:/* restore parse state 如果 needed */如果 (init_str) {结束_宏();带有宏替换的下个标记();}不需要_代码生成 = saved_nocode_wanted;
}/* 解析由符号“ sym”定义的函数,并在“当前_生成代码_段”中生成其代码 */
静态 无类型 生成_函数(符号 *sym)
{/* Initialize VLA state */结构体 范围 f = { 0 };当前_范围 = 根_范围 = &f;不需要_代码生成 = 0;输出代码索引 = 当前_生成代码_段->数据_偏移;如果 (sym->a.aligned) {size_t newoff = 返回_节_对齐偏移量(当前_生成代码_段, 0,1 << (sym->a.aligned - 1));生成_fill_nops(newoff - 输出代码索引);}/* NOTE: we patch the symbol size later */更新_外部_符号(sym, 当前_生成代码_段, 输出代码索引, 0);如果 (sym->type.ref->f.func_ctor)增加_数组 (zhi_状态, ".init_array", sym->c);如果 (sym->type.ref->f.func_dtor)增加_数组 (zhi_状态, ".fini_array", sym->c);函数名称 = 取_单词字符串(sym->v, NULL);func_ind = 输出代码索引;当前函数_返回类型 = sym->type.ref->type;当前函数_可变参数 = sym->type.ref->f.func_type == 函数_省略;/* put debug symbol */zhi_调试_函数开始(zhi_状态, sym);/* push a dummy symbol to enable local sym storage */符号_推送2(&局部符号_堆栈, 符号_字段, 0, 0);局部_范围 = 1; /* 循环 function parameters */生成函数_序言(sym);局部_范围 = 0;返回符号 = 0;清除_临时_局部_变量_列表();块(0);生成符号(返回符号);不需要_代码生成 = 0;/* reset local stack */弹出_局部_符号(&局部符号_堆栈, NULL, 0, 当前函数_可变参数);生成函数_结尾();当前_生成代码_段->数据_偏移 = 输出代码索引;局部_范围 = 0;标签_弹出(&全局符号_标签_堆栈, NULL, 0);符号_弹出(&清理_所有, NULL, 0);/* patch symbol size */elf符号(sym)->st_size = 输出代码索引 - func_ind;/* end of function */zhi_调试_函数结束(zhi_状态, 输出代码索引 - func_ind);/* It's better to crash than to generate wrong code */当前_生成代码_段 = NULL;函数名称 = ""; /* 循环 safety */当前函数_返回类型.t = VT_无类型; /* 循环 safety */当前函数_可变参数 = 0; /* 循环 safety */输出代码索引 = 0; /* 循环 safety */不需要_代码生成 = 0x80000000;检查_堆栈值();/* 执行 this after funcend debug info */带有宏替换的下个标记();
}静态 无类型 生成_内联函数(知心状态机 *s)
{符号 *sym;整数型 inline_generated, i;结构体 内联函数 *fn;打开缓存文件(s, ":内联:", 0);/* iterate 判断 内联 function are referenced */执行 {inline_generated = 0;循环 (i = 0; i < s->数量_内联_函数数; ++i) {fn = s->内联_函数数[i];sym = fn->sym;如果 (sym && (sym->c || !(sym->type.t & VT_内联))) {/* the function was used or forced (and then not internal):generate its code and convert it to a normal function */fn->sym = NULL;zhi_调试_备用文件(s, fn->文件名);开始_宏(fn->函数_字符串, 1);带有宏替换的下个标记();当前_生成代码_段 = 生成代码_段;生成_函数(sym);结束_宏();inline_generated = 1;}}} 判断 (inline_generated);关闭文件();
}静态 无类型 释放_内联函数(知心状态机 *s)
{整数型 i;循环 (i = 0; i < s->数量_内联_函数数; ++i){结构体 内联函数 *fn = s->内联_函数数[i];如果 (fn->sym)单词字符串_释放(fn->函数_字符串);}动态数组_重分配容量(&s->内联_函数数, &s->数量_内联_函数数);
}静态 整数型 声明0(整数型 l, 整数型 is_for_loop_init, 符号 *func_sym)
{整数型 v, has_init, r;C类型 type, btype;符号 *sym;属性定义 ad, adbase;判断 (1) {如果 (单词编码 == 关键字_STATIC_ASSERT || 单词编码 == 关键字_静态_声明) {动态字符串 error_str;整数型 c;带有宏替换的下个标记();跳过('(');c = 表达式_常量();如果 (单词编码 == ')') {如果 (!c)错误_打印("_Static_assert fail");带有宏替换的下个标记();去向 static_assert_out;}跳过(',');解析_多_字符串(&error_str, "string constant");如果 (c == 0)错误_打印("%s", (字符型 *)error_str.指向字符串的指针);动态字符串_释放(&error_str);跳过(')');static_assert_out:跳过(';');继续;}如果 (!解析_基本类型(&btype, &adbase)) {如果 (is_for_loop_init)返回 0;/* 跳过 redundant ';' 如果 not in old parameter 声明 范围 */如果 (单词编码 == ';' && l != VT_CMP) {带有宏替换的下个标记();继续;}如果 (l != VT_VC常量)跳出;如果 (单词编码 == 关键字_asm1 || 单词编码 == 关键字_asm2 || 单词编码 == 关键字_asm3 || 单词编码 == 关键字_汇编) {/* global asm 块 */汇编_全局_instr();继续;}如果 (单词编码 >= 符_没识别) {/* special test 循环 old K&R protos without explicit 整数型type. Only accepted when defining global data */btype.t = VT_整数;} 否则 {如果 (单词编码 != 符_文件结尾)应为("declaration");跳出;}}如果 (单词编码 == ';') {如果 ((btype.t & VT_基本类型) == VT_结构体) {整数型 v = btype.ref->v;如果 (!(v & 符号_字段) && (v & ~符号_结构体) >= 符号_第一个_匿名)zhi_警告("unnamed 结构体/共用体 that defines no instances");带有宏替换的下个标记();继续;}如果 (是_枚举(btype.t)) {带有宏替换的下个标记();继续;}}判断 (1) { /* iterate thru each declaration */type = btype;/* If the base type itself was an array type of unspecifiedsize (like in '类型定义 整数型 arr[]; arr x = {1};') thenwe will overwrite the unknown size by the real one 循环this 声明.  We need to unshare the ref symbol holdingthat size.  */如果 ((type.t & VT_数组) && type.ref->c < 0) {type.ref = 符号_压入栈(符号_字段, &type.ref->type, 0, type.ref->c);}ad = adbase;类型_声明(&type, &ad, &v, 类型_直接);
#如果 0{字符型 buf[500];字符串_的_类型(buf, 取大小(buf), &type, 取_单词字符串(v, NULL));printf("type = '%s'\n", buf);}
#结束如果如果 ((type.t & VT_基本类型) == VT_函数) {如果 ((type.t & VT_静态) && (l == VT_LOCAL))错误_打印("function without file 范围 cannot be 静态");/* 如果 old style function prototype, we accept adeclaration list */sym = type.ref;如果 (sym->f.func_type == 函数_旧 && l == VT_VC常量)声明0(VT_CMP, 0, sym);
#如果已定义 ZHI_TARGET_MACHO如果 (sym->f.func_alwinl&& ((type.t & (VT_外部 | VT_内联))== (VT_外部 | VT_内联))) {/* always_inline functions must be handled as 如果 theydon't generate multiple global defs, even 如果 外部内联, i.e. GNU 内联 semantics 循环 those.  Rewritethem into 静态 内联.  */type.t &= ~VT_外部;type.t |= VT_静态;}
#结束如果/* always compile '外部 内联' */如果 (type.t & VT_外部)type.t &= ~VT_内联;}如果 (gnu_扩展 && (单词编码 == 关键字_asm1 || 单词编码 == 关键字_asm2 || 单词编码 == 关键字_asm3 || 单词编码 == 关键字_汇编)) {ad.汇编_label = 在字符串_查找_汇编标签并解析();/* parse one last attribute list, after asm label */解析_属性(&ad);#如果 0/* gcc不允许在函数定义中使用__asm __(“ label”),但是为什么不这样做呢? */如果 (单词编码 == '{')应为(";");#结束如果}#如果已定义 ZHI_TARGET_PE如果 (ad.a.dllimport || ad.a.dllexport) {如果 (type.t & VT_静态)错误_打印("不能与静态链接");如果 (type.t & VT_别名) {zhi_警告("使用别名(类型定义)忽略了 '%s' 属性。",ad.a.dllimport ? (ad.a.dllimport = 0, "dllimport") :(ad.a.dllexport = 0, "dllexport"));} 否则 如果 (ad.a.dllimport) {如果 ((type.t & VT_基本类型) == VT_函数)ad.a.dllimport = 0;否则type.t |= VT_外部;}}
#结束如果如果 (单词编码 == '{') {如果 (l != VT_VC常量)错误_打印("无法使用局部函数");如果 ((type.t & VT_基本类型) != VT_函数)应为("函数定义");/* 拒绝函数定义中的抽象声明符使不带decl的旧样式参数具有int类型 */sym = type.ref;判断 ((sym = sym->next) != NULL) {如果 (!(sym->v & ~符号_字段))应为("identifier");如果 (sym->type.t == VT_无类型)sym->type = int_type;}/* apply post-declaraton attributes */合并_函数属性(&type.ref->f, &ad.f);/* put function symbol */type.t &= ~VT_外部;sym = 定义外部引用_符号(v, &type, 0, &ad);/* 静态 内联 functions are just recorded as a kindof macro. Their code will be emitted at the end ofthe compilation unit only 如果 they are used */如果 (sym->type.t & VT_内联) {结构体 内联函数 *fn;fn = 内存_申请(取大小 *fn + strlen(file->文件名));strcpy(fn->文件名, file->文件名);fn->sym = sym;跳过_或_保存_块(&fn->函数_字符串);动态数组_追加元素(&zhi_状态->内联_函数数,&zhi_状态->数量_内联_函数数, fn);} 否则 {/* compute text section */当前_生成代码_段 = ad.section;如果 (!当前_生成代码_段)当前_生成代码_段 = 生成代码_段;生成_函数(sym);}跳出;} 否则 {如果 (l == VT_CMP) {/* find parameter in function parameter list */循环 (sym = func_sym->next; sym; sym = sym->next)如果 ((sym->v & ~符号_字段) == v)去向 found;错误_打印("declaration 循环 parameter '%s' but no such parameter",取_单词字符串(v, NULL));
found:如果 (type.t & VT_存储) /* 'register' is okay */错误_打印("storage class specified 循环 '%s'",取_单词字符串(v, NULL));如果 (sym->type.t != VT_无类型)错误_打印("redefinition of parameter '%s'",取_单词字符串(v, NULL));转换_函数参数_类型(&type);sym->type = type;} 否则 如果 (type.t & VT_别名) {/* save typedefed type  *//* XXX: test storage specifiers ? */sym = 符号_查询(v);如果 (sym && sym->符号_范围 == 局部_范围) {如果 (!是_兼容_类型(&sym->type, &type)|| !(sym->type.t & VT_别名))错误_打印("incompatible redefinition of '%s'",取_单词字符串(v, NULL));sym->type = type;} 否则 {sym = 符号_压入栈(v, &type, 0, 0);}sym->a = ad.a;sym->f = ad.f;} 否则 如果 ((type.t & VT_基本类型) == VT_无类型&& !(type.t & VT_外部)) {错误_打印("declaration of 无类型 object");} 否则 {r = 0;如果 ((type.t & VT_基本类型) == VT_函数) {/* external function definition *//* specific 分支 循环 函数_调用 attribute */type.ref->f = ad.f;} 否则 如果 (!(type.t & VT_数组)) {/* not lvalue 如果 array */r |= VT_LVAL;}has_init = (单词编码 == '=');如果 (has_init && (type.t & VT_变长数组))错误_打印("variable length array cannot be initialized");如果 (((type.t & VT_外部) && (!has_init || l != VT_VC常量))|| (type.t & VT_基本类型) == VT_函数/* as with GCC, uninitialized global arrays with no sizeare considered 外部: */|| ((type.t & VT_数组) && !has_init&& l == VT_VC常量 && type.ref->c < 0)) {/* external variable or function */type.t |= VT_外部;sym = 定义外部引用_符号(v, &type, r, &ad);如果 (ad.alias_target) {ELF符号 *esym;符号 *alias_target;alias_target = 符号_查询(ad.alias_target);esym = elf符号(alias_target);如果 (!esym)错误_打印("unsupported forward __alias__ attribute");更新_外部_符号2(sym, esym->st_shndx, esym->st_value, esym->st_size, 0);}} 否则 {如果 (type.t & VT_静态)r |= VT_VC常量;否则r |= l;如果 (has_init)带有宏替换的下个标记();否则 如果 (l == VT_VC常量)/* uninitialized global variables may be overridden */type.t |= VT_外部;声明_初始化_分配(&type, &ad, r, has_init, v, l);}}如果 (单词编码 != ',') {如果 (is_for_loop_init)返回 1;跳过(';');跳出;}带有宏替换的下个标记();}}}返回 0;
}静态 无类型 声明(整数型 l)
{声明0(l, 0, NULL);
}/* ------------------------------------------------------------------------- */
#取消定义 生成跳转到_固定地址
#取消定义 生成跳转到标签
/* ------------------------------------------------------------------------- */

TCC(TinyC)编译器汉化(中文编译器、汉语编程)之五:语法分析下相关推荐

  1. Eclipse汉化 中文语言包下载安装 Babel Language Pack

    相关链接 Java & Eclipse & Maven 使用配置方法 Eclipse平台上新建Java项目使用Junit测试 如何在Eclipse平台使用git从GitHub上下载文件 ...

  2. 手绘白板动画视频制作工具VideoScribe 3.11.2 Windows最新横屏竖屏方屏视频号普屏电商六合一汉化中文专业版画布和输出视频无水印支持720p和1080p高清输出

    众所周知VideoScribe(以下简称VS)有7天免费试用版,任何人都可以去下载最新的安装包体验试用,支持Windows 64位系统和macOS苹果系统.免费试用版有以下特点: 默认提供美国英语,西 ...

  3. Android Studio部分汉化中文包

    由于MarkDown维护的便利性,此文章不再维护,请转到Android Studio部分汉化中文包 MarkDown格式 已在github上新建开源翻译项目https://github.com/And ...

  4. DevExpress 汉化中文

    DevExpress 汉化中文 1.先去官网上注册(免费的) 汉化 1.先去官网上注册(免费的) 注册成功后 1.登录官网:https://search.devexpress.com 2点击SUPPO ...

  5. TCC(TinyC)编译器汉化(中文编译器、汉语编程)之一:主文件汉化

    源码下载:https://download.csdn.net/download/yuan722723/13191360 一直想学习编译器,偶然的机会接触到TCC(TinyC)编译器源码.分析源代码是学 ...

  6. 英飞凌ADS编译器汉化

    需要的链接 http://archive.eclipse.org/technology/babel/update-site/R0.17.1/2019-06/ 1. 2. 进入联网后会出来一个下拉列表, ...

  7. Android Studio部分汉化中文包 MarkDown格式

    已在github上新建开源翻译项目https://github.com/AndroidStudioTranslate/Android-Studio-Translate 从android studio发 ...

  8. BuddyPress汉化中文语言包 BuddyPress汉化教程步骤

    2019独角兽企业重金招聘Python工程师标准>>> 上传BuddyPress后,默认是英文界面,语言包文件夹里面只有一个buddypress.pot[一种PowerPoint格式 ...

  9. 说说Cisco Packet Tracer的各种汉化中文语言包

    cisco packet tracer版本更新很快,目前很多人还在使用古老的5.X版本的,因为很多资料基于5.0版本的,其实新版本是可以兼容旧版本的,当然少量的功能不能使用也是有的. 首先看看官网的介 ...

  10. 【8005】如何设置idea汉化中文?

    问题场景: 自IntelliJ Idea 2020.1 正式发布了!重要的是开始支持中文,虽然支持,但不是默认中文,你还需要下载插件安装.如果想使用中文汉化,先把版本升升级哦!(今天有个同学问我怎么汉 ...

最新文章

  1. methods vue 使用过滤器_Vue.js中过滤器(filter)的使用
  2. 一些移动端开发的细节记录
  3. react学习(62)--注意数据格式返回
  4. 分享一个绝佳的实战机器学习的机会,边学边比拿奖金!
  5. PAT乙级 1013 数素数
  6. 加拿大证券监管机构澄清加密公司监管规定
  7. 笔记下UltraEdit的一些常用使用技巧
  8. xml提交数据的方法--gin
  9. windows10开启Webdav文件服务
  10. AI 算法工程师面试高频 100 题(附答案详解)
  11. Unity 2017-2019各个版本unityhub下载连接
  12. 人工智能机器学习数据挖掘重要会议日期
  13. 僵尸网络“Mykings”
  14. windows无法格式化u盘怎么办_U盘提示格式化怎么办 U盘提示格式化解决方法【详解】...
  15. kali linux u盘 live,Kali Linux Live U盘安装过程
  16. 30分钟搭建你的静态网站
  17. FFMPEG 参数详细说明
  18. ArcMap 制图出图
  19. 人生建议:千万不要考ACCA!看完这篇文章你都知道了!
  20. 冷门绝技,让你的Origin坐标轴“断掉”

热门文章

  1. Windows Installer (无法访问你试图使用功能所在的网络位置)问题
  2. 关于R4s软路由刷机教程
  3. 玩转软路由 篇四:软路由中OpenWRT作为旁路由的安装设置教程
  4. Mac securecrt 破解版安装
  5. Bugku -disordered_zip【MISC】
  6. shell脚本中 EOF的意思
  7. 在微博投放广告有哪些优势呢?微博广告推广位置介绍!
  8. spring boot(五) 用户注册功能
  9. 【python】pandas的excel处理:员工薪水分析
  10. 《货币金融学》米什金版思维导图