From ce05175372a9ddca1a225db0765ace1127a39293 Mon Sep 17 00:00:00 2001 From: Nicholas Date: Fri, 12 Nov 2021 09:22:01 -0800 Subject: chore: simplified organizational structure --- src/cmd/rc/code.c | 277 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100644 src/cmd/rc/code.c (limited to 'src/cmd/rc/code.c') diff --git a/src/cmd/rc/code.c b/src/cmd/rc/code.c new file mode 100644 index 0000000..786f284 --- /dev/null +++ b/src/cmd/rc/code.c @@ -0,0 +1,277 @@ +#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 Tindex: + emitf(Xmark); + walk(node->child[1]); + emitf(Xmark); + walk(node->child[0]); + emitf(Xindex); + 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 Tandand: + walk(node->child[0]); + emitf(Xtrue); + addr1 = emiti(0); + walk(node->child[1]); + storepc(addr1); + break; + + case Toror: + walk(node->child[0]); + emitf(Xfalse); + addr1 = emiti(0); + walk(node->child[1]); + storepc(addr1); + 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 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 '=': + 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; + /* control structures */ + case Twhile: + addr1 = interpreter.i; // head of loop + walk(node->child[0]); + if(addr1 == interpreter.i) + fatal("TODO"); + emitf(Xtrue); + addr2 = emiti(0); // goto end of loop + + walk(node->child[1]); + emitf(Xgoto); + emiti(addr1); // goto top of loop + storepc(addr2); + break; + + case Tfor: + emitf(Xmark); + if(node->child[1]){ // for( x in X ) + walk(node->child[1]); + // emitf(Xglob) + }else{ // for(X) + fatal("TODO"); + } + emitf(Xmark); // null initial value for Xlocal + emitf(Xmark); + walk(node->child[0]); + emitf(Xlocal); + + addr1 = emitf(Xfor); + addr2 = emiti(0); + + walk(node->child[2]); + emitf(Xgoto); + emiti(addr1); + storepc(addr2); + emitf(Xunlocal); + break; + + /* forks */ + 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 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; + } +} + +// ----------------------------------------------------------------------- +// 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; +} -- cgit v1.2.1