*これはなにか? hideyosiが、ASKAをLinuxに移植しようともくろんであれやこれやと弄くりまわした時の記録です。こんな文章でもどなたかのご参考くらいにはなるかもしれないと思い、恥を忍んで公開しています。 -すこし読んでいただければすぐにわかると思いますが、私はC、ましてやC++なんて出来ません。ヒーヒー言いながらGoogleで調べながらやってみました。 -この文章は、''OSASKのWiki''にはあまりふさわしいとは思えません。全てが一段落したら、私個人のWEBとかに移行しようと考えています。(今はまだ、いろんな人からの意見を頂ける場としてとても重宝なのであえてWikiに置かせて頂いておりますが・・・) ---- えーと・・長過ぎるので、コメントはこのへんにでも。 (^^;) #comment ---- *Linuxに移植してみよう! でも、そのまえに・・・ -まずは、Windowsでコンパイルしてみる。 --そもそも、私はCとかがよくわからない。また、Linuxだってそんなによくわかるわけでもないのだ。そこで、まずは移植以前に、本来のプラットホームであるWindows上でコンパイルを実体験してみよう。 --そんなわけで、まずは、''ソース''と''コンパイラ''が必要になる。Windowsの場合、Linuxとかと違ってもともと入っているわけではないのだから。 -コンパイラの調達 --Windows上でASKAのようなC++のソースをコンパイルするのによく用いられるのが、ご存知MicroSoftoのVisualC++である。(最新版は、Ver.6) --幸いなことに、私はこれを使える環境にあった。しかし、ここで考えた。このソフトは商用である。しかも、決して安くない。別に私は無料原理主義者ではないが、ちとこれでは・・・。また、同じC++とはいっても、Linuxのそれとはおそらくかなり扱いが違うだろう。元々の目的は、ASKAのLinuxへの移植だ。MS-VC++ では、あまりデータにならないかもしれない。ううん・・・どうしたものか・・・・。 COLOR(#009900){・askaβ19(英語版)はMinGWでコンパイルできましたよ。使ったのは多分 "[OSASK 5194] gcc移植計画." このへんのMinGWです。 -- [[I.Tak.]] SIZE(10){2003-07-25 (金) 21:10:01}} --そんなことをつぶやいていると、英雄I.Takさんからアドバイスが!。なになに? MinGWだって? --MinGWについて調べてみた。おぉ!。これは、ヨースルに、Linuxとかに乗っている gccを、Windowsに移植したものらしい!。フリーで使えるばかりではなく、元々がgccだ。これなら、本来の目的であるLinux移植にとってもよいデータになるぞ。さっそくMinGWのページにいってみる。 http://sourceforge.net/projects/mingw/ --ちょっとわかりにくかったが、このページ内の、''DOWNLOAD''と書かれているところをクリックすると、いろいろなソフトをダウンロードできるページに移れる。さっそくMinGWを探してみる。 --あれれ? MinGWは何種類かバージョンがある。I.Takさんのアドバイスでは 1.1。しかし、既に2.0や3.0rc3とかがある。まあrc3とかはともかくとして・・・・・ --そんなわけなので、両方とも入手してみた。MinGW-1.1.tar.gzとMinGW-2.0.0-3.exe。 --さて、まずはこれらをセットアップする。2.0は簡単だ。exeを実行すれが、インストーラが動いてセットアップしてくれる。1.1はtarなので、解凍にちょっとてこずったが、フリーソフトを探せばいくらでも見つかるだろう。私の場合は、それぞれ c:\mingw1 ・ c:\mingw2 にセットアップした。 -ソースの入手。しかし、落とし穴が! --ソースを入手すべく、今原さんのページへ。aska10b18.lzh をダウンロード。 --解凍すると、中には出来上がっているASKAとソースが入っている。ソースの中身だけを、 c:\aska_m というディレクトリを作ってコピー。さて、それじゃあ、さっそくコンパイルだ!。 --・・・・・・あれ???? --実は、大変な勘違いをしていたことが分かった。ASKAの最新版は、上記の aska10b18.lzh ではないのだ!。(そういえば、I.Takさんも、''askaβ19(英語版)'' って言ってたよね) --そんなわけで、慌てて調べてみると、ASKAの最新版は、[[OSASKの開発者向けのページ:http://www.imasy.org/~kawai/osask/developers.html]]にある、srcset05.lzh でした!!。 --さっそくダウンロードしなおして、C:\aska_m にコピーしなおし・・・・ -コンパイルしてみる。''まずは、MSVC++6'' --これは、極めて簡単だった。ASKAのソースの中に、ASKA.dws というファイルがある。これをダブルクリックするか、MSVC++6 からワークスペースとして開いてやる。(ASKA.dspではないよ) --あとは単にビルドするだけ。debug というディレクトリが出来て、その中に aska.exe が出来上がる。 -コンパイルしてみる。''MinGW1.1 の場合'' --ASKAのソースの中に、gmake.bat というバッチファイルがある。これはどうも、MinGW1.1でメイクするためのものらしい。中身を覗いてみると一目瞭然。3行目のMinGWをセットアップしてある場所だけちょこっと書き換えて、ダブルクリック。 --・・・あかん・・・。なんでだろう???? --だいぶなやまされたが、へんなことに気付いた。今現在、私はMinGW1.1を、 c:\mingw1 という場所にセットアップしてある。なので、 gmake.bat の三行目もそう書き換えた。どうも、これが問題らしい。理由はよくわからないが、c:\mingw1 を c:\mingw と書き換え、同じく gmake.bat もそれに合わせて変更。すると・・・ --コンパイル成功! aska.exe が作られた。 -コンパイルしてみる。''MinGW2.0 の場合'' --さて、こんどはMinGW2.0だ。↑ のパターンで考えると、おそらく私がいまセッティングしてある c:\mingw2 では同じような問題が起こるのだろう。MinGW1.1をセットアップしてある c:\mingw を、c:\mingw1 に戻す。そして、c:\mingw2 を c:\mingwに。 --また、なぜか MinGW2.0 には、 makeコマンドがない。探してみると、bin のなかに、mingw32-make.exe というのがある。これを make.exe に変更。 --また、よくほかのディレクトリを見てみると、1.1とは微妙に違う。そんなわけで、 gmake.bat を以下のように書き換えた。 REM Set Your MINGW Directory Below REM This Setting is for the mingw ver. 2.0 SET MINGW=c:\mingw SET PATH=%MINGW%\bin;%MINGW%\lib\gcc-lib\mingw32\3.2;%PATH% SET GCC_EXEC_PREFIX=%MINGW%\lib\gcc-lib\mingw32\3.2 SET LIBRARY_PATH=%MINGW%\lib;%MINGW%\lib\gcc-lib\mingw32\3.2 SET C_INCLUDE_PATH=%MINGW%\include SET CPLUS_INCLUDE_PATH=%MINGW%\include\c++ SET OBJC_INCLUDE_PATH=%MINGW%\lib\gcc-lib\mingw32\3.2\include\objc make del gmake.pif --そして、忘れてはいけないのがクリーン作業。つまり、さっき1.1で作られたものを消しておかなくてはいけない。 aska.exe と、*.o というファイルを削除 --さて、ではコンパイル。 gmake.bat を実行する。 module.h: In member function `void Module::Release()': module.h:37: ISO C++ forbids casting to an array type `unsigned char[]' module.h:37: ISO C++ forbids casting to an array type `unsigned char[]' module.h:37: ISO C++ forbids casting to an array type `unsigned char[]' make: *** [main.o] Error 1 --・・・・あれぇ???。こんなエラーが出た。 --これは、C++コンパイラのエラーだ。うーん・・。どういうことだろう。元々Cが使えない私には、この辺のことはわからない。Googleで調べてもなかなかヒットしない。うーん。こまったぁ・・・・ COLOR(#009900){・なんか文法チェックが厳しくてはねられているみたいですね。C++へのオプションでチェックをゆるめてやるといいのかな? -- [[K]] SIZE(10){2003-07-26 (土) 14:00:17}} COLOR(#009900){・とりあえず問題のmodule.hの37行目の[]を*に変えたらaska.exeができるみたいです。UPXで圧縮しても115KBもありますが。でけえ!。まあ、動けばいいか。って動くかどうかも確かめてはいませんが。 -- [[K]] SIZE(10){2003-07-26 (土) 14:41:29}} --Kタンから、こんなアドバイスが!。有難い!さっそく実践。 void Release(void){ DELETEPTR_SAFE((unsigned char[])lpMdlAdr); dwMdlSize=0; lpMdlPos=NULL; } ''↓'' void Release(void){ DELETEPTR_SAFE((unsigned char*)lpMdlAdr); dwMdlSize=0; lpMdlPos=NULL; } --この変更で、無事、コンパイルに成功しました。 ---あとで教えてもらったことなんですが、MinGW1.0はgcc2.95.3ベース・MinGW2.0は、gcc3.2がベースだそうです。gccは3.2から文法が厳しくなったそうです。char[] と char* は同じ意味であり、これまでは、まあちょっと変則的な書き方ってことで容認されてきたものが、3.2からは明確に間違った書き方ということになったのだそうです。 -検証と考察 COLOR(#009900){・8月頭までは多少時間があるので、LinuxとWin95を使って、コンパイル実験等お手伝い出来るかと思います。 -- [[くーみん]] SIZE(10){2003-07-27 (日) 18:35:41}} COLOR(#009900){・今度はちゃんと落とせたました。早速、OSASKのソースの中のinit.askを使って試したところ、全て正しいファイルと全く同じものを出力しました。 -- [[聖人]] SIZE(10){2003-07-27 (日) 22:29:40}} --こうして出来上がった3つのASKA。動作はみなさんが手伝って検証してくれました。おそらく問題ないのではと思います。 --問題としては、出来上がったASKAが軒並み大きいということです。 tolset05.lzh に含まれている、配布版のASKAは、65.5kbyte。しかし、今回作ったASKAは、UPXで圧縮してなお、以下の大きさです。 ---MSVC++6: 99kbyte ---MinGW1.1: 79kbyte ---MinGW2.0: 115kbyte --うーん・・・どうなんでしょう。とりあえずはこれでOKとしておきます。 *ASKAをLinuxに移植する試み さて、上記のような作業を通してちょっとだけものが解ったつもりになった私は、Linuxへの移植にチョッカイを出しました。 -まずは、下準備ね。 --getした''srcset05.lzh''をLinux上で解凍する。これは、 ~/$ lha -x srcset05.lzh --で楽々。カレントも移っておこう。 ~/$ cd aska/ensrc ~/aska/ensrc$ -一応。 ''makefile'' を、 ''Makefile''にリネームしておく。 ***俺は乱暴ものだ!! -そういうわけで、とりあえず下準備はOKなのだ。さて、どうするかっていうと・・・・いきなりメイクじゃ!! ~/aska/ensrc$ make g++ -O2 -I. -c main.cpp In file included from parser.h:21, from main.cpp:1: module.h:11: io.h: ?????????????????????? make: *** [main.o] エラー 1 ~/aska/ensrc$ -・・・そんなわけで、いきなりエラーが出ました。まあ、当然でしょうけど。 -さて、ここでちと考えて見る。C とかって、ソースファイルが一つじゃない場合って、まず、各ファイルを objファイルっていう中間ファイルにコンパイルして、そして出来上がった objファイル達を、最後にリンクで一つにして実行ファイルを作るわけだ。 -この場合、自動的にやってくれる make だと、エラーが出た時点で止まってしまう。でも、もしかしたら、ほかのソースの中で、そのままコンパイルできるのがあるかもしれない。とりあえず、 「objまでだけやってね」っつー状態にしてみよう。そのためのオプションは、 -c ということがわかった。さっそくやってみよう。 ~/aska/ensrc$ gcc -O2 -c *.cpp In file included from generator.h:21, from generator.cpp:1: module.h:11: io.h: ?????????????????????? In file included from parser.h:21, ・ ・ ・ from table.cpp:1: module.h:11: io.h: ?????????????????????? ~/aska/ensrc$ -うーん。ドバーっとエラーが出てきたけど、もしかしたらうまくいっているのも一つくらいあるかもしれないぞ?? ~/aska/ensrc$ ls *.cpp filepath.cpp main.cpp parser.cpp stringx.cpp textmodule.cpp generator.cpp module.cpp scanner.cpp table.cpp -ふむふむ。cppファイルは全部で9個ある。 ~/aska/ensrc$ ls *.o filepath.o stringx.o textmodule.o ~/aska/ensrc$ -・・・おぉぉ!。objファイルがいつのまにか3個出来ているぞ?。つまり、この3つに関しては、''とりあえずOK''ってーことでいいのかな。 ***残りの6個のcppファイルをコンパイルテスト --まず、ここいらあたりから。さっそく単品コンパイル。 ~/aska/ensrc$ gcc -O2 -c scanner.cpp In file included from scanner.h:21, from scanner.cpp:1: module.h:11: io.h: ?????????????????????? ~/aska/ensrc$ ~/aska/ensrc$ gcc -O2 -c module.cpp In file included from module.cpp:2: module.h:11: io.h: ?????????????????????? ~/aska/ensrc$ ~/aska/ensrc$ gcc -O2 -c parser.cpp In file included from parser.h:21, from parser.cpp:2: module.h:11: io.h: ?????????????????????? ~/aska/ensrc$ ~/aska/ensrc$ gcc -O2 -c generator.cpp In file included from generator.h:21, from generator.cpp:1: module.h:11: io.h: ?????????????????????? ~/aska/ensrc$ ~/aska/ensrc$ gcc -O2 -c module.cpp In file included from module.cpp:2: module.h:11: io.h: ?????????????????????? ~/aska/ensrc$ ~/aska/ensrc$ gcc -O2 -c main.cpp In file included from parser.h:21, from main.cpp:1: module.h:11: io.h: ?????????????????????? ~/aska/ensrc$ -・・・うむむ。全てのファイルで、同じようなエラーが出ている。どうも、おのおののcpp本体ではなく、インクルードしている module.h の11行目あたりに問題があるみたいだ。さっそく、覗いてみよう。 :mosule.h ・ ・ #include <stdio.h> #include <stdlib.h> #include <io.h> #include <iostream> ・ ・ -うーん。この #include <io.h> に問題があるみたい。どれどれっつーことで探してみると・・・・ないじゃん!!! -あっれぇ??。コンパイルが成功したWindowsのMinGWのほうを見てみる。ちゃんと、includeディレクトリ、すなわち、 stdio.h とかの、もっとも基本的で標準的なやつらのすぐ横っちょにあるぞ???。へんだなぁ・・・。 -LinuxBOXのHDの中をあっちこっち探してみると、やっと見つけた。一つは、/usr/include/sys/io.h と、あとはLinuxのカーネル内に、各CPU用に用意されているようだ。なーんだ。あるじゃないか。・・・・・でも、まてよ?。なんで、Linuxの場合はわざわざ違う場所に配置されているんだ??? -気になったので、おのおのの中身とMinGWのヤツを見比べてみる。えーと・・・・ -・・・・あっれぇ???。C言語出来ない私だけど、なんか、あまりにも中身が違い過ぎないか?。ヘッダーファイルって、関数とかの宣言とかしてるとこでしょ?。内容はともかく、関数の名前くらい共通のがあってもいいんじゃないか?。似ても似つかないくらい違うぞ。これ。 -判明した。なんと、これ、たまたま同じ名前っつーだけで、ぜんぜん違う用途のものらしい!。しかも、なんかMinGWの io.h は、「単純に移植や置き換えはできないんだよ!やーいやーい!」っつーことらしいぞ。うわぁぁぁ! しょっぱなかーらぁーけっつまづいてーヒザをーすりむいたぁー♪ (T∀T) -・・・必殺技!!! コメントアウトじゃぁ~!!! (とりあえず後回し・・) -俺は乱暴者だぁ~・・・ ***さて、手始めに、 scanner.cpp あたりから。 -ではでは。さっそくコンパイルしてみる。 ~/aska/ensrc$ gcc -O2 -c scanner.cpp In file included from scanner.h:20, from scanner.cpp:1: macro.h:24: parse error before `if' macro.h:24: stray '\' in program macro.h:25: stray '\' in program ・ ・ ・ scanner.cpp: In method `enum Token Scanner::PeekToken()': scanner.cpp:56: stray '\' in program ~/aska/ensrc$ -ふーん・・・。scanner.cpp ではなくて、インクルードしている macro.h の24行目(の前の部分)に問題があるらしいぞ。さっそく覗いてみる。 // ポインタが非NULLならばdeleteするマクロ #define DELETE_SAFE(var) \ if (var != NULL) {\ delete var;\ var = NULL;\ } -ふむ。ここいらへん、どうも行が長いので、¥ で割っているような感じだなぁ。どれどれ、試しに、一行にしてみよう。 // ポインタが非NULLならばdeleteするマクロ #define DELETE_SAFE(var) if (var != NULL) { delete var; var = NULL; } -これがなんと、大当たり!!。この部分ではエラーが出なくなった!! -でも、こんどが別の部分で同じようなエラー文が。 -あららら?。いま直した部分のすぐ下に、ほとんど同じような処理がされている。 // クラスのポインタ等をdeleteするマクロ #define DELETEPTR_SAFE(var) \ if (var != NULL) {\ delete [] var;\ var = NULL;\ -よし。ここも同じく一行にしてみよう。 // クラスのポインタ等をdeleteするマクロ #define DELETEPTR_SAFE(var) if (var != NULL) { delete [] var; var = NULL; } -おぉ!無事、コンパイル終了だ! また野望に一歩近づいた!! ***おっしゃぁ! 次は、parser.cpp じゃ! -さっそくコンパイル。 ~/aska/ensrc$ gcc -O2 -c parser.cpp parser.cpp: In method `long int Parser::LocalAddress(Parameter &)': parser.cpp:113: implicit declaration of function `int ltoa(...)' parser.cpp: In method `long int Parser::Selector(Parameter &, LabelList *)': -うーん。このエラーを調べてみると、「そんな関数、シラネーヨ!」っつー意味らしい。そんなわけで、この関数について調べてみると・・・・ -うひゃぁ!。えらいことだ。LinuxのGCCでは、「そんな関数、シラネーヨ!」なんだってー!。 うわぁぁぁんん! どうしよう。 -捨てる神あれば拾う神ありで、sprintf関数で代用できるつーことがわかった。そんなわけなので、エラーが出ていた部分 Error("Cannot use \"&\" for register, array, and immediate perand"); return 5; } param.disp += ltoa(selparam.ndisp + label->nLocalAddress, buf, 10); return 0; } -を、以下のように書き換え。 Error("Cannot use \"&\" for register, array, and immediate operand"); return 5; } param.disp += sprintf(buf,"%ld",selparam.ndisp + label->nLocalAddress); return 0; -念のため、ほかにこの関数がないか検索・・・。あったあった。ほかにも149行目、151行目にある。ちょうど近いので、一気に書き換えちゃう。 if(param.ndisp != 0){ if(param.disp == ""){ param.disp += ltoa(param.ndisp, buf, 10); }else{ param.disp += dummy + "+" + ltoa(param.ndisp, buf, 10); } param.ndisp = 0; ''↓'' if(Selector2(param) != 0) return 1; if(param.ndisp != 0){ if(param.disp == ""){ param.disp += sprintf(buf,"%ld",param.ndisp); }else{ param.disp += dummy + "+" + sprintf(buf,"%ld",param.ndisp); } param.ndisp = 0; -さーて、これでいいはず。再びコンパイル。 ~/aska/ensrc$ gcc -O2 -c parser.cpp parser.cpp: In method `long int Parser::Selector(Parameter &, LabelList *)': parser.cpp:151: no match for `basic_string<char,string_char_traits<char>,__default_alloc_template<true,0> > + int' ~/aska/ensrc$ -おんやぁ~?。なんだろう。このエラー。 -調べてみると、どうも、変数の型式が違うと怒っているらしい。うーん・・・ -結局、151行目を以下のようにすることで解決。これでいいのかなぁ・・・ sprintf(buf,"%ld",param.ndisp);param.disp += dummy + "+" + buf; -まあ、とりあえず、これでよしということにしておこう。(どーせ俺は乱暴者だい!) -ltoaは #define ltoa(n,b,l) (spfintf(b,"%ld",n), b) -とマクロ定義にすればパッチも小さくなってよいと思われ。(I.Tak.) ***module.cpp いってみようか! -コンパイルすると、 ~/aska/ensrc$ gcc -O2 -c module.cpp module.cpp: In method `long int Module::ReadFile(string &)': module.cpp:26: implicit declaration of function `int filelength(...)' -っとまあ、こういうエラーがでる。たしか、このパターンは、「そんな関数、シラネーヨ!!」だったなぁ。つまり、この filelength って関数がないっつーことらしい。 -調べてみると、どうもこいつも、MinGWに特有の関数らしい。ほいでは、代替の措置はないのかな? -いやぁ~。あるもんですな。そんなわけで、以下のブロックを、module.cpp の頭の部分に追加 #include <string.h> #include "module.h" //現在ではディレクトリの検索などはしていないので、単純に""や<>をはずすだけ string Module::MakeFullPath(string& p){ string str = p.substr(0, 0); if(str == "\"" || str == "\'" || str == "<"){ str = p.substr(1, str.size()-1); }else{ str = p.substr(); ''↓'' #include <string.h> #include "module.h" #include <sys/stat.h> int filelength (int fd) { struct stat st; if (fstat (fd, &st) == -1) { exit (1); } return st.st_size; } //現在ではディレクトリの検索などはしていないので、単純に""や<>をはずすだけ string Module::MakeFullPath(string& p){ string str = p.substr(0, 0); if(str == "\"" || str == "\'" || str == "<"){ str = p.substr(1, str.size()-1); -なんと、これだけでOKでしたぁ。 (ルンルン♪) ---I.Takさん、感謝~。 --勝手に修正して, 元の部分を外に出しておいたのはやはりまずかったか……というわけで再度修正。これでO.K.です (I.Tak.) ---うわぁぁ! 再度感謝。勘違いして元に戻してしまい、いま悲鳴をあげてマスタ・・・(T∀T) ***generator.cpp いくぞー! -コンパイル。 ~/aska/ensrc$ gcc -O2 -c generator.cpp generator.cpp: In method `void Generator::Param2LPSTR(char *, Parameter &)': generator.cpp:45: implicit declaration of function `int ltoa(...)' generator.cpp:45: passing `int' to argument 2 of `strcat(char *, const char *)' lacks a cast ・ ・ ~/aska/ensrc$ -ふーん。なるほど。一杯出てきたけど、これは parser.cpp の時と同じパターンだな。 ltoa関数を置き換えればいいんだ。 -えーと、どれどれ、いっぱいあるなぁ・・・。45・68・79行目の三箇所。 45行目 strcat(buf, ltoa(param.ndisp, buf2, 10)); 68行目 strcat(buf, ltoa(param.scale, buf2, 10)); 79行目 strcat(buf, ltoa(param.ndisp, buf2, 10)); ''↓'' 45行目 strcat(buf, sprintf(buf2,"%ld",param.ndisp)); 68行目 strcat(buf, sprintf(buf2,"%ld",param.ndisp)); 79行目 strcat(buf, sprintf(buf2,"%ld",param.ndisp)); -よーし。これでいいかな。コンパイル。 ~/aska/ensrc$ gcc -O2 -c generator.cpp generator.cpp: In method `void Generator::Param2LPSTR(char *, Parameter &)': generator.cpp:45: passing `int' to argument 2 of `strcat(char *, const char *)' lacks a cast generator.cpp:68: passing `int' to argument 2 of `strcat(char *, const char *)' lacks a cast generator.cpp:79: passing `int' to argument 2 of `strcat(char *, const char *)' lacks a cast -うにゃぁ?あれれ、なんじゃこりゃ?。うーん???。なんか、型違いっていってるよな・・・。 -そんなわけで、こういう風に変更。(・・・だんだん自身がなくなってきたなぁ・・) 45行目 sprintf(buf2,"%ld",param.ndisp);strcat(buf,buf2 ); 68行目 sprintf(buf2,"%ld",param.ndisp);strcat(buf,buf2 ); 79行目 sprintf(buf2,"%ld",param.ndisp);strcat(buf,buf2 ); -さーて、こんどこそ大丈夫かな。 ~/aska/ensrc$ gcc -O2 -c generator.cpp generator.cpp: In method `void Generator::RegistMul(Parameter &, Parameter &)': generator.cpp:510: implicit declaration of function `int itoa(...)' generator.cpp:510: passing `int' to argument 2 of `strcat(char *, const char *)' lacks a cast generator.cpp: In method `void Generator::RegistDiv(Parameter &, Parameter &)': generator.cpp:554: passing `int' to argument 2 of `strcat(char *, const char *)' lacks a cast -あらら?。今直した所はパスしているみたいだけど、別のところ。しかも、 itao ?? ltao じゃなくて?? -調べてみたら、これも3箇所もあった。一気に修正。ただし、さっきの ltoa とはほんのちょっとだけ違う。 "%ld" じゃなくて、 "%d" なので注意。 510行目 strcpy(buf, buf1); strcat(buf, ","); strcat(buf, itoa(x, buf2, 10)); 554行目 strcat(buf, ","); strcat(buf, itoa(x, buf1, 10)); 722行目 OutputMASM("#local", "equ", itoa(sysvarlocalvalue, buf, 10), ""); ''↓'' 510行目 strcpy(buf, buf1); strcat(buf, ","); sprintf(buf2,"%d",x);strcat(buf, buf2); 554行目 strcat(buf, ","); sprintf(buf1,"%d",x);strcat(buf, buf1); 722行目 sprintf(buf,"%d",sysvarlocalvalue);OutputMASM("#local", "equ", buf, ""); -いよーし!!。これでコンパイル、完了!!! ***うおぉぉ! table.cpp じゃ! -さーて・・・こいつはどこ修正するのかなぁ・・・ ~/aska/ensrc$ gcc -O2 -c table.cpp ~/aska/ensrc$ -・・・・あれ? 通っちゃった・・・ ひえぇーー!! *** main.cpp キタ━━━━(゚∀゚)━━━━ッ!! -いくぞ!! ラスト! ~/aska/ensrc$ gcc -O2 -c main.cpp ~/aska/ensrc$ -・・・・逝ってくれましたぁ・・・ -え?つーことは???。全コンパイル、いけるのか! いっけるのくあぁぁぁ!? ***ASKAちゃん、大地に立つ! -えーと・・・。そんなわけで、これでとりあえず、LinuxでASKAがコンパイルできます。ただ、このままメイクすると、aska.exe になっちゃうんで、 makefile を一部修正。44行目ね。 ・ ・ GC = gcc CFLAGS = -O2 -I. CPPFLAGS = PGNAME = aska.exe # # SRC Directory ・ ・ ''↓'' ・ ・ GC = gcc CFLAGS = -O2 -I. CPPFLAGS = PGNAME = aska # # SRC Directory ・ ・ -さて、それでは一旦クリーンして、いよいよmake。 ~/aska/ensrc$ make clean rm -f .depend a.out core aska rm -f *.o *~ ~/aska/ensrc$ make g++ -O2 -I. -c main.cpp g++ -O2 -I. -c parser.cpp g++ -O2 -I. -c module.cpp g++ -O2 -I. -c generator.cpp g++ -O2 -I. -c filepath.cpp g++ -O2 -I. -c scanner.cpp g++ -O2 -I. -c stringx.cpp g++ -O2 -I. -c table.cpp g++ -O2 -I. -c textmodule.cpp g++ -o aska main.o parser.o module.o generator.o filepath.o scanner.o stringx.o table.o textmodule.o strip aska ~/aska/ensrc$ -うおぉぉ!! ついに、ついにASKA、完成じゃぁぁぁぁぁぁ!!! -ASKAか・・・・ なにもかもがみななつかすい・・・・・(T∀T) *ASKA、新たなる旅立ち -さてさて、そーゆーわけで、ついにASKAがコンパイルできましたが、はたして、これは動くのでしょうか??? -そんなわけで、とりあえず tolset05.lzh に付属の hello0.ask と、hellok0.ask を当ててみました。 ・ ・ ・ ・ SIZE(25){う・・・うごいたぁ・・・・・} *ASKA 発動編---- -そんなわけでコンパイルに成功し、またとりあえず簡単な動作実験を行った。なんかいけそうだ。 -そんな折、T.Takさんからもコンパイル成功の一報が入る。 ---- *一応報告(I.Tak.) -LinuxでASKAをコンパイルだけすることに成功しました。 --module.h(多分): #include <io.h> を #include <sys/io.h> に変更 --module.cpp: filelength関数 (メソッド?) を自作 (fstat関数使用) --generator.cpp, parser.cpp: ltoa, itoa 関数を自作 --main.cpp: usageに入っている ":" を ": " に置換(^^; ---g++ -O2 -c *.cpp ---gcc -O2 -c *.c #Cソースを自作したので ---g++ -o aska *.o -これでバイナリができます。%%でもscanner.PeekTokenがすぐにTK_EOFを返すためか, 何も出力してくれません(T_T たちが悪い… -ちなみにコンパイラは 2.95.4。3.0を使ったら unsigned char[]へのキャストは ISO C++ では禁止だと叱られました。 ---- -うーん、そんなわけなので、私が作った版のパッチを作成して公開。みんなにいろいろな環境で検証してもらうことにした。 COLOR(#009900){・検証作業完了!。すくなくとも、tolset05.lzh に付属の hello0.ask と hellok0.ask に関しては、改行コード以外はまったく同一のファイルを吐き出しました。(うわぁぁぁ!!) -- [[hideyosi]] SIZE(10){2003-07-28 (月) 14:02:13}} COLOR(#009900){・パッチが完成しました。動作実験を行ってくれる勇者は名乗られよ!!。メールで送りますね。もすこし検証してもらって問題なければ、いよいよ一般公開じゃぁ~! ━━━━(゚∀゚)━━━━!! -- [[hideyosi]] SIZE(10){2003-07-28 (月) 14:21:43}} COLOR(#009900){・パッチ希望! 自分でやったら (変にマクロを使ったせいか) 失敗しました…… -- [[I.Tak.]] SIZE(10){2003-07-28 (月) 14:31:15}} COLOR(#009900){・g++ 2.95.3 でコンパイルしたら, 入力をまるで無視するバイナリができました(T^T ↓と同じ症状です。ちなみにDebian(@学校の端末)でやってます。 -- [[I.Tak.]] SIZE(10){2003-07-28 (月) 16:59:02}} COLOR(#009900){・うあぁぁぁ・・・(T∀T) 了解です。ちとこちらでも検証してみます。 -- [[hideyosi]] SIZE(10){2003-07-28 (月) 17:13:26}} COLOR(#009900){・おっかしいですねぇ・・・。うちのデビでは、ちゃんと稼動しますぅ・・。ウチのg++は、2.95.4(今回導入)なんですが・・・。念のため、うちのデビのパッケージリストを更新しましたので、見てみてください。(へんだなぁ・・・・???) -- [[hideyosi]] SIZE(10){2003-07-28 (月) 17:39:58}} COLOR(#009900){・RHL9,compat-gcc-7.3-2.96.118で、CCにgcc296,LDにg++296を指定しました何送っても無視されました。。。(鬱 -- SIZE(10){2003-07-29 (火) 18:09:35}} COLOR(#009900){・ご報告、どうもありがとうございます。ええと、すいません、もう少し詳しくお聞かせねがえませんか。コンパイルは通ったのでしょうか。それとも、出来上がったASKAがおかしいのでしょうか。またもしおかしいのでしたら、なにかメッセージ等出ていませんか。お手数でしょうが、是非お知らせいただけるとありがたいです。どうぞよろしくお願いいたします。 -- [[hideyosi]] SIZE(10){2003-07-29 (火) 18:21:30}} COLOR(#009900){・コンパイルはできても、できあがったASKAが、入出力をしません -- SIZE(10){2003-07-29 (火) 20:12:13}} -うーん・・・。何人かの方から、コンパイルは出来ても動作しないという報告を頂く。おかしいなあ。うちの環境では、どうしても「動作しない」を再現できない。やむなく Debian3.0 や RedHatLinux8.0 をインストールしたりして実験を繰り返してみたが、なにやってもウチではキチンと動作してしまう。 -こまりはてた私は、ヤケクソであっちこっちにデバッグ用の printf を忍ばせたパッチを作って内々に配布してみた。すると・・・・・ COLOR(#009900){・新パッチ動きました (@学校)。hellok0.askなどは処理できました。しかしどうやらASKAはDOSタイプの改行コード(CR+LF)に依存しているようで, ほかのUNIXやMACの改行コードではうんともすんとも言いませんでした。あと最後の行に改行が無いとエラー扱いにされます。オリジナルもこうでしたっけ? (Windowsでしか動かなかったので試したことが無い) -- [[I.Tak.]] SIZE(10){2003-07-31 (木) 16:37:27}} -I.Takさんからとんでもないヒントが飛び込んできた。もしやと思い、テスト用の hello0.ask の改行コードを全てUNIX型にしてASKAに当ててみる。・・・・うわぁ!!!。ウチでも、まったく動作しない!!! -どうやら原因はこれ臭い。そんなわけで、さっそく改行コードの処理をしている部分を探してみる。(ここいら辺は、Cの知識がない私にはかなりつらかったぁ・・・) -見つけた!。module.cpp の最後のほう。 HRESULT Module::ReadLine(LPSTR buf){ int i; if(lpMdlPos == NULL) return 3; if(lpMdlPos >= (LPSTR)lpMdlAdr + dwMdlSize) return 1; for(i = 0; i < 1023; i++){ if(*lpMdlPos == 0x0D && *(lpMdlPos+1) == 0x0A){ *buf = '\0'; lpMdlPos += 2; return 0; // 1行終了 } *(buf++) = *(lpMdlPos++); } *buf = '\0'; return 2; // バッファあふれ } -ううん・・・・。だめだ、よくわかんない。あてずっぽうで、以下のように変更。 HRESULT Module::ReadLine(LPSTR buf){ int i; if(lpMdlPos == NULL) return 3; if(lpMdlPos >= (LPSTR)lpMdlAdr + dwMdlSize) return 1; for(i = 0; i < 1023; i++){ // if(*lpMdlPos == 0x0D && *(lpMdlPos+1) == 0x0A){ if(*lpMdlPos == 0x0D && *(lpMdlPos+1) == 0x0A){ *buf = '\0'; lpMdlPos += 2; return 0; // 1行終了(DOS) } if(*lpMdlPos == 0x0A || *lpMdlPos == 0x0D){ *buf = '\0'; lpMdlPos += 1; return 0; // 1行終了(UNIX or MAC) } *(buf++) = *(lpMdlPos++); } *buf = '\0'; return 2; // バッファあふれ } -こんな変更をしたパッチを作り、再びテスト隊にみなさんに実験してもらう。 COLOR(#009900){・動きました。簡単なソースを処理させましたが, 三種の改行コードをみな認識できてます。しかし, 改行コードなしの行でソースが終わる場合誤動作します (運がいいとしませんが)。つうわけで(^^; 適当に(オリジナルに対する) パッチをまとめつつ修正してみました。http://user.ecc.u-tokyo.ac.jp/~g240845/osask/lzh/aska_test-0.0.2.patch.gz 使い方はファイルの先頭に書いてあります。 -- [[I.Tak.]] SIZE(10){2003-08-01 (金) 11:12:07}} -キタ━━━━(゚∀゚)━━━━ッ!! -I.Takさんから動作確認がきました。しかも、最後まで残っていた(つーか、私の技量では治せない)EOF問題も解決している模様! -さらにすごいオマケがついている。私がこれまで当てずっぽうで行ってきた修正が、I.Takさんの手によってとてもきれいで洗練されたものに清書されている。うわぁぁぁ!なるほど!そうか。こうやればいいのか。勉強になるぅーー! *ASKA めぐり合い宇宙編 -これで、ほぼASKAをLinuxに移植することは成功だと思う。(逆に、これ以上の部分に問題があった場合、もうそろそろ私には手におえないものだろう。) -I.Takさんが最後に清書してくれた版を、ASKAのページにて公開している。現在は、最後の動作実験のためtest版だが、おそらくこれが完成版となるだろう。 -この検証が終われば、I.Takさんが書いてくれたhistoryやらなんやらもひとまとめにして、Kタンに「どんなもんじゃろ?これ?」と提案してみるつもりである。
(This host) = http://osask.net