Blame doc-jp/mcpp-porting.html

Packit Service 8bf002
<html>
Packit Service 8bf002
<head>
Packit Service 8bf002
  <meta http-equiv="Content-Type" content="text/html; charset=EUC-JP">
Packit Service 8bf002
  <style> pre {color: navy} tt {color: maroon} </style>
Packit Service 8bf002
  <style> table {border-collapse: separate; border-spacing: 0px; empty-cells: show; background-color: #f0f0ff} </style>
Packit Service 8bf002
  <style> th, td {text-align: left; padding-left: 15px; padding-right: 15px} </style>
Packit Service 8bf002
</head>
Packit Service 8bf002
<body>
Packit Service 8bf002
Packit Service 8bf002

MCPP-PORTING

Packit Service 8bf002

== How to Port MCPP ==

Packit Service 8bf002
Packit Service 8bf002
Packit Service 8bf002

for V.2.7.2 (2008/11)

Packit Service 8bf002
松井  潔 (kmatsui@t3.rim.or.jp)
Packit Service 8bf002
Packit Service 8bf002
Packit Service 8bf002

== 目次 ==

Packit Service 8bf002
Packit Service 8bf002
Packit Service 8bf002

1. 概要

Packit Service 8bf002
1.1. OSや処理系を選ばない portable なソース
Packit Service 8bf002
1.2. 正確な Standard C モードに加えてその他の各種モードも
Packit Service 8bf002
1.3. このドキュメントの表記法
Packit Service 8bf002

Packit Service 8bf002

Packit Service 8bf002
2. 履歴
Packit Service 8bf002

Packit Service 8bf002

Packit Service 8bf002
3. 各処理系に移植する方法:概要
Packit Service 8bf002
3.1. 移植ずみの処理系: compiler-specific-build のコンパイル
Packit Service 8bf002
3.1.1. どの処理系でも必要な設定
Packit Service 8bf002
3.1.2. FreeBSD / GCC V.2.*, V.3.*, V.4.*
Packit Service 8bf002
3.1.3. Linux / GCC V.2.*, V.3.*, V.4.*
Packit Service 8bf002
3.1.4. Mac OS X / Apple-GCC V.4.*
Packit Service 8bf002
3.1.5. CygWIN / GCC V.2.*, V.3.*
Packit Service 8bf002
3.1.6. MinGW / GCC V.3.*
Packit Service 8bf002
3.1.7. LCC-WIN32 2003-08, 2006-03
Packit Service 8bf002
3.1.8. Visual C++ V.6.0, 2002, 2003, 2005, 2008
Packit Service 8bf002
3.1.9. Borland C V.5.*
Packit Service 8bf002
3.2. DECUS cpp で対応していた処理系
Packit Service 8bf002
3.3. noconfig.H, configed.H, system.H
Packit Service 8bf002
3.4. system.c
Packit Service 8bf002
3.5. ライブラリ関数
Packit Service 8bf002
3.6. 標準ヘッダ
Packit Service 8bf002
3.7. makefile と mcpp を使ったリコンパイル
Packit Service 8bf002
3.8. mcpp をコンパイルできる処理系
Packit Service 8bf002
3.9. コンパイルする処理系とターゲットの処理系
Packit Service 8bf002
3.10. MS-DOS 上の処理系、DJGPP 等
Packit Service 8bf002
3.11. Compiler-independent-build のコンパイル
Packit Service 8bf002
3.12. Subroutine-build のコンパイル
Packit Service 8bf002
3.12.1. configure する場合
Packit Service 8bf002
3.12.2. noconfig/*.mak を使う場合
Packit Service 8bf002
3.12.3. static library と shared library および DLL
Packit Service 8bf002

Packit Service 8bf002
4. 各処理系に移植する方法:詳細
Packit Service 8bf002
4.1. noconfig.H, configed.H, system.H の設定
Packit Service 8bf002
4.1.1. PART 1 ターゲットシステムの設定: compiler-specific-build
Packit Service 8bf002
4.1.1.1. 事前定義マクロ
Packit Service 8bf002
4.1.1.2. Include ディレクトリ等
Packit Service 8bf002
4.1.1.3. 行番号情報の出力形式その他
Packit Service 8bf002
4.1.1.4. 処理系の言語仕様に応じた設定
Packit Service 8bf002
4.1.1.5. Multi-byte character
Packit Service 8bf002
4.1.1.6. ターゲットとホストに共通の設定
Packit Service 8bf002
4.1.2. PART 2 ホストシステムの設定
Packit Service 8bf002
4.1.3. PART 3 mcpp の動作仕様の設定
Packit Service 8bf002
4.1.3.1. 新旧各種の動作モード
Packit Service 8bf002
4.1.3.2. 動作モードの細部の指定
Packit Service 8bf002
4.1.3.3. Translation limits の指定
Packit Service 8bf002
4.2. system.c
Packit Service 8bf002
4.extra. malloc()
Packit Service 8bf002

Packit Service 8bf002

Packit Service 8bf002
5. バグ報告と移植の報告
Packit Service 8bf002
5.1. バグかどうか?
Packit Service 8bf002
5.2. malloc() 関連のバグチェック
Packit Service 8bf002
5.3. バグ報告を
Packit Service 8bf002
5.4. 移植の報告を
Packit Service 8bf002
5.5. GCC 以外の処理系での configure の情報を
Packit Service 8bf002
5.6. データを送ってくれれば移植してみます
Packit Service 8bf002
5.7. 検証セットによる他の処理系のテスト報告を
Packit Service 8bf002
5.8. 改善のご意見を
Packit Service 8bf002

Packit Service 8bf002

Packit Service 8bf002
6. mcpp の長い道のり
Packit Service 8bf002
6.1. 構想3日、制作6年
Packit Service 8bf002
6.2. V.2.3 へ
Packit Service 8bf002
6.3. 「未踏ソフトウェア創造事業」に採択
Packit Service 8bf002
Packit Service 8bf002

Packit Service 8bf002
Packit Service 8bf002

1. 概要

Packit Service 8bf002

mcpp は Martin Minow の DECUS cpp を元に kmatsui(松井 潔)が全面的に書き直したCプリプロセッサです。mcpp という名前は Matsui cpp という意味です。これはソースで提供するもので、各処理系で使うには、その処理系に合わせてソースに若干の変更を加えた上でコンパイルして、mcpp の実行プログラムを作る必要があります。*1

Packit Service 8bf002

このドキュメントはソースを各処理系に移植する方法を説明しています。できあがった実行プログラムの動作仕様については、mcpp-manual.html というマニュアルを参照してください。

Packit Service 8bf002
これらのソース、ドキュメントはすべてオープンソース・ソフトウェアとして提供します。
Packit Service 8bf002
mcpp は次のような特徴を持っています。

Packit Service 8bf002

注:

Packit Service 8bf002

*1 mcpp V.2.6.3 からはコンパイルずみの何種類かのバイナリ・パッケージも次のサイトで提供するようにした。しかし、このドキュメントではそれには触れない。バイナリ・パッケージについてはこの web page を参照のこと。

Packit Service 8bf002
Packit Service 8bf002

http://mcpp.sourceforge.net/

Packit Service 8bf002
Packit Service 8bf002

Packit Service 8bf002
Packit Service 8bf002

1.1. OSや処理系を選ばない portable なソース

Packit Service 8bf002

Linux, FreeBSD, Windows 等の多くのOSをサポートしている portable なプリプロセッサであり、そのソースは Standard C (ANSI/ISO/JIS C) の処理系でさえあればコンパイルできる広い portability を持っています。ライブラリ関数は古典的なものしか使っていません。

Packit Service 8bf002
各処理系に移植するためには、多くの場合、ヘッダファイル中のいくつかのマクロ定義を書き替えてコンパイルするだけですみます。最悪の場合でもソースファイルに数十行書き足す程度です。

Packit Service 8bf002

Multi-byte character(漢字)の処理は日本の EUC-JP, shift-JIS, ISO2022-JP、中国の GB-2312、台湾の Big-5、韓国の KSC-5601 (KSX 1001) に対応しており、UTF-8 も使えます。Shift-JIS, ISO2022-JP, Big-5 の場合、コンパイラ本体が漢字を認識しない処理系では、mcpp がそれを補います。

Packit Service 8bf002

Packit Service 8bf002
Packit Service 8bf002

1.2. 正確な Standard C モードに加えてその他の各種モードも

Packit Service 8bf002

Standard C 準拠の動作モードのほかに、K&R 1st. のモードや "Reiser" model cpp のモードもあり、さらには自称 post-Standard 仕様のモードまであります。C++ のプリプロセッサとして動作する実行時オプションもあります。

Packit Service 8bf002
Standard C モードは既存の多くのプリプロセッサと違って、規格を完全に実装しているつもりです。C90, C95, C99, C++98 のすべてに対応しています。Standard C プリプロセスの reference model となるものを目指して作ってあります。これらの規格のバージョンは実行時オプションで指定することができます。*1

Packit Service 8bf002

ほかにいくつかの有用な拡張機能も持っています。マクロの展開機序や #if 式の評価機序をトレースする #pragma MCPP debug もあります。ヘッダファイルを "pre-preprocess" しておくこともできます。

Packit Service 8bf002
いくつかの有用な実行時オプションも備えています。ウォーニングのレベルを指定するオプションや、include directory を指定するオプション等です。
Packit Service 8bf002
ソースにどんな間違いがあっても mcpp は暴走したり見当外れなメッセージを出したりせず、正確でわかりやすい診断メッセージを出して適切な処理をします。移植上で問題となる点についても警告を発します。
Packit Service 8bf002
高品質でありながら、コードサイズは比較的小さく、メモリ消費も比較的少なくてすみます。
Packit Service 8bf002
詳細なドキュメントも付属しています。

Packit Service 8bf002

mcpp の欠点を強いて挙げれば、速度がやや遅いことです。GCC 3.*, 4.* / cc1 に比べると2倍から3倍の時間がかかります。しかし、Borland C 5.5 / cpp と同じくらいの速度で、ヘッダファイルの pre-preprocess の機能を使うともう少し速くなるので、特に遅いほうではありません。正確であること、portable なソースであること、少ないメモリでも動作すること等のためには、この程度の処理時間はやむをえないと考えています。

Packit Service 8bf002

なお、プリプロセッサの Standard C 準拠度をテストするための検証セットである "Validation Suite for Standard C Preprocessing"、その解説およびそれを使ってテストした各種プリプロセッサの採点簿 cpp-test.html を mcpp とともに公開しています。これを見ると、「Standard C 準拠」と称する既存のプリプロセッサにいかに多くの問題があるかがわかります。*2

Packit Service 8bf002

注:

Packit Service 8bf002

*1 C言語の規格としては ISO/IEC 9899:1990 (JIS X 3010-1993) が長く使われてきたが、1999 年には ISO/IEC 9899:1999 が採択された。ここでは前者を C90、後者を C99 と呼ぶ。前者は ANSI X3.159-1989 が移行したものなので、一般には ANSI C または C89 と呼ばれることもある。また、ISO/IEC 9899:1990 + Amendment 1995 を C95 と呼ぶことがある。C++ の規格は ISO/IEC 14882:1998 およびその正誤訂正版である ISO/IEC 14882:2003 で、この両者をここでは C++98 と呼ぶ。

Packit Service 8bf002

*2 この cpp は V.2.2 までは単に cpp と呼んでいたが、一般の cpp と紛らわしいので、V.2.3 からは mcpp と呼ぶことにした。このドキュメントでは V.2.2 までのバージョンも mcpp と呼ぶ。また、このドキュメントの名前は V.2.2 までは cpp.doc としていたが、V.2.3 からは porting.txt と変更し、V.2.5 からは mcpp-porting.txt と変更し、さらに V.2.6.2 からは mcpp-porting.html と変更した。私自身の名前も、V.2.2 までは Psycho としていたが、V.2.3 からは kmatsui に変更した。

Packit Service 8bf002

Packit Service 8bf002
Packit Service 8bf002

1.3. このドキュメントの表記法

Packit Service 8bf002

このドキュメントはかつてはテキストファイルでしたが、V.2.6.2 からは html ファイルに変わりました。

Packit Service 8bf002
このドキュメントでは次のようにフォントを使い分けています。

Packit Service 8bf002
    Packit Service 8bf002
  • <tt style="color:navy">source</tt>:
  • Packit Service 8bf002
    <tt style="color:navy">紺色</tt>の等幅フォントは、
    Packit Service 8bf002
    ソースコードの断片およびコマンドラインの入力を示すのに使われます。
    Packit Service 8bf002
  • <tt>__STDC__</tt>:
  • Packit Service 8bf002
    <tt style="color:maroon">くり色</tt>の等幅フォントは、標準事前定義マクロおよび何らかのマクロを示すのに使われます。
    Packit Service 8bf002
  • STD:
  • Packit Service 8bf002
    Italic フォントは mcpp の <samp>system.H</samp> というソースファイルで定義されるマクロを表します。このドキュメントではこれらの名前を mcpp の種々の設定を表記するためにも使います。これらのマクロは mcpp をコンパイルする時に使われるだけで、mcpp の実行プログラムには存在していないことに注意してください。
    Packit Service 8bf002
    Packit Service 8bf002

    Packit Service 8bf002
    Packit Service 8bf002

    2. 履歴

    Packit Service 8bf002
      Packit Service 8bf002
    1. DECUS cpp は Martin Minow によって作られ、1984/05 に usenet / net.sources で公開されました。DECUS というのは、DEC Users' Society という DEC 社のコンピュータのユーザグループだそうです。DECUS cpp は DEC の PDP-11 / RT11, PDP-11 / RSX, VAX / VMS, VAX / ULTRIX 等のシステムの当時のC言語処理系のために書かれたCプリプロセッサです。移植性の良い書き方がされているので、他のシステムに移植することは比較的容易で、オリジナル版でもすでに DEC 以外のいくつかの UNIX システムに対応していたようです。
    2. Packit Service 8bf002

      Packit Service 8bf002
    3. 私が mcpp の出発点としたのは、C Users' Group の配付ディスク #243 でした。このソース中にある修正履歴を見ると、原作者による最終修正が 85/06 となっています。その後、原作者がバージョンアップをしているという話は聞きません。
    4. Packit Service 8bf002

      Packit Service 8bf002
    5. その後 88/12 までに何人かによって MS-DOS 上のいくつかの処理系にも移植されました。CUG のディスクに入っているのはこのバージョンです。
    6. Packit Service 8bf002

      Packit Service 8bf002
    7. ftp.oreilly.com/pub/examples/imake/DECUS-cpp.tar.gz にもソースがあり、その time-stamp は 93/02 となっていますが、実際の内容は CUG のものより古く、85/01 のものです。なお、これに含まれている Martin Minow の README によると、このプログラムは public domain となっています(この README 自体も 84 または 85 年のものと思われる)。
    8. Packit Service 8bf002

      Packit Service 8bf002
    9. 89/04 に Gigo らによって OS-9/6x09 の Microware C に移植されたものが NIFTY-SERVE / FOS9 / lib 2 に登録されていました。
    10. Packit Service 8bf002

      Packit Service 8bf002
    11. mcpp V.2 は、私がこれらを元に全面的に書き直したものです。移植性をさらに向上させ、Standard C に完全に対応させるため、ソースファイルの分割の仕方も変え、多くのマクロを追加し、関数と変数の追加・分割・書き換え・改名を大幅に行っています。ソースの量もオリジナル版の3倍になっています。ドキュメントと検証セットはすべて、私がまったく新しく書いたものです。
    12. Packit Service 8bf002
      私はこれらをオープンソース・ソフトウェアとして公開します。私自身は DECUS とは何の関係もありません。
      Packit Service 8bf002
      なお、オリジナル版には版数が付けられていませんが、mcpp と対比する時には、そちらを DECUS cpp と呼ぶことにします。
      Packit Service 8bf002

      Packit Service 8bf002
    13. Standard C のマクロ展開の実装方法については、E. Ream 作の MS-DOS 上の PDS である CPP V.5.3 (1989/08, CUG #319) のソースも参考にしました。そのほか、GCC / cpp の動作や、J. Roskind の JRCPP のドキュメントからもいくつかの示唆を得ています。
    14. Packit Service 8bf002

      Packit Service 8bf002
    15. mcpp V.2.0 は検証セット V.1.0 とともに 1998/08 に NIFTY SERVE / FC / LIB 2 で公開され、ベクター社のサイトにも転載されました。
    16. Packit Service 8bf002

      Packit Service 8bf002
    17. mcpp V.2.1 は、V.2.0 に C99 1998/08 draft に対応するための修正を加えたものです。検証セット V.1.1 とともに 1998/09 に NIFTY SERVE / FC / LIB 2 およびベクター社のサイトに同時にアプロードされました。
    18. Packit Service 8bf002

      Packit Service 8bf002
    19. mcpp V.2.2 は V.2.1 を 1998/07 に決まった C++ Standard (ISO/IEC 14882:1998) に対応して update したものです。検証セット V.1.2 とともに 1998/11 に NIFTY SERVE / FC / LIB 2 およびベクター社のサイトに同時にアプロードされました。
    20. Packit Service 8bf002

      Packit Service 8bf002
    21. mcpp V.2.3 は V.2.2 を C99 に対応して update し、さらに Linux / GCC 2.95, GCC 3.2 等への移植を追加して、GCC / cpp との互換性を向上させたものです。また、実行時オプションを追加し、一部を変更しました。V.2.3 ではドキュメントの英語版も作成されました。mcpp に付属する検証セットには、GCC / testsuite の一部として自動的にテストを実行することのできる edition が追加されました。
    22. Packit Service 8bf002

      Packit Service 8bf002
    23. mcpp は V.2.3 の開発の途中で、検証セット V.1.3 とともに、情報処理推進機構(IPA) の平成14年度「未踏ソフトウェア創造事業」に新部 裕・プロジェクトマネージャによって採択され、2002/07 - 2003/02 の間は IPA の資金援助と新部PMの助言のもとに開発が進められました。英語版ドキュメントもこのプロジェクトの中で、有限会社・ハイウェル(東京)に翻訳を委託し、それに私が修正とテキスト整形を加えてできあがったものです。このプロジェクトの中で cvs repository と ftp site が用意され、V.2.3 はそこで 2002/08 に pre-release 1 が、2002/12 に pre-release 2 が、2003/02 にリリース版が開発されました。その後、2003/03 に V.2.3 patch 1 が出されています。*1
    24. Packit Service 8bf002

      Packit Service 8bf002
    25. mcpp はさらに平成15年度にも「未踏ソフトウェア創造事業」に伊知地 宏 PM によって継続して採択され、2003/06 - 2004/02 の間は IPA の資金援助と伊知地PMの助言のもとに V.2.4 への update 作業が進められました。そして、2003/11 には V.2.4 prerelease が開発されました。このバージョンでは Visual C++ 2003 への移植が追加され、また、mcpp の make を自動化する configure スクリプトが作成されました。なお、mcpp はそれまで明確なライセンス表示をしていませんでしたが、この時から BSD スタイルのライセンス表示をするようになりました。さらに、2004/02 にはリリース版が開発されました。このバージョンでは multi-byte character の処理が拡張されました。また、英語版ドキュメントもハイウェルに翻訳を委託し、日本語版に合わせて update されました。
    26. Packit Service 8bf002
      2004/03 には mcpp V.2.4.1 がリリースされました。これは再帰的マクロの展開方法を修正したものです。
      Packit Service 8bf002

      Packit Service 8bf002
    27. 2005/03 には mcpp V.2.5 がリリースされました。このバージョンでは、POST_STANDARD というコンパイル時のモードは STANDARD モードにその実行時オプションの一つとして吸収され、OLD_PREPROCESSOR というコンパイル時の設定は PRE_STANDARD モードの実行時オプションとして吸収されました。再帰的マクロの展開方法は再修正されて完全なものとなりました。また、GCC V.3.3, 3.4 に対応した一方で、16 ビットシステムでの処理系に関するドキュメントの多くを削除しました。
    28. Packit Service 8bf002

      Packit Service 8bf002
    29. 2006/07 には mcpp V.2.6 がリリースされました。このバージョンでは、STANDARD モードと PRE_STANDARD モードが1つの実行プログラムにまとめられました。compiler-independent-build の仕様は処理系に依存しないものに改められました。いくつかの処理系の新しいバージョンへの対応が追加された一方で、pre-C90 の仕様の処理系に移植するための設定は削除されました。MS-DOS 上のコンパイラへの移植も削除されました。ソースの書き換えは大幅なものになりました。今後はソースの追加や細部の修正はあっても、大幅な書き換えは発生しない見込みです。
    30. Packit Service 8bf002
      2006/08 には mcpp V.2.6.1 がリリースされました。このバージョンでは、MinGW への移植が追加されました。そのほか、バグ修正といくつかの比較的小さい改良がありました。
      Packit Service 8bf002
      2006/11 には mcpp V.2.6.2 がリリースされました。このバージョンでは、いくつかのバグが修正されるとともに、テキストファイルのドキュメントが html に変更されました。また、Juergen Mueller の contribution による subroutine-build が実装されました。
      Packit Service 8bf002
      2007/04 には mcpp V.2.6.3 がリリースされました。このバージョンでは、GCC-specific-build の GCC との互換性が強化されました。Subroutine-build では Greg Kress の contribution によってメモリ上のバッファへの出力が実装されました。また、このバージョンからいくつかのシステム用のバイナリ・パッケージが提供されるようになりました。
      Packit Service 8bf002
      2007/05 には mcpp V.2.6.4 がリリースされました。これは V.2.6.3 のバグフィックス版です。

      Packit Service 8bf002
    31. 2008/03 には mcpp V.2.7 がリリースされました。
    32. Packit Service 8bf002
      マクロに関する情報をコメントに書き込んで出力する「マクロ注釈モード」(macro notification mode) というものが実装され、コードがかなり増えました。このモードでは、プリプロセス後の出力から元のソース上のマクロの位置を知ることができます。このモードは C/C++ の refactoring tool のために実装されたものです。
      Packit Service 8bf002
      また、Mac OS X / Apple-GCC への移植が追加されました。
      Packit Service 8bf002
      Visual C++ 2008 への移植もされました。
      Packit Service 8bf002
      GCC-specific-build はさらに GCC に近いものになりました。
      Packit Service 8bf002
      前バージョンのいくつかのバグも修正されました。
      Packit Service 8bf002
      2008/05 には mcpp V.2.7.1 がリリースされました。
      Packit Service 8bf002
      これは V.2.7 のバグフィックス版で、前バージョンのいくつかのバグが修正されました。
      Packit Service 8bf002
      また、UNIX 系システムのバイナリ・パッケージはすべて shared library または DLL と、それをリンクした実行プログラムを提供するようになりました。
      Packit Service 8bf002
      2008/11 には mcpp V.2.7.2 がリリースされました。
      Packit Service 8bf002
      これは前バージョンのバグフィックス版です。
      Packit Service 8bf002
      Packit Service 8bf002

      注:

      Packit Service 8bf002

      *1 「未踏ソフトウェア創造事業」(Exploratory Software Project) の概要は次のところで知ることができる。

      Packit Service 8bf002
      Packit Service 8bf002

      http://www.ipa.go.jp/jinzai/esp/

      Packit Service 8bf002
      Packit Service 8bf002

      mcpp V.2.3 から V.2.5 までは次のところに置いてきたが、

      Packit Service 8bf002
      Packit Service 8bf002

      http://www.m17n.org/mcpp/

      Packit Service 8bf002
      Packit Service 8bf002

      2006/04 に次のところに移った。

      Packit Service 8bf002

      Packit Service 8bf002
      Packit Service 8bf002

      http://mcpp.sourceforge.net/

      Packit Service 8bf002
      Packit Service 8bf002

      cpp V.2.2 はベクター社のサイトの次のところにある。dos/prog/c というディレクトリに入れられているが、MS-DOS 専用ではない。ソースは UNIX, WIN32/MS-DOS 等に対応している。

      Packit Service 8bf002
      Packit Service 8bf002
      http://www.vector.co.jp/soft/dos/prog/se081188.html
      Packit Service 8bf002
      http://www.vector.co.jp/soft/dos/prog/se081189.html
      Packit Service 8bf002
      http://www.vector.co.jp/soft/dos/prog/se081186.html
      Packit Service 8bf002
      Packit Service 8bf002

      これらのアーカイブファイル中のテキストファイルは、Vector のものは DOS/Windows 系に合わせて、改行コードは [CR]+[LF]、漢字は shift-JIS で encode してある。SourceForge のものは V.2.5 までは UNIX 系に合わせて改行コードは [LF]、漢字は EUC-JP である。V.2.6 からは [CR]+[LF] / shift-JIS の zip 版と [LF] / EUC-JP の tar.gz 版の2種類のアーカイブファイルを置くようにした。

      Packit Service 8bf002

      Packit Service 8bf002
      Packit Service 8bf002

      3. 各処理系に移植する方法:概要

      Packit Service 8bf002

      mcpp のソースは5本のヘッダファイルと7本の *.c ファイルからなっています。OSや処理系に依存する部分は <samp>configed.H, noconfig.H, system.H, system.c</samp> の4本のソースにまとめてあります。<samp>configed.H</samp> と <samp>noconfig.H</samp> とは同時に使われることはなく、必ずどちらか一方が使われます。また、ライブラリ関数の一部のCによるソースが <samp>system.c</samp> にあります。したがって、mcpp を何らかの処理系で使うには、それに合わせてこれらのソースファイルに変更を加える必要があります。

      Packit Service 8bf002

      mcpp の実行プログラムは build する方法に応じて何種類かあります。

      Packit Service 8bf002
      Build する方法には次の2つの次元があります。
      Packit Service 8bf002
      Packit Service 8bf002
        Packit Service 8bf002
      1. stand-alone-build vs subroutine-build
      2. Packit Service 8bf002
      3. compiler-independent-build vs compiler-specific-build
      4. Packit Service 8bf002
        Packit Service 8bf002
          Packit Service 8bf002
        • stand-alone-build: 1つのコマンドとして単体で動くプリプロセッサです。
        • Packit Service 8bf002
          処理系のコンパイラ・ドライバから呼び出されるものもあります。
          Packit Service 8bf002
        • subroutine-build: 他のメインプログラムの中からサブルーチンとして
        • Packit Service 8bf002
          (必要なら繰り返し)呼び出されるものです。
          Packit Service 8bf002
          これについては 3.12 で述べます。

          Packit Service 8bf002
          Packit Service 8bf002
            Packit Service 8bf002
          • compiler-independent-build: 処理系からは独立して動くプリプロセッサです。
          • Packit Service 8bf002
            実行時オプションなどの仕様は処理系のいかんによらず一定です。
            Packit Service 8bf002
            プリプロセスだけすることができますが、処理系の一部として動作することはできません。*1
            Packit Service 8bf002
            これは多くの場合、コンパイルさえ通ればすむのでごく簡単です。これについては 3.11 で述べます。*2
            Packit Service 8bf002
          • compiler-specific-build: 特定の処理系のプリプロセッサを(もし可能なら)代替するためのものです。
          • Packit Service 8bf002
            その処理系に専用の仕様を持ち、その処理系の専用のディレクトリにインストールされます。
            Packit Service 8bf002
            Packit Service 8bf002
            Packit Service 8bf002

            以下の 3.1 - 3.9 ではこの stand-alone の compiler-specific-build を説明します。「GCC 版」「Visual C 用」等と表記しているのはすべて、それぞれ GCC-specific-build, Visual C-specific-build のことです。

            Packit Service 8bf002

            mcpp をコンパイルするには2つの方法があります。1つは configure スクリプトを実行して、<samp>config.h</samp> というヘッダファイルと Makefile を自動生成する方法です。あとは単に make; make install とするだけですみます。<samp>configed.H</samp> というヘッダファイルはこの場合に使われます。しかし、configure は UNIX 系のシステムと CygWIN, MinGW でしか使えません。

            Packit Service 8bf002
            もう1つは各処理系用の差分ファイルを使ってヘッダファイルに変更を加え、必要ならさらにヘッダファイルを編集した上で、その処理系専用の makefile を使って make する方法です。<samp>noconfig.H</samp> というヘッダファイルはこの場合に使われます。差分ファイルと makefile は noconfig というディレクトリにあります。Configure の使えるシステムでも、ヘッダファイルを直接、編集することで細かい制御をすることができます。しかし、差分ファイルはすでに移植ずみの処理系用のものしかありません。
            Packit Service 8bf002
            この章では差分ファイルを使う方法について説明します。Configure については INSTALL を見てください。

            Packit Service 8bf002

            注:

            Packit Service 8bf002

            *1 これを V.2.6, V.2.6.1 では stand-alone-build と呼んでいた。

            Packit Service 8bf002
            V.2.6.2 で subroutine-build ができたのに伴って、呼称を変更した。

            Packit Service 8bf002

            *2 mcpp V.2.6.3 からは mcpp.sourceforge.net で何種類かのバイナリ・パッケージが提供されるようになったが、これはすべて stand-alone の compiler-independent-build である。

            Packit Service 8bf002

            Packit Service 8bf002
            Packit Service 8bf002

            3.1. 移植ずみの処理系: compiler-specific-build のコンパイル

            Packit Service 8bf002

            私自身が動かすことのできるC処理系は次のもので、このいずれにも mcpp を移植してあります。すなわち、このソースをコンパイルでき、生成されたプリプロセッサがそれぞれの処理系の上で正しく動作することを確認しています。いずれも CPU は x86 系を使っています。Ubuntu だけが 64 ビット版で、他は 32 ビット版です。

            Packit Service 8bf002
            Packit Service 8bf002
            Packit Service 8bf002
              FreeBSD 6.3        GCC V.3.4.6
            Packit Service 8bf002
              Vine Linux 4.2     GCC V.2.95.3, V.3.2, V.3.3.6, V.3.4.3, V.4.1.1
            Packit Service 8bf002
              Fedora Linux 9     GCC V.4.3.0
            Packit Service 8bf002
              Debian LInux 4.0   GCC V.4.1.2
            Packit Service 8bf002
              Ubuntu Linux 8.04 / x86_64 GCC V.4.2.3
            Packit Service 8bf002
              Mac OS 10.5        GCC V.4.0.1
            Packit Service 8bf002
              CygWIN 1.3.10      GCC V.2.95.3
            Packit Service 8bf002
              CygWIN 1.5.18      GCC V.3.4.4
            Packit Service 8bf002
              MinGW (MSYS 1.0.11)GCC V.3.4.5
            Packit Service 8bf002
              WIN32              Visual C++ 2003, 2005, 2008
            Packit Service 8bf002
              WIN32              Borland C++ V.5.5J
            Packit Service 8bf002
              WIN32              LCC-Win32 2003-08, 2006-03
            Packit Service 8bf002
            Packit Service 8bf002
            Packit Service 8bf002

            また、他のユーザから提供された Visual C++ V.6.0, Visual C++ 2002, C++Builder 2007 (aka BCC V.5.9) の情報もあり、それらの処理系でコンパイルすることもできます。

            Packit Service 8bf002

            これらの処理系で mcpp をコンパイルするための修正は簡単で、<samp>noconfig.H</samp> の数個のマクロ定義を変更するだけです。

            Packit Service 8bf002

            noconfig ディレクトリの *.dif というファイルは FreeBSD 6.* / GCC 3.4 用の <samp>noconfig.H</samp> を各処理系用に修正する差分ファイルです。Visual C++ 2005 を例にとると、src ディレクトリで

            Packit Service 8bf002
            Packit Service 8bf002
            patch -c < ..\noconfig\vc2005.dif
            Packit Service 8bf002
            Packit Service 8bf002

            とすると、修正されます。patch は UNIX の標準的なコマンドで、Windows 等にも移植されています。patch を使わなくても、差分ファイルを見てエディタで修正してもかまいません。

            Packit Service 8bf002

            Include ディレクトリの指定などは、差分ファイルによる修正とは別に、ユーザが自分のシステムに合わせて修正しなければなりません。

            Packit Service 8bf002

            こうして修正したソースをコンパイルするための各処理系用の makefile も添付してあります(3.7 参照)。

            Packit Service 8bf002
            Packit Service 8bf002
            copy ..\noconfig\visualc.mak Makefile
            Packit Service 8bf002
            Packit Service 8bf002

            として src ディレクトリにコピーします。

            Packit Service 8bf002

            以下の作業も src ディレクトリで行います。作業は特に断らない限り、<samp>noconfig.H</samp> の修正です。

            Packit Service 8bf002
            Packit Service 8bf002

            3.1.1. どの処理系でも必要な設定

            Packit Service 8bf002

            以下のどの処理系でも、compiler-specific-build を作るためには、

            Packit Service 8bf002
            Packit Service 8bf002
            #define COMPILER        INDEPENDENT
            Packit Service 8bf002
            Packit Service 8bf002

            となっている行を

            Packit Service 8bf002
            Packit Service 8bf002
            #define COMPILER        MSC
            Packit Service 8bf002
            Packit Service 8bf002

            等と、その処理系を表すマクロに変更します。そして、

            Packit Service 8bf002

            Packit Service 8bf002
            Packit Service 8bf002
            #define VERSION_MSG     "GCC 3.4"
            Packit Service 8bf002
            Packit Service 8bf002

            という行を次のように適宜書き換えます。

            Packit Service 8bf002

            Packit Service 8bf002
            Packit Service 8bf002
            #define VERSION_MSG     "Visual C 2005"
            Packit Service 8bf002
            Packit Service 8bf002

            COMPILER の定義は make のオプションで上書きすることもできます。

            Packit Service 8bf002
            例えば、

            Packit Service 8bf002
            Packit Service 8bf002
            nmake COMPILER=MSC
            Packit Service 8bf002
            nmake COMPILER=MSC install
            Packit Service 8bf002
            Packit Service 8bf002

            等とします。差分ファイルで <samp>noconfig.H</samp> を書き換えた場合は、compiler-specific-build のための設定もその処理系用に書き換えられるので、COMPILER は書き換える必要はありません。make で COMPILER を指定すると compiler-specific-build が生成され、指定しないと compiler-independent-build が生成されます。

            Packit Service 8bf002

            また、デフォルトの include directory の設定が <samp>noconfig.H</samp> のものと異なる場合は、それを C_INCLUDE_DIR1, C_INCLUDE_DIR2 というマクロに書いておきます。C と異なる C++ 固有の include directory がある場合は、それを CPLUS_INCLUDE_DIR1, CPLUS_INCLUDE_DIR2, CPLUS_INCLUDE_DIR3 に書きます(これらのディレクトリは実行時に環境変数や -I オプションで指定することもできる)。<samp>noconfig.H</samp> で設定するのは処理系固有の include directory です。

            Packit Service 8bf002
            Include directory はこのほか、<samp>system.c</samp> でも設定されています。UNIX で言えば <samp>system.c</samp> で設定されるのはいわゆる OS-specific なもの(通常は /usr/include)といわゆる site-specific なもの(通常は /usr/local/include)です。Windows では <samp>system.c</samp> では include directory は何も設定されません。Windows では <samp>noconfig.H</samp> でもデフォルトでは include directory は設定されないので、自分で書くか、または環境変数 INCLUDE, CPLUS_INCLUDE で指定する必要があります。

            Packit Service 8bf002

            また、必要なら COMPILER_STD1, COMPILER_STD2 等で定義される組み込みマクロ名も変更します。

            Packit Service 8bf002

            Multi-byte character の encoding はデフォルトでは、UNIX 系では EUC-JP、Windows では shift-JIS としていますが、必要なら MBCHAR というマクロを書き換えて他の encoding に変更します(Multi-byte character encoding は実行時に環境変数・オプション・#pragma で変更することもできる)。

            Packit Service 8bf002
            処理系によっては shift-JIS や Big5 等の encoding に対応していないため、multi-byte character の中に '\\' と同じ 0x5c の値のバイトがあると tokenization でエラーになることがありますが、そういう処理系では mcpp は特殊な処理をしてコンパイラの欠陥を補います。この設定については 4.1.1.5 を見てください。

            Packit Service 8bf002

            添付の makefile については、BINDIR という変数で処理系のバイナリの置かれているディレクトリを書きます。

            Packit Service 8bf002

            GCC V.3, V.4 ではプリプロセスがコンパイラ (cc1, cc1plus) に吸収されてしまったので、GCC-specific-build の mcpp を使うには、gcc, g++ の呼び出しを shell-script に置き換えて、mcpp => cc1, mcpp => cc1plus の順序で実行されるようにしなければなりません。添付の makefile では、

            Packit Service 8bf002
            Packit Service 8bf002
            make COMPILER=GNUC
            Packit Service 8bf002
            make COMPILER=GNUC install
            Packit Service 8bf002
            Packit Service 8bf002

            とすると、これが自動的に設定されます。詳細は mcpp-manual.html#3.9.7 を見てください。

            Packit Service 8bf002

            ユーザが BINDIR 等への書き込み権限を持っていない場合は、UNIX 系では sudo make COMPILER=GNUC install とします。Windows ではあらかじめ administrator アカウントで、そのディレクトリの permission を変更しておきます。

            Packit Service 8bf002
            Packit Service 8bf002

            3.1.2. FreeBSD / GCC V.2.*, V.3.*, V.4.*

            Packit Service 8bf002

            ソースは FreeBSD 6.* 上の GCC (GNU C) V.3.4.* でコンパイルして compiler-independent-build の mcpp を生成する状態になっています。FreeBSD 6.* / GCC V.3.4.* 用の compiler-specific-build を作るには、

            Packit Service 8bf002
            Packit Service 8bf002
            #define COMPILER        INDEPENDENT
            Packit Service 8bf002
            Packit Service 8bf002

            となっている行を

            Packit Service 8bf002
            Packit Service 8bf002
            #define COMPILER        GNUC
            Packit Service 8bf002
            Packit Service 8bf002

            として、コンパイルすればできあがりです。

            Packit Service 8bf002
            COMPLIER は make COMPILER=GNUC で上書きすることもできます。

            Packit Service 8bf002

            GCC の他のバージョンであれば、VERSION_MSG というマクロおよび

            Packit Service 8bf002
            Packit Service 8bf002
            #define COMPILER_EXT_VAL    "3"
            Packit Service 8bf002
            #define COMPILER_EXT2_VAL   "4"
            Packit Service 8bf002
            #define COMPILER_CPLUS_VAL  "3"
            Packit Service 8bf002
            #define GCC_MAJOR_VERSION   3
            Packit Service 8bf002
            Packit Service 8bf002

            となっているところのバージョン番号を変更します。

            Packit Service 8bf002
            COMPILER_EXT_VAL は GCC の major version number を、COMPILER_EXT2_VAL は minor version number をいずれも文字列リテラルで書きます。COMPILER_CPLUS_VAL は <tt>__GNUG__</tt> マクロの値で、COMPILER_EXT_VAL と同じになります。
            Packit Service 8bf002
            また、GCC_MAJOR_VERSION COMPILER_EXT_VAL と同じ値を数値で書きます。

            Packit Service 8bf002
            Packit Service 8bf002

            FreeBSD のバージョンが 6.* でなければ、

            Packit Service 8bf002
            Packit Service 8bf002
            #define SYSTEM_EXT_VAL      "6"     /* V.5.*: 5, V.6.*:6    */
            Packit Service 8bf002
            Packit Service 8bf002

            の値を変更します。

            Packit Service 8bf002

            Packit Service 8bf002

            さらに include directory が FreeBSD 6.* の標準と違っている場合は、

            Packit Service 8bf002

            Packit Service 8bf002
            Packit Service 8bf002
            #define CPLUS_INCLUDE_DIR1  "/usr/include/c++/3.4"
            Packit Service 8bf002
            #define CPLUS_INCLUDE_DIR2  "/usr/include/c++/3.4/backward"
            Packit Service 8bf002
            Packit Service 8bf002

            となっているディレクトリを変更します。CPLUS_INCLUDE_DIR3, C_INCLUDE_DIR1 の設定も必要かもしれません。

            Packit Service 8bf002

            GCC V.2.7-2.95 であれば次のマクロの定義を 199409L に変更します。

            Packit Service 8bf002
            Packit Service 8bf002
            #define STDC_VERSION        0L
            Packit Service 8bf002
            Packit Service 8bf002

            他の UNIX 系 OS でもコンパイラが GCC であれば、このバージョン表示や、include ディレクトリの設定、OS固有の組み込みマクロの設定、等を変えるだけですむかもしれません(4.1.1 参照)。

            Packit Service 8bf002
            Packit Service 8bf002

            3.1.3. Linux / GCC V.2.*, V.3.*, V.4.*

            Packit Service 8bf002

            Linux / GCC ではまず、

            Packit Service 8bf002
            Packit Service 8bf002
            #define SYSTEM      SYS_FREEBSD
            Packit Service 8bf002
            Packit Service 8bf002

            Packit Service 8bf002
            Packit Service 8bf002
            #define SYSTEM      SYS_LINUX
            Packit Service 8bf002
            Packit Service 8bf002

            に変更します。

            Packit Service 8bf002
            そして、FreeBSD の場合と同じように、COMPILER, VERSION_MSG, COMPILER_EXT_VAL, COMPILER_EXT2_VAL, COMPILER_CPLUS_VAL, GCC_MAJOR_VERSION CPLUS_INCLUDE_DIR1, CPLUS_INCLUDE_DIR2, C_INCLUDE_DIR1 等のマクロの値を変更します。

            Packit Service 8bf002

            GCC 2.* では STDC_VERSION の値を変更し、さらに、

            Packit Service 8bf002
            Packit Service 8bf002
            #define COMPILER_SP3_VAL    "int"
            Packit Service 8bf002
            Packit Service 8bf002

            Packit Service 8bf002
            Packit Service 8bf002
            #define COMPILER_SP3_VAL    "long int"
            Packit Service 8bf002
            Packit Service 8bf002

            に変更します。

            Packit Service 8bf002

            include directory は

            Packit Service 8bf002
            Packit Service 8bf002
            gcc -xc -E -v /dev/null
            Packit Service 8bf002
            g++ -xc++ -E -v /dev/null
            Packit Service 8bf002
            Packit Service 8bf002

            として確かめてから設定してください。

            Packit Service 8bf002

            noconfig ディレクトリの linux_gcc2953.dif, linux_gcc32.dif, linux_gcc336.dif, linux_gcc343.dif は FreeBSD 6.* / GCC V.3.4 用のソースを VineLinux 4.0 / GCC V.2.95.3, V.3.2, V.3.3.6, V.3.4.3 用に修正する差分ファイルです。

            Packit Service 8bf002
            また、linux_gcc412.dif は Debian 4.0 / GCC V.4.1.2 用に修正するものです。
            Packit Service 8bf002
            それぞれ compiler-specific-build ではさらに COMPILER を変更します。Distribution の標準の GCC と追加インストールした GCC とで include directory がかなり異なる点に注意してください。

            Packit Service 8bf002

            なお、glibc の getopt() は POSIX 等の標準のものとは仕様が異なるので、使わずに、<samp>system.c</samp> の mcpp_getopt() を使ってください。

            Packit Service 8bf002
            Packit Service 8bf002

            3.1.4. Mac OS X / Apple-GCC V.4.*

            Packit Service 8bf002

            Mac OS X では Xcode というパッケージをインストールすると GCC もインストールされます。

            Packit Service 8bf002
            /usr/bin に多くの gcc, cc, g++, c++ 等々が現れますが、Intel-Mac の Mac OS X 10.5 (Leopard) の場合は、i686-apple-darwin9-gcc-4.0.1, i686-apple-darwin9-g++-4.0.1 というのがそのマシン用の native code を生成するコンパイラです。
            Packit Service 8bf002
            同時にクロスコンパイラもインストールされます。
            Packit Service 8bf002
            Intel-Mac の場合は、powerpc-apple-darwin9-gcc-4.0.1, powerpc-apple-darwin9-g++-4.0.1 というのが powerpc 用のバイナリを生成するクロスコンパイラです。
            Packit Service 8bf002
            単なる gcc (g++) は gcc-4.0 (g++-4.0) へのリンクで、これはデフォルトでは native compiler として動作しますが、-arch ppc というオプションを付けて起動すると powerpc 用のコンパイラ本体が呼び出されます。
            Packit Service 8bf002
            また、/Developer/usr/bin にも /usr/bin と同じコンパイラ一式がインストールされます。

            Packit Service 8bf002

            これらはいずれも Apple によって多くの拡張を施された Mac OS X 専用の GCC です。

            Packit Service 8bf002
            他のシステムの GCC と異なるのは、1つは framework と呼ばれる独特なディレクトリを system header directory としていることです。
            Packit Service 8bf002
            もう1つは Intel-Mac と PowerPC-Mac の双方のバイナリを片方の(1台の)マシン上で生成できるようになっていることです。
            Packit Service 8bf002
            さらに双方のバイナリを1つにバンドルしてどちらのマシンでも動くようにした universal binary というものを生成するしくみもあります。
            Packit Service 8bf002
            実は gcc-4.0, i686-apple-darwin9-gcc-4.0.1, powerpc-apple-darwin9-gcc-4.0.1 等や、そこから呼び出されるコンパイラ本体である /usr/libexec/gcc/SYSTEM/4.0.1 の cc1, cc1plus 等々もすべて i386 用と ppc 用との universal binary なのです(SYSTEM は i686-apple-darwin9 または powerpc-apple-darwin9)。
            Packit Service 8bf002
            これらをそのまま x86 マシンから powerpc マシンに持っていけば、native と cross の関係が逆転した状態で動くようになっているものと思われます。
            Packit Service 8bf002
            その上、Intel-Mac は ppc 用のバイナリを x86 のコードに変換しながら自動的に動かすようになっています。

            Packit Service 8bf002

            こういうことで、/usr/bin と /Developer/usr/bin に多くの gcc, g++ があり、それらへのリンクがあり、x86 用と ppc 用の libexec ディレクトリがあり、1つの実行プログラムに2つのバイナリがバンドルされており、ppc 用のバイナリが x86 で動き、拡張機能があり、非常に紛らわしいので注意してください。

            Packit Service 8bf002
            ここでは Intel-Mac 上の Mac OS X 10.5 (Leopard) を例にとりますが、ppc-Mac では i686 と powerpc (ppc) を入れ替えて読んでください。
            Packit Service 8bf002
            また、Mac OS X 10.4 (Tiger) では darwin9 を darwin8 と読み替えてください。

            Packit Service 8bf002
            Packit Service 8bf002

            3.1.4.1. ネイティブコンパイラとクロスコンパイラ

            Packit Service 8bf002

            ネイティブコンパイラ用の mcpp のインストールは簡単です。

            Packit Service 8bf002
            noconfig.H に mac_gcc401_i686.dif の変更を加えると、Intel-Mac 上の Mac OS X 10.5 / GCC 4.0.1 用の設定になります。
            Packit Service 8bf002
            Makefile としては mac_osx.mak を使います。
            Packit Service 8bf002
            make; sudo make install とすると compiler-independent-build が、make COMPILER=GNUC; sudo make COMPILER=GNUC install とすると GCC-specific-build ができます。
            Packit Service 8bf002
            /Developer/usr/bin には通常は PATH は通っていないので、コンパイラは /usr/bin のものが使われます。

            Packit Service 8bf002

            Intel-Mac 上で powerpc 用のクロスコンパイラにインストールするには、まず noconfig.H に mac_gcc401_powerpc.dif の変更を加えます。

            Packit Service 8bf002
            さらに Makefile を修正します。
            Packit Service 8bf002

            compiler-independent-build では NAME, CC, CXX という変数の定義を、いずれも mac_osx.mak 中のコメントにあるように powerpc を含む文字列に変更します。

            Packit Service 8bf002
            そして make; sudo make install とします。
            Packit Service 8bf002
            これは「クロスコンパイラで」コンパイルされたもので、ppc-Mac 上で動くはずです。

            Packit Service 8bf002

            GCC-specific-build では NAME, INCDIR, BINDIR, target_cc, arch を、やはり powerpc (ppc) を含む名前に変更します(CC, CXX は変更しない)。

            Packit Service 8bf002
            そして、make COMPILER=GNUC; sudo make COMPILER=GNUC install とします。
            Packit Service 8bf002
            これは Intel-Mac 上で動く「クロスコンパイラのための」ものなので、Intel-Mac 上で動きます。

            Packit Service 8bf002

            ppcMac 上では、Intel-Mac とは逆に、mac_gcc401_powerpc.dif でネイティブコンパイラ用の設定になり、mac_gcc401_i686.dif でクロスコンパイラ用の設定になるはずです。

            Packit Service 8bf002
            クロスコンパイラ用では、上記の Intel-Mac の Makefile の設定で変数に powerpc を含む名前を使ったところを、すべて i686 に変更します。

            Packit Service 8bf002
            Packit Service 8bf002

            3.1.4.2. Universal binary

            Packit Service 8bf002

            Universal binary を作るには、mac_osx.mak の UFLAGS という変数定義をコメントアウトしている # を外して、これを有効にするだけです。

            Packit Service 8bf002
            あとは前節の設定のままです。

            Packit Service 8bf002
            Packit Service 8bf002

            3.1.5. CygWIN / GCC V.2.*, 3.*

            Packit Service 8bf002

            CygWIN V.1.3.10 / GCC V.2.95.3 では <samp>noconfig.H</samp> に cyg1310.dif にあるような変更を加えます。

            Packit Service 8bf002
            CygWIN V.1.5.18 / GCC V.3.4.4 では cyg1518.dif を使います。

            Packit Service 8bf002

            さらに CYGWIN_ROOT_DIRECTORY というマクロを自分の環境に合わせて修正します。これは CygWIN の存在する Windows 上のディレクトリを次の形式で定義するものです。

            Packit Service 8bf002
            Packit Service 8bf002
            #define CYGWIN_ROOT_DIRECTORY   "c:/pub/compilers/cygwin"
            Packit Service 8bf002
            Packit Service 8bf002

            path-list 中の大文字・小文字は関係ありません。

            Packit Service 8bf002

            他の version でも、VERSION_MSG, CYGWIN_ROOT_DIRECTORY、および include directory のマクロを変更することで対応できるでしょう。

            Packit Service 8bf002

            CygWIN は Windows 上のシステムですが、UNIX のファイルシステムがシミュレートされているので、mcpp では UNIX 系システムの GCC とほぼ同様に扱います。Include directories も UNIX 系と同様に組み込まれます。

            Packit Service 8bf002
            Packit Service 8bf002

            3.1.6. MinGW / GCC V.3.*

            Packit Service 8bf002

            MinGW / GCC V.3.4.5 では <samp>noconfig.H</samp> に mingw345.dif のような変更を加えます。

            Packit Service 8bf002
            さらに MSYS_ROOT_DIRECTORY, MINGW_DIRECTORY という2つのマクロを自分の環境に合わせて修正します。これは次のように、それぞれ /, /mingw ディレクトリの Windows 上の位置に定義するものです。

            Packit Service 8bf002
            Packit Service 8bf002
            #define MSYS_ROOT_DIRECTORY "C:/Program Files/MSYS/1.0"
            Packit Service 8bf002
            #define MINGW_DIRECTORY     "C:/Program Files/MinGW"
            Packit Service 8bf002
            Packit Service 8bf002

            path-list 中の大文字・小文字は関係ありません。

            Packit Service 8bf002

            他の version でも、これらのマクロと VERSION_MSG、および include directory のマクロを変更することで対応できるでしょう。Include directory のマクロ定義は "C:/dir/mingw/include" という絶対パスでも、"/mingw/include" という MinGW 内のディレクトリでもかまいません。

            Packit Service 8bf002

            MinGW では symbolic link がサポートされていないので、gcc から GCC-specific-build の mcpp を起動するのに symbolic link が使えません。その上、MinGW / gcc はたとえ cc1 という名前でも shell-script の起動は拒否します。そこで、mcpp のコンパイルでは cc1.exe という実行プログラムを生成して、この中から mcpp.exe または GCC の cc1.exe, cc1plus.exe を呼び出します。

            Packit Service 8bf002

            MinGW の GCC-specific-build では include directories は mcpp が設定しますが、compiler-independent-build では設定されないので、環境変数 INCLUDE, CPLUS_INCLUDE で指定する必要があります。

            Packit Service 8bf002
            Packit Service 8bf002

            3.1.7. LCC-WIN32 2003-08, 2006-03

            Packit Service 8bf002

            LCC-WIN32 2003-08-*, 2006-03-* ではそれぞれ lcc0308.dif, lcc0603.dif のような変更を加えます。

            Packit Service 8bf002
            他の version では VERSION_MSG マクロを変更します。

            Packit Service 8bf002
            Packit Service 8bf002

            3.1.8. Visual C++ V.6.0, 2002, 2003, 2005, 2008

            Packit Service 8bf002

            Visual C++ 2008, 2005, 2003, 2002, 6.0 ではそれぞれ vc2008.dif, vc2005.dif, vc2003.dif, vc2002.dif, vc6.dif のような変更を加えます。もちろん、compiler-specific-build では COMPILER マクロを書き換えるか、nmake -DCOMPILER=MSC オプションで上書きします。

            Packit Service 8bf002

            Visual C の他のバージョンでは、VERSION_MSG マクロを変更するほか、<tt>_MSC_VER</tt> および <tt>_MSC_FULL_VER</tt> という組み込みマクロの値をそれぞれ COMPILER_EXT_VAL, COMPILER_EXT2_VAL というマクロの設定を変えることで対応させます。

            Packit Service 8bf002
            Packit Service 8bf002

            3.1.9. Borland C++ V.5.*

            Packit Service 8bf002

            Borland C V.5.5, V.5.9 (C++Builder 2007) / bcc32 ではそれぞれ bc55.dif, bc59.dif のような変更を加えます。

            Packit Service 8bf002

            Borland C/C++ の別のバージョンでは VERSION_MSG のほか、<tt>__TURBOC__</tt>, <tt>__BORLANDC__</tt>, <tt>__BCPLUSPLUS__</tt> という組み込みマクロの値をそれぞれ <samp>noconfig.H</samp> の COMPILER_STD2_VAL, COMPILER_EXT_VAL, COMPILER_CPLUS_VAL というマクロの設定を変えることで、対応させます(4.1.1.1 参照)。Digraphs の実装されているバージョンであれば、HAVE_DIGRAPHS の設定を変更します。<tt>__STDC_VERSION__</tt> の実装されているバージョンであれば、STDC_VERSION の設定を変更します。

            Packit Service 8bf002

            Packit Service 8bf002
            Packit Service 8bf002

            3.2. DECUS cpp で対応していた処理系

            Packit Service 8bf002

            PDP-11 上の RT-11 / DECUS C, RSX / DECUS C、VAX 上の VMS / VAX-11 C、PDP-11 / UNIX, VAX / ULTRIX の何かのCには DECUS cpp が対応していたようです。MS-DOS 上の Microsoft C, Lattice C のかなり古い版にも対応していたようです。これらはさすがにもう不要と思われ、また私自身がメンテナンスできないので、削除しました。

            Packit Service 8bf002

            Packit Service 8bf002
            Packit Service 8bf002

            3.3. noconfig.H, configed.H, system.H

            Packit Service 8bf002

            <samp>system.H</samp> は HAVE_CONFIG_H というマクロが non-0 に定義されていると <samp>configed.H</samp> を include し、そうでなければ <samp>noconfig.H</samp> を include します。<samp>configed.H, noconfig.H</samp> には mcpp の設定の PART 1 と PART 2 という部分があり、<samp>system.H</samp> には PART 3 があります。

            Packit Service 8bf002

            これらのファイルには、各処理系に移植する時に必要ないくつかのマクロが定義されています。まだ移植されていない処理系に移植するには、PART 1 に数行ないし十数行を書き足します。

            Packit Service 8bf002
            PART 1 はOSと target 処理系に依存する定義で、PART 2 は host 処理系に依存する定義、そして PART 3 は mcpp の動作仕様の定義です。
            Packit Service 8bf002
            <samp>configed.H, noconfig.H</samp> ではターゲット処理系とホスト処理系とが同じであると仮定していますが、異なる場合は PART 2 を編集する必要があります。

            Packit Service 8bf002

            デフォルトの設定と違う設定で移植する場合は、これらのファイルの全体に必ず目を通してください。

            Packit Service 8bf002

            Packit Service 8bf002
            Packit Service 8bf002

            3.4. system.c

            Packit Service 8bf002

            <samp>configed.H (noconfig.H), system.H</samp> のマクロだけでは吸収できないOSや処理系の差異は、<samp>system.c</samp> で吸収しています。未実装の処理系に移植するには、ここに数十行のソースを書き足すことが必要になるでしょう。

            Packit Service 8bf002

            このファイルに記述されているのは、mcpp 起動時のオプション、usage 文、include ディレクトリ、ヘッダファイルやソースファイルをオープンする時のOS固有のディレクトリパスの扱い、#pragma の処理、処理系固有の拡張ディレクティブの処理、等です。ほとんどは target OS と target 処理系の設定です。

            Packit Service 8bf002

            Packit Service 8bf002
            Packit Service 8bf002

            3.5. ライブラリ関数

            Packit Service 8bf002

            ライブラリ関数のうち、Standard C にない getopt(), stpcpy() のCによるソースも system.c に書いてあります。mcpp は getcwd(), stat() も使い、UNIX 系では readlink() も使いますが、この3つは OS に依存する関数であり portable に書くことができないので、ここには含めていません。この3つは Standard C にはありませんが、POSIX では規定されています。mcpp の使う低水準関数はこの3つだけです。これらを持たない処理系はないでしょう。

            Packit Service 8bf002
            このほか、MSC では stricmp() を、Mac OS X, CygWIN, MinGW では strcasecmp() も使います。*1, *2
            Packit Service 8bf002
            ライブラリ関数はいずれも、処理系によって微妙に違う恐れのある仕様に依存した使い方はしていないので、どの処理系のものでもバグさえなければ大丈夫です。

            Packit Service 8bf002

            注:

            Packit Service 8bf002

            *1 MinGW 版に限って spawnv() も使われる。

            Packit Service 8bf002

            *2 mcpp V.2.6.4 までは lib.c というソースファイルを独立させていたが、その内容が getopt(), stpcpy() の2つだけになったので、V.2.7 から system.c に吸収した。

            Packit Service 8bf002
            そして、getopt() は mcpp_getopt() と名前を変えて、リンクのトラブルを解消した。

            Packit Service 8bf002

            Packit Service 8bf002
            Packit Service 8bf002

            3.6. 標準ヘッダ

            Packit Service 8bf002

            mcpp のソースでは <samp>stdio.h, ctype.h, errno.h, stdlib.h, string.h, stddef.h, limits.h, time.h, sys/types.h, sys/stat.h</samp> を無条件で include しています。UNIX 系のシステムでは <samp>unistd.h</samp> も include します。これらを持たない処理系はまずないでしょう。

            Packit Service 8bf002

            Packit Service 8bf002
            Packit Service 8bf002

            3.7. makefile と mcpp を使ったリコンパイル

            Packit Service 8bf002

            noconfig ディレクトリにある *.mak は個別の処理系用の makefile です。詳細な設定ができます。make そのものは各処理系に付属のもの、またはそのシステムの標準的なものを想定しています。Visual C では make ではなく nmake を使います。

            Packit Service 8bf002

            まず、処理系を xyz とすると、FreeBSD / GCC 以外では

            Packit Service 8bf002
            Packit Service 8bf002
            patch -c < ../noconfig/xyz.dif
            Packit Service 8bf002
            Packit Service 8bf002

            として <samp>noconfig.H</samp> を修正します。次に、<samp>noconfig.H</samp> の COMPILERVERSION_MSG というマクロを書き換えます。さらに自分のシステムに合わせて <samp>noconfig.H</samp> の C_INCLUDE_DIR? 等のマクロを修正します。そして、使用する noconfig/xyz.mak を Makefile にコピーし、ディレクトリ指定等を自分のシステムに合わせて修正した上で、

            Packit Service 8bf002
            Packit Service 8bf002
            make
            Packit Service 8bf002
            make install
            Packit Service 8bf002
            make clean
            Packit Service 8bf002
            Packit Service 8bf002

            としてください。

            Packit Service 8bf002

            他の処理系では、これらを参考に必要な makefile を書いてください。ソースの依存関係は単純で、

            Packit Service 8bf002
              Packit Service 8bf002
            1. <samp>main.c, directive.c, eval.c, expand.c, support.c, system.c, mbchar.c</samp> は <samp>system.H, internal.H</samp> に依存する
            2. Packit Service 8bf002
            3. <samp>system.H</samp> は <samp>configed.H (noconfig.H)</samp> に依存する
            4. Packit Service 8bf002
              Packit Service 8bf002

              という関係になっています。

              Packit Service 8bf002
              <samp>system.H</samp> は <samp>internal.H</samp> より先に include する必要があります。
              Packit Service 8bf002
              <samp>internal.H</samp> はさらに <samp>mcpp_lib.h</samp> を include します。

              Packit Service 8bf002

              mcpp 自身を使って mcpp をリコンパイルするには、処理系のプリプロセッサのある場所にこの実行プログラムをおきます。例えば GCC V.2.95 であれば、処理系付属の cpp0 を cpp0_gnuc とでも rename しておき、その時に使うものを cpp0 にリンクするのが良いでしょう。すなわち、使うプリプロセッサを mcpp とすると、

              Packit Service 8bf002
              Packit Service 8bf002
              ln -sf mcpp cpp0
              Packit Service 8bf002
              Packit Service 8bf002

              とします。Windows では使うものを cpp32.exe 等にコピーします。*1

              Packit Service 8bf002

              mcpp 実行プログラムの名前は

              Packit Service 8bf002
              Packit Service 8bf002
              make NAME=mcpp
              Packit Service 8bf002
              Packit Service 8bf002

              等として指定することができます(同じことを BC make では make -DNAME=mcpp とする。UCB make では -D は付けても付けなくても良い。GNU make では -D は付けてはいけない)。

              Packit Service 8bf002

              添付の makefile では GCC 用(freebsd.mak, linux.mak, mac_osx.mak, cygwin.mak, mingw.mak)以外は make install ではこまかい処理はしないので、手で補ってください。処理系付属のプリプロセッサは、make install で消してしまうことのないように、あらかじめ別名のファイルにコピーしておいてください。

              Packit Service 8bf002

              Visual C, Borland C のような1パスコンパイラで mcpp を使ってリコンパイルする場合は、mcpp の出力ファイルをコンパイラに与えるソースファイルとします(例えば <samp>main.c</samp> というソースをプリプロセスしたものを <samp>main.i</samp> といった名前で出力して、それを cl や bcc32 にコンパイルさせる)。

              Packit Service 8bf002

              mcpp を使ってリコンパイルする時は、ヘッダファイルの "pre-preprocess" の機能を使うと、プリプロセス時間が大幅に短縮されます。添付の makefile を使う場合は、UCB make, GNU make, MS nmake では、

              Packit Service 8bf002
              Packit Service 8bf002
              make PREPROCESSED=1
              Packit Service 8bf002
              Packit Service 8bf002

              BC make では

              Packit Service 8bf002
              Packit Service 8bf002
              make -DPREPROCESSED=1
              Packit Service 8bf002
              Packit Service 8bf002

              とすると、自動的にヘッダファイルを pre-preprocess した上でプリプロセスし、それからコンパイルします。LCC-Win32 の make では if 文による場合分けができないので、makefile を修正してリコンパイルする必要があります。修正の内容は makefile そのものにコメントとして書いてあります。

              Packit Service 8bf002

              UCB make, GNU make, MS nmake では、MALLOC=KMMALLOC というオプションを付けて make すると、私が書いた malloc() をリンクします。これについては 4.extra を見てください。BC make では同じことを -DKMMALLOC というオプションで指定します。LCC-Win32 make で私の malloc() をリンクするためには、makefile を修正する必要があります。

              Packit Service 8bf002

              注:

              Packit Service 8bf002

              *1 FreeBSD では cpp0, cc1 を置く標準のディレクトリは /usr/libexec である。Linux では /usr/lib/gcc-lib/i686-redhat-linux/3.3.2 といったひどく奥深いディレクトリになっている。Linux / GCC では distribution やその version に応じて makefile のこのディレクトリの指定を書き換える必要がある。Include directory もいろいろあるので、確かめなければならない。

              Packit Service 8bf002

              また、Linux や FreeBSD では /usr/bin/cpp というものがあるが、これは実際には cpp0 または cc1 を呼び出す。gcc も cpp0 または cc1 を呼び出す。

              Packit Service 8bf002
              なお、mcpp-manual.html#3.9.5, mcpp-manual.html#3.9.7 も参照のこと。GCC 3.*, 4.* ではプリプロセスがコンパイラ (cc1, cc1plus) に吸収されてしまったので、mcpp を使うには gcc, g++ の呼び出しを shell-script に置き換える必要がある。

              Packit Service 8bf002

              Packit Service 8bf002
              Packit Service 8bf002

              3.8. mcpp をコンパイルできる処理系

              Packit Service 8bf002

              各処理系に移植するためにはいくつかの設定が必要ですが、mcpp のソースをコンパイルすること自体は、C90 (ANSI C) の仕様を満たしている処理系であれば十分できます。プリプロセッサも同様です。*1, *2

              Packit Service 8bf002

              char 型は符号付きでも符号なしでもかまいません。

              Packit Service 8bf002
              浮動小数点演算は不要です。
              Packit Service 8bf002

              Packit Service 8bf002

              このソースは処理系の微妙な差に影響されないように書いてあります。

              Packit Service 8bf002
              もっとも、実際に各処理系でコンパイルするためには、さらにその処理系のバグも回避する必要があります。これはやってみないと何が出てくるかわかりません。私が移植したいくつかの処理系でも、バグであることを確かめその回避方法を見つけるまでにかなりの時間がかかってしまったことが何回かあります。

              Packit Service 8bf002

              mcpp が対応していないのは、pre-C90 の処理系のほか、特殊な文字セットを持つ処理系と特殊な CPU です。

              Packit Service 8bf002
              EBCDIC には対応していません。
              Packit Service 8bf002
              また、整数演算が2の補数でない 
              Packit Service 8bf002
              CPU にも、対応していません。2の補数でない場合は、#if 式でオーバーフローが発生した時に、おかしくなるかもしれません。

              Packit Service 8bf002

              注:

              Packit Service 8bf002

              *1 mcpp V.2.5 までは K&R 1st. の処理系でもコンパイルできるようにしていたが、すでにその必要はなくなっていると思われるので、V.2.6 からは C90 を前提とするように改めた。それに伴ってソースを整理し、このドキュメントも整理した。

              Packit Service 8bf002

              *2 V.2.6.2 までは C++ でもコンパイルできるようにしていたが、V.2.6.3 からは C だけとした。

              Packit Service 8bf002

              Packit Service 8bf002
              Packit Service 8bf002

              3.9. コンパイルする処理系とターゲットの処理系

              Packit Service 8bf002

              mcpp のソースをコンパイルする処理系(ホスト)と、それによって生成された mcpp の実行プログラムを使う処理系(ターゲット)とは、必ずしも同じである必要はありません。これが違っている場合は、<samp>noconfig.H (configed.H)</samp> の SYSTEM, COMPILER でターゲットを指定し、HOST_SYSTEM, HOST_COMPILER はホストを指定します。また、PART 1 にある諸定義はターゲット用のもので、PART 2 にあるものはホスト用の設定です。<samp>system.c</samp> は主としてターゲット用のものです。

              Packit Service 8bf002

              ホストとターゲットの関係には、次のような制限があります。

              Packit Service 8bf002
                Packit Service 8bf002
              1. ホスト処理系はターゲット処理系と同じOS上のものであるか、またはクロスコンパイラであることが必要です。
              2. Packit Service 8bf002
                ホスト処理系とターゲット処理系の文字セットとはともに ASCII であることが必要です。
                Packit Service 8bf002
              3. ホスト処理系の long (unsigned long) はターゲット処理系のそれより範囲が狭くてはいけません。これは Standard C で規定されている条件でもあります。C99 では long long (unsigned long long) について同じことが言えます。
              4. Packit Service 8bf002
                Packit Service 8bf002

                なお、ここで言うホストとターゲットというのは、クロスコンパイラのそれとは関係ありません。クロスコンパイルするのはコンパイラ本体の仕事で、プリプロセッサは原則としてそれには関知しません。mcpp を「クロスコンパイラに」移植する場合は、そのクロスコンパイラがここで言うターゲット処理系です。ホスト処理系としてはクロスコンパイラでないものを使うことになるはずです。mcpp を「クロスコンパイラで」コンパイルする場合は、そのクロスコンパイラがホスト処理系で、クロスコンパイラのターゲットがターゲット処理系となります。

                Packit Service 8bf002

                Packit Service 8bf002
                Packit Service 8bf002

                3.10. MS-DOS 上の処理系、DJGPP 等

                Packit Service 8bf002

                mcpp の過去のバージョンでサポートしていたもののその後、サポートをやめた処理系について述べておきます。

                Packit Service 8bf002

                mcpp V.2.2 までは次の処理系をサポートしていましたが、V.2.4 で削除しました。

                Packit Service 8bf002
                Packit Service 8bf002
                MS-DOS          Turbo C V.2.0
                Packit Service 8bf002
                OS-9/6x09       Microware C
                Packit Service 8bf002
                Packit Service 8bf002

                V.2.5 では次の処理系に関するドキュメントを削除しました。

                Packit Service 8bf002
                Packit Service 8bf002
                DJGPP V.1.12    GCC V.2.7.1
                Packit Service 8bf002
                MS-DOS          LSI C-86 V.3.3 試食版
                Packit Service 8bf002
                Packit Service 8bf002

                V.2.6 では上の2つの処理系の設定をソースからも削除し、さらに次の処理系に関するドキュメントとソースを削除しました。

                Packit Service 8bf002
                Packit Service 8bf002
                MS-DOS          Borland C 4.0
                Packit Service 8bf002
                Plan 9          pcc
                Packit Service 8bf002
                 
                Packit Service 8bf002

                V.2.6 ではまた、MS-DOS 上の処理系やメモリの小さいシステムのための設定をすべて削除し、pre-C90 の処理系のための設定も削除しました。

                Packit Service 8bf002

                V.2.7.2 では次の処理系のサポートも削除しました。

                Packit Service 8bf002
                Packit Service 8bf002
                Win32           Borland C 4.0
                Packit Service 8bf002
                 
                Packit Service 8bf002

                いずれも古い処理系で、ユーザは少なくなっていると思われるものです。

                Packit Service 8bf002
                もしそれらの処理系でコンパイルする場合は、compiler-specific-build では多くの設定が必要で簡単ではありませんが、compiler-independent-build なら、その処理系が C90 の仕様をほぼ実装していれば、次のようにして簡単にできます。

                Packit Service 8bf002

                DJGPP については、noconfig.H で SYSTEM, HOST_SYSTEMSYS_WIN32 とし、HAVE_INTMAX_T, HAVE_INTTYPES_HFALSE とし、system.H で NBUFF をデフォルトの 1/4 くらいに押さえます。*1

                Packit Service 8bf002

                MS-DOS 上の処理系については、noconfig.H で SYSTEM, HOST_SYSTEMSYS_WIN32 とし、HAVE_LONG_LONGFALSE とし、system.H で NBUFF をデフォルトの 1/16 くらいに、IDMAX をデフォルトの 1/4 くらいに押さえます。さらに directive.c で SBSIZE をデフォルトの 1/8 くらいにします。そして、large memory model でコンパイルします。

                Packit Service 8bf002
                ただし、MS-DOS ではメモリの制約が厳しいので、この設定でコンパイルしておいても、長大なマクロ定義の多い場合などは out of memory となることがあります。

                Packit Service 8bf002

                注:

                Packit Service 8bf002

                *1 DJGPP / GCC 4.1.0 ではこの設定で mcpp V.2.6.1 をコンパイルできたという報告がある。

                Packit Service 8bf002

                Packit Service 8bf002
                Packit Service 8bf002

                3.11. Compiler-independent-build のコンパイル

                Packit Service 8bf002

                mcpp を処理系からは独立して単体で動く compiler-independent 版としてコンパイルすることもできます。これは多くの場合はコンパイルさえ通ればすむので簡単です。Compiler-independent 版は実行時オプションなどの仕様は一定で、処理系依存の部分はありません。OS による相違が少しあるだけです。include directory も UNIX 系で /usr/include, /usr/local/include が設定されるだけなので、あとは環境変数や -I オプションで指定する必要があります。*1, *2

                Packit Service 8bf002

                configure が使えるシステムで GCC でコンパイルする場合は単に mcpp のルートディレクトリで

                Packit Service 8bf002
                Packit Service 8bf002
                ./configure; make; make install
                Packit Service 8bf002
                Packit Service 8bf002

                とすればすみます。この場合は <samp>noconfig.H</samp> ではなく <samp>configed.H</samp> というヘッダファイルが使われます。configure の詳細については INSTALL-jp を参照してください。

                Packit Service 8bf002

                configure の使えないシステムでも mcpp がすでに移植されている処理系では、noconfig ディレクトリにある所定の差分ファイルを使って <samp>noconfig.H</samp> を書き換えればすみます。それ以外の変更は必要ありません。makefile も noconfig ディレクトリにあるものをコピーして使います。インストールするディレクトリは makefile 中の BINDIR という変数に書きます。そして、src ディレクトリで make し、make install します。

                Packit Service 8bf002
                mcpp がすでに移植されている処理系とバージョンが少し違うだけの場合は、まず近いバージョンの差分ファイルを適用して、それを編集します。

                Packit Service 8bf002

                mcpp がまだ移植されていない処理系では、<samp>noconfig.H</samp> を編集して数個のマクロを書き換えたり書き加えたりしてください。まず、HOST_COMPILER を適宜定義します。そして、COMPILERINDEPENDENT に定義し、SYSTEM をその OS に定義し、VERSION_MSG を適宜定義します。ターゲット処理系は存在しないので、PART 1 には設定することはありません。

                Packit Service 8bf002

                PART 2 は mcpp をコンパイルするホスト処理系が Standard C の仕様をどれだけ実装しているか、必要な関数を持っているかによって、設定が違ってきます。最も違うのは long long という型の実装です。Visual C 2002, 2003, 2005 や Borland C 5.5 等では <samp>__int64</samp> という型になっていて、その値を printf() で表示する指定子が VC 2005 以外では j や ll ではなく I64 なので、LL_FORM というマクロを "I64" に定義します。MinGW では long long がありますが、printf() の指定子は I64 です。

                Packit Service 8bf002
                Visual C 2008 では long long という型名も使えるようになりました。

                Packit Service 8bf002

                stpcpy() という関数のない処理系では、HOST_HAVE_STPCPYFALSE に定義します。

                Packit Service 8bf002

                makefile は noconfig ディレクトリにあるものを参考にして書いてください(3.7 も参照のこと)。

                Packit Service 8bf002

                Mac OS X には x86 と powerpc の双方のバイナリを片方のマシンで作れるように、ネイティブコンパイラとクロスコンパイラとが用意されています。

                Packit Service 8bf002
                また、それを使って universal binary というものも作れるようになっています。
                Packit Service 8bf002
                これは x86 と powerpc 用のバイナリを1本のファイルに束ねたものです。
                Packit Service 8bf002
                これらの仕組みは少し複雑なので、3.1.4 に compiler-specific-build と compiler-independent-build の双方についてまとめて説明してあります。

                Packit Service 8bf002

                なお、mcpp V.2.6.3 からは sourceforge のサイトで compiler-independent-build の何種類かのバイナリ・パッケージが提供されるようになりましたが、これはそれぞれのパッケージング方式に固有の方法でパッケージングされたものです。そのパッケージング仕様はそれぞれに対応するソース・パッケージ中にある設定ファイルに書かれています。FreeBSD, Linux, Mac OS X 用のものはすべてコンパイルには configure スクリプトを使っています。

                Packit Service 8bf002

                注:

                Packit Service 8bf002

                *1 mcpp V.2.4, V.2.5 では compiler-independent 版の仕様は中途半端で、

                Packit Service 8bf002
                処理系の仕様に対応した一般のコマンドとしてのプリプロセッサであった。V.2.6 からは処理系から独立した一定の仕様とした。

                Packit Service 8bf002

                *2 コンパイルさえ通ればすむと言っても、MS-DOS 上の処理系ではメモリの制約が厳しいので、コンパイルはできても実行すると out of memory になることがある。MS-DOS では translation limits の設定を大幅に押さえてコンパイルしなければならない。3.10 を参照。

                Packit Service 8bf002

                Packit Service 8bf002
                Packit Service 8bf002

                3.12. Subroutine-build のコンパイル

                Packit Service 8bf002

                mcpp を他の何らかのメインプログラムからサブルーチンとして呼び出すようにコンパイルすることもできます。これは独立したプリプロセッサと同じように、呼び出し元から実行時オプションを受取り、指定された入力ファイルをプリプロセスして出力ファイルに出力して、呼び出し元に戻るものです。必要なら複数のファイルについて繰り返し呼び出すこともできます。しかし、呼び出し元とトークン単位のやりとりをするものではありません。

                Packit Service 8bf002

                サブルーチン版では、出力先としてファイルではなくメモリ上のバッファを使うこともできます。

                Packit Service 8bf002

                mcpp のソースは、MCPP_LIB というマクロを non-0 に定義してコンパイルすると、サブルーチン版としてコンパイルされるようになっています。サブルーチンの入り口は stand-alone 版の main() が次のように mcpp_lib_main() という名前に変わるだけです。

                Packit Service 8bf002
                    int mcpp_lib_main( int argc, char ** argv);
                Packit Service 8bf002

                GCC では COMPILER マクロは GNUC ではなく INDEPENDENT のままでコンパイルします。GNUC とすると、GCC の libexec ディレクトリにインストールされて GCC から呼び出されるものができてしまうからです。

                Packit Service 8bf002
                他方で、Visual C, Borland C, LCC-Win32 等では COMPILERINDEPENDENT でも MSC, BORLANDC, LCC 等のどちらでもかまいません。これらの処理系ではプリプロセッサが独立していないので、compiler-specific-build でも処理系から呼び出されることはないからです。compiler-specific-build では処理系固有の事前定義マクロやオプションやいくつかの処理系固有の仕様が定義されるので、それがつごうが良いか悪いかでコンパイルの仕方を選びます。

                Packit Service 8bf002

                実際にコンパイルする時の手順を configure script を使う場合と noconfig/*.mak ファイルを使う場合とに分けて説明します。

                Packit Service 8bf002
                Packit Service 8bf002

                3.12.1. configure する場合

                Packit Service 8bf002

                GCC でコンパイルする場合は configure が使えます。

                Packit Service 8bf002
                Packit Service 8bf002
                ./configure --enable-mcpplib
                Packit Service 8bf002
                make
                Packit Service 8bf002
                sudo make install
                Packit Service 8bf002
                Packit Service 8bf002

                とすると、Linux や FreeBSD では compiler-independent 版の libmcpp.a, libmcpp.so.$(SHLIB_VER) が生成されて、デフォルトでは /usr/local/lib にインストールされます。

                Packit Service 8bf002
                そして、libmcpp.so および libmcpp.so.0 から libmcpp.so.$(SHLIB_VER) へのリンクが張られます。
                Packit Service 8bf002
                *.a は static ライブラリ、*.so は shared ライブラリです。
                Packit Service 8bf002
                libmcpp.la というファイルも生成されますが、これは libtool というツールが使うためのものです。
                Packit Service 8bf002
                $(SHLIB_VER) は mcpp V.2.6.3 では 0.0.0、V.2.6.4 では 0.0.1、V.2.7 では 0.1.0、V.2.7.1 では 0.2.0、V.2.7.2 では 0.3.0 としています。
                Packit Service 8bf002
                mcpp_lib.h, mcpp_out.h というヘッダファイルも /usr/local/include にインストールされます。
                Packit Service 8bf002
                これは libmcpp を使うプログラムに必要なものです。

                Packit Service 8bf002

                Mac OS X では *.so ではなく *.dylib という名前になります。

                Packit Service 8bf002
                また、make で CFLAGS+='-arch i386 -arch ppc' 等と、-arch オプションでいくつかの CPU を指定すると、それらに対応する universal binary のライブラリができます。
                Packit Service 8bf002
                さらに -isysroot と -mmacosx-version-min= というオプションを使って、使える Mac OS X のバージョンの範囲を広げることができます。
                Packit Service 8bf002
                次の例は、Leopard 上で Tiger と互換の i386 と ppc 用の universal binary の shared ライブラリを作るコマンドです。

                Packit Service 8bf002
                Packit Service 8bf002
                make CFLAGS+='-isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.4 -arch i386 -arch ppc'
                Packit Service 8bf002
                Packit Service 8bf002

                CygWIN, MinGW では *.so ではなく *.dll という名前の DLL となります。

                Packit Service 8bf002
                CygWIN では libmcpp.a, libmcpp.dll.a, libmcpp.la が /usr/local/lib に、cygmcpp-0.dll が /usr/local/bin にインストールされます。
                Packit Service 8bf002
                MinGW もほとんど同じですが、cygmcpp-0.dll が libmcpp-0.dll という名前になります。
                Packit Service 8bf002
                DLL を使うときは libmcpp.dll.a をリンクします。
                Packit Service 8bf002
                これは import library というものです。

                Packit Service 8bf002

                生成された libmcpp.so をリンクする main_libmcpp.c という簡単なソースもコンパイルされて、mcpp という名前で /use/local/bin にインストールされます。

                Packit Service 8bf002
                このソースでわかるように、libmcpp を使うには mcpp_lib.h というヘッダファイルを include します。*1

                Packit Service 8bf002

                最小限のドキュメントもインストールされます。

                Packit Service 8bf002

                testmain.c をコンパイルしてライブラリとリンクすると、もう少し複雑なテストができます。

                Packit Service 8bf002
                これは configure ではやらないので、次節の方法で行います。

                Packit Service 8bf002

                注:

                Packit Service 8bf002

                *1 libmcpp を使わない stand-alone 版の compiler-independent-build の mcpp も同じ名前で同じディレクトリにインストールされるので、お互いに上書きし合うことになる。

                Packit Service 8bf002
                ドキュメントは同じものが同じディレクトリにインストールされるので、これも上書きされる。

                Packit Service 8bf002
                Packit Service 8bf002

                3.12.2. noconfig/*.mak を使う場合

                Packit Service 8bf002

                noconfig.H と noconfig ディレクトリの makefile を使う場合は(noconfig.H にその処理系のバージョン用の patch を当てて、makefile の各ディレクトリの設定を自分のシステムに合わせて修正した上で)、次のようにします。

                Packit Service 8bf002
                Packit Service 8bf002
                make MCPP_LIB=1 mcpplib
                Packit Service 8bf002
                make MCPP_LIB=1 mcpplib_install
                Packit Service 8bf002
                Packit Service 8bf002
                これは compiler-independent 版のコンパイルですが、GCC 以外では COMPILER=MSC 等として compiler-specific 版でコンパイルしてもかまいません。
                Packit Service 8bf002
                Visual C では make ではなく nmake を使います。
                Packit Service 8bf002
                LCC-Win32 の make は低機能で if 文による場合分けができないので、makefile を編集しながら make する必要があります。

                Packit Service 8bf002

                Linux, FreeBSD, Mac OS X, CygWIN, MinGW では、libmcpp.la が生成されないのとドキュメントがインストールされない以外は、configure して make した場合と同様の結果になります。

                Packit Service 8bf002
                Mac OS X では、mac_osx.mak の UFLAGS という変数定義をコメントアウトしている # を外すと、universal binary の設定になります。
                Packit Service 8bf002
                Windows 上の処理系ではライブラリの名前は Linux 等とは違って、次のようになります。

                Packit Service 8bf002
                Packit Service 8bf002
                Packit Service 8bf002
                  FreeBSD / GCCLinux / GCCMac OS X / GCCCygWIN / GCCMinGW / GCCVisual C, Borland C, LCC-Win32
                Packit Service 8bf002
                  static librarylibmcpp.alibmcpp.alibmcpp.alibmcpp.alibmcpp.amcpp.lib
                Packit Service 8bf002
                  shared library or DLLlibmcpp.so.$(SHL_VER)libmcpp.so.$(SHLIB_VER)libmcpp.$(SHLIB_VER).dylibcygmcpp-$(DLL_VER).dlllibmcpp-$(DLL_VER).dllmcpp$(DLL_VER).dll
                Packit Service 8bf002
                  import library of DLLlibmcpp-$(DLL_VER).dll.alibmcpp-$(DLL_VER).dll.amcpp$(DLL_VER).lib
                Packit Service 8bf002
                Packit Service 8bf002
                Packit Service 8bf002

                $(SHL_VER) は mcpp V.2.6.3, V.2.6.4 では 0、V.2.7 では 1、V.2.7.1 では 2、V.2.7.2 では 3 です。

                Packit Service 8bf002
                $(SHLIB_VER) は mcpp V.2.6.3 では 0.0.0、V.2.6.4 では 0.0.1、V.2.7 では 0.1.0、V.2.7.1 では 0.2.0、V.2.7.2 では 0.3.0 です。
                Packit Service 8bf002
                $(DLL_VER) は mcpp V.2.6.3, V.2.6.4, V.2.7, V.2.7.1, V.2.7.2 ともに 0 です。
                Packit Service 8bf002
                $(SHLIB_VER) の1ケタ目または $(DLL_VER) が同じ場合は、$(SHLIB_VER) の2ケタ目以降の高いバージョンは低いバージョンの上位互換の関係にあります。

                Packit Service 8bf002

                Windows 上の処理系では import library というものも生成されますが、これは DLL を使うためのものです。

                Packit Service 8bf002
                DLL を使うときはこの import library をリンクします。
                Packit Service 8bf002
                Static library と import library は makefile 中で指定された $(LIBDIR) に、DLL 本体は $(BINDIR) にインストールされます。
                Packit Service 8bf002
                DLL を $(BINDIR) にインストールするのは、Windows では DLL は実行プログラムの PATH の通ったディレクトリになければならないからです。
                Packit Service 8bf002

                mcpp_lib.h, mcpp_out.h が $(INCDIR) にインストールされます。

                Packit Service 8bf002

                ライブラリ版をリンクする main_mcpplib.c もコンパイルされて mcpp という名前で $(BINDIR) にインストールされます。

                Packit Service 8bf002
                Windows 上の処理系ではさらに 'DLL_IMPORT=1' というオプションを指定すると、DLL 版の mcpp がリンクされます。

                Packit Service 8bf002

                次のようにすると、testmain.c というサンプルをメインプログラムとしてライブラリ版の mcpp がリンクされます。

                Packit Service 8bf002
                Packit Service 8bf002
                make testmain
                Packit Service 8bf002
                make testmain_install
                Packit Service 8bf002
                Packit Service 8bf002

                testmain.c にはメモリ上のバッファに出力する例も書いてあります。

                Packit Service 8bf002
                メモリに出力するには、メインプログラム中で mcpp_lib.h というヘッダファイルを include して、そこで宣言されている関数を使います。
                Packit Service 8bf002
                上記のコマンドに 'OUT2MEM=1' というオプションを付け加えると、testmain.c でこれが有効になります。
                Packit Service 8bf002
                <samp>OUT2MEM</samp> というマクロは単に testmain.c のためのもので、mcpp のためにはこのマクロは必要ありません。

                Packit Service 8bf002

                ライブラリ版を使うときは、testmain.c を参考に main プログラムを書き、noconfig/*.mak を参考に makefile を書いてください。

                Packit Service 8bf002
                Packit Service 8bf002

                3.12.3. static library と shared library および DLL

                Packit Service 8bf002

                ライブラリには static library と shared library(Windows 上では dynamically-linking library: DLL)とあります。

                Packit Service 8bf002
                Static library は *.o (*.obj) ファイルを集めたもので、コンパイル時にリンクされます。
                Packit Service 8bf002
                その変数や関数の global name はそのまま呼び出し側の global name となり、名前の衝突の危険もあります。
                Packit Service 8bf002
                このことは、V.2.6.1 まではライブラリ化を予定せずに開発されてきた mcpp にとっては大きな問題となります。
                Packit Service 8bf002
                これに対して shared library (DLL) は実行時にリンクされるもので、他のプログラムと共有されます。

                Packit Service 8bf002

                Windows 上の DLL ではライブラリの global name は外からは見えず、明示的に export された名前だけが外から import 可能です。

                Packit Service 8bf002
                mcpp の場合は mcpp_lib.h にある名前だけを import できます。

                Packit Service 8bf002

                UNIX 上の shared library では、一般にはライブラリの global name は外から丸見えで、名前の衝突に神経を使わなければなりません。

                Packit Service 8bf002
                しかし、GCC 4.0 以降で mcpp V.2.7 以降をコンパイルした場合は、mcpp_lib.h にある名前以外は外からは見えません。*1, *2

                Packit Service 8bf002

                こういうことで、Windows 上では DLL を使い、UNIX 上では GCC 4.0 以降でコンパイルした shared library を使うのが、名前の衝突が起こらず安心です。

                Packit Service 8bf002

                注:

                Packit Service 8bf002

                *1 mcpp V.2.7 以降では GCC V.4.0 で実装された #pragma GCC visibility * というディレクティブを使うようにしたためである。

                Packit Service 8bf002

                *2 なお、GCC V.4.1 以降には -fstack-protector というオプションがあるが、これは #pragma GCC visibility hidden とは両立しないようである。

                Packit Service 8bf002
                したがって、libmcpp のコンパイルでは使えない。

                Packit Service 8bf002

                Packit Service 8bf002
                Packit Service 8bf002

                4. 各処理系に移植する方法:詳細

                Packit Service 8bf002
                Packit Service 8bf002

                4.1. noconfig.H, configed.H, system.H の設定

                Packit Service 8bf002

                これらのヘッダファイルに記述されていることの意味は、たいていは読めばわかると思います。コメントも多く書き込んであります。さらに念のために以下に注釈を書いておきます。

                Packit Service 8bf002
                設定の PART 1, PART 2 は <samp>noconfig.H (configed.H)</samp> にあり、PART 3 は <samp>system.H</samp> にあります。

                Packit Service 8bf002

                まず、ターゲットシステム(mcpp を移植するシステム)とホストシステム(mcpp をコンパイルするシステム)を指定します。

                Packit Service 8bf002
                  Packit Service 8bf002
                • <samp>SYSTEM</samp>
                • Packit Service 8bf002
                  ターゲット処理系が動くOSを指定します。OSの名前はこの直後に定義されています。名前が定義されていないOSは適宜定義してください。
                  Packit Service 8bf002
                • <samp>COMPILER</samp>
                • Packit Service 8bf002
                  ターゲット処理系を指定します。コンパイラの名前はこの直後に定義されています。名前が定義されていないコンパイラは適宜定義してください。COMPILERINDEPENDENT に定義すると、ターゲット処理系の存在しない compiler-independent 版の mcpp が生成されます。この場合は PART 1 の多くの設定が無視されます。
                  Packit Service 8bf002
                • <samp>VERSION_MSG</samp>
                • Packit Service 8bf002
                  -v オプションや usage() 文で表示するためのホスト処理系のバージョン情報を文字列リテラルで書きます。
                  Packit Service 8bf002
                • <samp>HOST_SYSTEM, HOST_COMPILER</samp>
                • Packit Service 8bf002
                  ホストOS、ホスト処理系を指定します。ターゲットと同じ場合は、
                  Packit Service 8bf002
                  Packit Service 8bf002
                  #define HOST_SYSTEM     SYSTEM
                  Packit Service 8bf002
                  #define HOST_COMPILER   COMPILER
                  Packit Service 8bf002
                  Packit Service 8bf002
                  としておきます。
                  Packit Service 8bf002
                  Packit Service 8bf002

                  SYSTEM, COMPILER の命名には一定の規則がありますが、ソースを見たほうがわかりやすいでしょう。いささか仰々しい形になっていますが、SYSTEM はインクルードファイルのパスリストの形式やOS標準のインクルードディレクトリ等を知るためにしか使われていないので、あまり考える必要はありません。

                  Packit Service 8bf002
                  Packit Service 8bf002

                  4.1.1. PART 1 ターゲットシステムの設定: compiler-specific-build

                  Packit Service 8bf002
                  Packit Service 8bf002

                  4.1.1.1. 事前定義マクロ

                  Packit Service 8bf002
                    Packit Service 8bf002
                  • <samp>SYSTEM_OLD, SYSTEM_STD1, SYSTEM_STD2, SYSTEM_EXT, SYSTEM_EXT2, COMPILER_OLD, COMPILER_STD1, COMPILER_STD2, COMPILER_EXT, COMPILER_EXT2</samp>
                  • Packit Service 8bf002
                    mcpp で predefine する処理系固有のマクロの名前を文字列リテラルで指定します。不要なものは定義しないでおきます(0 個のトークンに定義してはいけない)。*_OLD で生成されるのは '_' (underline) で始まらない古い流儀のマクロで、これらは mcpp 実行時に -S <n> オプションで <n> に 1 以上を指定すると predefine されません(ただし、GCC-specific-build の STD モードでは、-ansi または -std=iso* オプションが指定されない限り、これらのマクロも定義される)。
                    Packit Service 8bf002
                    *_STD?, *_EXT, *_EXT2 では必ず _ で始まるマクロ名を指定します。*_STD1 は <samp>__</samp> で始まるもので、*_STD2 は <samp>__</samp> で始まって <samp>__</samp> で終わるものです。SYSTEM_EXT, SYSTEM_EXT2, COMPILER_STD1, COMPILER_STD2, COMPILER_EXT, COMPILER_EXT2 ではそのマクロの値も SYSTEM_EXT_VAL, SYSTEM_EXT2_VAL, COMPILER_STD1_VAL, COMPILER_STD2_VAL, COMPILER_EXT_VAL, COMPILER_EXT2_VAL で指定します。これは整数を "" で囲んだ文字列リテラルで指定します。0 個のトークンに展開されるマクロは "" と定義します。指定されなければ、そのマクロの値は 1 になります。その他の predefined マクロ(SYSTEM_OLD, SYSTEM_STD1, SYSTEM_STD2, COMPILER_OLD で指定されるもの)はすべて 1 の値を持ちます。
                    Packit Service 8bf002
                  • <samp>SYSTEM_SP_OLD, SYSTEM_SP_STD</samp>
                  • Packit Service 8bf002
                    処理系固有の特殊な事前定義マクロの名前を文字列リテラルで書き、その値を SYSTEM_SP_OLD_VAL, SYSTEM_SP_STD_VAL で定義します。
                    Packit Service 8bf002
                  • <samp>COMPILER_SP1, COMPILER_SP2, COMPILER_SP3</samp>
                  • Packit Service 8bf002
                    処理系固有の特殊な事前定義マクロの名前を文字列リテラルで書き、その値を COMPILER_SP1_VAL, COMPILER_SP2_VAL, COMPILER_SP3_VAL で定義します。
                    Packit Service 8bf002
                  • <samp>COMPILER_CPLUS, COMPILER_CPLUS_VAL</samp>
                  • Packit Service 8bf002
                    -+ オプション(C++ プリプロセス)を指定した時に定義される処理系固有の事前定義マクロの名前とその値を上記と同じように文字列リラテルで指定します。COMPILER_CPLUS_VAL を指定しないと、そのマクロの値は 1 になります。名前は '_' で始まるものでなければなりません。必要がなければ COMPILER_CPLUS そのものを定義しないでおきます。
                    Packit Service 8bf002
                    Packit Service 8bf002

                    このほか、実行時オプションに応じて <samp>system.c</samp> で定義される事前定義マクロもあります。CPU-dependent なマクロなどです。GCC V.3.3 以降では大量の事前定義マクロがあるので、これらの設定とは別に <samp>mcpp_g*.h</samp> という名前の4本の専用のヘッダファイルが mcpp のインストール時に自動的に生成されます。

                    Packit Service 8bf002

                    以上の設定で事前定義されたマクロはすべて実行時には -N オプションで無効となります。

                    Packit Service 8bf002
                    Packit Service 8bf002

                    4.1.1.2. Include ディレクトリ等

                    Packit Service 8bf002
                      Packit Service 8bf002
                    • <samp>C_INCLUDE_DIR1, C_INCLUDE_DIR2, CPLUS_INCLUDE_DIR1, CPLUS_INCLUDE_DIR2, CPLUS_INCLUDE_DIR3</samp>
                    • Packit Service 8bf002
                      mcpp でサーチする標準ヘッダファイルの include directory を指定します。CPLUS_INCLUDE_DIR? は C++ の include directory がCのものと違っている場合に、設定します(mcpp を起動する時に -+ オプションを指定することで有効となる)。UNIX の /usr/include, /usr/local/include は <samp>system.c</samp> で設定されるので、C_INCLUDE_DIR? にはそれ以外の処理系固有のものを指定します。
                      Packit Service 8bf002
                    • <samp>ENV_C_INCLUDE_DIR, ENV_CPLUS_INCLUDE_DIR</samp>
                    • Packit Service 8bf002
                      mcpp でサーチする標準ヘッダファイルの include directory を実行時に環境変数で指定する場合のために、その環境変数の名前に定義します。ENV_CPLUS_INCLUDE_DIR は C++ の include directory を指定する環境変数の名前です。デフォルトではそれぞれ "INCLUDE", "CPLUS_INCLUDE" に定義されます。GCC-specific-build では "C_INCLUDE_PATH", "CPLUS_INCLUDE_PATH" がデフォルトです。
                      Packit Service 8bf002
                      サーチパスはその外、<samp>system.c</samp> で設定されるもの、-I オプションで設定されるものがあります(それらの優先順位については mcpp-manual.html#4.2 を参照)。
                      Packit Service 8bf002
                    • <samp>ENV_SEP</samp>
                    • Packit Service 8bf002
                      この環境変数に複数のパスを書く時の separator を文字定数で書きます。
                      Packit Service 8bf002
                      <samp>/usr/local/abc/include:/usr/local/xyz/include</samp> と書く時の ':' や
                      Packit Service 8bf002
                      <samp>C:/BC55/INCLUDE;C:/BC55/LOCAL/INCLUDE</samp> と書く時の ';' がこれです。
                      Packit Service 8bf002
                    • <samp>SEARCH_INIT</samp>
                    • Packit Service 8bf002
                      ターゲット処理系が include ファイルをサーチする時のルールを書きます。#include "../dir/header.h" といったディレクティブを処理する時に、include ディレクトリをサーチする前にどのディレクトリをサーチするのかというルールです。カレントディレクトリからの相対パスをサーチする処理系では CURRENT とし、ソースファイル(include 元)のあるディレクトリからの相対パスをサーチする処理系では SOURCE とします。この両者の組合わせである場合は (CURRENT & SOURCE) とします。
                      Packit Service 8bf002
                      Packit Service 8bf002
                      Packit Service 8bf002

                      4.1.1.3. 行番号情報の出力形式その他

                      Packit Service 8bf002
                        Packit Service 8bf002
                      • <samp>LINE_PREFIX</samp>
                      • Packit Service 8bf002
                        mcpp から compiler-proper にファイル名と行番号情報を伝える形式を設定します。
                        Packit Service 8bf002
                        Packit Service 8bf002
                        #line 123 "fname"
                        Packit Service 8bf002
                        Packit Service 8bf002
                        というCのソースの形式がデフォルトとなっています。その他の形式を使う処理系では、この <samp>"#line "</samp> の部分を置き換える sequence を文字列リテラルで書いておきます。
                        Packit Service 8bf002
                        Packit Service 8bf002
                        # 123 "fname"
                        Packit Service 8bf002
                        Packit Service 8bf002
                        という形式なら <samp>"# "</samp> と定義し、どちらでもない独自の形式ならそれに合わせて定義します(場合によっては <samp>main.c</samp> の sharp() 等に書き足さなければならないかもしれない)。
                        Packit Service 8bf002
                        Visual C++ .net や Borland C のような1パスコンパイラの前段に mcpp を使う場合は、組み込みプリプロセッサに出力を渡すことになるので、mcpp の出力はCのソースになっていなければなりません。したがって、行番号の受け渡しは1番目の形式でなければなりません。
                        Packit Service 8bf002

                        Packit Service 8bf002
                      • <samp>EMFILE</samp>
                      • Packit Service 8bf002
                        <samp><errno.h></samp> で too many open files (for the process) を意味する errno の値を表すマクロが EMFILE でない場合は、EMFILE をそのマクロ名に定義します(もちろん、<samp><errno.h></samp> 自体に書き加えてもかまわない)。
                        Packit Service 8bf002
                      • <samp>ONE_PASS</samp>
                      • Packit Service 8bf002
                        ターゲット処理系がプリプロセッサの分離されていないいわゆる「ワンパスコンパイラ」であればこれを TRUE に、そうでなければ FALSE に定義します。これを TRUE とすると、#pragma MCPP put_defines (#put_defines) では、処理系の事前定義マクロはすべてコメントで囲んで出力します。ワンパスコンパイラでは mcpp の出力をこれに与えると再度プリプロセスされることになるので、二重定義を避けるためです。
                        Packit Service 8bf002
                        ただし、GCC V.3, V.4 はワンパスコンパイラとも言えますが、独立したプリプロセッサを使うこともできるので、このマクロは FALSE としておきます。
                        Packit Service 8bf002
                      • <samp>FNAME_FOLD</samp>
                      • Packit Service 8bf002
                        Windows のようにファイル名の大文字と小文字が区別されないOSではこれを TRUE と定義し、そうでなければ FALSE とします。
                        Packit Service 8bf002
                        Packit Service 8bf002
                        Packit Service 8bf002

                        4.1.1.4. 処理系の言語仕様に応じた設定

                        Packit Service 8bf002
                          Packit Service 8bf002
                        • <samp>EXPAND_PRAGMA</samp>
                        • Packit Service 8bf002
                          #pragma 行の引数が STDC 以外であればマクロ展開の対象となる処理系では、これを TRUE に定義します。デフォルトでは FALSE としています。Visual C, Borland C では #pragma 行の引数は常にマクロ展開の対象となるので、これは TRUE とします。C99 では #pragma の引数がマクロ展開の対象となるかどうかは implementation-defined で、C90 ではマクロ展開されないのが規定なのですが、しかし、mcpp は Visual C, Borland C 用に限っては C99 でなくてもマクロ展開の対象とします(引数が STDC または MCPP で始まらない限り)。
                          Packit Service 8bf002

                          Packit Service 8bf002
                        • <samp>HAVE_DIGRAPHS</samp>
                        • Packit Service 8bf002
                          Digraphs 処理が実装されている場合は TRUE、そうでなければ FALSE とします。
                          Packit Service 8bf002
                        • <samp>STDC</samp>
                        • Packit Service 8bf002
                          ターゲット処理系の事前定義マクロ <tt>__STDC__</tt> のデフォルト値に定義します。<tt>__STDC__</tt> が定義されていなければ 0 とします。
                          Packit Service 8bf002
                        • <samp>STDC_VERSION</samp>
                        • Packit Service 8bf002
                          ターゲット処理系の事前定義マクロ <tt>__STDC_VERSION__</tt> のデフォルト値に定義します。<tt>__STDC_VERSION__</tt> が定義されていなければ 0L とします。
                          Packit Service 8bf002

                          Packit Service 8bf002
                        • <samp>CHARBIT, UCHARMAX, LONGMAX, ULONGMAX</samp>
                        • Packit Service 8bf002
                          ターゲット処理系の <samp><limits.h></samp> の <tt>CHAR_BIT, UCHAR_MAX, LONG_MAX, ULONG_MAX</tt> の値を書きます。
                          Packit Service 8bf002
                          ただし、<samp>limits.h</samp> の <tt>UCHAR_MAX</tt> の定義は間違っている場合があるので、注意が必要です。255U, 0xffU 等と unsigned にしてはいけません。255, 0xff 等と signed int の値に定義します(cpp-test.html#5.1.3 参照)。
                          Packit Service 8bf002
                          Packit Service 8bf002
                          Packit Service 8bf002

                          4.1.1.5. Multi-byte character

                          Packit Service 8bf002

                          MBCHAR というマクロは multi-byte character の encoding を指定するものです。mcpp では下記の数種の encoding がすべて同時に実装されます。MBCHAR はデフォルトの encoding を指定するだけで、実行時に encoding を環境変数・オプション・#pragma で変更することができます(使い方については mcpp-manual.html#2.3, mcpp-manual#2.8, mcpp-manual.#3.4 を参照)。

                          Packit Service 8bf002
                            Packit Service 8bf002
                          • <samp>MBCHAR</samp>
                          • Packit Service 8bf002
                            ターゲットの multi-byte character(日本語では漢字)の encoding の種類を定義します。
                            Packit Service 8bf002
                            Packit Service 8bf002
                            Packit Service 8bf002
                              EUC_JP    日本の extended UNIX code (UJIS)
                            Packit Service 8bf002
                              SJIS      日本の shift-JIS (MS-Kanji)
                            Packit Service 8bf002
                              GB2312    中国の EUC-like な GB-2312(簡体字)
                            Packit Service 8bf002
                              BIGFIVE   台湾の Big5(繁体字)
                            Packit Service 8bf002
                              KSC5601   韓国の EUC-like な KSC-5601 (KSX 1001)
                            Packit Service 8bf002
                              ISO2022_JPISO-2022-JP1 という国際規格の日本語
                            Packit Service 8bf002
                              UTF8      unicode の encoding の1種である UTF-8
                            Packit Service 8bf002
                            Packit Service 8bf002
                            Packit Service 8bf002
                            初めの5つはいずれも shift-states を持たない、1文字が2バイトを占める encoding です。なお、multi-byte character, wide character の encoding が2バイトであるにもかかわらず、wchar_t が4バイトの型になっている処理系もありますが、プリプロセッサは wchar_t の型には関知しません。ソース上では multi-byte character や wide character が2バイトを占めているので、それに従って処理をします。
                            Packit Service 8bf002
                            ISO-2022-* は shift-states を持つ encoding です。UTF-8 は2バイトの unicode を1バイトないし3バイトで encode するものです。漢字は3バイトになります。
                            Packit Service 8bf002
                            MBCHAR を 0 に定義した場合、multi-byte character の処理をしないのがデフォルトの仕様になるだけで、環境変数・オプション・#pragma で実行時に変更されます。
                            Packit Service 8bf002

                            Packit Service 8bf002
                          • <samp>SJIS_IS_ESCAPE_FREE</samp>
                          • Packit Service 8bf002
                            コンパイラ本体が shift-JIS の処理をする場合は TRUE とし、しない場合は FALSE とします。
                            Packit Service 8bf002
                            Shift-JIS では漢字の2バイト目が '\\' と同じ 0x5c の値になることがあります。コンパイラ本体が shift-JIS を認識しない場合は、これを escape sequence と解釈してしまい、tokenization でエラーになります。
                            Packit Service 8bf002
                            SJIS_IS_ESCAPE_FREEFALSE とすると、mcpp が処理を補います。すなわち、最終出力の時に、文字列リテラルまたは文字定数の中の shift-JIS 漢字第2バイトが 0x5c であった場合は、そこに 0x5c のバイトをもう1つ付加します。これによって、英語版のコンパイラを一応 shift-JIS に対応させることができます。
                            Packit Service 8bf002
                          • <samp>BIGFIVE_IS_ESCAPE_FREE</samp>
                          • Packit Service 8bf002
                            同様に、コンパイラ本体が Big 5 の処理をする場合はこれを TRUE とし、しない場合は FALSE とします。
                            Packit Service 8bf002
                          • <samp>IS02022_JP_IS_ESCAPE_FREE</samp>
                          • Packit Service 8bf002
                            同様に、コンパイラ本体が ISO-2022-JP の処理をする場合はこれを TRUE とし、しない場合は FALSE とします。IS0-2022-* では '\\' ばかりでなく、'\'' や '"' と一致するバイトも出現します。ISO2022_JP_IS_ESCAPE_FREEFALSE の場合は mcpp は、'\\', '\'', '"' と一致するバイトの直前にすべて 0x5c のバイトを1つ挿入します。
                            Packit Service 8bf002
                            Packit Service 8bf002

                            なお、multi-byte character に関するコンパイラの動作は実行する時の環境によって変わる場合があります。自分の使う環境に合わせて設定してください。これについては、mcpp-manual.html#2.8 も参照してください。

                            Packit Service 8bf002
                            Packit Service 8bf002

                            4.1.1.6. ターゲットとホストに共通の設定

                            Packit Service 8bf002

                            次の2つは便宜上、PART 2 に書いてありますが、

                            Packit Service 8bf002
                            ターゲット処理系とホスト処理系の双方が指定の型を持つ場合に TRUE とし、そうでない場合は FALSE とします。

                            Packit Service 8bf002
                              Packit Service 8bf002
                            • <samp>HAVE_LONG_LONG</samp>
                            • Packit Service 8bf002
                              long long というデータ型を持つ処理系ではこれを TRUE とします。
                              Packit Service 8bf002
                              Visual C の 2005 までや Borland C 5.* のように、long long はないが __int64 という同じサイズの型があり printf() で表示するための length modifier も用意されている場合は、これは TRUE とします。
                              Packit Service 8bf002
                              Visual C 2008 では long long が使えます。
                              Packit Service 8bf002
                            • <samp>HAVE_INTMAX_T</samp>
                            • Packit Service 8bf002
                              intmax_t というデータ型が定義されていればこれを TRUE とします。
                              Packit Service 8bf002

                              Packit Service 8bf002
                            • <samp>LL_FORM</samp>
                            • Packit Service 8bf002
                              双方の処理系が long long を持っている場合は、ホスト処理系の最大の整数型の値を printf() で表示するための length modifier を文字列リテラルで定義します。C99 では "j" です。また、C99 では long long の length modifier は "ll" (ell-ell) です。Visual C の 2003 までと Borland C 5.* では __int64 の値を表示する "I64" を使います。MinGW でも "I64" です。
                              Packit Service 8bf002
                              Packit Service 8bf002
                              Packit Service 8bf002

                              4.1.2. PART 2 ホストシステムの設定

                              Packit Service 8bf002

                              <samp>noconfig.H, configed.H</samp> ではターゲット処理系とホスト処理系とが同一であると仮定していますが、異なる場合は PART 2 を書き直す必要があります。

                              Packit Service 8bf002
                                Packit Service 8bf002
                              • HOST_HAVE_STPCPY</samp>
                              • Packit Service 8bf002
                                ホスト処理系のライブラリに stpcpy() があれば TRUE に、なければ FALSE に定義します。FALSE であれば stpcpy() には <samp>system.c</samp> のものが使われます。
                                Packit Service 8bf002
                              • <samp>PATHMAX</samp>
                              • Packit Service 8bf002
                                ホスト処理系の <samp><limits.h</samp>> の <tt>PATH_MAX</tt> の値です。
                                Packit Service 8bf002
                                これは POSIX で規定されているマクロですが、これがない処理系では <samp><stdio.h</samp>> の <tt>FILENAME_MAX</tt> の値を使います。
                                Packit Service 8bf002
                                Packit Service 8bf002

                                PART 1 にもホストとターゲットが同一と仮定している部分があるので、必要ならそれを書き換えます。例えば次のようにホスト処理系の事前定義マクロを使っている行です。

                                Packit Service 8bf002
                                Packit Service 8bf002
                                #if _MSC_VER >= 1200
                                Packit Service 8bf002
                                Packit Service 8bf002
                                Packit Service 8bf002

                                4.1.3. PART 3 mcpp の動作仕様の設定

                                Packit Service 8bf002
                                Packit Service 8bf002

                                4.1.3.1. 新旧各種の動作モード

                                Packit Service 8bf002

                                <samp>system.H</samp> では mcpp の動作仕様を指定するマクロが定義されています。

                                Packit Service 8bf002

                                mcpp には mcpp_mode という変数があり、これがマクロの展開方法、使えるディレクティブ、使える predefined マクロ等、プリプロセッサの根幹となる動作の仕様を決めています。mcpp_mode の値には OLD_PREP, KR, STD, POST_STD の4種があります。

                                Packit Service 8bf002
                                mcpp の動作モードは実行時オプションで指定されます。mcpp をコンパイルする時には、これらの4つのマクロについては何も設定することはありません。しかし、各種の設定を正しく行うためには4つの動作仕様の違いを理解することが必要です。
                                Packit Service 8bf002
                                このほかに COMPAT モードもありますが、これは STD の変種です。

                                Packit Service 8bf002
                                  Packit Service 8bf002
                                • <samp>OLD_PREP</samp>
                                • Packit Service 8bf002
                                  いわゆる "Reiser" model cpp の動作仕様です。
                                  Packit Service 8bf002
                                • <samp>KR</samp>
                                • Packit Service 8bf002
                                  C90 以前の K&R 1st. のプリプロセス仕様です。
                                  Packit Service 8bf002
                                • <samp>STD</samp>
                                • Packit Service 8bf002
                                  規格 (C90, C99, C++98) 準拠のプリプロセス仕様です。
                                  Packit Service 8bf002
                                • <samp>POST_STD</samp>
                                • Packit Service 8bf002
                                  筆者が勝手に作ったプリプロセス仕様で、規格の首尾一貫しない規定を整理して単純化したものです。
                                  Packit Service 8bf002
                                  Packit Service 8bf002

                                  ここでは KROLD_PREP を合わせて pre-Standard モード、STDPOST_STD を合わせて Standard モードと呼ぶことにします。各モードの仕様の詳細については mcpp-manual.html#2.1 を参照してください。

                                  Packit Service 8bf002
                                  Packit Service 8bf002

                                  4.1.3.2. 動作モードの細部の指定

                                  Packit Service 8bf002
                                    Packit Service 8bf002
                                  • <samp>CPLUS</samp>
                                  • Packit Service 8bf002
                                    -+ オプションで C++ のプリプロセッサとして動作させた時に、標準組み込みマクロ <tt>__cplusplus</tt> がこの値に事前定義されます。C++98 では 199711L です。-V オプションによって実行時に変更できます。
                                    Packit Service 8bf002
                                  • <samp>TRIGRAPHS_INIT</samp>
                                  • Packit Service 8bf002
                                    STD モードでの trigraph 処理の初期状態を指定します。-3 オプションはその状態を反転させます。これを TRUE にすると、default で trigraph が認識され、-3 オプションで起動すると認識しません。FALSE の場合は逆に default で認識せず、-3 オプションで認識するようになります。
                                    Packit Service 8bf002
                                  • <samp>DIGRAPHS_INIT</samp>
                                  • Packit Service 8bf002
                                    Standard モードでの digraph 処理の初期状態を指定します。-2 オプションはその状態を反転させます。これを TRUE にすると、default で digraph が認識され、-2 オプションで起動すると認識しません。FALSE の場合は逆に default で認識せず、-2 オプションで認識するようになります。
                                    Packit Service 8bf002
                                    HAVE_DIGRAPHS == FALSE の処理系の場合、digraphs は mcpp が通常のトークンに変換します。
                                    Packit Service 8bf002
                                  • <samp>OK_UCN</samp>
                                  • Packit Service 8bf002
                                    STD モード で -V199901L または -+ オプションを指定した時に UCN (universal-character-name) を有効にするには、これを TRUE に定義します。デフォルトでは TRUE としています。*1
                                    Packit Service 8bf002
                                  • <samp>OK_MBIDENT</samp>
                                  • Packit Service 8bf002
                                    STD モード で -V199901L オプションを指定したときに identifier 中に multi-byte character を使えるようにするには、これを TRUE に定義します。デフォルトでは FALSE としています。
                                    Packit Service 8bf002

                                    Packit Service 8bf002
                                  • <samp>expr_t, uexpr_t</samp>
                                  • Packit Service 8bf002
                                    最も大きい整数の型に typedef で定義します。intmax_t, uintmax_t という型があればそれに、そうでなくて long long, unsigned long long を持つ処理系ではそれに、そうでなくて __int64, unsigned __int64 を持つ処理系ではそれに、そうでなければ long, unsigned long に定義します。
                                    Packit Service 8bf002
                                  • <samp>EXPR_MAX</samp>
                                  • Packit Service 8bf002
                                    uexpr_t の最大値に定義します。
                                    Packit Service 8bf002
                                    Packit Service 8bf002

                                    注:

                                    Packit Service 8bf002

                                    *1 UCN は C++, C99 の仕様で、Unicode の文字の値を \u または \U で始まる16進 escape sequence で表記するものである(mcpp-manual.html#3.7, cpp-test.html#2.8, cpp-test.html#4.6 参照)。

                                    Packit Service 8bf002

                                    Packit Service 8bf002
                                    Packit Service 8bf002

                                    4.1.3.3. Translation limits の指定

                                    Packit Service 8bf002
                                      Packit Service 8bf002
                                    • <samp>RESCAN_LIMIT</samp>
                                    • Packit Service 8bf002
                                      Standard モードでのマクロ展開時の再走査回数の限度を定義します。
                                      Packit Service 8bf002
                                      Standard モード では再走査回数は少ないので、あまり大きな値を設定する必要はありません。
                                      Packit Service 8bf002
                                    • <samp>PRESTD_RESCAN_LIMIT</samp>
                                    • Packit Service 8bf002
                                      pre-Standard モードでのマクロ展開時の再走査回数の限度を定義します。pre-Standard モード では再帰的なマクロ展開によって無限ループが発生しえますが、それがこのリミットにひっかかります。
                                      Packit Service 8bf002
                                    • <samp>NBUFF</samp>
                                    • Packit Service 8bf002
                                      論理行(ソースの物理行の行末の \ を取って接続した行)の最大長 +1 を定義します。コメントを a space に変換した後の行(コメントによって複数の論理行にまたがることもありうる)もこの長さにおさまっていなければなりません。
                                      Packit Service 8bf002
                                    • <samp>NMACWORK</samp>
                                    • Packit Service 8bf002
                                      マクロ展開の内部的なバッファのサイズを定義します。すなわち、1つの論理行中のマクロを展開した結果(マクロ呼び出しが複数行にまたがる場合は、それを展開した結果)はこのサイズにおさまっていなければなりません。これはまた、1つのマクロ定義の置換リストを内部的に記憶する際の最大長としても使われます。これは NBUFF*2 以上で NWORK*2 以上でなければなりません。
                                      Packit Service 8bf002
                                    • <samp>NWORK</samp>
                                    • Packit Service 8bf002
                                      mcpp の出力する最大行長を定義します。これは compiler-proper の受け取れる最大行長+1 を越えてはいけません。また、NBUFF の値を越えてもいけません。マクロ展開後の行長がこれを越えた時は、mcpp がこれ以下の行長に分割して出力します。文字列リテラルの長さは NWORK-2 の範囲に収まっていなければなりません(文字列リテラルの長さというのは、char 配列の要素数のことではなく、ソース上での文字列リテラルというトークンの長さである。両端の " を含み、\n 等は2バイトと数える。ワイド文字列リテラルでは先頭の L も含む)。
                                      Packit Service 8bf002
                                      ただし、GCC 版および Visual C 版では出力の最大行長としては NWORK ではなく NMACWORK を使います。
                                      Packit Service 8bf002
                                      これらの処理系ではコンパイラがかなり長い行を受け取ることができるので、分割して出力する必要がないからです。
                                      Packit Service 8bf002
                                    • <samp>IDMAX</samp>
                                    • Packit Service 8bf002
                                      識別子の最大長を定義します。これより長い名前もエラーにはなりませんが、この長さに切り詰められます。
                                      Packit Service 8bf002
                                    • <samp>NMACPARS</samp>
                                    • Packit Service 8bf002
                                      関数様マクロの引数の最大数を定義します。これは UCHARMAX よりも大きくはできません。
                                      Packit Service 8bf002
                                    • <samp>NEXP</samp>
                                    • Packit Service 8bf002
                                      #if 行の式のカッコでくくられるネストレベルの限度を定義します(本当はネストレベルがこれで直接決まるわけではない。正確には、式中の定数トークンの数がこの2倍、演算子トークンの数がこの3倍まで使える。かっこは一対で2つと数える)。
                                      Packit Service 8bf002
                                    • <samp>BLK_NEST</samp>
                                    • Packit Service 8bf002
                                      #if (#ifdef, #ifndef) section のネストレベルの限度(#if, etc. が何段階にネストできるか)を定義します。
                                      Packit Service 8bf002
                                    • <samp>INCLUDE_NEST</samp>
                                    • Packit Service 8bf002
                                      #include のネストレベルの限度を定義します。#include の無限再帰をチェックするためのものです。同時にオープンできるファイルの数に関する OS の制限を超えていてもかまいません。
                                      Packit Service 8bf002
                                    • <samp>SBSIZE</samp>
                                    • Packit Service 8bf002
                                      マクロを内部的に hash で分類して記憶する際の hash table の要素数を定義します。必ず2のベキ乗でなければなりません。マクロの数より小さくても動作は正常にしますが、大きいほうが処理はやや速くなります。
                                      Packit Service 8bf002
                                      Packit Service 8bf002

                                      それぞれ大きい値にするほど仕様は上等になりますが、NWORK, NBUFF, NMACWORK, SBSIZE は大きいとそれだけ大きなメモリを食います。実際のメモリ消費はマクロ定義の量によってさらに増えてゆきます(それぞれのマクロ定義の長さによって必要メモリが決まる。マクロ定義の内部的な形式は <samp>internal.H</samp> の struct defbuf に書いてある)。

                                      Packit Service 8bf002

                                      NMACWORK, NEXP, RESCAN_LIMIT はスタックを消費します。

                                      Packit Service 8bf002
                                      他のものはメモリはさほど必要としませんが、<samp>system.H</samp> のデフォルトの値以上にしても実用上の意味はほとんどないでしょう。

                                      Packit Service 8bf002

                                      C90, C99 の要求する translation limits の最低限度は <samp>system.H</samp> の最後のほうに書いてあります。C++98 の translation limits も書いてありますが、これはCと異なり、要求仕様ではありません。

                                      Packit Service 8bf002

                                      Packit Service 8bf002
                                      Packit Service 8bf002

                                      4.2. system.c

                                      Packit Service 8bf002

                                      主としてターゲット処理系に関するいくつかの設定を実装しています。

                                      Packit Service 8bf002
                                        Packit Service 8bf002
                                      • <samp>PATH_DELIM</samp>
                                      • Packit Service 8bf002
                                        OSの path-delimiter を定義しています。PATH_DELIM は \ としてはいけません(プログラムのつごうで)。Windows では / としています。ユーザプログラムではもちろん \ も使えますが、それを内部的には / に変換します。
                                        Packit Service 8bf002
                                      • <samp>OBJEXT</samp>
                                      • Packit Service 8bf002
                                        処理系の生成するいわゆるオブジェクトファイルの接尾子を文字列リテラルで定義します。UNIX 上の処理系の "o"、Windows 上の処理系の "obj" 等です。これは -M* オプションを指定した時の makefile 用依存関係行の出力に使われるものです。
                                        Packit Service 8bf002

                                        Packit Service 8bf002
                                      • <samp>do_options()</samp>
                                      • Packit Service 8bf002
                                        mcpp を起動する時のオプションを実装しています。まだ移植されていない処理系に移植する時には、その処理系付属のコンパイラドライバに合わせて、ここに何行か書き足すことが必要でしょう。do_options() に追加した時は、それに対応して次の set_opt_list(), usage() にも書き足します。
                                        Packit Service 8bf002
                                        do_options() は mcpp_getopt() を呼び出します。mcpp_getopt() は POSIX の getopt() と同じ仕様です。
                                        Packit Service 8bf002
                                        そのため、1つのオプション文字は引数なしか引数ありのどちらかに決めなければなりません。-P と -P- といったオプションの使い方は原則としてできません(しかし、処理系付属のプリプロセッサとの互換性のために必要な場合は、無理やりできなくもない。-M オプションの実装を参照)。また、-trigraphs といった長いオプションは t をオプション文字として rigraphs を引数とすることで実装するしかありません。
                                        Packit Service 8bf002
                                      • <samp>set_opt_list()</samp>
                                      • Packit Service 8bf002
                                        do_options() で使うオプション文字を設定します。
                                        Packit Service 8bf002
                                      • <samp>usage()</samp>
                                      • Packit Service 8bf002
                                        Usage 文が書かれています。
                                        Packit Service 8bf002
                                        モードごとのオプションがアルファベット順に並べられています。
                                        Packit Service 8bf002
                                      • <samp>set_sys_dirs()</samp>
                                      • Packit Service 8bf002
                                        Include directory を設定しています。<samp>noconfig.H (configed.H)</samp> のマクロ C_INCLUDE_DIR?, CPLUS_INCLUDE_DIR? で指定された処理系固有のディレクトリのほか、UNIX 系OSでの /usr/include, /usr/local/include もここで設定しています(<samp>noconfig.H, configed.H</samp> のマクロ ENV_C_INCLUDE_DIR, ENV_CPLUS_INCLUDE_DIR で定義された名前の環境変数による include directory 指定は set_env_dirs() で設定される)。
                                        Packit Service 8bf002

                                        Packit Service 8bf002
                                      • <samp>do_pragma()</samp>
                                      • Packit Service 8bf002
                                        #pragma の処理を実装しています。mcpp 自身が処理しない #pragma sub-directive はそのまま出力して compiler-proper に渡します。mcpp 自身が処理する #pragma MCPP debug 等はここから呼び出す関数で処理します。mcpp 自身が処理する #pragma sub-directive は原則として MCPP という名前で始まるようにしています。MCPP で始まる #pragma 行そのものは出力しません。また #pragma once も出力しません。しかし、#pragma __setlocale 行は出力します。規格では処理系固有の拡張 directive は #pragma sub-directive として実装することになっています。
                                        Packit Service 8bf002
                                      • <samp>do_old()</samp>
                                      • Packit Service 8bf002
                                        規格に合致しない preprocessing directive (#pragma sub-directive でない #assert, #asm, #endasm, #include_next, #warning, #put_defines, #debug 等)が必要な場合は、その処理をする関数を書き足したうえで、ここからそれを呼び出すようにします(ただし、GCC 用では #include_next, #warning は STD モード でも使えるようにしてある)。
                                        Packit Service 8bf002
                                        Packit Service 8bf002

                                        Standard C にはないライブラリ関数のうち、getopt() と stpcpy() のソースがここに書いてあります。

                                        Packit Service 8bf002
                                        getopt() はリンクのトラブルを防ぐため、mcpp_getopt() と名前を変えてあります。
                                        Packit Service 8bf002
                                        stpcpy() は HOST_HAVE_STPCPY が FALSE の時に使われます。

                                        Packit Service 8bf002

                                        Packit Service 8bf002
                                        Packit Service 8bf002

                                        4.extra. malloc()

                                        Packit Service 8bf002

                                        「kmmalloc -- デバッグ機能を持つ malloc()」というのは、私がCで書いた malloc(), free(), realloc(), calloc() の portable なソースです。これはメモリ効率を改善するとともに、デバッグのつごうを考えて書いてあります。デバッグ用のルーチンも添付してあります。これをリンクしておくと、思わぬバグがひっかかってくることがあります。*1, *2

                                        Packit Service 8bf002

                                        noconfig/*.mak で -DKMMALLOC -D_MEM_DEBUG -DXMALLOC というオプションを与えているのは、この私の malloc() 等とデバッグルーチンをリンクするためのものです。これをリンクした mcppEFREEP, EFREEBLK, EALLOCBLK, EFREEWRT, ETRAILWRT というエラー番号で途中で exit することがあれば、それは mcpp のバグを意味します。

                                        Packit Service 8bf002

                                        BSD_MALLOC, DB_MALLOC, MALLOC_DBG というマクロのどれかを 1 に定義して mcpp をコンパイルすると、私の malloc() とは別のそれぞれデバッグ機能を持った malloc() が使われます。いずれにしても、処理系付属のものではない malloc() を使うには、コンパイルする前にライブラリを作っておかなければなりません。これについては kmmalloc のドキュメントを見てください。

                                        Packit Service 8bf002

                                        注:

                                        Packit Service 8bf002

                                        *1 kmmalloc は次のところにある。

                                        Packit Service 8bf002

                                        Packit Service 8bf002
                                        Packit Service 8bf002

                                        http://download.vector.co.jp/pack/dos/prog/se026997.html

                                        Packit Service 8bf002
                                        Packit Service 8bf002

                                        *2 CygWIN ではライブラリの組み立てが他の malloc() を使えないようになっているので、私の malloc() は使っていない。

                                        Packit Service 8bf002
                                        Visual C 2005, 2008 でも同様である。

                                        Packit Service 8bf002

                                        Packit Service 8bf002
                                        Packit Service 8bf002

                                        5. バグ報告と移植の報告

                                        Packit Service 8bf002
                                        Packit Service 8bf002

                                        5.1. バグかどうか?

                                        Packit Service 8bf002

                                        プリプロセスの Standard C 適合性を検証するための Validation Suite を mcpp といっしょに公開しています。Standard C のプリプロセスのすべての規定を検証できるものにしたつもりです。もちろん、mcpp はこれを使ってチェックしてあります。それも、上記のすべての処理系でコンパイルしてチェックしてあります。したがって、バグや誤仕様はほとんどないと思いますが、しかし、まだいくつか残っている恐れもあります。まだ移植されていない処理系に新しく移植した場合は、処理系のバグにひっかかる可能性もあります。

                                        Packit Service 8bf002

                                        もし、不可解な動作が発見されたら、ぜひご報告ください。その際には、次の点のチェックをお願いします。

                                        Packit Service 8bf002
                                          Packit Service 8bf002
                                        1. STD モードの場合、自分の Standard C 解釈を確かめるため、まず Validation Suite を使ってみる。GCC / testsuite の使えるシステムでは、オプションを付けて configure して make check で自動テストができる。
                                        2. Packit Service 8bf002
                                        3. 自分の mcpp の移植に間違いはないかどうか、ドキュメントを確かめる。
                                        4. Packit Service 8bf002
                                        5. バグを再現するサンプルソースを抽出する。
                                        6. Packit Service 8bf002
                                        7. バグを引き出す部分を
                                        8. Packit Service 8bf002
                                          #pragma MCPP debug <args> と #pragma MCPP end_debug ではさんで mcpp の動作をトレースしてみる。この <args> をさらに増やしてより詳細にトレースしてみる。
                                          Packit Service 8bf002
                                          Packit Service 8bf002

                                          もし、"Bug: ..." という診断メッセージが出たら、それは間違いなく mcpp または処理系の(たぶん mcpp の)バグです。また、たとえむちゃくちゃな「ソース」でも、それを食わせることで mcpp が暴走するなら、それもバグです。

                                          Packit Service 8bf002
                                          もちろん、Standard C モード以外のモードの mcpp は Validation Suite では「間違い」だらけの動作をしますが、それは仕様です(それでも暴走はしないはず)。どういう仕様かは 4.1.3 を見てください。

                                          Packit Service 8bf002

                                          Packit Service 8bf002
                                          Packit Service 8bf002

                                          5.2. malloc() 関連のバグチェック

                                          Packit Service 8bf002

                                          私が書いた kmmalloc という malloc() 等のライブラリがあります(4.extra 参照)。

                                          Packit Service 8bf002

                                          Packit Service 8bf002
                                          もし、私のこの malloc() 等をリンクした mcpp で 120 から 124(処理系によっては 2120 から 2124)のエラー番号で途中で exit することがあれば、それは間違いなく mcpp または処理系の(たぶんライブラリ関数の)バグです。

                                          Packit Service 8bf002

                                          また、テストに使うサンプルソースのどこかに

                                          Packit Service 8bf002
                                          #pragma MCPP debug memory
                                          Packit Service 8bf002

                                          と書いておくと、その個所および終了時にヒープメモリに関する情報が出力されますが、ここで Heap error: ... というメッセージが出ることがあれば、それも間違いなく mcpp または処理系のバグです。

                                          Packit Service 8bf002

                                          これらのバグが発見されたら、サンプルソースの各部分を #if 0 と #endif ではさんでテストを繰り返し、バグを発生する部分を絞り込んでみてください。

                                          Packit Service 8bf002

                                          Packit Service 8bf002
                                          Packit Service 8bf002

                                          5.3. バグ報告を

                                          Packit Service 8bf002

                                          バグ報告には次のようなデータを付けてくださるようお願いします。

                                          Packit Service 8bf002
                                            Packit Service 8bf002
                                          1. mcpp を移植した処理系。
                                          2. Packit Service 8bf002
                                          3. 移植した方法(<samp>noconfig.H</samp> 等の設定)。
                                          4. Packit Service 8bf002

                                            Packit Service 8bf002
                                          5. バグと思われるものを再現できるサンプルソース。
                                          6. Packit Service 8bf002

                                            Packit Service 8bf002
                                          7. その処理結果。
                                          8. Packit Service 8bf002
                                            Packit Service 8bf002

                                            Packit Service 8bf002
                                            Packit Service 8bf002

                                            5.4. 移植の報告を

                                            Packit Service 8bf002

                                            mcpp はほとんどの処理系に比較的簡単に移植できるように書いてあるつもりです。

                                            Packit Service 8bf002
                                            しかし、私が持っている処理系は少数です。他の処理系への移植ではソースの書き足しが必要なはずです。それらの処理系への移植の報告をお待ちしています。それをソースにフィードバックしていきたいと思います。
                                            Packit Service 8bf002
                                            移植の報告は次のような形でお願いします。

                                            Packit Service 8bf002
                                              Packit Service 8bf002
                                            1. 処理系。
                                            2. Packit Service 8bf002

                                              Packit Service 8bf002
                                            3. <samp>noconfig.H (configed.H), system.H, system.c</samp> の設定。
                                            4. Packit Service 8bf002
                                              なるべくオリジナルとの差分ファイルが良いが、簡単なものならメモでも可。
                                              Packit Service 8bf002
                                              Packit Service 8bf002

                                              正しく移植できたかどうかを確かめるには、compiler-specific-build では、まずプリプロセッサを入れ替えて、ヘッダファイルの "pre-preprocess" の機能を使って自分自身をリコンパイルしてみるのが手っ取り早いでしょう。

                                              Packit Service 8bf002

                                              さらに Validation Suite で STD モードのチェックをします。ただ、これはファイルの数が多いので、デバッグを繰り返す時には手間がかかりすぎます。デバッグ中はまず、n_std.c をコンパイルして、正常にコンパイル・実行されるかどうかを見ます。処理系付属のコンパイラドライバでは mcpp に渡す方法のないオプションもありますが、それについては mcpp-manual.html#2.2 を見てください。先に mcpp を通してからコンパイルする手もあります。

                                              Packit Service 8bf002

                                              もしこれがうまくいかない場合は、 n_std.t というサンプルを使って、どこが悪いのか、目でチェックします。これがうまくいったら、e_std.t, m_*.t, unspcs.t, warns.t, misc.t もチェックします。"post-Standard" モードでは n_post.t, e_post.t を使います。

                                              Packit Service 8bf002

                                              これらを mcpp -QCz23 というオプションを付けて処理します(post-Standard モードでは -3 は不可)。STDC == 0 でコンパイルしてあれば -S1 -V199409L オプションも付けます。-C オプションでコメントも出力されるので、処理結果が期待通りかどうかがすぐわかります。

                                              Packit Service 8bf002
                                              -Q オプションで診断メッセージは mcpp.err というファイルに出力されるので、それをページャー等で読みます。
                                              Packit Service 8bf002
                                              -z オプションで、ヘッダファイルの出力は省略されます。
                                              Packit Service 8bf002
                                              -2 -3 で digraph と trigraph が有効になります。-S1 -V199409L で <tt>__STDC__</tt> が 1 に <tt>__STDC_VERSION__</tt> が 199409L になります。
                                              Packit Service 8bf002
                                              C99 対応のテストをするためには、-V199901L オプションを付けて n_std99.t, e_std99.t のチェックをします。

                                              Packit Service 8bf002

                                              Validation Suite の <samp>cpp_test.c</samp> というプログラムを使うと、n_*.c, i_*.c のサンプルのテストを自動的に行うことができます(ただし、これは○×をつけるだけで、詳細はわからない。また、e_*.?, u_*.?, unspcs.?, warns.? 等のテストは含まれない。mcpp 自身のテストをするためには、n_std.c をコンパイルするほうが早い)。

                                              Packit Service 8bf002

                                              なお、Validation Suite は GCC の testsuite に対応しています。したがって、mcpp を GCC のどれかのバージョンに移植した場合は、GCC / testsuite がインストールされていれば、GCC のプリプロセッサを mcpp に置き換えると、mcpp の自動テストができます。これについては cpp-test.html#3.2.3, mcpp-manual.html#3.9.7 を見てください。

                                              Packit Service 8bf002

                                              Packit Service 8bf002

                                              Packit Service 8bf002
                                              Packit Service 8bf002

                                              5.5. GCC 以外の処理系での configure の情報を

                                              Packit Service 8bf002

                                              mcpp は UNIX 系システムでは configure スクリプトが使えます。

                                              Packit Service 8bf002
                                              しかし、UNIX 系システムでの GCC 以外の処理系については私はまったく知らないので、compiler-specific-build の configure ではいくつかのオプションを指定してもらわなければなりません。

                                              Packit Service 8bf002

                                              これらのオプションで指定する内容については、その処理系を使っている人は知っているか、または調べることができるはずです。おわかりの方はぜひ教えてください。Configure に取り込んでゆきたいと思います。

                                              Packit Service 8bf002
                                              Configure については INSTALL をご覧ください。

                                              Packit Service 8bf002

                                              Packit Service 8bf002
                                              Packit Service 8bf002

                                              5.6. データを送ってくれれば移植してみます

                                              Packit Service 8bf002

                                              移植がうまくいかない場合は、そのようすをお知らせください。

                                              Packit Service 8bf002
                                              次のデータを付けてくれれば、移植したソースをお返しできるかもしれません。Configure の使える環境では、これらのデータのうちのかなりの部分を configure によって知ることができます。
                                              Packit Service 8bf002
                                              なお、C90 (ANSI C) に対応していない処理系は、mcpp V.2.6 からは移植の対象から外しました。

                                              Packit Service 8bf002
                                                Packit Service 8bf002
                                              1. OSとそのパスリストの形式(私は UNIX 系, DOS/Windows 系, OS-9 しか知らない)。
                                              2. Packit Service 8bf002
                                              3. 処理系の名前とバージョン。
                                              4. Packit Service 8bf002
                                              5. 基本文字セットは ASCII か。
                                              6. Packit Service 8bf002
                                                そうでなければどういう文字セットか。Multi-byte character(漢字)の encoding はシフト JIS か EUC-JP か、それとも何か。Shift-JIS のように <backslash> と同じコードが multi-byte character に含まれる encoding の場合、コンパイラ本体はそれを認識するか。
                                                Packit Service 8bf002
                                              7. Shell(コマンドプロセッサ)は大文字と小文字を区別するか。
                                              8. Packit Service 8bf002
                                              9. ファイル名の大文字と小文字は区別されるか。
                                              10. Packit Service 8bf002

                                                Packit Service 8bf002
                                              11. 実装したい実行時オプション。コンパイラドライバから渡されるオプション。
                                              12. Packit Service 8bf002
                                                プリプロセッサ単体で動かす時のオプション(getopt() で実装できないものは不可)。
                                                Packit Service 8bf002
                                              13. プリプロセッサが分離されている処理系か、それともいわゆるワンパスコンパイラか。
                                              14. Packit Service 8bf002
                                              15. その処理系の事前定義マクロとその値。C++ の時はどうなるか(コンパイラドライバから -D オプション等でプリプロセッサに渡されるマクロと、プリプロセッサ自身が事前定義するマクロとを区別すること)。
                                              16. Packit Service 8bf002
                                              17. long long 型はあるか。long long がある場合、printf() での long long の length modifier は何か。long long がなくても同じサイズの型があるか。
                                              18. Packit Service 8bf002
                                              19. #pragma 行の引数はマクロ展開の対象となるか。
                                              20. Packit Service 8bf002
                                              21. Include directory を指定する環境変数にはどういう名前を使うか。環境変数で複数のパスを記述する時の separator には何を使うか。
                                              22. Packit Service 8bf002
                                              23. 通常使う include directory。#include でヘッダファイルをサーチする時の規則。
                                              24. Packit Service 8bf002
                                              25. 必要な関数で、ライブラリに無いものがあるか。
                                              26. Packit Service 8bf002
                                              27. コンパイラ本体は digraph を認識するか。
                                              28. Packit Service 8bf002
                                              29. 識別子に $ を使うか。
                                              30. Packit Service 8bf002

                                                Packit Service 8bf002
                                              31. #asm, #endasm はあるか。
                                              32. Packit Service 8bf002
                                                これではさまれたブロックのコンパイラ本体への受け渡し形式はどうか。その他の規格外 directive にはどんなものがあるか。
                                                Packit Service 8bf002
                                              33. プリプロセッサで処理すべき #pragma sub-directive には何があるか。
                                              34. Packit Service 8bf002
                                              35. コンパイラ本体が受け取れる行長はどのくらいまでか(Validation Suite にある <samp>test-l/l_37_8.c</samp> をコンパイルするとわかる)。
                                              36. Packit Service 8bf002
                                              37. コンパイラ本体では、識別子は何バイトまで識別されるか。
                                              38. Packit Service 8bf002
                                              39. コンパイル後、リンク前の「オブジェクトファイル」の接尾子は何か(UNIX 上の処理系の .o や Windows 上の処理系の .obj に相当するもの)。
                                              40. Packit Service 8bf002
                                              41. 次の <samp>t_line.c</samp> というサンプルをプリプロセッサだけに通した結果(単体プリプロセッサを使うか、またはオプションでプリプロセス後の出力を指定する)。これは行番号とファイル名の情報をコンパイラ本体に渡す方法を見るためのものである。<samp><stdio.h></samp> の内容は長すぎるので、途中をカットして最初の10〜20行と最後の10〜20行があれば十分である。
                                              42. Packit Service 8bf002
                                                さらに、#line 1000 が処理された結果が #line 1000 "t_line.c" とならず #1000 "t_line.c" とかその他の形式になる処理系では、その部分を #line 1000 "t_line.c" と書き替えてコンパイラ本体に渡して、これを認識できるかどうかを見る(#line 1000 "t_line.c" でエラーにならなければ error line; の行でエラーメッセージが出るはずであるが、その時に行番号がどう出るか)。
                                                Packit Service 8bf002
                                                Packit Service 8bf002
                                                Packit Service 8bf002
                                                /* t_line.c */
                                                Packit Service 8bf002
                                                #include    <stdio.h>
                                                Packit Service 8bf002
                                                Packit Service 8bf002
                                                #line 1000
                                                Packit Service 8bf002
                                                Packit Service 8bf002
                                                error line;
                                                Packit Service 8bf002
                                                Packit Service 8bf002
                                                main( void)
                                                Packit Service 8bf002
                                                {
                                                Packit Service 8bf002
                                                    return  0;
                                                Packit Service 8bf002
                                                }
                                                Packit Service 8bf002
                                                Packit Service 8bf002

                                                ホスト処理系とターゲット処理系が違う場合はその双方について上記のデータがあれば、何とかなるでしょう。

                                                Packit Service 8bf002

                                                こうして並べてみると、チェックすべきことがずいぶんたくさんありますね。しかし、多くの処理系では移植ずみの処理系と共通の特性が多いでしょうから、一応動作するだけの移植であればさほどの手間ではないはずです。比較的手間のかかるのは実行時オプションと #pragma、さらに規格外仕様の実装です。これは一応動作するようになってから、徐々にやってゆくこともできます。唯一面倒なのは、処理系のバグにひっかかった場合です。

                                                Packit Service 8bf002

                                                Packit Service 8bf002
                                                Packit Service 8bf002

                                                5.7. 検証セットによる他の処理系のテスト報告を

                                                Packit Service 8bf002

                                                私が持っている処理系のプリプロセッサを私の検証セットでテストした結果は、cpp-test.html#6 にまとめてあります。

                                                Packit Service 8bf002
                                                その他の処理系についてテストした結果をお知らせください。項目が多いのでかなりの手間ですが。
                                                Packit Service 8bf002
                                                <samp>cpp_test.c</samp> によるテストであれば手間はかからないので、これだけでもお願いします。GCC の場合は、検証セットによる自動テストができます。

                                                Packit Service 8bf002

                                                Packit Service 8bf002
                                                Packit Service 8bf002

                                                5.8. 改善のご意見を

                                                Packit Service 8bf002

                                                バグ報告のほかにも、mcpp の使い勝手、診断メッセージ、mcpp のソース、Validation Suite、私の Standard C 解釈、ドキュメントの書き方、などについてご意見をお寄せください。

                                                Packit Service 8bf002
                                                趣味で作ったプリプロセッサですが、V.2.0 までだけでも6年半もかけて凝りに凝った労作です。凝りついでにできるだけ良いものにしたいと思っています。Cプリプロセッサについては、私の持っていない処理系への移植とテスト以外は、やって意味のあることはほとんどすべてやったつもりです。多少とも問題が残っていれば、手を入れたいと思います。
                                                Packit Service 8bf002
                                                Martin Minow のソースはとてもきれいな、クセのない、わかりやすいもので、これを読むだけでも私にとってはずいぶん勉強になりました。
                                                Packit Service 8bf002
                                                こういうものに興味を持つ人はかなり限られていると思いますが、多くのコメントと情報をお待ちしています。
                                                Packit Service 8bf002
                                                ご意見と情報は

                                                Packit Service 8bf002

                                                http://mcpp.sourceforge.net/

                                                Packit Service 8bf002

                                                の "Open Discussion Forum" またはメールでお願いします。

                                                Packit Service 8bf002

                                                Packit Service 8bf002

                                                Packit Service 8bf002
                                                Packit Service 8bf002

                                                6. mcpp の長い道のり

                                                Packit Service 8bf002
                                                Packit Service 8bf002

                                                6.1. 構想3日、制作6年

                                                Packit Service 8bf002

                                                1992/01 に DECUS cpp をいじりだした時には、

                                                Packit Service 8bf002
                                                こんな長丁場になるとは夢にも思いませんでした。正月休みにちょこっとバージョンアップしてみようと思っただけだったのです。
                                                Packit Service 8bf002
                                                やり始めて、ソースをちゃんと読まないとダメだとわかり、2か月くらいかけて読みました。読みがいのあるソースだったからでもあります。次にいくつかの仕様を C90 対応にバージョンアップしました。ここまでは当初の目的の通りでした。

                                                Packit Service 8bf002

                                                しかし、ここで私は自分が C90 のプリプロセス仕様を正確には知っていないことに気付きました。P. J. Plauger & Jim Brodie "Standard C" (1989) を読んだところ、function-like マクロの展開方法は、私の先入見をひっくり返すものでした(ある邦訳書はここを誤訳していたが)。そこで規格書を買って、プリプロセスに関する難解な文章をくり返し読みました。その結果、C90 のプリプロセスは伝統的なものとは多くの点で異なっていることがわかりました。#, ## 演算子が追加されたことは、そのほんの一部分にすぎなかったのです。

                                                Packit Service 8bf002

                                                ことに function-like マクロの展開ルーチンにはかなり頭を悩ましました。E. Ream の cpp のソースを参考に2〜3週間考えて、C90 用マクロ展開ルーチンを新しく書きました。私がプログラムのアルゴリズムでこんなに一生懸命考えたのは、後にも先にもないことです。1992/04 のことでした。

                                                Packit Service 8bf002

                                                さて、これで峠を越して、今度こそ cpp いじりはおしまいだと思ったのですが、ところがそれからさらに6年あまりたってしまいました。といっても、この間にはさほど頭を悩ます問題はなかったのです。にもかかわらず、時間はずいぶんかかりました。考えるだけ考えたら飽きてきて、cpp いじりに集中しなくなったせいもあります。しかし、それだけではありません。この間にやったのは次のようなことです。

                                                Packit Service 8bf002
                                                  Packit Service 8bf002
                                                1. 仕様をさらに明確にする。Standard モードでは規格に完全に対応させる。
                                                2. Packit Service 8bf002
                                                3. Standard C のモードを中心にプログラム構造・データ構造を再構成する。
                                                4. Packit Service 8bf002
                                                5. Portability を上げるため、ソースのスタイルを変える。
                                                6. Packit Service 8bf002
                                                7. デバッグをする。
                                                8. Packit Service 8bf002
                                                  処理系のバグや不備に対処する。
                                                  Packit Service 8bf002
                                                9. テストプログラムすなわち Validation
                                                10. Packit Service 8bf002
                                                  Suite を作る。
                                                  Packit Service 8bf002
                                                11. 他の処理系のテストをする。
                                                12. Packit Service 8bf002

                                                  Packit Service 8bf002
                                                13. ドキュメントを書く。
                                                14. Packit Service 8bf002

                                                  Packit Service 8bf002
                                                15. 1997/07 には新しいパソコンを買ったため、初めて使う WindowsNT/95,X Window System とそのソフトのインストールと習得に追われた。そうしているうちに C99-1997/11 draft が出て、これへの対応が必要となった。
                                                16. Packit Service 8bf002
                                                  Packit Service 8bf002

                                                  中でも時間のかかったのはドキュメントでした。ことに後半の4年くらいはソースをいじった時間はほんの少しで、ドキュメント書きが作業の大半を占めていました。おかげで大変な分量になってしまいましたが、しかし、時間がかかったのは量が多いせいばかりではありません。ドキュメントを書いていると、仕様の不明確なところが次々と出てくるのです。そのたびに規格書を読み返し、ソースを少しずついじりました。ソースをいじった時間は少なくても、回数は少なくありません。規格書もプリプロセス規定だけではなく、全体を ANSI C の Rationale も含めてよく読んでみました。私はプリプロセッサを作ることを通して C90 の勉強をしたようなものです。さらにはこれを通して、C90 の規定の問題点も明確に把握することができました。

                                                  Packit Service 8bf002

                                                  テストプログラムは初めは簡単なサンプルを何本か書いただけでした。ところが、書いて cpp をテストするたびに意外なバグが見つかるのです。そこで、C90 プリプロセスの全規定をテストする Validation Suite を書くことにしました。そして、Valadation Suite を書くことを通して、C90 の問題点がさらに明らかになってきました。C90 の不規則な部分に対応するのは、自分にとってはわずらわしいばかりであまり意味のないことでしたが、それよりも意味のある部分のほうがはるかに多かったことは確かです。

                                                  Packit Service 8bf002
                                                  この作業を通して私が学んだのは、次のようなことです。

                                                  Packit Service 8bf002
                                                    Packit Service 8bf002
                                                  1. プログラムの仕様は、詳細なドキュメントを書き終えるまで確定しない。
                                                  2. Packit Service 8bf002
                                                  3. プログラムのデバッグは、全仕様をテストするサンプルが完成するまで終わらない。
                                                  4. Packit Service 8bf002
                                                    Packit Service 8bf002

                                                    この考え方は完全主義的なものです。

                                                    Packit Service 8bf002
                                                    世の中のことは完全主義ではうまくゆかないものが多く、プログラムも例外ではありませんが、中には完全主義が重要な意味を持つ分野もあります。言語処理系はその一つでしょう。
                                                    Packit Service 8bf002
                                                    趣味だから何年もかけて徹底的にやることができたとも言えます。それにしても6年半は長すぎました。こんなに時間をかけて完全なプログラムを作って、いったいだれが使うのだろうという疑問がずっと続いていました。趣味で作るプログラムとしては、このくらいが規模の限度なのでしょう。

                                                    Packit Service 8bf002

                                                    しかし、mcpp はもう作ってしまったので、今後もメンテナンスをしていくつもりです。せっかくですから皆さん、コメント、報告、移植をお願いします。

                                                    Packit Service 8bf002

                                                    Packit Service 8bf002
                                                    Packit Service 8bf002

                                                    6.2. V.2.3 へ

                                                    Packit Service 8bf002

                                                    V.2.0 を公開した後、さらに V.2.1, V.2.2, V.2.3 と update を繰り返しました。C99 や正式に承認された ISO / C++ に対応させたり、対応処理系を増やしたり、バグをとったりというのがその内容です。

                                                    Packit Service 8bf002

                                                    V.2.2 までは簡単に update できていました。V.2.2 は V.2.0 から3か月しかたっていません。ところが、V.2.3 は V.2.2 から4年あまりもたってしまいました。私の身辺が多忙になり、時間がとれなくなったのが主な原因です。2000/07 に 60 歳になって、仕事を週4日に減らしてから、いくらか時間がとれるようになり、cpp いじりに復帰しました。

                                                    Packit Service 8bf002

                                                    V.2.3 は時間だけでなく、手間も比較的かかっています。GCC V.2.9x に実装してみたところ、GCC / cpp との互換性確保のためにかなり手を加えなければならないことがわかったからです。多くのオプションを追加し、拡張仕様を実装しました。また、一部のエラーをウォーニングに格下げしたり、頻発するウォーニングをデフォルトのウォーニングクラスからはずしたりして、規格による制限を緩和しています。

                                                    Packit Service 8bf002

                                                    こうした変更の多くは後向きのものであり、楽しいものではありませんでした。ことに C90 以前の "traditional" な仕様の一部を C99 の仕様と両立させなければならないというのは、はなはだ不本意なことでした。しかし、これが現在のオープンソース界の実情であれば、それにある程度合わせるのはやむをえません。

                                                    Packit Service 8bf002
                                                    規格による制約を緩和したことで、他の処理系用の版も、処理系付属のプリプロセッサと置き換えて使うためには使いやすくなったと思います。

                                                    Packit Service 8bf002

                                                    Packit Service 8bf002
                                                    Packit Service 8bf002

                                                    6.3. 「未踏ソフトウェア創造事業」に採択

                                                    Packit Service 8bf002

                                                    V.2.3 への update の途中で、mcpp および Validation Suite は情報処理振興事業協会 (IPA) の平成14年度「未踏ソフトウェア創造事業」というものに採択されました。たまたまこの事業のことを知ったので応募してみたところ、新部 裕・プロジェクトマネージャが採択してくれたのです。こうして 2002/07 から 2003/02 までは IPA の資金援助と新部PMの助言のもとに、開発が進められることになりました。ドキュメントの英訳も、ハイウェルが引き受けてくれることになりました

                                                    Packit Service 8bf002

                                                    比較的小さいソフトウェアながらも、これだけ時間をかけ、私のライフワークのようになってしまったものです。その完成度には自信がありましたが、世に出る機会がなく、残念な思いをしてきました。その機会がついに与えられたのです。私はこのプロジェクトを遂行するため、仕事を週3日に減らしました。

                                                    Packit Service 8bf002
                                                    私がこのプロジェクトでやることとして考えたのは、次のようなことでした。

                                                    Packit Service 8bf002
                                                      Packit Service 8bf002
                                                    1. 英語版のドキュメントを作成する。それを使って、mcpp と検証セットを国際的な評価の場に出してゆく。C処理系の大半が外国製となっている現状では、英語版ドキュメントの存在は評価と普及のために必須だからである。
                                                    2. Packit Service 8bf002
                                                    3. 移植の対象を広げる。これまで対応してきた処理系の新しいバージョンに対応させるほか、市販の主要な処理系への移植を進める。
                                                    4. Packit Service 8bf002
                                                      Packit Service 8bf002

                                                      さらに新部 PM から次の提案がありました。

                                                      Packit Service 8bf002
                                                        Packit Service 8bf002
                                                      1. GCC 3.x にも移植し、さらにその testsuite で私の検証セットが利用できるようにする。
                                                      2. Packit Service 8bf002
                                                      3. 開発をオープンな形で進めてゆく。
                                                      4. Packit Service 8bf002
                                                        開発とその成果を共有しやすいように、標準的なやり方を採用する。
                                                        Packit Service 8bf002
                                                        Packit Service 8bf002

                                                        私自身もこれらはぜひやりたいことであるので、喜んで計画に追加しました。

                                                        Packit Service 8bf002
                                                        ところが、私の計画は遅延に遅延を重ねました。
                                                        Packit Service 8bf002
                                                        まず、ディスククラッシュに見舞われました。また、何か新しいことをするたびに使ったことのないソフトウェアを使って、そのたびに時間がかかりました。GCC をソースからコンパイルしたのも初めてですが、これはいくつかのトラブルに見舞われました。大量のドキュメントの更新と大量の英訳のチェックと修正にも、かなりの時間がかかりました。その上、母の入院という事態まで発生しました。プロジェクトは市販の処理系への対応等、計画の一部を断念する結果となりました。

                                                        Packit Service 8bf002

                                                        私はこれまで一つの穴を深く掘ってゆくようなことしかしてこなかったので、穴を少し広げようとするとひどく手間がかかってしまうのです。アマチュアプログラマが何かを掘り下げるには、こういうやり方をしなければできることではありません。しかし、その成果を世に出すためには、穴をいくらか広げなければならないのでした。

                                                        Packit Service 8bf002
                                                        穴を広げる過程で、私は新部 PM の助言と励ましを得て、いくつかの未経験のソフトウェアを習得し、開発の前線というものに触れることができました。自分の文章がこなれた英文に翻訳されて戻ってくるのも、大変うれしいことでした。時間に追われるのは苦しいことですが、内容はどれも新鮮で楽しいことでした。

                                                        Packit Service 8bf002

                                                        「未踏ソフトウェア創造事業」はこれでおしまいではありませんでした。平成15年度にも、伊知地 宏・プロジェクトマネージャが mcpp を継続プロジェクトとして採択してくれたのです。こうして、前年度の積み残しの課題を初めとして、私にとっては未経験の領域のいくつかの課題に取り組むこととなりました。

                                                        Packit Service 8bf002

                                                        今回も私の6年前のパソコンにトラブルが発生し、ハードウェアと OS を upgrade する過程でさらにいくつかのトラブルに見舞われました。未経験のソフトウェアの習得にも時間を要し、開発はやはり遅れ気味でした。いったん退院して比較的元気になっていた母の容態が、プロジェクトが大詰めに近づくのと並行して以前にも増して悪くなってきたことも、心配の種でした(母は 2004 年 2 月に死去した)。しかし、伊知地PMが目標を無理のないところに設定してくれたおかげで、あわてずにじっくりと課題に取り組むことができました。

                                                        Packit Service 8bf002

                                                        Visual C++ への移植、configure スクリプトの作成、多様な multi-byte character encoding への対応等の課題を達成することができました。また、ソースコードの整理という目立たないながらも作者としてはこだわりのある課題にも取り組みました。日本語版と英語版のドキュメントの更新という手間のかかる作業も、ハイウェルの協力を得て達成することができました。

                                                        Packit Service 8bf002

                                                        この成果によって、私は伊知地PMから何と「スーパークリエータ」という評価を受けることができました。私の実力にとっては過分の評価ですが、長年にわたる mcpp の積み重ねを認めていただいたものと思い、大変喜んでいます。

                                                        Packit Service 8bf002

                                                        2年近くにわたる「未踏ソフトウェア」のプロジェクトによって、mcpp は世界一高品質な C/C++ プリプロセッサに仕上がったつもりです。熟年のアマチュアプログラマとして非力ながらもよくやったと自分では納得しています。

                                                        Packit Service 8bf002

                                                        未踏ソフトウェアのプロジェクトが終わってからも、mcpp の改良作業は続けられています。まだいくつかの課題が残っています。これらの課題を達成し、mcpp を普及させるために、今後も着実に取り組みを続けてゆくつもりです。

                                                        Packit Service 8bf002
                                                        </body>
                                                        Packit Service 8bf002
                                                        </html>