Cおよび Objective-C のソース コードを前処理するために、 Cプリプロセッサ以外のものを使用することに興味があります。良い代替手段はありますか?
例としては、Cコードの途中で python や perl のスニペットにエスケープできるようにし、そのスニペットがCを吐き出し、それが通常どおりコンパイルされるようなものです。
Cおよび Objective-C のソース コードを前処理するために、 Cプリプロセッサ以外のものを使用することに興味があります。良い代替手段はありますか?
例としては、Cコードの途中で python や perl のスニペットにエスケープできるようにし、そのスニペットがCを吐き出し、それが通常どおりコンパイルされるようなものです。
PHPを C プリプロセッサとして使用できます。利点は次のとおりです。
<?
標準 C では使用され?>
ません (非標準 C では、壊れる唯一のものは、最小/最大を返す古い GCC 拡張演算子です)。ただし、真剣に使用する場合は、前処理されたコードをデバッグするために PHP に #line ディレクティブを出力させる必要があります。
<?php include_once "stdio.h"; ?>
int main()
{
<?php
for($i = 0; $i < 20; $i++)
echo 'printf("%d\n", '.$i.');';
?>
}
m4 を検討することをお勧めします。
http://www.gnu.org/software/m4/
Cogは正確にはプリプロセッサではありませんが、コード内でインライン化され、オンザフライで生成されます。
コードを実行し、その結果をスプライスするという考え方は、準引用と呼ばれます。実行するコードは引用符で囲まれていません。
私はLuaを使用してこの問題を解決する方法を知っています。自分で書いた引用防止関数を使用string.gsub
しました。引用符の引用にはシェル構文を使用しました。シェルの場合と同様に、引用符で囲まれていないコードは文字列を返し、それがコードにスプライスされます。
以下prog
は、引用符で囲まれていないテキストを含むCコードであり、引用符で囲まれantiquote
ていない関数です。二重角かっこを引用するLuaの特別な文字列を最大限に活用しました。 実際には、これは行いません。別のファイルに入れprog
ます。
names = { 'John', 'Paul', 'George', 'Ringo' }
local prog = [===[
#include <stdio.h>
main() {
$(local out = { }
for _, n in ipairs(names) do
table.insert(out, string.format([[ printf("The name is %%s\n", %q);]], n))
end
return table.concat(out, '\n ')
)
}
]===]
local function antiquote(s)
local body = s:match '^%$%((.*)%)$'
return assert(loadstring(body))()
end
prog = prog:gsub('%$%b()', antiquote)
io.stdout:write(prog)
使用中のプログラムは次のようになります。
: nr@curlycoat 1181 ; lua /home/nr/tmp/emit-c.lua
#include <stdio.h>
main() {
printf("The name is %s\n", "John");
printf("The name is %s\n", "Paul");
printf("The name is %s\n", "George");
printf("The name is %s\n", "Ringo");
}
確かに、標準の C プリプロセッサは非常に限られています。
最近、このようなツールを作成しました: https://github.com/d-ash/perlpp
たとえば、これ
<?
my @types = ('char', 'int', 'long');
foreach (@types) {
?>
<?= $_ ?> read_<?= uc($_) ?>(<?= $_ ?>* v);
<? } ?>
これになる
char read_CHAR(char* v);
int read_INT(int* v);
long read_LONG(long* v);
構文は PHP に似ていますが、代わりに Perl を使用し、テキストを Perl 文字列に取り込むことができます。
cxwによる編集— @d-ash の承認を得て、私は perlpp のメンテナーでもあります。ご不明な点がございましたら、お気軽にお問い合わせください。
問題を少し抽象化すると、実際にはコードのテンプレート エンジンを探していることになります。ほとんどの Web サイトが動的に生成されたコンテンツを静的テンプレートに挿入するように、動的に生成されたコードをプログラムに挿入したいと考えています。
私は現在、ほとんどのテンプレート作業にJinja2 (Python) を使用しています。あらゆる点で非常に構成可能であることがわかりました。
C++ で手を汚す準備ができている場合は、Spirit 再帰降下パーサーを使用して構築された Boost の Wave パーサーがあります。これは完全な C プリプロセッサであり、C および C++ のすべての最新仕様 (さらには、Objective C、AFAICS) に準拠しています。
高度にモジュール化されているため、必要な追加機能を実行できる独自のドライバーを切り替えることができます。
私は過去にこの同じ問題について考えました。あなたのコードをコンパイルしたい人は誰でも新しい前処理ツールを必要とするという事実に問題がないことを確認してください. あなただけがそれに取り組む場合は問題ありませんが、他の人がコードを利用できるようにしたい場合は、ツール要件を追加することをお勧めします。
短い答えは「いいえ」です。プリプロセッサは C のセマンティクスと密接に結びついているため、実際にはそれを削除することはできません。実際、一部のコンパイラでは、昔のように独立したフェーズでさえありません。 Mac は、Objective C 構文を解析するだけです。したがって、m4 などの別のマクロ プロセッサを使用して、ソース テキストを C に渡す前に処理することはできますが、C プリプロセッサを削除するのではなく、前処理の別のステップを追加することになります。
しかし、ここにはもっと深い疑問があります。CPP フェーズをなくすことで何を得たいのでしょうか?
CPP は、おそらく再実装する必要のない C コードの多くの重要なことを行います。代わりに探しているように見えるのは、C コードを発行するテンプレート プロセスである可能性があります。
Cheetahは、Python を使用できるようにする多くのツールの 1 つにすぎません。Python を使用するものもあれば、他の言語でさらに多くのものを使用するものもありますが、Cheetah は出力に依存しないことで知られており、一部のテンプレート エンジンは HTML/XML を非常に重視しています。あなたの研究をしてください。
お気に入りのプログラミング言語を使用してスクリプト/ツールを構築し、ソース ファイル (.c/.cpp または .h など) を生成できます。それらを単純#include
にするか、プロジェクトにコンパイルします。の近くにコメントを付けて#include
、ツールがどこにあるのか、何が生成されたのかを識別するのに役立つ場合があります。
これは、「実際の」プリプロセッサを使用するほど便利 (またはクリーン) ではないかもしれませんが、機能します。繰り返しますが、それは本当にあなたのケースに依存します。
人々が何を考え出すのか興味があります。私は、Perl で書かれたプリプロセッサを使って小さなカスタム作業を行う傾向がありました。プリプロセッサを呼び出す Makefile を作成するのは簡単です。たとえば、「meta」という名前のプログラムを呼び出して、「file.c.meta」から「file.c」を生成するルールは次のとおりです。
% :: %.meta
meta $< > $@
カスタムフィットのCデータ構造を生成するなど、「メタ」を使って楽しいことをしています。それは間違いなく私が探求することをお勧めする方向です. 私の希望は、最終的には C++ テンプレートとほぼ同等のメタ ライブラリを思いつくことです。
Python のようなプリプロセッサhttp://ray.cg.tuwien.ac.at/rft/Papers/PYM/pym.htmlを紹介する 2001 年の論文を見ました。誰かが使っているかどうかは明らかではありません..