/* Autoconf patching by David Hedbor, neotron@lysator.liu.se */
#include "tintin.h"
#include <ctype.h>
int stacks[100][3];
extern struct listnode *common_myvars;
#ifdef HAVE_UNISTD_H
#include <stdlib.h>
#include <unistd.h>
#endif
extern char *get_arg_in_braces();
extern struct listnode *searchnode_list();
void math_command(line, ses)
char *line;
struct session *ses;
{
struct listnode *my_vars, *ln;
char left[BUFFER_SIZE], right[BUFFER_SIZE];
char temp[BUFFER_SIZE], result[BUFFER_SIZE];
int i;
my_vars = (ses) ? ses->myvars : common_myvars;
line = get_arg_in_braces(line, left, 0);
line = get_arg_in_braces(line, right, 1);
substitute_vars(right, result);
substitute_myvars(result, right, ses);
i = eval_expression(right);
sprintf(temp, "%d", i);
if ((ln = searchnode_list(my_vars, left)) != NULL)
deletenode_list(my_vars, ln);
insertnode_list(my_vars, left, temp, "0", ALPHA);
}
void if_command(line, ses)
char *line;
struct session *ses;
{
char left[BUFFER_SIZE], right[BUFFER_SIZE], temp[BUFFER_SIZE];
char elsebuf[BUFFER_SIZE];
/* int i; */
line = get_arg_in_braces(line, left, 0);
line = get_arg_in_braces(line, right, 1);
/* MOVED by if-else addition
substitute_vars(right,temp);
substitute_myvars(temp,right,ses);
*/
substitute_vars(left, temp);
substitute_myvars(temp, left, ses);
if (eval_expression(left)) {
/* MOVED to here */
substitute_vars(right, temp);
substitute_myvars(temp, right, ses);
parse_input(right, ses);
}
else {
/* ADDITION for if-else addition */
line = (char *) get_arg_stop_spaces(line, elsebuf);
if (*elsebuf && strcmp(elsebuf, "else") == 0) {
line = get_arg_in_braces(line, elsebuf, 1);
substitute_vars(elsebuf, temp);
substitute_myvars(temp, elsebuf, ses);
parse_input(elsebuf, ses);
}
}
}
int eval_expression(arg)
char *arg;
{
int i, begin, end, flag, prev;
char temp[BUFFER_SIZE];
i = conv_to_ints(arg);
if (i == 1) { /* changed for if strings */
while (1) {
i = 0;
flag = 1;
begin = -1;
end = -1;
prev = -1;
while (stacks[i][0] && flag) {
if (stacks[i][1] == 0) {
begin = i;
}
else if (stacks[i][1] == 1) {
end = i;
flag = 0;
}
prev = i;
i = stacks[i][0];
}
if ((flag && (begin != -1)) || (!flag && (begin == -1))) {
tintin_puts2("#Unmatched parentheses error.", (struct session *) NULL);
return 0;
}
if (flag) {
if (prev == -1)
return (stacks[0][2]);
begin = -1;
end = i;
}
i = do_one_inside(begin, end);
if (!i) {
sprintf(temp, "#Invalid expression to evaluate in {%s}", arg);
tintin_puts2(temp, (struct session *) NULL);
return 0;
}
}
}
else if (i == 2)
return 1; /* changed for #if strings */
else
return 0;
}
int conv_to_ints(arg)
char *arg;
{
int i, flag;
char *ptr, *tptr;
char left[256], right[256];
i = 0;
ptr = arg;
while (*ptr) {
if (*ptr == ' ')
;
/* START ADDITION for #if-strings */
else if (*ptr == '[') {
ptr++;
tptr = left;
while ((*ptr) && (*ptr != ']') && (*ptr != '=')) {
*tptr = (*ptr);
ptr++;
tptr++;
}
*tptr = '\0';
if (!*ptr)
return -1;
if (*ptr == ']')
return -2;
tptr = right;
ptr++;
while ((*ptr) && (*ptr != ']')) {
*tptr = (*ptr);
ptr++;
tptr++;
}
*tptr = '\0';
if (!*ptr)
return -1;
if (strcmp(right, left) == 0)
return 2;
return 3;
}
/* END ADDITION for #if-strings */
else if (*ptr == '(') {
stacks[i][1] = 0;
}
else if (*ptr == ')') {
stacks[i][1] = 1;
}
else if (*ptr == '!') {
if (*(ptr + 1) == '=') {
stacks[i][1] = 12;
ptr++;
}
else
stacks[i][1] = 2;
}
else if (*ptr == '*') {
stacks[i][1] = 3;
}
else if (*ptr == '/') {
stacks[i][1] = 4;
}
else if (*ptr == '+') {
stacks[i][1] = 5;
}
else if (*ptr == '-') {
flag = -1;
if (i > 0)
flag = stacks[i - 1][1];
if (flag == 15)
stacks[i][1] = 6;
else {
tptr = ptr;
ptr++;
while (isdigit(*ptr))
ptr++;
sscanf(tptr, "%d", &stacks[i][2]);
stacks[i][1] = 15;
ptr--;
}
}
else if (*ptr == '>') {
if (*(ptr + 1) == '=') {
stacks[i][1] = 8;
ptr++;
}
else
stacks[i][1] = 7;
}
else if (*ptr == '<') {
if (*(ptr + 1) == '=') {
ptr++;
stacks[i][1] = 10;
}
else
stacks[i][1] = 9;
}
else if (*ptr == '=') {
stacks[i][1] = 11;
if (*(ptr + 1) == '=')
ptr++;
}
else if (*ptr == '&') {
stacks[i][1] = 13;
if (*(ptr + 1) == '&')
ptr++;
}
else if (*ptr == '|') {
stacks[i][1] = 14;
if (*(ptr + 1) == '|')
ptr++;
}
else if (isdigit(*ptr)) {
stacks[i][1] = 15;
tptr = ptr;
while (isdigit(*ptr))
ptr++;
sscanf(tptr, "%d", &stacks[i][2]);
ptr--;
}
else if (*ptr == 'T') {
stacks[i][1] = 15;
stacks[i][2] = 1;
}
else if (*ptr == 'F') {
stacks[i][1] = 15;
stacks[i][2] = 0;
}
else {
tintin_puts2("#Error. Invalid expression in #if or #math", (struct session *) NULL);
return 0;
}
if (*ptr != ' ') {
stacks[i][0] = i + 1;
i++;
}
ptr++;
}
if (i > 0)
stacks[i][0] = 0;
return 1;
}
int do_one_inside(begin, end)
int begin;
int end;
{
/* int prev, ptr, highest, loc, ploc, next, nval, flag; */
int prev, ptr, highest, loc, ploc, next;
while (1) {
ptr = 0;
if (begin > -1)
ptr = stacks[begin][0];
highest = 16;
loc = -1;
ploc = -1;
prev = -1;
while (ptr < end) {
if (stacks[ptr][1] < highest) {
highest = stacks[ptr][1];
loc = ptr;
ploc = prev;
}
prev = ptr;
ptr = stacks[ptr][0];
}
if (highest == 15) {
if (begin > -1) {
stacks[begin][1] = 15;
stacks[begin][2] = stacks[loc][2];
stacks[begin][0] = stacks[end][0];
return 1;
}
else {
stacks[0][0] = stacks[end][0];
stacks[0][1] = 15;
stacks[0][2] = stacks[loc][2];
return 1;
}
}
else if (highest == 2) {
next = stacks[loc][0];
if (stacks[next][1] != 15 || stacks[next][0] == 0) {
return 0;
}
stacks[loc][0] = stacks[next][0];
stacks[loc][1] = 15;
stacks[loc][2] = !stacks[next][2];
}
else {
next = stacks[loc][0];
if (ploc == -1 || stacks[next][0] == 0 || stacks[next][1] != 15)
return 0;
if (stacks[ploc][1] != 15)
return 0;
switch (highest) {
case 3: /* highest priority is * */
stacks[ploc][0] = stacks[next][0];
stacks[ploc][2] *= stacks[next][2];
break;
case 4: /* highest priority is / */
stacks[ploc][0] = stacks[next][0];
stacks[ploc][2] /= stacks[next][2];
break;
case 5: /* highest priority is + */
stacks[ploc][0] = stacks[next][0];
stacks[ploc][2] += stacks[next][2];
break;
case 6: /* highest priority is - */
stacks[ploc][0] = stacks[next][0];
stacks[ploc][2] -= stacks[next][2];
break;
case 7: /* highest priority is > */
stacks[ploc][0] = stacks[next][0];
stacks[ploc][2] = (stacks[ploc][2] > stacks[next][2]);
break;
case 8: /* highest priority is >= */
stacks[ploc][0] = stacks[next][0];
stacks[ploc][2] = (stacks[ploc][2] >= stacks[next][2]);
break;
case 9: /* highest priority is < */
stacks[ploc][0] = stacks[next][0];
stacks[ploc][2] = (stacks[ploc][2] < stacks[next][2]);
break;
case 10: /* highest priority is <= */
stacks[ploc][0] = stacks[next][0];
stacks[ploc][2] = (stacks[ploc][2] <= stacks[next][2]);
break;
case 11: /* highest priority is == */
stacks[ploc][0] = stacks[next][0];
stacks[ploc][2] = (stacks[ploc][2] == stacks[next][2]);
break;
case 12: /* highest priority is != */
stacks[ploc][0] = stacks[next][0];
stacks[ploc][2] = (stacks[ploc][2] != stacks[next][2]);
break;
case 13: /* highest priority is && */
stacks[ploc][0] = stacks[next][0];
stacks[ploc][2] = (stacks[ploc][2] && stacks[next][2]);
break;
case 14: /* highest priority is || */
stacks[ploc][0] = stacks[next][0];
stacks[ploc][2] = (stacks[ploc][2] || stacks[next][2]);
break;
default:
tintin_puts2("#Programming error *slap Bill*", (struct session *) NULL);
return 0;
}
}
}
}