/*************************************************************** crc's _ _ ___ _ _ __ ___ _ _| | |_ / (_) | ___ | '_ ` _ \| | | | | __| / /| | |/ _ \ | | | | | | |_| | | |_ / / | | | (_) | |_| |_| |_|\__,_|_|\__/_/ |_|_|\___/ (c) charles childers This is a special implementation of my ilo computer, with many copies of ilo running under a single process. Under this you can quickly switch between ilo instances. - `bye` will act like `restart` on the current computer - ctrl+c restarts the current computer - ctrl+n switches to the next ilo - ctrl+p switches to the previous ilo - ctrl+a shuts down mult/ilo - switching can only be done when the system is waiting for input **************************************************************/ #include #include #include #include #include #include #define V void #define I int #define C char #define ILOS 5 struct termios old_term, new_term; typedef struct ilo ilo; struct ilo { I ip, /* instruction pointer */ sp, /* data stack pointer */ rp, /* address stack pointer */ ds[33], /* data stack */ as[257], /* address stack */ m[65536]; /* memory */ C *blocks, /* name of block file (ilo.blocks) */ *rom; /* name of image (ilo.rom) */ I a, b, f, s, d, l; C i[1]; }; struct ilo systems[ILOS]; I cur, cancel; #define DS v->ds #define AS v->as #define SP v->sp #define RP v->rp #define IP v->ip #define M v->m #define A v->a #define B v->b #define S v->s #define D v->d #define L v->l #define T DS[SP] /* Top of Data Stack */ #define N DS[SP-1] /* Next on Data Stack */ #define R AS[RP] /* Top of Address Stack */ V iof(ilo *); V push(ilo *v, I n) { DS[SP + 1] = n; SP += 1; } I pop(ilo *v) { SP -= 1; return DS[SP + 1]; } V load_image(ilo *v) { v->f = open(v->rom, O_RDONLY, 0666); if (!v->f) { return; }; read(v->f, &M, 65536 * 4); close(v->f); v->i[0] = 32; IP = SP = RP = 0; } V save_image(ilo *v) { v->f = open(v->rom, O_WRONLY, 0666); write(v->f, &M, 65536 * 4); close(v->f); } V block_common(ilo *v) { B = pop(v); /* block buffer */ A = pop(v); /* block number */ lseek(v->f, 4096 * A, SEEK_SET); } V read_block(ilo *v) { v->f = open(v->blocks, O_RDONLY, 0666); block_common(v); read(v->f, M + B, 4096); close(v->f); } V write_block(ilo *v) { v->f = open(v->blocks, O_WRONLY, 0666); block_common(v); write(v->f, M + B, 4096); close(v->f); } V save_ip(ilo *v) { RP += 1; R = IP; } V symmetric(ilo *v) { if (B >= 0 && N < 0) { T += 1; N -= B; } } V li(ilo *v) { IP += 1; push(v, M[IP]); } V du(ilo *v) { push(v, T); } V dr(ilo *v) { DS[SP] = 0; SP -= 1; } V sw(ilo *v) { A = T; T = N; N = A; } V pu(ilo *v) { RP += 1; R = pop(v); } V po(ilo *v) { push(v, R); RP -= 1; } V ju(ilo *v) { IP = pop(v) - 1; } V ca(ilo *v) { save_ip(v); IP = pop(v) - 1; } V cc(ilo *v) { A = pop(v); if (pop(v)) { save_ip(v); IP = A - 1; } } V cj(ilo *v) { A = pop(v); if (pop(v)) { IP = A - 1; } } V re(ilo *v) { IP = R; RP -= 1; } V eq(ilo *v) { N = (N == T) ? -1 : 0; SP -= 1; } V ne(ilo *v) { N = (N != T) ? -1 : 0; SP -= 1; } V lt(ilo *v) { N = (N < T) ? -1 : 0; SP -= 1; } V gt(ilo *v) { N = (N > T) ? -1 : 0; SP -= 1; } V fe(ilo *v) { T = M[T]; } V st(ilo *v) { M[T] = N; SP -= 2; } V ad(ilo *v) { N += T; SP -= 1; } V su(ilo *v) { N -= T; SP -= 1; } V mu(ilo *v) { N *= T; SP -= 1; } V di(ilo *v) { A = T; B = N; if (A == 0) { cancel = 1; iof(v); return; } T = B / A; N = B % A; symmetric(v); } V an(ilo *v) { N = T & N; SP -= 1; } V or(ilo *v) { N = T | N; SP -= 1; } V xo(ilo *v) { N = T ^ N; SP -= 1; } V sl(ilo *v) { N = N << T; SP -= 1; } V sr(ilo *v) { N = N >> T; SP -= 1; } V cp(ilo *v) { L = pop(v); D = pop(v); S = T; T = -1; while (L) { if (M[D] != M[S]) { T = 0; } L -= 1; S += 1; D += 1; } } V cy(ilo *v) { L = pop(v); D = pop(v); S = pop(v); while (L) { M[D] = M[S]; L -= 1; S += 1; D += 1; } } V pre(V) { cur -= 1; if (cur < 0) cur = ILOS - 1; } V nxt(V) { cur += 1; if (cur > (ILOS - 1)) cur = 0; } V msgs(V) { printf("\n*** SWITCH TO %d ***\n", cur); } V msgx(V) { printf("\n*** SHUTDOWN REQUESTED ***\n"); tcsetattr(STDIN_FILENO,TCSANOW, &old_term); exit(1); } V msgr(V) { printf("\n*** RESTART %d ***\n", cur); } V ioa(ilo *v) { v->i[0] = (char)pop(v); write(1, &v->i, 1); } V iob(ilo *v) { read(0, &v->i, 1); push(v, v->i[0]); if (v->i[0] == 14) { T = 32; nxt(); msgs(); } if (v->i[0] == 16) { T = 32; pre(); msgs(); } if (v->i[0] == 3) { T = 32; msgr(); iof(v); cancel = 1; } if (v->i[0] == 1) { T = 32; msgx(); } if (v->i[0] == 8 || v->i[0] == 127) { v->i[0] = '\b'; write(1, &v->i, 1); v->i[0] = ' '; write(1, &v->i, 1); v->i[0] = '\b'; write(1, &v->i, 1); } else { write(1, &v->i, 1); } } V ioc(ilo *v) { read_block(v); } V iod(ilo *v) { write_block(v); } V ioe(ilo *v) { save_image(v); } V iof(ilo *v) { load_image(v); IP = -1; } V iog(ilo *v) { iof(v); } V ioh(ilo *v) { push(v, SP); push(v, RP); } V io(ilo *v) { switch (pop(v)) { case 0: ioa(v); break; case 1: iob(v); break; case 2: ioc(v); break; case 3: iod(v); break; case 4: ioe(v); break; case 5: iof(v); break; case 6: iog(v); break; case 7: ioh(v); break; default: break; } } V process(ilo *v, I o) { switch (o) { case 0: break; case 1: li(v); break; case 2: du(v); break; case 3: dr(v); break; case 4: sw(v); break; case 5: pu(v); break; case 6: po(v); break; case 7: ju(v); break; case 8: ca(v); break; case 9: cc(v); break; case 10: cj(v); break; case 11: re(v); break; case 12: eq(v); break; case 13: ne(v); break; case 14: lt(v); break; case 15: gt(v); break; case 16: fe(v); break; case 17: st(v); break; case 18: ad(v); break; case 19: su(v); break; case 20: mu(v); break; case 21: di(v); break; case 22: an(v); break; case 23: or(v); break; case 24: xo(v); break; case 25: sl(v); break; case 26: sr(v); break; case 27: cp(v); break; case 28: cy(v); break; case 29: io(v); break; default: break; } } V process_bundle(ilo *v, I opcode) { if (cancel) return; process(v, opcode & 0xFF); if (cancel) return; process(v, (opcode >> 8) & 0xFF); if (cancel) return; process(v, (opcode >> 16) & 0xFF); if (cancel) return; process(v, (opcode >> 24) & 0xFF); } V execute(V) { ilo *v = &systems[cur]; while (IP < 65536) { cancel = 0; process_bundle(v, M[IP]); IP += 1; v = &systems[cur]; } } V handle_sigint(I sig) { printf("\n*** SIGINT (%d) : RESTARTING %d ***\n", sig, cur); cancel = 1; iof(&systems[cur]); } I main(I argc, C **argv) { ilo *v; I i; cur = 0; for (i = 0; i < ILOS; i++) { v = &systems[i]; v->blocks = (argc > 1) ? argv[1] : "ilo.blocks"; v->rom = (argc > 2) ? argv[2] : "ilo.rom"; load_image(v); } if (signal(SIGINT, handle_sigint) == SIG_ERR) { perror("signal"); return 1; } tcgetattr(STDIN_FILENO, &old_term); new_term = old_term; new_term.c_lflag &=(~ICANON & ~ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &new_term); execute(); tcsetattr(STDIN_FILENO, TCSANOW, &old_term); return 0; }