From 6133c9562acd7e527f6b7081e702b44a4e524fcb Mon Sep 17 00:00:00 2001 From: Ari Johnson Date: Fri, 22 May 2009 00:43:32 +0000 Subject: [PATCH] Implement named %q (cherry picked from commit 36f1cdf98a62184db3f33e9213955fbbca7a4874) --- hdrs/externs.h | 9 +++++++ src/bsd.c | 3 +++ src/cque.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/extmail.c | 1 + src/funmisc.c | 13 +++++++-- src/game.c | 5 ++++ src/look.c | 3 +++ src/parse.c | 39 ++++++++++++++++++++++++--- src/predicat.c | 2 ++ src/prog.c | 29 ++++++++++++++++++++ src/unparse.c | 1 + src/wild.c | 2 ++ src/wiz.c | 1 + 13 files changed, 175 insertions(+), 6 deletions(-) diff --git a/hdrs/externs.h b/hdrs/externs.h index 2932d32..f95f841 100644 --- a/hdrs/externs.h +++ b/hdrs/externs.h @@ -218,6 +218,8 @@ struct eval_context { int re_subpatterns; /**< The number of re subpatterns */ int *re_offsets; /**< The offsets for the subpatterns */ char *re_from; /**< The positions of the subpatterns */ + HASHTAB namedregs; + HASHTAB namedregsnxt; }; typedef struct eval_context EVAL_CONTEXT; @@ -249,6 +251,13 @@ extern void dequeue_semaphores(dbref thing, char const *aname, int count, extern void shutdown_queues(void); extern void do_hourly(void); +extern void init_namedregs(HASHTAB *); +extern void free_namedregs(HASHTAB *); +extern void clear_namedregs(HASHTAB *); +extern void copy_namedregs(HASHTAB *, HASHTAB *); +extern void set_namedreg(HASHTAB *, const char *, const char *); +extern const char *get_namedreg(HASHTAB *, const char *); + /* From create.c */ extern dbref do_dig(dbref player, const char *name, char **argv, int tport); diff --git a/src/bsd.c b/src/bsd.c index 9d24fdc..6ac6c96 100644 --- a/src/bsd.c +++ b/src/bsd.c @@ -2810,6 +2810,7 @@ do_command(DESC *d, char *command) global_eval_context.wenv[j] = (char *) NULL; for (j = 0; j < NUMQ; j++) global_eval_context.renv[j][0] = '\0'; + clear_namedregs(&global_eval_context.namedregs); global_eval_context.process_command_port = d->descriptor; process_command(d->player, command, d->player, d->player, 1); @@ -3783,6 +3784,7 @@ announce_connect(dbref player, int isnew, int num) global_eval_context.wnxt[j] = NULL; for (j = 0; j < NUMQ; j++) global_eval_context.rnxt[j] = NULL; + clear_namedregs(&global_eval_context.namedregsnxt); strcpy(global_eval_context.ccom, ""); /* do the person's personal connect action */ @@ -3854,6 +3856,7 @@ announce_disconnect(dbref player) global_eval_context.wnxt[j] = NULL; for (j = 0; j < NUMQ; j++) global_eval_context.rnxt[j] = NULL; + clear_namedregs(&global_eval_context.namedregsnxt); /* Setup all connect information as info to pass */ (void) queue_attribute(player, "ADISCONNECT", player); diff --git a/src/cque.c b/src/cque.c index 6723fb4..1b45f81 100644 --- a/src/cque.c +++ b/src/cque.c @@ -67,6 +67,7 @@ typedef struct bque { #endif char fqueued; /**< function inserted into queue */ enum qid_flags qid; /**< queue identification # */ + HASHTAB namedregs; } BQUE; static BQUE *qfirst = NULL, *qlast = NULL, *qwait = NULL; @@ -232,6 +233,7 @@ free_qentry(BQUE *point) if (point->rval[a]) { mush_free((Malloc_t) point->rval[a], "bqueue_rval"); } + free_namedregs(&point->namedregs); if (point->semattr) mush_free((Malloc_t) point->semattr, "bqueue_semattr"); if (point->comm) @@ -257,13 +259,19 @@ pay_queue(dbref player, const char *command) char *val_rnxt[NUMQ]; char *preserves[10]; char *preserveq[NUMQ]; + HASHTAB preserve_namedregs; save_global_nxt("pay_queue_save", preserve_wnxt, preserve_rnxt, val_wnxt, val_rnxt); save_global_regs("pay_queue_save", preserveq); save_global_env("pay_queue_save", preserves); + init_namedregs(&preserve_namedregs); + copy_namedregs(&preserve_namedregs, &global_eval_context.namedregs); + clear_namedregs(&global_eval_context.namedregs); notify_format(Owner(player), T("GAME: Object %s(%s) lost a %s to queue loss."), Name(player), unparse_dbref(player), MONEY); + copy_namedregs(&global_eval_context.namedregs, &preserve_namedregs); + free_namedregs(&preserve_namedregs); restore_global_regs("pay_queue_save", preserveq); restore_global_env("pay_queue_save", preserves); restore_global_nxt("pay_queue_save", preserve_wnxt, preserve_rnxt, val_wnxt, @@ -334,6 +342,8 @@ parse_que(dbref player, const char *command, dbref cause) else { tmp->rval[a] = mush_strdup(global_eval_context.rnxt[a], "bqueue_rval"); } + init_namedregs(&tmp->namedregs); + copy_namedregs(&tmp->namedregs, &global_eval_context.namedregs); if (IsPlayer(cause)) { if (qlast) { @@ -384,6 +394,8 @@ div_parse_que(dbref division, const char *command, dbref called_division, dbref else { tmp->rval[a] = mush_strdup(global_eval_context.rnxt[a], "bqueue_rval"); } + init_namedregs(&tmp->namedregs); + copy_namedregs(&tmp->namedregs, &global_eval_context.namedregs); if (IsPlayer(player)) { if (qlast) { qlast->next = tmp; @@ -526,6 +538,8 @@ wait_que(dbref player, int wait, char *command, dbref cause, dbref sem, tmp->rval[a] = mush_strdup(global_eval_context.rnxt[a], "bqueue_rval"); } } + init_namedregs(&tmp->namedregs); + copy_namedregs(&tmp->namedregs, &global_eval_context.namedregs); if (until) { tmp->left = wait; @@ -692,6 +706,7 @@ do_top(int ncom) else global_eval_context.renv[a][0] = '\0'; } + copy_namedregs(&global_eval_context.namedregs, &entry->namedregs); global_eval_context.process_command_port = 0; s = entry->comm; global_eval_context.break_called = 0; @@ -991,6 +1006,7 @@ do_wait(dbref player, dbref cause, char *arg1, char *cmd, int until, char finvoc global_eval_context.wnxt[j] = global_eval_context.wenv[j]; for (j = 0; j < NUMQ; j++) global_eval_context.rnxt[j] = global_eval_context.renv[j]; + copy_namedregs(&global_eval_context.namedregsnxt, &global_eval_context.namedregs); arg2 = strip_braces(cmd); if (is_strict_integer(arg1)) { @@ -1406,6 +1422,7 @@ do_halt(dbref owner, const char *ncom, dbref victim) global_eval_context.wnxt[j] = global_eval_context.wenv[j]; for (j = 0; j < NUMQ; j++) global_eval_context.rnxt[j] = global_eval_context.renv[j]; + copy_namedregs(&global_eval_context.namedregsnxt, &global_eval_context.namedregs); parse_que(player, ncom, player); } } @@ -1593,6 +1610,8 @@ shutdown_queues(void) shutdown_a_queue(&qlfirst, &qllast); shutdown_a_queue(&qsemfirst, &qsemlast); shutdown_a_queue(&qwait, NULL); + free_namedregs(&global_eval_context.namedregs); + free_namedregs(&global_eval_context.namedregsnxt); } @@ -1614,6 +1633,60 @@ shutdown_a_queue(BQUE **head, BQUE **tail) } } +void init_namedregs(HASHTAB *regs) { + hashinit(regs, 16, sizeof(char *)); +} + +void free_namedregs(HASHTAB *regs) { + clear_namedregs(regs); + hashfree(regs); +} + +void clear_namedregs(HASHTAB *regs) { + char *value; + + for(value = (char *) hash_firstentry(regs); value; value = (char *) hash_nextentry(regs)) + mush_free(value, "namedreg"); + + hashflush(regs, 16); +} + +void copy_namedregs(HASHTAB *dest, HASHTAB *src) { + char *key; + + for(key = hash_firstentry(src); key; key = hash_nextentry_key(src)) + set_namedreg(dest, key, get_namedreg(src, key)); +} + +void set_namedreg(HASHTAB *regs, const char *name, const char *value) { + char *key; + char *oldvalue; + + key = strupper(name); + + oldvalue = (char *) hashfind(key, regs); + if(oldvalue) { + mush_free(oldvalue, "namedreg"); + hashdelete(key, regs); + } + + hashadd(key, mush_strdup(value, "namedreg"), regs); +} + +const char *get_namedreg(HASHTAB *regs, const char *name) { + char *key; + char *value; + + key = strupper(name); + + value = (char *) hashfind(key, regs); + + if(value) + return value; + + return ""; +} + FUNCTION(fun_wait) { char tbuf[BUFFER_LEN], *tbp; const char *p; diff --git a/src/extmail.c b/src/extmail.c index 10aba79..6407907 100644 --- a/src/extmail.c +++ b/src/extmail.c @@ -2766,6 +2766,7 @@ filter_mail(dbref from, dbref player, char *subject, global_eval_context.wenv[j] = NULL; for (j = 0; j < NUMQ; j++) global_eval_context.renv[j][0] = '\0'; + clear_namedregs(&global_eval_context.namedregs); strcpy(arg, unparse_dbref(from)); global_eval_context.wenv[0] = arg; strcpy(arg2, subject); diff --git a/src/funmisc.c b/src/funmisc.c index 8757a60..2f254ce 100644 --- a/src/funmisc.c +++ b/src/funmisc.c @@ -175,8 +175,15 @@ FUNCTION(fun_setq) strcpy(global_eval_context.renv[qindex], args[n + 1]); if (n == 0 && !strcmp(called_as, "SETR")) safe_strl(args[n + 1], arglens[n + 1], buff, bp); - } else - safe_str(T("#-1 REGISTER OUT OF RANGE"), buff, bp); + } else { + if (*args[n] && !strpbrk(args[n], "|<>% \n\r\t")) { + set_namedreg(&global_eval_context.namedregs, args[n], args[n+1]); + if (n == 0 && !strcmp(called_as, "SETR")) + safe_strl(args[n + 1], arglens[n + 1], buff, bp); + } else { + safe_str(T("#-1 REGISTER OUT OF RANGE"), buff, bp); + } + } } } @@ -190,6 +197,8 @@ FUNCTION(fun_r) ((qindex = qreg_indexes[(unsigned char) args[0][0]]) != -1) && global_eval_context.renv[qindex]) safe_str(global_eval_context.renv[qindex], buff, bp); + else if (*args[0]) + safe_str(get_namedreg(&global_eval_context.namedregs, args[0]), buff, bp); else safe_str(T("#-1 REGISTER OUT OF RANGE"), buff, bp); } diff --git a/src/game.c b/src/game.c index d34fb0b..7df66d8 100644 --- a/src/game.c +++ b/src/game.c @@ -712,6 +712,8 @@ do_restart(void) global_eval_context.wnxt[j] = NULL; for (j = 0; j < NUMQ; j++) global_eval_context.rnxt[j] = NULL; + init_namedregs(&global_eval_context.namedregs); + init_namedregs(&global_eval_context.namedregsnxt); /* Initialize the regexp patterns to nothing */ global_eval_context.re_code = NULL; @@ -767,6 +769,8 @@ init_game_config(const char *conf) global_eval_context.renv[a][0] = '\0'; global_eval_context.rnxt[a] = NULL; } + clear_namedregs(&global_eval_context.namedregs); + clear_namedregs(&global_eval_context.namedregsnxt); /* set MUSH start time */ globals.start_time = time((time_t *) 0); @@ -1912,6 +1916,7 @@ do_dolist(dbref player, char *list, char *command, dbref cause, global_eval_context.wnxt[j] = global_eval_context.wenv[j]; for (j = 0; j < NUMQ; j++) global_eval_context.rnxt[j] = global_eval_context.renv[j]; + copy_namedregs(&global_eval_context.namedregsnxt, &global_eval_context.namedregs); bp = outbuf; if (flags & DOL_DELIM) list += 2; diff --git a/src/look.c b/src/look.c index 3db1408..41b6795 100644 --- a/src/look.c +++ b/src/look.c @@ -94,6 +94,7 @@ look_exits(dbref player, dbref loc, const char *exit_name) } for (j = 0; j < NUMQ; j++) global_eval_context.renv[j][0] = '\0'; + clear_namedregs(&global_eval_context.namedregs); bp = arg; DOLIST(thing, Exits(loc)) { if (((Light(loc) || Light(thing)) || !(Dark(loc) || Dark(thing))) @@ -261,6 +262,7 @@ look_contents(dbref player, dbref loc, const char *contents_name) } for (j = 0; j < NUMQ; j++) global_eval_context.renv[j][0] = '\0'; + clear_namedregs(&global_eval_context.namedregs); bp = arg; bp2 = arg2; DOLIST(thing, Contents(loc)) { @@ -1022,6 +1024,7 @@ do_inventory(dbref player) for(j = 0; j < NUMQ ; j++) global_eval_context.renv[j][0] = '\0'; + clear_namedregs(&global_eval_context.namedregs); bp = arg; bp2 = arg2; DOLIST(thing, Contents(player)) { diff --git a/src/parse.c b/src/parse.c index 95499df..157276e 100644 --- a/src/parse.c +++ b/src/parse.c @@ -738,6 +738,22 @@ process_expression(char *buff, char **bp, char const **str, switch (savec) { case 'Q': case 'q': + savec = **str; + if (!savec) + goto exit_sequence; + safe_chr(savec, buff, bp); + (*str)++; + if (savec == '<') { + for (savec = **str; savec && savec != '>'; savec = **str) { + safe_chr(savec, buff, bp); + (*str)++; + } + if(!savec) + goto exit_sequence; + safe_chr(savec, buff, bp); + (*str)++; + } + break; case 'V': case 'v': case 'W': @@ -883,10 +899,25 @@ process_expression(char *buff, char **bp, char const **str, if (!nextc) goto exit_sequence; (*str)++; - if ((qindex = qreg_indexes[(unsigned char) nextc]) == -1) - break; - if (global_eval_context.renv[qindex]) - safe_str(global_eval_context.renv[qindex], buff, bp); + if (nextc == '<') { + const char *tmp; + char regname[BUFFER_LEN]; + for(tmp = *str; *tmp && *tmp != '>'; tmp++) + ; + if(!*tmp || tmp == *str) { + (*str)--; + goto exit_sequence; + } + strncpy(regname, *str, tmp - *str); + regname[tmp - *str] = '\0'; + safe_str(get_namedreg(&global_eval_context.namedregs, regname), buff, bp); + *str = tmp + 1; + } else { + if ((qindex = qreg_indexes[(unsigned char) nextc]) == -1) + break; + if (global_eval_context.renv[qindex]) + safe_str(global_eval_context.renv[qindex], buff, bp); + } break; case 'R': case 'r': /* newline */ diff --git a/src/predicat.c b/src/predicat.c index 3141b91..73ccee7 100644 --- a/src/predicat.c +++ b/src/predicat.c @@ -327,6 +327,7 @@ real_did_it(dbref player, dbref thing, const char *what, const char *def, global_eval_context.wnxt[j] = myenv[j]; for (j = 0; j < NUMQ; j++) global_eval_context.rnxt[j] = NULL; + clear_namedregs(&global_eval_context.namedregsnxt); attribs_used = charge_action(player, thing, awhat) || attribs_used; orator = preserve_orator; return attribs_used; @@ -1057,6 +1058,7 @@ do_switch(dbref player, char *expression, char **argv, dbref cause, global_eval_context.wnxt[a] = global_eval_context.wenv[a]; for (a = 0; a < NUMQ; a++) global_eval_context.rnxt[a] = global_eval_context.renv[a]; + copy_namedregs(&global_eval_context.namedregsnxt, &global_eval_context.namedregs); /* now try a wild card match of buff with stuff in coms */ for (a = 1; diff --git a/src/prog.c b/src/prog.c index 11602c5..0714192 100644 --- a/src/prog.c +++ b/src/prog.c @@ -60,6 +60,7 @@ COMMAND(cmd_prog) DESC *d; int i, pflags = 0; char buf[BUFFER_LEN], *bp; + char *key; if (!arg_left) { notify(player, "Invalid arguments."); @@ -181,6 +182,12 @@ COMMAND(cmd_prog) } safe_chr('|', tbuf1, &tbp); } + for(key = hash_firstentry_key(&global_eval_context.namedregs); key; key = hash_nextentry_key(&global_eval_context.namedregs)) { + safe_str(key, tbuf1, &tbp); + safe_chr('|', tbuf1, &tbp); + safe_str(get_namedreg(&global_eval_context.namedregs, key), tbuf1, &tbp); + safe_chr('|', tbuf1, &tbp); + } tbp--; *tbp = '\0'; @@ -209,6 +216,7 @@ FUNCTION(fun_prog) dbref target, thing; char pflags = 0x0; int i; + char *key; target = match_result(executor, args[0], TYPE_PLAYER, MAT_EVERYTHING); if (!GoodObject(target) || !Connected(target)) { @@ -277,6 +285,13 @@ FUNCTION(fun_prog) } safe_chr('|', tbuf1, &tbp); } + for(key = hash_firstentry_key(&global_eval_context.namedregs); key; key = hash_nextentry_key(&global_eval_context.namedregs)) { + safe_str(key, tbuf1, &tbp); + safe_chr('|', tbuf1, &tbp); + safe_str(get_namedreg(&global_eval_context.namedregs, key), tbuf1, &tbp); + safe_chr('|', tbuf1, &tbp); + } + tbp--; *tbp = '\0'; @@ -460,6 +475,7 @@ prog_handler(DESC * d, char *input) char *tbuf, *bp; char *p_buf[NUMQ]; int rcnt, i; + char *key; if (!strcmp(input, "IDLE")) return 1; @@ -486,6 +502,13 @@ prog_handler(DESC * d, char *input) strcpy(global_eval_context.renv[i], p_buf[i]); global_eval_context.rnxt[i] = global_eval_context.renv[i]; } + + for (; i < (rcnt - 1); i+= 2) { + if (p_buf[i] && strlen(p_buf[i]) > 0 && p_buf[i+1] && strlen(p_buf[i+1]) > 0) { + set_namedreg(&global_eval_context.namedregs, p_buf[i], p_buf[i+1]); + set_namedreg(&global_eval_context.namedregsnxt, p_buf[i], p_buf[i+1]); + } + } } strcpy(buf, atr_value(d->pinfo.atr)); global_eval_context.wnxt[0] = input; @@ -501,6 +524,12 @@ prog_handler(DESC * d, char *input) } safe_chr('|', buf, &bp); } + for(key = hash_firstentry_key(&global_eval_context.namedregs); key; key = hash_nextentry_key(&global_eval_context.namedregs)) { + safe_str(key, buf, &bp); + safe_chr('|', buf, &bp); + safe_str(get_namedreg(&global_eval_context.namedregs, key), buf, &bp); + safe_chr('|', buf, &bp); + } bp--; *bp = '\0'; /* Now Save to XY_PROGENV */ diff --git a/src/unparse.c b/src/unparse.c index 02f14cc..59f2d91 100644 --- a/src/unparse.c +++ b/src/unparse.c @@ -212,6 +212,7 @@ nameformat(dbref player, dbref loc, char *tbuf1, char *defname) } for (j = 0; j < NUMQ; j++) global_eval_context.renv[j][0] = '\0'; + clear_namedregs(&global_eval_context.namedregs); strcpy(arg, unparse_dbref(loc)); global_eval_context.wenv[0] = arg; strcpy(arg2, defname); diff --git a/src/wild.c b/src/wild.c index c561f92..26b0056 100644 --- a/src/wild.c +++ b/src/wild.c @@ -459,6 +459,7 @@ wild_match_case(const char *RESTRICT s, const char *RESTRICT d, int cs) global_eval_context.wnxt[j] = (char *) NULL; for (j = 0; j < NUMQ; j++) global_eval_context.rnxt[j] = (char *) NULL; + clear_namedregs(&global_eval_context.namedregsnxt); return wild(s, d, 0, cs); } @@ -523,6 +524,7 @@ regexp_match_case(const char *RESTRICT s, const char *RESTRICT d, int cs) } for (j = 0; j < NUMQ; j++) global_eval_context.rnxt[j] = (char *) NULL; + clear_namedregs(&global_eval_context.namedregsnxt); for (i = 0; (i < 10) && (i < NUMARGS); i++) { pcre_copy_substring(d, offsets, subpatterns, i, wtmp[i], BUFFER_LEN); diff --git a/src/wiz.c b/src/wiz.c index 31b79c4..4205b1b 100644 --- a/src/wiz.c +++ b/src/wiz.c @@ -629,6 +629,7 @@ do_force(dbref player, const char *what, char *command) global_eval_context.wnxt[j] = global_eval_context.wenv[j]; for (j = 0; j < NUMQ; j++) global_eval_context.rnxt[j] = global_eval_context.renv[j]; + copy_namedregs(&global_eval_context.namedregsnxt, &global_eval_context.namedregs); if(ooref == NOTHING) { ooref = player; l = 1; -- 2.30.2