void code_term() { #if TERMCODE code *cn; int count = 0; while (code_list) { cn = code_next(code_list); mem_ffree(code_list); code_list = cn; count++; } #ifdef DEBUG printf("Max # of codes = %d\n",count); #endif #else #ifdef DEBUG int count = 0; for (code *cn = code_list; cn; cn = code_next(cn)) count++; printf("Max # of codes = %d\n",count); #endif #endif }
static int cmdfunc( int cmd ) { // 実行処理 (命令実行時に呼ばれます) // code_next(); // 次のコードを取得(最初に必ず必要です) switch( cmd ) { // サブコマンドごとの分岐 case 0x00: hsplua_cmd::hl_newstate(); break; case 0x01: hsplua_cmd::hl_switchstate(); break; case 0x02: hsplua_cmd::hl_close(); break; case 0x04: hsplua_cmd::hl_gccollect(); break; case 0x05: hsplua_cmd::hl_gcgen(); break; case 0x06: hsplua_cmd::hl_gcinc(); break; case 0x07: hsplua_cmd::hl_gcrestart(); break; case 0x08: hsplua_cmd::hl_gcsetpause(); break; case 0x09: hsplua_cmd::hl_gcsetstepmul(); break; case 0x0a: hsplua_cmd::hl_gcstep(); break; case 0x0b: hsplua_cmd::hl_gcstop(); break; case 0x10: hsplua_cmd::hl_pop(); break; case 0x11: hsplua_cmd::hl_pushboolean(); break; case 0x12: hsplua_cmd::hl_pushfunction(); break; case 0x13: hsplua_cmd::hl_pushinteger(); break; case 0x14: hsplua_cmd::hl_pushlightuserdata(); break; case 0x15: hsplua_cmd::hl_pushlstring(); break; case 0x16: hsplua_cmd::hl_pushnil(); break; case 0x17: hsplua_cmd::hl_pushnumber(); break; case 0x18: hsplua_cmd::hl_pushstring(); break; case 0x19: hsplua_cmd::hl_pushvalue(); break; case 0x1a: hsplua_cmd::hl_pushvarptr(); break; default: puterror( HSPERR_UNSUPPORTED_FUNCTION ); break; } return RUNMODE_RUN; }
static void *reffunc( int *type_res, int cmd ) { // 関数・システム変数の実行処理 (値の参照時に呼ばれます) // int answerType = 0; // '('で始まるかを調べる // if ( *type != TYPE_MARK ) puterror( HSPERR_INVALID_FUNCPARAM ); if ( *val != '(' ) puterror( HSPERR_INVALID_FUNCPARAM ); code_next(); switch( cmd ) { // サブコマンドごとの分岐 case 0x80: *type_res = hsplua_func::hl_isboolean(); break; case 0x81: *type_res = hsplua_func::hl_iscfunction(); break; case 0x82: *type_res = hsplua_func::hl_isfunction(); break; case 0x83: *type_res = hsplua_func::hl_islightuserdata(); break; case 0x84: *type_res = hsplua_func::hl_isnil(); break; case 0x85: *type_res = hsplua_func::hl_isnone(); break; case 0x86: *type_res = hsplua_func::hl_isnoneornil(); break; case 0x87: *type_res = hsplua_func::hl_isnumber(); break; case 0x88: *type_res = hsplua_func::hl_isstring(); break; case 0x89: *type_res = hsplua_func::hl_istable(); break; case 0x8a: *type_res = hsplua_func::hl_isthread(); break; case 0x8b: *type_res = hsplua_func::hl_isuserdata(); break; case 0x90: *type_res = hsplua_func::hl_toboolean(); break; case 0x91: *type_res = hsplua_func::hl_tocfunction(); break; case 0x92: *type_res = hsplua_func::hl_tointeger(); break; case 0x93: *type_res = hsplua_func::hl_tonumber(); break; case 0x94: *type_res = hsplua_func::hl_topointer(); break; case 0x95: *type_res = hsplua_func::hl_tostring(); break; case 0x96: *type_res = hsplua_func::hl_touserdata(); break; case 0x98: *type_res = hsplua_func::hl_gccount(); break; case 0x99: *type_res = hsplua_func::hl_gcisrunning(); break; default: puterror( HSPERR_UNSUPPORTED_FUNCTION ); break; } // '('で終わるかを調べる // if ( *type != TYPE_MARK ) puterror( HSPERR_INVALID_FUNCPARAM ); if ( *val != ')' ) puterror( HSPERR_INVALID_FUNCPARAM ); code_next(); return (void *)&ref_val; }
static void *reffunc_function( int *type_res, int arg ) { void *ptr; // 返値のタイプを設定する // *type_res = HSPVAR_FLAG_INT; // 返値のタイプを指定する ptr = &reffunc_intfunc_ivalue; // 返値のポインタ // '('で始まるかを調べる // if ( *type != TYPE_MARK ) throw HSPERR_INVALID_FUNCPARAM; if ( *val != '(' ) throw HSPERR_INVALID_FUNCPARAM; code_next(); switch( arg & 0xff ) { // int function case 0x002: // dirinfo p1 = code_geti(); ptr = getdir( p1 ); *type_res = HSPVAR_FLAG_STR; break; case 0x003: // sysinfo p1 = code_geti(); *type_res = sysinfo( p1 ); ptr = ctx->stmp; break; default: throw HSPERR_UNSUPPORTED_FUNCTION; } // ')'で終わるかを調べる // if ( *type != TYPE_MARK ) throw HSPERR_INVALID_FUNCPARAM; if ( *val != ')' ) throw HSPERR_INVALID_FUNCPARAM; code_next(); return ptr; }
static int cmdfunc_ax2dllcmd(int cmd) { code_next(); switch ( cmd ) { case 0x000: code_gets(); code_gets(); code_gets(); code_next(); break; case 0x001: code_gets(); break; default: throw HSPERR_UNSUPPORTED_FUNCTION; } return 0; }
void code_free(code *cstart) { code **pc; code *c; for (pc = &cstart; (c = *pc) != NULL; pc = &code_next(c)) { if (c->Iop == ASM) { mem_free(c->IEV1.as.bytes); } } *pc = code_list; code_list = cstart; }
code *code_calloc() { code *c; static code czero; //printf("code %x\n", sizeof(code)); c = code_list; if (c) code_list = code_next(c); else c = (code *)mem_fmalloc(sizeof(*c)); *c = czero; // zero it out //dbg_printf("code_calloc: %p\n",c); return c; }
static void *reffunc_dllcmd( int *type_res, int arg ) { // reffunc : TYPE_DLLFUNC // (拡張DLL関数) // // '('で始まるかを調べる // if ( *type != TYPE_MARK ) throw ( HSPERR_INVALID_FUNCPARAM ); if ( *val != '(' ) throw ( HSPERR_INVALID_FUNCPARAM ); *type_res = HSPVAR_FLAG_INT; exec_dllcmd( arg, STRUCTDAT_OT_FUNCTION ); reffunc_intfunc_ivalue = hspctx->stat; // ')'で終わるかを調べる // if ( *type != TYPE_MARK ) throw ( HSPERR_INVALID_FUNCPARAM ); if ( *val != ')' ) throw ( HSPERR_INVALID_FUNCPARAM ); code_next(); return &reffunc_intfunc_ivalue; }
void except_fillInEHTable(symbol *s) { unsigned fsize = NPTRSIZE; // target size of function pointer dt_t **pdt = &s->Sdt; /* void* pointer to start of function (Windows) unsigned offset of ESP from EBP unsigned offset from start of function to return code unsigned nguards; // dimension of guard[] (Linux) Guard guard[]; // sorted such that the enclosing guarded sections come first catchoffset: unsigned ncatches; // number of catch blocks { void *type; // symbol representing type unsigned bpoffset; // EBP offset of catch variable void *handler; // catch handler code } catch[]; */ /* Be careful of this, as we need the sizeof Guard on the target, not * in the compiler. */ unsigned GUARD_SIZE; if (config.ehmethod == EH_DM) GUARD_SIZE = (I64 ? 3*8 : 5*4); else if (config.ehmethod == EH_WIN32) GUARD_SIZE = 3*4; else assert(0); int sz = 0; // Address of start of function if (config.ehmethod == EH_WIN32) { symbol_debug(funcsym_p); pdt = dtxoff(pdt,funcsym_p,0,TYnptr); sz += fsize; } //printf("ehtables: func = %s, offset = x%x, startblock->Boffset = x%x\n", funcsym_p->Sident, funcsym_p->Soffset, startblock->Boffset); // Get offset of ESP from EBP long spoff = cod3_spoff(); pdt = dtdword(pdt,spoff); sz += 4; // Offset from start of function to return code pdt = dtdword(pdt,retoffset); sz += 4; // First, calculate starting catch offset int guarddim = 0; // max dimension of guard[] int ndctors = 0; // number of ESCdctor's for (block *b = startblock; b; b = b->Bnext) { if (b->BC == BC_try && b->Bscope_index >= guarddim) guarddim = b->Bscope_index + 1; // printf("b->BC = %2d, Bscope_index = %2d, last_index = %2d, offset = x%x\n", // b->BC, b->Bscope_index, b->Blast_index, b->Boffset); if (usednteh & EHcleanup) for (code *c = b->Bcode; c; c = code_next(c)) { if (c->Iop == (ESCAPE | ESCddtor)) ndctors++; } } //printf("guarddim = %d, ndctors = %d\n", guarddim, ndctors); if (config.ehmethod == EH_DM) { pdt = dtsize_t(pdt,guarddim + ndctors); sz += NPTRSIZE; } unsigned catchoffset = sz + (guarddim + ndctors) * GUARD_SIZE; // Generate guard[] int i = 0; for (block *b = startblock; b; b = b->Bnext) { //printf("b = %p, b->Btry = %p, b->offset = %x\n", b, b->Btry, b->Boffset); if (b->BC == BC_try) { assert(b->Bscope_index >= i); if (i < b->Bscope_index) { int fillsize = (b->Bscope_index - i) * GUARD_SIZE; pdt = dtnzeros(pdt, fillsize); sz += fillsize; } i = b->Bscope_index + 1; int nsucc = b->numSucc(); if (config.ehmethod == EH_DM) { //printf("DHandlerInfo: offset = %x", (int)(b->Boffset - startblock->Boffset)); pdt = dtdword(pdt,b->Boffset - startblock->Boffset); // offset to start of block // Compute ending offset unsigned endoffset; for (block *bn = b->Bnext; 1; bn = bn->Bnext) { //printf("\tbn = %p, bn->Btry = %p, bn->offset = %x\n", bn, bn->Btry, bn->Boffset); assert(bn); if (bn->Btry == b->Btry) { endoffset = bn->Boffset - startblock->Boffset; break; } } //printf(" endoffset = %x, prev_index = %d\n", endoffset, b->Blast_index); pdt = dtdword(pdt,endoffset); // offset past end of guarded block } pdt = dtdword(pdt,b->Blast_index); // parent index if (b->jcatchvar) // if try-catch { assert(catchoffset); pdt = dtdword(pdt,catchoffset); pdt = dtsize_t(pdt,0); // no finally handler catchoffset += NPTRSIZE + (nsucc - 1) * (3 * NPTRSIZE); } else // else try-finally { assert(nsucc == 2); pdt = dtdword(pdt,0); // no catch offset block *bhandler = b->nthSucc(1); assert(bhandler->BC == BC_finally); // To successor of BC_finally block bhandler = bhandler->nthSucc(0); // finally handler address if (config.ehmethod == EH_DM) { assert(bhandler->Boffset > startblock->Boffset); pdt = dtsize_t(pdt,bhandler->Boffset - startblock->Boffset); // finally handler offset } else pdt = dtcoff(pdt,bhandler->Boffset); } sz += GUARD_SIZE; } } /* Append to guard[] the guard blocks for temporaries that are created and destroyed * within a single expression. These are marked by the special instruction pairs * (ESCAPE | ESCdctor) and (ESCAPE | ESCddtor). */ if (usednteh & EHcleanup) { #define STACKINC 16 int stackbuf[STACKINC]; int *stack = stackbuf; int stackmax = STACKINC; int scopeindex = guarddim; for (block *b = startblock; b; b = b->Bnext) { /* Set up stack of scope indices */ stack[0] = b->Btry ? b->Btry->Bscope_index : -1; int stacki = 1; unsigned boffset = b->Boffset; for (code *c = b->Bcode; c; c = code_next(c)) { if (c->Iop == (ESCAPE | ESCdctor)) { code *c2 = code_next(c); if (config.flags2 & CFG2seh) nteh_patchindex(c2, scopeindex); if (config.ehmethod == EH_DM) pdt = dtdword(pdt,boffset - startblock->Boffset); // guard offset // Find corresponding ddtor instruction int n = 0; unsigned eoffset = boffset; unsigned foffset; for (; 1; c2 = code_next(c2)) { // Bugzilla 13720: optimizer might elide the corresponding ddtor if (!c2) goto Lnodtor; if (c2->Iop == (ESCAPE | ESCddtor)) { if (n) n--; else { foffset = eoffset; code *cf = code_next(c2); if (config.flags2 & CFG2seh) { nteh_patchindex(cf, stack[stacki - 1]); foffset += calccodsize(cf); cf = code_next(cf); } foffset += calccodsize(cf); while (!cf->isJumpOP()) { cf = code_next(cf); foffset += calccodsize(cf); } // issue 9438 //cf = code_next(cf); //foffset += calccodsize(cf); if (config.ehmethod == EH_DM) pdt = dtdword(pdt,eoffset - startblock->Boffset); // guard offset break; } } else if (c2->Iop == (ESCAPE | ESCdctor)) { n++; } else eoffset += calccodsize(c2); } //printf("boffset = %x, eoffset = %x, foffset = %x\n", boffset, eoffset, foffset); pdt = dtdword(pdt,stack[stacki - 1]); // parent index pdt = dtdword(pdt,0); // no catch offset if (config.ehmethod == EH_DM) { assert(foffset > startblock->Boffset); pdt = dtsize_t(pdt,foffset - startblock->Boffset); // finally handler offset } else pdt = dtcoff(pdt,foffset); // finally handler address if (stacki == stackmax) { // stack[] is out of space; enlarge it int *pi = (int *)malloc((stackmax + STACKINC) * sizeof(int)); assert(pi); memcpy(pi, stack, stackmax * sizeof(int)); if (stack != stackbuf) free(stack); stack = pi; stackmax += STACKINC; } stack[stacki++] = scopeindex; ++scopeindex; sz += GUARD_SIZE; } else if (c->Iop == (ESCAPE | ESCddtor)) { stacki--; assert(stacki != 0); } Lnodtor: boffset += calccodsize(c); } } if (stack != stackbuf) free(stack); } // Generate catch[] for (block *b = startblock; b; b = b->Bnext) { if (b->BC == BC_try && b->jcatchvar) // if try-catch { int nsucc = b->numSucc(); pdt = dtsize_t(pdt,nsucc - 1); // # of catch blocks sz += NPTRSIZE; for (int i = 1; i < nsucc; ++i) { block *bcatch = b->nthSucc(i); pdt = dtxoff(pdt,bcatch->Bcatchtype,0,TYnptr); pdt = dtsize_t(pdt,cod3_bpoffset(b->jcatchvar)); // EBP offset // catch handler address if (config.ehmethod == EH_DM) { assert(bcatch->Boffset > startblock->Boffset); pdt = dtsize_t(pdt,bcatch->Boffset - startblock->Boffset); // catch handler offset } else pdt = dtcoff(pdt,bcatch->Boffset); sz += 3 * NPTRSIZE; } } } assert(sz != 0); }
static int cmdfunc_extcmd( int cmd ) { // cmdfunc : TYPE_EXTCMD // (内蔵GUIコマンド) // code_next(); // 次のコードを取得(最初に必ず必要です) switch( cmd ) { // サブコマンドごとの分岐 case 0x02: // exec { char *ps; char fname[HSP_MAX_PATH]; strncpy( fname, code_gets(), HSP_MAX_PATH-1 ); p1 = code_getdi( 0 ); ps = code_getds( "" ); ExecFile( fname, ps, p1 ); break; } case 0x03: // dialog cmdfunc_dialog(); break; case 0x0f: // mes,print { //char stmp[1024]; char *ptr; int chk; chk = code_get(); if ( chk<=PARAM_END ) { printf( "¥n" ); break; } ptr = (char *)(HspVarCorePtr(mpval)); if ( mpval->flag != HSPVAR_FLAG_STR ) { ptr = (char *)HspVarCoreCnv( mpval->flag, HSPVAR_FLAG_STR, ptr ); // 型が一致しない場合は変換 } printf( "%s¥n",ptr ); //strsp_ini(); //while(1) { // chk = strsp_get( ptr, stmp, 0, 1022 ); // printf( "%s¥n",stmp ); // if ( chk == 0 ) break; //} break; } case 0x27: // input (console) { PVal *pval; APTR aptr; char *pp2; char *vptr; int strsize; int a; strsize = 0; aptr = code_getva( &pval ); //pp2 = code_getvptr( &pval, &size ); p2 = code_getdi( 0x4000 ); p3 = code_getdi( 0 ); if ( p2 < 64 ) p2 = 64; pp2 = code_stmp( p2+1 ); switch( p3 & 15 ) { case 0: while(1) { if ( p2<=0 ) break; a = getchar(); if ( a==EOF ) break; *pp2++ = a; p2--; strsize++; } break; case 1: while(1) { if ( p2<=0 ) break; a = getchar(); if (( a==EOF )||( a=='\n' )) break; *pp2++ = a; p2--; strsize++; } break; case 2: while(1) { if ( p2<=0 ) break; a = getchar(); if ( a == '\r' ) { int c = getchar(); if( c != '\n' ) { ungetc(c, stdin); } break; } if (( a==EOF )||( a=='\n' )) break; *pp2++ = a; p2--; strsize++; } break; } *pp2 = 0; ctx->strsize = strsize + 1; if ( p3 & 16 ) { if (( pval->support & HSPVAR_SUPPORT_FLEXSTORAGE ) == 0 ) throw HSPERR_TYPE_MISMATCH; //HspVarCoreAllocBlock( pval, (PDAT *)vptr, strsize ); vptr = (char *)HspVarCorePtrAPTR( pval, aptr ); memcpy( vptr, ctx->stmp, strsize ); } else { code_setva( pval, aptr, TYPE_STRING, ctx->stmp ); } break; } default: throw HSPERR_UNSUPPORTED_FUNCTION; } return RUNMODE_RUN; }
static int cmdfunc_intcmd( int cmd ) { // cmdfunc : TYPE_INTCMD // (内蔵コマンド) // int p1,p2,p3; // code_next(); // 次のコードを取得(最初に必ず必要です) switch( cmd ) { // サブコマンドごとの分岐 case 0x00: // onexit case 0x01: // onerror case 0x02: // onkey case 0x03: // onclick case 0x04: // oncmd { /* rev 45 不具合 : (onxxx系命令) (ラベル型変数) 形式の書式でエラー に対処 */ int tval = *type; int opt = IRQ_OPT_GOTO; int cust; int actid; IRQDAT *irq; unsigned short *sbr; if ( tval == TYPE_VAR ) { if ( ( ctx->mem_var + *val )->flag == HSPVAR_FLAG_LABEL ) tval = TYPE_LABEL; } if (( tval != TYPE_PROGCMD )&&( tval != TYPE_LABEL )) { // ON/OFF切り替え int i = code_geti(); code_enableirq( cmd, i ); break; } if ( tval == TYPE_PROGCMD ) { // ジャンプ方法指定 opt = *val; if ( opt >= 2 ) throw HSPERR_SYNTAX; code_next(); } sbr = code_getlb2(); if ( cmd != 0x04 ) { code_setirq( cmd, opt, -1, sbr ); break; } cust = code_geti(); actid = *(exinfo->actscr); irq = code_seekirq( actid, cust ); if ( irq == NULL ) irq = code_addirq(); irq->flag = IRQ_FLAG_ENABLE; irq->opt = opt; irq->ptr = sbr; irq->custom = cust; irq->custom2 = actid; break; } case 0x11: // exist case 0x12: // delete case 0x13: // mkdir case 0x14: // chdir code_event( HSPEVENT_FNAME, 0, 0, code_gets() ); code_event( HSPEVENT_FEXIST + (cmd - 0x11), 0, 0, NULL ); break; case 0x15: // dirlist { PVal *pval; APTR aptr; char *ptr; aptr = code_getva( &pval ); code_event( HSPEVENT_FNAME, 0, 0, code_gets() ); p1=code_getdi(0); code_event( HSPEVENT_FDIRLIST1, p1, 0, &ptr ); code_setva( pval, aptr, TYPE_STRING, ptr ); code_event( HSPEVENT_FDIRLIST2, 0, 0, NULL ); break; } case 0x16: // bload case 0x17: // bsave { PVal *pval; char *ptr; int size; int tmpsize; code_event( HSPEVENT_FNAME, 0, 0, code_gets() ); ptr = code_getvptr( &pval, &size ); p1 = code_getdi( -1 ); p2 = code_getdi( -1 ); if (( p1 < 0 )||( p1 > size )) p1 = size; if ( cmd == 0x16 ) { tmpsize = p2;if ( tmpsize<0 ) tmpsize = 0; code_event( HSPEVENT_FREAD, tmpsize, p1, ptr ); } else { code_event( HSPEVENT_FWRITE, p2, p1, ptr ); } break; } case 0x18: // bcopy code_event( HSPEVENT_FNAME, 0, 0, code_gets() ); code_event( HSPEVENT_FCOPY, 0, 0, code_gets() ); break; case 0x19: // memfile { PVal *pval; char *ptr; int size; ptr = code_getvptr( &pval, &size ); p1=code_getdi( 0 ); p2=code_getdi( 0 ); if ( p2==0 ) p2 = size - p1; dpm_memfile( ptr+p1, p2 ); break; } case 0x1a: // poke case 0x1b: // wpoke case 0x1c: // lpoke { PVal *pval; char *ptr; int size; int fl; int len; char *bp; ptr = code_getvptr( &pval, &size ); p1 = code_getdi( 0 ); if ( p1<0 ) throw HSPERR_BUFFER_OVERFLOW; ptr += p1; if ( code_get() <= PARAM_END ) { fl = HSPVAR_FLAG_INT; bp = (char *)&p2; p2 = 0; } else { fl = mpval->flag; bp = mpval->pt; } if ( cmd == 0x1a ) { switch( fl ) { case HSPVAR_FLAG_INT: if ( p1 >= size ) throw HSPERR_BUFFER_OVERFLOW; *ptr = *bp; break; case HSPVAR_FLAG_STR: len = (int)strlen( bp ); ctx->strsize = len; len++; if ( (p1+len)>size ) throw HSPERR_BUFFER_OVERFLOW; strcpy( ptr, bp ); break; default: throw HSPERR_TYPE_MISMATCH; } break; } if ( fl != HSPVAR_FLAG_INT ) throw HSPERR_TYPE_MISMATCH; if ( cmd == 0x1b ) { if ( (p1+2)>size ) throw HSPERR_BUFFER_OVERFLOW; *(short *)ptr = (short)(*(short *)bp); } else { if ( (p1+4)>size ) throw HSPERR_BUFFER_OVERFLOW; *(int *)ptr = (*(int *)bp); } break; } case 0x1d: // getstr { PVal *pval2; PVal *pval; APTR aptr; char *ptr; char *p; int size; aptr = code_getva( &pval ); ptr = code_getvptr( &pval2, &size ); p1 = code_getdi( 0 ); p2 = code_getdi( 0 ); p3 = code_getdi( 1024 ); if ( p1 >= size ) throw HSPERR_BUFFER_OVERFLOW; ptr += p1; p = code_stmp( p3 + 1 ); strsp_ini(); ctx->stat = strsp_get( ptr, p, p2, p3 ); ctx->strsize = strsp_getptr(); code_setva( pval, aptr, HSPVAR_FLAG_STR, p ); break; } case 0x1e: // chdpm code_event( HSPEVENT_FNAME, 0, 0, code_gets() ); p1 = code_getdi( -1 ); dpm_bye(); p2 = dpm_ini( ctx->fnbuffer, 0, -1, p1 ); if ( p2 ) throw HSPERR_FILE_IO; #ifndef HSP3IMP #ifdef HSPWIN Sleep( 1000 ); #endif #endif break; case 0x1f: // memexpand { PVal *pval; APTR aptr; PDAT *ptr; aptr = code_getva( &pval ); ptr = HspVarCorePtrAPTR( pval, aptr ); if (( pval->support & HSPVAR_SUPPORT_FLEXSTORAGE ) == 0 ) throw HSPERR_TYPE_MISMATCH; p1 = code_getdi( 0 ); if ( p1 < 64 ) p1 = 64; HspVarCoreAllocBlock( pval, ptr, p1 ); break; } case 0x20: // memcpy { PVal *pval; char *sptr; char *tptr; int bufsize_t,bufsize_s; tptr = code_getvptr( &pval, &bufsize_t ); sptr = code_getvptr( &pval, &bufsize_s ); p1 = code_getdi( 0 ); p2 = code_getdi( 0 ); p3 = code_getdi( 0 ); if( p2 < 0 || p3 < 0 ) throw HSPERR_BUFFER_OVERFLOW; tptr += p2; sptr += p3; if ( (p1+p2)>bufsize_t ) throw HSPERR_BUFFER_OVERFLOW; if ( (p1+p3)>bufsize_s ) throw HSPERR_BUFFER_OVERFLOW; if ( p1>0 ) { memmove( tptr, sptr, p1 ); } break; } case 0x21: // memset { PVal *pval; char *ptr; int size; ptr = code_getvptr( &pval, &size ); p1 = code_getdi( 0 ); p2 = code_getdi( 0 ); p3 = code_getdi( 0 ); if ( p3 < 0 ) throw HSPERR_BUFFER_OVERFLOW; ptr += p3; if ( (p3+p2)>size ) throw HSPERR_BUFFER_OVERFLOW; if ( p2>0 ) { memset( ptr, p1, p2 ); } break; } case 0x22: // notesel ctx->notep_aptr = ctx->note_aptr; ctx->notep_pval = ctx->note_pval; ctx->note_aptr = code_getva( &ctx->note_pval ); if ( ctx->note_pval->flag != HSPVAR_FLAG_STR ) { code_setva( ctx->note_pval, ctx->note_aptr, TYPE_STRING, "" ); } break; case 0x23: // noteadd { char *np; char *ps; char *tmp; int size; np = note_update(); ps = code_gets(); size = (int)strlen( ps ) + 8; HspVarCoreAllocBlock( ctx->note_pval, (PDAT *)np, (int)strlen(np) + size ); tmp = code_stmpstr( ps ); p1 = code_getdi( -1 ); p2 = code_getdi( 0 ); np = note_update(); note.PutLine( tmp, p1, p2 ); break; } case 0x24: // notedel p1 = code_getdi( 0 ); note_update(); note.PutLine( NULL, p1, 1 ); break; case 0x25: // noteload { int size; char *ptr; char *pdat; code_event( HSPEVENT_FNAME, 0, 0, code_gets() ); p1 = code_getdi( -1 ); code_event( HSPEVENT_FEXIST, 0, 0, NULL ); size = ctx->strsize; if ( size < 0 ) throw HSPERR_FILE_IO; if ( p1>=0 ) if ( size >= p1 ) { ctx->strsize = size = p1; } pdat = note_update(); HspVarCoreAllocBlock( ctx->note_pval, (PDAT *)pdat, size+1 ); ptr = (char *)note_update(); code_event( HSPEVENT_FREAD, 0, size, ptr ); ptr[size] = 0; break; } case 0x26: // notesave { char *pdat; int size; code_event( HSPEVENT_FNAME, 0, 0, code_gets() ); pdat = note_update(); size = (int)strlen( pdat ); code_event( HSPEVENT_FWRITE, -1, size, pdat ); break; } case 0x27: // randomize #ifdef HSPWIN p2 = (int)GetTickCount(); // Windowsの場合はtickをシード値とする #else p2 = (int)time(0); // Windows以外のランダムシード値 #endif p1 = code_getdi( p2 ); #ifdef HSPRANDMT mt.seed( p1 ); #else srand( p1 ); #endif break; case 0x28: // noteunsel ctx->note_aptr = ctx->notep_aptr; ctx->note_pval = ctx->notep_pval; break; case 0x29: // noteget { PVal *pval; APTR aptr; char *p; note_update(); aptr = code_getva( &pval ); p1 = code_getdi( 0 ); p = note.GetLineDirect( p1 ); code_setva( pval, aptr, TYPE_STRING, p ); note.ResumeLineDirect(); break; } case 0x2a: // split { // 指定した文字列で分割された要素を代入する(fujidig) PVal *pval = NULL; int aptr = 0; char *sptr; char *sep; char *newsptr; int size; int sep_len; int n = 0; int is_last = 0; sptr = code_getvptr( &pval, &size ); if ( pval->flag != HSPVAR_FLAG_STR ) throw HSPERR_TYPE_MISMATCH; sep = code_gets(); sep_len = (int)strlen( sep ); while (1) { newsptr = strstr2( sptr, sep ); if ( !is_last && *exinfo->npexflg & EXFLG_1 ) { // 分割結果の数が格納する変数より多ければ最後の変数に配列で格納していく // ただし最後の要素が a.2 のように要素指定があればそれ以降は全く格納しない if ( aptr != 0 ) pval = NULL; is_last = 1; aptr = 0; } if ( is_last ) { aptr ++; if ( pval != NULL && aptr >= pval->len[1] ) { if ( pval->len[2] != 0 ) throw HSPVAR_ERROR_ARRAYOVER; HspVarCoreReDim( pval, 1, aptr+1 ); } } else { aptr = code_getva( &pval ); } if ( pval != NULL ) { if ( newsptr == NULL ) { code_setva( pval, aptr, HSPVAR_FLAG_STR, sptr ); } else { var_set_str_len( pval, aptr, sptr, (int)(newsptr - sptr) ); } } n ++; if ( newsptr == NULL ) { // 格納する変数の数が分割できた数より多ければ残った変数それぞれに空文字列を格納する while( ( *exinfo->npexflg & EXFLG_1 ) == 0 ) { aptr = code_getva( &pval ); code_setva( pval, aptr, HSPVAR_FLAG_STR, "" ); } break; } sptr = newsptr + sep_len; } ctx->stat = n; break; } case 0x02b: // strrep { PVal *pval; APTR aptr; char *ss; char *s_rep; char *s_buffer; char *s_result; aptr = code_getva( &pval ); if ( pval->flag != HSPVAR_FLAG_STR ) throw HSPERR_TYPE_MISMATCH; s_buffer = (char *)HspVarCorePtrAPTR( pval, aptr ); ss = code_gets(); if ( *ss == 0 ) throw HSPERR_ILLEGAL_FUNCTION; ReplaceSetMatch( s_buffer, ss ); s_rep = code_gets(); s_result = ReplaceStr( s_rep ); code_setva( pval, aptr, TYPE_STRING, s_result ); ctx->stat = ReplaceDone(); break; } case 0x02c: // setease { HSPREAL dval; HSPREAL dval2; dval = code_getd(); dval2 = code_getd(); p1 = code_getdi( ease_type ); setEase( p1, dval, dval2 ); break; } case 0x02d: // sortval { int a,i; PVal *p1; APTR ap; int order; ap = code_getva( &p1 ); // パラメータ1:変数 order = code_getdi( 0 ); // パラメータ2:数値 i=p1->len[1]; if (i<=0) throw HSPERR_ILLEGAL_FUNCTION; switch(p1->flag) { case HSPVAR_FLAG_DOUBLE: { double *dp; dp=(double *)p1->pt; DataIni( i ); for(a=0;a<i;a++) { dtmp[a].as.dkey=dp[a]; dtmp[a].info=a; } if (order == 0) { std::sort(dtmp, dtmp + i, less_double_1); } else { std::sort(dtmp, dtmp + i, less_double_0); } for(a=0;a<i;a++) { code_setva( p1, a, HSPVAR_FLAG_DOUBLE, &(dtmp[a].as.dkey) ); // 変数に値を代入 } break; } case HSPVAR_FLAG_INT: { int *p; p=(int *)p1->pt; DataIni( i ); for(a=0;a<i;a++) { dtmp[a].as.ikey=p[a]; dtmp[a].info=a; } if (order == 0) { std::sort(dtmp, dtmp + i, less_int_1); } else { std::sort(dtmp, dtmp + i, less_int_0); } for(a=0;a<i;a++) { p[a]=dtmp[a].as.ikey; } break; } default: throw HSPERR_ILLEGAL_FUNCTION; } break; } case 0x02e: // sortstr { int i,len,order; char *p; PVal *pv; APTR ap; HspVarProc *proc; char **pvstr; ap = code_getva( &pv ); // パラメータ1:変数 order = code_getdi( 0 ); // パラメータ2:数値 if ( pv->flag != 2 ) throw HSPERR_TYPE_MISMATCH; if (( pv->len[2] != 0 )||( ap != 0 )) throw HSPERR_ILLEGAL_FUNCTION; proc = HspVarCoreGetProc( pv->flag ); len = pv->len[1]; DataIni( len ); for(i=0;i<len;i++) { p = (char *)HspVarCorePtrAPTR( pv, i ); dtmp[i].as.skey = p; dtmp[i].info = i; } if (order == 0) { std::sort(dtmp, dtmp + i, less_str_1); } else { std::sort(dtmp, dtmp + i, less_str_0); } pvstr = (char **)(pv->master); // 変数に直接sbポインタを書き戻す for(i=0;i<len;i++) { if ( i == 0 ) { pv->pt = dtmp[i].as.skey; sbSetOption(pv->pt, &pv->pt); } else { pvstr[i] = dtmp[i].as.skey; sbSetOption(pvstr[i], &pvstr[i]); } } break; } case 0x02f: // sortnote { int i,sflag; char *p; char *stmp; PVal *pv; APTR ap; ap = code_getva( &pv ); // パラメータ1:変数 sflag = code_getdi( 0 ); // パラメータ2:数値 p = (char *)HspVarCorePtrAPTR( pv, ap ); i = GetNoteLines(p); if ( i <= 0 ) throw HSPERR_ILLEGAL_FUNCTION; DataIni( i ); NoteToData( p, dtmp ); if (sflag == 0) { std::sort(dtmp, dtmp + i, less_str_1); } else { std::sort(dtmp, dtmp + i, less_str_0); } stmp = code_stmp( (int)DataToNoteLen( dtmp, i ) + 1 ); DataToNote( dtmp, stmp, i ); code_setva( pv, ap, HSPVAR_FLAG_STR, stmp ); // 変数に値を代入 break; } case 0x030: // sortget { PVal *pv; APTR ap; int result; int n; ap = code_getva( &pv ); n = code_getdi( 0 ); if ( dtmp == NULL ) throw HSPERR_ILLEGAL_FUNCTION; if (0 <= n && n < dtmp_size ) { result=dtmp[n].info; } else { result=0; } code_setva( pv, ap, HSPVAR_FLAG_INT, &result ); break; } default: throw HSPERR_UNSUPPORTED_FUNCTION; } return RUNMODE_RUN; }
static void *reffunc_intfunc( int *type_res, int arg ) { // reffunc : TYPE_INTFUNC // (内蔵関数) // void *ptr; int chk; HSPREAL dval; HSPREAL dval2; int ival; char *sval; int p1,p2,p3; // '('で始まるかを調べる // if ( *type != TYPE_MARK ) throw HSPERR_INVALID_FUNCPARAM; if ( *val != '(' ) throw HSPERR_INVALID_FUNCPARAM; code_next(); // 返値のタイプをargをもとに設定する // 0~255 : int // 256~383 : string // 384~511 : double(HSPREAL) // switch( arg>>7 ) { case 2: // 返値がstr *type_res = HSPVAR_FLAG_STR; // 返値のタイプを指定する ptr = NULL; // 返値のポインタ break; case 3: // 返値がdouble *type_res = HSPVAR_FLAG_DOUBLE; // 返値のタイプを指定する ptr = &reffunc_intfunc_value; // 返値のポインタ break; default: // 返値がint *type_res = HSPVAR_FLAG_INT; // 返値のタイプを指定する ptr = &reffunc_intfunc_ivalue; // 返値のポインタ break; } switch( arg ) { // int function case 0x000: // int { int *ip; chk = code_get(); if ( chk <= PARAM_END ) { throw HSPERR_INVALID_FUNCPARAM; } ip = (int *)HspVarCoreCnvPtr( mpval, HSPVAR_FLAG_INT ); reffunc_intfunc_ivalue = *ip; break; } case 0x001: // rnd ival = code_geti(); if ( ival == 0 ) throw HSPERR_DIVIDED_BY_ZERO; #ifdef HSPRANDMT { std::uniform_int_distribution<int> dist( 0, ival - 1 ); reffunc_intfunc_ivalue = dist( mt ); } #else reffunc_intfunc_ivalue = rand()%ival; #endif break; case 0x002: // strlen sval = code_gets(); reffunc_intfunc_ivalue = (int) strlen( sval ); break; case 0x003: // length(3.0) case 0x004: // length2(3.0) case 0x005: // length3(3.0) case 0x006: // length4(3.0) { PVal *pv; pv = code_getpval(); reffunc_intfunc_ivalue = pv->len[ arg - 0x002 ]; break; } case 0x007: // vartype(3.0) { PVal *pv; HspVarProc *proc; if ( *type == TYPE_STRING ) { sval = code_gets(); proc = HspVarCoreSeekProc( sval ); if ( proc == NULL ) throw HSPERR_ILLEGAL_FUNCTION; reffunc_intfunc_ivalue = proc->flag; } else { code_getva( &pv ); reffunc_intfunc_ivalue = pv->flag; } break; } case 0x008: // gettime ival = code_geti(); reffunc_intfunc_ivalue = gettime( ival ); break; case 0x009: // peek case 0x00a: // wpeek case 0x00b: // lpeek { PVal *pval; char *ptr; int size; ptr = code_getvptr( &pval, &size ); p1 = code_getdi( 0 ); if ( p1<0 ) throw HSPERR_ILLEGAL_FUNCTION; ptr += p1; if ( arg == 0x09 ) { if ( (p1+1)>size ) throw HSPERR_ILLEGAL_FUNCTION; reffunc_intfunc_ivalue = ((int)(*ptr)) & 0xff; } else if ( arg == 0x0a ) { if ( (p1+2)>size ) throw HSPERR_ILLEGAL_FUNCTION; reffunc_intfunc_ivalue = ((int)(*(short *)ptr)) & 0xffff; } else { if ( (p1+4)>size ) throw HSPERR_ILLEGAL_FUNCTION; reffunc_intfunc_ivalue = *(int *)ptr; } break; } case 0x00c: // varptr { PVal *pval; APTR aptr; PDAT *pdat; STRUCTDAT *st; if ( *type == TYPE_DLLFUNC ) { st = &(ctx->mem_finfo[ *val ]); reffunc_intfunc_ivalue = (int)(size_t)(st->proc); code_next(); break; } aptr = code_getva( &pval ); pdat = HspVarCorePtrAPTR( pval, aptr ); reffunc_intfunc_ivalue = (int)(size_t)(pdat); break; } case 0x00d: // varuse { PVal *pval; APTR aptr; PDAT *pdat; aptr = code_getva( &pval ); if ( pval->support & HSPVAR_SUPPORT_VARUSE ) { pdat = HspVarCorePtrAPTR( pval, aptr ); reffunc_intfunc_ivalue = HspVarCoreGetUsing( pval, pdat ); } else throw HSPERR_TYPE_MISMATCH; break; } case 0x00e: // noteinfo ival = code_getdi(0); note_update(); switch( ival ) { case 0: reffunc_intfunc_ivalue = note.GetMaxLine(); break; case 1: reffunc_intfunc_ivalue = note.GetSize(); break; default: throw HSPERR_ILLEGAL_FUNCTION; } break; case 0x00f: // instr { PVal *pval; char *ptr; char *ps; char *ps2; int size; int p1; ptr = code_getvptr( &pval, &size ); if ( pval->flag != HSPVAR_FLAG_STR ) throw HSPERR_TYPE_MISMATCH; p1 = code_getdi(0); if ( p1 >= size ) throw HSPERR_BUFFER_OVERFLOW; ps = code_gets(); if ( p1 >= 0 ) { ptr += p1; ps2 = strstr2( ptr, ps ); } else { ps2 = NULL; } if ( ps2 == NULL ) { reffunc_intfunc_ivalue = -1; } else { reffunc_intfunc_ivalue = (int)(ps2 - ptr); } break; } case 0x010: // abs reffunc_intfunc_ivalue = code_geti(); if ( reffunc_intfunc_ivalue < 0 ) reffunc_intfunc_ivalue = -reffunc_intfunc_ivalue; break; case 0x011: // limit p1 = code_geti(); p2 = code_geti(); p3 = code_geti(); reffunc_intfunc_ivalue = GetLimit( p1, p2, p3 ); break; case 0x012: // getease p1 = code_geti(); p2 = code_getdi(-1); reffunc_intfunc_ivalue = getEaseInt( p1, p2 ); break; case 0x013: // notefind { char *ps; char *p; int findopt; ps = code_gets(); p = code_stmpstr( ps ); findopt = code_getdi(0); note_update(); reffunc_intfunc_ivalue = note.FindLine( p, findopt ); break; } // str function case 0x100: // str { char *sp; chk = code_get(); if ( chk <= PARAM_END ) { throw HSPERR_INVALID_FUNCPARAM; } sp = (char *)HspVarCoreCnvPtr( mpval, HSPVAR_FLAG_STR ); ptr = (void *)sp; break; } case 0x101: // strmid { PVal *pval; char *sptr; char *p; char chrtmp; int size; int i; int slen; sptr = code_getvptr( &pval, &size ); if ( pval->flag != HSPVAR_FLAG_STR ) throw HSPERR_TYPE_MISMATCH; p1 = code_geti(); p2 = code_geti(); slen=(int)strlen( sptr ); if ( p1 < 0 ) { p1=slen - p2; if ( p1 < 0 ) p1 = 0; } if ( p1 >= slen ) p2 = 0; if ( p2 > slen ) p2 = slen; sptr += p1; ptr = p = code_stmp( p2 + 1 ); for(i=0;i<p2;i++) { chrtmp = *sptr++; *p++ = chrtmp; if (chrtmp==0) break; } *p = 0; break; } case 0x103: // strf ptr = cnvformat(); break; case 0x104: // getpath { char *p; char pathname[HSP_MAX_PATH]; p = ctx->stmp; strncpy( pathname, code_gets(), HSP_MAX_PATH-1 ); p1=code_geti(); getpath( pathname, p, p1 ); ptr = p; break; } case 0x105: // strtrim { PVal *pval; char *sptr; char *p; int size; sptr = code_getvptr( &pval, &size ); if ( pval->flag != HSPVAR_FLAG_STR ) throw HSPERR_TYPE_MISMATCH; p1 = code_getdi(0); p2 = code_getdi(32); ptr = p = code_stmp( size + 1 ); strcpy( p, sptr ); switch( p1 ) { case 0: TrimCodeL( p, p2 ); TrimCodeR( p, p2 ); break; case 1: TrimCodeL( p, p2 ); break; case 2: TrimCodeR( p, p2 ); break; case 3: TrimCode( p, p2 ); break; } break; } // double function case 0x180: // sin dval = code_getd(); reffunc_intfunc_value = sin( dval ); break; case 0x181: // cos dval = code_getd(); reffunc_intfunc_value = cos( dval ); break; case 0x182: // tan dval = code_getd(); reffunc_intfunc_value = tan( dval ); break; case 0x183: // atan dval = code_getd(); dval2 = code_getdd( 1.0 ); reffunc_intfunc_value = atan2( dval, dval2 ); break; case 0x184: // sqrt dval = code_getd(); reffunc_intfunc_value = sqrt( dval ); break; case 0x185: // double { HSPREAL *dp; chk = code_get(); if ( chk <= PARAM_END ) { throw HSPERR_INVALID_FUNCPARAM; } dp = (HSPREAL *)HspVarCoreCnvPtr( mpval, HSPVAR_FLAG_DOUBLE ); reffunc_intfunc_value = *dp; break; } case 0x186: // absf reffunc_intfunc_value = code_getd(); if ( reffunc_intfunc_value < 0 ) reffunc_intfunc_value = -reffunc_intfunc_value; break; case 0x187: // expf dval = code_getd(); reffunc_intfunc_value = exp( dval ); break; case 0x188: // logf dval = code_getd(); reffunc_intfunc_value = log( dval ); break; case 0x189: // limitf { HSPREAL d1,d2,d3; d1 = code_getd(); d2 = code_getd(); d3 = code_getd(); if ( d1 < d2 ) d1 = d2; if ( d1 > d3 ) d1 = d3; reffunc_intfunc_value = d1; break; } case 0x18a: // powf dval = code_getd(); dval2 = code_getd(); reffunc_intfunc_value = pow( dval, dval2 ); break; case 0x18b: // geteasef dval = code_getd(); dval2 = code_getdd(1.0); if ( dval2 == 1.0 ) { reffunc_intfunc_value = getEase( dval ); } else { reffunc_intfunc_value = getEase( dval, dval2 ); } break; default: throw HSPERR_UNSUPPORTED_FUNCTION; } // ')'で終わるかを調べる // if ( *type != TYPE_MARK ) throw HSPERR_INVALID_FUNCPARAM; if ( *val != ')' ) throw HSPERR_INVALID_FUNCPARAM; code_next(); return ptr; }
static void *reffunc_ctrlfunc( int *type_res, int arg ) { // reffunc : TYPE_DLLCTRL // (拡張DLLコントロール関数) // void *ptr; int p1,p2; // '('で始まるかを調べる // if ( *type != TYPE_MARK ) throw ( HSPERR_INVALID_FUNCPARAM ); if ( *val != '(' ) throw ( HSPERR_INVALID_FUNCPARAM ); code_next(); ptr = &reffunc_intfunc_ivalue; *type_res = HSPVAR_FLAG_INT; switch( arg ) { // サブコマンドごとの分岐 case 0x100: // callfunc { PVal *pval; PDAT *p; pval = code_getpval(); p = HspVarCorePtrAPTR( pval, 0 ); p1 = code_geti(); p2 = code_geti(); reffunc_intfunc_ivalue = call_extfunc( (void *)p1, (int *)p, p2 ); break; } case 0x101: // cnvwtos { PVal *pval; char *sptr; int size; sptr = code_getvptr( &pval, &size ); hspctx->stmp = sbExpand( hspctx->stmp, size ); ptr = hspctx->stmp; cnvsjis( ptr, sptr, size ); *type_res = HSPVAR_FLAG_STR; break; } case 0x102: // comevdisp #ifdef HSP_COM_UNSUPPORTED throw ( HSPERR_UNSUPPORTED_FUNCTION ); #else { PVal *pval; APTR aptr; IUnknown **ppunk; // 第1パラメータ:COMオブジェクト変数 aptr = code_getva( &pval ); if ( pval->flag != TYPE_COMOBJ ) throw ( HSPERR_TYPE_MISMATCH ); ppunk = (IUnknown **)HspVarCorePtrAPTR( pval, aptr ); if ( !IsVaridComPtr(ppunk) ) throw ( HSPERR_COMDLL_ERROR ); // イベントの DISPID 取得 reffunc_intfunc_ivalue = GetEventDispID( *ppunk ); break; } #endif // HSP_COM_UNSUPPORTED case 0x103: // libptr { //LIBDAT *lib; STRUCTDAT *st; switch( *type ) { case TYPE_DLLFUNC: case TYPE_MODCMD: p1 = *val; break; case TYPE_DLLCTRL: p1 = *val; if ( p1 >= TYPE_OFFSET_COMOBJ ) { p1 -= TYPE_OFFSET_COMOBJ; break; } default: throw ( HSPERR_TYPE_MISMATCH ); } code_next(); st = GetPRM( p1 ); //lib = &hspctx->mem_linfo[ st->index ]; reffunc_intfunc_ivalue = (int)st; break; } default: throw ( HSPERR_SYNTAX ); } // ')'で終わるかを調べる // if ( *type != TYPE_MARK ) throw ( HSPERR_INVALID_FUNCPARAM ); if ( *val != ')' ) throw ( HSPERR_INVALID_FUNCPARAM ); code_next(); return ptr; }
static int cmdfunc_ctrlcmd( int cmd ) { // cmdfunc : TYPE_DLLCTRL // (拡張DLLコントロールコマンド) // code_next(); // 次のコードを取得(最初に必ず必要です) if ( cmd >= TYPE_OFFSET_COMOBJ ) { #ifdef HSP_COM_UNSUPPORTED throw ( HSPERR_UNSUPPORTED_FUNCTION ); #else // COM インターフェースメソッドの呼び出し STRUCTDAT *st; st = GetPRM( cmd - TYPE_OFFSET_COMOBJ ); hspctx->stat = code_expand_and_call( st ); return RUNMODE_RUN; #endif } switch( cmd ) { // サブコマンドごとの分岐 case 0x00: // newcom #ifdef HSP_COM_UNSUPPORTED throw ( HSPERR_UNSUPPORTED_FUNCTION ); #else { PVal *pval; APTR aptr; IUnknown **ppunkNew, *punkDef; CLSID clsid; char *clsid_name; const IID *piid, *piid2; void *iptr; LIBDAT *lib; STRUCTDAT *st; int inimode; // 第1パラメータ:新しいインターフェースポインタを格納する変数 // (変数にNULLポインタを格納) aptr = code_getva( &pval ); iptr = NULL; code_setva( pval, aptr, TYPE_COMOBJ, &iptr ); ppunkNew = (IUnknown **)HspVarCorePtrAPTR( pval, aptr ); // CLSID / IID 情報を取得 if ( !code_getexflg() && *type == TYPE_DLLCTRL ) { // 第2パラメータ:#usecom 登録情報 st = code_getcomst(); if ( st->otindex != -1 ) throw HSPERR_TYPE_MISMATCH; lib = &hspctx->mem_linfo[ st->index ]; if ( lib->clsid == -1 ) throw HSPERR_INVALID_PARAMETER; clsid_name = strp(lib->clsid); piid = (IID *)strp( lib->nameidx ); piid2 = NULL; } else { // 第2パラメータ:文字列 CLSID // (IID はデフォルトで IID_IDispatch, サポートされていなければ IID_IUnknown ) clsid_name = code_getds(""); piid = &IID_IDispatch; piid2 = &IID_IUnknown; } inimode = code_getdi(0); // 初期化モード punkDef = (IUnknown *)code_getdi(0); // デフォルトオブジェクト // 新規CLSIDからインスタンスを作成 hspctx->stat = 0; switch ( inimode ) { case 0: // 新規にロード if ( clsid_name[0]!='\0' ) { if ( GetIIDFromString(&clsid,clsid_name,true) != FALSE && SUCCEEDED( CoCreateInstance( clsid, NULL, CLSCTX_SERVER, *piid, (void**)ppunkNew )) && *ppunkNew != NULL ) { break; } if ( piid2 != NULL && SUCCEEDED( CoCreateInstance( clsid, NULL, CLSCTX_SERVER, *piid2, (void**)ppunkNew )) && *ppunkNew != NULL ) { break; } hspctx->stat = 1; } break; case -2: // オブジェクトを明示的に指定する場合 ( AddRef() あり) if ( punkDef != NULL ) punkDef->AddRef(); case -1: // オブジェクトを明示的に指定する場合 ( AddRef() なし) *ppunkNew = punkDef; break; default: throw HSPERR_UNSUPPORTED_FUNCTION; } #ifdef HSP_COMOBJ_DEBUG COM_DBG_MSG( "newcom : pObj=%p : &pObj=%p\n", *ppunkNew, ppunkNew); #endif break; } #endif // HSP_COM_UNSUPPORTED case 0x01: // querycom #ifdef HSP_COM_UNSUPPORTED throw HSPERR_UNSUPPORTED_FUNCTION; #else { PVal *pval, *pvalNew; APTR aptr, aptrNew; IUnknown **ppunkDst, **ppunkSrc; IID iid; const IID *piid; void *iptr; STRUCTDAT *st; LIBDAT *lib; // 第1パラメータ:新しいインターフェースポインタを格納する変数 aptrNew = code_getva( &pvalNew ); // 第2パラメータ:既存のCOMオブジェクト aptr = code_getva( &pval ); if ( pval->flag != TYPE_COMOBJ ) throw ( HSPERR_TYPE_MISMATCH ); ppunkSrc = (IUnknown **)HspVarCorePtrAPTR( pval, aptr ); if ( ! IsVaridComPtr(ppunkSrc) ) throw ( HSPERR_COMDLL_ERROR ); // IID 情報を取得 if ( *type == TYPE_DLLCTRL ) { // 第3パラメータ:#usecom 登録情報 st = code_getcomst(); if ( st->otindex != -1 ) throw ( HSPERR_TYPE_MISMATCH ); lib = &hspctx->mem_linfo[ st->index ]; piid = (IID *)strp( lib->nameidx ); } else { // 第3パラメータ:文字列 IID GetIIDFromString( &iid, code_gets() ); piid = &iid; } if ( pvalNew->flag != TYPE_COMOBJ ) { // 代入により型変換 iptr = NULL; code_setva( pvalNew, aptrNew, TYPE_COMOBJ, &iptr ); } ppunkDst = (IUnknown **)HspVarCorePtrAPTR( pvalNew, aptrNew ); // query によりインスタンスを得る QueryComPtr( ppunkDst, *ppunkSrc, piid ); if ( IsVaridComPtr(ppunkSrc) ) hspctx->stat = 0; else hspctx->stat = 1; break; } #endif // HSP_COM_UNSUPPORTED case 0x02: // delcom #ifdef HSP_COM_UNSUPPORTED throw ( HSPERR_UNSUPPORTED_FUNCTION ); #else { PVal *pval; APTR aptr; IUnknown **ppunk; VARIANT *var; void *ptr; // 第1パラメータ:解放するCOMオブジェクト変数 aptr = code_getva( &pval ); ptr = HspVarCorePtrAPTR( pval, aptr ); switch ( pval->flag ) { case TYPE_COMOBJ: ppunk = (IUnknown **)ptr; ReleaseComPtr( ppunk ); break; case TYPE_VARIANT: var = (VARIANT *)ptr; VariantClear( var ); break; default: throw HSPERR_TYPE_MISMATCH; } // このタイミングで一時オブジェクトも削除しちゃう if ( comconv_var.vt != VT_EMPTY ) VariantClear( &comconv_var ); break; } #endif // HSP_COM_UNSUPPORTED case 0x03: // cnvstow { PVal *pval; char *ptr; char *ps; int size; ptr = code_getvptr( &pval, &size ); ps = code_gets(); cnvwstr( ptr, ps, size/2 ); break; } case 0x04: // comres #ifdef HSP_COM_UNSUPPORTED throw ( HSPERR_UNSUPPORTED_FUNCTION ); #else if ( code_getexflg() ) { comres_pval = NULL; comres_aptr = 0; } else { comres_aptr = code_getva( &comres_pval ); } break; #endif // HSP_COM_UNSUPPORTED case 0x05: // axobj #ifdef HSP_COM_UNSUPPORTED throw ( HSPERR_UNSUPPORTED_FUNCTION ); #else { PVal *pval; APTR aptr; const IID *piid; void *iptr; BMSCR *bm; HWND hwnd; int id,sx,sy; char clsid_name[1024]; IUnknown **ppunk, *punkObj, *punkObj2; STRUCTDAT *st; LIBDAT *lib; HRESULT hr; bm = GetBMSCR(); // 第1パラメータ:新しいインターフェースポインタを格納する変数 // (あらかじめ変数にNULLを格納) aptr = code_getva( &pval ); iptr = NULL; code_setva( pval, aptr, TYPE_COMOBJ, &iptr ); ppunk = (IUnknown **)HspVarCorePtrAPTR( pval, aptr ); // オブジェクトの CLSID, ProgID, etc. if ( *type == TYPE_DLLCTRL ) { // 第2パラメータ:#usecom 登録情報から取得 st = code_getcomst(); if ( st->otindex != -1 ) throw ( HSPERR_TYPE_MISMATCH ); lib = &hspctx->mem_linfo[ st->index ]; piid = (IID *)strp( lib->nameidx ); if ( lib->clsid == -1 ) throw ( HSPERR_INVALID_PARAMETER ); strncpy( clsid_name, strp(lib->clsid), sizeof(clsid_name)-1 ); } else { // 第2パラメータ:文字列 CLSID or ProgID を取得 (IID は IDispatch) piid = &IID_IDispatch; strncpy( clsid_name, code_gets(), sizeof(clsid_name)-1 ); } // コントロールのサイズ sx = code_getdi( bm->sx ); sy = code_getdi( bm->sy ); // ActiveXとしてロード // if ( fn_atxinit == NULL ) throw ( HSPERR_UNSUPPORTED_FUNCTION ); hwnd = CreateWindow( atxwndclass, clsid_name, WS_CHILD, // 最初は WS_VISIBLE なし (後で ShowWindow() ) bm->cx, bm->cy, sx, sy, bm->hwnd, (HMENU)0, (HINSTANCE)hspctx->instance, NULL ); punkObj2 = NULL; if ( hwnd ) { punkObj = NULL; fn_atxgetctrl( hwnd, (void**)&punkObj ); if ( punkObj ) { // 指定 IID が存在するかどうか hr = punkObj->QueryInterface( *piid, (void**)&punkObj2 ); punkObj->Release(); } } if ( punkObj2 == NULL ) { // 目的オブジェクトではないときコントロールを削除 if (hwnd) { DestroyWindow( hwnd ); } hspctx->stat = -1; break; } // COM 型変数に格納 *ppunk = punkObj2; // HSPのウインドゥオブジェクトとして登録する ShowWindow( hwnd, SW_SHOW ); id = AddHSPObject( hwnd, HSPOBJ_TAB_SKIP, sy ); #ifdef HSP_COMOBJ_DEBUG Alertf( "axobj : pObj=%p : &pObj=%p\n", *ppunk, ppunk); #endif break; } #endif // HSP_COM_UNSUPPORTED case 0x06: // winobj { #ifdef HSPDISH throw ( HSPERR_UNSUPPORTED_FUNCTION ); #else char clsname[1024]; char winname[1024]; HWND hwnd; char *ps; BMSCR *bm; int i; int prm[6]; ps = code_gets(); strncpy( clsname, ps, 1023 ); ps = code_gets(); strncpy( winname, ps, 1023 ); bm = GetBMSCR(); for(i=0;i<6;i++) { prm[i] = code_getdi(0); } if ( prm[2] <= 0 ) prm[2] = bm->ox; if ( prm[3] <= 0 ) prm[3] = bm->oy; hwnd = CreateWindowEx( (DWORD) prm[0], // 拡張ウィンドウスタイル clsname, // ウィンドウクラス名 winname, // ウィンドウ名 (DWORD) prm[1], // ウィンドウスタイル bm->cx, bm->cy, prm[2], prm[3], // X,Y,SIZEX,SIZEY bm->hwnd, // 親ウィンドウのハンドル (HMENU) prm[4], // メニューハンドルまたは子ウィンドウID bm->hInst, // インスタンスハンドル (PVOID) prm[5] // ウィンドウ作成データ ); // AddHSPObject( hwnd, HSPOBJ_TAB_SKIP, prm[3], NULL, 0 ); // HSPのウインドゥオブジェクトとして登録する AddHSPObject( hwnd, HSPOBJ_TAB_SKIP, prm[3] ); break; #endif // HSPDISH } case 0x07: // sendmsg { int hw,p1,p2,p3,p4,fl,sz; char *vptr; hw = code_getdi(0); p1 = code_getdi(0); vptr = code_getsptr( &fl ); if ( fl == TYPE_STRING ) { p2 = (int)code_stmpstr( vptr ); } else { p2 = *(int *)vptr; } vptr = code_getsptr( &fl ); if ( fl == TYPE_STRING ) { p3 = (int)vptr; } else { p3 = *(int *)vptr; } //Alertf( "SEND[%x][%x][%x]",p1,p2,p3 ); hspctx->stat = (int)SendMessage( (HWND)hw, p1, p2, p3 ); break; } case 0x08: // comevent #ifdef HSP_COM_UNSUPPORTED throw ( HSPERR_UNSUPPORTED_FUNCTION ); #else { PVal *pval; APTR aptr; void* iptr; char *ps; IID iid, *piid; unsigned short *subr; IUnknown **ppunk, **ppunkEvent; // 第1パラメータ:イベントハンドラオブジェクト (IEventHandler) を格納する変数 // (あらかじめ NULL で初期化) aptr = code_getva( &pval ); iptr = NULL; code_setva( pval, aptr, TYPE_COMOBJ, &iptr ); ppunkEvent = (IUnknown **)HspVarCorePtrAPTR( pval, aptr ); // 第2パラメータ:COMオブジェクトを格納した変数 aptr = code_getva( &pval ); if ( pval->flag != TYPE_COMOBJ ) throw ( HSPERR_TYPE_MISMATCH ); ppunk = (IUnknown **)HspVarCorePtrAPTR( pval, aptr ); if ( ! IsVaridComPtr(ppunk) ) throw ( HSPERR_COMDLL_ERROR ); // 第3パラメータ:コネクションポイントIID (文字列形式) ps = code_getds(""); if ( ps[0] != '\0' ) { piid = &iid; GetIIDFromString( piid, ps ); } else { piid = NULL; // NULL のときデフォルトIID が自動的に取得される } // 第4パラメータ:コールバック用のサブルーチンラベル subr = code_getlb2(); // イベントハンドラ作成・接続 SetComEvent( ppunkEvent, ppunk, piid, subr ); #ifdef HSP_COMOBJ_DEBUG COM_DBG_MSG( "comevent : pEvent=%p : pObj=%p\n", *ppunkEvent, *ppunk); #endif break; } #endif // HSP_COM_UNSUPPORTED case 0x09: // comevarg #ifdef HSP_COM_UNSUPPORTED throw ( HSPERR_UNSUPPORTED_FUNCTION ); #else { PVal *pval, *pval2; APTR aptr, aptr2; VARIANT *v; void *ptr; int p1,p2; int res; IUnknown **ppunk; VARIANT varTemp; // 第1パラメータ:イベントのパラメータを格納する変数 aptr = code_getva( &pval ); // 第2パラメータ:イベントハンドラオブジェクト変数 aptr2 = code_getva( &pval2 ); if ( pval2->flag != TYPE_COMOBJ ) throw ( HSPERR_TYPE_MISMATCH ); ppunk = (IUnknown **)HspVarCorePtrAPTR( pval2, aptr2 ); if ( ! IsVaridComPtr(ppunk) ) throw ( HSPERR_COMDLL_ERROR ); // 第3パラメータ:パラメータインデックス p1 = code_getdi(0); // 第4パラメータ:文字列変換フラグ p2 = code_getdi(0); // イベントのパラメータ取得 v = GetEventArg( *ppunk, p1 ); if ( v == NULL ) throw ( HSPERR_ILLEGAL_FUNCTION ); switch ( p2 ) { case 0: VariantInit( &varTemp ); VariantCopyInd( &varTemp, v ); ptr = comget_variant( &varTemp, &res ); VariantClear( &varTemp ); break; case 1: VariantInit( &varTemp ); if FAILED( VariantChangeType( &varTemp, v, VARIANT_ALPHABOOL, VT_BSTR ) ) throw ( HSPERR_TYPE_INITALIZATION_FAILED ); ptr = comget_variant( &varTemp, &res ); VariantClear( &varTemp ); break; case 2: ptr = v; res = HSPVAR_FLAG_VARIANT; break; default: throw ( HSPERR_ILLEGAL_FUNCTION ); } code_setva( pval, aptr, res, ptr ); hspctx->stat = res; break; } #endif // HSP_COM_UNSUPPORTED case 0x0a: // sarrayconv #ifdef HSP_COM_UNSUPPORTED throw ( HSPERR_UNSUPPORTED_FUNCTION ); #else { PVal *pval1, *pval2; APTR aptr1, aptr2; int convdir, size; VARIANT *variant, varTemp; VARTYPE vt; SAFEARRAY *psa; long lbound, ubound; HRESULT hr; aptr1 = code_getva( &pval1 ); aptr2 = code_getva( &pval2 ); convdir = code_getdi(0); size = code_getdi(0); switch ( convdir ) { case 0: case 2: case 4: // 配列変数から SafeArray に変換 VariantInit( &varTemp ); code_setva( pval1, aptr1, HSPVAR_FLAG_VARIANT, &varTemp ); variant = (VARIANT *)HspVarCorePtrAPTR( pval1, aptr1 ); VariantClear( variant ); // 一応 if ( convdir == 2 ) { // バイナリデータ(一次元のみ) void *ptr = HspVarCorePtrAPTR( pval2, aptr2 ); psa = CreateBinarySafeArray( ptr, size, &vt ); } else { BOOL bVariant = ( convdir == 4 ); psa = ConvVar2SafeArray( pval2, bVariant, &vt ); } variant->vt = vt | VT_ARRAY; variant->parray = psa; break; case 1: case 3: // SafeArray から配列変数に変換 if ( pval2->flag != HSPVAR_FLAG_VARIANT ) throw HSPERR_INVALID_TYPE; variant = (VARIANT *)HspVarCorePtrAPTR( pval2, aptr2 ); if ( (variant->vt & VT_ARRAY) == 0 ) throw HSPERR_INVALID_TYPE; psa = variant->parray; if ( psa == NULL ) throw HSPERR_ARRAY_OVERFLOW; vt = variant->vt & VT_TYPEMASK; if ( vt == VT_EMPTY ) { hr = SafeArrayGetVartype( psa, &vt ); if ( FAILED(hr) || vt == VT_EMPTY ) throw HSPERR_INVALID_ARRAYSTORE; } if ( convdir == 1 ) { ConvSafeArray2Var( pval1, psa, vt ); } else { // バイナリデータ(一次元のみ) int varsize; void *ptr = HspVarCorePtrAPTR( pval1, aptr1 ); if ( vt != VT_UI1 && vt != VT_I1 ) throw HSPERR_INVALID_TYPE; SafeArrayGetLBound( psa, 1, &lbound ); hr = SafeArrayGetUBound( psa, 1, &ubound ); if ( FAILED(hr) ) throw HSPERR_ARRAY_OVERFLOW; size = ubound - lbound + 1; HspVarCoreGetBlockSize( pval1, (PDAT*)ptr, &varsize ); if ( varsize < size ) throw HSPERR_BUFFER_OVERFLOW; GetBinarySafeArray( ptr, size, psa ); } break; default: throw ( HSPERR_UNSUPPORTED_FUNCTION ); } break; } #endif // HSP_COM_UNSUPPORTED default: throw ( HSPERR_SYNTAX ); } return RUNMODE_RUN; }
static int cmdfunc_intcmd( int cmd ) { // cmdfunc : TYPE_INTCMD // (内蔵コマンド) // int p1,p2,p3; // code_next(); // 次のコードを取得(最初に必ず必要です) switch( cmd ) { // サブコマンドごとの分岐 case 0x00: // onexit case 0x01: // onerror case 0x02: // onkey case 0x03: // onclick case 0x04: // oncmd { /* rev 45 不具合 : (onxxx系命令) (ラベル型変数) 形式の書式でエラー に対処 */ int tval = *type; int opt = IRQ_OPT_GOTO; int cust; int actid; IRQDAT *irq; unsigned short *sbr; if ( tval == TYPE_VAR ) { if ( ( ctx->mem_var + *val )->flag == HSPVAR_FLAG_LABEL ) tval = TYPE_LABEL; } if (( tval != TYPE_PROGCMD )&&( tval != TYPE_LABEL )) { // ON/OFF切り替え int i = code_geti(); code_enableirq( cmd, i ); break; } if ( tval == TYPE_PROGCMD ) { // ジャンプ方法指定 opt = *val; if ( opt >= 2 ) throw HSPERR_SYNTAX; code_next(); } sbr = code_getlb2(); if ( cmd != 0x04 ) { code_setirq( cmd, opt, -1, sbr ); break; } cust = code_geti(); actid = *(exinfo->actscr); irq = code_seekirq( actid, cust ); if ( irq == NULL ) irq = code_addirq(); irq->flag = IRQ_FLAG_ENABLE; irq->opt = opt; irq->ptr = sbr; irq->custom = cust; irq->custom2 = actid; break; } case 0x11: // exist case 0x12: // delete case 0x13: // mkdir case 0x14: // chdir code_event( HSPEVENT_FNAME, 0, 0, code_gets() ); code_event( HSPEVENT_FEXIST + (cmd - 0x11), 0, 0, NULL ); break; case 0x15: // dirlist { PVal *pval; APTR aptr; char *ptr; aptr = code_getva( &pval ); code_event( HSPEVENT_FNAME, 0, 0, code_gets() ); p1=code_getdi(0); code_event( HSPEVENT_FDIRLIST1, p1, 0, &ptr ); code_setva( pval, aptr, TYPE_STRING, ptr ); code_event( HSPEVENT_FDIRLIST2, 0, 0, NULL ); break; } case 0x16: // bload case 0x17: // bsave { PVal *pval; char *ptr; int size; int tmpsize; code_event( HSPEVENT_FNAME, 0, 0, code_gets() ); ptr = code_getvptr( &pval, &size ); p1 = code_getdi( -1 ); p2 = code_getdi( -1 ); if (( p1 < 0 )||( p1 > size )) p1 = size; if ( cmd == 0x16 ) { tmpsize = p2;if ( tmpsize<0 ) tmpsize = 0; code_event( HSPEVENT_FREAD, tmpsize, p1, ptr ); } else { code_event( HSPEVENT_FWRITE, p2, p1, ptr ); } break; } case 0x18: // bcopy code_event( HSPEVENT_FNAME, 0, 0, code_gets() ); code_event( HSPEVENT_FCOPY, 0, 0, code_gets() ); break; case 0x19: // memfile { PVal *pval; char *ptr; int size; ptr = code_getvptr( &pval, &size ); p1=code_getdi( 0 ); p2=code_getdi( 0 ); if ( p2==0 ) p2 = size - p1; dpm_memfile( ptr+p1, p2 ); break; } case 0x1a: // poke case 0x1b: // wpoke case 0x1c: // lpoke { PVal *pval; char *ptr; int size; int fl; int len; char *bp; ptr = code_getvptr( &pval, &size ); p1 = code_getdi( 0 ); if ( p1<0 ) throw HSPERR_BUFFER_OVERFLOW; ptr += p1; if ( code_get() <= PARAM_END ) { fl = HSPVAR_FLAG_INT; bp = (char *)&p2; p2 = 0; } else { fl = mpval->flag; bp = mpval->pt; } if ( cmd == 0x1a ) { switch( fl ) { case HSPVAR_FLAG_INT: if ( p1 >= size ) throw HSPERR_BUFFER_OVERFLOW; *ptr = *bp; break; case HSPVAR_FLAG_STR: len = (int)strlen( bp ); ctx->strsize = len; len++; if ( (p1+len)>size ) throw HSPERR_BUFFER_OVERFLOW; strcpy( ptr, bp ); break; default: throw HSPERR_TYPE_MISMATCH; } break; } if ( fl != HSPVAR_FLAG_INT ) throw HSPERR_TYPE_MISMATCH; if ( cmd == 0x1b ) { if ( (p1+2)>size ) throw HSPERR_BUFFER_OVERFLOW; *(short *)ptr = (short)(*(short *)bp); } else { if ( (p1+4)>size ) throw HSPERR_BUFFER_OVERFLOW; *(int *)ptr = (*(int *)bp); } break; } case 0x1d: // getstr { PVal *pval2; PVal *pval; APTR aptr; char *ptr; char *p; int size; aptr = code_getva( &pval ); ptr = code_getvptr( &pval2, &size ); p1 = code_getdi( 0 ); p2 = code_getdi( 0 ); p3 = code_getdi( 1024 ); if ( p1 >= size ) throw HSPERR_BUFFER_OVERFLOW; ptr += p1; p = code_stmp( p3 + 1 ); strsp_ini(); ctx->stat = strsp_get( ptr, p, p2, p3 ); ctx->strsize = strsp_getptr(); code_setva( pval, aptr, HSPVAR_FLAG_STR, p ); break; } case 0x1e: // chdpm code_event( HSPEVENT_FNAME, 0, 0, code_gets() ); p1 = code_getdi( -1 ); dpm_bye(); p2 = dpm_ini( ctx->fnbuffer, 0, -1, p1 ); if ( p2 ) throw HSPERR_FILE_IO; #ifndef HSP3IMP #ifdef HSPWIN Sleep( 1000 ); #endif #endif break; case 0x1f: // memexpand { PVal *pval; APTR aptr; PDAT *ptr; aptr = code_getva( &pval ); ptr = HspVarCorePtrAPTR( pval, aptr ); if (( pval->support & HSPVAR_SUPPORT_FLEXSTORAGE ) == 0 ) throw HSPERR_TYPE_MISMATCH; p1 = code_getdi( 0 ); if ( p1 < 64 ) p1 = 64; HspVarCoreAllocBlock( pval, ptr, p1 ); break; } case 0x20: // memcpy { PVal *pval; char *sptr; char *tptr; int bufsize_t,bufsize_s; tptr = code_getvptr( &pval, &bufsize_t ); sptr = code_getvptr( &pval, &bufsize_s ); p1 = code_getdi( 0 ); p2 = code_getdi( 0 ); p3 = code_getdi( 0 ); if( p2 < 0 || p3 < 0 ) throw HSPERR_BUFFER_OVERFLOW; tptr += p2; sptr += p3; if ( (p1+p2)>bufsize_t ) throw HSPERR_BUFFER_OVERFLOW; if ( (p1+p3)>bufsize_s ) throw HSPERR_BUFFER_OVERFLOW; if ( p1>0 ) { memmove( tptr, sptr, p1 ); } break; } case 0x21: // memset { PVal *pval; char *ptr; int size; ptr = code_getvptr( &pval, &size ); p1 = code_getdi( 0 ); p2 = code_getdi( 0 ); p3 = code_getdi( 0 ); if ( p3 < 0 ) throw HSPERR_BUFFER_OVERFLOW; ptr += p3; if ( (p3+p2)>size ) throw HSPERR_BUFFER_OVERFLOW; if ( p2>0 ) { memset( ptr, p1, p2 ); } break; } case 0x22: // notesel ctx->notep_aptr = ctx->note_aptr; ctx->notep_pval = ctx->note_pval; ctx->note_aptr = code_getva( &ctx->note_pval ); if ( ctx->note_pval->flag != HSPVAR_FLAG_STR ) { code_setva( ctx->note_pval, ctx->note_aptr, TYPE_STRING, "" ); } break; case 0x23: // noteadd { char *np; char *ps; char *tmp; int size; np = note_update(); ps = code_gets(); size = (int)strlen( ps ) + 8; HspVarCoreAllocBlock( ctx->note_pval, (PDAT *)np, (int)strlen(np) + size ); tmp = sbAlloc( size ); strcpy( tmp, ps ); p1 = code_getdi( -1 ); p2 = code_getdi( 0 ); np = note_update(); note.PutLine( tmp, p1, p2 ); sbFree( tmp ); break; } case 0x24: // notedel p1 = code_getdi( 0 ); note_update(); note.PutLine( NULL, p1, 1 ); break; case 0x25: // noteload { int size; char *ptr; char *pdat; code_event( HSPEVENT_FNAME, 0, 0, code_gets() ); p1 = code_getdi( -1 ); code_event( HSPEVENT_FEXIST, 0, 0, NULL ); size = ctx->strsize; if ( size < 0 ) throw HSPERR_FILE_IO; if ( p1>=0 ) if ( size >= p1 ) { ctx->strsize = size = p1; } pdat = note_update(); HspVarCoreAllocBlock( ctx->note_pval, (PDAT *)pdat, size+1 ); ptr = (char *)note_update(); code_event( HSPEVENT_FREAD, 0, size, ptr ); ptr[size] = 0; break; } case 0x26: // notesave { char *pdat; int size; code_event( HSPEVENT_FNAME, 0, 0, code_gets() ); pdat = note_update(); size = (int)strlen( pdat ); code_event( HSPEVENT_FWRITE, -1, size, pdat ); break; } case 0x27: // randomize #ifdef HSPWIN p2 = (int)GetTickCount(); // Windowsの場合はtickをシード値とする #else p2 = (int)time(0); // Windows以外のランダムシード値 #endif p1 = code_getdi( p2 ); srand( p1 ); break; case 0x28: // noteunsel ctx->note_aptr = ctx->notep_aptr; ctx->note_pval = ctx->notep_pval; break; case 0x29: // noteget { PVal *pval; APTR aptr; char *p; note_update(); aptr = code_getva( &pval ); p1 = code_getdi( 0 ); p = note.GetLineDirect( p1 ); code_setva( pval, aptr, TYPE_STRING, p ); note.ResumeLineDirect(); break; } case 0x2a: // split { // 指定した文字列で分割された要素を代入する(fujidig) PVal *pval = NULL; int aptr = 0; char *sptr; char *sep; char *newsptr; int size; int sep_len; int n = 0; int is_last = 0; sptr = code_getvptr( &pval, &size ); if ( pval->flag != HSPVAR_FLAG_STR ) throw HSPERR_TYPE_MISMATCH; sep = code_gets(); sep_len = (int)strlen( sep ); while (1) { newsptr = strstr2( sptr, sep ); if ( !is_last && *exinfo->npexflg & EXFLG_1 ) { // 分割結果の数が格納する変数より多ければ最後の変数に配列で格納していく // ただし最後の要素が a.2 のように要素指定があればそれ以降は全く格納しない if ( aptr != 0 ) pval = NULL; is_last = 1; aptr = 0; } if ( is_last ) { aptr ++; if ( pval != NULL && aptr >= pval->len[1] ) { if ( pval->len[2] != 0 ) throw HSPVAR_ERROR_ARRAYOVER; HspVarCoreReDim( pval, 1, aptr+1 ); } } else { aptr = code_getva( &pval ); } if ( pval != NULL ) { if ( newsptr == NULL ) { code_setva( pval, aptr, HSPVAR_FLAG_STR, sptr ); } else { var_set_str_len( pval, aptr, sptr, (int)(newsptr - sptr) ); } } n ++; if ( newsptr == NULL ) { // 格納する変数の数が分割できた数より多ければ残った変数それぞれに空文字列を格納する while( ( *exinfo->npexflg & EXFLG_1 ) == 0 ) { aptr = code_getva( &pval ); code_setva( pval, aptr, HSPVAR_FLAG_STR, "" ); } break; } sptr = newsptr + sep_len; } ctx->stat = n; break; } default: throw HSPERR_UNSUPPORTED_FUNCTION; } return RUNMODE_RUN; }
void genDwarfEh(Funcsym *sfunc, int seg, Outbuffer *et, bool scancode, unsigned startoffset, unsigned retoffset) { #ifdef DEBUG unittest_dwarfeh(); #endif /* LPstart = encoding of LPbase * LPbase = landing pad base (normally omitted) * TType = encoding of TTbase * TTbase = offset from next byte to past end of Type Table * CallSiteFormat = encoding of fields in Call Site Table * CallSiteTableSize = size in bytes of Call Site Table * Call Site Table[]: * CallSiteStart * CallSiteRange * LandingPad * ActionRecordPtr * Action Table * TypeFilter * NextRecordPtr * Type Table */ et->reserve(100); block *startblock = sfunc->Sfunc->Fstartblock; //printf("genDwarfEh: func = %s, offset = x%x, startblock->Boffset = x%x, scancode = %d startoffset=x%x, retoffset=x%x\n", //sfunc->Sident, (int)sfunc->Soffset, (int)startblock->Boffset, scancode, startoffset, retoffset); #if 0 printf("------- before ----------\n"); for (block *b = startblock; b; b = b->Bnext) WRblock(b); printf("-------------------------\n"); #endif unsigned startsize = et->size(); assert((startsize & 3) == 0); // should be aligned DwEhTable *deh = &dwehtable; deh->dim = 0; Outbuffer atbuf; Outbuffer cstbuf; /* Build deh table, and Action Table */ int index = -1; block *bprev = NULL; // The first entry encompasses the entire function { unsigned i = deh->push(); DwEhTableEntry *d = deh->index(i); d->start = startblock->Boffset + startoffset; d->end = startblock->Boffset + retoffset; d->lpad = 0; // no cleanup, no catches index = i; } for (block *b = startblock; b; b = b->Bnext) { if (index > 0 && b->Btry == bprev) { DwEhTableEntry *d = deh->index(index); d->end = b->Boffset; index = d->prev; if (bprev) bprev = bprev->Btry; } if (b->BC == BC_try) { unsigned i = deh->push(); DwEhTableEntry *d = deh->index(i); d->start = b->Boffset; block *bf = b->nthSucc(1); if (bf->BC == BCjcatch) { d->lpad = bf->Boffset; d->bcatch = bf; unsigned *pat = bf->BS.BIJCATCH.actionTable; unsigned length = pat[0]; assert(length); unsigned offset = -1; for (unsigned u = length; u; --u) { /* Buy doing depth-first insertion into the Action Table, * we can combine common tails. */ offset = actionTableInsert(&atbuf, pat[u], offset); } d->action = offset + 1; } else d->lpad = bf->nthSucc(0)->Boffset; d->prev = index; index = i; bprev = b->Btry; } if (scancode) { unsigned coffset = b->Boffset; int n = 0; for (code *c = b->Bcode; c; c = code_next(c)) { if (c->Iop == (ESCAPE | ESCdctor)) { unsigned i = deh->push(); DwEhTableEntry *d = deh->index(i); d->start = coffset; d->prev = index; index = i; ++n; } if (c->Iop == (ESCAPE | ESCddtor)) { assert(n > 0); --n; DwEhTableEntry *d = deh->index(index); d->end = coffset; d->lpad = coffset; index = d->prev; } coffset += calccodsize(c); } assert(n == 0); } } //printf("deh->dim = %d\n", (int)deh->dim); #if 1 /* Build Call Site Table * Be sure to not generate empty entries, * and generate nested ranges reflecting the layout in the code. */ assert(deh->dim); unsigned end = deh->index(0)->start; for (unsigned i = 0; i < deh->dim; ++i) { DwEhTableEntry *d = deh->index(i); if (d->start < d->end) { #if ELFOBJ #define WRITE writeuLEB128 #elif MACHOBJ #define WRITE write32 #else assert(0); #endif unsigned CallSiteStart = d->start - startblock->Boffset; cstbuf.WRITE(CallSiteStart); unsigned CallSiteRange = d->end - d->start; cstbuf.WRITE(CallSiteRange); unsigned LandingPad = d->lpad ? d->lpad - startblock->Boffset : 0; cstbuf.WRITE(LandingPad); unsigned ActionTable = d->action; cstbuf.writeuLEB128(ActionTable); //printf("\t%x %x %x %x\n", CallSiteStart, CallSiteRange, LandingPad, ActionTable); #undef WRITE } } #else /* Build Call Site Table * Be sure to not generate empty entries, * and generate multiple entries for one DwEhTableEntry if the latter * is split by nested DwEhTableEntry's. This is based on the (undocumented) * presumption that there may not * be overlapping entries in the Call Site Table. */ assert(deh->dim); unsigned end = deh->index(0)->start; for (unsigned i = 0; i < deh->dim; ++i) { unsigned j = i; do { DwEhTableEntry *d = deh->index(j); //printf(" [%d] start=%x end=%x lpad=%x action=%x bcatch=%p prev=%d\n", // j, d->start, d->end, d->lpad, d->action, d->bcatch, d->prev); if (d->start <= end && end < d->end) { unsigned start = end; unsigned dend = d->end; if (i + 1 < deh->dim) { DwEhTableEntry *dnext = deh->index(i + 1); if (dnext->start < dend) dend = dnext->start; } if (start < dend) { #if ELFOBJ #define WRITE writeLEB128 #elif MACHOBJ #define WRITE write32 #else assert(0); #endif unsigned CallSiteStart = start - startblock->Boffset; cstbuf.WRITE(CallSiteStart); unsigned CallSiteRange = dend - start; cstbuf.WRITE(CallSiteRange); unsigned LandingPad = d->lpad - startblock->Boffset; cstbuf.WRITE(LandingPad); unsigned ActionTable = d->action; cstbuf.WRITE(ActionTable); //printf("\t%x %x %x %x\n", CallSiteStart, CallSiteRange, LandingPad, ActionTable); #undef WRITE } end = dend; } } while (j--); } #endif /* Write LSDT header */ const unsigned char LPstart = DW_EH_PE_omit; et->writeByte(LPstart); unsigned LPbase = 0; if (LPstart != DW_EH_PE_omit) et->writeuLEB128(LPbase); const unsigned char TType = (config.flags3 & CFG3pic) ? DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4 : DW_EH_PE_absptr | DW_EH_PE_udata4; et->writeByte(TType); /* Compute TTbase, which is the sum of: * 1. CallSiteFormat * 2. encoding of CallSiteTableSize * 3. Call Site Table size * 4. Action Table size * 5. 4 byte alignment * 6. Types Table * Iterate until it converges. */ unsigned TTbase = 1; unsigned CallSiteTableSize = cstbuf.size(); unsigned oldTTbase; do { oldTTbase = TTbase; unsigned start = (et->size() - startsize) + uLEB128size(TTbase); TTbase = 1 + uLEB128size(CallSiteTableSize) + CallSiteTableSize + atbuf.size(); unsigned sz = start + TTbase; TTbase += -sz & 3; // align to 4 TTbase += sfunc->Sfunc->typesTableDim * 4; } while (TTbase != oldTTbase); if (TType != DW_EH_PE_omit) et->writeuLEB128(TTbase); unsigned TToffset = TTbase + et->size() - startsize; #if ELFOBJ const unsigned char CallSiteFormat = DW_EH_PE_absptr | DW_EH_PE_uleb128; #elif MACHOBJ const unsigned char CallSiteFormat = DW_EH_PE_absptr | DW_EH_PE_udata4; #else assert(0); #endif et->writeByte(CallSiteFormat); et->writeuLEB128(CallSiteTableSize); /* Insert Call Site Table */ et->write(&cstbuf); /* Insert Action Table */ et->write(&atbuf); /* Align to 4 */ for (unsigned n = (-et->size() & 3); n; --n) et->writeByte(0); /* Write out Types Table in reverse */ Symbol **typesTable = sfunc->Sfunc->typesTable; for (int i = sfunc->Sfunc->typesTableDim; i--; ) { Symbol *s = typesTable[i]; /* MACHOBJ 64: pcrel 1 length 1 extern 1 RELOC_GOT * 32: [0] address x004c pcrel 0 length 2 value x224 type 4 RELOC_LOCAL_SECTDIFF * [1] address x0000 pcrel 0 length 2 value x160 type 1 RELOC_PAIR */ dwarf_reftoident(seg, et->size(), s, 0); } assert(TToffset == et->size() - startsize); }