#include "rc.h" #include "parse.h" #include "exec.h" // ----------------------------------------------------------------------- // types struct Interpreter { int i, cap; Code *code; }; Code *compiled = nil; static struct Interpreter interpreter; #define emiti(x) ((void)(interpreter.i != interpreter.cap || grow()), interpreter.code[interpreter.i].i = (x), interpreter.i++) #define emitf(x) ((void)(interpreter.i != interpreter.cap || grow()), interpreter.code[interpreter.i].f = (x), interpreter.i++) #define emits(x) ((void)(interpreter.i != interpreter.cap || grow()), interpreter.code[interpreter.i].s = (x), interpreter.i++) static int grow(void) { interpreter.cap += 100; interpreter.code = erealloc(interpreter.code, sizeof(*interpreter.code)*interpreter.cap); memset(interpreter.code+interpreter.cap-100, 0, 100*sizeof(*interpreter.code)); return 0; } static void storepc(int a) { if(interpreter.i <= a || a < 0) fatal("bad address %d in interpreter", a); interpreter.code[a].i = interpreter.i; } static void walk(Tree *node) { Tree *n; int addr1, addr2; if(!node) return; switch(node->type){ default: print(shell.err, "bad type %d in interpreter walk\n", node->type); fatal("crashing\n"); break; case '$': emitf(Xmark); walk(node->child[0]); emitf(Xdollar); break; case Tcount: emitf(Xmark); walk(node->child[0]); emitf(Xcount); break; case Tjoin: emitf(Xmark); walk(node->child[0]); emitf(Xjoin); break; case ';': walk(node->child[0]); walk(node->child[1]); break; case '^': emitf(Xmark); walk(node->child[1]); emitf(Xmark); walk(node->child[0]); emitf(Xconcatenate); break; case Targs: walk(node->child[1]); walk(node->child[0]); break; case Tparen: case Tblock: walk(node->child[0]); break; case Tbasic: emitf(Xmark); walk(node->child[0]); emitf(Xbasic); break; case '&': emitf(Xasync); addr1 = emiti(0); walk(node->child[0]); emitf(Xexit); storepc(addr1); break; case Tsubshell: emitf(Xsubshell); addr1 = emiti(0); walk(node->child[0]); emitf(Xexit); storepc(addr1); break; case Tbang: walk(node->child[0]); emitf(Xbang); case Tword: emitf(Xword); emits(strdup(node->str)); break; case Twords: walk(node->child[1]); walk(node->child[0]); break; case Tpipe: emitf(Xpipe); emiti(node->redir.fd[0]); emiti(node->redir.fd[1]); addr1 = emiti(0); addr2 = emiti(0); walk(node->child[0]); emitf(Xexit); storepc(addr1); walk(node->child[1]); emitf(Xreturn); storepc(addr2); emitf(Xpipewait); break; case '=': for(n=node; node && node->type == '='; node = node->child[2]) ; if(node){ for(node=n; node->type=='='; node = node->child[2]){ emitf(Xmark); walk(node->child[1]); emitf(Xmark); walk(node->child[0]); emitf(Xlocal); } walk(node); for(node=n; node->type=='='; node = node->child[2]) emitf(Xunlocal); }else{ for(node=n; node; node=node->child[2]){ emitf(Xmark); walk(node->child[1]); emitf(Xmark); walk(node->child[0]); emitf(Xassign); } } node = n; break; } } // ----------------------------------------------------------------------- // main exports void freecode(Code *c) { if(--c[0].i!=0) return; efree(c); } Code * copycode(Code *c) { c[0].i++; return c; } int compile(Tree *node) { flush(shell.err); interpreter.i = 0; interpreter.code = emalloc(100*sizeof(*interpreter.code)); emiti(0); // reference count: no thread owns code yet walk(node); emitf(Xreturn); emitf(nil); compiled = interpreter.code; return 0; }