Mercurial > otakunoraifu
diff scn2k/scn2k_cmd.cc @ 52:15a18fbe6f21
* Known bugs added to the README
* Code cleaning (0 -> NULL when needed, indentation, spaces, ...)
author | thib |
---|---|
date | Sat, 18 Apr 2009 18:35:39 +0000 |
parents | 5f548e5957a8 |
children | d7cde171a1de |
line wrap: on
line diff
--- a/scn2k/scn2k_cmd.cc +++ b/scn2k/scn2k_cmd.cc @@ -26,14 +26,14 @@ */ -#include"scn2k.h" +#include "scn2k.h" -#include<stdlib.h> -#include<stdarg.h> -#include<stdio.h> -#include<string.h> -#include<string> -#include"system/file.h" +#include <stdlib.h> +#include <stdarg.h> +#include <stdio.h> +#include <string.h> +#include <string> +#include "system/file.h" using namespace std; @@ -47,7 +47,8 @@ using namespace std; bool debug_flag = false; void dprintf(const char* fmt, ...) { if (debug_flag) { - va_list ap; va_start(ap, fmt); + va_list ap; + va_start(ap, fmt); vprintf(fmt, ap); va_end(ap); } @@ -162,40 +163,42 @@ void Flags::Set(VarInfo info, int value) void Flags::SetSys(int value) { sys = value; } + void Flags::SetStr(VarInfo info, string val) { switch(info.type) { - case TYPE_VARLOCSTR: - if (info.number >= 3) return; - loc_str[info.number] = val; - break; - case TYPE_VARSYSSTR: - if (info.number >= 2000) return; - sys_str[info.number] = val; - break; - case TYPE_VARSTR: - if (info.number >= 2000) return; - str[info.number] = val; - break; + case TYPE_VARLOCSTR: + if (info.number >= 3) return; + loc_str[info.number] = val; + break; + case TYPE_VARSYSSTR: + if (info.number >= 2000) return; + sys_str[info.number] = val; + break; + case TYPE_VARSTR: + if (info.number >= 2000) return; + str[info.number] = val; + break; } return; } + void Flags::Str(int type, unsigned int number, char* buf, int sz) const { if (sz <= 0) return; buf[0] = 0; const string* sptr; switch(type) { - case TYPE_VARLOCSTR: - if (number >= 3) return; - sptr = &loc_str[number]; - break; - case TYPE_VARSYSSTR: - if (number >= 2000) return; - sptr = &sys_str[number]; - break; - case TYPE_VARSTR: - if (number >= 2000) return; - sptr = &str[number]; - break; + case TYPE_VARLOCSTR: + if (number >= 3) return; + sptr = &loc_str[number]; + break; + case TYPE_VARSYSSTR: + if (number >= 2000) return; + sptr = &sys_str[number]; + break; + case TYPE_VARSTR: + if (number >= 2000) return; + sptr = &str[number]; + break; } int len = sptr->length(); @@ -204,6 +207,7 @@ void Flags::Str(int type, unsigned int n buf[sz] = 0; return; } + string Flags::Str(int type, unsigned int number) const { switch(type) { case TYPE_VARLOCSTR: @@ -238,6 +242,7 @@ void Flags::Save(string& save) { } } } + void Flags::Load(const char* save) { int i,j; for (i=0; i<=TYPE_NONSYSVARMAX; i++) { @@ -281,10 +286,9 @@ void Flags::Load(const char* save) { if (save) save++; } while (save); } - return; } -void Flags::SaveSys(string& save) { +void Flags::SaveSys(string& save) { //FIXME: see how to factorize with Save char buf[1024]; int j; save = "\n[Flags]\n"; @@ -307,7 +311,8 @@ void Flags::SaveSys(string& save) { } } } -void Flags::LoadSys(const char* save) { + +void Flags::LoadSys(const char* save) { //FIXME: Same as Save and SaveSys int i,j; for (i=6; i<=7; i++) { for (j=0; j<2000; j++) { @@ -352,7 +357,6 @@ void Flags::LoadSys(const char* save) { if (save) save++; } while (save); } - return; } bool Flags::Exec(Cmd& cmd) { @@ -365,230 +369,176 @@ bool Flags::Exec(Cmd& cmd) { if (cmd.cmd1 == 1 && cmd.cmd2 == 0x0a) { // 文字列演算 VarInfo arg1 = cmd.args[0]; switch(cmd.cmd3) { - case 0: - if (cmd.cmd4 == 0) { - SetStr(arg1, cmd.Str(cmd.args[1])); - } else if (cmd.cmd4 == 1) { - string s = cmd.Str(cmd.args[1]); - const char* sc = s.c_str(); - int len = cmd.args[2].value; - int i; - for (i=0; i < sc[i] && len != 0; i++, len--) { - if (sc[i]<0 && sc[i+1]!=0) i++; + case 0: + if (cmd.cmd4 == 0) { + SetStr(arg1, cmd.Str(cmd.args[1])); + } else if (cmd.cmd4 == 1) { + string s = cmd.Str(cmd.args[1]); + const char* sc = s.c_str(); + int len = cmd.args[2].value; + int i; + for (i=0; i < sc[i] && len != 0; i++, len--) { + if (sc[i]<0 && sc[i+1]!=0) i++; + } + s.erase(i); // 全角で len 文字まで切り詰める + SetStr(arg1, s); + // fprintf(stderr,"Set[%d,%d]<-%s\n",arg1.type,arg1.number,s.c_str()); + } else break; + cmd.clear(); + break; + case 1: + if (cmd.cmd4 == 0) { + SetStr(arg1, ""); + cmd.clear(); + } else if (cmd.cmd4 == 1) { + // 領域指定で文字列クリア + VarInfo v1 = cmd.args[0]; + VarInfo v2 = cmd.args[1]; + eprintf("memclear(str). Var[%d]<%d> - Var[%d]<%d>\n",v1.type, v1.number, v2.type, v2.number); + if (v1.type != v2.type || (v1.type != TYPE_VARSTR && v1.type != TYPE_VARSYSSTR && v1.type != TYPE_VARLOCSTR)) { + eprintf(" error: bad args\n"); + } else { + if (v1.number < 0) v1.number = 0; + if (v2.number > 2000) v2.number = 2000; + for (; v1.number <= v2.number; v1.number++) { + SetStr(v1, ""); + } + } + cmd.clear(); } - s.erase(i); // 全角で len 文字まで切り詰める - SetStr(arg1, s); -// fprintf(stderr,"Set[%d,%d]<-%s\n",arg1.type,arg1.number,s.c_str()); - } else break; - cmd.clear(); - break; - case 1: - if (cmd.cmd4 == 0) { - SetStr(arg1, ""); + case 2: + SetStr(arg1, Str(arg1.type,arg1.number) + cmd.Str(cmd.args[1])); + // fprintf(stderr,"Append[%d,%d]<-%s(%d:%d)\n",arg1.type,arg1.number,Str(arg1.type,arg1.number).c_str(),cmd.args[1].type,cmd.args[1].number); + cmd.clear(); + break; + case 3: + SetSys(strlen(cmd.Str(cmd.args[0]))); + cmd.clear(); + break; + case 4: + { int v = strcmp(cmd.Str(cmd.args[0]), cmd.Str(cmd.args[1])); + // string s1=cmd.Str(cmd.args[0]); + // string s2=cmd.Str(cmd.args[1]); + // fprintf(stderr,"Cmp %s(%d:%d):%s(%d:%d):%d\n",s1.c_str(),cmd.args[0].type,cmd.args[0].number,s2.c_str(),cmd.args[1].type,cmd.args[1].number,v); + if (v < 0) SetSys(-1); + else if (v > 0) SetSys(1); + else SetSys(0); cmd.clear(); - } else if (cmd.cmd4 == 1) { - // 領域指定で文字列クリア - VarInfo v1 = cmd.args[0]; - VarInfo v2 = cmd.args[1]; - eprintf("memclear(str). Var[%d]<%d> - Var[%d]<%d>\n",v1.type, v1.number, v2.type, v2.number); - if (v1.type != v2.type || (v1.type != TYPE_VARSTR && v1.type != TYPE_VARSYSSTR && v1.type != TYPE_VARLOCSTR)) { - eprintf(" error: bad args\n"); - } else { - if (v1.number < 0) v1.number = 0; - if (v2.number > 2000) v2.number = 2000; - for (; v1.number <= v2.number; v1.number++) { - SetStr(v1, ""); + break; } + case 5: // substring, index from left + case 6: // substring, index from right + // 全角対応らしい + //FIXME: Make sure it works properly + { int offset = cmd.args[2].value; + int len = strlen(cmd.Str(cmd.args[1])); + string str = cmd.Str(cmd.args[1]); + const char* s = str.c_str(); + if (cmd.cmd3 == 6) offset = len - offset; + if (offset < 0) offset = 0; + // 先頭 N 文字を読み飛ばす + int i; + int offset_top = 0; + for (i=0; i<offset && s[offset_top] != 0; i++) { + if (s[offset_top] < 0 && s[offset_top+1] != 0) offset_top += 2; + else offset_top += 1; + } + if (s[offset_top] == 0) { + SetStr(arg1, ""); + } else if (cmd.cmd4 == 0) { // 長さ制限なし + SetStr(arg1, string(s, offset_top, len-offset_top)); + } else { // cmd.cmd4 == 1 + int slen = cmd.args[3].value; + int offset_end = offset_top; + for (i=0; i<slen && s[offset_end] != 0; i++) { + if (s[offset_end] < 0 && s[offset_end]+1 != 0) offset_end += 2; + else offset_end += 1; } + string result(s, offset_top, offset_end-offset_top); + SetStr(arg1, result); } cmd.clear(); - } - case 2: - SetStr(arg1, Str(arg1.type,arg1.number) + cmd.Str(cmd.args[1])); -// fprintf(stderr,"Append[%d,%d]<-%s(%d:%d)\n",arg1.type,arg1.number,Str(arg1.type,arg1.number).c_str(),cmd.args[1].type,cmd.args[1].number); - cmd.clear(); - break; - case 3: - SetSys(strlen(cmd.Str(cmd.args[0]))); - cmd.clear(); - break; - case 4: - { int v = strcmp(cmd.Str(cmd.args[0]), cmd.Str(cmd.args[1])); -// string s1=cmd.Str(cmd.args[0]); -// string s2=cmd.Str(cmd.args[1]); -// fprintf(stderr,"Cmp %s(%d:%d):%s(%d:%d):%d\n",s1.c_str(),cmd.args[0].type,cmd.args[0].number,s2.c_str(),cmd.args[1].type,cmd.args[1].number,v); - if (v < 0) SetSys(-1); - else if (v > 0) SetSys(1); - else SetSys(0); - cmd.clear(); - break; } - case 5: // substring, index from left - case 6: // substring, index from right - // 全角対応らしい - //FIXME: Make sure it works properly - { int offset = cmd.args[2].value; - int len = strlen(cmd.Str(cmd.args[1])); - string str = cmd.Str(cmd.args[1]); - const char* s = str.c_str(); - if (cmd.cmd3 == 6) offset = len - offset; - if (offset < 0) offset = 0; - // 先頭 N 文字を読み飛ばす - int i; - int offset_top = 0; - for (i=0; i<offset && s[offset_top] != 0; i++) { - if (s[offset_top] < 0 && s[offset_top+1] != 0) offset_top += 2; - else offset_top += 1; - } - if (s[offset_top] == 0) { - SetStr(arg1, ""); - } else if (cmd.cmd4 == 0) { // 長さ制限なし - SetStr(arg1, string(s, offset_top, len-offset_top)); - } else { // cmd.cmd4 == 1 - int slen = cmd.args[3].value; - int offset_end = offset_top; - for (i=0; i<slen && s[offset_end] != 0; i++) { - if (s[offset_end] < 0 && s[offset_end]+1 != 0) offset_end += 2; - else offset_end += 1; + break; } + case 7: {// strlen w/ kanji + const char* s = cmd.Str(cmd.args[0]); int i; + for (i=0; *s != 0; i++) { + if (*s < 0 && s[1] != 0) s += 2; + else s++; + } + SetSys(i); + cmd.clear(); + break; } + case 8: // 文字列を切って短くする + if (cmd.args[1].value <= 0) { + SetStr(arg1, ""); + } else if (cmd.args[1].value < strlen(cmd.Str(cmd.args[1]))) { + Str(arg1.type,arg1.number).erase(cmd.args[1].value); + } + cmd.clear(); + break; + case 0x0e: // 漢字モードでitoa + { + int arg1 = cmd.args[0].value; + string result; + char wc[3]; wc[2]=0; + char buf[20]; + if (cmd.cmd4 == 0) { + sprintf(buf, "%d", arg1); + } else { // cmd.cmd4 == 1 + char fmt[20]; + sprintf(fmt, "%%%dd", cmd.args[2].value); + sprintf(buf, fmt, arg1); } - string result(s, offset_top, offset_end-offset_top); - SetStr(arg1, result); - } - cmd.clear(); - break; } - case 7: {// strlen w/ kanji - const char* s = cmd.Str(cmd.args[0]); int i; - for (i=0; *s != 0; i++) { - if (*s < 0 && s[1] != 0) s += 2; - else s++; - } - SetSys(i); - cmd.clear(); - break; } - case 8: // 文字列を切って短くする - if (cmd.args[1].value <= 0) { - SetStr(arg1, ""); - } else if (cmd.args[1].value < strlen(cmd.Str(cmd.args[1]))) { - Str(arg1.type,arg1.number).erase(cmd.args[1].value); - } - cmd.clear(); - break; - case 0x0e: // 漢字モードでitoa - { - int arg1 = cmd.args[0].value; - string result; - char wc[3]; wc[2]=0; - char buf[20]; - if (cmd.cmd4 == 0) { - sprintf(buf, "%d", arg1); - } else { // cmd.cmd4 == 1 - char fmt[20]; - sprintf(fmt, "%%%dd", cmd.args[2].value); - sprintf(buf, fmt, arg1); - } - int i; - for (i=0; buf[i] != 0; i++) { - if (buf[i] == ' ') { - wc[0] = 0x81; // ' ' in SHIFT_JIS - wc[1] = 0x40; - } else if (buf[i] == '-') { - wc[0] = 0x81; // '-' in SHIFT_JIS - wc[1] = 0x7c; - } else if (isdigit(buf[i])) { - wc[0] = 0x82; // number in SHIFT_JIS - wc[1] = buf[i] - '0' + 0x4f; - } else { - continue; + int i; + for (i=0; buf[i] != 0; i++) { + if (buf[i] == ' ') { + wc[0] = 0x81; // ' ' in SHIFT_JIS + wc[1] = 0x40; + } else if (buf[i] == '-') { + wc[0] = 0x81; // '-' in SHIFT_JIS + wc[1] = 0x7c; + } else if (isdigit(buf[i])) { + wc[0] = 0x82; // number in SHIFT_JIS + wc[1] = buf[i] - '0' + 0x4f; + } else { + continue; + } + result += wc; } - result += wc; - } - SetStr(cmd.args[1], result); - cmd.clear(); - } - break; - case 0x0f: case 0x11: // itoa (0x11 の方は zero padding するっぽい) - if (cmd.cmd4 == 0) { - int arg1 = cmd.args[0].value; - char buf[1024]; sprintf(buf, "%d", arg1); - SetStr(cmd.args[1], buf); + SetStr(cmd.args[1], result); cmd.clear(); - } else if (cmd.cmd4 == 1) { - // 漢字(SJIS) : 82 [4f+N] - // やはり漢字じゃない? - int arg1 = cmd.args[0].value; - char buf[1024]; char fmt[1024]; - if (cmd.cmd3 == 0x0f) { - sprintf(fmt, "%%%dd",cmd.args[2].value); /* 空白でパディング */ - } else { - sprintf(fmt, "%%0%dd",cmd.args[2].value); } - sprintf(buf, fmt, arg1); - SetStr(cmd.args[1], buf); - cmd.clear(); - } - break; - case 0x64: // 文字列の表示 : 引数をテキストウィンドウに表示 - if (cmd.cmd4 == 1) { - char buf[256]; - snprintf(buf, 255, "%d", Get(cmd.args[0].type, cmd.args[0].number)); - cmd.args[0].type = TYPE_STR; - cmd.args[0].value = cmd.AddStr(buf); - cmd.cmd4 = 0; - } - -#if 0 -@@@ -save 27 -ともよメガネのところ -- オブジェクト関連:seen9061:0 呼び出しで黒い背景画をかさねるところ、変になる -@@@ -%Xで置換する名前の設定。0x51e で読みだし。セーブファイルごとに保存されるはずなので実装を考えること -%は0-3 (4 以降は使ってない)で、渚、秋生、渚、伊吹先生、など -StrVar を拡張して代入すること -初期値はこの辺 -Text側に納め、セーブファイルでも同じようにすべきだろうなあ - args:0,"渚" - args:1,"秋生" - args:2,"渚" - args:3,"伊吹先生" - args:4,"朋也くん" - args:5,"岡崎さん" - - -106737 : 0x23 - cmd 01-04:051f:00[ 2] - args:0,"古河" -106758 : line 1712 -106761 : 0x23 - cmd 01-04:051f:00[ 2] - args:2,"古河" -106782 : line 1713 -106785 : 0x23 - cmd 01-04:051f:00[ 2] - args:4,"岡崎さん" - -47382 : 0x23 - cmd 01-04:051e:00[ 2] - args:4,V<18>[0](=0) - -47408 : 0x23 - cmd 01-0a:0004:00[ 2] - args:V<18>[0](=0),"岡崎さん" -47437 : expr: V<0>[1000](=0)=V<sys> -47451 : 0x23 - cmd 01-0a:0004:00[ 2] - args:V<18>[0](=0),"朋也くん" -47480 : expr: V<0>[1001](=0)=V<sys> -47494 : V<0>[1000](=0)==0(=true)-> 47589 -47526 : 0x23 - cmd 01-04:0514:00[ 2] - args:0,V<18>[0](=0) /* NAME.A を帰す */ -47552 : 0x23 - cmd 01-0a:0002:00[ 2] - args:V<18>[0](=0),"さん" -47577 : jmp -> 47672 -47589 : V<0>[1001](=0)==0(=true)-> 47672 -47621 : 0x23 - cmd 01-04:0514:00[ 2] - args:1,V<18>[0](=0) /* NAME.B を帰す */ -47647 : 0x23 - cmd 01-0a:0002:00[ 2] - args:V<18>[0](=0),"くん" -47672 : pos. 279 -47675 : 0x23 - cmd 01-0a:0064:00[ 1] - args:V<18>[0](=0) - -#endif - cmd.cmd_type = CMD_TEXT; - break; + break; + case 0x0f: case 0x11: // itoa (0x11 の方は zero padding するっぽい) + if (cmd.cmd4 == 0) { + int arg1 = cmd.args[0].value; + char buf[1024]; sprintf(buf, "%d", arg1); + SetStr(cmd.args[1], buf); + cmd.clear(); + } else if (cmd.cmd4 == 1) { + // 漢字(SJIS) : 82 [4f+N] + // やはり漢字じゃない? + int arg1 = cmd.args[0].value; + char buf[1024]; char fmt[1024]; + if (cmd.cmd3 == 0x0f) { + sprintf(fmt, "%%%dd",cmd.args[2].value); /* 空白でパディング */ + } else { + sprintf(fmt, "%%0%dd",cmd.args[2].value); + } + sprintf(buf, fmt, arg1); + SetStr(cmd.args[1], buf); + cmd.clear(); + } + break; + case 0x64: // 文字列の表示 : 引数をテキストウィンドウに表示 + if (cmd.cmd4 == 1) { + char buf[256]; + snprintf(buf, 255, "%d", Get(cmd.args[0].type, cmd.args[0].number)); + cmd.args[0].type = TYPE_STR; + cmd.args[0].value = cmd.AddStr(buf); + cmd.cmd4 = 0; + } + cmd.cmd_type = CMD_TEXT; + break; } } if (cmd.cmd1 == 1 && cmd.cmd2 == 0x0b) { // 数値変数演算 @@ -773,6 +723,15 @@ inline int eval(int v1, int op, int v2) return v2; } +Cmd::Cmd(const Flags& f, int _sys_ver) : flags(f), system_version(_sys_ver) { + cmd_type = CMD_NOP; + argc = 0; + errorflag = false; + cmdstr[0] = 0; + strend = 0; + pos = -1; +} + /* 演算子 op := 0x5c <uchar op> */ /* 数式 exp: [op] <token> [op <token> [...]] */ int Cmd::GetExpression(const char*& d, VarInfo* info_ptr) { @@ -1217,11 +1176,10 @@ void Cmd::GetSelection(const char*& d) { /* 一致しない場合があるのでコメントアウト */ // if (arg_count != argc) SetError(); dprintf("\n}\n"); - return; } void Cmd::GetCmd(Flags& flags_orig, const char*& d ) { - if (d == 0) { SetError(); return;} + if (d == NULL) { SetError(); return;} if (cmd_type != CMD_NOP) return; cmdstr[0] = 0; @@ -1368,8 +1326,8 @@ retry: } else { SetError(); } - return; } + void Cmd::clear(void) { cmd_type = CMD_NOP; ResetString(); @@ -1474,6 +1432,24 @@ void Cmd::SetStrvar(VarInfo info, const args.push_back(info); } + +const char* Cmd::Str(const VarInfo& info) const { + if (info.type != TYPE_STR && info.type != TYPE_VARSTR && info.type != TYPE_VARLOCSTR && info.type != TYPE_VARSYSSTR) + return ""; + int pt = info.value; + if (pt < 0 || pt >= STRHEAP_SIZE) return ""; + return strheap + pt; +} + +int Cmd::AddStr(char* s) { + // 1-0a-0064 はこういうものが必要らしい + int start = strend; + while (*s) strheap[strend++] = *s++; + strheap[strend++] = 0; + return start; +} + + void Cmd::read(const CmdSimplified& from) { errorflag = false; ResetString(); @@ -1487,7 +1463,7 @@ void Cmd::read(const CmdSimplified& from /* args の読み込み */ args.clear(); char* d = from.args; - if (d == 0) return; + if (d == NULL) return; while(*d != TYPE_END) { VarInfo info; switch(*d) { @@ -1511,8 +1487,8 @@ void Cmd::read(const CmdSimplified& from *d = TYPE_END; } } - return; } + void Cmd::write(CmdSimplified& to, char*& buffer) const { /* if (cmd_type != CMD_OTHER) { @@ -1529,7 +1505,7 @@ void Cmd::write(CmdSimplified& to, char* to.argc = argc; /* args の書き込み */ if (args.empty()) { - to.args = 0; + to.args = NULL; } else { to.args = buffer; char* d = to.args; @@ -1554,9 +1530,10 @@ void Cmd::write(CmdSimplified& to, char* buffer = d; } } + void CmdSimplified::copy(const CmdSimplified& from, char*& args_buffer) { *this = from; - if (args == 0) return; + if (args == NULL) return; char* args_old = from.args; /* args のコピー */ while(*args_old != TYPE_END) { @@ -1572,6 +1549,7 @@ void CmdSimplified::copy(const CmdSimpli args = args_buffer; args_buffer += args_len; } + void CmdSimplified::Save(string& saveret) { char buf[1024]; sprintf(buf, "%02x-%02x:%04x:%02x(%02d),", cmd1, cmd2, cmd3, cmd4, argc); @@ -1609,7 +1587,7 @@ void CmdSimplified::Load(const char* sav type = CMD_OTHER; sscanf(save, "%02x-%02x:%04x:%02x(%02d),", &cmd1, &cmd2, &cmd3, &cmd4, &argc); save = strchr(save, ','); - if (save == 0) { + if (save == NULL) { *args_buffer++ = TYPE_END; return; } @@ -1639,7 +1617,6 @@ void CmdSimplified::Load(const char* sav } } *args_buffer++ = TYPE_END; - return; } #ifdef SCN_DUMP @@ -1653,17 +1630,22 @@ int main(int argc, char** argv) { /* determine file names */ bool verbose = false; char* inname = "seen.txt"; - char* outname = 0; + char* outname = NULL; if (argc > 2 && strcmp(argv[1],"-v") == 0) { int i; for (i=1; i<argc; i++) argv[i] = argv[i+1]; argc--; verbose = true; } switch(argc) { - case 1: break; - case 2: inname = argv[1]; break; - case 3: inname = argv[1]; outname = argv[2]; break; - default: usage(); + case 1: break; + case 2: + inname = argv[1]; + break; + case 3: + inname = argv[1]; + outname = argv[2]; + break; + default: usage(); } /* open output file */ FILE* outstream = stdout; @@ -1681,7 +1663,7 @@ int main(int argc, char** argv) { int system_version = 0; while( (fname = archive.ListItem()) != 0) { ARCINFO* info = archive.Find(fname,""); - if (info == 0) continue; + if (info == NULL) continue; char* data = info->CopyRead(); char* d = data; char* dend = d + info->Size();