/************************************************************************* * TinyFugue - programmable mud client * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2002, 2003, 2004, 2005, 2006-2007 Ken Keys * * TinyFugue (aka "tf") is protected under the terms of the GNU * General Public License. See the file "COPYING" for details. ************************************************************************/ /* $Id: parse.h,v 35004.51 2007/01/13 23:12:39 kkeys Exp $ */ #ifndef PARSE_H #define PARSE_H /* keywords: must be sorted and numbered sequentially */ typedef enum { BREAK = 0200, DO, DONE, ELSE, ELSEIF, ENDIF, EXIT, IF, LET, RESULT, RETURN, SET, SETENV, TEST, THEN, WHILE } keyword_id_t; #define OPNUM_MASK 0x007F /* opcode type */ #define OPT_MASK 0x7000 #define OPT_EXPR 0x0000 /* must be zero, for ascii operators */ #define OPT_SUB 0x1000 #define OPT_JUMP 0x2000 #define OPT_CTRL 0x3000 /* opcode flag */ #define OPF_MASK 0x0080 #define OPF_0 0x0000 #define OPF_APP 0x0080 /* append (SUB & PSUB) */ #define OPF_NEG 0x0080 /* negate result (CTRL); negate cond (JUMP) */ #define OPF_SIDE 0x0080 /* has side effect (EXPR) */ /* opcode arg type */ #define OPA_MASK 0x0700 #define OPA_INT 0x0000 /* must be zero, for ascii operators */ #define OPA_NONE 0x0100 #define OPA_STRP 0x0200 #define OPA_CHAR 0x0300 #define OPA_VALP 0x0400 #define OPA_CMDP 0x0500 #define OPLABEL_MASK (OPNUM_MASK | OPF_MASK) #define op_type(op) ((op) & OPT_MASK) #define op_type_is(op, type) (op_type(op) == OPT_##type) #define op_arg_type(op) ((op) & OPA_MASK) #define op_arg_type_is(op, type) (op_arg_type(op) == OPA_##type) #define op_is_push(op) (((op) & OPF_MASK) != OPF_APP) #define op_is_append(op) (((op) & OPF_MASK) == OPF_APP) #define op_has_sideeffect(op) (((op) & OPF_MASK) == OPF_SIDE) #define opnum(op) ((op) & OPNUM_MASK) #define opnum_eq(op1, op2) (opnum(op1) == opnum(op2)) typedef enum { #define defopcode(name, num, optype, argtype, flag) \ OP_##name = (num | OPT_##optype | OPA_##argtype | OPF_##flag), #include "opcodes.h" OP_ENDOFLIST = 0xffff } opcode_t; typedef union InstructionArg { int i; char c; conString *str; Value *val; struct BuiltinCmd *cmd; } InstructionArg; typedef struct Instruction { opcode_t op; union InstructionArg arg; const char *start, *end; /* start/end points in source code, for mecho */ int comefroms; /* number of insts that jump to this one */ } Instruction; struct Program { conString *src; /* source code */ int srcstart; /* offset of start in src */ const char *sip; /* pointer into src->data, for compiling */ Instruction *code; /* compiled code */ int len; /* length of compiled code */ int size; /* size of code array */ const char *mark; /* pointer into source code, for mecho */ int optimize; /* opimization level */ }; typedef struct Arg { int start, end; } Arg; extern void parse_error(Program *prog, const char *type, const char *expect); extern void parse_error_suggest(Program *prog, const char *type, const char *expect, const char *suggestion); extern int varsub(Program *prog, int sub_warn, int in_expr); extern int exprsub(Program *prog, int in_expr); extern int dollarsub(Program *prog, String **destp); extern conString *valstr(Value *val); extern const char *valstd(Value *val); extern long valint(const Value *val); extern int valtime(struct timeval *tv, const Value *val); extern int valbool(const Value *val); #if !NO_FLOAT extern double valfloat(const Value *val); #endif /* NO_FLOAT */ extern void *valptr(Value *val); extern int pushval(Value *val); extern void freeval_fl(Value *val, const char *file, int line); extern Value *expr_value(const char *expression); extern Value *expr_value_safe(Program *prog); extern void code_add(Program *prog, opcode_t op, ...); extern int reduce(opcode_t op, int n); extern const char *oplabel(opcode_t op); extern struct Value *newptr_fl(void *ptr, const char *file, int line); #define popval() \ ((Value*)stack[--stacktop]) /* get Nth operand from stack (counting backwards from top) */ #define opd(N) (stack[stacktop-(N)]) #define opdfloat(N) valfloat(opd(N)) /* float value of opd(N) */ #define opdint(N) valint(opd(N)) /* int value of opd(N) */ #define opdbool(N) valbool(opd(N)) /* boolean value of opd(N) */ #define opdstr(N) valstr(opd(N)) /* String value of opd(N) */ #define opdstd(N) valstd(opd(N)) /* String data of opd(N) */ #define opdtime(tv, N) valtime(tv, opd(N)) /* copy timeval of opd(N) */ #define freeval(val) freeval_fl((val), __FILE__, __LINE__) #define comefrom(prog, from, to) \ do { \ if (from >= 0) { \ (prog)->code[(from)].arg.i = (to); \ (prog)->code[(to)].comefroms++; \ } \ } while (0) #define ip (prog->sip) /* XXX */ extern Value *stack[]; /* expression stack */ extern int stacktop; /* first free position on stack */ extern Arg *tf_argv; /* shifted command argument vector */ extern int tf_argc; /* shifted command/function arg count */ extern int argtop; /* top of function argument stack */ extern const conString *argstring; /* command argument text */ extern keyword_id_t block; /* type of current expansion block */ extern int condition; /* checked by /if and /while */ extern int evalflag; /* flag: should we evaluate? */ #endif /* PARSE_H */