#include "all.h" #include "str.h" static void emit_prelude(str *out) { str_append(out, "void _start(void){" "struct termios orig;" "rawon(0, &orig);" "u8 t[30000]={0};" "u8*p=t+15000;"); } static void emit_runtime(str *out) { str_append(out, "typedef unsigned long sz;" "typedef unsigned char u8;"); str_append(out, "typedef unsigned int tcflag_t;" "typedef unsigned char cc_t;" "typedef unsigned int speed_t;"); str_append(out, "struct termios{tcflag_t c_iflag;tcflag_t c_oflag;tcflag_t " "c_cflag;tcflag_t c_lflag;cc_t c_line;cc_t c_cc[19];speed_t " "c_ispeed; speed_t c_ospeed;};"); str_append(out, "static inline long sys3(long n, long a1, long a2, long a3){" "long ret;" "__asm__ volatile (" "\"syscall\"" ":\"=a\"(ret)" ":\"a\"(n),\"D\"(a1),\"S\"(a2),\"d\"(a3)" ":\"rcx\",\"r11\",\"memory\"" ");" "return ret;" "}"); str_append(out, "static void rawon(int fd,struct termios *orig){" "sys3(16,fd,0x5401,(long)orig);" "struct termios t=*orig;" "t.c_lflag&=~(2|010|0100000);" "t.c_cc[6]=1;" "t.c_cc[5]=0;" "sys3(16,fd,0x5402,(long)&t);" "}"); str_append(out, "static void rawoff(int fd,struct termios *orig){" "sys3(16,fd,0x5402,(long)orig);" "}"); } static void emit_epilogue(str *out) { str_append(out, "rawoff(0,&orig);sys3(60,0,0,0);}"); } void emit_node(str *out, ast_node_t *node) { for (; node; node = node->next) { switch (node->type) { case AST_INC: str_appendf(out, "*p+=%d;", node->val); break; case AST_DEC: str_appendf(out, "*p-=%d;", node->val); break; case AST_PTR_INC: str_appendf(out, "p+=%d;", node->val); break; case AST_PTR_DEC: str_appendf(out, "p-=%d;", node->val); break; case AST_OUT: str_appendf(out, "sys3(1,1,(long)p,1);"); break; case AST_IN: str_appendf(out, "sys3(0,0,(long)p,1);"); break; case AST_LOOP: str_append(out, "while(*p){"); for (size_t i = 0; i < node->children.len; i++) { emit_node(out, node->children._data[i]); } str_append(out, "}"); break; case AST_CLEAR: str_append(out, "*p=0;"); break; } } } str gen_code(ast_node_t *ast) { str out = {0}; emit_runtime(&out); emit_prelude(&out); emit_node(&out, ast); emit_epilogue(&out); return out; }