/* * LANGUAGE - Language support * * Author: * Emile van Bergen, emile@evbergen.xs4all.nl * * Permission to redistribute an original or modified version of this program * in source, intermediate or object code form is hereby granted exclusively * under the terms of the GNU General Public License, version 2. Please see the * file COPYING for details, or refer to http://www.gnu.org/copyleft/gpl.html. * * History: * 2001/05/06 - EvB - Created */ /* * INCLUDES & DEFINES */ #include /* For ssize_t */ #include /* For META, META_AV */ /* Stack machine result codes */ #define VM_CONTINUE 0 #define VM_HALTED 1 #define VM_ABORTED 2 #define VM_OVERFLOW 3 #define VM_UNDERFLOW 4 #define VM_NOMEM 5 #define VM_INVALIDOP 6 #define VM_INVALIDARG 7 #define VM_IFACETRAP 8 /* Stack machine opcodes */ /* Low nibble opcode type specifiers. Note that if any of these are different, * the opcode is also *called* differently, so don't misuse the type flags as * some form of immediate operand! * * (bits 0-1: stack requirements) * 0 = nothing needed * 1 = fixup one * 2 = fixup two, discard one * 3 = discard one * * (bit 2: if fixup two, default list for left (2nd) arg, reserved otherwise) * 0 = default for left term is request list * 1 = default for left term is reply list * * (bit 3: reserved) */ #define OP_FIXCNT(opcode) (((opcode) & 3) <= 2 ? ((opcode) & 3) : 0) #define OP_DSCCNT(opcode) (((opcode) >> 1) & 1) #define OP_USEREP(opcode, arg) (((opcode) >> 2) & ((arg) == ((opcode) & 3))) /* arg: l=2, r=1, so the above applies for opcode's highest arg. */ #define OP_HALT 0x00000 #define OP_ABORT 0xffff0 #define OP_ACCEPT 0xf0000 #define OP_REJECT 0xf0010 #define OP_ACCTRESP 0xf0020 #define OP_NOP 0x00010 #define OP_PUSHINT 0x00020 #define OP_PUSHSTR 0x00030 #define OP_PUSHAV 0x00040 /* ref to first/last atr from req/rep */ #define OP_POP 0x00053 /* discard */ #define OP_NEG 0x00061 #define OP_NOT 0x00071 #define OP_MUL 0x00082 #define OP_DIV 0x00092 #define OP_CIDRMASK 0x000a2 /* mask address using CIDR netmask */ #define OP_MOD 0x000b2 #define OP_ADD 0x000c2 #define OP_SUB 0x000d2 #define OP_SHL 0x000e2 #define OP_SHR 0x000f2 #define OP_XOR 0x00102 #define OP_AND 0x00112 #define OP_OR 0x00122 #define OP_GE 0x00132 #define OP_LE 0x00142 #define OP_GT 0x00152 #define OP_LT 0x00162 #define OP_EQ 0x00172 #define OP_NE 0x00182 #define OP_BF 0x00192 /* before first */ #define OP_AF 0x001a2 /* after first */ #define OP_BL 0x001b2 /* before last */ #define OP_AL 0x001c2 /* after last */ #define OP_FO 0x001d2 /* first of */ #define OP_LO 0x001e2 /* last of */ #define OP_MD5 0x001f1 #define OP_HEX 0x00201 #define OP_UPPER 0x00211 #define OP_LOWER 0x00221 #define OP_RANDOM 0x00231 #define OP_DICTENC 0x00240 /* encode rep using given dict. space */ #define OP_XORSTR 0x00262 #define OP_CONCAT 0x00272 #define OP_GESTR 0x00282 #define OP_LESTR 0x00292 #define OP_GTSTR 0x002a2 #define OP_LTSTR 0x002b2 #define OP_EQSTR 0x002c2 #define OP_NESTR 0x002d2 #define OP_OCTSTR2ORD 0x00301 #define OP_DECSTR2ORD 0x00311 #define OP_HEXSTR2ORD 0x00321 #define OP_RAWSTR2ORD 0x00331 /* binary value in network order */ #define OP_IPASTR2ORD 0x00341 /* n.n.n.n */ #define OP_DATSTR2ORD 0x00351 /* YYYYMMDDhhmmss */ #define OP_INTSTR2ORD 0x00361 /* leading 0 = oct, leading 0x = hex */ #define OP_ORD2OCTSTR 0x00381 #define OP_ORD2DECSTR 0x00391 #define OP_ORD2HEXSTR 0x003a1 #define OP_ORD2RAWSTR 0x003b1 /* binary value in network order */ #define OP_ORD2IPASTR 0x003c1 /* n.n.n.n */ #define OP_ORD2DATSTR 0x003d1 /* YYYYMMDDhhmmss */ #define OP_ORD2DFMSTR 0x003e2 /* formatted date using strftime() */ #define OP_STR2MAC 0x003f2 /* canonicalized MAC address */ #define OP_PAPDECR 0x00402 /* decrypt/encrypt with PAP method */ #define OP_PAPENCR 0x00412 /* using Secret . Authenticator */ #define OP_UNIXCRYPT 0x00422 /* unix crypt(3) using given salt */ #define OP_HMACMD5 0x00432 /* HMAC using MD5 with given key */ #define OP_DICTDEC 0x00442 /* decode using given dict. space */ #define OP_EXISTS 0x00481 /* returns 1 if resolved */ #define OP_BOOLNOT 0x00491 /* boolean not, returns 1 when false */ #define OP_JMPZ 0x004a1 /* jmp if zero (false) */ #define OP_JMPNZ 0x004b1 /* jmp if nonzero (true) */ #define OP_ADDAV 0x00506 /* add referenced AV based on term */ #define OP_REPLACEAV 0x00516 /* replace referenced AV with term */ #define OP_POKEAV 0x00526 /* poke at referenced AV's memory */ #define OP_DELAV 0x00535 /* delete referenced AV (see code) */ #define OP_DELALLAV 0x00540 /* delete all inst. of referenced AV */ #define OP_MOVEALLAV 0x00550 /* copy all inst. of referenced AV */ #define OP_JOINSTR 0x00560 /* join all inst. of referenced AV into stack item */ #define OP_CALLIFACE 0x00600 /* call external interface */ /* Request and Reply list indexes for head and tail arrays */ #define VM_REQ 0 #define VM_REP 1 /* * TYPES */ typedef struct insn { int op; /* Opcode */ union { META_ORD ord; struct { short disp; /* Displacement for jmpXX and pushstr */ short str_len; /* String length in bytes for pushstr */ } d; struct { META_ITEM *item; int flags; /* Flags for META_AV object on stack */ } i; struct iface *iface; } imm; /* Immediate operand */ } INSN; typedef struct vm { INSN *ip, *codeend; META_AV *stk, *head[2], *tail[2]; /* 0 = req, 1 = rep */ int sp, stackend; /* sp is index in stack array; stack grows up */ } VM; /* * PROTOTYPES */ /* langcompile.c */ #ifdef COMP_MEM ssize_t lang_compile(META *m, struct iface *ifaces, char *source, INSN *buf, ssize_t bufsize); #else struct text; ssize_t lang_compile(META *m, struct iface *ifaces, struct text *source, INSN *buf, ssize_t bufsize); #endif /* langdisasm.c */ void lang_disassemble(META *m, INSN *i, ssize_t bufsize); /* langvm.c */ VM *vm_new(INSN *code, ssize_t len, int stackend, META_AV *reqhead, META_AV *reqtail, META_AV *rephead, META_AV *reptail); void vm_chgcode(VM *vm, INSN *code, ssize_t len); void vm_popall(VM *vm); void vm_del(VM *vm); int vm_run(META *m, VM *vm); struct iface *vm_getiface(VM *vm); void vm_dumptrace(VM *vm, META *m, INSN *codestart); void vm_dumpstack(VM *vm, META *m);