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;
    }
    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_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
Last-modified: 2026-05-03 (日) 23:36:45 (43d)