acl4のページ0020

(1) 概要


(2) デモ

(3) ライブラリプログラム

#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_setPath         a_Preprocessor_SourceFile_setPath
    #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
#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(_a_ w->src, w->path, 0, 0);
    w->lin = 0;
}

a_static void a_Preprocessor_SourceFile_din(a_Preprocessor_SourceFile *w)
{
    a_VecChr_din4(_a_ w->src, w->path, 0, 0);
}

a_static intptr_t a_Preprocessor_SourceFile_setPath(a_Preprocessor_SourceFile *w, const char *path, intptr_t n)
{
    intptr_t i = 0;
    if (n >= 7 && strncmp(path, "inline:", 7) == 0) {
        a_VecChr_puts(w->path, path, n);
        a_VecChr_puts(w->src, &path[7], n - 7);
        a_VecChr_convEsc(w->src);
    } else if (n >= 6 && strncmp(path, "imm<", 4) == 0) {
        const char *p = strstr(path, ">:");
        if (p != NULL && p + 2 - path <= n) {
            a_VecChr_puts(w->path, path + 4, p - path - 4);
            a_VecChr_puts(w->src, p + 2, path + n - (p + 2));
        } else
            i = -1;
    } else {
        a_VecChr_puts(w->path, path, n);
        i = a_VecChr_readFileAll(w->src, w->path->p);
        a_VecChr_eraseCr(w->src);
    }
    if (i >= 0) { i = a_VecChr_N(w->src); 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 + a_VecChr_N(w->src));
    if (a_VecChr_N(lin) > 0) w->lin++;
}

a_class(a_Preprocessor_SourceFiles) {
    a_VecChr buf[1], stk[1];
    char *s;
    a_DbgLv1( a_DbgObjInf doi[1]; )
};

a_static void a_Preprocessor_SourceFiles_ini(_aDef_ a_Preprocessor_SourceFiles *w)
{
    a_VecChr_ini4(_a_ w->buf, w->stk, 0, 0);
    a_VecChr_reserve0(w->buf);
    w->s = w->buf->p;
    a_DbgLv2( a_DbgObjInf_ini(_aThr, w->doi, "Preprocessor_SourceFiles"); )
}

a_static void a_Preprocessor_SourceFiles_din(_aDef_ a_Preprocessor_SourceFiles *w)
{
    a_DbgLv2( a_DbgObjInf_din(_aThr, w->doi); )
    intptr_t i, n = a_VecChr_N(w->stk) / (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(_a_  p[i], sizeof (a_Preprocessor_SourceFile));
    }
    a_VecChr_din4(_a_ w->buf, w->stk, 0, 0);
}

a_static intptr_t a_Preprocessor_SourceFiles_addFile(a_Preprocessor_SourceFiles *w, const char *path, intptr_t n, int flg)
{
    a_Preprocessor_SourceFile *p = a_malloc(_a_  sizeof (a_Preprocessor_SourceFile));
    a_Preprocessor_SourceFile_ini(p);
    if (n < 0) n = strlen(path);
    intptr_t i = a_Preprocessor_SourceFile_setPath(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(_a_  p, sizeof (a_Preprocessor_SourceFile));
        if ((flg & 1) != 0)
            fprintf(stderr, "Preprocessor_SourceFiles_addFile: fopen error: path=\"%.*s\"\n", n, path);
    }
    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 (a_VecChr_N(w->stk) == 0) return NULL;
    return *(a_Preprocessor_SourceFile **) a_VecChr_stkTop(w->stk, 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 + a_VecChr_N(w->buf));
    if (a_VecChr_N(lin) == 0) {
        while (a_VecChr_N(w->stk) > 0) {
            a_Preprocessor_SourceFile *sf = a_Preprocessor_SourceFiles_getSf(w);
            a_Preprocessor_SourceFile_gets(sf, lin);
            if (a_VecChr_N(lin) > 0) break;
            a_VecChr_stkRmv(w->stk, sizeof (a_Preprocessor_SourceFile *));
            a_Preprocessor_SourceFile_din(sf);
            a_free(_a_  sf, sizeof (a_Preprocessor_SourceFile));
        }
    }
}

#if (a_Version >= 1)
    #define Preprocessor_Eval       a_Preprocessor_Eval
    #define Preprocessor_Eval_ini   a_Preprocessor_Eval_ini
    #define Preprocessor_Eval_din   a_Preprocessor_Eval_din
    #define Preprocessor_eval       a_Preprocessor_eval
    #define Preprocessor_If         a_Preprocessor_If
    #define Preprocessor_If_ini     a_Preprocessor_If_ini
    #define Preprocessor_If_din     a_Preprocessor_If_diin
    #define Preprocessor_if         a_Preprocessor_if
#endif

a_class(a_Preprocessor_Eval) {
    char err;
    a_VecChr tmp[1];
    int (*hook0)(a_Preprocessor_Eval *w, a_Token0 *t0, int pri, const char *t, intptr_t *pi);
    int (*hook1)(a_Preprocessor_Eval *w, a_Token0 *t0, int pri, const char *t, intptr_t *pi);
    int (*hook2)(a_Preprocessor_Eval *w, a_Token0 *t0, int pri, const char *t, intptr_t *pi);
    void *v[4];
    a_DbgLv1( a_DbgObjInf doi[1]; )
};

a_static int a_Preprocessor_Eval_hook0(a_Preprocessor_Eval *w, a_Token0 *t0, int pri, const char *t, intptr_t *pi)
{
    (void) w; (void) t0; (void) pri; (void) t; (void) pi; return 0;
}

a_static void a_Preprocessor_Eval_ini(_aDef_ a_Preprocessor_Eval *w)
{
    w->err = 0;
    a_VecChr_ini(_a_ w->tmp);
    w->hook0 = w->hook1 = w->hook2 = a_Preprocessor_Eval_hook0;
    a_DbgLv2( a_DbgObjInf_ini(_aThr, w->doi, "Preprocessor_Eval"); )
}

a_static void a_Preprocessor_Eval_din(_aDef_ a_Preprocessor_Eval *w)
{
    a_DbgLv2( a_DbgObjInf_din(_aThr, w->doi); )
    a_VecChr_din(_a_ w->tmp);
}

a_static intptr_t a_Preprocessor_eval(a_Preprocessor_Eval *w, a_Token0 *t0, int pri)
// この関数の利用者は、 pri=0x7fff として呼び出すことを想定.
{
    const char *t = a_Token1_get(t0); intptr_t i = 0, j, n = t0->len; uint32_t c = t0->c;
    j = w->hook0(w, t0, pri, t, &i);
    if (j < 0) return i; if (j == 1) goto op2;
    if (n == 0 || c == ('/' | '/' << 8)) { w->err = 1; return i; }
    if (c == '(') {
        i = a_Preprocessor_eval(w, t0, 99);
        a_Token1_get(t0);
        if (t0->c != ')') w->err = 1;
        goto op2;
    }
    if (c == '+' && pri >= 2) { i = + a_Preprocessor_eval(w, t0, 2); goto op2; }
    if (c == '-' && pri >= 2) { i = - a_Preprocessor_eval(w, t0, 2); goto op2; }
    if (c == '!' && pri >= 2) { i = ! a_Preprocessor_eval(w, t0, 2); goto op2; }
    if (c == '~' && pri >= 2) { i = ~ a_Preprocessor_eval(w, t0, 2); goto op2; }

    j = w->hook1(w, t0, pri, t, &i);
    if (j < 0) return i; if (j == 1) goto op2;
    if ('0' <= *t && *t <= '9') {
        i = strtol(t, NULL, 0);
    } else if (n >= 2 && *t == 0x27) { // '...'
        a_VecChr_N(w->tmp) = 0;
        a_VecChr_puts(w->tmp, t + 1, n - 2);
        a_VecChr_convEsc(w->tmp); a_VecChr_reserve0(w->tmp); i = w->tmp->p[0];
    } else if (&t[n] < t0->s1 && t[n] == '(') {
        // 未定義マクロの引数部分を読み飛ばす. 値は0とする.
        a_Token1_get(t0);
        a_parseArgs(t0, w->tmp);
        if (t0->c != ')') w->err = 1;
    }
    // それ以外の知らないトークンは引数なし未定義マクロだと解釈し、すべて値0とする.
op2:
    t = a_Token1_get(t0); c = t0->c; n = t0->len;
    j = w->hook2(w, t0, pri, t, &i);
    if (j < 0) return i; if (j == 1) goto op2;
//  if (n == 0) { w->err = 1; return i; }
    if (c ==  '*'             && pri >=  4) { i = i *  a_Preprocessor_eval(w, t0,  3); goto op2; }
    if (c ==  '+'             && pri >=  5) { i = i +  a_Preprocessor_eval(w, t0,  4); goto op2; }
    if (c ==  '-'             && pri >=  5) { i = i -  a_Preprocessor_eval(w, t0,  4); goto op2; }
    if (c == ('<' | '<' << 8) && pri >=  6) { i = i << a_Preprocessor_eval(w, t0,  5); goto op2; }
    if (c == ('>' | '>' << 8) && pri >=  6) { i = i >> a_Preprocessor_eval(w, t0,  5); goto op2; }
    if (c == ('<' | '=' << 8) && pri >=  7) { i = i <= a_Preprocessor_eval(w, t0,  6); goto op2; }
    if (c ==  '<'             && pri >=  7) { i = i <  a_Preprocessor_eval(w, t0,  6); goto op2; }
    if (c == ('>' | '=' << 8) && pri >=  7) { i = i >= a_Preprocessor_eval(w, t0,  6); goto op2; }
    if (c ==  '>'             && pri >=  7) { i = i >  a_Preprocessor_eval(w, t0,  6); goto op2; }
    if (c == ('=' | '=' << 8) && pri >=  8) { i = i == a_Preprocessor_eval(w, t0,  7); goto op2; }
    if (c == ('!' | '=' << 8) && pri >=  8) { i = i != a_Preprocessor_eval(w, t0,  7); goto op2; }
    if (c ==  '&'             && pri >=  9) { i = i &  a_Preprocessor_eval(w, t0,  8); goto op2; }
    if (c ==  '^'             && pri >= 10) { i = i ^  a_Preprocessor_eval(w, t0,  9); goto op2; }
    if (c ==  '|'             && pri >= 11) { i = i |  a_Preprocessor_eval(w, t0, 10); goto op2; }
    if (c == ('&' | '&' << 8) && pri >= 12) { i = i && a_Preprocessor_eval(w, t0, 11); goto op2; }
    if (c == ('|' | '|' << 8) && pri >= 13) { i = i || a_Preprocessor_eval(w, t0, 12); goto op2; }
    if (c ==  '/'             && pri >=  4) {
        j = a_Preprocessor_eval(w, t0,  3);
        if (j != 0) { i = i / j; } else { w->err = 1; i = 0; }
        goto op2;
    }
    if (c ==  '%'             && pri >=  4) {
        j = a_Preprocessor_eval(w, t0,  3);
        if (j != 0) { i = i % j; } else { w->err = 1; i = 0; }
        goto op2;
    }
    t0->s = t; return i; // 一度読み込んだ未解釈の演算子をt0に押し戻してからreturn.
}

a_class(a_Preprocessor_If) {
    a_VecChr stk[1];
    char phase;
    int (*eval)(a_Preprocessor_Eval *, a_Token0 *, int);
    a_Preprocessor_Eval *w_eval;
    a_DbgLv1( a_DbgObjInf doi[1]; )
};

a_static void a_Preprocessor_If_ini(_aDef_ a_Preprocessor_If *w)
{
    a_VecChr_ini(_a_ w->stk); a_VecChr_reserve(w->stk, 16); a_VecChr_N(w->stk) = 1; w->stk->p[0] = 5;
    w->phase = 1;
    a_DbgLv2( a_DbgObjInf_ini(_aThr, w->doi, "Preprocessor_If"); )
}

a_static void a_Preprocessor_If_din(_aDef_ a_Preprocessor_If *w)
{
    a_DbgLv2( a_DbgObjInf_din(_aThr, w->doi); )
    a_VecChr_din(_a_ w->stk);
}

a_static int a_Preprocessor_if(a_Preprocessor_If *w, a_VecChr *linBuf, a_Token0 *t0, char *t)
{
    intptr_t n = t0->len; (void) linBuf;
    w->w_eval->err = 0;
    if (n == 2 && memcmp(t, "if", 2) == 0) {
        a_VecChr_resizeDiff(w->stk, 1); char *sp = &(w->stk->p[a_VecChr_N(w->stk) - 1]); *sp = 0;
        if ((sp[-1] & 1) != 0 && w->eval(w->w_eval, t0, 0x7fff) != 0) *sp = 5;
        a_Token1_get(t0);
        if ((t0->c != 0 && t0->c != ('/' | '/' << 8)) || w->w_eval->err != 0) {
            if ((sp[-1] & 1) != 0) *sp = 5;
            w->phase = *sp & 1; return 0;
        }
        w->phase = *sp & 1;
        return 1;
        // *spの値の説明: bit0-2に意味がある.
        //   bit0: phaseの値.
        //   bit1: 今はthen節の中にいるのか?それともelse節の中にいるのか?(0=then, 1=else).
        //   bit2: if~elif~elif~...~else~endif のかたまりにおいて、今までどこかで条件が成立したことがあるか?(1=ある).
        //     このbit2は意外に重要で、なぜならどこかで条件が成立してしまえば、以降はendifまで無視しなければならないから.
    }
    if (n == 4 && memcmp(t, "elif", 4) == 0 && a_VecChr_N(w->stk) > 1) {
        char *sp = &(w->stk->p[a_VecChr_N(w->stk) - 1]);
        if ((*sp & 2) != 0) return 0; // elseのあとにelifが来るのはおかしい. エラーに気づかせるために「未処理」とする.
        *sp &= 6;
        if ((sp[-1] & 1) != 0 && (*sp & 4) == 0 && w->eval(w->w_eval, t0, 0x7fff) != 0) *sp = 5;
        a_Token1_get(t0);
        if ((t0->c != 0 && t0->c != ('/' | '/' << 8)) || w->w_eval->err != 0) {
            if ((sp[-1] & 1) != 0) *sp = 5;
            w->phase = *sp & 1; return 0;
        }
        w->phase = *sp & 1;
        return 1;
    }
    if (n == 4 && memcmp(t, "else", 4) == 0 && a_VecChr_N(w->stk) > 1) {
        char *sp = &(w->stk->p[a_VecChr_N(w->stk) - 1]);
        if ((*sp & 2) != 0) return 0; // elseのあとにelseが来るのはおかしい.
        *sp |= 2; *sp &= 6;
        if ((sp[-1] & 1) != 0 && (*sp & 4) == 0) *sp = 7;
        w->phase = *sp & 1;
        return 1;
    }
    if (n == 5 && memcmp(t, "endif", 5) == 0 && a_VecChr_N(w->stk) > 1) {
        char *sp = &(w->stk->p[--(a_VecChr_N(w->stk)) - 1]);
        w->phase = *sp & 1;
        return 1;
    }
    return 0;
}

(99) 更新履歴


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