Index: function.c ================================================================== --- function.c +++ function.c @@ -1,7 +1,7 @@ #if 0 -gcc ${CFLAGS:--s -O2} -c function.c `sdl-config --cflags` +gcc ${CFLAGS:--s -O2} -c -fplan9-extensions function.c `sdl-config --cflags` exit #endif #include "SDL.h" #include @@ -8,10 +8,16 @@ #include #include #include "sqlite3.h" #include "smallxrm.h" #include "heromesh.h" + +typedef struct { + struct sqlite3_vtab_cursor; + sqlite3_int64 rowid; + char unique,eof; +} Cursor; static void fn_basename(sqlite3_context*cxt,int argc,sqlite3_value**argv) { sqlite3_result_text(cxt,basefilename,-1,SQLITE_STATIC); } @@ -41,15 +47,149 @@ sqlite3_int64 a; if(sqlite3_value_type(*argv)==SQLITE_NULL) return; a=sqlite3_value_int64(*argv)&0xFFFFFFFF; sqlite3_result_int64(cxt,a-(a&0x80000000?0x100000000LL:0)); } + +static int vt0_close(sqlite3_vtab_cursor*cur) { + sqlite3_free(cur); + return SQLITE_OK; +} + +static int vt0_connect(sqlite3*db,void*aux,int argc,const char*const*argv,sqlite3_vtab**vt,char**err) { + sqlite3_declare_vtab(db,aux); + *vt=sqlite3_malloc(sizeof(sqlite3_vtab)); + return *vt?SQLITE_OK:SQLITE_NOMEM; +} + +static int vt0_disconnect(sqlite3_vtab*vt) { + sqlite3_free(vt); + return SQLITE_OK; +} + +static int vt0_eof(sqlite3_vtab_cursor*pcur) { + Cursor*cur=(void*)pcur; + return cur->eof; +} + +static int vt0_index(sqlite3_vtab*vt,sqlite3_index_info*info) { + int i; + if(info->nOrderBy==1 && info->aOrderBy->iColumn==-1 && !info->aOrderBy->desc) info->orderByConsumed=1; + for(i=0;inConstraint;i++) { + if(info->aConstraint[i].iColumn==-1 && info->aConstraint[i].op==SQLITE_INDEX_CONSTRAINT_EQ && info->aConstraint[i].usable) { + info->aConstraintUsage[i].argvIndex=1; + info->aConstraintUsage[i].omit=1; + info->idxFlags=SQLITE_INDEX_SCAN_UNIQUE; + break; + } + } + return SQLITE_OK; +} + +static int vt0_open(sqlite3_vtab*vt,sqlite3_vtab_cursor**cur) { + *cur=sqlite3_malloc(sizeof(Cursor)); + return *cur?SQLITE_OK:SQLITE_NOMEM; +} + +static int vt0_rename(sqlite3_vtab*vt,const char*z) { + return SQLITE_ERROR; +} + +static int vt0_rowid(sqlite3_vtab_cursor*pcur,sqlite3_int64*rowid) { + Cursor*cur=(void*)pcur; + *rowid=cur->rowid; + return SQLITE_OK; +} + +#define Module(a,...) static const sqlite3_module a={ \ + .xBestIndex=vt0_index, .xClose=vt0_close, .xConnect=vt0_connect, .xDisconnect=vt0_disconnect, \ + .xEof=vt0_eof, .xOpen=vt0_open, .xRename=vt0_rename, .xRowid=vt0_rowid, __VA_ARGS__ }; + +static int vt1_messages_column(sqlite3_vtab_cursor*pcur,sqlite3_context*cxt,int n) { + Cursor*cur=(void*)pcur; + switch(n) { + case 0: // ID + sqlite3_result_int64(cxt,cur->rowid); + break; + case 1: // NAME + if(sqlite3_vtab_nochange(cxt)) return SQLITE_OK; + if(cur->rowid<256) sqlite3_result_text(cxt,standard_message_names[cur->rowid],-1,0); + else sqlite3_result_text(cxt,sqlite3_mprintf("#%s",messages[cur->rowid-256]),-1,sqlite3_free); + break; + case 2: // TRACE + if(cur->rowid>=0 && cur->rowid<0x4100) sqlite3_result_int(cxt,message_trace[cur->rowid>>3]&(1<<(cur->rowid&7))?1:0); + break; + } + return SQLITE_OK; +} + +static int vt1_messages_filter(sqlite3_vtab_cursor*pcur,int idxNum,const char*idxStr,int argc,sqlite3_value**argv) { + Cursor*cur=(void*)pcur; + if(argc) { + cur->rowid=sqlite3_value_int64(*argv); + cur->unique=1; + if(cur->rowid>=0x4100 || cur->rowid<0) cur->eof=1; + else if(cur->rowid>=N_MESSAGES || cur->rowid<256) cur->eof=1; + else cur->eof=messages[cur->rowid-256]?0:1; + } else { + cur->rowid=0; + cur->unique=0; + cur->eof=0; + } + return SQLITE_OK; +} + +static int vt1_messages_next(sqlite3_vtab_cursor*pcur) { + Cursor*cur=(void*)pcur; + if(cur->unique) { + cur->eof=1; + } else if(cur->rowid<256) { + ++cur->rowid; + if(cur->rowid==N_MESSAGES) { + cur->rowid=256; + if(!*messages) goto next_user_msg; + } + } else { + next_user_msg: + for(;;) { + if(++cur->rowid==0x4100) { + cur->eof=1; + break; + } + if(messages[cur->rowid-256]) break; + } + } + return SQLITE_OK; +} + +static int vt1_messages_update(sqlite3_vtab*vt,int argc,sqlite3_value**argv,sqlite3_int64*rowid) { + sqlite3_int64 id; + int v; + if(argc!=5 || sqlite3_value_type(*argv)!=SQLITE_INTEGER) return SQLITE_CONSTRAINT_VTAB; + id=sqlite3_value_int64(*argv); + if(id!=sqlite3_value_int64(argv[1])) return SQLITE_CONSTRAINT_VTAB; + if(sqlite3_value_type(argv[4])!=SQLITE_INTEGER) return SQLITE_MISMATCH; + v=sqlite3_value_int(argv[4]); + if(v&~1) return SQLITE_CONSTRAINT_CHECK; + if(id<0 || id>=0x4100) return SQLITE_INTERNAL; + if(v) message_trace[id>>3]|=1<<(id&7); + else message_trace[id>>3]&=~(1<<(id&7)); + return SQLITE_OK; +} + +Module(vt_messages, + .xColumn=vt1_messages_column, + .xFilter=vt1_messages_filter, + .xNext=vt1_messages_next, + .xUpdate=vt1_messages_update, +); void init_sql_functions(sqlite3_int64*ptr0,sqlite3_int64*ptr1) { sqlite3_create_function(userdb,"BASENAME",0,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_basename,0,0); sqlite3_create_function(userdb,"LEVEL_CACHEID",0,SQLITE_UTF8|SQLITE_DETERMINISTIC,ptr0,fn_cacheid,0,0); sqlite3_create_function(userdb,"MODSTATE",0,SQLITE_UTF8,0,fn_modstate,0,0); sqlite3_create_function(userdb,"PICTURE_SIZE",0,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_picture_size,0,0); sqlite3_create_function(userdb,"RESOURCE",-1,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_resource,0,0); sqlite3_create_function(userdb,"SIGN_EXTEND",1,SQLITE_UTF8|SQLITE_DETERMINISTIC,0,fn_sign_extend,0,0); sqlite3_create_function(userdb,"SOLUTION_CACHEID",0,SQLITE_UTF8|SQLITE_DETERMINISTIC,ptr1,fn_cacheid,0,0); + sqlite3_create_module(userdb,"MESSAGES",&vt_messages,"CREATE TABLE `MESSAGES`(`ID` INTEGER PRIMARY KEY, `NAME` TEXT, `TRACE` INT);"); } Index: heromesh.h ================================================================== --- heromesh.h +++ heromesh.h @@ -28,10 +28,11 @@ #define NVALUE(x) SVALUE(x,TY_NUMBER) #define CVALUE(x) UVALUE(x,TY_CLASS) #define MVALUE(x) UVALUE(x,TY_MESSAGE) #define ZVALUE(x) UVALUE(x,TY_STRING) +#define N_MESSAGES 23 extern const char*const standard_message_names[]; extern const char*const standard_sound_names[]; extern const char*const heromesh_key_names[256]; extern sqlite3*userdb; @@ -38,10 +39,11 @@ extern xrm_db*resourcedb; extern const char*basefilename; extern xrm_quark optionquery[16]; extern Uint32 generation_number; extern char main_options[128]; +extern Uint8 message_trace[0x4100/8]; unsigned char*read_lump(int sol,int lvl,long*sz,sqlite3_value**us); void write_lump(int sol,int lvl,long sz,const unsigned char*data); void set_cursor(int id); Index: main.c ================================================================== --- main.c +++ main.c @@ -41,10 +41,11 @@ xrm_db*resourcedb; const char*basefilename; xrm_quark optionquery[16]; Uint32 generation_number; char main_options[128]; +Uint8 message_trace[0x4100/8]; static const char*globalclassname; static SDL_Cursor*cursor[77]; static FILE*levelfp; static FILE*solutionfp;