acl4のページ0013

(1)

#if (a_Version >= 1)
    #define Preprocessor_incl0          a_Preprocessor_incl0
    #define Preprocessor_Put0           a_Preprocessor_Put0
    #define Preprocessor_Put0_ini       a_Preprocessor_Put0_ini
    #define Preprocessor_Put0_din       a_Preprocessor_Put0_din
    #define Preprocessor_put0           a_Preprocessor_put0
    #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_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));
        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));
        return 1;
    }
    return 0;
}

a_class(a_Preprocessor_Put0) {
    a_Preprocessor_SourceFiles *sfs;
    a_VecChr *dst, path[1];
    intptr_t lin;
};

a_static void a_Preprocessor_Put0_ini(a_Preprocessor_Put0 *w) { a_VecChr_ini(w->path); w->lin = 0; }
a_static void a_Preprocessor_Put0_din(a_Preprocessor_Put0 *w) { a_VecChr_din(w->path); }

a_static void a_Preprocessor_put0(a_Preprocessor_Put0 *w, a_VecChr *lin)
{
    a_Preprocessor_SourceFile *sf = a_Preprocessor_SourceFiles_getSf(w->sfs);
    if (w->path->n != sf->path->n || (w->path->n > 0 && memcmp(w->path->p, sf->path->p, w->path->n) != 0)) {
        char *s = a_malloc(_arg_  sf->path->n + 64);
        sprintf(s, "#line %d \"%.*s\"\n", (int) sf->lin, (int) sf->path->n, sf->path->p);
        a_VecChr_puts(w->dst, s, s + strlen(s));
        a_free(_arg_  s, sf->path->n + 64);
        a_VecChr_replace(w->path, 0, w->path->n, sf->path->p, sf->path->n);
    } else if (w->lin + 1 < sf->lin && sf->lin < w->lin + 9) {
        while (w->lin + 1 < sf->lin) {
            char *s = "\n";
            a_VecChr_puts(w->dst, s, s + 1);
            w->lin++;
        }
    } else if (w->lin + 1 != sf->lin) {
        char s[64];
        sprintf(s, "#line %d\n", (int) sf->lin);
        a_VecChr_puts(w->dst, s, s + strlen(s));
    }
    a_VecChr_puts(w->dst, lin->p, lin->p + lin->n);
    w->lin = sf->lin;
}

a_class(a_Preprocessor) {
    a_Token0 t0[1];
    a_Preprocessor_SourceFiles sfs[1];
    a_Set0 set[1];
    a_Preprocessor_If ppIf[1];
    a_Preprocessor_Eval ppEv[1];
    a_Preprocessor_Put0 put0[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_static void a_Preprocessor_ini(a_Preprocessor *w)
{
    a_Token0_ini1(w->t0);
    a_Preprocessor_SourceFiles_ini(w->sfs);
    a_Preprocessor_if0(w->ppIf);
    a_Set0_ini(w->set);
    // 以下はとりあえずのデフォルト設定. 不要なら上書きする.
    w->ppIf->eval = (void *) a_Preprocessor_eval;
    w->ppIf->w_eval = w->ppEv;
    w->incl = (void *) a_Preprocessor_incl0;
    w->w_incl = NULL;
    a_Preprocessor_Put0_ini(w->put0);
    w->put = (void *) a_Preprocessor_put0;
    w->w_put = w->put0;
    w->put0->sfs = w->sfs;
    a_Preprocessor_define7(w->set, -1, "ifdef",    "if    defined");
    a_Preprocessor_define7(w->set, -1, "ifndef",   "if   !defined");
    a_Preprocessor_define7(w->set, -1, "elifdef",  "elif  defined");
    a_Preprocessor_define7(w->set, -1, "elifndef", "elif !defined");
}

a_static void a_Preprocessor_din(a_Preprocessor *w)
{
    a_Preprocessor_define3(w->set);
    a_Preprocessor_if3(w->ppIf);
    a_Preprocessor_SourceFiles_din(w->sfs);
    a_Preprocessor_Put0_din(w->put0);
}

a_static void a_Preprocessor_line(a_Preprocessor *w)
{
    a_Preprocessor_SourceFile *sf = a_Preprocessor_SourceFiles_getSf(w->sfs);
    const char *t = a_Token1_get(w->t0);
    sf->lin = strtol(t, NULL, 0) - 1;
    t = a_Token1_get(w->t0);
    if (w->t0->len >= 2 && *t == 0x22) {
        sf->path->n = 0;
        a_VecChr_puts(sf->path, t + 1, t + w->t0->len - 1);
    }
}

a_static void a_Preprocessor_main(a_Preprocessor *w)
{
    int defC = 1;
    a_VecChr lin[1], tmp[1], stkDef[1]; a_VecChr_ini4(lin, tmp, stkDef, 0);
    for (;;) {
        a_Preprocessor_SourceFiles_gets(w->sfs, lin);
        if (lin->n == 0) break;
        for (;;) { // 末尾が "\\\n"であれば、後続行を接続.
            char *p1 = lin->p + lin->n;
            if (!(lin->n >= 2 && p1[-2] == '\\' && p1[-1] == '\n')) break;
            a_Preprocessor_SourceFiles_gets(w->sfs, tmp);
            a_VecChr_replace(lin, lin->n - 2, 2, tmp->p, tmp->n);
        }
        if (a_Preprocessor_isDirective(lin->p, lin->p + lin->n) == 0) {
            a_Preprocessor_SourceFile *sf = a_Preprocessor_SourceFiles_getSf(w->sfs);
            if (a_Preprocessor_define2(w->set, w->t0, lin, defC, sf->path, sf->lin, 0) != 0) {
retry:
                 a_Preprocessor_SourceFiles_addBuf(w->sfs, lin->p, lin->n);
                 continue;
            }
            if (w->ppIf->phase != 0)
                w->put(w->w_put, lin, w->sfs);
            continue;
        }
        const char *s = lin->p, *s1 = lin->p + lin->n;
        while (s < s1 && *(const unsigned char *) s <= ' ') s++;
        s++; // '#'.
        if (strncmp(s, "if", 2) == 0 || strncmp(s, "elif", 4) == 0) {
            a_Preprocessor_SourceFile *sf = a_Preprocessor_SourceFiles_getSf(w->sfs);
            if (a_Preprocessor_define2(w->set, w->t0, lin, defC, sf->path, sf->lin, 0) != 0) goto retry;
        }
        w->t0->s = s + 1; w->t0->s1 = lin->p + lin->n; a_Token1_get(w->t0);
        if (w->ppIf->phase != 0) {
            if (strncmp(s, "include", 7) == 0) { if (w->incl(w->w_incl, s + 7, s1, w->sfs) > 0) continue; }
            if (strncmp(s, "define", 6) == 0) { a_Preprocessor_define5(w->set, w->t0, lin, defC, w->sfs, stkDef, 0); continue; }
            if (strncmp(s, ".def",   4) == 0) { a_Preprocessor_define5(w->set, w->t0, lin, defC, w->sfs, stkDef, 1); continue; }
            if (strncmp(s, ".addTl", 6) == 0) { a_Preprocessor_define5(w->set, w->t0, lin, defC, w->sfs, stkDef, 2); continue; }
            if (strncmp(s, ".addHd", 6) == 0) { a_Preprocessor_define5(w->set, w->t0, lin, defC, w->sfs, stkDef, 3); continue; } 
            if (strncmp(s, "undef",  5) == 0) { if (a_Preprocessor_define6(w->set, w->t0, lin, stkDef, 0) > 0) continue; }
            if (strncmp(s, ".undef", 6) == 0) { if (a_Preprocessor_define6(w->set, w->t0, lin, stkDef, 1) > 0) continue; }
            if (strncmp(s, "line",   4) == 0) { a_Preprocessor_line(w); continue; }
        }
        w->t0->s = s; w->t0->s1 = lin->p + lin->n;
        char *t = a_Token1_get(w->t0);
        if (a_Preprocessor_if2(w->ppIf, lin, w->t0, t) > 0) continue;
        if (w->ppIf->phase != 0)
            w->put(w->w_put, lin, w->sfs); // エラー検出のため.
        continue;
    }
    while (stkDef->n > 0) {
        a_Preprocessor_Define *sp = a_VecChr_stkRmv(stkDef, sizeof (a_Preprocessor_Define));
        a_Preprocessor_Define_din(sp);
    }
    a_VecChr_din4(lin, tmp, stkDef, 0);
}

(2) 説明

(3) サンプルプログラム: t0013a.c [13行]

#define a_Version 1
#include <acl4.c>

int main(int argc, const char **argv)
{
    if (argc < 2) return 1;
    Preprocessor pp[1]; Preprocessor_ini(pp);                            // プリプロセッサの初期化.
    Preprocessor_SourceFiles_addFile(pp->sfs, argv[1], strlen(argv[1])); // 最初に読むファイルを指定.
    VecChr dst[1]; VecChr_ini(dst); pp->put0->dst = dst;                 // 出力先のオブジェクトを指定.
    Preprocessor_main(pp); Preprocessor_din(pp);                         // プリプロセッサ処理. およびメモリ開放.
    VecChr_reserve0(dst); puts(dst->p); VecChr_din(dst);                 // 処理結果を出力. およびメモリ開放.
    a_malloc_debugList(_arg);                                            // メモリリークがないか確認.
}

(3) サンプルプログラム: t0013b.c [101行]

#define a_Version 1
#include <acl4.c>

class_(Var) { SetElm elm[1]; double d; };
Set0 setVar[1];

double *getVarPtr(const char *s, intptr_t n) → p0002b.c のものをそのまま使います

int np = 0;

double eval(Token0 *t0, int pri) → p0002b.c のものをそのまま使います

void myPut(Preprocessor_Put0 *w, VecChr *lin)
{
    // エラーが起きて未処理扱いになったプリプロセッサ制御行があれば、それはエラー出力して変換結果に含めない.
    if (Preprocessor_isDirective(lin->p, lin->p + lin->n) != 0)
        fprintf(stderr, "[err] %.*s", lin->n, lin->p);
    else
        VecChr_puts(w->dst, lin->p, lin->p + lin->n);
}

int main(int argc, const char **argv)
{
    if (argc < 2) return 1;
    Preprocessor pp[1]; Preprocessor_ini(pp);                            // プリプロセッサの初期化.
    pp->put = (void *) myPut;                                            // 出力関数の変更.
    Preprocessor_SourceFiles_addFile(pp->sfs, argv[1], strlen(argv[1])); // 入力ファイルを指定.
    VecChr vc[1]; VecChr_ini(vc); pp->put0->dst = vc;                    // 出力先のオブジェクトを指定.
    Preprocessor_main(pp); Preprocessor_din(pp);                         // プリプロセッサ処理. およびメモリ開放.

    Token0 t0[1]; Token0_ini1(t0); // ここから下は p0002b.c の main にあったものをそのまま使用.
    Set0_ini(setVar);
    t0->s = vc->p; t0->s1 = vc->p + vc->n;
    double d = eval(t0, 99);
    if (np == 0)
         printf("%f\n", d);
    VecChr_din(vc);
    intptr_t i, n = setVar->tbl->n / sizeof (Var *);
    for (i = 0; i < n; i++)
        free_(_arg_  ((Var **) setVar->tbl->p)[i], sizeof (Var));
    Set0_din(setVar);
    a_malloc_debugList(_arg);
    return 0;
}




(99) 更新履歴


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS