/* eval.c */
/* Expression parsing module created by Lawrence Foard */
#include "copyright.h"
#include <ctype.h>
#include "db.h"
#include "config.h"
#include "externs.h"
#include "interface.h"
#include "match.h"
#include "strings.h"
/* functions for the string expressions */
dbref match_thing(dbref player, const char *name)
{
struct match_data md;
init_match(player, name, NOTYPE, &md);
match_everything(&md);
return(noisy_match_result(&md));
}
void fun_rand(char *buff, const char *args[10])
{
int mod = atoi(args[0]);
if (mod < 1)
mod = 1;
sprintf(buff,"%d",(random() & 65535) % mod);
}
void fun_time(char *buff, const char *args[10])
{
long tt;
time(&tt);
strcpy(buff, (char *) ctime(&tt));
buff[strlen(buff)-1] = 0;
}
void fun_get(char *buff, const char *args[10], dbref player)
{
dbref thing;
char x[1024];
char y[1024];
if(!index(args[0], '/')) {
strcpy(buff, "NO MATCH");
return;
}
strcpy(x, args[0]);
*index(x, '/') = '\0';
strcpy(y, 1 + index(args[0], '/'));
if((thing = match_thing(player, x)) == NOTHING) {
sprintf(buff, "NO MATCH");
return;
}
if (!controls(player, thing))
{
strcpy(buff,"PERMISSION DENIED");
return;
}
if(!get_property_class(thing, y)) {
strcpy(buff,"NO MATCH");
return;
}
strcpy(buff, get_property_class(thing,y));
}
void fun_mid(char *buff, const char *args[10])
{
int l = atoi(args[1]);
int len = atoi(args[2]);
if ((l < 0) || (len < 0) || ((len + l) > 1000))
{
strcpy(buff,"OUT OF RANGE");
return;
}
if (l < strlen(args[0]))
strcpy(buff, args[0] + l);
else
*buff = 0;
buff[len] = 0;
}
void fun_add(char *buff, const char *args[10])
{
sprintf(buff, "%d", atoi(args[0]) + atoi(args[1]));
}
void fun_sub(char *buff, const char *args[10])
{
sprintf(buff, "%d", atoi(args[0]) - atoi(args[1]));
}
void fun_mul(char *buff, const char *args[10])
{
sprintf(buff, "%d", atoi(args[0]) * atoi(args[1]));
}
void fun_div(char *buff, const char *args[10])
{
int bot = atoi(args[1]);
if (bot == 0)
bot = 1;
sprintf(buff, "%d", atoi(args[0]) / bot);
}
void fun_mod(char *buff, const char *args[10])
{
int bot = atoi(args[1]);
if (bot == 0)
bot = 1;
sprintf(buff, "%d", atoi(args[0]) % bot);
}
/* read first word from a string */
void fun_first(char *buff, char *args[10])
{
char *s = args[0];
char *b;
/* get rid of leading space */
while(*s && (*s == ' ')) s++;
b = s;
while(*s && (*s != ' ')) s++;
*s++ = 0;
strcpy(buff, b);
}
void fun_rest(char *buff, const char *args[10])
{
char *s = args[0];
/* skip leading space */
while(*s && (*s == ' ')) s++;
/* skip firsts word */
while(*s && (*s != ' ')) s++;
/* skip leading space */
while(*s && (*s == ' ')) s++;
strcpy(buff, s);
}
void fun_strlen(char *buff, const char *args[10])
{
sprintf(buff, "%d", strlen(args[0]));
}
/* handle 0-9,va-vz,n,# */
void fun_v(char *buff, const char *args[10], dbref privs, dbref doer)
{
int c = args[0][0];
switch(c)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (!awptr[c - '0'])
{
*buff = 0;
return;
}
strcpy(buff, awptr[c - '0']);
break;
case 'v':
case 'V':
{
int a;
a = toupper(args[0][1]);
if ((a < 'A') || (a > 'Z'))
{
*buff = 0;
return;
}
{
char x[5];
*x = 'v';
*(x + 2) = '\0';
*(x + 1) = a;
if(get_attr(privs, x))
strcpy(buff, get_attr(privs, x));
else
*buff = '\0';
}
}
break;
case 'n':
case 'N':
strcpy(buff, DBFETCH(doer)->name);
break;
case '#':
sprintf(buff, "#%d", doer);
break;
/* info about location and stuff */
/* objects # */
case '!':
sprintf(buff, "#%d", privs);
break;
default:
*buff = 0;
}
}
void fun_s(char *buff, char *args[10], dbref privs, dbref doer)
{
char buff1[BUFFER_LEN];
strcpy(buff1, pronoun_substitute(doer, args[0], privs));
strcpy(buff, buff1 + strlen(NAME(doer)) + 1);
}
void fun_num(char *buff, const char *args[10], dbref privs)
{
sprintf(buff, "#%d", match_thing(privs, args[0]));
}
void fun_con(char *buff, const char *args[10], dbref privs, dbref doer)
{
dbref it = match_thing(privs, args[0]);
if ((it != NOTHING) && (controls(privs, it) ||
(DBFETCH(privs)->location == it) || (it == doer))) {
sprintf(buff, "#%d", DBFETCH(it)->contents);
} else {
strcpy(buff, "#-1");
}
return;
}
/* return next exit that is ok to see */
dbref next_exit(dbref player, dbref this)
{
while((this != NOTHING) && (FLAGS(this) & DARK) && !controls(player, this))
this = DBFETCH(this)->next;
return(this);
}
void fun_exit(char *buff, const char *args[10], dbref privs, dbref doer)
{
dbref it = match_thing(privs, args[0]);
if ((it != NOTHING) && (controls(privs, it)
|| (DBFETCH(privs)->location == it) || (it == doer)))
{
sprintf(buff, "#%d", next_exit(privs, DBFETCH(it)->exits));
} else {
strcpy(buff, "#-1");
}
return;
}
void fun_next(char *buff, const char *args[10], dbref privs, dbref doer)
{
dbref it = match_thing(privs, args[0]);
if (it != NOTHING)
{
if (Typeof(it) != TYPE_EXIT)
{
if (controls(privs, DBFETCH(it)->location) ||
(DBFETCH(it)->location == doer) ||
(DBFETCH(it)->location == DBFETCH(privs)->location)) {
sprintf(buff, "#%d", DBFETCH(it)->next);
return;
}
}
else
{
sprintf(buff, "#%d", next_exit(privs, DBFETCH(it)->next));
return;
}
}
strcpy(buff, "#-1");
return;
}
void fun_loc(char *buff, const char *args[10], dbref privs, dbref doer)
{
dbref it = match_thing(privs, args[0]);
if ((it != NOTHING) &&
(controls(privs, it) || controls(privs, DBFETCH(it)->location) ||
(it == doer)))
{
sprintf(buff,"#%d",DBFETCH(it)->location);
} else {
strcpy(buff,"#-1");
}
return;
}
void fun_owner(char *buff, const char *args[10], dbref privs)
{
dbref it = match_thing(privs, args[0]);
if (it != NOTHING)
it = DBFETCH(it)->owner;
sprintf(buff,"#%d", it);
}
void fun_name(char *buff, const char *args[10], dbref privs)
{
dbref it = match_thing(privs, args[0]);
if (it == NOTHING)
strcpy(buff, "");
else
if (Typeof(it) == TYPE_EXIT)
{
char *s;
strcpy(buff, DBFETCH(it)->name);
for(s = buff; *s && (*s != ';'); s++)
;
*s = 0;
}
else
strcpy(buff, DBFETCH(it)->name);
}
void fun_match(char *buff, char *args[10])
{
int wcount = 1;
char *s = args[0];
char *ptrsrv[10];
int a;
for(a = 0; a < 10; a++)
ptrsrv[a] = awptr[a];
do
{
char *r;
while(*s && (*s == ' '))
s++;
r = s;
while(*s && (*s != ' '))
s++;
if (*s)
*s++=0;
if (wild_match(args[1], r))
{
sprintf(buff, "%d", wcount);
for(a = 0; a < 10; a++)
awptr[a] = ptrsrv[a];
return;
}
wcount++;
}
while(*s);
strcpy(buff, "0");
for(a = 0; a < 10; a++)
awptr[a]=ptrsrv[a];
}
void fun_extract(char *buff, char *args[10])
{
int start = atoi(args[1]);
int len = atoi(args[2]);
char *s = args[0];
char *r;
if ((start < 1) || (len < 1))
{
*buff = 0;
return;
}
start--;
while(start && *s)
{
while(*s && (*s == ' '))
s++;
while(*s && (*s != ' '))
s++;
start--;
}
while(*s && (*s == ' '))
s++;
r = s;
while(len && *s)
{
while(*s && (*s == ' '))
s++;
while(*s && (*s != ' '))
s++;
len--;
}
*s = 0;
strcpy(buff, r);
}
typedef struct fun FUN;
struct fun
{
char *name;
void (*fun) ();
int nargs;
};
FUN flist[] = {
{"RAND", fun_rand, 1},
{"TIME", fun_time, 0},
{"GET", fun_get, 1},
{"MID", fun_mid, 3},
{"ADD", fun_add, 2},
{"SUB", fun_sub, 2},
{"MUL", fun_mul, 2},
{"DIV", fun_div, 2},
{"MOD", fun_mod, 2},
{"FIRST", fun_first, 1},
{"REST", fun_rest, 1},
{"STRLEN", fun_strlen, 1},
{"V", fun_v, 1},
{"S", fun_s, 1},
{"MATCH", fun_match, 2},
{"EXTRACT",fun_extract,3},
{"NUM", fun_num, 1},
{"CON", fun_con, 1},
{"NEXT", fun_next, 1},
{"OWNER", fun_owner, 1},
{"LOC", fun_loc, 1},
{"EXIT", fun_exit, 1},
{"NAME", fun_name, 1},
{NULL, NULL, 0}
};
void do_fun(char **str, char *buff, dbref privs, dbref doer)
{
char *s;
FUN *fp;
char *args[10];
char obuff[1024];
int a;
/* look for buff in flist */
strcpy(obuff, buff);
for(s = buff; *s; s++)
*s = islower(*s) ? toupper(*s) : *s;
for(fp = flist; fp->name && strcmp(fp->name, buff); fp++);
/* if not found return all stuff up to next matching ) */
if (!fp->name)
{
int deep = 2;
char *t = buff + strlen(obuff);
strcpy(buff, obuff);
*t++ = '(';
while(**str && deep)
switch(*t++ = *(*str)++)
{
case '(':
deep++;
break;
case ')':
deep--;
break;
}
if (**str)
{
(*str)--;
t--;
}
*t = 0;
return;
}
/* now get the arguments to the function */
for(a = 0; (a < 10) && **str && (**str != ')'); a++)
{
if (**str == ',')
(*str)++;
exec(str, obuff, privs, doer, 1);
args[a] = alloc_ec_string(obuff);
}
if (**str)
(*str)++;
if ((fp->nargs != -1) && (fp->nargs != a))
sprintf(buff, "Function (%s) only expects %d arguments",
fp->name, fp->nargs);
else
fp->fun(buff, args, privs, doer);
}
void exec(char **str, char *buff, dbref privs, dbref doer, int coma)
{
char *s, *e = buff;
*buff = 0;
/* eat preceding space */
for (s = *str; *s && isspace(*s); s++)
;
/* parse until (, ],) or , */
for (; *s; s++)
switch (*s) {
case ',': /* comma in list of function arguments */
case ')': /* end of arguments */
if (!coma)
goto cont;
case ']': /* end of expression */
/* eat trailing space */
while ((--e >= buff) && isspace(*e)) ;
e[1] = 0;
*str = s;
return;
case '(': /* this is a function */
while ((--e >= buff) && isspace(*e))
;
e[1] = 0;
*str = s + 1;
/* if just ()'s by them self then it is quoted */
if (*buff)
do_fun(str, buff, privs, doer);
return;
case '{':
if (e == buff) {
int deep = 1;
e = buff;
s++;
while (deep && *s)
switch (*e++ = *s++) {
case '{':
deep++;
break;
case '}':
deep--;
break;
}
if ((e > buff) && (e[-1] == '}'))
e--;
while ((--e >= buff) && isspace(*e))
;
e[1] = 0;
*str = s;
return;
} else
/* otherwise is a quote in middle, search for other end */
{
int deep = 1;
*e++ = *s++;
while (deep && *s)
switch (*e++ = *s++) {
case '{':
deep++;
break;
case '}':
deep--;
break;
}
s--;
}
break;
default:
cont:
*e++ = *s;
break;
}
while ((--e >= buff) && isspace(*e))
;
e[1] = 0;
*str = s;
return;
}
char * check_arg(char *what, dbref player, dbref cause)
{
char buf[BUFFER_LEN];
if(!what) return alloc_ec_string("");
printf("what: %s\n", what);
exec(&what, buf, player, cause, 0);
printf("buf: %s\n", buf);
return alloc_ec_string(buf);
}