* 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(水) 初版

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