/* Copyright (c) 2002
* Marko Boomstra (m.boomstra@chello.nl). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <conf.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <ncurses.h>
#include <panel.h>
#include "mudix.h"
typedef enum
{
OP_NONE,
OP_EQUAL, /* == */
OP_INEQUAL, /* != */
OP_GREATER, /* > */
OP_GREATER_EQUAL, /* >= */
OP_LESSER, /* < */
OP_LESSER_EQUAL /* <= */
} OPERATOR_TYPE;
void show_vars(void)
{
static int current;
VAR *var;
char *str;
int line, i, width, height, centre, wsize;
width = LEN_COL-4;
height = 20;
wsize = height-2;
centre = ((width-2)/2)-1;
wresize(wMsg, height, width);
werase(wMsg);
move_panel(pMsg, 1, 2);
if (panel_hidden(pMsg) == PANEL_HIDDEN)
current = 0;
for (line=1, i=0, var = settings->vars_list; var; var = var->next) {
if (!var->name || !var->value)
continue;
i+=2;
if (i < (current*wsize)+2)
continue;
mvwprintw(wMsg, line++, 1, "Name : %s", var->name);
mvwprintw(wMsg, line++, 1, "Value: %s", var->value);
if (line >= wsize && var->next) {
current++;
break;
}
if (!var->next) /* last one */
current = 0;
}
draw_border(wMsg);
str = "Variables";
mvwprintw(wMsg, 0, centre-strlen(str)/2, str);
show_panel(pMsg);
return;
}
VAR *new_var(bool last)
{
VAR *var;
if (!(var = (VAR *)malloc(sizeof(VAR))))
return NULL;
if (last && settings->vars_list) {
VAR *iVar;
for (iVar = settings->vars_list; iVar; iVar = iVar->next) {
if (!iVar->next)
break;
}
iVar->next = var;
var->next = NULL;
}
else {
var->next = settings->vars_list;
settings->vars_list = var;
}
var->name = NULL;
var->value = NULL;
return var;
}
void free_var(VAR *var)
{
VAR *iVar;
if (!var)
return;
for (iVar = settings->vars_list; iVar; iVar = iVar->next) {
if (iVar->next == var) {
iVar->next = var->next;
break;
}
}
if (var == settings->vars_list)
settings->vars_list = var->next;
if (var->name)
free(var->name);
if (var->value)
free(var->value);
free(var);
return;
}
VAR *var_lookup(char *var)
{
VAR *iVar;
for (iVar = settings->vars_list; iVar; iVar = iVar->next) {
if (!iVar->name || !iVar->value)
continue;
if (!strcmp(var, iVar->name))
break;
}
return iVar;
}
static bool is_numeric(char *str, double *value)
{
char *begin = str;
/* parse till end of string */
while (*str != '\0')
{
/* character in the string is not a digit! no numeric string */
if (!isdigit(*str))
{
return FALSE;
}
str++;
}
*value = strtod(begin, NULL);
return TRUE;
}
static OPERATOR_TYPE get_operator(char *expr)
{
OPERATOR_TYPE retval = OP_NONE;
switch (*expr)
{
case '!': /* != */
if (*(expr+1) == '=')
{
retval = OP_INEQUAL;
}
break;
case '=': /* == */
if (*(expr+1) == '=')
{
retval = OP_EQUAL;
}
break;
case '>': /* >=, > */
if (*(expr+1) == '=')
{
retval = OP_GREATER_EQUAL;
}
else
{
retval = OP_GREATER;
}
break;
case '<': /* <=, < */
if (*(expr+1) == '=')
{
retval = OP_LESSER_EQUAL;
}
else
{
retval = OP_LESSER;
}
break;
default:
break;
}
return retval;
}
static bool check_expression(char *expr)
{
static char arg1[MAX_STRING];
static char arg2[MAX_STRING];
VAR *var;
char *pExpr = expr;
char *pArg1, *pArg2;
OPERATOR_TYPE opr;
bool retval, fNumeric = FALSE;
double lval, rval;
/* get the first argument */
pArg1 = arg1;
while (*pExpr)
{
if (*pExpr == '!' ||
*pExpr == '=' ||
*pExpr == '>' ||
*pExpr == '<')
{
break;
}
*pArg1++ = *pExpr++;
}
*pArg1 = '\0';
/* retrieve the operator type */
opr = get_operator(pExpr);
if (opr == OP_NONE)
{
return FALSE;
}
else if (opr == OP_LESSER || opr == OP_GREATER)
{
pExpr++;
}
else
{
pExpr += 2;
}
/* copy the 2nd argument into arg2 */
strcpy(arg2, pExpr);
/* look up if this references a variable */
var = var_lookup(arg1);
if (var)
{
/* set the argument pointer to point to the variable value :) */
pArg1 = var->value;
}
else
{
/* set to the original argument */
pArg1 = arg1;
}
/* look up if this references a variable */
var = var_lookup(arg2);
if (var)
{
/* set the argument pointer to point to the variable value :) */
pArg2 = var->value;
}
else
{
/* set to the original argument */
pArg2 = arg2;
}
/* check if arguments are numeric */
if (is_numeric(pArg1, &lval) && is_numeric(pArg2, &rval))
{
fNumeric = TRUE;
}
/* now check the operand type and the values */
switch (opr)
{
case OP_GREATER:
retval = fNumeric? (lval > rval):
(strcmp(pArg1, pArg2) > 0);
break;
case OP_GREATER_EQUAL:
retval = fNumeric? (lval >= rval):
(strcmp(pArg1, pArg2) >= 0);
break;
case OP_LESSER:
retval = fNumeric? (lval < rval):
(strcmp(pArg1, pArg2) < 0);
break;
case OP_LESSER_EQUAL:
retval = fNumeric? (lval <= rval):
(strcmp(pArg1, pArg2) <= 0);
break;
case OP_INEQUAL:
retval = fNumeric? (lval != rval):
(strcmp(pArg1, pArg2) != 0);
break;
case OP_EQUAL:
retval = fNumeric? (lval == rval):
(strcmp(pArg1, pArg2) == 0);
break;
default:
retval = FALSE;
break;
}
return retval;
}
bool process_if(char *buffer)
{
char str[MAX_STRING];
/* grab the expression */
buffer = get_arg(buffer, str);
/* and check it */
if (check_expression(str))
{
/* grab first argument after expression and process it */
get_arg(buffer, str);
process_input(str, NULL, TRUE);
return TRUE;
}
else
{
/* skip to 2nd argument */
buffer = get_arg(buffer, str);
get_arg(buffer, str);
if (str[0])
{
/* process the 'else' command */
process_input(str, NULL, TRUE);
}
return FALSE;
}
}
syntax highlighted by Code2HTML, v. 0.9.1