* acl4のページt0003 -(by [[K]], 2026.05.04) ** (1) 概要 -a4_t0003 は、 acl4v1 の2番目の補助ライブラリプログラムになります。 -補助ライブラリというのは、 acl4 ライブラリに加えられるほどきちんと書いてないけど、しかしそれなりには有用なのでライブラリ化はしておきたい、くらいの意味合いです。 -提供される主な機能は、以下の通りです。 --(1-1)DB/DW/DDで構成されたソースコードを解釈し、メモリに書き込む関数(アセンブラの最終処理) --(1-2) --(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) 更新履歴 -2026.05.04(月) 初版