* acl4のページ0011
-(by [[K]], 2026.02.11)
** (1)
#if (a_Version >= 1)
#define Preprocessor_SourceFile a_Preprocessor_SourceFile
#define Preprocessor_SourceFile_ini a_Preprocessor_SourceFile_ini
#define Preprocessor_SourceFile_din a_Preprocessor_SourceFile_din
#define Preprocessor_SourceFile_read a_Preprocessor_SourceFile_read
#define Preprocessor_SourceFile_gets a_Preprocessor_SourceFile_gets
#define Preprocessor_SourceFiles a_Preprocessor_SourceFiles
#define Preprocessor_SourceFiles_ini a_Preprocessor_SourceFiles_ini
#define Preprocessor_SourceFiles_din a_Preprocessor_SourceFiles_din
#define Preprocessor_SourceFiles_addFile a_Preprocessor_SourceFiles_addFile
#define Preprocessor_SourceFiles_addBuf a_Preprocessor_SourceFiles_addBuf
#define Preprocessor_SourceFiles_getSf a_Preprocessor_SourceFiles_getSf
#define Preprocessor_SourceFiles_gets a_Preprocessor_SourceFiles_gets
#define Preprocessor_isDirective a_Preprocessor_isDirective
#endif
a_class(a_Preprocessor_SourceFile) {
a_VecChr src[1], path[1];
intptr_t lin;
char *s;
};
a_static void a_Preprocessor_SourceFile_ini(a_Preprocessor_SourceFile *w)
{
a_VecChr_ini4(w->src, w->path, 0, 0);
w->lin = 0;
}
a_static void a_Preprocessor_SourceFile_din(a_Preprocessor_SourceFile *w)
{
a_VecChr_din4(w->src, w->path, 0, 0);
}
a_static intptr_t a_Preprocessor_SourceFile_read(a_Preprocessor_SourceFile *w, const char *path, intptr_t n)
{
intptr_t i = 0;
a_VecChr_puts(w->path, path, path + n);
if (n >= 7 && strncmp(path, "inline:", 7) == 0) {
a_VecChr_puts(w->src, &path[7], path + n);
a_VecChr_convEsc(w->src);
} else {
i = a_VecChr_readFileAll(w->src, w->path->p);
a_VecChr_eraseCr(w->src);
}
if (i >= 0) { i = w->src->n; w->s = w->src->p; }
return i;
}
a_static void a_Preprocessor_SourceFile_gets(a_Preprocessor_SourceFile *w, a_VecChr *lin)
{
w->s = a_VecChr_gets(lin, w->s, w->src->p + w->src->n);
if (lin->n > 0) w->lin++;
}
a_class(a_Preprocessor_SourceFiles) {
a_VecChr buf[1], stk[1];
char *s;
};
a_static void a_Preprocessor_SourceFiles_ini(a_Preprocessor_SourceFiles *w)
{
a_VecChr_ini4(w->buf, w->stk, 0, 0);
a_VecChr_reserve0(w->buf);
w->s = w->buf->p;
}
a_static void a_Preprocessor_SourceFiles_din(a_Preprocessor_SourceFiles *w)
{
intptr_t i, n = w->stk->n / (sizeof (a_Preprocessor_SourceFile *));
a_Preprocessor_SourceFile **p = (a_Preprocessor_SourceFile **) w->stk->p;
for (i = 0; i < n; i++) {
a_Preprocessor_SourceFile_din(p[i]);
a_free(_arg_ p[i], sizeof (a_Preprocessor_SourceFile));
}
a_VecChr_din4(w->buf, w->stk, 0, 0);
}
a_static intptr_t a_Preprocessor_SourceFiles_addFile(a_Preprocessor_SourceFiles *w, const char *path, intptr_t n)
{
a_Preprocessor_SourceFile *p = a_malloc(_arg_ sizeof (a_Preprocessor_SourceFile));
a_Preprocessor_SourceFile_ini(p);
intptr_t i = a_Preprocessor_SourceFile_read(p, path, n);
if (i > 0) {
a_Preprocessor_SourceFile **pp = a_VecChr_stkAdd(w->stk, sizeof (a_Preprocessor_SourceFile *));
*pp = p;
} else {
a_Preprocessor_SourceFile_din(p);
a_free(_arg_ p, sizeof (a_Preprocessor_SourceFile));
}
return i;
}
a_static void a_Preprocessor_SourceFiles_addBuf(a_Preprocessor_SourceFiles *w, const char *s, intptr_t n)
{
a_VecChr_replace(w->buf, 0, w->s - w->buf->p, s, n);
w->s = w->buf->p;
}
a_static a_Preprocessor_SourceFile *a_Preprocessor_SourceFiles_getSf(a_Preprocessor_SourceFiles *w)
{
if (w->stk->n == 0) return NULL;
return *(a_Preprocessor_SourceFile **) (w->stk->p + w->stk->n - sizeof (a_Preprocessor_SourceFile *));
}
a_static void a_Preprocessor_SourceFiles_gets(a_Preprocessor_SourceFiles *w, a_VecChr *lin)
{
w->s = a_VecChr_gets(lin, w->s, w->buf->p + w->buf->n);
if (lin->n == 0) {
while (w->stk->n > 0) {
a_Preprocessor_SourceFile *sf = a_Preprocessor_SourceFiles_getSf(w);
a_Preprocessor_SourceFile_gets(sf, lin);
if (lin->n > 0) break;
w->stk->n -= sizeof (a_Preprocessor_SourceFile *);
a_Preprocessor_SourceFile_din(sf);
a_free(_arg_ sf, sizeof (a_Preprocessor_SourceFile));
}
}
}
a_static int a_Preprocessor_isDirective(const char *s, const char *s1)
{
while (s < s1 && *(const unsigned char *) s <= ' ') s++;
return (s < s1 && *s == '#');
}
** (2) 説明
-Preprocessor_SourceFile と Preprocessor_SourceFiles は、 #include が多重に重なったり、マクロ展開した行があって、今はどのファイルの何行目を処理しているのかわからなくなったので作りました。
-Preprocessor_SourceFile は、1つのファイルだけを管理するクラスで、今何行目を読んでいるかを把握しています。1行ずつ取り出すことができます。
-Preprocessor_SourceFiles は、内部に Preprocessor_SourceFile のスタックを持っていて、 #include するたびにスタックに積みます。
-読み込みの際は常にスタックトップのファイルから1行ずつ取り出します。
-スタックトップのファイルを読みつくしてしまったら、スタックを1つ戻して、当たらなスタックトップから1行ずつ読みます。
-ただし Preprocessor_SourceFiles はこのスタック以外にもバッファを持っています。このバッファは define マクロを展開した結果などが優先的に格納されています。
-もしバッファが空ではないときは、ファイルからではなくバッファから1行ずつ取り出します。
** (3)
-このページにはサンプルプログラムがありません。
-これらを使って、 [[a4_0013]] でプリプロセッサを作ります。
** (99) 更新履歴
-2026.02.11(水) 初版