mopdの実装を学ぶため、mopdに置いてあるファイルを一つずつ見ていくことにしました。おそらく、ソースを読むために必要となる派生的な技術に手を出す必要が出てくると思いますが、それもこれも勉強だと思います。短期間に全力疾走して解析を終えることにはならないでしょうから、長期に亘ることを意識して、TW5で情報を整理しながら進めていこうと思います。
まず最初にmopd/process.hから見ていきます。このファイルは、コメントを除けば、10数行しかありません。
#ifndef _PROCESS_H_
#define _PROCESS_H_
#ifdef NO__P
void mopProcessDL (/* FILE *, struct if_info *, u_char *, int *,
u_char *, u_char *, int, u_short */);
void mopProcessRC (/* FILE *, struct if_info *, u_char *, int *,
u_char *, u_char *, int, u_short */);
#else
__BEGIN_DECLS
void mopProcessDL __P((FILE *, struct if_info *, u_char *, int *,
u_char *, u_char *, int, u_short));
void mopProcessRC __P((FILE *, struct if_info *, u_char *, int *,
u_char *, u_char *, int, u_short));
__END_DECLS
#endif
#endif _PROCESS_H_
ここで「__BEGIN_DECLS」と「__END_DECLS」のペア、「__P()」というマクロらしきもの、「NO__P」という定義が利用されています。これらが何かを調べるところから始めていきたいと思います。
まず「__BEGIN_DECLS」と「__END_DECLS」は、Web上にある記事「C言語系 / NetBSD1.6における setjmp(), longjmp() の実装(2) (v1)」で説明されていました。同様の説明は他にも見つかったので、それ自体は難しいことは何もありません。ただし調べても不明だったのは、なぜ「extern "C"」を直に記述しないで、これらを使うのかという事です。しかも「8.1 Writing C header files」では、「BEGIN_C_DECLS」と「END_C_DECLS」を使うことにしています。何か歴史的な事情があったのではないかと思うのですが、その経緯がわかりませんでした。
次に「__P()」というマクロは、初期のC言語とANSI Cとのプロトタイプ宣言の違いを吸収するために使うようです。mopd-2.5.3が何時から開発されていたのか、ChangeLogなどがないので、不明ですが、その当時はK&R CとANSI Cの違いを気にする必要があったのでしょう。しかし2023年の今となっては、あまり気にしなくても良さそうです。
最後に「NO__P」という定義は、otherOS/Makefileの中で定義されているのを見つけました。rs6000-aix3、sun3-sunos4、sun4-sunos5などの環境下では定義されるようです。多分それらでは「__P()」が存在しないのでしょう。
このファイルがどのように変更されているかを確認してみました。
- NetBSDでは、「NO__P」の定義を確認している箇所が無くなっていますし、「__P()」も使っていません。
- OpenBSDでは、NetBSDと同様の対応に加えて、「__BEGIN_DECLS」と「__END_DECLS」も消えています。
- FreeBSDでは、portsのパッチが増え過ぎないようにしたかったのか、何の変更も加えられていません。
- Linux版は、NetBSDの変更を取り込んでいるようですが、「NO__P」の定義を確認している箇所が無くなっているものの、「__P()」は残っています。