acl4のページ0010

(1)

#if (a_Version >= 1)
    #define Preprocessor_Define     a_Preprocessor_Define
    #define Preprocessor_define0    a_Preprocessor_define0
    #define Preprocessor_define1    a_Preprocessor_define1
    #define Preprocessor_define2    a_Preprocessor_define2
    #define Preprocessor_define3    a_Preprocessor_define3
#endif

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

a_static void a_Preprocessor_if0(a_Preprocessor_If *w)
{
    a_VecChr_ini(w->stk); a_VecChr_reserve(w->stk, 16); w->stk->n = 1; w->stk->p[0] = 5;
    w->phase = 1;
}

a_static int a_Preprocessor_if1(a_Preprocessor_If *w, a_VecChr *linBuf, a_Token0 *t0, char *t)
{
    (void) w;
    intptr_t n = t0->len;
    const char *s = NULL;
    if (n == 5 && memcmp(t, "ifdef",    5) == 0)  s = "#if    defined(%.*s)";
    if (n == 6 && memcmp(t, "ifndef",   6) == 0)  s = "#if   !defined(%.*s)";
    if (n == 7 && memcmp(t, "elifdef",  7) == 0)  s = "#elif  defined(%.*s)";
    if (n == 8 && memcmp(t, "elifndef", 8) == 0)  s = "#elif !defined(%.*s)";
    if (s != NULL) {
        const char *nam = a_Token1_get(t0);
        intptr_t namLen = t0->len;
        char *u = a_malloc(_arg_  namLen);
        memcpy(u, nam, namLen);
        linBuf->n = 0;
        a_VecChr_printf(linBuf, s, namLen, u);
        a_free(_arg_  u, namLen);
        t0->s = linBuf->p + 1; t0->s1 = linBuf->p + linBuf->n;
        t = a_Token1_get(t0); n = t0->len;
        return 1;
    }
    return 0;
}

a_static int a_Preprocessor_if2(a_Preprocessor_If *w, a_VecChr *linBuf, a_Token0 *t0, char *t)
{
    intptr_t n = t0->len;
    const char *s = NULL;
    if (n == 2 && memcmp(t, "if", 2) == 0) {
        a_VecChr_resizeDiff(_arg_  w->stk, 1); char *sp = &(w->stk->p[w->stk->n - 1]); *sp = 0;
        if ((sp[-1] & 1) != 0 && w->eval(w->w_eval, t0) != 0) *sp = 5;
        w->phase = *sp & 1;
        return 1;
    }
    if (n == 4 && memcmp(t, "elif", 4) == 0 && w->stk->n > 1) {
        char *sp = &(w->stk->p[w->stk->n - 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) != 0) *sp = 5;
        w->phase = *sp & 1;
        return 1;
    }
    if (n == 4 && memcmp(t, "else", 4) == 0 && w->stk->n > 1) {
        char *sp = &(w->stk->p[w->stk->n - 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 && w->stk->n > 1) {
        char *sp = &(w->stk->p[--(w->stk->n) - 1]);
        w->phase = *sp & 1;
        return 1;
    }
    return 0;
}

a_static void a_Preprocessor_if3(a_Preprocessor_If *w) { a_VecChr_din(w->stk); }

a_class(a_Preprocessor_Eval) { char err; };

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; uint32_t c = t0->c, n = t0->len;
    if (n == 0) { 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; }
    if ('0' <= *t && *t <= '9')
        i = strtol(t, NULL, 0);
    else {
        if (&t[n] < t0->s1 && t[n] == '(') {
            // 未定義マクロの引数部分を読み飛ばす. 値は0とする.
            a_Token1_get(t0);
            a_VecChr dmy[1]; a_VecChr_ini(dmy);
            a_parseArgs(t0, dmy);
            if (t0->c != ')') w->err = 1;
            a_VecChr_din(dmy);
        }
    }
op2:
    t = a_Token1_get(t0); c = t0->c; n = t0->len;
    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.
}

(2)

(3)

(99) 更新履歴


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