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) 更新履歴