好きだねぇ~これwww
すこし調べてみると、.g01アプリの場合、ソース冒頭で引数の定義を行っている。で、それに対応して自動的にUsage表示をしてくれると。こういう仕組みになってた。
今までは普通のCのソースに文字列を書き足せばそれでよかった。
(もちろん.g01だってそれは出来る。)
・・・でもなぁ。なーんかそれじゃ、色気がないというか。欲が出てきた。
そこで、Usageと同じように、ソースヘッドに番号だけを埋め込んで、hijk側で制御するようにできないもんかなぁと。いかにもefg01の仕様っぽいし、サイズだって極限まで絞れ、無駄が出ないようにできるはず。(なにより、そういう統一的な形のほうがなんかカッコよくない??)
で、現在の妄想。バージョン番号を出したい場合はhijk側でオプションを付けるってのはどうだろう?
>hijk.exe -v Nasuka.g01 hijk Version 1.1 Nasuka Version 1.3 Usage>Nasuka in:filename out:filename
こんな感じに。
この構想には二つ意味がある。まず、現在はなにも引数をつけないと自動的にUsageが表示されるという仕様になっているんだけど、なにも引数をつけない場合はディフォルトの設定で動作を始めてほしいというアプリだってあるはずだ。(引数自体は持っている)そういう設計のアプリの場合、今のUsageの仕様はすこし不便ではないかと考えた。また当然、バージョン番号等を統一的に扱うような仕様にしておけば、小さくなるばかりではなく、説明や使い方を書く場合も最低限の文章で書くことができるはず。
これはUsage(オプションの扱い)でも同じで、普通のC言語のように自由気ままにやらせちゃうと余計な容量やコードが入り込み、さらには非統一的にもなる。あえて出来ることを絞ることでこの問題は解消される。
誤解してほしくないのだが別にそれを悪だと言ってるんじゃないよ。ヘンな突っ込み入れんといてね。
たとえばこんな仕様。
どかな??
ここでいろいろ解析してみた。0x0cとか0x1cとかのコードを打ち込むことで、タイプや文字数を指摘している仕様らしい。
なんか余ってないかな? さっそくソースコードを読み解いてみる・・・
ここかなぁ・・・ func06_init();
void func06_init() { UCHAR *p; func06str = malloc(sizeof (struct FUNC06STR)); func06str->flags &= 0; func06str->usgs = 2; func06str->def_arg0 = 1; func06str->usg[0].tag[0] = '\0'; func06str->usg[0].flg = 0; func06str->usg[0].usg[0] = '\0'; func06str->usg[0].typ = 0xff; func06str->usg[1].tag[0] = '\0'; func06str->usg[1].flg = 3; func06str->usg[1].usg[0] = '\0'; func06str->usg[1].typ = 0xfe; /* 3:str */ for (func06str->argv0 = p = *main_argv; *p != '\0'; p++) { if (*p == '\\' || *p == '/') func06str->argv0 = p + 1; } return; }
うーん。この関数って、内部にコマンドライン情報を格納するための構造体を定義して、さらに初期化してる・・・のかなぁ???
102行目がそれかな。ここでFUNC06STR構造体を定義。さらに108行でそれをグローバル変数として生成・・・かなこれ?
おっと!FUNC06STR内に、さらにFUNC06STR_SUB00構造体が入ってる。入れ子になってるのか
0 | usg | tag(32文字?) | usg(32文字?) | def(32文字) | typ(1文字) | flg(1文字) | dmy_c(2文字) | def_int(int×1) | dmy_i(int×6) |
1 | usg | tag(32文字?) | usg(32文字?) | def(32文字) | typ(1文字) | flg(1文字) | dmy_c(2文字) | def_int(int×1) | dmy_i(int×6) |
2 | usg | tag(32文字?) | usg(32文字?) | def(32文字) | typ(1文字) | flg(1文字) | dmy_c(2文字) | def_int(int×1) | dmy_i(int×6) |
・ | |||||||||
62 | usg | tag(32文字?) | usg(32文字?) | def(32文字) | typ(1文字) | flg(1文字) | dmy_c(2文字) | def_int(int×1) | dmy_i(int×6) |
63 | usg | tag(32文字?) | usg(32文字?) | def(32文字) | typ(1文字) | flg(1文字) | dmy_c(2文字) | def_int(int×1) | dmy_i(int×6) |
def_arg0(int×1) | |||||||||
flags(int×1) | |||||||||
usgs(int×1) | |||||||||
*argv0(ポインタ) | |||||||||
argv_f(256文字) | |||||||||
argv_all(6万5千文字) |
ちょっと別の方向からアプローチしてみよう。
gas2naskのソースを見てみると、先頭で例のコマンドラインの設定をして、そのあと、g01_setcmdline関数を呼び出している。この関数はなにをやってくれてるんだろう???
んんん? guigui01.hを見てみると、この関数はdefineになってるなぁ・・・defineって、文字列置換だったよね?たしか???
#define g01_setcmdlin(p) __asm__ __volatile__("movl %%eax,%%edi\n\tcall _g01_execcmd"::"a"(p):"%esi","%edi","cc")
つーことは・・・・
__asm__ __volatile__("movl %%eax,%%edi\n\tcall_g01_execcmd"::"a"(p):"%esi","%edi","cc")
これに置換された後コンパイルされるってこと・・・なのか? なんだべ? これ???
はっはあぁぁぁ・・・・・
わかったぞ! これはgcc由来のインラインアセンブラの書き方だ! 分解して書いてみると・・・
__asm__ __volatile__(" movl %%eax,%%edi call_g01_execcmd"::"a"(p):"%esi","%edi","cc" )
うへぇ! 難しい・・・。 eaxの値をediに写し、g01_execcmdを呼び出している・・・のかな??
やっと見つけた。startup.ask内にやっとこさg01_execcmdを見つけた・・・
だめだあぁぁぁ・・・わっかんねえぇぇぇぇ・・・・
この関数を見ていると、やっぱりどう見ても、例のコマンド定義の文字列はfunc06str構造体に格納されているらしい。この構造体は先のinitで初期化されているんだけど、どこでここに定義されたものが当て込まれているんだろう。その部分が解れば、特別なコードを使って「以下はバージョン番号」だよ!と定義できるはずなんだが・・・・
seroさんがヒントくれた!! さっそくそのへんを検証・・・・すると・・・
こんなコードを発見。状況から予測を当てはめると・・・
for (j = 0;; j++) { ←jは63までループする仕様。(超えるとエラー?) i = getnum_api(&ra, 0); たしか、SUB00構造体もこの数! if (i == 4) { func06str->usgs = j; ←iが4だとループを打ち切る。4? 0x40が終端じゃなかった? break; ブレイク時にその数をusgsに記憶?引数の個数になるぞ?! } if (j == 64) { puts("func6: internal error (2)"); exit(1); } if (i == 5) i = 0xfff0 << 2 | 0; if (i == 6) ←引数の先頭の決め打ちコードは0x86・・・ i = 0xfff1 << 2 | 2; if (i == 7) { ←確か、改行コードは0x87・・・7!? /* 改行 */ if (j == 0) { ←jが0の時。引数の先頭?に改行がある状態? エラーにしてる puts("func6: internal error (3)"); exit(1);
まだ確認が甘いが、このiって、コードの一桁目に合致するような気がしてならない・・・
そもそもiってなんだよ? i = getnum_api(&ra, 0); getnum_apiってのはどういう関数だ???
また、一桁目が重要なのは、いずれも0x8xなコード達。(他のは逆に、一桁目が可変するものが多い)
i = 0xfff0 << 2 | 0; ←なにしてっかってーと・・・ ・ 1111111111110000(0xfff0) を左に二つ、ビットシフトしなされ。 ・ 1111111111000000 できやした。 ・ 0000000000000000(0) ゼロと論理演算(論理和)しなされ ・ 1111111111000000 できやした~ あれ?? これ、なにをしてるの??なんのためにこんな演算を???