* acl4のページ0022
-(by [[K]], 2026.04.26)
** (1) 概要
-a4_0022 は、 acl4v1 にとっての7番目のライブラリプログラムになります。
-提供される主な機能は、以下の通りです。
--(1-1)プリプロセッサを構成するための細かい関数群
--(1-2)プリプロセッサの main 関数
-以下、それぞれについてもう少し詳しく説明します。
~
-(1-1)プリプロセッサを構成するための細かい関数群
--include 用の関数と、出力用の整形をする関数があります。
-(1-2)プリプロセッサの main 関数
--プリプロセッサの本体のクラスと、 main 関数です。
** (2) デモ
** (3) ライブラリプログラム
#if (a_Version >= 1)
#define Preprocessor_incl0 a_Preprocessor_incl0
#define Preprocessor_Put1 a_Preprocessor_Put1
#define Preprocessor_Put1_ini a_Preprocessor_Put1_ini
#define Preprocessor_Put1_din a_Preprocessor_Put1_din
#define Preprocessor_put1 a_Preprocessor_put1
#define Preprocessor_put2 a_Preprocessor_put2
#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_isDirective(const char *s, const char *s1)
{
while (s < s1 && *(const unsigned char *) s <= ' ') s++;
return (s < s1 && *s == '#');
}
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), 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), 1);
return 1;
}
return 0;
}
a_class(a_Preprocessor_Put1) {
a_Preprocessor_SourceFiles *sfs;
a_VecChr *dst, path[1];
intptr_t lin;
a_DbgLv1( a_DbgObjInf doi[1]; )
};
a_static void a_Preprocessor_Put1_ini(_aDef_ a_Preprocessor_Put1 *w)
{
a_VecChr_ini(_a_ w->path); w->lin = 0;
a_DbgLv2( a_DbgObjInf_ini(_aThr, w->doi, "Preprocessor_Put1"); )
}
a_static void a_Preprocessor_Put1_din(_aDef_ a_Preprocessor_Put1 *w)
{
a_DbgLv2( a_DbgObjInf_din(_aThr, w->doi); )
a_VecChr_din(_a_ w->path);
}
a_static void a_Preprocessor_put1(a_Preprocessor_Put1 *w, a_VecChr *lin)
{
a_Preprocessor_SourceFile *sf = a_Preprocessor_SourceFiles_getSf(w->sfs);
if (a_VecChr_N(w->path) != a_VecChr_N(sf->path) || (a_VecChr_N(w->path) > 0 && memcmp(w->path->p, sf->path->p, a_VecChr_N(w->path)) != 0)) {
a_VecChr_printf(w->dst, "#line %d \"%.*s\"\n", (int) sf->lin, (int) a_VecChr_N(sf->path), sf->path->p);
a_VecChr_replace(w->path, 0, a_VecChr_N(w->path), sf->path->p, a_VecChr_N(sf->path));
} else if (w->lin + 1 < sf->lin && sf->lin < w->lin + 9) {
while (w->lin + 1 < sf->lin) {
a_VecChr_puts(w->dst, "\n", 1);
w->lin++;
}
} else if (w->lin + 1 != sf->lin)
a_VecChr_printf(w->dst, "#line %d\n", (int) sf->lin);
a_VecChr_puts(w->dst, lin->p, a_VecChr_N(lin));
w->lin = sf->lin;
}
a_static void a_Preprocessor_put2(a_Preprocessor_Put1 *w, a_VecChr *lin)
{
intptr_t n = a_VecChr_N(lin);
if (a_Preprocessor_isDirective(lin->p, lin->p + n) != 0)
fprintf(stderr, "[err] %.*s", (int) n, lin->p);
else
a_VecChr_puts(w->dst, lin->p, n);
}
a_static void a_Preprocessor_line(a_Preprocessor_SourceFiles *sfs, a_Token0 *t0)
{
a_Preprocessor_SourceFile *sf = a_Preprocessor_SourceFiles_getSf(sfs);
const char *t = a_Token1_get(t0);
sf->lin = strtol(t, NULL, 0) - 1;
t = a_Token1_get(t0);
if (t0->len >= 2 && *t == 0x22) {
a_VecChr_N(sf->path) = 0;
a_VecChr_puts(sf->path, t + 1, t0->len - 2);
}
}
a_static void a_Preprocessor_undef(int mod, a_Token0 *t0, a_VecChr *lin, a_VecChr *args, a_Set0 *set)
{
if (mod == 0) {
char *t = a_Token1_get(t0);
a_Preprocessor_Define0 *pd = a_Set0_findKn(set, t, t0->len);
if (pd != NULL) {
a_Set0_rmv(set, pd->elm);
a_Preprocessor_Define0_din(pd->elm);
}
}
if (mod == 1) {
char *t = a_Token1_get(t0); intptr_t repLen;
a_Preprocessor_findDef(set, t, t0, args, 1, &repLen);
}
(void) lin;
}
a_class(a_Preprocessor) {
a_Token0 t0[1], t0a[1];
a_Preprocessor_SourceFiles sfs[1];
a_Set0 set[1], typCache[1];
a_Preprocessor_If ppIf[1];
a_Preprocessor_Eval ppEv[1];
a_VecChr defEnum[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_DbgLv1( a_DbgObjInf doi[1]; )
};
a_static void a_Preprocessor_ini(_aDef_ a_Preprocessor *w)
{
a_Token0_ini1(w->t0);
a_Token0_ini1(w->t0a);
a_Set0_ini(_a_ w->set, a_Preprocessor_Define0_din);
a_Set0_ini(_a_ w->typCache, a_TypedDef_TypeCache_din);
a_Preprocessor_SourceFiles_ini(_a_ w->sfs);
a_Preprocessor_If_ini(_a_ w->ppIf);
a_Preprocessor_Eval_ini(_a_ w->ppEv);
a_VecChr_ini(_a_ w->defEnum);
w->ppIf->eval = a_Preprocessor_eval;
w->ppIf->w_eval = w->ppEv;
w->incl = (void *) a_Preprocessor_incl0;
w->w_incl = NULL;
a_Preprocessor_define2(0, "ifdef if defined", w->t0, w->set, 1, w->typCache);
a_Preprocessor_define2(0, "ifndef if !defined", w->t0, w->set, 1, w->typCache);
a_Preprocessor_define2(0, "elifdef elif defined", w->t0, w->set, 1, w->typCache);
a_Preprocessor_define2(0, "elifndef elif !defined", w->t0, w->set, 1, w->typCache);
a_DbgLv2( a_DbgObjInf_ini(_aThr, w->doi, "Preprocessor"); )
}
a_static void a_Preprocessor_din(_aDef_ a_Preprocessor *w)
{
a_DbgLv2( a_DbgObjInf_din(_aThr, w->doi); )
a_Set0_din(_a_ w->set);
a_Set0_din(_a_ w->typCache);
a_Preprocessor_SourceFiles_din(_a_ w->sfs);
a_Preprocessor_If_din(_a_ w->ppIf);
a_Preprocessor_Eval_din(_a_ w->ppEv);
a_VecChr_din(_a_ w->defEnum);
}
a_static void a_Preprocessor_main(a_Preprocessor *w)
{
int defC = 1, retryCount = 0;
a_VecChr lin[1], tmp[1], tmp1[1], args[1]; a_VecChr_ini4(_a_ lin, tmp, tmp1, args);
for (;;) {
if (w->sfs->s >= w->sfs->buf->p + a_VecChr_N(w->sfs->buf)) retryCount = 0; // バッファが空になった.
a_Preprocessor_SourceFiles_gets(w->sfs, lin);
if (a_VecChr_N(lin) == 0) break;
for (;;) { // 末尾が "\\\n"であれば、後続行を接続.
char *p1 = lin->p + a_VecChr_N(lin);
if (!(a_VecChr_N(lin) >= 2 && p1[-2] == '\\' && p1[-1] == '\n')) break;
a_Preprocessor_SourceFiles_gets(w->sfs, tmp);
a_VecChr_replace(lin, a_VecChr_N(lin) - 2, 2, tmp->p, a_VecChr_N(tmp));
}
if (retryCount >= 64) {
if (w->ppIf->phase != 0)
w->put(w->w_put, lin, w->sfs);
continue;
}
if (a_Preprocessor_isDirective(lin->p, lin->p + a_VecChr_N(lin)) == 0) {
a_Preprocessor_SourceFile *sf = a_Preprocessor_SourceFiles_getSf(w->sfs);
if (a_Preprocessor_substitute0(w->t0, lin, sf->path, sf->lin, 0, tmp, w->defEnum) != 0) {
retry:
a_Preprocessor_SourceFiles_addBuf(w->sfs, lin->p, a_VecChr_N(lin));
retryCount++; continue;
}
if (a_Preprocessor_substitute1(w->t0, w->t0a, lin, 0, w->set, tmp, tmp1, defC) != 0) goto retry;
if (w->ppIf->phase != 0)
w->put(w->w_put, lin, w->sfs);
continue;
}
const char *s = lin->p, *s1 = lin->p + a_VecChr_N(lin);
while (s < s1 && *(const unsigned char *) s <= ' ') s++;
s++; // '#'.
if (strncmp(s, "if", 2) == 0 || strncmp(s, "elif", 4) == 0 || strncmp(s, "defineX", 7) == 0 || strncmp(s, "typedDefX", 9) == 0) { // これらで始まる場合は例外的にsubstitute()する.
a_Preprocessor_SourceFile *sf = a_Preprocessor_SourceFiles_getSf(w->sfs);
if (a_Preprocessor_substitute0(w->t0, lin, sf->path, sf->lin, 0, tmp, w->defEnum) != 0) goto retry;
if (a_Preprocessor_substitute1(w->t0, w->t0a, lin, 0, w->set, tmp, tmp1, defC) != 0) goto retry;
}
w->t0->s = s; w->t0->s1 = s1; a_Token1_get(w->t0);
if (w->ppIf->phase != 0) {
if (w->t0->len == 7 && strncmp(s, "include", 7) == 0) { if (w->incl(w->w_incl, s + 7, s1, w->sfs) > 0) continue; }
if (w->t0->len == 6 && strncmp(s, "define", 6) == 0) { a_Preprocessor_define1(0, w->t0, lin, w->sfs, args, tmp, tmp1, w->set, defC, w->typCache); continue; }
if (w->t0->len == 8 && strncmp(s, "typedDef", 8) == 0) { a_Preprocessor_define1(1, w->t0, lin, w->sfs, args, tmp, tmp1, w->set, defC, w->typCache); continue; }
if (w->t0->len == 4 && strncmp(s, "line", 4) == 0) { a_Preprocessor_line(w->sfs, w->t0); continue; }
if (w->t0->len == 5 && strncmp(s, "undef", 5) == 0) { a_Preprocessor_undef(0, w->t0, lin, args, w->set); continue; }
if (w->t0->len == 6 && strncmp(s, "undefx", 6) == 0) { a_Preprocessor_undef(1, w->t0, lin, args, w->set); continue; }
if (w->t0->len == 7 && strncmp(s, "defineX", 7) == 0) { a_Preprocessor_define1(0, w->t0, lin, w->sfs, args, tmp, tmp1, w->set, defC, w->typCache); continue; }
if (w->t0->len == 9 && strncmp(s, "typedDefX", 9) == 0) { a_Preprocessor_define1(1, w->t0, lin, w->sfs, args, tmp, tmp1, w->set, defC, w->typCache); continue; }
}
w->t0->s = s; // w->t0->s1 = s1;
char *t = a_Token1_get(w->t0);
if (a_Preprocessor_if(w->ppIf, lin, w->t0, t) > 0) continue; // if, elif, else, endif.
if (w->ppIf->phase != 0)
w->put(w->w_put, lin, w->sfs); // エラー検出のため.
continue;
}
a_VecChr_din4(_a_ lin, tmp, tmp1, args);
}
a_static void a_Preprocessor_ini1(const char *s, intptr_t n, int mod, a_VecChr *dst)
{
a_Preprocessor pp[1]; a_Preprocessor_ini(_a_ pp);
a_Preprocessor_Put1 put1[1];
if (mod == 1 || mod == 2) {
a_Preprocessor_Put1_ini(_a_ put1);
pp->w_put = put1;
put1->dst = dst;
}
if (mod == 1) {
pp->put = (void *) a_Preprocessor_put1;
put1->sfs = pp->sfs;
}
if (mod == 2)
pp->put = (void *) a_Preprocessor_put2;
a_Preprocessor_SourceFiles_addFile(pp->sfs, s, n, 1);
if (mod == 1 || mod == 2) {
a_Preprocessor_main(pp); a_Preprocessor_din(_a_ pp);
a_VecChr tmp[1], imm[1]; a_VecChr_ini4(_a_ tmp, imm, 0, 0);
put1->dst = tmp; a_Preprocessor_main(pp); a_Preprocessor_Put1_din(_a_ put1);
a_VecChr_printf(imm, "imm<tmp>:%.*s", a_VecChr_N(tmp), tmp->p);
a_Preprocessor_SourceFiles_addFile(pp->sfs, imm->p, a_VecChr_N(imm), 1);
a_Preprocessor_Put1_ini(_a_ put1); put1->dst = dst; a_Preprocessor_main(pp);
a_VecChr_din4(_a_ tmp, imm, 0, 0);
a_Preprocessor_din(_a_ pp);
a_Preprocessor_Put1_din(_a_ put1);
}
}
** (99) 更新履歴
-2026.04.26(日) 初版
-2026.05.03(日) #define/#typedDefの前方参照に対応