/* 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); }