acl4のページt0003
(1) 概要
- a4_t0003 は、 acl4v1 の2番目の補助ライブラリプログラムになります。
- 補助ライブラリというのは、 acl4 ライブラリに加えられるほどきちんと書いてないけど、しかしそれなりには有用なのでライブラリ化はしておきたい、くらいの意味合いです。
- 提供される主な機能は、以下の通りです。
- (1-1)DB/DW/DDで構成されたソースコードを解釈し、メモリに書き込む関数(アセンブラなどで使われる)
- (1-2)C言語用のミニコンパイラの最初のバージョン
(2) デモ
(3) ライブラリプログラム
// #include <windows.h> してあることが前提.
a_static void *a_mallocRWX(intptr_t siz) { return VirtualAlloc(0, siz, MEM_COMMIT, PAGE_EXECUTE_READWRITE); } // 参考: https://essen.osask.jp/?a21_txt02
a_static intptr_t a_putBin(const char *s, intptr_t sn, char *b, intptr_t bn, a_Token0 *t0, a_Preprocessor_Eval *ev)
{
a_VecChr lbl[1]; a_VecChr_ini(_a_ lbl);
intptr_t pass, bi, *pi, *bp = (intptr_t *) b;
for (pass = 0; pass < 2; pass++) {
t0->s = s; t0->s1 = s + sn; bi = 0;
for (;;) {
const char *t = a_Token1_get(t0); intptr_t n = t0->len, i, j, k, m;
if (t0->c == ',' || t0->c == ';') continue;
if (t0->c == 0) break;
if (bn - bi < 16) { a_VecChr_din(_a_ lbl); return -1; }
if (n == 3 && memcmp(t, "LBL", 3) == 0) {
i = a_Preprocessor_eval(ev, t0, 0x7fff);
a_VecChr_reserve(lbl, (i + 1) * sizeof (intptr_t));
pi = (intptr_t *) lbl->p; pi[i] = (intptr_t) &b[bi];
}
m = 0;
if (n == 4 && memcmp(t, "DB_L", 4) == 0) m = 1;
if (n == 4 && memcmp(t, "DW_L", 4) == 0) m = 2;
if (n == 4 && memcmp(t, "DD_L", 4) == 0) m = 4;
if (m > 0) {
a_Token1_get(t0); i = a_Preprocessor_eval(ev, t0, 0x7fff);
a_Token1_get(t0); j = a_Preprocessor_eval(ev, t0, 0x7fff);
a_Token1_get(t0); k = a_Preprocessor_eval(ev, t0, 0x7fff); Token1_get(t0);
if (i == 1) { i = (intptr_t) &b[bi]; } else { a_VecChr_reserve(lbl, (i + 1) * sizeof (intptr_t)); pi = (intptr_t *) lbl->p; i = pi[i]; }
if (j == 1) { j = (intptr_t) &b[bi]; } else { a_VecChr_reserve(lbl, (j + 1) * sizeof (intptr_t)); pi = (intptr_t *) lbl->p; j = pi[j]; }
i = i - j + k;
goto db_i;
}
m = 0;
if (n == 4 && memcmp(t, "DB_R", 4) == 0) m = 1;
if (n == 4 && memcmp(t, "DW_R", 4) == 0) m = 2;
if (n == 4 && memcmp(t, "DD_R", 4) == 0) m = 4;
if (m > 0) {
i = a_Preprocessor_eval(ev, t0, 0x7fff);
i = i - (intptr_t) &b[bi];
goto db_i;
}
m = 0;
if (n == 2 && memcmp(t, "DB", 2) == 0) m = 1;
if (n == 2 && memcmp(t, "DW", 2) == 0) m = 2;
if (n == 2 && memcmp(t, "DD", 2) == 0) m = 4;
if (m > 0) {
i = a_Preprocessor_eval(ev, t0, 0x7fff);
db_i:
b[bi++] = i & 0xff;
if (m > 1) b[bi++] = (i >> 8) & 0xff;
if (m > 2) b[bi++] = (i >> 16) & 0xff;
if (m > 3) b[bi++] = (i >> 24) & 0xff;
}
if (n == 2 && memcmp(t, "DP", 2) == 0)
bp[bi++] = a_Preprocessor_eval(ev, t0, 0x7fff);
}
}
a_VecChr_din(_a_ lbl);
return bi;
}
a_static void a_conv_pp(const char *s, intptr_t sn, a_VecChr *dst, int flg, int dbg, const char *msg, FILE *fp, const char *incl)
{
a_VecChr vc[1]; a_VecChr_ini(_a_ vc);
if ((flg & 1) != 0) a_VecChr_N(dst) = 0;
if ((flg & 2) == 0)
a_VecChr_printf(vc, "imm<%s>:#include \"%s.h\"\n%.*s", incl, incl, sn, s);
else
a_VecChr_printf(vc, "imm<%s>:%.*s", incl, sn, s);
a_Preprocessor_ini1(vc->p, VecChr_N(vc), (flg >> 4) & 0xf, dst);
if (dbg != 0) fprintf(fp, msg, VecChr_N(dst), dst->p);
a_VecChr_din(_a_ vc);
}
a_static void a_convVc_pp(VecChr *src, VecChr *dst, int flg, int dbg, const char *msg, FILE *fp, const char *incl)
{
a_conv_pp(src->p, VecChr_N(src), dst, flg, dbg, msg, fp, incl);
}
a_class(a_AsmDbConstTable) { a_SetElm elm[1]; intptr_t v; };
a_static int a_eval_hook1(a_Preprocessor_Eval *w, a_Token0 *t0, int pri, const char *t, intptr_t *pi)
{
a_BufFree *bf = w->v[0];
a_VecChr *vcTmp = w->v[1];
a_Set0 *set = w->v[2];
intptr_t n = t0->len; (void) pri;
if (n >= 2 && t[0] == 0x22) {
char *s;
a_VecChr_N(vcTmp) = 0; a_VecChr_puts(vcTmp, t + 1, n - 2);
a_VecChr_convEsc(vcTmp);
*pi = (intptr_t) (s = a_BufFree_malloc(_a_ bf, a_VecChr_N(vcTmp) + 1));
memcpy(s, vcTmp->p, a_VecChr_N(vcTmp) + 1);
return 1;
}
a_AsmDbConstTable *elm = a_Set0_findKn(set, t, n);
if (elm != NULL) { *pi = elm->v; return 1; }
return 0;
}
a_static intptr_t a_conv_asmDb_bin(const char *s, intptr_t sn, char *b, intptr_t bn1, a_AsmDbConstTable *t, intptr_t tn, a_BufFree *bf)
{
a_Token0 t0[1]; a_Token0_ini1(t0); a_VecChr vc[1]; a_VecChr_ini(_a_ vc);
a_Set0 set[1]; a_Set0_ini(_a_ set, NULL); intptr_t i;
for (i = 0; i < tn; i++) {
t[i].elm->n = strlen(t[i].elm->k);
a_Set0_add(set, t[i].elm);
}
a_Preprocessor_Eval ev[1]; a_Preprocessor_Eval_ini(_a_ ev); ev->err = 0;
ev->hook1 = a_eval_hook1; ev->v[0] = bf; ev->v[1] = vc; ev->v[2] = set;
intptr_t bn = a_putBin(s, sn, b, bn1, t0, ev);
a_VecChr_din(_a_ vc); a_Set0_din(_a_ set); a_Preprocessor_Eval_din(_a_ ev);
return bn;
}
a_class(a_MiniCompiler_Sub) {
int mod;
int lb; a_VecChr vc[2];
// mod=0: for文.
// lb+0:continue0, lb+1:continue, lb+2:continue2, lb+3:break.
// vc0:繰り返し条件, vc1:cotinue時のインクリメント処理など.
};
a_class(a_MiniCompiler) {
a_Token0 *t0;
a_BufFree bf[1];
a_VecChr *vc;
a_VecChr stk[1], lbl[1];
int tmpNo, tmpLb, autoClose;
};
a_static void a_MiniCompiler_ini(a_MiniCompiler *w)
{
a_BufFree_ini(_a_ w->bf); a_VecChr_ini4(_a_ w->stk, w->lbl, 0, 0); w->tmpNo = 0; w->tmpLb = 0; w->autoClose = 0;
}
a_static void a_MiniCompiler_din(a_MiniCompiler *w)
{
a_BufFree_flush(_a_ w->bf); a_BufFree_din(_a_ w->bf); a_VecChr_din4(_a_ w->stk, w->lbl, 0, 0);
}
a_static char *a_MiniCompiler_newTmp(a_MiniCompiler *w)
{
char s[256];
intptr_t n = sprintf(s, "tmp%d", w->tmpNo++);
char *v = a_BufFree_malloc(_a_ w->bf, n + 1);
memcpy(v, s, n + 1);
return v;
}
#define a_MiniCompiler_compile_Macro0(pri, fmt) vv = a_MiniCompiler_compile(w, pri); tv = a_MiniCompiler_newTmp(w); a_VecChr_printf(w->vc, fmt, tv, v, vv); v = tv; goto op2
a_static char *a_MiniCompiler_compile(a_MiniCompiler *w, int pri)
{
char *v, *tv, *vv;
op1:
const char *tt, *t = a_Token1_get(w->t0); intptr_t n = w->t0->len; uint32_t c = w->t0->c;
if (w->autoClose > 0) { w->t0->s = t; c = '}'; w->autoClose--; }
if (c == '}') {
a_MiniCompiler_Sub *sb = VecChr_stkTop(w->stk, sizeof (a_MiniCompiler_Sub));
if (sb->mod == 0) {
a_VecChr_printf(w->vc, "Lbl_T(LT%04d);\n%s%sLbl_T(LT%04d);\n", sb->lb + 1, sb->vc[1].p, sb->vc[0].p, sb->lb + 3);
a_VecChr_din4(_a_ &sb->vc[0], &sb->vc[1], 0, 0); a_VecChr_stkRmv(w->stk, sizeof (a_MiniCompiler_Sub)); goto op1;
}
w->t0->s = t; return NULL;
}
if (n == 0) return NULL;
if (c == '-') {
tv = a_MiniCompiler_compile(w, 1); v = a_MiniCompiler_newTmp(w);
a_VecChr_printf(w->vc, "Mul(%s, %s, CInt:-1);\n", v, tv); goto op2;
}
if (c == ';') { if (pri == 98) { w->t0->s = t; return NULL; } a_VecChr_printf(w->vc, "Semi();\n"); w->tmpNo = 0; w->autoClose *= -1; goto op1; }
if (c == '(') { v = a_MiniCompiler_compile(w, 99); a_Token1_get(w->t0); goto op2; } // (...)
tt = a_Token1_get(w->t0); if (w->t0->c == ':') { // コードラベル宣言.
a_VecChr_printf(w->vc, "Lbl_T(%.*s);\n", n, t);
a_VecChr_printf(w->lbl, "#defineX %.*s defEnum(1)\n", n, t);
goto op1;
}
if (n == 2 && memcmp(t, "if", 2) == 0 && w->t0->c == '(') {
v = a_MiniCompiler_compile(w, 99); a_Token1_get(w->t0); // ')'.
tt = a_Token1_get(w->t0);
if (w->t0->len == 4 && memcmp(tt, "goto", 4) == 0) {
tt = a_Token1_get(w->t0); a_VecChr_printf(w->vc, "Jne(%s, CInt:0, Txt:%.*s);\n", v, w->t0->len, tt); goto op1;
}
w->t0->s = t; return NULL;
}
if (n == 3 && memcmp(t, "for", 2) == 0 && w->t0->c == '(') {
a_MiniCompiler_compile(w, 98); Token1_get(w->t0);
a_MiniCompiler_Sub *sb = a_VecChr_stkAdd(w->stk, sizeof (a_MiniCompiler_Sub));
sb->mod = 0;
sb->lb = w->tmpLb; w->tmpLb += 4;
a_VecChr_ini4(_a_ &sb->vc[0], &sb->vc[1], 0, 0);
a_VecChr_printf(w->vc, "Jmp_T(LT%04d);\n", sb->lb + 2);
a_VecChr_printf(w->vc, "Lbl_T(LT%04d);\n", sb->lb + 0);
a_VecChr *vc0 = w->vc; w->vc = &sb->vc[0];
a_VecChr_printf(w->vc, "Lbl_T(LT%04d);\n", sb->lb + 2);
v = a_MiniCompiler_compile(w, 98); Token1_get(w->t0);
if (v == NULL) { a_VecChr_printf(w->vc, "Jmp_T(LT%04d);\n", sb->lb + 0); }
else { a_VecChr_printf(w->vc, "Jne(%s, CInt:0, Txt:LT%04d);\n", v, sb->lb + 0); }
w->vc = &sb->vc[1];
v = a_MiniCompiler_compile(w, 98); a_Token1_get(w->t0); // ')'
w->vc = vc0; w->tmpNo = 0;
tt = a_Token1_get(w->t0); if (w->t0->c != '{') { w->t0->s = tt; w->autoClose--; }
goto op1;
}
if (n == 13 && memcmp(t, "Mul64Shr_RRRI", 13) == 0) {
for (;;) {
a_Token1_get(w->t0); if (w->t0->c == ';') break;
}
a_VecChr_printf(w->vc, "%.*s\n", w->t0->s - t, t);
goto op1;
}
if (n == 7 && memcmp(t, "openWin", 7) == 0) goto cFunc;
if (n == 6 && memcmp(t, "setPix", 6) == 0) goto cFunc;
if (n == 8 && memcmp(t, "flushWin", 8) == 0) goto cFunc;
if (n == 7 && memcmp(t, "waitInf", 7) == 0) goto cFunc;
if (n == 6 && memcmp(t, "printf", 6) == 0) {
cFunc:
a_VecChr vc0[1]; a_VecChr_ini(_a_ vc0); a_VecChr_printf(vc0, "%.*s(", n, t);
for (;;) {
t = Token1_get(w->t0); if (w->t0->c == ')') break;
if (w->t0->c == ',') continue;
w->t0->s = t; v = a_MiniCompiler_compile(w, 98); tt = a_MiniCompiler_newTmp(w);
a_VecChr_printf(w->vc, "Let(%s, %s);\n", tt, v);
a_VecChr_printf(vc0, "%s,", tt);
}
n = a_VecChr_N(vc0); if (vc0->p[n - 1] == ',') n--;
a_VecChr_printf(w->vc, "%.*s);\n", n, vc0->p); a_VecChr_din(_a_ vc0); v = "tmp0"; goto op2;
}
w->t0->s = tt; // 一度読み込んだ未解釈の演算子をt0に押し戻す.
if (n == 3 && memcmp(t, "int", 3) == 0) {
for (;;) {
t = a_Token1_get(w->t0); if (*t == ';') break;
if (*t == ',') continue;
a_VecChr_printf(w->vc, "#defineX %.*s Int:defEnum(0)\n", w->t0->len, t);
}
w->t0->s = t; goto op1;
}
if (('0' <= *t && *t <= '9') || *t == 0x22) {
v = a_BufFree_malloc(_a_ w->bf, n + 1 + 5);
memcpy(v, "CInt:", 5); memcpy(v + 5, t, n); v[n + 5] = '\0';
} else {
v = a_BufFree_malloc(_a_ w->bf, n + 1);
memcpy(v, t, n); v[n] = '\0';
}
op2:
t = a_Token1_get(w->t0); c = w->t0->c; n = w->t0->len;
if (n == 0) return v;
if (c == ('+' | '+' << 8) && pri >= 1) {
tv = a_MiniCompiler_newTmp(w);
a_VecChr_printf(w->vc, "Let(%s, %s); Add(%s, %s, CInt:1);\n", tv, v, v, v);
v = tv; goto op2;
}
if (c == '*' && pri >= 4) { a_MiniCompiler_compile_Macro0( 3, "Mul(%s, %s, %s);\n"); }
if (c == '/' && pri >= 4) { a_MiniCompiler_compile_Macro0( 3, "Div(%s, %s, %s);\n"); }
if (c == '%' && pri >= 4) { a_MiniCompiler_compile_Macro0( 3, "Mod(%s, %s, %s);\n"); }
if (c == '+' && pri >= 5) { a_MiniCompiler_compile_Macro0( 4, "Add(%s, %s, %s);\n"); }
if (c == '-' && pri >= 5) { a_MiniCompiler_compile_Macro0( 4, "Sub(%s, %s, %s);\n"); }
if (c == ('<' | '<' << 8) && pri >= 6) { a_MiniCompiler_compile_Macro0( 5, "Shl(%s, %s, %s);\n"); }
if (c == ('>' | '>' << 8) && pri >= 6) { a_MiniCompiler_compile_Macro0( 5, "Shr(%s, %s, %s);\n"); }
if (c == ('<' | '=' << 8) && pri >= 7) { a_MiniCompiler_compile_Macro0( 6, "Cle(%s, %s, %s);\n"); }
if (c == '<' && pri >= 7) { a_MiniCompiler_compile_Macro0( 6, "Clt(%s, %s, %s);\n"); }
if (c == ('>' | '=' << 8) && pri >= 7) { a_MiniCompiler_compile_Macro0( 6, "Cge(%s, %s, %s);\n"); }
if (c == '>' && pri >= 7) { a_MiniCompiler_compile_Macro0( 6, "Cgt(%s, %s, %s);\n"); }
if (c == ('=' | '=' << 8) && pri >= 8) { a_MiniCompiler_compile_Macro0( 7, "Ceq(%s, %s, %s);\n"); }
if (c == ('!' | '=' << 8) && pri >= 8) { a_MiniCompiler_compile_Macro0( 7, "Cne(%s, %s, %s);\n"); }
if (c == '&' && pri >= 9) { a_MiniCompiler_compile_Macro0( 8, "And(%s, %s, %s);\n"); }
if (c == '^' && pri >= 10) { a_MiniCompiler_compile_Macro0( 9, "Xor(%s, %s, %s);\n"); }
if (c == '|' && pri >= 11) { a_MiniCompiler_compile_Macro0(10, "Or_(%s, %s, %s);\n"); }
if (c == '=' && pri >= 15) { a_VecChr_printf(w->vc, "Let(%s, %s);\n", v, a_MiniCompiler_compile(w, 15)); goto op2; }
if (c == ';' && pri >= 98) { if (pri == 98) { w->t0->s = t; return v; } a_VecChr_printf(w->vc, "Semi();\n"); w->tmpNo = 0; w->autoClose *= -1; goto op1; }
w->t0->s = t; return v; // 一度読み込んだ未解釈の演算子をt0に押し戻してからreturn.
}
void a_conv_clang_clout(const char *s, intptr_t sn, a_VecChr *dst, int flg)
{
if ((flg & 1) != 0) a_VecChr_N(dst) = 0;
a_Token0 t0[1]; a_Token0_ini1(t0);
t0->s = s; t0->s1 = s + sn;
a_MiniCompiler mc[1]; a_MiniCompiler_ini(mc); mc->t0 = t0; mc->vc = dst;
a_MiniCompiler_compile(mc, 99); a_VecChr_replace(dst, 0, 0, mc->lbl->p, a_VecChr_N(mc->lbl));
a_MiniCompiler_din(mc); a_VecChr_reserve0(dst);
}
void a_convVc_clang_clout(a_VecChr *src, a_VecChr *dst, int flg) { a_conv_clang_clout(src->p, a_VecChr_N(src), dst, flg); }
(99) 更新履歴