static void idbgPrintFunc( void* data, SGS_CTX, int type, const char* message ) { SGS_IDBG = (sgs_IDbg*) data; D->stkoff = C->stack_off - C->stack_base; D->stksize = C->stack_top - C->stack_base; D->pfn( D->pctx, C, type, message ); if( D->inside || type < D->minlev ) return; D->inside = 1; C->sf_count -= SGS_IDBG_STACK_EXTENSION; printf( "----- Interactive SGScript Debug Inspector -----" ); for(;;) { printf( "\n> " ); idbg_readStdin( D ); if( ferror( stdin ) ) break; if( !*D->iword ) continue; if( STREQ( D->iword, "continue" ) || STREQ( D->iword, "cont" ) ) break; if( STREQ( D->iword, "quit" ) ) exit( 0 ); if( STREQ( D->iword, "reprint" ) ) D->pfn( D->pctx, C, type, message ); if( STREQ( D->iword, "stack" ) ) sgs_Stat( C, SGS_STAT_DUMP_STACK ); if( STREQ( D->iword, "globals" ) ) sgs_Stat( C, SGS_STAT_DUMP_GLOBALS ); if( STREQ( D->iword, "objects" ) ) sgs_Stat( C, SGS_STAT_DUMP_OBJECTS ); if( STREQ( D->iword, "callstack" ) || STREQ( D->iword, "frames" ) ) sgs_Stat( C, SGS_STAT_DUMP_FRAMES ); if( STREQ( D->iword, "exec" ) ) sgs_ExecBuffer( C, D->input.ptr + 5, D->input.size - 5 ); if( STREQ( D->iword, "eval" ) ) { int rvc = 0; sgs_EvalBuffer( C, D->input.ptr + 5, D->input.size - 5, &rvc ); sgs_PushGlobal( C, "printvars" ); sgs_Call( C, rvc, 0 ); } if( STREQ( D->iword, "print" ) ) { int rvc = 0; sgs_MemBuf prepstr = sgs_membuf_create(); sgs_membuf_appbuf( &prepstr, C, "return (", 8 ); sgs_membuf_appbuf( &prepstr, C, D->input.ptr + 5, D->input.size - 5 ); sgs_membuf_appbuf( &prepstr, C, ");", 2 ); sgs_EvalBuffer( C, prepstr.ptr, prepstr.size, &rvc ); sgs_membuf_destroy( &prepstr, C ); sgs_PushGlobal( C, "printvars" ); sgs_Call( C, rvc, 0 ); } } C->sf_count += SGS_IDBG_STACK_EXTENSION; D->inside = 0; }
static void idbg_readStdin( SGS_IDBG ) { /* read from STDIN */ size_t wsz = 31, i = 0; char bfr[ BFR_SIZE ]; sgs_membuf_resize( &D->input, D->C, 0 ); while( fgets( bfr, BFR_SIZE, stdin ) ) { size_t len = strlen( bfr ); sgs_membuf_appbuf( &D->input, D->C, bfr, len ); if( len && bfr[ len - 1 ] == '\n' ) break; } sgs_membuf_appchr( &D->input, D->C, 0 ); /* parse first word */ while( i < wsz && i < D->input.size && isalpha( D->input.ptr[ i ] ) ) { D->iword[ i ] = D->input.ptr[ i ]; i++; } D->iword[ i ] = 0; }
static void mode3hook( void* userdata, SGS_CTX, int evid ) { sgs_ProfData* P = (sgs_ProfData*) userdata; if( P->hfn ) P->hfn( P->hctx, C, evid ); if( evid == SGS_HOOK_ENTER || evid == SGS_HOOK_CONT || evid == SGS_HOOK_EXIT || evid == SGS_HOOK_PAUSE ) { SGS_SHCTX_USE; mode3item CD = { NULL, S->numallocs, S->numfrees, S->numblocks, (double) S->memsize }; sgs_StackFrame* target = NULL, *sf, *lastrec = NULL; mode3item* items = SGS_ASSUME_ALIGNED( P->frametmp.ptr, mode3item ); size_t i, itemcount = P->frametmp.size / sizeof(mode3item); if( evid == SGS_HOOK_ENTER || evid == SGS_HOOK_CONT ) target = C->sf_last; else if( evid == SGS_HOOK_EXIT ) target = C->sf_last->prev; /* pause => null */ /* ignore the case when target = current */ if( itemcount && items[ itemcount - 1 ].frame == target ) return; /* find target in stack */ for( i = 0; i < itemcount; ++i ) { if( items[ i ].frame == target ) break; } if( i == itemcount ) { /* find last recorded frame in call stack */ sf = NULL; if( itemcount ) { sf = C->sf_first; while( sf ) { if( items[ itemcount - 1 ].frame == sf ) break; sf = sf->next; } } lastrec = sf; if( sf == NULL || target == NULL ) i = 0; /* frame not found/req., remove everything */ /* otherwise, remove nothing, it's an "ENTER" */ } else i++; /* remove starting from next frame */ /* if there is anything to remove */ if( i < itemcount ) { size_t bki = i; sf = C->sf_first; /* generate core key (from start to first removed incl.) */ sgs_membuf_resize( &P->keytmp, C, 0 ); while( sf && sf != items[ i ].frame ) { const char* fname = "<error>"; sgs_StackFrameInfo( C, sf, &fname, NULL, NULL ); sgs_membuf_appbuf( &P->keytmp, C, fname, strlen( fname ) ); sgs_membuf_appchr( &P->keytmp, C, 0 ); sf = sf->next; } /* iterate removable frames (assuming frame pointers are valid) */ for( ; i < itemcount; ++i ) { const char* fname = "<error>"; sgs_StackFrameInfo( C, items[ i ].frame, &fname, NULL, NULL ); sgs_membuf_appbuf( &P->keytmp, C, fname, strlen( fname ) ); sgs_membuf_appchr( &P->keytmp, C, 0 ); /* commit memory addition */ { mode3item prevCD = items[ i ], *PD; sgs_VHTVar* pair = sgs_vht_get_str( &P->prof->timings, P->keytmp.ptr, (uint32_t) P->keytmp.size, sgs_HashFunc( P->keytmp.ptr, P->keytmp.size ) ); if( pair ) { PD = (mode3item*) pair->val.data.P; } else { sgs_Variable key, val; val.type = SGS_VT_PTR; val.data.P = PD = sgs_Alloc( mode3item ); memset( PD, 0, sizeof(*PD) ); sgs_InitStringBuf( C, &key, P->keytmp.ptr, (sgs_SizeVal) P->keytmp.size ); sgs_vht_set( &P->prof->timings, C, &key, &val ); sgs_Release( C, &key ); } PD->numallocs += CD.numallocs - prevCD.numallocs; PD->numfrees += CD.numfrees - prevCD.numfrees; PD->numblocks += CD.numblocks - prevCD.numblocks; PD->szdelta += CD.szdelta - prevCD.szdelta; } } /* commit size */ sgs_membuf_resize( &P->frametmp, C, bki * sizeof(mode3item) ); itemcount = bki; } /* add new frame start times */ if( lastrec || ( target != NULL && itemcount == 0 ) ) { if( lastrec ) sf = lastrec->next; else sf = C->sf_first; while( sf ) { mode3item NI = CD; NI.frame = sf; sgs_membuf_appbuf( &P->frametmp, C, &NI, sizeof(NI) ); if( sf == target ) break; sf = sf->next; } } } else if( evid == SGS_HOOK_CREAT ) { sgs_ProfAttach( C, P->prof ); } else if( evid == SGS_HOOK_CFREE ) { sgs_ProfDetach( C, P->prof ); } /* CFORK not supported yet */ }