* 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の前方参照に対応

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS