diff options
Diffstat (limited to 'eval.c')
-rw-r--r-- | eval.c | 1456 |
1 files changed, 0 insertions, 1456 deletions
@@ -1,1456 +0,0 @@ -/* - * eval.c -- functions for builtin calculator - * - * (created: Massimiliano Ghilardi (Cosmos), Jan 15th, 1995) - * - * Copyright (C) 1998 by Massimiliano Ghilardi - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -#include <ctype.h> -#include <errno.h> -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <strings.h> -#include <time.h> -#include <unistd.h> - -#include <sys/time.h> -#include <sys/types.h> - -#include "defines.h" -#include "main.h" -#include "utils.h" -#include "cmd2.h" -#include "list.h" -#include "map.h" -#include "tty.h" -#include "edit.h" -#include "eval.h" - -#ifdef USE_RANDOM -# define get_random random -# define init_random srandom -#else -# define get_random lrand48 -# define init_random srand48 -#endif - -typedef struct { - int type; - long num; /* used for numeric types or as index for all variables */ - ptr txt; /* used for text types */ -} object; - -#define LEFT 1 -#define RIGHT 2 - -#define BINARY 0 -#define PRE_UNARY LEFT -#define POST_UNARY RIGHT - -#define LOWEST_UNARY_CODE 49 -/* - * it would be 47, but operators 47 '(' and 48 ')' - * are treated separately - */ - -enum op_codes { - null=0, comma, eq, or_or_eq, xor_xor_eq, and_and_eq, or_eq, xor_eq, and_eq, - lshift_eq, rshift_eq, plus_eq, minus_eq, times_eq, div_eq, ampersand_eq, - or_or, xor_xor, and_and, or, xor, and, - less, less_eq, greater, greater_eq, eq_eq, not_eq, - lshift, rshift, plus, minus, times, division, ampersand, - - colon_less, colon_greater, less_colon, greater_colon, - point_less, point_greater, less_point, greater_point, - colon, point, question, another_null, - - left_paren, right_paren, not, tilde, - pre_plus_plus, post_plus_plus, pre_minus_minus, post_minus_minus, - star, print, _random_, _attr_, colon_question, point_question, - pre_plus, pre_minus, a_circle, dollar, pre_null, post_null -}; - -typedef enum op_codes operator; - -typedef struct { - char priority, assoc, syntax, *name; - operator code; -} operator_list; - -typedef struct { - object obj[MAX_STACK]; - int curr_obj; - operator op[MAX_STACK]; - int curr_op; -} stack; - -char *error_msg[] = { - "unknown error", - "math stack overflow", - "math stack underflow", - "stack overflow", - "stack underflow", - "expression syntax", - "operator expected", - "value expected", - "division by zero", - "operand or index out of range", - "missing right parenthesis", - "missing left parenthesis", - "internal error!", - "operator not supported", - "operation not completed (internal error)", - "out of memory", - "text/string longer than limit, discarded", - "infinite loop", - "numeric value expected", - "string expected", - "missing label", - "missing separator \";\"", - "#history recursion too deep", - "user break", - "too many defined variables", - "undefined variable", - "invalid digit in numeric value", - "bad attribute syntax", - "invalid variable name", -}; - -operator_list op_list[] = { - { 0, 0, 0, "", null }, - - { 1, LEFT, BINARY, ",", comma }, - - { 2, RIGHT, BINARY, "=", eq }, - { 2, RIGHT, BINARY, "||=", or_or_eq }, - { 2, RIGHT, BINARY, "^^=", xor_xor_eq }, - { 2, RIGHT, BINARY, "&&=", and_and_eq }, - { 2, RIGHT, BINARY, "|=", or_eq }, - { 2, RIGHT, BINARY, "^=", xor_eq }, - { 2, RIGHT, BINARY, "&=", and_eq }, - { 2, RIGHT, BINARY, "<<=", lshift_eq }, - { 2, RIGHT, BINARY, ">>=", rshift_eq }, - { 2, RIGHT, BINARY, "+=", plus_eq }, - { 2, RIGHT, BINARY, "-=", minus_eq }, - { 2, RIGHT, BINARY, "*=", times_eq }, - { 2, RIGHT, BINARY, "/=", div_eq }, - { 2, RIGHT, BINARY, "%=", ampersand_eq }, - - { 3, LEFT, BINARY, "||", or_or }, - - { 4, LEFT, BINARY, "^^", xor_xor }, - - { 5, LEFT, BINARY, "&&", and_and }, - - { 6, LEFT, BINARY, "|", or }, - - { 7, LEFT, BINARY, "^", xor }, - - { 8, LEFT, BINARY, "&", and }, - - { 9, LEFT, BINARY, "<", less }, - { 9, LEFT, BINARY, "<=", less_eq }, - { 9, LEFT, BINARY, ">", greater }, - { 9, LEFT, BINARY, ">=", greater_eq }, - { 9, LEFT, BINARY, "==", eq_eq }, - { 9, LEFT, BINARY, "!=", not_eq }, - - {10, LEFT, BINARY, "<<", lshift }, - {10, LEFT, BINARY, ">>", rshift }, - - {11, LEFT, BINARY, "+", plus }, - {11, LEFT, BINARY, "-", minus }, - - {12, LEFT, BINARY, "*", times }, - {12, LEFT, BINARY, "/", division }, - {12, LEFT, BINARY, "%", ampersand }, - - {14, LEFT, BINARY, ":<", colon_less }, - {14, LEFT, BINARY, ":>", colon_greater }, - {14, LEFT, BINARY, "<:", less_colon }, - {14, LEFT, BINARY, ">:", greater_colon }, - {14, LEFT, BINARY, ".<", point_less }, - {14, LEFT, BINARY, ".>", point_greater }, - {14, LEFT, BINARY, "<.", less_point }, - {14, LEFT, BINARY, ">.", greater_point }, - {14, LEFT, BINARY, ":", colon }, - {14, LEFT, BINARY, ".", point }, - {14, LEFT, BINARY, "?", question }, - - { 0, 0, 0, "", another_null }, - - { 0, RIGHT, PRE_UNARY, "(", left_paren }, - { 0, RIGHT, POST_UNARY, ")", right_paren }, - - {13, RIGHT, PRE_UNARY, "!", not }, - {13, RIGHT, PRE_UNARY, "~", tilde }, - {13, RIGHT, PRE_UNARY, "++", pre_plus_plus }, - {13, RIGHT, POST_UNARY, "++", post_plus_plus }, - {13, RIGHT, PRE_UNARY, "--", pre_minus_minus }, - {13, RIGHT, POST_UNARY, "--", post_minus_minus }, - {13, RIGHT, PRE_UNARY, "*", star }, - {13, RIGHT, PRE_UNARY, "%", print }, - {13, RIGHT, PRE_UNARY, "rand", _random_ }, - {13, RIGHT, PRE_UNARY, "attr", _attr_ }, - - {14, LEFT, PRE_UNARY, ":?", colon_question }, - {14, LEFT, PRE_UNARY, ".?", point_question }, - - {15, RIGHT, PRE_UNARY, "+", pre_plus }, - {15, RIGHT, PRE_UNARY, "-", pre_minus }, - {15, RIGHT, PRE_UNARY, "@", a_circle }, - {15, RIGHT, PRE_UNARY, "$", dollar }, - - { 0, 0, PRE_UNARY, "", pre_null }, - { 0, 0, POST_UNARY, "", post_null } -}; - -static stack stk; -static char *line; -static int depth; -int error; - -void print_error(int err_num) -{ - clear_input_line(1); - if (error == NO_MEM_ERROR) { - tty_printf("#system call error: %s (%d", "malloc", ENOMEM); - tty_printf(": %s)\n", strerror(ENOMEM)); - } else - tty_printf("#error: %s.\n", error_msg[err_num]); -} - -static int push_op(operator *op) -{ - if (stk.curr_op<MAX_STACK) { - stk.op[++stk.curr_op]=*op; - return 1; - } - else { - error=STACK_OV_ERROR; - return 0; - } -} - -static int pop_op(operator *op) -{ - if (stk.curr_op>=0) { - *op=stk.op[stk.curr_op--]; - return 1; - } - else { - error=STACK_UND_ERROR; - return 0; - } -} - -static int push_obj(object *obj) -{ - object *tmp; - - int curr=stk.curr_obj; - - if (curr<MAX_STACK) { - tmp = stk.obj + (stk.curr_obj = ++curr); - memmove(tmp, obj, sizeof(object)); - return 1; - } - else { - error=STACK_OV_ERROR; - return 0; - } -} - -static int pop_obj(object *obj) -{ - object *tmp; - - int curr=stk.curr_obj; - - if (curr>=0) { - tmp = stk.obj + curr; - stk.curr_obj--; - memmove(obj, tmp, sizeof(object)); - return 1; - } - else { - error=STACK_UND_ERROR; - return 0; - } -} - -static int check_operator(char side, operator *op, int mindepth) -{ - int i, max, len; - operator match; - char *name, c, d; - - if (!(c=*line) || c == CMDSEP) { - *op = side==BINARY ? null : side==LEFT ? pre_null : post_null; - return 1; - } - else if ((c=='$' || c=='@') && (d=line[1]) && (isalpha(d) || d=='_')) - return 0; /* Danger! found named variable */ - - else if (side==LEFT && c=='(') { - line++; - depth++; - *op=left_paren; - return 1; - } - else if (side==RIGHT && c==')') { - if (--depth >= mindepth) { - line++; - *op=right_paren; - } - else /* exit without touching the parenthesis */ - *op=post_null; - return 1; - } - else if (side==RIGHT && (c=='}' || c==']') && depth == mindepth) { - /* allow also exiting with a '}' or a ']' */ - --depth; - *op=post_null; - return 1; - } - - for (max=match=0, i=(side==BINARY ? 1 : LOWEST_UNARY_CODE); - *(name = op_list[i].name); i++) - if ((len=strlen(name)) > max && - (side==BINARY || side==op_list[i].syntax) && - !strncmp(line, name, (size_t)len)) { - match=op_list[i].code; - max=len; - } - - if (match) { - *op=match; - line+=max; - return 1; - } - else { - *op= side==BINARY ? null : side==PRE_UNARY ? pre_null : post_null; - if (side==BINARY) - error=NO_OPERATOR_ERROR; - } - return 0; -} - -static int check_object(object *obj) -{ - long i=0, base = 10; - char c, *end, digit; - - if (c=*line, c == '#' || isdigit(c)) { - while (c == '#' || isalnum(c)) { - digit = !!isdigit(c); - if (c == '#') { - base = i; - i = 0; - if (!base) - base = 16; - } else { - i *= base; - if (digit) - i += (c - '0'); - else { - if (c >= 'a' && c <= 'z') - c = (c - 'a') + 'A'; - if (c - 'A' + 10 >= base) { - error=OUT_BASE_ERROR; - return 0; - } - i += (c - 'A' + 10); - } - } - c=*++line; - } - obj->type=TYPE_NUM; - obj->num=i; - i=1; - } - else if(c=='\"') { - end=first_valid(++line, '\"'); - if (*end) { - obj->type=TYPE_TXT; - obj->txt=ptrmcpy(obj->txt, line, end-line); - if (!REAL_ERROR) { - ptrunescape(obj->txt); - i=1; - line=end+1; - } - } - } - else if ((c=='$' || c=='@') && (c=line[1]) && (isalpha(c) || c=='_')) { - varnode *named_var; /* Found named variable */ - - if (*(line++) == '@') { - i = 0; - obj->type = TYPE_NUM_VAR; - } - else { - i = 1; - obj->type = TYPE_TXT_VAR; - } - end = line + 1; - while ((c=*end) && (isalpha(c) || c=='_' || isdigit(c))) - end++; - c = *end; *end = '\0'; - if (!(named_var = *lookup_varnode(line, i))) { - named_var = add_varnode(line, i); - if (REAL_ERROR) - return 0; - if (opt_info) { - PRINTF("#new variable: %s\n", line - 1); - } - } - *end = c; - line = end; - obj->num = named_var->index; - i = 1; - } - else if (!strncmp(line, "timer", 5)) { - obj->type = TYPE_NUM; - update_now(); - obj->num = diff_vtime(&now, &ref_time); - line += 5; - i = 1; - } - else if (!strncmp(line, "map", 3)) { - char buf[MAX_MAPLEN + 1]; - map_sprintf(buf); - obj->type = TYPE_TXT; - obj->txt = ptrmcpy(obj->txt, buf, strlen(buf)); - if (!REAL_ERROR) { - line += 3; - i = 1; - } - } - else if (!strncmp(line, "noattr", 6)) { - obj->type = TYPE_TXT; - obj->txt = ptrmcpy(obj->txt, tty_modestandoff, strlen(tty_modestandoff)); - obj->txt = ptrmcat(obj->txt, tty_modenorm, strlen(tty_modenorm)); - if (!REAL_ERROR) { - line += 6; - i = 1; - } - } - else - error=NO_VALUE_ERROR; - - return (int)i; -} - -static void check_delete(object *obj) -{ - if (obj->type==TYPE_TXT && obj->txt) { - ptrdel(obj->txt); - obj->txt = NULL; - } -} - -static int exe_op(operator *op) -{ - object o1, o2, *p=NULL; - long *l, rnd, delta; - ptr src = NULL, dst = NULL, start = NULL; - int srclen; - char *ssrc, *tmp; - int ret=0, i=0, j=0, danger=0; - - o1.txt = o2.txt = NULL; - - switch ((int)*op) { - case (int)comma: - if (pop_obj(&o2) && pop_obj(&o1)); - else if (REAL_ERROR) break; - check_delete(&o1); - p=&o2; - ret=1; - break; - case (int)eq: - if (pop_obj(&o2) && pop_obj(&o1)); - else if (REAL_ERROR) break; - - if (o2.type==TYPE_NUM_VAR) { - o2.num = *VAR[o2.num].num; - o2.type = TYPE_NUM; - } - - if (o1.type==TYPE_NUM_VAR && o2.type==TYPE_NUM) { - *VAR[o1.num].num = o2.num; - p=&o2; - ret=1; - } - else if (o1.type==TYPE_TXT_VAR && - (o2.type==TYPE_TXT || o2.type==TYPE_TXT_VAR)) { - - if (o2.type==TYPE_TXT_VAR) { - o2.txt = ptrdup(*VAR[o2.num].str); - if (REAL_ERROR) break; - o2.type=TYPE_TXT; - } - - *VAR[o1.num].str = ptrcpy(*VAR[o1.num].str, o2.txt); - if (REAL_ERROR) break; - p=&o2; - ret=1; - } - else - error=SYNTAX_ERROR; - break; - case (int)or_or_eq: - case (int)xor_xor_eq: - case (int)and_and_eq: - case (int)or_eq: - case (int)xor_eq: - case (int)and_eq: - case (int)lshift_eq: - case (int)rshift_eq: - case (int)plus_eq: - case (int)minus_eq: - case (int)times_eq: - case (int)div_eq: - case (int)ampersand_eq: - if (pop_obj(&o2) && pop_obj(&o1)); - else if (REAL_ERROR) break; - - if (o2.type==TYPE_NUM_VAR) { - o2.num = *VAR[o2.num].num; - o2.type = TYPE_NUM; - } - - if (o1.type==TYPE_NUM_VAR && o2.type==TYPE_NUM) { - l=VAR[o1.num].num; - - switch ((int)*op) { - case (int)or_or_eq: if ( o2.num) *l = 1; else *l = !!*l; break; - case (int)xor_xor_eq:if ( o2.num) *l = !*l; else *l = !!*l; break; - case (int)and_and_eq:if (!o2.num) *l = 0; else *l = !!*l; break; - case (int)or_eq: *l |= o2.num; break; - case (int)xor_eq: *l ^= o2.num; break; - case (int)and_eq: *l &= o2.num; break; - case (int)lshift_eq: *l <<= o2.num; break; - case (int)rshift_eq: *l >>= o2.num; break; - case (int)plus_eq: *l += o2.num; break; - case (int)minus_eq: *l -= o2.num; break; - case (int)times_eq: *l *= o2.num; break; - case (int)div_eq: *l /= o2.num; break; - case (int)ampersand_eq: - if ((*l %= o2.num) < 0) *l += o2.num; break; - } - o2.num=*l; - p=&o2; - ret=1; - } - else if (*op==plus_eq && o1.type==TYPE_TXT_VAR && - (o2.type==TYPE_TXT || o2.type==TYPE_TXT_VAR)) { - - if (o2.type==TYPE_TXT) - src=o2.txt; - else - src=*VAR[o2.num].str; - - *VAR[o1.num].str = ptrcat(*VAR[o1.num].str, src); - check_delete(&o2); - - dst = ptrdup(*VAR[o1.num].str); - if (REAL_ERROR) break; - - o1.type=TYPE_TXT; - o1.txt=dst; - p=&o1; - ret=1; - } - else if (*op==times_eq && o1.type==TYPE_TXT_VAR && - (o2.type==TYPE_NUM || o2.type==TYPE_NUM_VAR)) { - - if (o2.type==TYPE_NUM_VAR) { - o2.num = *VAR[o2.num].num; - o2.type = TYPE_NUM; - } - - if (o2.num < 0) - error = OUT_RANGE_ERROR; - else if (o2.num == 0) - ptrzero(*VAR[o1.num].str); - else if (o2.num == 1) - ; - else if (*VAR[o1.num].str && (delta = ptrlen(*VAR[o1.num].str))) { - long n; - *VAR[o1.num].str = ptrsetlen(*VAR[o1.num].str, delta*o2.num); - tmp = ptrdata(*VAR[o1.num].str); - for (n = 1; !error && n<o2.num; n++) - memcpy(tmp+n*delta, tmp, delta); - } - - check_delete(&o2); - dst = ptrdup(*VAR[o1.num].str); - if (REAL_ERROR) break; - - o1.type=TYPE_TXT; - o1.txt=dst; - p=&o1; - ret=1; - } - else - error=SYNTAX_ERROR; - break; - case (int)or_or: - case (int)xor_xor: - case (int)and_and: - case (int)or: - case (int)xor: - case (int)and: - case (int)less: - case (int)less_eq: - case (int)greater: - case (int)greater_eq: - case (int)eq_eq: - case (int)not_eq: - case (int)lshift: - case (int)rshift: - case (int)minus: - case (int)plus: - case (int)times: - case (int)division: - case (int)ampersand: - if (pop_obj(&o2) && pop_obj(&o1)); - else if (REAL_ERROR) break; - - if (o1.type==TYPE_NUM_VAR) { - o1.num = *VAR[o1.num].num; - o1.type = TYPE_NUM; - } - if (o2.type==TYPE_NUM_VAR) { - o2.num = *VAR[o2.num].num; - o2.type = TYPE_NUM; - } - - if (o1.type==TYPE_NUM && o2.type==TYPE_NUM) { - if (!o2.num && - (*op==division || *op==ampersand)) { - error=DIV_BY_ZERO_ERROR; - break; - } - - switch ((int)*op) { - case (int)less: o1.num = o1.num < o2.num ? 1 : 0; break; - case (int)less_eq: o1.num = o1.num <= o2.num ? 1 : 0; break; - case (int)greater: o1.num = o1.num > o2.num ? 1 : 0; break; - case (int)greater_eq:o1.num = o1.num >= o2.num ? 1 : 0; break; - case (int)eq_eq: o1.num = o1.num == o2.num ? 1 : 0; break; - case (int)not_eq: o1.num = o1.num != o2.num ? 1 : 0; break; - case (int)or_or: o1.num = o1.num || o2.num; break; - case (int)xor_xor:if (o2.num) o1.num = !o1.num; break; - case (int)and_and: o1.num = o1.num && o2.num; break; - case (int)or: o1.num |= o2.num; break; - case (int)xor: o1.num ^= o2.num; break; - case (int)and: o1.num &= o2.num; break; - case (int)lshift: o1.num <<= o2.num; break; - case (int)rshift: o1.num >>= o2.num; break; - case (int)minus: o1.num -= o2.num; break; - case (int)plus: o1.num += o2.num; break; - case (int)times: o1.num *= o2.num; break; - case (int)division:o1.num /= o2.num; break; - case (int)ampersand: - if ((o1.num %= o2.num) < 0) o1.num += o2.num; break; - } - - p=&o1; - ret=1; - } - else if ((o1.type==TYPE_TXT || o1.type==TYPE_TXT_VAR) && - (o2.type==TYPE_TXT || o2.type==TYPE_TXT_VAR)) { - - if (o1.type==TYPE_TXT_VAR) { - o1.txt = ptrdup(*VAR[o1.num].str); - o1.type = TYPE_TXT; /* not a var anymore */ - if (REAL_ERROR) break; - } - dst = o1.txt; - if (o2.type==TYPE_TXT) - src=o2.txt; - else - src=*VAR[o2.num].str; - - if (*op == plus) { - dst = ptrcat(dst, src); - o1.type = TYPE_TXT; - } else { - o1.num = ptrcmp(dst, src); - switch ((int)*op) { - case (int)minus: break; - case (int)less: o1.num = o1.num < 0; break; - case (int)less_eq: o1.num = o1.num <= 0; break; - case (int)greater: o1.num = o1.num > 0; break; - case (int)greater_eq: o1.num = o1.num >= 0; break; - case (int)eq_eq: o1.num = o1.num == 0; break; - case (int)not_eq: o1.num = o1.num != 0; break; - default: - error=SYNTAX_ERROR; - p=NULL; ret=0; break; - } - check_delete(&o1); - /* moved here because it interfered with allowing the dst ptr from - * being freed, casing a very tiny memory leak */ - o1.type = TYPE_NUM; - } - check_delete(&o2); - if (!REAL_ERROR) { - o1.txt = dst; - p=&o1; - ret=1; - } - } - else if (*op==times - && (o1.type==TYPE_TXT_VAR || o1.type==TYPE_TXT) - && o2.type==TYPE_NUM) { - - if (o2.num > 0 && o1.type==TYPE_TXT_VAR) { - o1.txt = ptrdup(*VAR[o1.num].str); - if (REAL_ERROR) break; - } - dst = o1.txt; - - if (o2.num < 0) - error = OUT_RANGE_ERROR; - else if (o2.num == 0) - ptrzero(dst); - else if (o2.num == 1) - ; - else if (dst && (delta = ptrlen(dst))) { - long n; - dst = ptrsetlen(dst, delta*o2.num); - tmp = ptrdata(dst); - for (n = 1; !error && n<o2.num; n++) - memcpy(tmp+n*delta, tmp, delta); - } - check_delete(&o2); - if (REAL_ERROR) break; - - o1.type=TYPE_TXT; - o1.txt=dst; - p=&o1; - ret=1; - } - else - error=SYNTAX_ERROR; - break; - case (int)colon_less: - case (int)colon_greater: - case (int)less_colon: - case (int)greater_colon: - case (int)colon: - case (int)point_less: - case (int)point_greater: - case (int)less_point: - case (int)greater_point: - case (int)point: - if (pop_obj(&o2) && pop_obj(&o1)); - else if (REAL_ERROR) break; - - if (o2.type==TYPE_NUM_VAR) { - o2.num = *VAR[o2.num].num; - o2.type = TYPE_NUM; - } - - if ((o1.type!=TYPE_TXT_VAR && o1.type!=TYPE_TXT) || o2.type!=TYPE_NUM) { - error=SYNTAX_ERROR; - break; - } - - if (o2.num<=0) { - error=OUT_RANGE_ERROR; - break; - } - - if (o1.type==TYPE_TXT_VAR) { - o1.type=TYPE_TXT; - o1.txt=dst=NULL; - src=start=*VAR[o1.num].str; - } - else { - /* Potentially dangerous: src and dst are overlapping */ - src=dst=start=o1.txt; - danger=1; - } - - if (!src) { - /* src == empty string. just return it */ - check_delete(&o2); - o1.txt = src; - if (!REAL_ERROR) - p=&o1; ret=1; - break; - } - - srclen = ptrlen(src); - ssrc = ptrdata(src); - - switch ((int)*op) { - case (int)colon_less: - while (o2.num && srclen) { - /* skip span of multiple word delimeters */ - while (srclen && memchr(DELIM, *ssrc, DELIM_LEN)) - srclen--, ssrc++, j++; - /* skip whole words */ - if (srclen && (tmp = memchrs(ssrc, srclen, DELIM, DELIM_LEN))) - i=tmp-ssrc, o2.num--, ssrc+=i, j+=i, srclen-=i; - else break; - } - - if (o2.num) { /* end of valid string before the n-th word */ - if (danger) - ; - else - dst = ptrcpy(dst, start); - } else { - if (danger) - ptrtrunc(dst, j); - else - dst = ptrmcpy(dst, ptrdata(start), j); - } - break; - case (int)colon: - case (int)colon_greater: - o2.num--; - /* skip span of multiple word delimeters */ - while (srclen && memchr(DELIM, *ssrc, DELIM_LEN)) - srclen--, ssrc++; - while (o2.num && srclen) { - /* skip whole words */ - if (srclen && (tmp = memchrs(ssrc, srclen, DELIM, DELIM_LEN))) { - i=tmp-ssrc, o2.num--, ssrc+=i, srclen-=i; - /* skip span of multiple word delimeters */ - while (srclen && memchr(DELIM, *ssrc, DELIM_LEN)) - srclen--, ssrc++; - } else break; - } - - if (o2.num) /* end of valid string before the n-th word */ - ptrzero(dst); - else { - if (*op==colon && - (tmp = memchrs(ssrc, srclen, DELIM, DELIM_LEN))) { - dst = ptrmcpy(dst, ssrc, tmp-ssrc); - } - else - dst = ptrmcpy(dst, ssrc, srclen); - } - break; - case (int)less_colon: - o2.num--; - while (o2.num && srclen) { - /* skip span of multiple word delimeters */ - while (srclen && memchr(DELIM, ssrc[srclen], DELIM_LEN)) - srclen--; - /* skip whole words */ - if (srclen && (tmp=memrchrs(ssrc, srclen, DELIM, DELIM_LEN))) - o2.num--, srclen=tmp-ssrc; - else break; - } - - if (o2.num) /* end of valid string before the n-th word */ - ptrzero(dst); - else - dst = ptrmcpy(dst, ssrc, srclen); - break; - case (int)greater_colon: - while (o2.num && srclen) { - /* skip span of multiple word delimeters */ - while (srclen && memchr(DELIM, ssrc[srclen], DELIM_LEN)) - srclen--; - /* skip whole words */ - if (srclen && (tmp=memrchrs(ssrc, srclen, DELIM, DELIM_LEN))) - o2.num--, srclen=tmp-ssrc; - else break; - } - - if (o2.num) /* end of valid string before the n-th word */ - dst = ptrcpy(dst, start); - else - dst = ptrmcpy(dst, ssrc+srclen+1, - ptrlen(start) - (ssrc+srclen+1 - ptrdata(start))); - break; - case (int)point: - j = o2.num <= srclen ? o2.num-1 : srclen; - dst = ptrmcpy(dst, ssrc+j, 1); - break; - case (int)point_less: - j = o2.num < srclen ? o2.num : srclen; - if (danger) - ptrtrunc(dst, j); - else - dst = ptrmcpy(dst, ssrc, j); - break; - case (int)less_point: - j = srclen-o2.num+1; - if (j < 0) - j = 0; - if (danger) - ptrtrunc(dst, j); - else - dst = ptrmcpy(dst, ssrc, j); - break; - case (int)point_greater: - j = o2.num-1 < srclen ? o2.num-1 : srclen; - dst = ptrmcpy(dst, ssrc+j, srclen-j); - break; - case (int)greater_point: - j = srclen-o2.num; - if (j < 0) - j = 0; - dst = ptrmcpy(dst, ssrc+j, srclen-j); - break; - } - check_delete(&o2); - o1.txt = dst; - if (!REAL_ERROR) - p=&o1; ret=1; - break; - case (int)colon_question: - case (int)point_question: - if (pop_obj(&o1)); - else if (REAL_ERROR) break; - - if (o1.type==TYPE_TXT) - src=o1.txt; - else if (o1.type==TYPE_TXT_VAR) - src=*VAR[o1.num].str; - else { - error=SYNTAX_ERROR; - break; - } - if (!src) { - /* empty string. return 0 */ - check_delete(&o1); - o1.type=TYPE_NUM; - o1.num =0; - p=&o1; - ret=1; - break; - } - - ssrc = ptrdata(src); - srclen = ptrlen(src); - - if (*op==colon_question) { - o1.num = 0; - /* skip span of multiple word delimeters */ - while (srclen && memchr(DELIM, *ssrc, DELIM_LEN)) - ssrc++, srclen--; - while (srclen) { - /* skip whole words */ - if (srclen && (tmp=memchrs(ssrc, srclen, DELIM, DELIM_LEN))) { - i=tmp-ssrc, o1.num++, ssrc+=i, srclen-=i; - /* skip span of multiple word delimeters */ - while (srclen && memchr(DELIM, *ssrc, DELIM_LEN)) - srclen--, ssrc++; - } else { - srclen=0; - o1.num++; - } - } - } - else - o1.num=srclen; - - check_delete(&o1); - o1.type=TYPE_NUM; - p=&o1; - ret=1; - break; - case (int)question: - if (pop_obj(&o2) && pop_obj(&o1)); - else if (REAL_ERROR) break; - - if (o1.type==TYPE_TXT) - src = o1.txt; - else if (o1.type==TYPE_TXT_VAR) - src = *VAR[o1.num].str; - else - error = SYNTAX_ERROR; - - if (o2.type==TYPE_TXT) - dst = o2.txt; - else if (o2.type==TYPE_TXT_VAR) - dst = *VAR[o2.num].str; - else - error = SYNTAX_ERROR; - - if (!error) { - if ((ssrc = ptrfind(src, dst))) - i = (int)(ssrc - ptrdata(src)) + 1; - else - i = 0; - o1.type = TYPE_NUM; - o1.num = i; - p=&o1; ret=1; - } - check_delete(&o1); - check_delete(&o2); - break; - case (int)null: - case (int)another_null: - if (pop_obj(&o2) && pop_obj(&o1)); - else if (REAL_ERROR) break; - - check_delete(&o1); - check_delete(&o2); - - o1.type=0, o1.num=0, o1.txt=NULL; - - p=&o1; - ret=1; - break; - case (int)left_paren: - error=MISSING_PAREN_ERROR; - break; - case (int)right_paren: - if (pop_op(op)); - else if (REAL_ERROR) break; - - if (*op!=left_paren) - error=MISMATCH_PAREN_ERROR; - else - ret=1; - - break; - case (int)_random_: -#ifdef NO_RANDOM - error = NOT_SUPPORTED_ERROR; - break; -#endif - case (int)pre_plus: - case (int)pre_minus: - case (int)not: - case (int)tilde: - - if (pop_obj(&o1)); - else if (REAL_ERROR) break; - - if (o1.type==TYPE_NUM_VAR) { - o1.num = *VAR[o1.num].num; - o1.type = TYPE_NUM; - } - if (o1.type==TYPE_NUM) { - if (*op==pre_minus) - o1.num=-o1.num; - else if (*op==not) - o1.num=!o1.num; - else if (*op==tilde) - o1.num=~o1.num; -#ifndef NO_RANDOM - else if (*op==_random_) { - if (o1.num <= 0) { - error=OUT_RANGE_ERROR; - break; - } else { - delta = LONG_MAX - LONG_MAX % o1.num; - while (rnd = get_random(), rnd > delta); - /* skip numbers that would alterate distribution */ - o1.num = rnd / (delta / o1.num); - } - } -#endif - p=&o1; - ret=1; - } - else - error=SYNTAX_ERROR; - break; - case (int)_attr_: - if (pop_obj(&o1)); - else if (REAL_ERROR) break; - - if (o1.type==TYPE_TXT_VAR) { - o1.txt = ptrdup(*VAR[o1.num].str); - if (REAL_ERROR) break; - o1.type = TYPE_TXT; - } - - if (o1.type==TYPE_TXT) { - char dummy[CAPLEN]; /* just because attr_string must write somewhere */ - - if (o1.txt) - i = parse_attributes(ptrdata(o1.txt)); - else - i = NOATTRCODE; - if (i == -1) - error=BAD_ATTR_ERROR; - else { - o1.txt = ptrsetlen(o1.txt, CAPLEN); - if (REAL_ERROR) break; - attr_string(i, ptrdata(o1.txt), dummy); - ptrtrunc(o1.txt, strlen(ptrdata(o1.txt))); - p=&o1; - ret = 1; - } - } else - error=NO_STRING_ERROR; - break; - - case (int)star: - case (int)print: - if (pop_obj(&o1)); - else if (REAL_ERROR) break; - - if (o1.type==TYPE_NUM_VAR) - o1.num = *VAR[o1.num].num; - else if (o1.type==TYPE_TXT_VAR) - o1.txt = *VAR[o1.num].str; - - if (o1.type==TYPE_NUM || o1.type==TYPE_NUM_VAR) { - o1.txt = NULL; - if (*op==print) { - char buf[LONGLEN]; - sprintf(buf, "%ld", o1.num); - o1.txt = ptrmcpy(o1.txt, buf, strlen(buf)); - } else { - char buf = (char)o1.num; - o1.txt = ptrmcpy(o1.txt, &buf, 1); - } - if (REAL_ERROR) break; - o1.type = TYPE_TXT; - p=&o1; ret=1; - } - else if (o1.type==TYPE_TXT || o1.type==TYPE_TXT_VAR) { - if (*op==print) { - if (o1.txt && ptrlen(o1.txt)) - o1.num = atol(ptrdata(o1.txt)); - else - o1.num = 0; - } else { - if (o1.txt && ptrlen(o1.txt)) - o1.num = (long)(byte)*ptrdata(o1.txt); - else - o1.num = 0; - } - check_delete(&o1); - o1.type = TYPE_NUM; - p=&o1; ret=1; - } - else - error=SYNTAX_ERROR; - break; - case (int)pre_plus_plus: - case (int)post_plus_plus: - case (int)pre_minus_minus: - case (int)post_minus_minus: - if (pop_obj(&o1)); - else if (REAL_ERROR) break; - - if (o1.type==TYPE_NUM_VAR) { - l=VAR[o1.num].num; - o1.type=TYPE_NUM; - - if (*op==pre_plus_plus) - o1.num=++*l; - else if (*op==post_plus_plus) - o1.num=(*l)++; - else if (*op==pre_minus_minus) - o1.num=--*l; - else - o1.num=(*l)--; - - p=&o1; - ret=1; - } - else - error=SYNTAX_ERROR; - break; - case (int)a_circle: - case (int)dollar: - if (pop_obj(&o1)); - else if (REAL_ERROR) break; - - if (*op == dollar) - delta = 1; - else - delta = 0; - - if (o1.type==TYPE_NUM_VAR) { - o1.type=TYPE_NUM; - o1.num=*VAR[o1.num].num; - } - - if (o1.type==TYPE_NUM) { - if (o1.num<-NUMVAR || o1.num>=NUMPARAM) { - error=OUT_RANGE_ERROR; - break; - } - o1.type= delta ? TYPE_TXT_VAR : TYPE_NUM_VAR; - p=&o1; - ret=1; - } else { - varnode *named_var; - char c; - - if (o1.type==TYPE_TXT_VAR) - o1.txt = *VAR[o1.num].str; - else if (o1.type!=TYPE_TXT) { - error=SYNTAX_ERROR; - break; - } - - if (o1.txt && (tmp=ptrdata(o1.txt)) && - ((c=*tmp) == '_' || isalpha(c))) { - tmp++; - while ((c=*tmp) == '_' || isalnum(c)) - tmp++; - } - if (!o1.txt || *tmp) { - error=INVALID_NAME_ERROR; - break; - } - - if (!(named_var = *lookup_varnode(ptrdata(o1.txt), delta))) { - named_var = add_varnode(ptrdata(o1.txt), delta); - if (REAL_ERROR) - break; - if (opt_info) { - PRINTF("#new variable: %c%s\n", delta - ? '$' : '@', ptrdata(o1.txt)); - } - } - o1.type= delta ? TYPE_TXT_VAR : TYPE_NUM_VAR; - p=&o1; - ret=1; - } - break; - case (int)pre_null: - case (int)post_null: - ret=1; - break; - default: - break; - } - - if (REAL_ERROR) { - check_delete(&o2); - check_delete(&o1); - } - - if (!REAL_ERROR) { - if (!ret) - error=NOT_DONE_ERROR; - else if (p) { - if (push_obj(p)) - ; - else - check_delete(p); - } - } - - if (REAL_ERROR) - return 0; - - return ret; -} - -static int whichfirst(operator *op1, operator *op2) -{ - int p1, p2; - - p1=op_list[*op1].priority; - p2=op_list[*op2].priority; - if (p1!=p2) - return p1>p2 ? -1 : 1; - - p1 = op_list[*op1].assoc == LEFT; - return p1 ? -1 : 1; -} - -static int compare_and_unload(operator *op) -{ - int first=0; - operator new; - - if (REAL_ERROR || stk.curr_op<0) - return 1; - - while (stk.curr_op>=0 && pop_op(&new) && !REAL_ERROR && - (first = whichfirst(&new, op)) == -1 && - (first = 0, exe_op(&new)) - ); - - if (!REAL_ERROR) { - if (!first) - return 1; - else - return push_op(&new); - } else - return 0; -} - -static int _eval(int mindepth) -{ - operator op; - object obj; - char endreached = 0; - - for (;;) { - memzero(&obj, sizeof(obj)); - - while (*line==' ') line++; - if (!*line || *line == CMDSEP) - endreached = 1; - - while (check_operator(LEFT, &op, mindepth) && push_op(&op) && - !endreached) { - - if (error) return 0; - while (*line==' ') line++; - if (!*line || *line == CMDSEP) - endreached = 1; - } - - if (!endreached && check_object(&obj) && push_obj(&obj)); - else if (error) return 0; - - while (*line==' ') line++; - if (!*line || *line == CMDSEP) - endreached = 1; - - while (check_operator(RIGHT, &op, mindepth) && compare_and_unload(&op) && - exe_op(&op) && depth>=mindepth && !endreached) { - - if (error) return 0; - while (*line==' ') - line++; - if (!*line || *line == CMDSEP) - endreached = 1; - } - if (error) return 0; - - if (endreached || depth < mindepth) - break; - - if (check_operator(BINARY, &op, mindepth) && - compare_and_unload(&op) && push_op(&op)); - else if (error) return 0; - } - return 1; -} - -int eval_any(long *lres, ptr *pres, char **what) -{ - int printmode; - long val; - ptr txt; - object res; - - if (pres) - printmode = PRINT_AS_PTR; - else if (lres) - printmode = PRINT_AS_LONG; - else - printmode = PRINT_NOTHING; - - error=0; - stk.curr_obj=stk.curr_op=-1; - line = *what; - - depth = 0; - (void)_eval(0); - - if (!error) - (void)pop_obj(&res); - if (error) { - if (opt_debug) { - PRINTF("#result not available\n"); - } - } else if (printmode!=PRINT_NOTHING || opt_debug) { - if (res.type==TYPE_NUM || res.type==TYPE_NUM_VAR) { - - val = res.type==TYPE_NUM ? res.num : *VAR[res.num].num; - - if (printmode==PRINT_AS_PTR) { - *pres = ptrsetlen(*pres, LONGLEN); - if (!MEM_ERROR) { - sprintf(ptrdata(*pres), "%ld", val); - (*pres)->len = strlen(ptrdata(*pres)); - } - } else if (printmode==PRINT_AS_LONG) - *lres=val; - - if (opt_debug) { - if (error) { - PRINTF("#result not available\n"); - } else { - PRINTF("#result: %ld\n", val); - } - } - } else { - txt = res.type==TYPE_TXT ? res.txt : *VAR[res.num].str; - if (printmode==PRINT_AS_PTR) { - if (txt && *ptrdata(txt)) { - if (res.type == TYPE_TXT) - /* shortcut! */ - *pres = txt; - else - *pres = ptrcpy(*pres, txt); - } else - ptrzero(*pres); - } - if (opt_debug) { - if (error) { - PRINTF("#result not available\n"); - } else if (txt && *ptrdata(txt)) { - PRINTF("#result: %s\n", ptrdata(txt)); - } else { - PRINTF("#result empty\n"); - } - } - } - } - *what=line; - - if (!error) { - if (printmode==PRINT_AS_PTR && res.type == TYPE_TXT - && res.txt && ptrdata(res.txt)) - /* shortcut! */ - ; - else - check_delete(&res); - } else { - while (stk.curr_obj>=0) { - pop_obj(&res); - check_delete(&res); - } - res.type = 0; - } - - if (res.type==TYPE_TXT_VAR) - res.type = TYPE_TXT; - else if (res.type==TYPE_NUM_VAR) - res.type = TYPE_NUM; - - return res.type; -} - -int evalp(ptr *res, char **what) -{ - return eval_any((long *)0, res, what); -} - -int evall(long *res, char **what) -{ - return eval_any(res, (ptr *)0, what); -} - -int evaln(char **what) -{ - return eval_any((long *)0, (ptr *)0, what); -} - |