/* eval.c */
/* Expression parsing module created by Lawrence Foard */
#include "copyright.h"
#include <ctype.h>
#include <string.h>
#include <math.h>
#include <sys/time.h>
#include <sys/types.h>
#include "config.h"
#include "db.h"
#include "interface.h"
#include "externs.h"
#ifdef MEM_CHECK
#include "mem_check.h"
#endif
#ifdef USE_NALLOC
#include "nalloc.h"
extern NALLOC *glurp;
#endif
/* functions not found in this file */
extern void fun_lwho(); /* bsd.c */
extern void fun_lsearch(); /* wiz.c */
/* functions for the string expressions */
void exec();
dbref match_thing(player, name)
dbref player;
const char *name;
{
init_match(player, name, NOTYPE);
match_everything();
return (noisy_match_result());
}
/* --------------------------------------------------------------------------
* Utility functions: RAND, TIME
*/
void fun_rand(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
/*
* Uses Sh'dow's random number generator, found in utils.c. Better
* distribution than original, w/ minimal speed losses.
*/
sprintf(buff, "%d", getrandom(atoi(args[0])));
}
void fun_time(buff, dumm1, dumm2, dumm3)
char *buff;
char *dumm3[10];
dbref dumm1, dumm2;
{
time_t tt;
tt = time((time_t *) 0);
/*
* There is NO WAY this string could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff, "%s", ctime(&tt));
buff[strlen(buff)-1] = '\0';
}
/* --------------------------------------------------------------------------
* Attribute functions: GET, XGET, V, S
*/
void fun_get(buff, args, player, dummy)
char *buff;
char *args[10];
dbref player;
dbref dummy;
{
dbref thing;
char *s;
ATTR *a;
char tbuf1[BUFFER_LEN];
strcpy(tbuf1, args[0]);
for(s = tbuf1; *s && (*s != '/'); s++);
if(!*s) {
/*
* There is NO WAY this string could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
strcpy(buff, "#-1 BAD ARGUMENT FORMAT TO GET");
return;
}
*s++ = 0;
thing = match_thing(player, tbuf1);
if(thing == NOTHING) {
/*
* There is NO WAY this string could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
strcpy(buff, "#-1 NO SUCH OBJECT VISIBLE");
return;
}
if(*s == '_') s++;
if(!*s) {
/*
* There is NO WAY this string could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
strcpy(buff, "#-1 BAD ARGUMENT FORMAT TO GET");
return;
}
a = atr_get(thing, s);
if(!a) {
/*
* There is NO WAY this string could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
strcpy(buff, "#-1 NO SUCH ATTRIBUTE");
return;
}
if (Hasprivs(player) ||
(db[player].owner == db[a->creator].owner) ||
((controls(player, thing) || Visual(thing)) &&
!((a->flags & AF_WIZARD) || (a->flags & AF_DARK))) ||
!(a->flags & AF_ODARK)) {
if(strlen(uncompress(a->value)) < BUFFER_LEN)
strcpy(buff, uncompress(a->value));
else
/*
* There is NO WAY this string could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
strcpy(buff, "#-1 ATTRIBUTE LENGTH TOO LONG");
} else
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
strcpy(buff, "#-1 NO PERMISSION TO GET ATTRIBUTE");
}
/* Functions like get, but uses the standard way of passing arguments */
/* to a function, and thus doesn't choke on nested functions within. */
void fun_xget(buff, args, player, dumm1)
char *buff;
char *args[10];
dbref player;
dbref dumm1;
{
dbref thing;
char *attrib;
char *obj;
ATTR *a;
obj = args[0];
thing = match_thing(player, obj);
if (thing == NOTHING) {
strcpy(buff, "#-1 NO SUCH OBJECT VISIBLE");
return;
}
attrib = args[1];
a = atr_get(thing, attrib);
if (!a) {
strcpy(buff, "#-1 NO SUCH ATTRIBUTE");
return;
}
if (Hasprivs(player) ||
(db[player].owner == db[a->creator].owner) ||
((controls(player, thing) || Visual(thing)) &&
!((a->flags & AF_WIZARD) || (a->flags & AF_DARK))) ||
!(a->flags & AF_ODARK)) {
if (strlen(uncompress(a->value)) < BUFFER_LEN)
strcpy(buff, uncompress(a->value));
else
strcpy(buff, "#-1 ATTRIBUTE LENGTH TOO LONG");
} else
strcpy(buff, "#-1 NO PERMISSION TO GET ATTRIBUTE");
}
/* handle 0-9,va-vz,n,# */
void fun_v(buff, args, privs, doer)
char *buff;
char *args[10];
dbref privs;
dbref doer;
{
int c;
ATTR *a;
switch (c = args[0][0]) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (!wptr[c - '0']) {
buff[0] = '\0';
return;
}
if(strlen(wptr[c - '0']) < BUFFER_LEN)
strcpy(buff, wptr[c - '0']);
else
buff[0] = '\0';
break;
case 'n':
case 'N':
if(args[0][1]) {
a = atr_get(privs, args[0]);
if(a) {
if((a->flags & AF_DARK) ||
((a->flags & AF_WIZARD) && !Hasprivs(privs)))
/*
* There is NO WAY this number could every be longer than
* BUFFER_LEN. therefore, no checking is required.
*/
buff[0] = '\0';
else {
if(strlen(uncompress(a->value)) < BUFFER_LEN)
strcpy(buff, uncompress(a->value));
else
buff[0] = '\0';
}
} else
buff[0] = '\0';
} else
/*
* There is NO WAY this string could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
strcpy(buff, db[doer].name);
break;
case '#':
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff, "#%d", doer);
break;
/* info about location and stuff */
/* objects # */
case '!':
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff, "#%d", privs);
break;
default:
if(*args[0] == '_')
a = atr_get(privs, args[0]+1);
else
a = atr_get(privs, args[0]);
if(a) {
if((a->flags & AF_DARK) ||
((a->flags & AF_WIZARD) && !Hasprivs(privs)))
buff[0] = '\0';
else {
if(strlen(uncompress(a->value)) < BUFFER_LEN)
strcpy(buff, uncompress(a->value));
else
buff[0] = '\0';
}
} else
buff[0] = '\0';
}
}
void fun_s(buff, args, privs, doer)
char *buff;
char *args[10];
dbref privs;
dbref doer;
{
char *s = pronoun_substitute(doer, args[0], privs);
if(strlen(s) < BUFFER_LEN)
strcpy(buff, s);
else
buff[0] = '\0';
}
/* --------------------------------------------------------------------------
* Arithmetic functions: ADD, SUB, MUL, DIV, MOD, GT, GTE, LT, LTE,
* EQ, NEQ, MAX, MIN, DIST2D, DIST3D, LNUM
*/
void fun_add(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff, "%d", atoi(args[0]) + atoi(args[1]));
}
void fun_sub(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff, "%d", atoi(args[0]) - atoi(args[1]));
}
void fun_mul(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff, "%d", atoi(args[0]) * atoi(args[1]));
}
void fun_div(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
int bot = atoi(args[1]);
if (bot == 0)
bot = 1;
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff, "%d", atoi(args[0]) / bot);
}
void fun_mod(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
int bot = atoi(args[1]);
if (bot == 0)
bot = 1;
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff, "%d", atoi(args[0]) % bot);
}
void fun_gt(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff,"%d", (atoi(args[0]) > atoi(args[1])));
}
void fun_gte(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff,"%d", (atoi(args[0]) >= atoi(args[1])));
}
void fun_lt(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff,"%d", (atoi(args[0]) < atoi(args[1])));
}
void fun_lte(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff,"%d", (atoi(args[0]) <= atoi(args[1])));
}
void fun_eq(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff,"%d", (atoi(args[0]) == atoi(args[1])));
}
void fun_neq(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff,"%d", (atoi(args[0]) != atoi(args[1])));
}
void fun_max(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
int max;
int i = 1;
if (!args[0]) {
strcpy(buff, "#-1 TOO FEW ARGUMENTS");
return;
} else
max = atoi(args[0]);
while (i < 10 && args[i]) {
max = (atoi(args[i]) > max) ? atoi(args[i]) : max;
i++;
}
sprintf(buff, "%d", max);
}
void fun_min(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
int min;
int i = 1;
if (!args[0]) {
strcpy(buff, "#-1 TOO FEW ARGUMENTS");
return;
} else
min = atoi(args[0]);
while (i < 10 && args[i]) {
min = (atoi(args[i]) < min) ? atoi(args[i]) : min;
i++;
}
sprintf(buff, "%d", min);
}
/* this function and dist3d are taken from the 2.0 code */
void fun_dist2d(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
int d;
double r;
d = atoi(args[0]) - atoi(args[2]);
r = (double) (d * d);
d = atoi(args[1]) - atoi(args[3]);
r += (double) (d * d);
d = (int) (sqrt(r) + 0.5);
sprintf(buff, "%d", d);
}
void fun_dist3d(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
int d;
double r;
d = atoi(args[0]) - atoi(args[3]);
r = (double) (d * d);
d = atoi(args[1]) - atoi(args[4]);
r += (double) (d * d);
d = atoi(args[2]) - atoi(args[5]);
r += (double) (d * d);
d = (int) (sqrt(r) + 0.5);
sprintf(buff, "%d", d);
}
void fun_lnum(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
int x, i;
x = atoi(args[0]);
if ((x > 100) || (x < 0)) {
strcpy(buff, "#-1 NUMBER OUT OF RANGE");
return;
}
else {
strcpy(buff,"0");
for (i = 1; i < x; i++)
sprintf(buff, "%s %d", buff, i);
}
}
/* --------------------------------------------------------------------------
* String functions: FIRST, REST, STRLEN, COMP, POS, MID, EXTRACT, WORDPOS,
* MATCH, CAT, REMOVE, MEMBER, FLIP, UCSTR, LCSTR, WORDS
*/
/* read first word from a string */
void fun_first(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
char *s = args[0];
char *b;
/* get rid of leading space */
while (*s && (*s == ' '))
s++;
b = s;
while (*s && (*s != ' '))
s++;
*s++ = 0;
if(strlen(b) < BUFFER_LEN)
strcpy(buff, b);
else
buff[0] = '\0';
}
void fun_rest(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
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++;
if(strlen(s) < BUFFER_LEN)
strcpy(buff, s);
else
buff[0] = '\0';
}
void fun_strlen(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff, "%d", strlen(args[0]));
}
void fun_mid(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
int l = atoi(args[1]), len = atoi(args[2]);
if ((l < 0) || (len < 0) || ((len + l) > BUFFER_LEN)) {
strcpy(buff, "#-1 OUT OF RANGE");
return;
}
if (l < strlen(args[0]))
strcpy(buff, args[0] + l);
else
*buff = 0;
buff[len] = 0;
}
void fun_comp(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
int x;
x = strcmp(args[0], args[1]);
if (x > 0)
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
strcpy(buff, "1");
else if (x < 0)
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
strcpy(buff, "-1");
else
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
strcpy(buff, "0");
}
void fun_pos(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
int i = 1;
char *t, *u, *s = args[1];
while (*s) {
u = s;
t = args[0];
while (*t && *t == *u)
++t, ++u;
if (*t == '\0') {
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff, "%d", i);
return;
}
++i, ++s;
}
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
strcpy(buff, "#-1");
return;
}
void fun_match(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
int a;
int wcount = 1;
char *s = args[0];
char *ptrsrv[10];
for (a = 0; a < 10; a++)
ptrsrv[a] = wptr[a];
do {
char *r;
/* trim off leading space */
while (*s && (*s == ' '))
s++;
r = s;
/* scan to next space and truncate if necessary */
while (*s && (*s != ' '))
s++;
if (*s)
*s++ = 0;
if (wild_match(args[1], r)) {
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff, "%d", wcount);
for (a = 0; a < 10; a++)
wptr[a] = ptrsrv[a];
return;
}
wcount++;
} while (*s);
strcpy(buff, "#-1");
for (a = 0; a < 10; a++)
wptr[a] = ptrsrv[a];
}
/* taken from the 2.0 code */
void fun_wordpos(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
char *cp;
char done, inspace;
int charpos = atoi(args[1]);
int word = 1;
for (inspace = 0, done = 0, cp = args[0]; cp && *cp && !done; cp++) {
if ((*cp == ' ') && (!inspace)) {
word++;
inspace = 1;
}
if ((*cp != ' ') && (inspace))
inspace = 0;
if ((cp - args[0] + 1) == charpos)
done = 1;
}
if (!done)
strcpy(buff, "#-1");
else
sprintf(buff, "%d", word);
}
void fun_extract(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
int start = atoi(args[1]), len = atoi(args[2]);
char *s = args[0], *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;
if(strlen(r) < BUFFER_LEN)
strcpy(buff, r);
else
buff[0] = '\0';
}
int translate(arg)
char *arg;
{
int temp;
char *temp2;
if (arg[0] == '#')
if ((temp = atoi(arg+1)) == -1)
return 0;
else
return temp;
else
temp2 = arg;
while (isspace(*temp2))
temp2++;
if ((*temp2 == '\0') && (temp2 == arg))
return 0;
if (isdigit(*temp2))
return atoi(temp2);
return 1;
}
void fun_cat(buff,args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
if(strlen(args[0]) + strlen(args[1]) < BUFFER_LEN)
sprintf(buff,"%s %s",args[0],args[1]);
else
sprintf(buff, "%s", args[0]);
}
void fun_remove(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
char *s, *t, *p;
int done = 0;
/*
* This function is 'safe' since it is impossible that any of the arg[]
* elements will be larger than BUFFER_LEN, and in the worst case, this
* does nothing to the the length, thereby it's still < BUFFER_LEN
*/
if(index(args[1],' ')) {
strcpy(buff,"#-1 CAN ONLY DELETE ONE ELEMENT");
return;
}
s = p = args[0];
t = args[1];
while (*s && !done) {
if (*t)
if (*s == *t)
t++;
else {
t = args[1];
while (*(s+1) && *s != ' ')
s++;
p = s;
}
else
done = 1;
s++;
}
if ((*t == '\0') && ((*(s-1) == ' ') || (*s == '\0'))) {
if (p == args[0])
strcpy(buff,s);
else {
*p = '\0';
if (*s == '\0')
strcpy(buff,args[0]);
else
sprintf(buff,"%s %s",args[0],s);
}
return;
}
strcpy(buff,args[0]);
}
void fun_member(buff,args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
char *s, *t;
int done = 0;
int element = 1;
if (index(args[1],' ')) {
strcpy(buff,"#-1 CAN ONLY TEST ONE ELEMENT");
return;
}
s = args[0];
t = args[1];
while (*s && !done) {
if (*t)
if (*s == *t)
t++;
else {
element++;
t = args[1];
while (*(s+1) && *s != ' ')
s++;
}
else
done = 1;
s++;
}
if ((*t == '\0') && ((*(s-1) == ' ') || (*s == '\0'))) {
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff,"%d",element);
return;
}
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
strcpy(buff,"0");
}
void fun_flip(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
char *s = args[0];
char *p, *q, temp;
int n;
n = strlen(s);
q = (n > 0) ? s + n - 1 : s;
for (p = s; p < q; ++p, --q) {
temp = *p;
*p = *q;
*q = temp;
}
strcpy(buff, s);
}
void fun_lcstr(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
char *ap;
ap = args[0];
strcpy(buff, "");
while (*ap) {
if (isupper(*ap))
*buff++ = tolower(*ap++);
else
*buff++ = *ap++;
}
*buff++ = '\0';
/* No need to check buffer length */
}
void fun_ucstr(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
char *ap;
ap = args[0];
strcpy(buff, "");
while (*ap) {
if (islower(*ap))
*buff++ = toupper(*ap++);
else
*buff++ = *ap++;
}
*buff++ = '\0';
/* No need to check buffer length */
}
void fun_words(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
char *s = args[0];
int wcount = 0;
while(*s && *s == ' ')
s++;
while(*s) {
wcount++;
while(*s && *s != ' ')
s++;
while(*s && *s == ' ')
s++;
}
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff,"%d",wcount);
}
/* --------------------------------------------------------------------------
* Word functions: CAPSTR, ART, SUBJ, OBJ, POSS, ALPHAMAX, ALPHAMIN
*/
void fun_capstr(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
strcpy(buff, args[0]);
if (islower(*buff))
*buff = toupper(*buff);
/* No need to check buffer length */
}
/* checks a word and returns the appropriate article, "a" or "an" */
void fun_art(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
char c = tolower(*args[0]);
if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u')
strcpy(buff, "an");
else
strcpy(buff, "a");
}
/* utility function to find sex of object, used by SUBJ, OBJ, and POSS.
* Returns 0 for none, 1 for female, 2 for male
*/
int find_sex(thing)
dbref thing;
{
ATTR *a;
int gender;
a = atr_get(thing, "SEX");
if (!a)
gender = 0;
else {
switch (*uncompress(a->value)) {
case 'M': case 'm':
gender = 2;
break;
case 'W': case 'w': case 'F': case 'f':
gender = 1;
break;
default:
gender = 0;
}
}
return gender;
}
void fun_subj(buff, args, player, dumm1)
char *buff;
char *args[10];
dbref player;
dbref dumm1;
{
dbref thing;
int gender;
thing = match_thing(player, args[0]);
if (thing == NOTHING) {
strcpy(buff, "#-1 NO MATCH");
return;
}
gender = find_sex(thing);
switch (gender) {
case 1:
strcpy(buff, "she");
break;
case 2:
strcpy(buff, "he");
break;
default:
strcpy(buff, "it");
}
}
void fun_obj(buff, args, player, dumm1)
char *buff;
char *args[10];
dbref player;
dbref dumm1;
{
dbref thing;
int gender;
thing = match_thing(player, args[0]);
if (thing == NOTHING) {
strcpy(buff, "#-1 NO MATCH");
return;
}
gender = find_sex(thing);
switch (gender) {
case 1:
strcpy(buff, "her");
break;
case 2:
strcpy(buff, "him");
break;
default:
strcpy(buff, "it");
}
}
void fun_poss(buff, args, player, dumm1)
char *buff;
char *args[10];
dbref player;
dbref dumm1;
{
dbref thing;
int gender;
thing = match_thing(player, args[0]);
if (thing == NOTHING) {
strcpy(buff, "#-1 NO MATCH");
return;
}
gender = find_sex(thing);
switch (gender) {
case 1:
strcpy(buff, "her");
break;
case 2:
strcpy(buff, "his");
break;
default:
strcpy(buff, "its");
}
}
void fun_alphamax(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
char *amax;
int i = 1;
if (!args[0]) {
strcpy(buff, "#-1 TOO FEW ARGUMENTS");
return;
} else
amax = args[0];
while ((i < 10) && args[i]) {
amax = (strcmp(amax, args[i]) > 0) ? amax : args[i];
i++;
}
sprintf(buff, "%s", amax);
}
void fun_alphamin(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
char *amin;
int i = 1;
if (!args[0]) {
strcpy(buff, "#-1 TOO FEW ARGUMENTS");
return;
} else
amin = args[0];
while ((i < 10) && args[i]) {
amin = (strcmp(amin, args[i]) < 0) ? amin : args[i];
i++;
}
sprintf(buff, "%s", amin);
}
/* --------------------------------------------------------------------------
* MUSH utilities: FLAGS, NUM, RNUM, LEXITS, EXITS, LCON, CON, NEXT, MAIL,
* NEARBY, TYPE, HASFLAG, LOCK, ELOCK, LOC, HOME, OWNER, NAME
*/
void fun_flags(buff, args, player, dumm1)
char *buff;
char *args[10];
dbref player;
dbref dumm1;
{
dbref thing;
thing = match_thing(player, args[0]);
if (thing == NOTHING) {
strcpy(buff,"#-1");
return;
}
/*
* There is NO WAY this string could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
strcpy(buff, unparse_flags(thing));
}
void fun_num(buff, args, privs, dumm1)
char *buff;
char *args[10];
dbref privs;
dbref dumm1;
{
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff, "#%d", match_thing(privs, args[0]));
}
#ifdef DO_GLOBALS
void fun_rnum(buff, args, privs, dumm1)
char *buff;
char *args[10];
dbref privs;
dbref dumm1;
{
dbref place = match_thing(privs, args[0]);
char *name = args[1];
dbref thing;
init_match_remote(place, name, NOTYPE);
match_remote();
switch (thing = match_result()) {
case NOTHING:
strcpy(buff, "#-1 NO MATCH");
break;
case AMBIGUOUS:
strcpy(buff, "#-1 AMBIGUOUS MATCH");
break;
default:
sprintf(buff, "#%d", thing);
}
}
#endif
/*
* fun_lcon, fun_lexits, fun_con, fun_exit, fun_next, and next_exit were all
* re-coded by d'mike, 7/12/91. next_con was added at this time as well.
* the functions now check for several things before returning a result to the
* caller. new checks : will only return the number of the exit/object if :
* - you're a wizard ( of course )
* - you control the object/exit in question (you always know where your
* stuff is!)
* - you control the room in which the object/exit is located
* - the obj/exit is not dark, and the room it's in is not dark/opaque
* either. (exits are still returned in opaque rooms. I'm planning on
* changing look/examine/etc. to reflect this state as well.)
*/
void fun_lcon(buff, args, privs, dumm1)
char *buff;
char *args[10];
dbref privs;
dbref dumm1;
{
dbref it = match_thing(privs, args[0]);
dbref thing;
char tbuf1[BUFFER_LEN];
buff[0] = '\0';
if (it != NOTHING) {
DOLIST(thing, db[it].contents) {
if (Hasprivs(privs) ||
controls(privs, thing) ||
controls(privs, it) ||
(!Dark(thing) &&
!Dark(it) &&
!(db[it].flags & OPAQUE))) {
if (buff[0] == '\0')
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff, "#%d", thing);
else {
if ((strlen(buff)+15) < BUFFER_LEN) {
sprintf(tbuf1, "%s #%d", buff, thing);
strcpy(buff, tbuf1);
}
}
}
}
} else
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
strcpy(buff, "#-1");
}
/* fun_con is a wrapper for next_con now. */
void fun_con(buff, args, privs, dumm1)
char *buff;
char *args[10];
dbref privs;
dbref dumm1;
{
dbref it = match_thing(privs, args[0]);
if (it != NOTHING)
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff, "#%d", next_con(privs, db[it].contents));
else
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
strcpy(buff, "#-1");
return;
}
/* return nect contents that is ok to see */
dbref next_con(player, this)
dbref player;
dbref this;
{
while((this !=NOTHING) &&
!(Hasprivs(player) ||
controls(player, this) ||
controls(player, db[this].location) ||
(!Dark(db[this].location) &&
!(db[db[this].location].flags & OPAQUE) &&
!Dark(this)))) {
this = db[this].next;
}
return(this);
}
/* return next exit that is ok to see */
dbref next_exit(player, this)
dbref player;
dbref this;
{
while ((this != NOTHING) &&
!(Hasprivs(player) ||
controls(player, this) ||
controls(player, db[this].exits) ||
(!Dark(db[this].exits) && /* WHY is this check here.. it's useless */
!Dark(this)))) {
this = db[this].next;
}
return(this);
}
void fun_lexits(buff,args, privs, dumm1)
char *buff;
char *args[10];
dbref privs;
dbref dumm1;
{
dbref it = match_thing(privs, args[0]);
dbref thing;
char tbuf1[BUFFER_LEN];
buff[0] = '\0';
if (it != NOTHING) {
DOLIST(thing,db[it].exits) {
if (Hasprivs(privs) ||
controls(privs, thing) ||
controls(privs, it) ||
(!Dark(thing) && !Dark(it))) {
if (buff[0] == '\0')
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff,"#%d",thing);
else {
if ((strlen(buff)+15) < BUFFER_LEN) {
sprintf(tbuf1,"%s #%d",buff,thing);
strcpy(buff,tbuf1);
}
}
}
}
} else
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
strcpy(buff,"#-1");
}
/* fun_exit is really just a wrapper for next_exit now... */
void fun_exit(buff, args, privs, dumm1)
char *buff;
char *args[10];
dbref privs;
dbref dumm1;
{
dbref it = match_thing(privs, args[0]);
if (it != NOTHING)
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff, "#%d", next_exit(privs, db[it].exits));
else
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
strcpy(buff, "#-1");
return;
}
void fun_next(buff, args, privs, dumm1)
char *buff;
char *args[10];
dbref privs;
dbref dumm1;
{
dbref it = match_thing(privs, args[0]);
if (it != NOTHING) {
if (Typeof(it) != TYPE_EXIT) {
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff, "#%d", next_con(privs, db[it].next));
return;
} else {
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff, "#%d", next_exit(privs, db[it].next));
return;
}
}
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
strcpy(buff, "#-1");
return;
}
#ifdef USE_MAILER
void fun_mail(buff, args, player, dummy)
char *buff;
char *args[10];
dbref player;
dbref dummy;
{
mdbref thing;
if (thing = search_mail(player, atol(args[0])))
strcpy(buff, mdb[thing].message);
else
strcpy(buff, "#-1 INVALID MAIL NUMBER");
return;
}
#endif
void fun_nearby(buff, args, privs, dumm1)
char *buff;
char *args[10];
dbref privs;
dbref dumm1;
{
int n;
dbref obj1 = match_thing(privs, args[0]);
dbref obj2 = match_thing(privs, args[1]);
if (!controls(privs, obj1) && !controls(privs, obj2)
&& !nearby(privs, obj1) && !nearby(privs, obj2)) {
strcpy(buff, "#-1 NO OBJECTS CONTROLLED");
return;
}
if ((n = nearby(obj1, obj2)) == -1) {
strcpy(buff, "#-1");
return;
} else
sprintf(buff, "%d", n);
}
void fun_type(buff, args, privs, dumm1)
char *buff;
char *args[10];
dbref privs;
dbref dumm1;
{
dbref it = match_thing(privs, args[0]);
if (it == NOTHING) {
strcpy(buff, "#-1");
return;
}
switch (Typeof(it)) {
case TYPE_PLAYER:
strcpy(buff, "PLAYER");
break;
case TYPE_THING:
strcpy(buff, "THING");
break;
case TYPE_EXIT:
strcpy(buff, "EXIT");
break;
case TYPE_ROOM:
strcpy(buff, "ROOM");
break;
default:
strcpy(buff, "WEIRD OBJECT");
fprintf(stderr, "PANIC Weird object #%d (type %d)", it, Typeof(it));
}
}
void fun_hasflag(buff, args, privs, dumm1)
char *buff;
char *args[10];
dbref privs;
dbref dumm1;
{
int f = 0;
dbref it = match_thing(privs, args[0]);
char *p = args[1];
if (it == NOTHING) {
strcpy(buff, "#-1");
return;
}
f = find_flag(p, it);
if (db[it].flags & f)
strcpy(buff, "1");
else
strcpy(buff, "0");
}
void fun_lock(buff, args, privs, dumm1)
char *buff;
char *args[10];
dbref privs;
dbref dumm1;
{
dbref it = match_thing(privs, args[0]);
const char *s;
if((it != NOTHING) && controls(privs, it)) {
s = unparse_boolexp(privs, db[it].key, 1);
if(strlen(s) < BUFFER_LEN) {
sprintf(buff, "%s", s);
return;
}
}
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
strcpy(buff, "#-1");
return;
}
void fun_elock(buff, args, privs, dumm1)
char *buff;
char *args[10];
dbref privs;
dbref dumm1;
{
dbref it = match_thing(privs, args[0]);
dbref victim = match_thing(privs, args[1]);
if (it != NOTHING) {
/*
* We do not check for control because this can be bypassed by using
* an indirect lock.
*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff, "%d", eval_boolexp(victim, db[it].key, it, 0, BASICLOCK));
return;
}
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
strcpy(buff, "#-1");
return;
}
void fun_loc(buff, args, privs, dumm1)
char *buff;
char *args[10];
dbref privs;
dbref dumm1;
{
dbref it = match_thing(privs, args[0]);
if (it != NOTHING &&
(controls(privs, it) || nearby(privs, it)
#ifdef PLAYER_LOCATE
|| (Typeof(it) == TYPE_PLAYER && (db[it].flags & PLAYER_DARK) == 0)
#endif
)) {
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff, "#%d", db[it].location);
return;
}
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
strcpy(buff, "#-1");
return;
}
void fun_zone(buff, args, privs, dumm1)
char *buff;
char *args[10];
dbref privs;
dbref dumm1;
{
dbref it = match_thing(privs, args[0]);
if (it == NOTHING || !controls(privs, it) || (Typeof(it) == TYPE_ROOM)) {
strcpy(buff, "#-1");
return;
}
sprintf(buff, "#%d", db[it].zone);
}
void fun_home(buff, args, privs, dumm1)
char *buff;
char *args[10];
dbref privs;
dbref dumm1;
{
dbref it = match_thing(privs, args[0]);
if(it == NOTHING ||
!controls(privs, it) ||
(Typeof(it) == TYPE_ROOM)) {
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
strcpy(buff,"#-1");
return;
}
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff, "#%d", db[it].exits);
}
void fun_money(buff, args, privs, dumm1)
char *buff;
char *args[10];
dbref privs;
dbref dumm1;
{
dbref it = match_thing(privs, args[0]);
if(it == NOTHING) {
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
strcpy(buff,"#-1");
return;
}
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff,"%d",db[it].penn);
}
void fun_owner(buff, args, privs, dumm1)
char *buff;
char *args[10];
dbref privs;
dbref dumm1;
{
dbref it = match_thing(privs, args[0]);
if (it != NOTHING)
it = db[it].owner;
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff, "#%d", it);
}
void fun_name(buff, args, privs, dumm1)
char *buff;
char *args[10];
dbref privs;
dbref dumm1;
{
dbref it = match_thing(privs, args[0]);
if (it == NOTHING)
strcpy(buff, "");
else if (Typeof(it) == TYPE_EXIT) {
char *s;
if(strlen(db[it].name) < BUFFER_LEN) {
strcpy(buff, db[it].name);
for (s = buff; *s && (*s != ';'); s++) ;
*s = 0;
} else
buff[0] = '\0';
} else {
if(strlen(db[it].name) < BUFFER_LEN)
strcpy(buff, db[it].name);
else
buff[0] = '\0';
}
}
/* --------------------------------------------------------------------------
* Booleans: AND, OR, XOR, NOT
*/
void fun_and(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff, "%d", translate(args[0]) && translate(args[1]));
}
void fun_or(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff, "%d", translate(args[0]) || translate(args[1]));
}
void fun_not(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff, "%d", !translate(args[0]));
}
void fun_xor(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
/*
* There is NO WAY this number could every be longer than BUFFER_LEN.
* therefore, no checking is required.
*/
sprintf(buff, "%d", ((translate(args[0]) && !translate(args[1])) ||
(!translate(args[0]) && translate(args[1]))));
}
/* --------------------------------------------------------------------------
* SORT function and its auxiliaries
*/
void swap(char **p, char **q)
/* swaps two pointers to strings */
{
char *temp;
temp = *p;
*p = *q;
*q = temp;
}
void do_sort(char *s[], int n)
/* uses a transposition sort to sort an array of words */
{
int i, j; /* utility */
for (i = 0; i < n; i++)
for (j = i + 1; j < n; j++)
if (strcmp(*(s + i), *(s + j)) > 0)
swap(s + i, s + j);
}
void fun_sort(buff, args, dumm1, dumm2)
char *buff;
char *args[10];
dbref dumm1, dumm2;
{
int i = 0;
int nargs = 0;
/* find number of arguments */
while (i < 10 && (args[i++] != '\0'))
nargs++;
if (nargs < 1) {
strcpy(buff, "#-1 TOO FEW ARGUMENTS");
return;
}
if (nargs == 1) {
strcpy(buff, args[0]);
return;
}
/* this case should never happen */
if (nargs > 10) {
strcpy(buff, "#-1 TOO MANY ARGUMENTS");
return;
}
do_sort(args, nargs);
/* copy the sort into buffer, checking to make sure that it doesn't */
/* overflow the buffer */
i = 0;
strcpy(buff, args[i++]);
while (i < nargs) {
if ((strlen(buff) + strlen(args[i])) < BUFFER_LEN)
sprintf(buff, "%s %s", buff, args[i++]);
else {
strcpy(buff, "#-1 STRING TOO LONG");
return;
}
}
sprintf(buff, "%s%c", buff, '\0');
}
/* --------------------------------------------------------------------------
* The actual function handlers
*/
typedef struct fun FUN;
struct fun {
const char *name;
void (*fun) ();
int nargs;
};
FUN flist[] =
{
{"RAND", fun_rand, 1},
{"TIME", fun_time, 0},
{"LWHO", fun_lwho, 0},
{"GET", fun_get, 1},
{"XGET", fun_xget, 2},
{"MID", fun_mid, 3},
{"ADD", fun_add, 2},
{"SUB", fun_sub, 2},
{"MUL", fun_mul, 2},
{"DIV", fun_div, 2},
{"MOD", fun_mod, 2},
{"MAX", fun_max, -1},
{"MIN", fun_min, -1},
{"ALPHAMAX", fun_alphamax, -1},
{"ALPHAMIN", fun_alphamin, -1},
{"DIST2D", fun_dist2d, 4},
{"DIST3D", fun_dist3d, 6},
{"FIRST", fun_first, 1},
{"REST", fun_rest, 1},
{"FLAGS", fun_flags, 1},
{"STRLEN", fun_strlen, 1},
{"COMP", fun_comp, 2},
{"SUBJ", fun_subj, 1},
{"OBJ", fun_obj, 1},
{"POSS", fun_poss, 1},
{"V", fun_v, 1},
{"S", fun_s, 1},
{"POS", fun_pos, 2},
{"MATCH", fun_match, 2},
{"WORDPOS", fun_wordpos, 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},
{"ZONE", fun_zone, 1},
{"EXIT", fun_exit, 1},
{"NAME", fun_name, 1},
{"AND",fun_and, 2},
{"OR", fun_or, 2},
{"NOT", fun_not, 1},
{"XOR", fun_xor, 2},
{"GT", fun_gt, 2},
{"GTE", fun_gte, 2},
{"LT", fun_lt, 2},
{"LTE", fun_lte, 2},
{"EQ", fun_eq, 2},
{"NEQ", fun_neq, 2},
{"CAT", fun_cat, 2},
{"MEMBER", fun_member, 2},
{"REMOVE", fun_remove, 2},
{"HOME", fun_home, 1},
{"MONEY", fun_money, 1},
{"FLIP", fun_flip, 1},
{"LCSTR", fun_lcstr, 1},
{"UCSTR", fun_ucstr, 1},
{"CAPSTR", fun_capstr, 1},
{"ART", fun_art, 1},
{"WORDS", fun_words, 1},
{"SORT", fun_sort, -1},
{"LSEARCH", fun_lsearch, 3},
{"LCON", fun_lcon, 1},
{"LEXITS", fun_lexits, 1},
#ifdef USE_MAILER
{"MAIL", fun_mail, 1},
#endif
#ifdef DO_GLOBALS
{"RNUM", fun_rnum, 2},
#endif
{"LNUM", fun_lnum, 1},
{"NEARBY", fun_nearby, 2},
{"TYPE", fun_type, 1},
{"HASFLAG", fun_hasflag, 2},
{"LOCK", fun_lock, 1},
{"ELOCK", fun_elock, 2},
{NULL, NULL, 0}
};
void do_fun(str, buff, privs, doer)
char **str;
char *buff;
dbref privs;
dbref doer;
{
char *s;
FUN *fp;
char *args[10];
char obuff[BUFFER_LEN];
int a;
for(a = 0; a < 10; a++)
args[a] = NULL;
/* 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);
if(args[a]) {
#ifdef USE_NALLOC
na_unalloc(glurp, (char *) args[a]);
#else
free((char *) args[a]);
#endif
#ifdef MEM_CHECK
del_check("expression_args");
#endif
args[a] = NULL;
}
#ifdef USE_NALLOC
strcpy((args[a] = (char *) na_ualloc(glurp, strlen(obuff) + 1)), obuff);
#else
strcpy((args[a] = (char *)malloc(strlen(obuff)+1)), obuff);
#endif
#ifdef MEM_CHECK
add_check("expression_args");
#endif
}
if (**str)
(*str)++;
if ((fp->nargs != -1) && (fp->nargs != a))
strcpy(buff, tprintf("#-1 Function (%s) only expects %d arguments",
fp->name, fp->nargs));
else
fp->fun(buff, args, privs, doer);
for(a = 0; a < 10; a++) {
if(args[a]) {
#ifdef USE_NALLOC
na_unalloc(glurp, (char *)args[a]);
#else
free((char *)args[a]);
#endif
#ifdef MEM_CHECK
del_check("expression_args");
#endif
}
}
}
/* execute a string expression, return result in buff */
void exec(str, buff, privs, doer, coma)
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;
}
/* function to split up a list given a seperator */
/* note str will get hacked up */
char *parse_up(str, delimit)
char **str;
char delimit;
{
int deep = 0;
char *s = *str, *os = *str;
if (!*s)
return (NULL);
while (*s && (*s != delimit)) {
if (*s++ == '{') {
deep = 1;
while (deep && *s)
switch (*s++) {
case '{':
deep++;
break;
case '}':
deep--;
break;
}
}
}
if (*s)
*s++ = 0;
*str = s;
return (os);
}