Implement named %q<registers>
authorAri Johnson <ari@theari.com>
Fri, 22 May 2009 00:43:32 +0000 (00:43 +0000)
committerAri Johnson <ari@theari.com>
Fri, 22 May 2009 00:43:32 +0000 (00:43 +0000)
13 files changed:
hdrs/externs.h
src/bsd.c
src/cque.c
src/extmail.c
src/funmisc.c
src/game.c
src/look.c
src/parse.c
src/predicat.c
src/prog.c
src/unparse.c
src/wild.c
src/wiz.c

index 2932d3211c7a0b3c64161c06cc115a62cc498727..f95f84187e816b5b825931716cbbf55a8234dc85 100644 (file)
@@ -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);
index 9d24fdcc1117ab47977b150553138550dd15bf97..6ac6c9616b1c243963c797eb95490898b00d98c3 100644 (file)
--- 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);
index 6723fb4c2ee12ede07027ab8c214d3283934c18b..1b45f81d81f830307244ca87ae6a7318029f98bd 100644 (file)
@@ -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;
index 10aba79a57eb70e087ec2b6b31e5f0ee542354f9..6407907c739e128edd4e64b68bf52cf82831a428 100644 (file)
@@ -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);
index 8757a6018be4a76954834d12c23c9b216972ac23..2f254ce98f80329e0b4bd17a00014a3ec92f7d01 100644 (file)
@@ -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);
 }
index d34fb0b2cb357f2a07fbadc0fa98af1d071420b4..7df66d81e8d85867e78bdb2954f3ab90b7b4e7e3 100644 (file)
@@ -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;
index 3db1408ff64f32a8c32bf9f544c77946d9ba8258..41b6795076b0bb3e4444d74d2a1e11217340abff 100644 (file)
@@ -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)) {
index 95499df583ee246778a8eb7703173370bb1d70a7..157276eb365037203e56633cad85e6c70415299a 100644 (file)
@@ -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 */
index 3141b9136699d7ae563ebc5fdab9852b87956060..73ccee775dc34aaac32d87c00d9b2f036c572bf7 100644 (file)
@@ -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;
index 11602c50ecd04579523f6c44c7e7992003e7dd67..07141923e13a896b373a28d0ea7765e2266c5a7f 100644 (file)
@@ -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 */
index 02f14ccf1352501a84fd6e43ecbc238f3181a70b..59f2d9126f747b59132ff59ea97ea289ebbf96b2 100644 (file)
@@ -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);
index c561f9237428a5ab3f85f41b08105742c7d7fe54..26b0056b3f36530f9891c004ab146f6de5d0ebaf 100644 (file)
@@ -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);
index 31b79c475f8d6a4cc319951ebed5d4f6766139ad..4205b1b6fcf44f950a0afe6d14da54275e19cdf0 100644 (file)
--- 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;