/* Destroy all operating structures assocaited with the symtab pointer passed in. */ extern void jw_nuke( void* st ) { char* buf; // pointer to the original json to free if( st == NULL ) { return; } sym_foreach_class( st, 0, nix_things, NULL ); // free anything that the symtab references sym_free( st ); // free the symtab itself }
void test_mem_sar_get_range (void) { sym_t * sym = sym_new_dna(); test_assert_critical(sym != NULL); txt_t * txt = txt_new(sym); test_assert_critical(txt != NULL); test_assert(txt_append("TAGCNTCGACA", txt) == 0); test_assert(txt_commit_seq("seq0",txt) == 0); test_assert(txt_commit_rc(txt) == 0); sar_t * sar = sar_build(txt); test_assert_critical(sar != NULL); int64_t * sa_buf = malloc(30*sizeof(int64_t)); test_assert_critical(sa_buf != NULL); redirect_stderr(); // Set alloc failure rate to 0.1. set_alloc_failure_rate_to(0.1); for (int i = 0; i < 100; i++) { sar_get_range(0,10,sa_buf,sar); sar_get_range(10,5,sa_buf,sar); sar_get_range(19,30,sa_buf,sar); } reset_alloc(); // Set alloc countdown 0->10. for (int i = 0; i <= 10; i++) { set_alloc_failure_countdown_to(i); sar_get_range(0,10,sa_buf,sar); sar_get_range(10,5,sa_buf,sar); sar_get_range(19,30,sa_buf,sar); } reset_alloc(); free(sa_buf); sar_free(sar); txt_free(txt); sym_free(sym); unredirect_stderr(); }
void test_mem_sar_file (void) { sym_t * sym = sym_new_dna(); test_assert_critical(sym != NULL); txt_t * txt = txt_new(sym); test_assert_critical(txt != NULL); test_assert(txt_append("TAGCNTCGACA", txt) == 0); test_assert(txt_commit_seq("seq0",txt) == 0); test_assert(txt_commit_rc(txt) == 0); sar_t * sar = sar_build(txt); test_assert_critical(sar != NULL); sar_t * sar_i; redirect_stderr(); // Set alloc failure rate to 0.1. set_alloc_failure_rate_to(0.1); for (int i = 0; i < 100; i++) { sar_file_write("test30.sar", sar); sar_i = sar_file_read("test30.sar"); sar_free(sar_i); } reset_alloc(); // Set alloc countdown 0->10. for (int i = 0; i <= 10; i++) { set_alloc_failure_countdown_to(i); sar_file_write("test30.sar", sar); sar_i = sar_file_read("test30.sar"); sar_free(sar_i); } reset_alloc(); sar_free(sar); txt_free(txt); sym_free(sym); unredirect_stderr(); }
static void asm_free_labels(TCCState *st) { Sym *s, *s1; Section *sec; for(s = st->asm_labels; s != NULL; s = s1) { s1 = s->prev; /* define symbol value in object file */ if (s->r) { if (s->r == SHN_ABS) sec = SECTION_ABS; else sec = st->sections[s->r]; put_extern_sym2(s, sec, s->jnext, 0, 0); } /* remove label */ table_ident[s->v - TOK_IDENT]->sym_label = NULL; sym_free(s); } st->asm_labels = NULL; }
/* Real work for parsing an object ({...}) from the json. Called by jw_new() and recurses to deal with sub-objects. */ void* parse_jobject( void* st, char *json, char* prefix ) { jthing_t *jtp; // json thing that we just created int i; int n; char *name; // name in the json char *data; // data string from the json jthing_t* jarray; // array of jthings we'll coonstruct int size; int osize; int njtokens; // tokens actually sussed out jsmn_parser jp; // 'parser' object jsmntok_t *jtokens; // pointer to tokens returned by the parser char pname[1024]; // name with prefix char wbuf[256]; // temp buf to build a working name in char* dstr; // dup'd string jsmn_init( &jp ); // does this have a failure mode? jtokens = (jsmntok_t *) malloc( sizeof( *jtokens ) * MAX_THINGS ); if( jtokens == NULL ) { fprintf( stderr, "abort: cannot allocate tokens array\n" ); exit( 1 ); } njtokens = jsmn_parse( &jp, json, strlen( json ), jtokens, MAX_THINGS ); if( jtokens[0].type != JSMN_OBJECT ) { // if it's not an object then we can't parse it. fprintf( stderr, "warn: badly formed json; initial opening bracket ({) not detected\n" ); return NULL; } /* DEBUG for( i = 1; i < njtokens-1; i++ ) { // we'll silently skip the last token if its "name" without a value fprintf( stderr, ">>> %4d: size=%d start=%d end=%d %s\n", i, jtokens[i].size, jtokens[i].start, jtokens[i].end, extract( json, &jtokens[i] ) ); } */ for( i = 1; i < njtokens-1; i++ ) { // we'll silently skip the last token if its "name" without a value if( jtokens[i].type != JSMN_STRING ) { fprintf( stderr, "warn: badly formed json [%d]; expected name (string) found type=%d %s\n", i, jtokens[i].type, extract( json, &jtokens[i] ) ); sym_free( st ); return NULL; } name = extract( json, &jtokens[i] ); if( *prefix != 0 ) { snprintf( pname, sizeof( pname ), "%s.%s", prefix, name ); name = pname; } size = jtokens[i].size; i++; // at the data token now switch( jtokens[i].type ) { case JSMN_UNDEFINED: fprintf( stderr, "warn: element [%d] in json is undefined\n", i ); break; case JSMN_OBJECT: // save object in two ways: as an object 'blob' and in the current symtab using name as a base (original) dstr = strdup( extract( json, &jtokens[i] ) ); snprintf( wbuf, sizeof( wbuf ), "%s_json", name ); // must stash the json string in the symtab for clean up during nuke sym_fmap( st, (unsigned char *) wbuf, 0, dstr ); parse_jobject( st, dstr, name ); // recurse to add the object as objectname.xxxx elements jtp = mk_thing( st, name, jtokens[i].type ); // create thing and reference it in current symtab if( jtp == NULL ) { fprintf( stderr, "warn: memory alloc error processing element [%d] in json\n", i ); free( dstr ); sym_free( st ); return NULL; } jtp->v.pv = (void *) sym_alloc( 255 ); // object is just a blob if( jtp->v.pv == NULL ) { fprintf( stderr, "error: [%d] symtab for object blob could not be allocated\n", i ); sym_free( st ); free( dstr ); return NULL; } dstr = strdup( extract( json, &jtokens[i] ) ); sym_fmap( jtp->v.pv, (unsigned char *) JSON_SYM_NAME, 0, dstr ); // must stash json so it is freed during nuke() parse_jobject( jtp->v.pv, dstr, "" ); // recurse acorss the string and build a new symtab size = jtokens[i].end; // done with them, we need to skip them i++; while( i < njtokens-1 && jtokens[i].end < size ) { //fprintf( stderr, "\tskip: [%d] object element start=%d end=%d (%s)\n", i, jtokens[i].start, jtokens[i].end, extract( json, &jtokens[i]) ); i++; } i--; // must allow loop to bump past the last break; case JSMN_ARRAY: size = jtokens[i].size; // size is burried here, and not with the name jtp = mk_thing( st, name, jtokens[i].type ); i++; // first thing is the whole array string which I don't grock the need for, but it's their code... if( jtp == NULL ) { fprintf( stderr, "warn: memory alloc error processing element [%d] in json\n", i ); sym_free( st ); return NULL; } jarray = jtp->v.pv = (jsmntok_t *) malloc( sizeof( *jarray ) * size ); // allocate the array memset( jarray, 0, sizeof( *jarray ) * size ); jtp->nele = size; for( n = 0; n < size; n++ ) { // for each array element jarray[n].prim_type = PT_UNKNOWN; // assume not primative type switch( jtokens[i+n].type ) { case JSMN_UNDEFINED: fprintf( stderr, "warn: [%d] array element %d is not valid type (undefined) is not string or primative\n", i, n ); fprintf( stderr, "\tstart=%d end=%d\n", jtokens[i+n].start, jtokens[i+n].end ); break; case JSMN_OBJECT: jarray[n].v.pv = (void *) sym_alloc( 255 ); if( jarray[n].v.pv == NULL ) { fprintf( stderr, "error: [%d] array element %d size=%d could not allocate symtab\n", i, n, jtokens[i+n].size ); sym_free( st ); return NULL; } jarray[n].jsmn_type = JSMN_OBJECT; parse_jobject( jarray[n].v.pv, extract( json, &jtokens[i+n] ), "" ); // recurse acorss the string and build a new symtab osize = jtokens[i+n].end; // done with them, we need to skip them i++; while( i+n < njtokens-1 && jtokens[n+i].end < osize ) { //fprintf( stderr, "\tskip: [%d] object element start=%d end=%d (%s)\n", i, jtokens[i].start, jtokens[i].end, extract( json, &jtokens[i]) ); i++; } i--; // allow incr at loop end break; case JSMN_ARRAY: fprintf( stderr, "warn: [%d] array element %d is not valid type (array) is not string or primative\n", i, n ); n += jtokens[i+n].size; // this should skip the nested array break; case JSMN_STRING: data = extract( json, &jtokens[i+n] ); jarray[n].v.pv = (void *) data; jarray[n].jsmn_type = JSMN_STRING; break; case JSMN_PRIMITIVE: data = extract( json, &jtokens[i+n] ); switch( *data ) { case 0: jarray[n].prim_type = PT_VALUE; jarray[n].v.fv = 0; break; case 'T': case 't': jarray[n].v.fv = 1; jarray[n].prim_type = PT_BOOL; break; case 'F': case 'f': jarray[n].prim_type = PT_BOOL; jarray[n].v.fv = 0; break; case 'N': // assume null, nil, or some variant case 'n': jarray[n].prim_type = PT_NULL; jarray[n].v.fv = 0; break; default: jarray[n].prim_type = PT_VALUE; jarray[n].v.fv = strtof( data, NULL ); // store all numerics as float break; } jarray[n].jsmn_type = JSMN_PRIMITIVE; break; default: fprintf( stderr, "warn: [%d] array element %d is not valid type (unknown=%d) is not string or primative\n", i, n, jtokens[i].type ); sym_free( st ); return NULL; break; } } i += size - 1; // must allow loop to push to next break; case JSMN_STRING: data = extract( json, &jtokens[i] ); jtp = mk_thing( st, name, jtokens[i].type ); if( jtp == NULL ) { fprintf( stderr, "warn: memory alloc error processing element [%d] in json\n", i ); sym_free( st ); return NULL; } jtp->v.pv = (void *) data; // just point into the large json string break; case JSMN_PRIMITIVE: data = extract( json, &jtokens[i] ); jtp = mk_thing( st, name, jtokens[i].type ); if( jtp == NULL ) { fprintf( stderr, "warn: memory alloc error processing element [%d] in json\n", i ); sym_free( st ); return NULL; } switch( *data ) { // assume T|t is true and F|f is false case 0: jtp->v.fv = 0; jtp->prim_type = PT_VALUE; break; case 'T': case 't': jtp->prim_type = PT_BOOL; jtp->v.fv = 1; break; case 'F': case 'f': jtp->prim_type = PT_BOOL; jtp->v.fv = 0; break; case 'N': // Null or some form of that case 'n': jtp->prim_type = PT_NULL; jtp->v.fv = 0; break; default: jtp->prim_type = PT_VALUE; jtp->v.fv = strtof( data, NULL ); // store all numerics as float break; } break; default: fprintf( stderr, "unknown type at %d\n", i ); break; } } free( jtokens ); return st; }
void gcode(void) { int i, n, t, r, stacksize, addr, pc, disp, rel, errs, more, func_start; Branch *b, *bn; // Generate function prolog func_start = cur_text_section->data_offset; if (!func_naked) { // Align local size to word stacksize = (-loc + 3) & -4; if (stacksize >= 4096) { // Generate stack guard since parameters can cross page boundary Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0); gen(0xb8); // mov stacksize, %eax genword(stacksize); gen(0xe8); // call __chkstk, (does the stackframe too) put_reloc(cur_text_section, sym, cur_text_section->data_offset, R_386_PC32); genword(-4); } else { if (do_debug || loc || !func_noargs) { gen(0x55); // push %ebp gen(0x89); // mov %esp, %ebp gen(0xe5); } if (stacksize > 0) { if (stacksize == (char) stacksize) { gen(0x83); // sub esp, stacksize gen(0xec); gen(stacksize); } else { gen(0x81); // sub esp, stacksize gen(0xec); genword(stacksize); } } } // Save callee-saved registers used by function. for (r = 0; r < NB_REGS; ++r) { if ((reg_classes[r] & RC_SAVE) && (regs_used & (1 << r))) { gen(0x50 + r); // push r } } } // Optimize jumps more = 1; while (more) { more = 0; for (i = 0; i < br; ++i) { b = branch + i; if (b->type == CodeLabel) b->target = 0; if (b->type != CodeJump) continue; t = skip_nops(b->target, 1); if (branch[t].type == CodeJump && !branch[t].param && b->target != branch[t].target) { // Eliminate jump to jump b->target = branch[t].target; more = 1; continue; } // Find next non-nop n = i + 1; while (branch[n].type == CodeNop || branch[n].type == CodeLine) n++; bn = branch + n; if (b->ind != bn->ind) continue; if (!b->param && bn->type == CodeJump) { // Eliminate dead jump instruction bn->type = CodeNop; more = 1; continue; } if (b->target > i && b->target <= n) { // Eliminate jump to next instruction b->type = CodeNop; more = 1; continue; } t = skip_nops(n + 1, 0); if (bn->type == CodeJump && !bn->param && b->target == t && bn->ind == branch[t].ind) { // Optimize inverted jump if (b->param) b->param ^= 1; b->target = bn->target; bn->type = CodeNop; more = 1; continue; } } // Eliminate unused labels for (i = 0; i < br; ++i) { b = branch + i; if (b->type == CodeJump) branch[b->target].target++; } for (i = 0; i < br; ++i) { b = branch + i; if (b->type == CodeLabel && !b->target && !b->sym) { // Remove label with no references b->type = CodeNop; more = 1; } } } // Assign addresses to branch points, assuming only long jumps addr = cur_text_section->data_offset; pc = 0; for (i = 0; i < br; ++i) { b = branch + i; addr += b->ind - pc; b->addr = addr; switch (b->type) { case CodeJump: addr += 5; if (b->param != 0) addr++; break; case CodeAlign: // Use convervative estimate for short/long jump estimation addr += b->param - 1; break; } pc = b->ind; } // Find jumps which can be encoded as short jumps for (i = 0; i < br; ++i) { b = branch + i; if (b->type == CodeJump) { disp = branch[b->target].addr - b->addr - 2; if (b->param) disp--; if (disp == (char) disp) b->type = CodeShortJump; } } // Assign final addresses to branch points addr = cur_text_section->data_offset; pc = 0; for (i = 0; i < br; ++i) { b = branch + i; addr += b->ind - pc; b->addr = addr; switch (b->type) { case CodeJump: addr += 5; if (b->param) addr++; break; case CodeShortJump: addr += 2; break; case CodeAlign: addr = (addr + b->param - 1) & -b->param; break; } pc = b->ind; } // Generate code blocks pc = 0; errs = 0; for (i = 0; i < br; ++i) { b = branch + i; // Output code block before branch point if (b->ind != pc) { genblk(code + pc, b->ind - pc); pc = b->ind; } switch (b->type) { case CodeLabel: // Export label if symbol defined if (b->sym) { put_extern_sym_ex(b->sym, cur_text_section, b->addr, 0, 0); sym_free(b->sym); } break; case CodeJump: // Generate long jump instruction if (branch[b->target].type != CodeLabel) { printf("internal error: jump %d to non-label %d\n", i, b->target); errs++; } if (b->param > 0xff) error("invalid displacement"); if (b->param == 0) { gen(0xe9); genword(branch[b->target].addr - (b->addr + 5)); } else { gen(0x0f); gen(b->param - 0x10); genword(branch[b->target].addr - (b->addr + 6)); } break; case CodeShortJump: // Generate short jump instruction if (branch[b->target].type != CodeLabel) { printf("internal error: jump %d to non-label %d\n", i, b->target); errs++; } if (b->param == 0) { gen(0xeb); } else { gen(b->param - 0x20); } gen(branch[b->target].addr - (b->addr + 2)); break; case CodeReloc: if (b->param) { rel = R_386_PC32; } else { rel = R_386_32; } put_elf_reloc(symtab_section, cur_text_section, b->addr, rel, b->target); break; case CodeAlign: i = addr; while (i & (b->param - 1)) { gen(b->target); i++; } break; case CodeLine: put_stabn(N_SLINE, 0, b->target, b->addr - func_start); break; } } // Generate function epilog if (!func_naked) { // Restore callee-saved registers used by function. for (r = NB_REGS; r >= 0; --r) { if ((reg_classes[r] & RC_SAVE) && (regs_used & (1 << r))) { gen(0x58 + r); // pop r } } if (do_debug || loc || !func_noargs) gen(0xc9); // leave // Generate return if (func_ret_sub == 0) { gen(0xc3); // ret } else { gen(0xc2); // ret n gen(func_ret_sub); gen(func_ret_sub >> 8); } } #ifdef DEBUG_BRANCH printf("\nbranch table for %s\n", func_name); printf(" # t targ parm ind addr\n"); printf("---- - ---- ----- -------- --------\n"); for (i = 0; i < br; ++i) { b = branch + i; printf("%04d %c %04d %04x %08x %08x", i, "SLJjRANlE"[b->type], b->target, b->param, b->ind, b->addr); if (branch[i].sym) { printf(" sym=%s", get_tok_str(b->sym->v, NULL)); } printf("\n"); } printf("\n"); #endif if (errs) error("internal error: code generation"); }
int main(int argc, char ** argv) { char * test; int i; struct WorkFlow * wf; rb_tree * symtab, * functab; struct Symbol * s, * q; test = malloc(1024); memstat_init(); // jmm_init(); symtab = symtable_init(); functab = functable_init(); stdlib_arythm_register(functab); strcpy(test, "rcmp(rcmp(33, 34), rcmp(34, 35)) + 8"); if (inf_check_brackets(test)) printf("Correct!\n"); wf = inf_transform_to_reverse_postfix(functab, test); puts(test); for(i = 0; i < wf->count; ++i) { printf("%d ", wf->ops[i].id); } puts(""); for(i = 0; i < wf->count; ++i) { switch (wf->ops[i].id) { case SYM_NUM: printf("%s", (char *)wf->ops[i].data); break; case SYM_SYMBOL: printf("%s", (char *)wf->ops[i].data); break; case SYM_OPS_ADD: printf("+"); break; case SYM_OPS_SUB: printf("-"); break; case SYM_OPS_MUL: printf("*"); break; case SYM_OPS_DIV: printf("/"); break; case SYM_OPS_EXP: printf("^"); break; case SYM_FUNC: printf("%s", (char *)wf->ops[i].data); break; default: break; } printf(" "); } puts(""); s = process_postfix_workflow(wf, symtab, functab); printf("%s = %ld/%ld\n", test, ((struct Rational *)s->data)->num, ((struct Rational *)s->data)->denom); sym_rational_normalize(s); printf("%s = %ld/%ld\n", test, ((struct Rational *)s->data)->num, ((struct Rational *)s->data)->denom); workflow_free(wf); // sym_free(s); strcpy(test, "(7*2)/12"); wf = inf_transform_to_reverse_postfix(functab, test); q = process_postfix_workflow(wf, symtab, functab); printf("%s = %ld/%ld\n", test, ((struct Rational *)q->data)->num, ((struct Rational *)q->data)->denom); if (sym_rational_is_eq(s, q)) printf("They are equal\n"); sym_free(q); sym_free(s); workflow_free(wf); free(test); functable_shutdown(functab); symtable_shutdown(symtab); memstat_shutdown(); return 0; }