acl4のページ0013
(1)
#if (a_Version >= 1)
#define Preprocessor_incl0 a_Preprocessor_incl0
#define Preprocessor_Put0 a_Preprocessor_Put0
#define Preprocessor_Put0_ini a_Preprocessor_Put0_ini
#define Preprocessor_Put0_din a_Preprocessor_Put0_din
#define Preprocessor_put0 a_Preprocessor_put0
#define Preprocessor a_Preprocessor
#define Preprocessor_ini a_Preprocessor_ini
#define Preprocessor_din a_Preprocessor_din
#define Preprocessor_line a_Preprocessor_line
#define Preprocessor_main a_Preprocessor_main
#endif
a_static int a_Preprocessor_incl0(void *w, char *s, char *s1, a_Preprocessor_SourceFiles *sfs)
{
(void) w;
while (s < s1 && *(unsigned char *) s <= ' ') s++;
if (*s == 0x22) {
char *t = strchr(s + 1, 0x22);
if (t == NULL) t = s1;
a_Preprocessor_SourceFiles_addFile(sfs, s + 1, t - (s + 1));
return 1;
}
if (*s == '<') {
char *t = strchr(s + 1, '>');
if (t == NULL) t = s1;
if (t[-2] == '.' && t[-1] == 'h') return 0; // through.
a_Preprocessor_SourceFiles_addFile(sfs, s + 1, t - (s + 1));
return 1;
}
return 0;
}
a_class(a_Preprocessor_Put0) {
a_Preprocessor_SourceFiles *sfs;
a_VecChr *dst, path[1];
intptr_t lin;
};
a_static void a_Preprocessor_Put0_ini(a_Preprocessor_Put0 *w) { a_VecChr_ini(w->path); w->lin = 0; }
a_static void a_Preprocessor_Put0_din(a_Preprocessor_Put0 *w) { a_VecChr_din(w->path); }
a_static void a_Preprocessor_put0(a_Preprocessor_Put0 *w, a_VecChr *lin)
{
a_Preprocessor_SourceFile *sf = a_Preprocessor_SourceFiles_getSf(w->sfs);
if (w->path->n != sf->path->n || (w->path->n > 0 && memcmp(w->path->p, sf->path->p, w->path->n) != 0)) {
char *s = a_malloc(_arg_ sf->path->n + 64);
sprintf(s, "#line %d \"%.*s\"\n", sf->lin, sf->path->n, sf->path->p);
a_VecChr_puts(w->dst, s, s + strlen(s));
a_free(_arg_ s, sf->path->n + 64);
a_VecChr_replace(w->path, 0, w->path->n, sf->path->p, sf->path->n);
} else if (w->lin + 1 < sf->lin && sf->lin < w->lin + 9) {
while (w->lin + 1 < sf->lin) {
char *s = "\n";
a_VecChr_puts(w->dst, s, s + 1);
w->lin++;
}
} else if (w->lin + 1 != sf->lin) {
char s[64];
sprintf(s, "#line %d\n", sf->lin);
a_VecChr_puts(w->dst, s, s + strlen(s));
}
a_VecChr_puts(w->dst, lin->p, lin->p + lin->n);
w->lin = sf->lin;
}
a_class(a_Preprocessor) {
a_Token0 t0[1];
a_Preprocessor_SourceFiles sfs[1];
a_Set0 set[1];
a_Preprocessor_If ppIf[1];
a_Preprocessor_Eval ppEv[1];
a_Preprocessor_Put0 put0[1];
int (*incl)(void *, const char *, const char *, a_Preprocessor_SourceFiles *);
void (*put)(void *, a_VecChr *, a_Preprocessor_SourceFiles *);
void *w_incl, *w_put;
};
a_static void a_Preprocessor_ini(a_Preprocessor *w)
{
a_Token0_ini1(w->t0);
a_Preprocessor_SourceFiles_ini(w->sfs);
a_Preprocessor_if0(w->ppIf);
a_Set0_ini(w->set);
// 以下はとりあえずのデフォルト設定. 不要なら上書きする.
w->ppIf->eval = (void *) a_Preprocessor_eval;
w->ppIf->w_eval = w->ppEv;
w->incl = (void *) a_Preprocessor_incl0;
w->w_incl = NULL;
a_Preprocessor_Put0_ini(w->put0);
w->put = (void *) a_Preprocessor_put0;
w->w_put = w->put0;
w->put0->sfs = w->sfs;
a_Preprocessor_define7(w->set, -1, "ifdef", "if defined");
a_Preprocessor_define7(w->set, -1, "ifndef", "if !defined");
a_Preprocessor_define7(w->set, -1, "elifdef", "elif defined");
a_Preprocessor_define7(w->set, -1, "elifndef", "elif !defined");
}
a_static void a_Preprocessor_din(a_Preprocessor *w)
{
a_Preprocessor_define3(w->set);
a_Preprocessor_if3(w->ppIf);
a_Preprocessor_SourceFiles_din(w->sfs);
a_Preprocessor_Put0_din(w->put0);
}
a_static void a_Preprocessor_line(a_Preprocessor *w)
{
a_Preprocessor_SourceFile *sf = a_Preprocessor_SourceFiles_getSf(w->sfs);
const char *t = a_Token1_get(w->t0);
sf->lin = strtol(t, NULL, 0) - 1;
t = a_Token1_get(w->t0);
if (w->t0->len >= 2 && *t == 0x22) {
sf->path->n = 0;
a_VecChr_puts(sf->path, t + 1, t + w->t0->len - 1);
}
}
a_static void a_Preprocessor_main(a_Preprocessor *w)
{
int defC = 1;
a_VecChr lin[1], tmp[1], stkDef[1]; a_VecChr_ini4(lin, tmp, stkDef, 0);
for (;;) {
a_Preprocessor_SourceFiles_gets(w->sfs, lin);
if (lin->n == 0) break;
for (;;) { // 末尾が "\\\n"であれば、後続行を接続.
char *p1 = lin->p + lin->n;
if (!(lin->n >= 2 && p1[-2] == '\\' && p1[-1] == '\n')) break;
a_Preprocessor_SourceFiles_gets(w->sfs, tmp);
a_VecChr_replace(lin, lin->n - 2, 2, tmp->p, tmp->n);
}
if (a_Preprocessor_isDirective(lin->p, lin->p + lin->n) == 0) {
a_Preprocessor_SourceFile *sf = a_Preprocessor_SourceFiles_getSf(w->sfs);
if (a_Preprocessor_define2(w->set, w->t0, lin, defC, sf->path, sf->lin, 0) != 0) {
retry:
a_Preprocessor_SourceFiles_addBuf(w->sfs, lin->p, lin->n);
continue;
}
if (w->ppIf->phase != 0)
w->put(w->w_put, lin, w->sfs);
continue;
}
const char *s = lin->p, *s1 = lin->p + lin->n;
while (s < s1 && *(const unsigned char *) s <= ' ') s++;
s++; // '#'.
if (strncmp(s, "if", 2) == 0 || strncmp(s, "elif", 4) == 0) {
a_Preprocessor_SourceFile *sf = a_Preprocessor_SourceFiles_getSf(w->sfs);
if (a_Preprocessor_define2(w->set, w->t0, lin, defC, sf->path, sf->lin, 0) != 0) goto retry;
}
w->t0->s = s + 1; w->t0->s1 = lin->p + lin->n; a_Token1_get(w->t0);
if (w->ppIf->phase != 0) {
if (strncmp(s, "include", 7) == 0) { if (w->incl(w->w_incl, s + 7, s1, w->sfs) > 0) continue; }
if (strncmp(s, "define", 6) == 0) { a_Preprocessor_define5(w->set, w->t0, lin, defC, w->sfs, stkDef, 0); continue; }
if (strncmp(s, ".def", 4) == 0) { a_Preprocessor_define5(w->set, w->t0, lin, defC, w->sfs, stkDef, 1); continue; }
if (strncmp(s, ".addTl", 6) == 0) { a_Preprocessor_define5(w->set, w->t0, lin, defC, w->sfs, stkDef, 2); continue; }
if (strncmp(s, ".addHd", 6) == 0) { a_Preprocessor_define5(w->set, w->t0, lin, defC, w->sfs, stkDef, 3); continue; }
if (strncmp(s, "undef", 5) == 0) { if (a_Preprocessor_define6(w->set, w->t0, lin, stkDef, 0) > 0) continue; }
if (strncmp(s, ".undef", 6) == 0) { if (a_Preprocessor_define6(w->set, w->t0, lin, stkDef, 1) > 0) continue; }
if (strncmp(s, "line", 4) == 0) { a_Preprocessor_line(w); continue; }
}
w->t0->s = s; w->t0->s1 = lin->p + lin->n;
char *t = a_Token1_get(w->t0);
if (a_Preprocessor_if2(w->ppIf, lin, w->t0, t) > 0) continue;
if (w->ppIf->phase != 0)
w->put(w->w_put, lin, w->sfs); // エラー検出のため.
continue;
}
while (stkDef->n > 0) {
a_Preprocessor_Define *sp = a_VecChr_stkRmv(stkDef, sizeof (a_Preprocessor_Define));
a_Preprocessor_Define_din(sp);
}
a_VecChr_din4(lin, tmp, stkDef, 0);
}
(2) 説明
(3) サンプルプログラム: t0013a.c
- acl4ライブラリは以下のようにして利用します。
- [1]まずa4_0001~a4_0013のプログラムをつなげて"acl4.c"として保存します。
- [2]次にacl4を使ったプログラムを書きます。
- [3]コンパイル時に、"acl4.c"のあるパスをインクルードパスの一つとして指定します。
#define a_Version 1
#include <acl4.c>
int main(int argc, const char **argv)
{
if (argc < 2) return 1;
Preprocessor pp[1]; Preprocessor_ini(pp); // プリプロセッサの初期化.
Preprocessor_SourceFiles_addFile(pp->sfs, argv[1], strlen(argv[1])); // 最初に読むファイルを指定.
VecChr dst[1]; VecChr_ini(dst); pp->put0->dst = dst; // 出力先のオブジェクトを指定.
Preprocessor_main(pp); Preprocessor_din(pp); // プリプロセッサ処理. およびメモリ開放.
VecChr_reserve0(dst); puts(dst->p); VecChr_din(dst); // 処理結果を出力. およびメモリ開放.
a_malloc_debugList(_arg); // メモリリークがないか確認.
}
- ちゃんと動く(と思われる)プリプロセッサです。
- t0013a.exe を使って、 t0013a.c をプリプロセスして、そのあとコンパイラにかけたところ、問題なくビルドできていたので、たぶん大きなバグはないと思います。
- 「 >t0013a t0013a.c > t0013a.txt 」とすると、こんな感じのファイルができます。
#line 7 "a4_0001.c"
#line 19
#include <ctype.h>
#include <errno.h>
#include <float.h>
(中略)
#line 3 "t0013a.c"
int main(int argc, const char **argv)
{
if (argc < 2) return 1;
a_Preprocessor pp[1]; a_Preprocessor_ini(pp); // プリプロセッサの初期化.
a_Preprocessor_SourceFiles_addFile(pp->sfs, argv[1], strlen(argv[1])); // 最初に読むファイルを指定.
a_VecChr dst[1]; a_VecChr_ini(dst); pp->put0->dst = dst; // 出力先のオブジェクトを指定.
a_Preprocessor_main(pp); a_Preprocessor_din(pp); // プリプロセッサ処理. およびメモリ開放.
a_VecChr_reserve0(dst); puts(dst->p); a_VecChr_din(dst); // 処理結果を出力. およびメモリ開放.
a_malloc_debugList("t0013a.c", 12); // メモリリークがないか確認.
}
- 目視でも、正しく変換できていると思います。
- なお、標準関数の #include が処理されずにそのままになっているのは意図的なものです。
- Preprocessor_incl0 で < ... .h> な include については、インクルード処理をするなと明記しているからです。
- まだインクルードパスを探す処理を書いていないので、無理にやっても失敗してしまうのです。
(3) サンプルプログラム: t0013b.c
(99) 更新履歴