static struct vector *decls(declfun_p * dcl) { struct vector *v = vec_new(); node_t *basety; int sclass, fspec; int level = SCOPE; int follow[] = {STATIC, INT, CONST, IF, '}', 0}; basety = specifiers(&sclass, &fspec); if (token->id == ID || token->id == '*' || token->id == '(') { struct token *id = NULL; node_t *ty = NULL; int params = 0; // for functioness // declarator if (level == GLOBAL) declarator(&ty, &id, ¶ms); else declarator(&ty, &id, NULL); attach_type(&ty, basety); if (level == GLOBAL && params) { if (first_funcdef(ty)) { vec_push(v, funcdef(id, ty, sclass, fspec)); return v; } else { exit_params(); } } for (;;) { if (id) { int kind; if (dcl == globaldecl) kind = GLOBAL; else if (dcl == paramdecl) kind = PARAM; else kind = LOCAL; node_t *decl = make_decl(id, ty, sclass, fspec, dcl); if (token->id == '=') decl_initializer(decl, sclass, kind); ensure_decl(decl, sclass, kind); vec_push(v, decl); } if (token->id != ',') break; expect(','); id = NULL; ty = NULL; // declarator declarator(&ty, &id, NULL); attach_type(&ty, basety); } } else if (isenum(basety) || isstruct(basety) || isunion(basety)) { // struct/union/enum int node_id; node_t *decl; if (isstruct(basety)) node_id = STRUCT_DECL; else if (isunion(basety)) node_id = UNION_DECL; else node_id = ENUM_DECL; decl = ast_decl(node_id); DECL_SYM(decl) = TYPE_TSYM(basety); vec_push(v, decl); } else { error("invalid token '%s' in declaration", token->name); } match(';', follow); return v; }
Token *build_type (typeID t, Token o, Token ret[]) { /* XXX: elliptics */ if (is_reference (t)) t = ptrdown (dereference (t)); Token tmp [100], *dcls = &tmp [20], *dcle = dcls; Token *st = open_typeID (t); int i = 1, b = 0; if (o) { *(++dcle) = -1; *dcls-- = o; } else *dcls-- = -1; for (;;i++) { switch (st [i]) { case '*': *dcls-- = '*'; b = 1; continue; case '[': if (b) *dcls-- = '(', *dcle++ = ')', b = 0; *dcle++ = '['; *dcle++ = ']'; continue; case '(': if (b) *dcls-- = '(', *dcle++ = ')', b = 0; *dcle++ = '('; for (i++;;) if (st [i] == B_ELLIPSIS) { *dcle++ = ELLIPSIS; break; } else { if (st [i] == INTERNAL_ARGEND) break; Token arg [50]; intcpy (dcle, build_type (st [i++], 0, arg)); dcle += intlen (dcle); *dcle++ = ','; } if (dcle [-1] == ',') --dcle; *dcle++ = ')'; continue; case -1: break; default: PRINTF ("UNKNWOWN %i\n", st [i]); } break; } *dcle = -1; if (st [0] >= 0) if (ISSYMBOL (st [0])) sintprintf (ret, st [0], -1); else sintprintf (ret, isunion (st [0]) ? RESERVED_union : iRESERVED_struct (st [0]), name_of_struct (st [0]), -1); else switch (st [0]) { case B_UCHAR: sintprintf (ret, RESERVED_unsigned, RESERVED_char, -1); ncase B_SCHAR: sintprintf (ret, RESERVED_char, -1); ncase B_USINT: sintprintf (ret, RESERVED_unsigned, RESERVED_short, RESERVED_int, -1); ncase B_SSINT: sintprintf (ret, RESERVED_short, RESERVED_int, -1); ncase B_UINT: sintprintf (ret, RESERVED_unsigned, RESERVED_int, -1); ncase B_SINT: sintprintf (ret, RESERVED_int, -1); ncase B_ULONG: sintprintf (ret, RESERVED_unsigned, RESERVED_long, -1); ncase B_SLONG: sintprintf (ret, RESERVED_long, -1); ncase B_ULLONG: sintprintf (ret, RESERVED_unsigned, RESERVED_long, RESERVED_long, -1); ncase B_SLLONG: sintprintf (ret, RESERVED_long, RESERVED_long, -1); ncase B_FLOAT: sintprintf (ret, RESERVED_float, -1); ncase B_DOUBLE: sintprintf (ret, RESERVED_double, -1); ncase B_VOID: sintprintf (ret, RESERVED_void, -1); } intcat (ret, dcls + 1); return ret; }