void init(int argc, char* argv[]) { {extern void input_init(int, char *[]); input_init(argc, argv);} {extern void main_init(int, char *[]); main_init(argc, argv);} {extern void prof_init(int, char *[]); prof_init(argc, argv);} {extern void trace_init(int, char *[]); trace_init(argc, argv);} {extern void type_init(int, char *[]); type_init(argc, argv);} }
/* profInit - initialize basic block profiling options */ void prof_init(int argc, char* argv[]) { int i; static int inited; if (inited) return; inited = 1; type_init(argc, argv); if (IR) { for (i = 1; i < argc; i++) if (strncmp(argv[i], "-a", 2) == 0) { if (ncalled == -1 && process(argv[i][2] ? &argv[i][2] : "prof.out") > 0) ncalled = 0; } else if ((strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-C") == 0) && YYlink == 0) { YYlink = genident(STATIC, array(unsignedtype, 0, 0), GLOBAL); attach((Apply)bbentry, YYlink, &events.entry); attach((Apply)bbexit, YYlink, &events.returns); attach((Apply)bbfunc, YYlink, &events.exit); attach((Apply)bbvars, YYlink, &events.end); if (strcmp(argv[i], "-b") == 0) { YYcounts = genident(STATIC, array(unsignedtype, 0, 0), GLOBAL); maplist = append(allocate(sizeof(struct map), PERM), maplist); ((struct map*)maplist->x)->size = 0; attach((Apply)bbcall, YYcounts, &events.calls); attach((Apply)bbincr, YYcounts, &events.points); } } } }
/* Parse array declarations of the form [s0][s1]..[sn], resulting in type * [s0] [s1] .. [sn] (base). * * Only the first dimension s0 can be unspecified, yielding an incomplete type. * Incomplete types are represented by having size of zero. */ static struct typetree *direct_declarator_array(struct typetree *base) { if (peek().token == '[') { long length = 0; consume('['); if (peek().token != ']') { struct var expr = constant_expression(); assert(expr.kind == IMMEDIATE); if (!is_integer(expr.type) || expr.imm.i < 1) { error("Array dimension must be a natural number."); exit(1); } length = expr.imm.i; } consume(']'); base = direct_declarator_array(base); if (!size_of(base)) { error("Array has incomplete element type."); exit(1); } base = type_init(T_ARRAY, base, length); } return base; }
static struct block *primary_expression(struct block *block) { const struct symbol *sym; struct token tok; switch ((tok = next()).token) { case IDENTIFIER: sym = sym_lookup(&ns_ident, tok.strval); if (!sym) { error("Undefined symbol '%s'.", tok.strval); exit(1); } /* Special handling for builtin pseudo functions. These are expected to * behave as macros, thus should be no problem parsing as function call * in primary expression. Constructs like (va_arg)(args, int) will not * work with this scheme. */ if (!strcmp("__builtin_va_start", sym->name)) { block = parse__builtin_va_start(block); } else if (!strcmp("__builtin_va_arg", sym->name)) { block = parse__builtin_va_arg(block); } else { block->expr = var_direct(sym); } break; case INTEGER_CONSTANT: block->expr = var_int(tok.intval); break; case '(': block = expression(block); consume(')'); break; case STRING: sym = sym_add(&ns_ident, ".LC", type_init(T_ARRAY, &basic_type__char, strlen(tok.strval) + 1), SYM_STRING_VALUE, LINK_INTERN); /* Store string value directly on symbol, memory ownership is in string * table from previously called str_register. The symbol now exists as * if it was declared static char .LC[] = "...". */ ((struct symbol *) sym)->string_value = tok.strval; /* Result is an IMMEDIATE of type [] char, with a reference to the new * symbol containing the string literal. Will decay into char * on * evaluation. */ block->expr = var_direct(sym); assert(block->expr.kind == IMMEDIATE); break; default: error("Unexpected '%s', not a valid primary expression.", tok.strval); exit(1); } return block; }
int main(void) { GC_INIT(); GREG g; int jval, jval2; char c; sym_tab_init(); ast_init(); type_init(); scope_init(); rel_assign_init(); jit_t * jit = llvm_init(); yyinit(&g); printf("Welcome to Cesium v 0.2\n"); printf("To exit press CTRL-D\n\n"); printf("> "); while (1) { if (!(jval = setjmp(exc))) { if (!yyparse(&g)) { printf("Error parsing\n"); abort(); } else if (root != NULL) { rel_stack_init(); rel_assign_mark(); scope_mark(); annotate_ast(root); if (TRACE) ast_print(root, 0); unify(rel_stack, rel_assign); if (TRACE) print_assigns(rel_assign); exec_root(jit, root); if (root->tag != AST_FNDEC) rel_assign_rewind(); } } else if (jval == 1) root = NULL; else if (jval == 2) break; printf("\n> "); } yydeinit(&g); llvm_cleanup(jit); return 0; }
RutObject * _rut_object_alloc0 (size_t bytes, RutType *type, RutTypeInit type_init) { RutObject *object = g_slice_alloc0 (bytes); if (G_UNLIKELY (type->name == NULL)) type_init (); rut_object_init (object, type); return object; }
/* C99: Define __func__ as static const char __func__[] = sym->name; */ static void define_builtin__func__(const char *name) { struct typetree *type; struct symbol *sym; assert(ns_ident.current_depth == 1); /* Just add the symbol directly as a special string value. No explicit * assignment reflected in the IR. */ type = type_init(T_ARRAY, &basic_type__char, strlen(name) + 1); sym = sym_add(&ns_ident, "__func__", type, SYM_STRING_VALUE, LINK_INTERN); sym->string_value = name; }
void file_manager__init () { new_file_manager = ayyi_filemanager_new(); type_init(); pixmaps_init(); dir_init(); g_idle_add(_load_plugins, NULL); initialised = TRUE; }
void backend_init() { ph_init(); block_init(); cod3_setdefault(); if (global.params.is64bit) { util_set64(); type_init(); cod3_set64(); } else { util_set32(); type_init(); cod3_set32(); } rtlsym_init(); // uses fregsaved, so must be after it's set inside cod3_set* out_config_init(); }
/* trace_init - initialize for tracing */ void trace_init(int argc, char *argv[]) { int i; static int inited; if (inited) return; inited = 1; type_init(argc, argv); if (IR) for (i = 1; i < argc; i++) if (strncmp(argv[i], "-t", 2) == 0 && strchr(argv[i], '=') == NULL) { Symbol printer = mksymbol(EXTERN, argv[i][2] ? &argv[i][2] : "printf", ftype(inttype, ptr(qual(CONST, chartype)))); printer->defined = 0; attach((Apply)tracecall, printer, &events.entry); attach((Apply)tracereturn, printer, &events.returns); break; } }
/* FOLLOW(parameter-list) = { ')' }, peek to return empty list; even though K&R * require at least specifier: (void) * Set parameter-type-list = parameter-list, including the , ... */ static struct typetree *parameter_list(const struct typetree *base) { struct typetree *func = type_init(T_FUNCTION); func->next = base; while (peek().token != ')') { const char *name = NULL; struct typetree *type; type = declaration_specifiers(NULL); type = declarator(type, &name); if (is_void(type)) { if (nmembers(func)) { error("Incomplete type in parameter list."); } break; } type_add_member(func, name, type); if (peek().token != ',') { break; } consume(','); if (peek().token == ')') { error("Unexpected trailing comma in parameter list."); exit(1); } else if (peek().token == DOTS) { consume(DOTS); assert(!is_vararg(func)); type_add_member(func, "...", NULL); assert(is_vararg(func)); break; } } return func; }
/** * 函数系统初始化 **/ int function_init() { /*防止多次初始化*/ /*没有初始化或者初始化失败可以进行初始化*/ static int init = 0; if(init == 1) return 0; init = 1; /*创建函数信息的哈希表*/ func_hash = hash_new(20, func_equal, func_copy, free_func); if(!func_hash) { init = -1; return init; } /*初始化类型信息系统*/ if(type_init() < 0) { init = -1; return init; } return 0; }
static struct typetree *pointer(const struct typetree *base) { struct typetree *type = type_init(T_POINTER, base); #define set_qualifier(d) \ if (type->qualifier & d) \ error("Duplicate type qualifier '%s'.", peek().strval); \ type->qualifier |= d; consume('*'); while (1) { if (peek().token == CONST) { set_qualifier(Q_CONST); } else if (peek().token == VOLATILE) { set_qualifier(Q_VOLATILE); } else break; next(); } #undef set_qualifier return type; }
/* main_init - process program arguments */ void main_init(int argc, char *argv[]) { char *infile = NULL, *outfile = NULL; int i; static int inited; if (inited) return; inited = 1; type_init(argc, argv); for (i = 1; i < argc; i++) if (strcmp(argv[i], "-g") == 0 || strcmp(argv[i], "-g2") == 0) glevel = 2; else if (strncmp(argv[i], "-g", 2) == 0) { /* -gn[,x] */ char *p = strchr(argv[i], ','); glevel = atoi(argv[i]+2); if (p) { comment = p + 1; if (glevel == 0) glevel = 1; if (stabIR.stabline == NULL) { stabIR.stabline = IR->stabline; stabIR.stabend = IR->stabend; IR->stabline = stabline; IR->stabend = stabend; } } } else if (strcmp(argv[i], "-x") == 0) xref++; else if (strcmp(argv[i], "-A") == 0) { ++Aflag; } else if (strcmp(argv[i], "-P") == 0) Pflag++; else if (strcmp(argv[i], "-w") == 0) wflag++; else if (strcmp(argv[i], "-n") == 0) { if (!YYnull) { YYnull = install(string("_YYnull"), &globals, GLOBAL, PERM); YYnull->type = func(voidptype, NULL, 1); YYnull->sclass = EXTERN; (*IR->defsymbol)(YYnull); } } else if (strncmp(argv[i], "-n", 2) == 0) { /* -nvalid[,check] */ char *p = strchr(argv[i], ','); if (p) { YYcheck = install(string(p+1), &globals, GLOBAL, PERM); YYcheck->type = func(voidptype, NULL, 1); YYcheck->sclass = EXTERN; (*IR->defsymbol)(YYcheck); p = stringn(argv[i]+2, p - (argv[i]+2)); } else p = string(argv[i]+2); YYnull = install(p, &globals, GLOBAL, PERM); YYnull->type = func(voidptype, NULL, 1); YYnull->sclass = EXTERN; (*IR->defsymbol)(YYnull); } else if (strcmp(argv[i], "-v") == 0) fprint(stderr, "%s %s\n", argv[0], rcsid); else if (strncmp(argv[i], "-s", 2) == 0) density = strtod(&argv[i][2], NULL); else if (strncmp(argv[i], "-errout=", 8) == 0) { FILE *f = fopen(argv[i]+8, "w"); if (f == NULL) { fprint(stderr, "%s: can't write errors to `%s'\n", argv[0], argv[i]+8); exit(EXIT_FAILURE); } fclose(f); f = freopen(argv[i]+8, "w", stderr); assert(f); } else if (strncmp(argv[i], "-e", 2) == 0) { int x; if ((x = strtol(&argv[i][2], NULL, 0)) > 0) errlimit = x; } else if (strncmp(argv[i], "-little_endian=", 15) == 0) IR->little_endian = argv[i][15] - '0'; else if (strncmp(argv[i], "-mulops_calls=", 18) == 0) IR->mulops_calls = argv[i][18] - '0'; else if (strncmp(argv[i], "-wants_callb=", 13) == 0) IR->wants_callb = argv[i][13] - '0'; else if (strncmp(argv[i], "-wants_argb=", 12) == 0) IR->wants_argb = argv[i][12] - '0'; else if (strncmp(argv[i], "-left_to_right=", 15) == 0) IR->left_to_right = argv[i][15] - '0'; else if (strncmp(argv[i], "-wants_dag=", 11) == 0) IR->wants_dag = argv[i][11] - '0'; else if (*argv[i] != '-' || strcmp(argv[i], "-") == 0) { if (infile == NULL) infile = argv[i]; else if (outfile == NULL) outfile = argv[i]; } if (infile != NULL && strcmp(infile, "-") != 0 && freopen(infile, "r", stdin) == NULL) { fprint(stderr, "%s: can't read `%s'\n", argv[0], infile); exit(EXIT_FAILURE); } if (outfile != NULL && strcmp(outfile, "-") != 0 && freopen(outfile, "w", stdout) == NULL) { fprint(stderr, "%s: can't write `%s'\n", argv[0], outfile); exit(EXIT_FAILURE); } }
void out_config_init( int model, // 32: 32 bit code // 64: 64 bit code // Windows: set bit 0 to generate MS-COFF instead of OMF bool exe, // true: exe file // false: dll or shared library (generate PIC code) bool trace, // add profiling code bool nofloat, // do not pull in floating point code bool verbose, // verbose compile bool optimize, // optimize code int symdebug, // add symbolic debug information // 1: D // 2: fake it with C symbolic debug info bool alwaysframe, // always create standard function frame bool stackstomp, // add stack stomping code unsigned char avx, // use AVX instruction set (0, 1, 2) bool betterC // implement "Better C" ) { #if MARS //printf("out_config_init()\n"); if (!config.target_cpu) { config.target_cpu = TARGET_PentiumPro; config.target_scheduler = config.target_cpu; } config.fulltypes = CVNONE; config.fpxmmregs = FALSE; config.inline8087 = 1; config.memmodel = 0; config.flags |= CFGuchar; // make sure TYchar is unsigned tytab[TYchar] |= TYFLuns; bool mscoff = model & 1; model &= 32 | 64; #if TARGET_WINDOS if (model == 64) { config.exe = EX_WIN64; config.fpxmmregs = TRUE; config.avx = avx; config.ehmethod = betterC ? EH_NONE : EH_DM; // Not sure we really need these two lines, try removing them later config.flags |= CFGnoebp; config.flags |= CFGalwaysframe; config.flags |= CFGromable; // put switch tables in code segment config.objfmt = OBJ_MSCOFF; } else { config.exe = EX_WIN32; config.ehmethod = betterC ? EH_NONE : EH_WIN32; config.objfmt = mscoff ? OBJ_MSCOFF : OBJ_OMF; } if (exe) config.wflags |= WFexe; // EXE file only optimizations config.flags4 |= CFG4underscore; #endif #if TARGET_LINUX if (model == 64) { config.exe = EX_LINUX64; config.ehmethod = betterC ? EH_NONE : EH_DWARF; config.fpxmmregs = TRUE; config.avx = avx; } else { config.exe = EX_LINUX; config.ehmethod = betterC ? EH_NONE : EH_DWARF; if (!exe) config.flags |= CFGromable; // put switch tables in code segment } config.flags |= CFGnoebp; if (!exe) { config.flags3 |= CFG3pic; config.flags |= CFGalwaysframe; // PIC needs a frame for TLS fixups } config.objfmt = OBJ_ELF; #endif #if TARGET_OSX config.fpxmmregs = TRUE; config.avx = avx; if (model == 64) { config.exe = EX_OSX64; config.fpxmmregs = TRUE; config.ehmethod = betterC ? EH_NONE : EH_DWARF; } else { config.exe = EX_OSX; config.ehmethod = betterC ? EH_NONE : EH_DWARF; } config.flags |= CFGnoebp; if (!exe) { config.flags3 |= CFG3pic; config.flags |= CFGalwaysframe; // PIC needs a frame for TLS fixups } config.flags |= CFGromable; // put switch tables in code segment config.objfmt = OBJ_MACH; #endif #if TARGET_FREEBSD if (model == 64) { config.exe = EX_FREEBSD64; config.ehmethod = betterC ? EH_NONE : EH_DWARF; config.fpxmmregs = TRUE; config.avx = avx; } else { config.exe = EX_FREEBSD; config.ehmethod = betterC ? EH_NONE : EH_DWARF; if (!exe) config.flags |= CFGromable; // put switch tables in code segment } config.flags |= CFGnoebp; if (!exe) { config.flags3 |= CFG3pic; config.flags |= CFGalwaysframe; // PIC needs a frame for TLS fixups } config.objfmt = OBJ_ELF; #endif #if TARGET_OPENBSD if (model == 64) { config.exe = EX_OPENBSD64; config.fpxmmregs = TRUE; config.avx = avx; } else { config.exe = EX_OPENBSD; if (!exe) config.flags |= CFGromable; // put switch tables in code segment } config.flags |= CFGnoebp; config.flags |= CFGalwaysframe; if (!exe) config.flags3 |= CFG3pic; config.objfmt = OBJ_ELF; config.ehmethod = betterC ? EH_NONE : EH_DM; #endif #if TARGET_SOLARIS if (model == 64) { config.exe = EX_SOLARIS64; config.fpxmmregs = TRUE; config.avx = avx; } else { config.exe = EX_SOLARIS; if (!exe) config.flags |= CFGromable; // put switch tables in code segment } config.flags |= CFGnoebp; config.flags |= CFGalwaysframe; if (!exe) config.flags3 |= CFG3pic; config.objfmt = OBJ_ELF; config.ehmethod = betterC ? EH_NONE : EH_DM; #endif config.flags2 |= CFG2nodeflib; // no default library config.flags3 |= CFG3eseqds; #if 0 if (env->getEEcontext()->EEcompile != 2) config.flags4 |= CFG4allcomdat; if (env->nochecks()) config.flags4 |= CFG4nochecks; // no runtime checking #elif TARGET_OSX #else config.flags4 |= CFG4allcomdat; #endif if (trace) config.flags |= CFGtrace; // turn on profiler if (nofloat) config.flags3 |= CFG3wkfloat; configv.verbose = verbose; if (optimize) go_flag((char *)"-o"); if (symdebug) { #if SYMDEB_DWARF configv.addlinenumbers = 1; config.fulltypes = (symdebug == 1) ? CVDWARF_D : CVDWARF_C; #endif #if SYMDEB_CODEVIEW if (config.objfmt == OBJ_MSCOFF) { configv.addlinenumbers = 1; config.fulltypes = CV8; if(symdebug > 1) config.flags2 |= CFG2gms; } else { configv.addlinenumbers = 1; config.fulltypes = CV4; } #endif if (!optimize) config.flags |= CFGalwaysframe; } else { configv.addlinenumbers = 0; config.fulltypes = CVNONE; //config.flags &= ~CFGalwaysframe; } if (alwaysframe) config.flags |= CFGalwaysframe; if (stackstomp) config.flags2 |= CFG2stomp; config.betterC = betterC; ph_init(); block_init(); cod3_setdefault(); if (model == 64) { util_set64(); type_init(); cod3_set64(); } else { util_set32(); type_init(); cod3_set32(); } rtlsym_init(); // uses fregsaved, so must be after it's set inside cod3_set* #endif }
int main(int argc, char* argv[]) { _debug_ = 0; samplecat_init(); gtk_init_check(&argc, &argv); type_init(); pixmaps_init(); icon_theme_init(); Window win; GLXContext ctx; GLboolean fullscreen = GL_FALSE; static int width = 400, height = 300; int i; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "-verbose") == 0) { _debug_ = 1; } #if 0 else if (strcmp(argv[i], "-swap") == 0 && i + 1 < argc) { swap_interval = atoi( argv[i+1] ); do_swap_interval = GL_TRUE; i++; } else if (strcmp(argv[i], "-forcegetrate") == 0) { /* This option was put in because some DRI drivers don't support the * full GLX_OML_sync_control extension, but they do support * glXGetMscRateOML. */ force_get_rate = GL_TRUE; } #endif else if (strcmp(argv[i], "-fullscreen") == 0) { fullscreen = GL_TRUE; } else if (strcmp(argv[i], "-help") == 0) { printf("Usage:\n"); printf(" glx [options]\n"); printf("Options:\n"); printf(" -help Print this information\n"); printf(" -verbose Output info to stdout\n"); printf(" -swap N Swap no more than once per N vertical refreshes\n"); printf(" -forcegetrate Try to use glXGetMscRateOML function\n"); printf(" -fullscreen Full-screen window\n"); return 0; } } Display* dpy = XOpenDisplay(NULL); if(!dpy){ printf("Error: couldn't open display %s\n", XDisplayName(NULL)); return -1; } int screen = DefaultScreen(dpy); make_window(dpy, "Samplcecat", (XDisplayWidth(dpy, screen) - width) / 2, (XDisplayHeight(dpy, screen) - height) / 2, width, height, fullscreen, &win, &ctx); agl_get_extensions(); glx_init(dpy); g_main_loop_new(NULL, true); scene = (AGlRootActor*)agl_actor__new_root_(CONTEXT_TYPE_GLX); void scene_needs_redraw(AGlScene* scene, gpointer _){ need_draw = true; } scene->draw = scene_needs_redraw; gboolean add_content(gpointer _) { app->config_ctx.filename = g_strdup_printf("%s/.config/" PACKAGE "/" PACKAGE, g_get_home_dir()); config_load(&app->config_ctx, &app->config); if (app->config.database_backend && can_use(samplecat.model->backends, app->config.database_backend)) { #define list_clear(L) g_list_free(L); L = NULL; list_clear(samplecat.model->backends); samplecat_model_add_backend(app->config.database_backend); } db_init( #ifdef USE_MYSQL &app->config.mysql #else NULL #endif ); if (!db_connect()) { g_warning("cannot connect to any database.\n"); return EXIT_FAILURE; } samplecat_list_store_do_search((SamplecatListStore*)samplecat.store); Waveform* w = NULL; WaveformCanvas* wfc = wf_context_new(scene); agl_actor__add_child((AGlActor*)scene, actors.bg = background_actor(NULL)); actors.bg->region.x2 = 1; actors.bg->region.y2 = 1; agl_actor__add_child((AGlActor*)scene, actors.search = search_view(NULL)); agl_actor__add_child((AGlActor*)scene, actors.list = list_view(NULL)); agl_actor__add_child((AGlActor*)scene, actors.wave = (AGlActor*)wf_canvas_add_new_actor(wfc, w)); void scene_set_size(AGlActor* scene) { #define SPACING 2 int vspace = scene->region.y2 - 40; int y = 20; int h = search_view_height((SearchView*)actors.search); actors.search->region = (AGliRegion){20, y, scene->region.x2 - 20, y + h}; agl_actor__set_size(actors.search); vspace -= h + SPACING; y += h + SPACING; actors.list->region = (AGliRegion){20, y, scene->region.x2 - 20, y + vspace / 2}; vspace -= vspace / 2; y += vspace; agl_actor__set_size(actors.list); // clear cache actors.wave->region = (AGliRegion){ 20, y, scene->region.x2 - 20, y + vspace }; wf_actor_set_rect((WaveformActor*)actors.wave, &(WfRectangle){ 0.0, 0.0, agl_actor__width(actors.wave), agl_actor__height(actors.wave) }); need_draw = true; }
int main(int argc, char **argv) { struct type_info *type; char *bi[] = {"int", "short", "char", "void *"}; char *bi2[] = {"struct hello", "struct ok", "struct hello", "struct hello *", "struct you", "struct f**k", "struct muni", "struct fuck_you_foreya"}; int i = 0; struct func_info *fi; struct variant_info *vi; char *types[] = {"int", "struct hello", "struct pointrt", "struct he", "int * *"}; char *names[] = {"k", "j", "f**k", "you", "doc"}; char *param_list[] = {"char * hua , int hello", "void", "", "void * hello", "void * type , struct hello * * f**k , int k"}; char *name; struct HashTable *func_table; type_init(); for(i = 0; i < sizeof(bi) / sizeof(char*); i ++) { type = get_type(bi[i]); printf("full_name:%s, name:%s, level:%d, len:%d, is_struct:%d\n", bi[i], type->ti_name, type->pointer_level, type->len, type->is_struct); } for(i = 0; i < sizeof(bi2)/ sizeof(char*); i ++) { type = create_type_info(bi2[i], i + 1); } for(i = 0; i < sizeof(bi2) / sizeof(char*); i ++) { type = get_type(bi2[i]); printf("Full name:%s, name %s, level %d, len %d, is_struct %d, ref %d\n", bi2[i], type->si->name, type->pointer_level, type->len, type->is_struct, type->ref); } /*测试函数信息*/ function_init(); func_table = create_func_table(); printf("--------------function------------------------\n"); for(i = 0; i < sizeof(types) / sizeof(char*); i ++) { fi = create_func_info(types[i], names[i], param_list[i]); printf("%d\n", insert_func_table(func_table, fi)); } for(i = 0; i < sizeof(types) / sizeof(char*); i ++) { fi = get_func_from_table(func_table, names[i]); printf("Full-name:%s, param_num:%d, name:%s\n", names[i], fi->param_info->param_num, fi->fi_name); print_type_info(fi->ret_info); print_param_info(fi->param_info); } printf("---------------------------------------------\n"); for(i = 0; i < sizeof(types) / sizeof(char*); i ++) { vi = create_variant_info(types[i], names[i]); if(vi->type_info->is_struct) name = vi->type_info->si->name; else name = vi->type_info->ti_name; printf("full-name:%s, type_name:%s, real_name:%s, ref:%d\n", names[i], name, vi->vi_name, vi->type_info->ref); } return 0; }
static struct block *postfix_expression(struct block *block) { struct var root; block = primary_expression(block); root = block->expr; while (1) { const struct member *field; const struct typetree *type; struct var expr, copy, *arg; struct token tok; int i, j; switch ((tok = peek()).token) { case '[': do { /* Evaluate a[b] = *(a + b). The semantics of pointer arithmetic * takes care of multiplying b with the correct width. */ consume('['); block = expression(block); root = eval_expr(block, IR_OP_ADD, root, block->expr); root = eval_deref(block, root); consume(']'); } while (peek().token == '['); break; case '(': type = root.type; if (is_pointer(root.type) && is_function(root.type->next)) type = type_deref(root.type); else if (!is_function(root.type)) { error("Expression must have type pointer to function, was %t.", root.type); exit(1); } consume('('); arg = calloc(nmembers(type), sizeof(*arg)); for (i = 0; i < nmembers(type); ++i) { if (peek().token == ')') { error("Too few arguments, expected %d but got %d.", nmembers(type), i); exit(1); } block = assignment_expression(block); arg[i] = block->expr; /* todo: type check here. */ if (i < nmembers(type) - 1) { consume(','); } } while (is_vararg(type) && peek().token != ')') { consume(','); arg = realloc(arg, (i + 1) * sizeof(*arg)); block = assignment_expression(block); arg[i] = block->expr; i++; } consume(')'); for (j = 0; j < i; ++j) param(block, arg[j]); free(arg); root = eval_call(block, root); break; case '.': consume('.'); tok = consume(IDENTIFIER); field = find_type_member(root.type, tok.strval); if (!field) { error("Invalid field access, no member named '%s'.", tok.strval); exit(1); } root.type = field->type; root.offset += field->offset; break; case ARROW: consume(ARROW); tok = consume(IDENTIFIER); if (is_pointer(root.type) && is_struct_or_union(root.type->next)) { field = find_type_member(type_deref(root.type), tok.strval); if (!field) { error("Invalid field access, no member named '%s'.", tok.strval); exit(1); } /* Make it look like a pointer to the field type, then perform * normal dereferencing. */ root.type = type_init(T_POINTER, field->type); root = eval_deref(block, root); root.offset = field->offset; } else { error("Invalid field access."); exit(1); } break; case INCREMENT: consume(INCREMENT); copy = create_var(root.type); eval_assign(block, copy, root); expr = eval_expr(block, IR_OP_ADD, root, var_int(1)); eval_assign(block, root, expr); root = copy; break; case DECREMENT: consume(DECREMENT); copy = create_var(root.type); eval_assign(block, copy, root); expr = eval_expr(block, IR_OP_SUB, root, var_int(1)); eval_assign(block, root, expr); root = copy; break; default: block->expr = root; return block; } } }
static void member_declaration_list(struct typetree *type) { struct namespace ns = {0}; struct typetree *decl_base, *decl_type; const char *name; push_scope(&ns); do { decl_base = declaration_specifiers(NULL); do { name = NULL; decl_type = declarator(decl_base, &name); if (!name) { error("Missing name in member declarator."); exit(1); } else if (!size_of(decl_type)) { error("Field '%s' has incomplete type '%t'.", name, decl_type); exit(1); } else { sym_add(&ns, name, decl_type, SYM_DECLARATION, LINK_NONE); type_add_member(type, name, decl_type); } if (peek().token == ',') { consume(','); continue; } } while (peek().token != ';'); consume(';'); } while (peek().token != '}'); pop_scope(&ns); } static struct typetree *struct_or_union_declaration(void) { struct symbol *sym = NULL; struct typetree *type = NULL; enum type kind = (next().token == STRUCT) ? T_STRUCT : T_UNION; if (peek().token == IDENTIFIER) { const char *name = consume(IDENTIFIER).strval; sym = sym_lookup(&ns_tag, name); if (!sym) { type = type_init(kind); sym = sym_add(&ns_tag, name, type, SYM_TYPEDEF, LINK_NONE); } else if (is_integer(&sym->type)) { error("Tag '%s' was previously declared as enum.", sym->name); exit(1); } else if (sym->type.type != kind) { error("Tag '%s' was previously declared as %s.", sym->name, (sym->type.type == T_STRUCT) ? "struct" : "union"); exit(1); } /* Retrieve type from existing symbol, possibly providing a complete * definition that will be available for later declarations. Overwrites * existing type information from symbol table. */ type = &sym->type; if (peek().token == '{' && type->size) { error("Redefiniton of '%s'.", sym->name); exit(1); } } if (peek().token == '{') { if (!type) { /* Anonymous structure; allocate a new standalone type, * not part of any symbol. */ type = type_init(kind); } consume('{'); member_declaration_list(type); assert(type->size); consume('}'); } /* Return to the caller a copy of the root node, which can be overwritten * with new type qualifiers without altering the tag registration. */ return (sym) ? type_tagged_copy(&sym->type, sym->name) : type; } static void enumerator_list(void) { struct var val; struct symbol *sym; int enum_value = 0; consume('{'); do { const char *name = consume(IDENTIFIER).strval; if (peek().token == '=') { consume('='); val = constant_expression(); if (!is_integer(val.type)) { error("Implicit conversion from non-integer type in enum."); } enum_value = val.imm.i; } sym = sym_add( &ns_ident, name, &basic_type__int, SYM_ENUM_VALUE, LINK_NONE); sym->enum_value = enum_value++; if (peek().token != ',') break; consume(','); } while (peek().token != '}'); consume('}'); } static struct typetree *enum_declaration(void) { struct typetree *type = type_init(T_SIGNED, 4); consume(ENUM); if (peek().token == IDENTIFIER) { struct symbol *tag = NULL; const char *name = consume(IDENTIFIER).strval; tag = sym_lookup(&ns_tag, name); if (!tag || tag->depth < ns_tag.current_depth) { tag = sym_add(&ns_tag, name, type, SYM_TYPEDEF, LINK_NONE); } else if (!is_integer(&tag->type)) { error("Tag '%s' was previously defined as aggregate type.", tag->name); exit(1); } /* Use enum_value as a sentinel to represent definition, checked on * lookup to detect duplicate definitions. */ if (peek().token == '{') { if (tag->enum_value) { error("Redefiniton of enum '%s'.", tag->name); } enumerator_list(); tag->enum_value = 1; } } else { enumerator_list(); } /* Result is always integer. Do not care about the actual enum definition, * all enums are ints and no type checking is done. */ return type; } static struct typetree get_basic_type_from_specifier(unsigned short spec) { switch (spec) { case 0x0001: /* void */ return basic_type__void; case 0x0002: /* char */ case 0x0012: /* signed char */ return basic_type__char; case 0x0022: /* unsigned char */ return basic_type__unsigned_char; case 0x0004: /* short */ case 0x0014: /* signed short */ case 0x000C: /* short int */ case 0x001C: /* signed short int */ return basic_type__short; case 0x0024: /* unsigned short */ case 0x002C: /* unsigned short int */ return basic_type__unsigned_short; case 0x0008: /* int */ case 0x0010: /* signed */ case 0x0018: /* signed int */ return basic_type__int; case 0x0020: /* unsigned */ case 0x0028: /* unsigned int */ return basic_type__unsigned_int; case 0x0040: /* long */ case 0x0050: /* signed long */ case 0x0048: /* long int */ case 0x0058: /* signed long int */ case 0x00C0: /* long long */ case 0x00D0: /* signed long long */ case 0x00D8: /* signed long long int */ return basic_type__long; case 0x0060: /* unsigned long */ case 0x0068: /* unsigned long int */ case 0x00E0: /* unsigned long long */ case 0x00E8: /* unsigned long long int */ return basic_type__unsigned_long; case 0x0100: /* float */ return basic_type__float; case 0x0200: /* double */ case 0x0240: /* long double */ return basic_type__double; default: error("Invalid type specification."); exit(1); } } /* Parse type, qualifiers and storage class. Do not assume int by default, but * require at least one type specifier. Storage class is returned as token * value, unless the provided pointer is NULL, in which case the input is parsed * as specifier-qualifier-list. */ struct typetree *declaration_specifiers(int *stc) { struct typetree *type = NULL; struct token tok; int done = 0; /* Use a compact bit representation to hold state about declaration * specifiers. Initialize storage class to sentinel value. */ unsigned short spec = 0x0000; enum qualifier qual = Q_NONE; if (stc) *stc = '$'; #define set_specifier(d) \ if (spec & d) error("Duplicate type specifier '%s'.", tok.strval); \ next(); spec |= d; #define set_qualifier(d) \ if (qual & d) error("Duplicate type qualifier '%s'.", tok.strval); \ next(); qual |= d; #define set_storage_class(t) \ if (!stc) error("Unexpected storage class in qualifier list."); \ else if (*stc != '$') error("Multiple storage class specifiers."); \ next(); *stc = t; do { switch ((tok = peek()).token) { case VOID: set_specifier(0x001); break; case CHAR: set_specifier(0x002); break; case SHORT: set_specifier(0x004); break; case INT: set_specifier(0x008); break; case SIGNED: set_specifier(0x010); break; case UNSIGNED: set_specifier(0x020); break; case LONG: if (spec & 0x040) { set_specifier(0x080); } else { set_specifier(0x040); } break; case FLOAT: set_specifier(0x100); break; case DOUBLE: set_specifier(0x200); break; case CONST: set_qualifier(Q_CONST); break; case VOLATILE: set_qualifier(Q_VOLATILE); break; case IDENTIFIER: { struct symbol *tag = sym_lookup(&ns_ident, tok.strval); if (tag && tag->symtype == SYM_TYPEDEF && !type) { consume(IDENTIFIER); type = type_init(T_STRUCT); *type = tag->type; } else { done = 1; } break; } case UNION: case STRUCT: if (!type) { type = struct_or_union_declaration(); } else { done = 1; } break; case ENUM: if (!type) { type = enum_declaration(); } else { done = 1; } break; case AUTO: case REGISTER: case STATIC: case EXTERN: case TYPEDEF: set_storage_class(tok.token); break; default: done = 1; break; } if (type && spec) { error("Invalid combination of declaration specifiers."); exit(1); } } while (!done); #undef set_specifier #undef set_qualifier #undef set_storage_class if (type) { if (qual & type->qualifier) { error("Duplicate type qualifier:%s%s.", (qual & Q_CONST) ? " const" : "", (qual & Q_VOLATILE) ? " volatile" : ""); } } else if (spec) { type = type_init(T_STRUCT); *type = get_basic_type_from_specifier(spec); } else { error("Missing type specifier."); exit(1); } type->qualifier |= qual; return type; } /* Set var = 0, using simple assignment on members for composite types. This * rule does not consume any input, but generates a series of assignments on the * given variable. Point is to be able to zero initialize using normal simple * assignment rules, although IR can become verbose for large structures. */ static void zero_initialize(struct block *block, struct var target) { int i; struct var var; assert(target.kind == DIRECT); switch (target.type->type) { case T_STRUCT: case T_UNION: target.type = unwrapped(target.type); var = target; for (i = 0; i < nmembers(var.type); ++i) { target.type = get_member(var.type, i)->type; target.offset = var.offset + get_member(var.type, i)->offset; zero_initialize(block, target); } break; case T_ARRAY: assert(target.type->size); var = target; target.type = target.type->next; assert(is_struct(target.type) || !target.type->next); for (i = 0; i < var.type->size / var.type->next->size; ++i) { target.offset = var.offset + i * var.type->next->size; zero_initialize(block, target); } break; case T_POINTER: var = var_zero(8); var.type = type_init(T_POINTER, &basic_type__void); eval_assign(block, target, var); break; case T_UNSIGNED: case T_SIGNED: var = var_zero(target.type->size); eval_assign(block, target, var); break; default: error("Invalid type to zero-initialize, was '%t'.", target.type); exit(1); } }
static struct block *object_initializer(struct block *block, struct var target) { int i, filled = target.offset; const struct typetree *type = target.type; assert(!is_tagged(type)); consume('{'); target.lvalue = 1; switch (type->type) { case T_UNION: /* C89 states that only the first element of a union can be * initialized. Zero the whole thing first if there is padding. */ if (size_of(get_member(type, 0)->type) < type->size) { target.type = (type->size % 8) ? type_init(T_ARRAY, &basic_type__char, type->size) : type_init(T_ARRAY, &basic_type__long, type->size / 8); zero_initialize(block, target); } target.type = get_member(type, 0)->type; block = initializer(block, target); if (peek().token != '}') { error("Excess elements in union initializer."); exit(1); } break; case T_STRUCT: for (i = 0; i < nmembers(type); ++i) { target.type = get_member(type, i)->type; target.offset = filled + get_member(type, i)->offset; block = initializer(block, target); if (peek().token == ',') { consume(','); } else break; if (peek().token == '}') { break; } } while (++i < nmembers(type)) { target.type = get_member(type, i)->type; target.offset = filled + get_member(type, i)->offset; zero_initialize(block, target); } break; case T_ARRAY: target.type = type->next; for (i = 0; !type->size || i < type->size / size_of(type->next); ++i) { target.offset = filled + i * size_of(type->next); block = initializer(block, target); if (peek().token == ',') { consume(','); } else break; if (peek().token == '}') { break; } } if (!type->size) { assert(!target.symbol->type.size); assert(is_array(&target.symbol->type)); /* Incomplete array type can only be in the root level of target * type tree, overwrite type directly in symbol. */ ((struct symbol *) target.symbol)->type.size = (i + 1) * size_of(type->next); } else { while (++i < type->size / size_of(type->next)) { target.offset = filled + i * size_of(type->next); zero_initialize(block, target); } } break; default: error("Block initializer only apply to aggregate or union type."); exit(1); } consume('}'); return block; }