<HEAD><TITLE>discuss@charon: [1627] in "Coldmud discussion meeting"</TITLE>
<H1>[1627] in Coldmud discussion meeting</H1></HEAD>
<A HREF="/"><IMG SRC="/i-d.gif" ALT="root"></A>
<A HREF="?1627"><IMG SRC="/i-back.gif" ALT="meeting"></A>
<A HREF="/help.html"><IMG SRC="/i-help.gif" ALT="help"></A>
<A HREF="1"><IMG SRC="/i-first.gif" ALT="first"></A>
<A HREF="1626"><IMG SRC="/i-fref.gif" ALT="first in chain"></A>
<A HREF="1626"><IMG SRC="/i-pref.gif" ALT="previous in chain"></A>
<A HREF="1626"><IMG SRC="/i-prev.gif" ALT="previous"></A>
<A HREF="1628"><IMG SRC="/i-next.gif" ALT="next"></A>
<A HREF="1634"><IMG SRC="/i-nref.gif" ALT="next in chain"></A>
<A HREF="1640"><IMG SRC="/i-lref.gif" ALT="last in chain"></A>
<A HREF="1641"><IMG SRC="/i-last.gif" ALT="last"></A>
<HR><H2>Re: Genesis 1.1.9 - STABLE</H2>
<H3>daemon@ATHENA.MIT.EDU (Mon Oct  2 01:47:50 2000
)</H3>
<PRE>
Message-ID: &lt;39D81CA4.E22BFA91@geocities.com&gt;
Date: Mon, 02 Oct 2000 00:27:00 -0500
From: Allen Noe &lt;psyclone42@geocities.com&gt;
MIME-Version: 1.0
To: coldstuff@cold.org
Content-Type: multipart/mixed;
 boundary="------------D7BC7F13A4C5C616FD457A6A"
Reply-To: coldstuff@cold.org

This is a multi-part message in MIME format.
--------------D7BC7F13A4C5C616FD457A6A
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Brandon Gillespie wrote:
&gt; 
&gt; This is available.  There is not really anything notable here--primarily
&gt; cleanup.  It is just getting the stable branch up to date before I start
&gt; tossing changes into the development branch.  Amoung the changes to be
&gt; expected are method cache optimizations from Bruce.

It looks great, it compiles great, and it seems to run great too.

However I noticed a few things that didn't get in, so I'm (re)posting
the diffs I use. Separated into two patches for your convenience, the
stable one shouldn't break anything, the -dev one might, but I haven't
noticed anything.

They can apply together, against a clean 1.1.9, with a 3 line offset in
one.

In the stable one:
* html_escape needs to encode if there are doublequotes, otherwise
Bruce's added case won't be used. (me)
* $http.decode now returns a buffer; workaround for $http.decode("%1b")
and similar returning improper strings. (me)
* Corrected random(x)'s throw message for x &lt; 1 (me)
* Make method_bytecode() act like list_method(), specifically not
returning bytecode for methods on parent objects (me)
* Also fix a bug in method_bytecode where it checks the wrong variable.
(me)

In the dev one:
* Some method-cache stuff, if you're impatient. (Bruce)
* Have stack(1) not bother returning line number or pc. (me)
* Have method_bytecode() return jumps so if (1) { return 1; } return 0;
has different bytecode than if (1) { return 1; return 0; } (me)
* Add SYMBOL calling_method(), the same as stack()[2][3] (me)
* Add LIST explode_quoted(STRING), which is a native version of
ColdCore's $string.explode_quoted() (Jeremy Weatherford)
--------------D7BC7F13A4C5C616FD457A6A
Content-Type: text/plain; charset=us-ascii;
 name="my-stable.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="my-stable.patch"

diff -ur Genesis-1.1.9-STABLE/src/modules/web.c Genesis/src/modules/web.c
--- Genesis-1.1.9-STABLE/src/modules/web.c	Tue Jul 13 16:05:39 1999
+++ Genesis/src/modules/web.c	Sun Oct  1 23:47:24 2000
@@ -159,7 +159,7 @@
     len = string_length(in);
 
     /* incase they don't need it */
-    if (!memchr(s, '&lt;', len) &amp;&amp; !memchr(s, '&gt;', len) &amp;&amp; !memchr(s, '&amp;', len))
+    if (!memchr(s, '&lt;', len) &amp;&amp; !memchr(s, '&gt;', len) &amp;&amp; !memchr(s, '&amp;', len) &amp;&amp; !memchr(s, '\"', len))
         return string_dup(in);
 
     /* doh, they do.. */
@@ -188,7 +188,8 @@
 }
 
 NATIVE_METHOD(decode) {
-    cStr * str;
+    cStr * str, * ret;
+    cBuf * buf;
 
     INIT_1_ARG(STRING);
 
@@ -197,7 +198,12 @@
     CLEAN_STACK();
     anticipate_assignment();
 
-    RETURN_STRING(decode(string_prep(str, str-&gt;start, str-&gt;len)));
+    ret = decode(string_prep(str, str-&gt;start, str-&gt;len));
+    buf = buffer_new(ret-&gt;len);
+    memcpy(buf-&gt;s, ret-&gt;s, ret-&gt;len);
+    string_discard(ret);
+
+    RETURN_BUFFER(buf);
 }
 
 NATIVE_METHOD(encode) {
diff -ur Genesis-1.1.9-STABLE/src/ops/math.c Genesis/src/ops/math.c
--- Genesis-1.1.9-STABLE/src/ops/math.c	Tue Jul 13 16:13:52 1999
+++ Genesis/src/ops/math.c	Sun Oct  1 23:47:24 2000
@@ -276,7 +276,7 @@
 
     /* If INT1 is negative, throw ~range */
     if (INT1 &lt;= 0) {
-        cthrow(range_id, "Maximum value was less than 0.");
+        cthrow(range_id, "Maximum value is less than 1.");
         return;  
     }
  
diff -ur Genesis-1.1.9-STABLE/src/ops/object.c Genesis/src/ops/object.c
--- Genesis-1.1.9-STABLE/src/ops/object.c	Wed Nov 17 23:28:39 1999
+++ Genesis/src/ops/object.c	Sun Oct  1 23:47:24 2000
@@ -987,7 +987,7 @@
     if (!func_init_1(&amp;args, SYMBOL))
         return;
 
-    method = object_find_method(cur_frame-&gt;object-&gt;objnum, args[0].u.symbol, FROB_ANY);
+    method = object_find_method_local(cur_frame-&gt;object, args[0].u.symbol, FROB_ANY);
 
     /* keep these for later reference, if its already around */
     if (!method)
@@ -1012,7 +1012,7 @@
         }
 
         if (info-&gt;arg2) {
-            list = add_op_arg(list, info-&gt;arg1, ops[x], method);
+            list = add_op_arg(list, info-&gt;arg2, ops[x], method);
             x++;
         }
     }

--------------D7BC7F13A4C5C616FD457A6A
Content-Type: text/plain; charset=us-ascii;
 name="my-dev.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="my-dev.patch"

diff -ur Genesis-1.1.9-STABLE/src/data/object.c Genesis/src/data/object.c
--- Genesis-1.1.9-STABLE/src/data/object.c	Tue Jul 13 15:47:30 1999
+++ Genesis/src/data/object.c	Sun Oct  1 23:46:23 2000
@@ -145,9 +145,19 @@
     cList *children;
     cData *d, cthis;
     Obj *kid;
+    Long has_methods = 0, i = 0;
 
-    /* Invalidate the method cache. */
-    cur_stamp++;
+    do {
+        if (object-&gt;methods.tab[i].m) {
+            has_methods = 1;
+        }
+	i++;
+    } while (!has_methods &amp;&amp; (i &lt; object-&gt;methods.size));
+
+    /* Invalidate the method cache if object is not a method-less leaf object */
+    if ((list_length(object-&gt;children) != 0) || (has_methods)) {
+        cur_stamp++;
+    }
 
     /* remove the object name, if it has one */
     object_del_objname(object);
@@ -1085,9 +1095,6 @@
 Int object_del_method(Obj *object, Long name) {
     Int *indp, ind;
 
-    /* Invalidate the method cache. */
-    cur_stamp++;
-
     /* This is the index-thread equivalent of double pointers in a standard
      * linked list.  We traverse the list using pointers to the -&gt;next element
      * of the method pointers. */
@@ -1114,6 +1121,9 @@
 
 	    object-&gt;dirty = 1;
 
+	    /* Invalidate method cache */
+	    cur_stamp++;
+
 	    /* Return one, meaning the method was successfully deleted. */
 	    return 1;
 	}
@@ -1162,9 +1172,18 @@
     method = object_find_method_local(object, name, FROB_ANY);
     if (method == NULL)
         return -1;
+    if (method-&gt;m_access == access) {
+        /* yay, we don't have to do anything. let's go home. */
+        return access;
+    }
+    if ((method-&gt;m_access == MS_FROB) || (access == MS_FROB)) {
+        /*
+	 * only invalidate when changing to or from 'frob' access.
+	 */
+	cur_stamp++;
+    }
     method-&gt;m_access = access;
     object-&gt;dirty = 1;
-    cur_stamp++; /* to invalidate cached frob/!frob defaults */
     return access;
 }
 
diff -ur Genesis-1.1.9-STABLE/src/execute.c Genesis/src/execute.c
--- Genesis-1.1.9-STABLE/src/execute.c	Tue Jul 13 16:13:51 1999
+++ Genesis/src/execute.c	Sun Oct  1 23:46:23 2000
@@ -568,6 +568,33 @@
     return r;
 }
 
+cList * task_stack_2(void) {
+    cList * r;
+    cData   d,
+           * list;
+    Frame  * f;
+  
+    r = list_new(0);
+    d.type = LIST;
+    for (f = cur_frame; f; f = f-&gt;caller_frame) {
+
+        d.u.list = list_new(3);
+        list = list_empty_spaces(d.u.list, 3);
+
+        list[0].type = OBJNUM;
+        list[0].u.objnum = f-&gt;object-&gt;objnum;
+        list[1].type = OBJNUM;
+        list[1].u.objnum = f-&gt;method-&gt;object-&gt;objnum;
+        list[2].type = SYMBOL;
+        list[2].u.symbol = ident_dup(f-&gt;method-&gt;name);
+
+        r = list_add(r, &amp;d);
+        list_discard(d.u.list);
+    }
+
+    return r;
+}
+
 /*
 // ---------------------------------------------------------------
 */
diff -ur Genesis-1.1.9-STABLE/src/grammar.y Genesis/src/grammar.y
--- Genesis-1.1.9-STABLE/src/grammar.y	Tue Jul 13 15:47:29 1999
+++ Genesis/src/grammar.y	Sun Oct  1 23:46:23 2000
@@ -157,7 +157,8 @@
 %token F_CACHE_INFO F_BIND_FUNCTION F_UNBIND_FUNCTION F_ATOMIC
 %token F_METHOD_INFO F_ENCODE F_DECODE F_SIN F_EXP F_LOG F_COS
 %token F_TAN F_SQRT F_ASIN F_ACOS F_ATAN F_POW F_ATAN2 F_CONFIG F_ROUND
-%token F_FLUSH OP_HANDLED_FROB F_VALUE F_HANDLER
+%token F_FLUSH OP_HANDLED_FROB F_VALUE F_HANDLER F_CALLINGMETHOD
+%token F_EXPLODE_QUOTED
 
 /* Reserved for future use. */
 /*%token FORK*/
diff -ur Genesis-1.1.9-STABLE/src/include/execute.h Genesis/src/include/execute.h
--- Genesis-1.1.9-STABLE/src/include/execute.h	Tue Jul 13 16:05:03 1999
+++ Genesis/src/include/execute.h	Sun Oct  1 23:46:23 2000
@@ -215,6 +215,7 @@
 VMState *task_lookup(Long tid);
 cList * task_list(void);
 cList * task_stack(void);
+cList * task_stack_2(void);
 void run_paused_tasks(void);
 void bind_opcode(Int opcode, cObjnum objnum);
 
diff -ur Genesis-1.1.9-STABLE/src/include/functions.h Genesis/src/include/functions.h
--- Genesis-1.1.9-STABLE/src/include/functions.h	Tue Jul 13 15:47:31 1999
+++ Genesis/src/include/functions.h	Sun Oct  1 23:46:23 2000
@@ -157,6 +157,7 @@
 COLDC_FUNC(tasks);
 COLDC_FUNC(tick);
 COLDC_FUNC(stack);
+COLDC_FUNC(calling_method);
 COLDC_FUNC(method);
 COLDC_FUNC(this);
 COLDC_FUNC(definer);
diff -ur Genesis-1.1.9-STABLE/src/include/strutil.h Genesis/src/include/strutil.h
--- Genesis-1.1.9-STABLE/src/include/strutil.h	Tue Jul 13 13:15:00 1999
+++ Genesis/src/include/strutil.h	Sun Oct  1 23:46:23 2000
@@ -20,6 +20,7 @@
 cStr * strfmt(cStr * str, cData * args, Int argc);
 cList   * strexplode(cStr * str, char * sep, Int sep_len, Bool blanks);
 cList   * strsplit(cStr * str, cStr * regexp, Int flags);
+cList   * strexplodequoted(cStr * str);
 
 /* string flags */
 #define RF_NONE      0
diff -ur Genesis-1.1.9-STABLE/src/opcodes.c Genesis/src/opcodes.c
--- Genesis-1.1.9-STABLE/src/opcodes.c	Tue Jul 13 15:47:29 1999
+++ Genesis/src/opcodes.c	Sun Oct  1 23:46:23 2000
@@ -176,6 +176,7 @@
     { F_PAUSE,            "pause",                func_pause },
     { F_REFRESH,          "refresh",              func_refresh },
     { F_TICKS_LEFT,       "ticks_left",           func_ticks_left },
+    { F_CALLINGMETHOD,    "calling_method",       func_calling_method },
     { F_METHODOP,         "method",               func_method },
     { F_THIS,             "this",                 func_this },
     { F_DEFINER,          "definer",              func_definer },
@@ -275,6 +276,7 @@
     { F_MATCH_REGEXP,     "match_regexp",    func_match_regexp },
     { F_REGEXP,           "regexp",          func_regexp },
     { F_SPLIT,            "split",           func_split },
+    { F_EXPLODE_QUOTED,   "explode_quoted",  func_explode_quoted },
     { F_CRYPT,            "crypt",           func_crypt },
     { F_MATCH_CRYPTED,    "match_crypted",   func_match_crypted },
     { F_UPPERCASE,        "uppercase",       func_uppercase },
diff -ur Genesis-1.1.9-STABLE/src/ops/object.c Genesis/src/ops/object.c
--- Genesis-1.1.9-STABLE/src/ops/object.c	Wed Nov 17 23:28:39 1999
+++ Genesis/src/ops/object.c	Sun Oct  1 23:46:46 2000
@@ -957,7 +957,10 @@
             d.type = STRING;
             d.u.str = object_get_string(obj, op);
             break;
-        /* case JUMP: */ /* ignore JUMP */
+        case JUMP:
+            d.type = INTEGER;
+            d.u.val = op;
+            break;
         default:
             return out;
 #if DISABLED   /* none of these are used as args in op_table */
diff -ur Genesis-1.1.9-STABLE/src/ops/string.c Genesis/src/ops/string.c
--- Genesis-1.1.9-STABLE/src/ops/string.c	Sun Oct  1 16:35:31 2000
+++ Genesis/src/ops/string.c	Sun Oct  1 23:46:23 2000
@@ -566,3 +566,19 @@
     push_int(r);
 }
 
+COLDC_FUNC(explode_quoted) {
+    cData * args;
+    cList * exploded;
+
+    /* Accept a string to explode and an optional string for the word
+     * separator. */
+    if (!func_init_1(&amp;args, STRING))
+        return;
+
+    exploded = strexplodequoted(args[0].u.str);
+
+    /* Pop the arguments and push the list onto the stack. */
+    pop(1);
+    push_list(exploded);
+    list_discard(exploded);
+}
diff -ur Genesis-1.1.9-STABLE/src/ops/task.c Genesis/src/ops/task.c
--- Genesis-1.1.9-STABLE/src/ops/task.c	Tue Jul 13 13:51:02 1999
+++ Genesis/src/ops/task.c	Sun Oct  1 23:46:23 2000
@@ -152,6 +152,7 @@
 }
 
 /* ----------------------------------------------------------------- */
+/*
 void func_stack(void) {
     cList * list;
 
@@ -162,6 +163,34 @@
 
     push_list(list);
     list_discard(list);
+}
+*/
+
+void func_stack(void) {
+    cList *list;
+
+    INIT_0_OR_1_ARGS(INTEGER);
+
+    if (argc) {
+        list = task_stack_2();
+        pop(1);
+    } else {
+        list = task_stack();
+    }
+
+    push_list(list);
+    list_discard(list);
+}
+
+void func_calling_method() {
+    /* Accept no arguments, and push the name of the calling method. */
+    if (!func_init_0())
+        return;
+
+    if (cur_frame-&gt;caller_frame)
+        push_symbol(cur_frame-&gt;caller_frame-&gt;method-&gt;name);
+    else
+        push_int(0);
 }
 
 void func_method(void) {
diff -ur Genesis-1.1.9-STABLE/src/strutil.c Genesis/src/strutil.c
--- Genesis-1.1.9-STABLE/src/strutil.c	Tue Jul 13 16:13:51 1999
+++ Genesis/src/strutil.c	Sun Oct  1 23:46:23 2000
@@ -1085,3 +1085,35 @@
     return list;
 }
 
+cList * strexplodequoted(cStr * str) {
+    char     * s = string_chars(str),
+             * p = s,
+             * q;
+    Int        len = string_length(str);
+    cList   * list = list_new(0);
+    cStr * word;
+    cData     d;
+
+    d.type = STRING;
+
+    while (*p) {
+      while (*p == ' ')
+        p++;
+      if (*p == '"') {
+        p++;
+        q = p;
+        while (*q &amp;&amp; !(*q == '"' &amp;&amp; (*(q+1) == ' ' || !*(q+1))))
+          q++;
+        ADD_WORD((p, q-p));
+        p = q+1; /* after end quote */
+      } else if (*p) {
+        q = p;
+        while (*q &amp;&amp; (*q != ' ')) /* stop on space */
+          q++;
+        ADD_WORD((p, q-p));
+        p = q;
+      }
+    }
+
+    return list;
+}

--------------D7BC7F13A4C5C616FD457A6A--

</PRE>
