/* cleanup all static data used during compilation */ static void tcc_cleanup(void) { int i, n; if (NULL == tcc_state) { return; } tcc_state = NULL; /* free -D defines */ free_defines (NULL); /* free tokens */ n = tok_ident - TOK_IDENT; for (i = 0; i < n; i++) { free (table_ident[i]); } free (table_ident); /* free sym_pools */ dynarray_reset (&sym_pools, &nb_sym_pools); /* string buffer */ cstr_free (&tokcstr); /* reset symbol stack */ sym_free_first = NULL; /* cleanup from error/setjmp */ macro_ptr = NULL; }
void end_new_file(void) { while (inctop) { struct incstate *p; p = inctop; (void)fclose(yyin); free(current_file); current_file = p->file; yyin = p->yyin; inctop = p->next; if (p->outp != NULL) { free((char *)p->outp); } free((char *)p); } while (iftop) { struct ifstate *p; p = iftop; iftop = p->next; free((char *)p); } free_defines(); }
void start_new_file(FILE *f) { struct lpc_predef_s *tmpf; free_defines(); add_define("_FUNCTION", -1, ""); add_define("LPC4", -1, ""); /* Tell coders this is LPC ver 4.0 */ add_define("CD_DRIVER", -1, ""); #ifdef DEBUG add_define("DEBUG_DRIVER", -1, ""); #endif add_define("T_INTEGER" , -1, ltoa(T_NUMBER)); add_define("T_FLOAT" , -1, ltoa(T_FLOAT)); add_define("T_STRING" , -1, ltoa(T_STRING)); add_define("T_OBJECT" , -1, ltoa(T_OBJECT)); add_define("T_FUNCTION", -1, ltoa(T_FUNCTION)); add_define("T_ARRAY" , -1, ltoa(T_POINTER)); add_define("T_MAPPING" , -1, ltoa(T_MAPPING)); for (tmpf = lpc_predefs; tmpf; tmpf = tmpf->next) { char namebuf[NSIZE]; char mtext[MLEN]; *mtext='\0'; (void)sscanf(tmpf->flag, "%[^=]=%[ -~=]", namebuf, mtext); if (strlen(namebuf) >= NSIZE) fatal("NSIZE exceeded\n"); if (strlen(mtext) >= MLEN) fatal("MLEN exceeded\n"); add_define(namebuf,-1,mtext); } keep1.token = keep2.token = keep3.token = -47; yyin = f; slast = '\n'; lastchar = '\n'; inctop = 0; /* If not here, where? */ num_incfiles = 0; current_incfile = 0; current_line = 1; lex_fatal = 0; incdepth = 0; nbuf = 0; outp = defbuf+DEFMAX; pragma_strict_types = 0; pragma_no_inherit = pragma_no_clone = pragma_no_shadow = pragma_resident = 0; nexpands = 0; }
/*-------------------------------------------------------------------------*/ Bool assert_simul_efun_object (void) /* (Re)load the simul_efun object and extract all information we need. * Result is TRUE if either the simul_efun object could be loaded, or if * master::get_simul_efun() did not return a string/string vector to * name the simul efun object. The result is FALSE if master::get_simul_efun() * specified a simul efun object, which couldn't be found. * * In other words: after calling assert_simul_efun_object(), the caller * still has to check if simul_efun_object is NULL. * * At the time of call, simul_efun_object must be NULL. */ { svalue_t *svp; object_t *ob; program_t *progp; CBool *visible; /* Flag for every function: visible or not */ string_t *name; int i, j, num_fun; invalidate_simul_efuns(); /* Invalidate the simul_efun information */ free_defines(); /* to prevent #defines hideing places for globals */ /* Get the name(s) of the simul_efun object. */ svp = apply_master(STR_GET_SEFUN, 0); /* If a simul_efun_object appears during the GET_SEFUN call, it * might have been due to a recursive get_simul_efun() call which may * have gotten an old backup copy. This can lead to hard-to-debug * variable and function definition inconsistencies. */ if (simul_efun_object) { printf("%s simul_efun object appeared while asking for it.\n", time_stamp()); return MY_TRUE; } if (svp == NULL) { printf("%s No simul_efun\n", time_stamp()); return MY_TRUE; } if (svp->type == T_POINTER) { simul_efun_vector = svp->u.vec; svp->type = T_NUMBER; if (VEC_SIZE(svp->u.vec)) svp = svp->u.vec->item; } if (svp->type != T_STRING) { printf("%s No simul_efun\n", time_stamp()); return MY_TRUE; } /* Make the (primary) simul_efun name */ name = del_slash(svp->u.str); if (simul_efun_file_name) free_mstring(simul_efun_file_name); simul_efun_file_name = make_tabled(name); /* Get the object and load the program */ ob = find_object(simul_efun_file_name); if (ob == NULL) { fprintf(stderr, "%s The simul_efun file %s was not loaded.\n" , time_stamp(), get_txt(simul_efun_file_name)); fprintf(stderr, "%s The function get_simul_efun() in the master must load it.\n" , time_stamp()); return MY_FALSE; } if (O_PROG_SWAPPED(ob) && load_ob_from_swap(ob) < 0) { fprintf(stderr, "%s Out of memory (unswap object '%s') ==> " "No simul_efun\n", time_stamp(), get_txt(ob->name)); return MY_TRUE; } reference_prog( (simul_efun_program = ob->prog), "get_simul_efun"); num_fun = ob->prog->num_function_names; if (num_fun == 0) return MY_TRUE; if (!simul_efunp) { simul_efunp = xalloc(sizeof (function_t) * num_fun); } else num_fun = total_simul_efun; free_defines(); /* to prevent #defines hideing places for globals */ /* locals and defines are freed now. There are still reserved words, * but it is impossible to define a function with the name being * a reserved word, thus, there will be no clashes with higher-priority * shared identifiers. */ progp = ob->prog; visible = alloca((i = ob->prog->num_functions) * sizeof(*visible)); memset(visible, 0, i); i = ob->prog->num_function_names; while (--i >= 0) visible[progp->function_names[i]] = MY_TRUE; /* The functions .num_function_names+1 .. .num_functions are not * visible by definition. */ /* Loop over the functions in the simul_efun object and * copy the salient information. */ for (i = 0; i < ob->prog->num_functions; i++) { int ix; funflag_t flags, flags2; bytecode_p funstart; mp_int fun_ix_offs, var_ix_offs; program_t *inherit_progp; function_t*funheader; if (!visible[i]) continue; ix = i; flags2 = flags = progp->functions[ix]; flags &= ~FUNSTART_MASK; /* Pinpoint the function, resolving inheritance where * necessary. */ fun_ix_offs = ix; var_ix_offs = 0; inherit_progp = progp; while (flags2 & NAME_INHERITED) { inherit_t *inheritp; inheritp = &inherit_progp->inherit[flags2 & INHERIT_MASK]; ix -= inheritp->function_index_offset; var_ix_offs += inheritp->variable_index_offset; inherit_progp = inheritp->prog; flags2 = inherit_progp->functions[ix]; } fun_ix_offs -= ix; funstart = inherit_progp->program + (flags2 & FUNSTART_MASK); funheader = inherit_progp->function_headers + FUNCTION_HEADER_INDEX(funstart); /* Don't stumble over undefined functions */ if (is_undef_function(funstart)) { flags |= NAME_UNDEFINED; } /* If the function is __INIT, pretend it's a private function */ if ( !(flags & (TYPE_MOD_STATIC|TYPE_MOD_PRIVATE|NAME_UNDEFINED)) ) { if (mstreq(funheader->name, STR_VARINIT)) flags |= TYPE_MOD_PRIVATE; } /* If the function is indeed visible, get its information */ if ( !(flags & (TYPE_MOD_STATIC|TYPE_MOD_PROTECTED|TYPE_MOD_PRIVATE|NAME_UNDEFINED)) ) { string_t *function_name; ident_t *p; unsigned char num_arg; function_name = funheader->name; num_arg = funheader->num_arg; /* Find or make the identifier for the function */ p = make_shared_identifier_mstr(function_name, I_TYPE_GLOBAL, 0); if (p->type == I_TYPE_UNKNOWN) { init_global_identifier(p, /* bVariable: */ MY_FALSE); p->next_all = all_simul_efuns; all_simul_efuns = p; } if (flags & TYPE_MOD_VARARGS) num_arg = SIMUL_EFUN_VARARGS; /* Find the proper index in simul_efunp[] */ switch(0) { default: /* TRY... */ /* Try to find a discarded sefun entry with matching * name, number of arguments and XVARARGS flag to reuse. */ if (all_discarded_simul_efun >= 0) { int last; j = all_discarded_simul_efun; while ( (j = simul_efunp[last = j].offset.next_sefun) >= 0) { if (num_arg != simul_efunp[j].num_arg || 0 != ((simul_efunp[j].flags ^ flags) & TYPE_MOD_XVARARGS) ) continue; if (!mstreq(function_name, simul_efunp[j].name)) continue; /* Found one: remove it from the 'discarded' list */ simul_efunp[last].offset.next_sefun = simul_efunp[j].offset.next_sefun; break; } if (j >= 0) break; /* switch */ } /* New simul_efun: make a new entry */ (void)ref_mstring(function_name); j = num_simul_efun++; if (num_simul_efun > num_fun) { num_fun = num_simul_efun + 12; simul_efunp = rexalloc(simul_efunp , sizeof (function_t) * num_fun ); } simul_efunp[j].name = function_name; simul_efunp[j].num_arg = num_arg; } /* switch() */ /* j now indexes the simul_efunp[] entry to use */ p->u.global.sim_efun = j; simul_efunp[j].flags = funheader->flags; simul_efunp[j].type = funheader->type; simul_efunp[j].num_locals = funheader->num_locals; /* If possible, make an entry in the simul_efun table */ if ((size_t)j < SEFUN_TABLE_SIZE) { simul_efun_table[j].funstart = funstart; simul_efun_table[j].program = inherit_progp; simul_efun_table[j].function_index_offset = fun_ix_offs; simul_efun_table[j].variable_index_offset = var_ix_offs; } } /* if (function visible) */ } /* for ( all functions) */ total_simul_efun = num_fun; simul_efun_object = ob; return MY_TRUE; } /* get_simul_efun_object() */
/* compile the C file opened in 'file'. Return non zero if errors. */ static int tcc_compile(TCCState *s1) { Sym *define_start; #ifdef INC_DEBUG printf ("%s: **** new file\n", file->filename); #endif preprocess_init (s1); funcname = ""; /* define some often used types */ int8_type.t = VT_INT8; int16_type.t = VT_INT16; int32_type.t = VT_INT32; int64_type.t = VT_INT64; char_pointer_type.t = VT_INT8; mk_pointer (&char_pointer_type); if (tcc_state->bits != 64) { size_type.t = VT_INT32; } else { size_type.t = VT_INT64; } func_old_type.t = VT_FUNC; func_old_type.ref = sym_push (SYM_FIELD, &int32_type, FUNC_CDECL, FUNC_OLD); // FIXME: Should depend on the target options too #ifdef TCC_TARGET_ARM arm_init_types (); #endif #if 0 /* define 'void *alloca(unsigned int)' builtin function */ { Sym *s1; p = anon_sym++; sym = sym_push (p, mk_pointer (VT_VOID), FUNC_CDECL, FUNC_NEW); s1 = sym_push (SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0); s1->next = NULL; sym->next = s1; sym_push (TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0); } #endif define_start = define_stack; nocode_wanted = 1; if (setjmp (s1->error_jmp_buf) == 0) { s1->nb_errors = 0; s1->error_set_jmp_enabled = 1; ch = file->buf_ptr[0]; tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF; parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM; // pvtop = vtop; next (); decl (VT_CONST); if (tok != TOK_EOF) { expect ("declaration"); } #if 0 if (pvtop != vtop) { fprintf (stderr, "internal compiler error:" " vstack leak? (%d)", vtop - pvtop); } #endif } s1->error_set_jmp_enabled = 0; /* reset define stack, but leave -Dsymbols (may be incorrect if they are undefined) */ free_defines (define_start); sym_pop (&global_stack, NULL); sym_pop (&local_stack, NULL); return s1->nb_errors != 0? -1: 0; }