FreyaSX開発メモ(3) -- 17 June, 2004, Yutaka Sato

移植作業

開発メモ(1)でも書きましたように、Freyaの移植作業は最初にMacOSX上の gcc-3.1 で行ったのですが、その後ついでにということで Linux や 別の 構成の gccでも通るように少しずつ修正を追加しました。それぞれの環境 ごとに、かなりコンパイルエラーの発生状況が異なりましたので、 いずれでも通るようにするために、多少の行ったり来たりが必要でした。

これまでのところ、以下のコンパイル環境を用いて FreyaSX を作成できて います。また、実行もできる(たぶん問題無さそうだ)ということも、 簡単にですが確かめました。

  1) gcc 3.1  on MacOS X 10.2
  2) gcc 3.3  on MacOS X 10.3
  3) gcc 2.96 on Linux RedHat 7.1
  4) gcc 3.3  on Linux (Zaurus)
  5) gcc 2.95 on MacOS X 10.2 for ARM-Linux (cross compiler for Zaurus)
移植のために行った変更点をまとめると表1のようになります。 これらは、Freya が開発終了して以降の gcc (特に3.x以降) の問題と、 機種依存あるいは実装依存の問題からなります。 少し苦労したのは後者で、これは実行して動作を追跡して、その意味を 理解しないと原因がわからないため、結構手間がかかりました。 なんだかんだで全体で正味1週間くらいかかってしまったような気がします。

苦労したところ

いちばん苦労したのは a) の fstream の seek 問題です。 とりあえず make が通って実行形式ができたので、やれやれと、索引を 作ってみて、検索プログラム(fsearch)で検索してみると、なんだか "internal error" というのが出て、結果を全て表示できません。 再現と追跡が簡単なように、テスト用に10件ばかりの小さな索引を作り、 プログラムのあちこちに動作トレース用のprint関数を挟んで (cerr<<とかいうのがどうも馴染めませんで:p) 動作を見ていきました。 とにかく最初は Freya の全体のつくりや動きがどうなっているか ほとんどわかりませんし、なにかすごく複雑な問題が起きているのかと 思っていました。

ですが、追跡してゆくと、どうやら単にファイルからレコードを読み 込むことに失敗しているのが原因で、それはどうやらファイルに ランダムアクセスするためのseekに失敗しているからでした。結局、 ファイルの末尾のレコードを読み込んだ時にEOFになって、それを クリアしてやらないとseekg()が失敗する、ということがわかりました。 最終的にこれだと突き止めるのにまる一日ばかり。

ファイルの最後のデータを読んだ時に (さらにその先まで読もうとはして いないのに) EOF状態がオンになる (eof() が 1 になる) というのは、 理解できない仕様(?)です。 この状況は MacOSX + gcc3.1 で発生しますが、例えば gcc 2.96 on Linux では起こりません。gcc の実装のバグかも知れません。

まあ原因はわかったらからいいやと、全ての seekg() の前に clear() を するようにしました。この時、seekp() も同様にするかどうするかは迷い、 一旦そのようにしたのですが、書き込みの場合にはそういう問題は起こら ないだろうと思い、不必要な変更は避けたいと思ったので止めました。 ところが、後日、索引の作成 (findex) で "internal error" が起こって いるのを見つけました。 結局これも seekp() の問題だったのですが、seekg() の件からすでに数日 以上経過していて、忘れてしまっていたのかも知れません。問題を突き 止めるのに、またも一日、無駄に食ってしまいました。 (どうして seekp() がエラーになるのか、原因の追求はしていません)

これとは別に少してこずったのが、b) の「fstream の get() が型エラーを 起こすという」問題です(gcc-3.3)。元のプログラムは以下のようになって います。

  unsigned char key;
  file.get(key);
エラーを回避するために、最初は素直に、
  char skey;
  unsigned char key;
  file.get(skey);
  key = skey;
のように変更して、エラーも警告も出なくなり、問題なく動きました。 しかしその後、もっとシンプルにと思い、
  unsigned char key;
  file.get((char)key);
に変更しました。これを MacOSX上の gcc-3.1 に戻しても、エラーも警告も 出ず、問題なく動きました。実は、この時はたまたま、移植作業中の コンパイル待ちを短くするようにと、最適化オプションを外してコンパイル していたのです。 ところが、後日、開発メモ(2) の高速化作業を行う際に、最適化オプションを 付けてコンパイルしたら、なにか動作がおかしくなりました。その時には、 -O を付けたのがおかしくなった原因だということもすぐにはわからず、 さらには、動作を追跡してこの部分が原因であることを突き止めるのにも、 少し手間がかかってしまいました。 後になって、gcc-3.3で -O付きで上記の文をコンパイルすると「key が初期化 されずに使われるかも知れない」という警告が出ていることがわかりました。 なぜそのようになるのかは不明ですが。 ともかく、最初の変更の形に戻して一件落着としました。

コンパイルの段階で、ちょっとひっかかってしまったのが一件あります。 これは XMap.c中で使われている mmap() 関数の戻り値の代入の際の型不一致 の問題です。

  27 mapaddr = mmap(NULL,
              ...
  31            fd,
  32            (off_t)0 );
そのエラーメッセージは、
  XMap.cc:32: cannot convert `void *' to `char *' in assignment
というものでした。32行目を見ると、他でも型が問題になっていたファイルの オフセット情報が引数として渡されているので、これが問題だと思ってしまい、 いろいろキャストしてみたりしたのですが、どうにもエラーを回避できません。 結局これは assignment で問題が起きているのだということに気づくのに かなり時間がかかってしまいました。gcc 以外でもそうなのかどうかわかり ませんが、こういう場合って、実際に代入がある行 (ここでは27行目の "=") の行番号を表示して欲しいものだと思ったりしました。

今回のまとめ

もう結構な歳なので、他人の作ったプログラムを移植する作業というのは ちょっとつらいかと思ったのですが、それほどの苦痛でもありませんでした。 また、この作業をはじめるまで、C++ のことはほとんど知りませんでしたが、 移植の作業をしているうちに、だいたいわかるようになったのも、当初の もくろみどおりでした。まあしかし、C++ で書くと何が有難いのかという ことは、いまいちわかりませんでしたけど:p

Gcc 方面はかなり拓けた感じになりました。あとは Win32 (VC++) への移植を やるかどうかですが。。。 個人的には DeleGate の移植で Win32 ではずいぶん無駄に人生を使って しまったと感じています。ただ苦労しただけで、ほとんど得られるものは ありませんでした。Mac は Unix に乗って起死回生の復活を遂げるという、 なかなか素敵なことをやってくれました。Windowsでも、いずれそのような ことが起こらないとも限りませんから、その日を待とうかと思います。 まあ、滅亡してくれちゃったら、それはそれで有難いんですが:p


------------------------------------------------------------------------
表1. Freya移植のための変更点一覧


a) fstream が一旦EOFになった状態からseekg(),seekp()できず失敗する
 (DescFile.cc, IndexFile.cc, Indexer.cc, LexiconFile.cc, fmerge.cc, patricia.cc)
 → 全ての seekg(), seekp() の前に clear() を挿入。

b) fstream の get(unsigned char) で型エラー
 (patricia.c)
 → 一旦 signed char に読んでから、unsigned char に代入。

c) fstream のrdbuf()->fd が廃止された
 (IndexFile.cc, fmerge.cc)
 →  fstat(rdbuf()->fd)でファイルサイズを検査するのを止めて、seek() と tell()で検査するように変更。

d) fstream の第3引数(open mode flag)が廃止された
 (Indexer.cc, findex.cc, fmkmorphdic.cc)
 →  モードを 0666 にするために使われているが、デフォルトの 0664 で構わないと思うので、第3引数を削除。

e) strstream が廃止された?
 (fsearchcgi.cc)
 →  stringstream で置き換え。

f) ostream の write, istream の read の第一引数の型が char* でないと失敗する
 (IndexFile.cc, Indexer.cc, LexiconEntry.cc, LexiconFile.cc, fsearchcgi.cc, patricia.cc)
 →  ひたすらキャスト。

g) and, or, not が予約語?になった
 (Evaluator.h, Evaluator.cc, Expression.cc)
 それぞれ And, Or, Not に書き換え。

h) 代入時に void* から char* への自動キャストが行われない (2.96)
 (XMap.cc)
 →  明示的にキャスト。

i) fstream の gcount() や tellg() を size_t と比較する時の警告
 (DescFile.cc, IndexFile.cc, LexiconFile.cc)
 →  キャスト。

------------------------------------------------------------------------
表2. 動作確認環境の詳細

  1) gcc 3.1  on MacOS X 10.2
  Reading specs from /usr/libexec/gcc/darwin/ppc/3.1/specs
  Thread model: posix
  Apple Computer, Inc. GCC version 1175, based on gcc version 3.1 20020420 (prerelease)

  2) gcc 3.3  on MacOS X 10.3
  Reading specs from /usr/libexec/gcc/darwin/ppc/3.3/specs
  Thread model: posix
  gcc version 3.3 20030304 (Apple Computer, Inc. build 1495)
 
  3) gcc 2.96 on Linux RedHat 7.1
  Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/2.96/specs
  gcc version 2.96 20000731 (Red Hat Linux 7.1 2.96-81)

  4) gcc 3.3  on Linux (Zaurus)
  Reading specs from /usr/local/gnu/lib/gcc-lib/arm-linux/3.3.2/specs
  Configured with: ../gcc-3.3.2/configure --build=i686-pc-linux --host=arm-linux --prefix=/usr/local/gnu --with-cpu=xscale --enable-shared --enable-languages=c++
  Thread model: posix
  gcc version 3.3.2

  5) gcc 2.95 on MacOS X 10.2 for ARM-Linux (cross compiler for Zaurus)
  Reading specs from /Developer/Zaurus-X-gcc/opt/Embedix/tools/lib/gcc-lib/arm-linux/2.95.3/specs
  gcc version 2.95.3 20010315 (release)

------------------------------------------------------------------------

diff -cr ../freya-0.92.4/src/DescFile.cc ./src/DescFile.cc
*** ../freya-0.92.4/src/DescFile.cc	Fri May  8 00:56:24 1998
--- ./src/DescFile.cc	Mon May 31 05:37:16 2004
***************
*** 15,23 ****
--- 15,27 ----
  int
  DescFile::getRecord(DescRecord &rec, int nth){
      char buf[blksize];
+     file.clear();
      file.seekg(blksize * nth);
      file.read(buf, blksize);
+ /*
      if(file.gcount() != (size_t)blksize){
+ */
+     if((size_t)file.gcount() != (size_t)blksize){
          PRINTERRMSG("read error occured while reading .dsc record.");
          return 0;
      }
diff -cr ../freya-0.92.4/src/DescRecord.cc ./src/DescRecord.cc
*** ../freya-0.92.4/src/DescRecord.cc	Thu May 25 16:01:04 2000
--- ./src/DescRecord.cc	Sun Jun 13 13:28:45 2004
***************
*** 8,13 ****
--- 8,14 ----
  #include <stdlib.h>
  #include <sys/param.h>
  #include <arpa/inet.h>
+ #include <netinet/in.h> // ntohl()
  }
  #include "DescRecord.h"
  #include "htmlutil.h"
diff -cr ../freya-0.92.4/src/Evaluator.cc ./src/Evaluator.cc
*** ../freya-0.92.4/src/Evaluator.cc	Fri May  8 00:56:24 1998
--- ./src/Evaluator.cc	Sun Jun 13 17:28:12 2004
***************
*** 10,16 ****
--- 10,19 ----
  #include "Evaluator.h"
  
  int
+ /*
  Evaluator::and(Result *dst, int dstLen, const Result *src, int srcLen) const {
+ */
+ Evaluator::And(Result *dst, int dstLen, const Result *src, int srcLen) const {
      if(dst == NULL || dstLen == 0 || src == NULL || srcLen == 0)
          return 0;
      int r = 0;
***************
*** 35,41 ****
--- 38,47 ----
  
  
  int
+ /*
  Evaluator::not(Result *dst, int dstLen, const Result *src, int srcLen) const {
+ */
+ Evaluator::Not(Result *dst, int dstLen, const Result *src, int srcLen) const {
      if(src == NULL || srcLen == 0 || dstLen == 0)
          return dstLen;
      
***************
*** 58,64 ****
--- 64,73 ----
  
  
  int
+ /*
  Evaluator::or(Result *dst, const Result *src1, int srcLen1,
+ */
+ Evaluator::Or(Result *dst, const Result *src1, int srcLen1,
             const Result *src2, int srcLen2) const {
      if(src2 == NULL || srcLen2 == 0){
          if(src1 == NULL || srcLen1 == 0) return 0;
diff -cr ../freya-0.92.4/src/Evaluator.h ./src/Evaluator.h
*** ../freya-0.92.4/src/Evaluator.h	Fri May  8 00:56:23 1998
--- ./src/Evaluator.h	Sun Jun 13 17:27:24 2004
***************
*** 10,20 ****
--- 10,29 ----
  public:
      Evaluator() { }
      virtual ~Evaluator() { }
+ /*
      virtual int and(Result *dst, int dstLen,
+ */
+     virtual int And(Result *dst, int dstLen,
                      const Result *src, int srcLen) const;
+ /*
      virtual int not(Result *dst, int dstLen,
+ */
+     virtual int Not(Result *dst, int dstLen,
                      const Result *src, int srcLen) const;
+ /*
      virtual int or(Result *dst, const Result *src1, int srcLen1,
+ */
+     virtual int Or(Result *dst, const Result *src1, int srcLen1,
                     const Result *src2, int srcLen2) const;
      virtual int rank(Result *result, int resultLen) const;
  };
diff -cr ../freya-0.92.4/src/Expression.cc ./src/Expression.cc
*** ../freya-0.92.4/src/Expression.cc	Fri May  8 00:56:24 1998
--- ./src/Expression.cc	Thu Jun 17 07:29:28 2004
***************
*** 224,230 ****
--- 224,233 ----
              required = tmp;
              requiredLen = tmpLen;
          }else{
+ /*
              requiredLen = evaluator.and(required, requiredLen, tmp, tmpLen);
+ */
+             requiredLen = evaluator.And(required, requiredLen, tmp, tmpLen);
              if(requiredLen == 0){   // not found
                  delete []tmp;
                  delete []required;
***************
*** 247,257 ****
--- 250,267 ----
                  basic = tmp;
                  basicLen = tmpLen;
              }else{
+ /*
                  Result *or = new Result[basicLen + tmpLen];
                  int orLen = evaluator.or(or, basic, basicLen, tmp, tmpLen);
+ */
+                 Result *Or = new Result[basicLen + tmpLen];
+                 int orLen = evaluator.Or(Or, basic, basicLen, tmp, tmpLen);
                  delete []basic;
                  delete []tmp;
+ /*
                  basic = or;
+ */
+                 basic = Or;
                  basicLen = orLen;
              }
          }
***************
*** 260,266 ****
--- 270,279 ----
      // (3) multiply (1) and (2)
      if(required){
          if(basic){
+ /*
              requiredLen = evaluator.and(required, requiredLen, basic, basicLen);
+ */
+             requiredLen = evaluator.And(required, requiredLen, basic, basicLen);
              delete []basic;
          }
      }else{
***************
*** 284,290 ****
--- 297,306 ----
          int tmpLen;
          Result *tmp = queries[i]->eval(ret, tmpLen);
          if(tmp){
+ /*
              requiredLen = evaluator.not(required, requiredLen, tmp, tmpLen);
+ */
+             requiredLen = evaluator.Not(required, requiredLen, tmp, tmpLen);
              delete []tmp;
              if(requiredLen == 0){ // not found
                  delete []required;
***************
*** 335,341 ****
--- 351,360 ----
              delete []result1;
              return NULL;        // not found
          }
+ /*
          resultLen = evaluator.and(result1, resultLen1, result2, resultLen2);
+ */
+         resultLen = evaluator.And(result1, resultLen1, result2, resultLen2);
          delete []result2;
          if(resultLen == 0){
              delete []result1;
diff -cr ../freya-0.92.4/src/IndexFile.cc ./src/IndexFile.cc
*** ../freya-0.92.4/src/IndexFile.cc	Fri May  8 00:56:24 1998
--- ./src/IndexFile.cc	Sun Jun 13 13:31:54 2004
***************
*** 18,23 ****
--- 18,32 ----
  
  char IndexFile::MAGIC[] = "_FREYAIDXFILE_\n"; // 16 bytes
  
+ int fileSize(fstream &file)
+ {
+         streampos spos = file.tellg();
+         file.seekg(0, ios::end);
+         off_t filesize = file.tellg();
+         file.seekg(spos);
+         return filesize;
+ }
+ 
  IndexFile::IndexFile(fstream &file, int rdonlyp, int newfilep)
      : idxfile(file), readonlyp(rdonlyp), blockNum(0)
  {
***************
*** 26,34 ****
--- 35,46 ----
  
      if(! newfilep){
          // read table from the file tail
+ /*
          struct stat fstatus;
          fstat(idxfile.rdbuf()->fd(), &fstatus);
          off_t filesize = fstatus.st_size;
+ */
+         off_t filesize = fileSize(idxfile);
          // cerr << "filesize = " << filesize << endl;
  
          int tailblkNum; // 全体がtail tableとして使われているブロックの数
***************
*** 48,54 ****
--- 60,69 ----
              PRINTERRMSG("MAGIC check fail!");
          }else{
              // idxfile.seekg(0);
+ /*
              idxfile.read(freeSizeTbl, sizeof(freeSizeTbl[0]) * blockNum);
+ */
+             idxfile.read((char*)freeSizeTbl, sizeof(freeSizeTbl[0]) * blockNum);
              assert(sizeof(freeSizeTbl[0]) * blockNum ==
                     filesize - blockNum*BLOCKSIZE - sizeof(MAGIC));
          }
***************
*** 58,67 ****
--- 73,86 ----
  IndexFile::~IndexFile(){
      if(! readonlyp){
          //cout << "write MAGIC, blockNum =" << blockNum << endl;
+         idxfile.clear();
          idxfile.seekp(blockNum * BLOCKSIZE, ios::beg);
          idxfile.clear();
          idxfile.write(MAGIC, sizeof(MAGIC));
+ /*
          idxfile.write(freeSizeTbl, blockNum * sizeof(freeSizeTbl[0]));
+ */
+         idxfile.write((char*)freeSizeTbl, blockNum * sizeof(freeSizeTbl[0]));
      }
      idxfile.close();
      if(freeSizeTbl) delete []freeSizeTbl;
***************
*** 359,372 ****
--- 378,396 ----
  // キャッシュを実装する際はoverrideする
  int
  IndexFile::readBlock(char *buf, blockno_t bn, size_t size){
+     idxfile.clear();
      idxfile.seekg(bn * BLOCKSIZE, ios::beg);
      idxfile.read(buf, size);
+ /*
      if(idxfile.gcount() != size) return -1;
+ */
+     if((size_t)idxfile.gcount() != (size_t)size) return -1;
      return idxfile.rdstate();   // エラーがなければ 0
  }
  
  int
  IndexFile::writeBlock(const char *buf, blockno_t bn, size_t size){
+     idxfile.clear();
      idxfile.seekp(bn * BLOCKSIZE, ios::beg);
      idxfile.clear();
      idxfile.write(buf, size);
diff -cr ../freya-0.92.4/src/Indexer.cc ./src/Indexer.cc
*** ../freya-0.92.4/src/Indexer.cc	Mon Jun 22 01:10:54 1998
--- ./src/Indexer.cc	Thu Jun 17 07:30:03 2004
***************
*** 82,89 ****
--- 82,93 ----
              lastoffset = typeoffset[i + 1];
          }
      }
+ /*
      xmapfile.write(&base, sizeof(base));
      xmapfile.write(typerange, sizeof(typerange));
+ */
+     xmapfile.write((char*)&base, sizeof(base));
+     xmapfile.write((char*)typerange, sizeof(typerange));
      // 初期化しておく
      for(i = 0; i < XMap::TYPENUM + 1; i++)
          typeoffset[i] = 0;
***************
*** 94,101 ****
--- 98,109 ----
      static short int scores[XMap::TYPENUM]
          = { WEIGHT_URL, WEIGHT_TITLE, WEIGHT_AUTHOR,
              WEIGHT_KEYWORD, WEIGHT_TEXTW1, WEIGHT_TEXTW2 };
+ /*
      xmapfile.write(&offset, sizeof(offset));
      xmapfile.write(scores, sizeof(scores));
+ */
+     xmapfile.write((char*)&offset, sizeof(offset));
+     xmapfile.write((char*)scores, sizeof(scores));
  }
  
  void
***************
*** 261,271 ****
--- 269,284 ----
      char idxfilename[PATH_MAX];
      int no;
  
+     xmapfile.clear();
      xmapfile.seekp(0);
      for(no = 0; no <= 999; no++){
          makefilename(lexfilename, idxfilename, basename, no);
+ /*
          fstream lexfile(lexfilename, ios::in|ios::out|ios::trunc, 0666);
          fstream idxfile(idxfilename, ios::in|ios::out|ios::trunc, 0666);
+ */
+         fstream lexfile(lexfilename, ios::in|ios::out|ios::trunc);
+         fstream idxfile(idxfilename, ios::in|ios::out|ios::trunc);
          if(lexfile.good() && idxfile.good()){
              LexiconFile lexicon(lexfile, 0, 1); // !readonly, newfile
              CachedIndexFile indexfile(8, idxfile, 0, 1); // !readonly, newfile
diff -cr ../freya-0.92.4/src/LexiconEntry.cc ./src/LexiconEntry.cc
*** ../freya-0.92.4/src/LexiconEntry.cc	Fri May  8 00:56:24 1998
--- ./src/LexiconEntry.cc	Thu May 27 19:47:31 2004
***************
*** 170,176 ****
--- 170,179 ----
          assert(entry.valueNum <= 5);
          stream << entry.key;
          stream << (char)(LexiconEntry::ENTITYENTRY1 - 1 + entry.valueNum);
+ /*
          stream.write(entry.values, sizeof(pos_t) * entry.valueNum);
+ */
+         stream.write((char*)entry.values, sizeof(pos_t) * entry.valueNum);
      }else{
          if(entry.bn == (blockno_t)-1){ // type A
              cerr << "Warning: null entry! " << entry.key << endl;
***************
*** 180,191 ****
--- 183,201 ----
              //cerr << "output external : " << entry.key << endl;
              stream << entry.key;
              stream << (char)LexiconEntry::XREFERENCEENTRY;
+ /*
              stream.write(&entry.bn, sizeof(entry.bn));
+ */
+             stream.write((char*)&entry.bn, sizeof(entry.bn));
          }else{                  // type B
              stream << entry.key;
              stream << (char)LexiconEntry::REFERENCEENTRY;
+ /*
              stream.write(&entry.bn, sizeof(entry.bn));
              stream.write(&entry.rn, sizeof(entry.rn));
+ */
+             stream.write((char*)&entry.bn, sizeof(entry.bn));
+             stream.write((char*)&entry.rn, sizeof(entry.rn));
          }
      }
  
***************
*** 225,237 ****
--- 235,254 ----
          entry.valueNum = 0;
          break;
      case LexiconEntry::XREFERENCEENTRY:
+ /*
          stream.read(&entry.bn, sizeof(entry.bn));
+ */
+         stream.read((char*)&entry.bn, sizeof(entry.bn));
          entry.rn = (recno_t)-1;
          entry.valueNum = 0;
          break;
      case LexiconEntry::REFERENCEENTRY:
+ /*
          stream.read(&entry.bn, sizeof(entry.bn));
          stream.read(&entry.rn, sizeof(entry.rn));
+ */
+         stream.read((char*)&entry.bn, sizeof(entry.bn));
+         stream.read((char*)&entry.rn, sizeof(entry.rn));
          entry.valueNum = 0;
          break;
      case LexiconEntry::ENTITYENTRY1:
***************
*** 241,247 ****
--- 258,267 ----
      case LexiconEntry::ENTITYENTRY5:
          entry.valueNum = entrytype - LexiconEntry::ENTITYENTRY1 + 1;
          entry.values = new pos_t[entry.valueNum];
+ /*
          stream.read(entry.values, sizeof(pos_t) * entry.valueNum);
+ */
+         stream.read((char*)entry.values, sizeof(pos_t) * entry.valueNum);
          break;
      default:
          PRINTERRMSG("Unexpected sequence found! (while reading Lexicon file)");
diff -cr ../freya-0.92.4/src/LexiconFile.cc ./src/LexiconFile.cc
*** ../freya-0.92.4/src/LexiconFile.cc	Thu May 25 16:38:40 2000
--- ./src/LexiconFile.cc	Thu Jun 17 16:39:43 2004
***************
*** 62,67 ****
--- 62,68 ----
  
  int
  LexiconFile::readHeader(){
+     file.clear();
      file.seekg(0);
      file.clear();
      file.read(headerbuf, HEADERSIZE);
***************
*** 73,84 ****
--- 74,93 ----
          PRINTERRMSG("Invalid lexicon file! Please check the file.");
          return 2;
      }
+ /*
      file.read(offsetTbl, 65536 * sizeof(offsetTbl[0]));
+ */
+     file.read((char*)offsetTbl, 65536 * sizeof(offsetTbl[0]));
  
      filesize = *(size_t *)(headerbuf + sizeof(MAGIC));
  #if 1
+ /*
      file.seekg((streamoff) 0, ios::end);
      if(file.tellg() != (int)filesize){
+ */
+     file.clear();
+     file.seekg(0, ios::end);
+     if((size_t)file.tellg() != (size_t)filesize){
          filesize = file.tellg();
      }
  #endif
***************
*** 88,103 ****
--- 97,117 ----
  
  int
  LexiconFile::writeHeader(){
+     file.clear();
      file.seekp(0);
      file.clear();
      *(size_t *)(headerbuf + sizeof(MAGIC)) = filesize;
      file.write(headerbuf, HEADERSIZE);
+ /*
      file.write(offsetTbl, 65536 * sizeof(offsetTbl[0]));
+ */
+     file.write((char*)offsetTbl, 65536 * sizeof(offsetTbl[0]));
      return file.fail();
  }
  
  istream &
  LexiconFile::rewind(){
+     file.clear();
      file.seekg(HEADERSIZE + sizeof(offsetTbl[0]) * 65536);
      return file;
  }
***************
*** 105,110 ****
--- 119,125 ----
  void
  LexiconFile::prepareAppend(){
      memset(offsetTbl, 0, 65536 * sizeof(offsetTbl[0]));
+     file.clear();
      file.seekp(HEADERSIZE + sizeof(offsetTbl[0]) * 65536);
      file.clear();
  }
***************
*** 135,140 ****
--- 150,156 ----
      if(0 == findRegion(key, from, to))
          return 0;
      //cout << "LexiconFile::search: from = " << from << " to = " << to << endl;
+     file.clear();
      file.seekg(from);
      while(file.tellg() < (streampos)to){
          LexiconEntry entry;
***************
*** 164,169 ****
--- 180,186 ----
          return NULL;
  
      int keyLen = strlen(key);
+     file.clear();
      file.seekg(from);
      LexiconEntry *entryp;
      while(file.tellg() < (streampos)to){
***************
*** 194,199 ****
--- 211,217 ----
          return 0;               // not found
      //cout << "LexiconFile::findPrefix: from = " << from
      //     << " to = " << to << endl;
+     file.clear();
      file.seekg(from);
      int matchLen = 0;
      while(file.tellg() < (streampos)to){
diff -cr ../freya-0.92.4/src/XMap.cc ./src/XMap.cc
*** ../freya-0.92.4/src/XMap.cc	Fri May  8 00:56:24 1998
--- ./src/XMap.cc	Thu May 27 19:54:36 2004
***************
*** 24,30 ****
--- 24,33 ----
      fstat(fd, &st);
      mapsize = st.st_size;
      entryNum = mapsize / ENTRYSIZE - 1;
+ /*
      mapaddr = mmap(NULL,        // start address (hint)
+ */
+     mapaddr = (caddr_t)mmap(NULL,        // start address (hint)
                     mapsize,     // size
                     PROT_READ,   // protection
                     MAP_SHARED,  // flags
diff -cr ../freya-0.92.4/src/findex.cc ./src/findex.cc
*** ../freya-0.92.4/src/findex.cc	Fri May  8 00:56:24 1998
--- ./src/findex.cc	Thu Jun 17 07:32:38 2004
***************
*** 86,92 ****
--- 86,95 ----
      // prepare xmap
      char xmappath[PATH_MAX];
      strcpy(xmappath, outputbase); strcat(xmappath, ".map");
+ /*
      fstream xmapfile(xmappath, ios::in|ios::out|ios::trunc, 0666);
+ */
+     fstream xmapfile(xmappath, ios::in|ios::out|ios::trunc);
      if(! xmapfile.good()){
          PRINTERRMSG("cannot create a translation map file.\n");
          cerr << "  xmappath = \"" << xmappath << "\"\n";
diff -cr ../freya-0.92.4/src/fmerge.cc ./src/fmerge.cc
*** ../freya-0.92.4/src/fmerge.cc	Fri May  8 00:56:24 1998
--- ./src/fmerge.cc	Sun Jun 13 13:32:00 2004
***************
*** 18,23 ****
--- 18,25 ----
  #include "CachedIndexFile.h"
  #include "Indexer.h"
  
+ extern int fileSize(fstream&);
+ 
  char *
  mystrdup(const char *str){
      int l = strlen(str);
***************
*** 37,42 ****
--- 39,45 ----
  int
  mergedsc(ostream &newdscfile, char *dscfilenames[], int *ndocs, int n){
      cout << "merging descriptions " << flush;
+     newdscfile.clear();
      newdscfile.seekp(0);
      for(int i = 0; i < n; i++){
          fstream dscfile(dscfilenames[i], ios::in);
***************
*** 46,54 ****
--- 49,60 ----
              cerr << "  filename = \"" << dscfilenames[i] << '"' << endl;
              return i + 1;
          }
+ /*
          struct stat fstatus;
          fstat(dscfile.rdbuf()->fd(), &fstatus);
          off_t filesize = fstatus.st_size;
+ */
+         off_t filesize = fileSize(dscfile);
          ndocs[i] = filesize / DSCBLOCKSIZE;
          
          cout << '.' << flush;
***************
*** 74,79 ****
--- 80,86 ----
          sizeof(short_size_t) * XMap::TYPENUM;
      char entry[entrysize];
      size_t newlastoffset = 0;
+     newmapfile.clear();
      newmapfile.seekp(0);
      for(int i = 0; i < n; i++){
          fstream mapfile(mapfilenames[i], ios::in);
***************
*** 83,91 ****
--- 90,101 ----
              cerr << "  filename = \"" << mapfilenames[i] << '"' << endl;
              return i + 1;
          }
+ /*
          struct stat fstatus;
          fstat(mapfile.rdbuf()->fd(), &fstatus);
          off_t filesize = fstatus.st_size;
+ */
+         off_t filesize = fileSize(mapfile);
          ndocs[i] = filesize / entrysize - 1;
          
          cout << '.' << flush;
diff -cr ../freya-0.92.4/src/fmkmorphdic.cc ./src/fmkmorphdic.cc
*** ../freya-0.92.4/src/fmkmorphdic.cc	Fri May  8 00:56:24 1998
--- ./src/fmkmorphdic.cc	Mon May 17 14:32:36 2004
***************
*** 68,74 ****
--- 68,77 ----
          source.close();
      }
  
+ /*
      fstream patfile(argv[2], ios::out|ios::trunc, 0666);
+ */
+     fstream patfile(argv[2], ios::out|ios::trunc);
      cout << "saving dictionary as file: " << argv[2] << endl;
  	int size = pat.save(patfile);
      if(patfile.good()){
diff -cr ../freya-0.92.4/src/fsearch.cc ./src/fsearch.cc
*** ../freya-0.92.4/src/fsearch.cc	Fri May  8 00:56:24 1998
--- ./src/fsearch.cc	Thu Jun 17 07:33:30 2004
***************
*** 3,9 ****
--- 3,11 ----
  // $Id: fsearch.cc,v 0.12 1998-01-24 23:48:10+09 harada Exp $
  //
  #include <iostream.h>
+ /*
  #include <strstream.h>
+ */
  extern "C" {
  #include <assert.h>
  #include <unistd.h>
diff -cr ../freya-0.92.4/src/fsearchcgi.cc ./src/fsearchcgi.cc
*** ../freya-0.92.4/src/fsearchcgi.cc	Thu May 25 16:30:05 2000
--- ./src/fsearchcgi.cc	Thu Jun 17 07:51:55 2004
***************
*** 2,10 ****
--- 2,18 ----
  //
  // $Id: fsearchcgi.cc,v 0.15 1998-01-27 12:30:30+09 harada Exp $
  //
+ /*
  #include <iostream.h>
  #include <strstream.h>
+ */
+ #include <iostream>
+ #include <sstream>
+ #include <string>
+ using namespace std;
+ 
  extern "C" {
+ #include <stdio.h>
  #include <assert.h>
  #include <errno.h>
  #include <unistd.h>
***************
*** 78,84 ****
--- 86,95 ----
               "%d %b %Y %H:%M:%S %Z", localtime(&now));
  
      if(NULL == query || '\0' == query[0]) query = "-";
+ /*
      ostrstream line;
+ */
+     stringstream line;
      line << datebuf << ' ' << host << ' ' << user << ' '
           << param_index << ' ' << param_style << ' '
           << resultNum << ' ' << param_from << ' ' << param_n << ' '
***************
*** 89,100 ****
--- 100,119 ----
      errno = 0;
      if(0 != takeLock(fd)) return -1;
  
+ /*
      char *linestr = line.str();
+ */
+     string linestr = line.str();
      lseek(fd, 0, SEEK_END);
+ /*
      write(fd, linestr, strlen(linestr));
+ */
+     write(fd, linestr.c_str(), linestr.length());
      releaseLock(fd);
      close(fd);
+ /*
      delete []linestr;
+ */
  
      return errno;
  }
***************
*** 131,141 ****
--- 150,169 ----
      html_entitize(qtitle, title);
      html_entitize(qerrormsg, errormsg);
      html_entitize(qquery, query);
+ /*
      ostrstream numstr, dispnumstr;
+ */
+     stringstream numstr, dispnumstr;
      numstr << ' ' << resultNum << '\0';
+ /*
      char *resultnum = numstr.str();
+ */
+     string resultnum = numstr.str();
      dispnumstr << param_n << '\0';
+ /*
      char *dispnum = dispnumstr.str();
+ */
+     string dispnum = dispnumstr.str();
  
      char linebuf[LINE_MAX];
      for(;;){
***************
*** 150,163 ****
--- 178,199 ----
          replace_string(linebuf, "$errormsg", qerrormsg);
          replace_string(linebuf, "$query", qquery);
          replace_string(linebuf, "$index", param_index);
+ /*
          replace_string(linebuf, "$result", resultnum);
+ */
+         replace_string(linebuf, "$result", resultnum.c_str());
          replace_string(linebuf, "$style", param_style);
+ /*
          replace_string(linebuf, "$dispnum", dispnum);
+ */
+         replace_string(linebuf, "$dispnum", dispnum.c_str());
          out << linebuf << endl;
      }
      htmlfile.close();
+ /*
      delete []resultnum;
      delete []dispnum;
+ */
      return 0;
  }
  
***************
*** 333,343 ****
--- 369,385 ----
      char buf[DSCBLOCKSIZE + 128];
      char *escurl = escape_url(path);
      char *esckey = escape_url(key);
+ /*
      strstream jscode;
+ */
+     stringstream jscode;
      jscode << "onClick=\"this.href='http://odin.ingrid.org/cgi-bin/launcher?URL="
             << escurl << "&nth=" << n << '/' << resultNum
             << "&key=" << esckey << '\0';
+ /*
      char *jscodestr = jscode.str();
+ */
+     string jscodestr = jscode.str();
      
      cout << "<DT><B><A HREF="<< escurl
           << "\" " << jscodestr << "';\">";
***************
*** 360,366 ****
--- 402,410 ----
          << "</NOBR></SMALL><BR>" << endl; 
      delete []escurl;
      delete []esckey;
+ /*
      delete []jscodestr;
+ */
  }
  
  int
***************
*** 559,581 ****
--- 603,640 ----
          else
              rto = (resultLen > rto) ? rto : resultLen;
  
+ /*
          ostrstream stitle, squery;
+ */
+         stringstream stitle, squery;
          stitle << "Result: ";
          cexp.print(stitle);
          stitle << " (" << resultLen << " documents found. #" << param_from;
          stitle << "--#" << rto << ')' << '\0'; // terminate explicitly
          cexp.print(squery); squery << '\0';
+ /*
          char *titlestr = stitle.str();
          char *querystr = squery.str();
+ */
+         string titlestr = stitle.str();
+         string querystr = squery.str();
+ /*
          display_html(cout, "head.html", titlestr, querystr,
+ */
+         display_html(cout, "head.html", titlestr.c_str(), querystr.c_str(),
                       "(no error)", resultLen);
          print_results(descfile, result, uquery,
                        resultLen, param_n, param_from -1, rto - 1);
+ /*
          display_html(cout, "foot.html", titlestr, querystr,
+ */
+         display_html(cout, "foot.html", titlestr.c_str(), querystr.c_str(),
                       "(no error)", resultLen);
          writelog(uquery, resultLen);
+ /*
          delete []titlestr;
          delete []querystr;
+ */
      }
      if(result) delete []result;
      
diff -cr ../freya-0.92.4/src/jlib.cc ./src/jlib.cc
*** ../freya-0.92.4/src/jlib.cc	Fri May  8 00:56:23 1998
--- ./src/jlib.cc	Thu Jun 17 07:50:19 2004
***************
*** 4,9 ****
--- 4,10 ----
  //  $Id: jlib.cc,v 0.9 1997-12-27 07:49:19+09 harada Exp $
  //
  #include "jlib.h"
+ #include <string.h> // for strlen()
  
  int jstrcmp(const char *s1, const char *s2)
  {
diff -cr ../freya-0.92.4/src/patricia.cc ./src/patricia.cc
*** ../freya-0.92.4/src/patricia.cc	Fri May  8 00:56:23 1998
--- ./src/patricia.cc	Thu Jun 17 07:41:20 2004
***************
*** 7,12 ****
--- 7,14 ----
  #include <assert.h>
  #include <string.h>
  }
+ #include "fstream.h" // for streampos
+ 
  #include "patricia.h"
  
  #ifdef PATRICIA_DEBUG
***************
*** 194,211 ****
--- 196,221 ----
  
  int
  Patricia::load(istream &patfile){
+     patfile.clear();
      patfile.seekg(0);
  
      // read header
      unsigned int magic;
      int root_idx;
+ /*
      patfile.read(&magic, sizeof(magic));
+ */
+     patfile.read((char*)&magic, sizeof(magic));
      if(magic != MAGIC){
          cerr << "Patricia::load(): invalid PAT file." << endl;
          return -1;
      }
+ /*
      patfile.read(&keyNum, sizeof(keyNum));
      patfile.read(&root_idx, sizeof(root_idx));
+ */
+     patfile.read((char*)&keyNum, sizeof(keyNum));
+     patfile.read((char*)&root_idx, sizeof(root_idx));
  
      // prepare body
      Pat_node *node_table[keyNum];
***************
*** 217,236 ****
--- 227,260 ----
      for(i = 0; i < keyNum; i++){
          // read key
          Pat_node *node = node_table[i];
+         char skeylen;
          unsigned char keylen;
+ /*
          patfile.get(keylen);    // may keylen be 0
+ */
+         patfile.get(skeylen);    // may keylen be 0
+         keylen = skeylen;
          node->key = new char[keylen + 1];
          patfile.read(node->key, (int)keylen);
          node->key[keylen] = '\0';
  
          // read content, checkbit
+ /*
          patfile.read(& node->content, sizeof(node->content));
          patfile.read(& node->checkbit, sizeof(node->checkbit));
+ */
+         patfile.read((char*)& node->content, sizeof(node->content));
+         patfile.read((char*)& node->checkbit, sizeof(node->checkbit));
  
          // read branches
          int left_idx, right_idx;
+ /*
          patfile.read(&left_idx, sizeof(int));
          patfile.read(&right_idx, sizeof(int));
+ */
+         patfile.read((char*)&left_idx, sizeof(int));
+         patfile.read((char*)&right_idx, sizeof(int));
+ 
          node->left = node_table[left_idx];
          node->right = node_table[right_idx];
  
***************
*** 247,252 ****
--- 271,277 ----
  // 全ノードをdumpしてファイルに格納する
  int
  Patricia::save(ostream &patfile){
+     patfile.clear();
      patfile.seekp(0);
  
      if(root_node == NULL){
***************
*** 259,267 ****
--- 284,297 ----
      // write header
      unsigned int magic = MAGIC;
      int root_idx = root_node->dump_idx;
+ /*
      patfile.write(&magic, sizeof(magic));
      patfile.write(&keyNum, sizeof(keyNum));
      patfile.write(&root_idx, sizeof(root_idx));
+ */
+     patfile.write((char*)&magic, sizeof(magic));
+     patfile.write((char*)&keyNum, sizeof(keyNum));
+     patfile.write((char*)&root_idx, sizeof(root_idx));
  
      // write body
      for(int i = 0; i < total; i++){
***************
*** 270,281 ****
--- 300,321 ----
  
          patfile.put((unsigned char)len);
          patfile.write(node->key, len); // may len be 0
+ /*
          patfile.write(& node->content, sizeof(node->content));
          patfile.write(& node->checkbit, sizeof(node->checkbit));
+ */
+         patfile.write((char*)& node->content, sizeof(node->content));
+         patfile.write((char*)& node->checkbit, sizeof(node->checkbit));
          assert(node->left->dump_idx != -1);
+ /*
          patfile.write(& node->left->dump_idx, sizeof(int));
+ */
+         patfile.write((char*)& node->left->dump_idx, sizeof(int));
          assert(node->right->dump_idx != -1);
+ /*
          patfile.write(& node->right->dump_idx, sizeof(int));
+ */
+         patfile.write((char*)& node->right->dump_idx, sizeof(int));
      }
      patfile << flush;
  
------------------------------------------------------------------------
</PRE>