    Provide a call() macro function which calls another function given its name

    The function invokes new code in interpret.c which calls the desired, named
    function with any remaining arguments to call(). In this way, the function
    is called using the same interpretation environment as call()'s invoker.

diff -ur nedit_official nedit_mod
diff -ur nedit_official/source/interpret.c nedit_mod/source/interpret.c
--- nedit_official/source/interpret.c	2007-01-30 14:51:11.000000000 +0100
+++ nedit_mod/source/interpret.c	2007-02-20 00:38:16.406467200 +0100
@@ -113,6 +113,7 @@
 static int power(void);
 static int concat(void);
 static int assign(void);
+static int callSubroutineFromSymbol(Symbol *sym, int nArgs);
 static int callSubroutine(void);
 static int fetchRetVal(void);
 static int branch(void);
@@ -1863,7 +1864,9 @@
 ** arguments and space for local variables are added to the stack, and the
 ** PC is set to point to the new function. For a built-in routine, the
 ** arguments are popped off the stack, and the routine is just called.
-**
+*/
+/*
+** For callSubroutine:
 ** Before: Prog->  [subrSym], nArgs, next, ...
 **         Stack-> argN-arg1, next, ...
 ** After:  Prog->  next, ...            -- (built-in called subr)
@@ -1871,21 +1874,13 @@
 **    or:  Prog->  (in called)next, ... -- (macro code called subr)
 **         Stack-> symN-sym1(FP), argArray, nArgs, oldFP, retPC, argN-arg1, next, ...
 */
-static int callSubroutine(void)
+static int callSubroutineFromSymbol(Symbol *sym, int nArgs)
 {
-    Symbol *sym, *s;
-    int i, nArgs;
+    Symbol *s;
+    int i;
     static DataValue noValue = {NO_TAG, {0}};
     Program *prog;
     char *errMsg;
-    
-    sym = PC->sym;
-    PC++;
-    nArgs = PC->value;
-    PC++;
-    
-    DISASM_RT(PC-3, 3);
-    STACKDUMP(nArgs, 3);
 
     /*
     ** If the subroutine is built-in, call the built-in routine
@@ -1989,6 +1984,74 @@
 }
 
 /*
+** Before: Prog->  [subrSym], nArgs, next, ...
+**         Stack-> argN-arg1, next, ...
+**
+** After:  Prog->  next, ...            -- (built-in called subr)
+**         Stack-> retVal?, next, ...
+**    or:  Prog->  (in called)next, ... -- (macro code called subr)
+**         Stack-> symN-sym1(FP), argArray, nArgs, oldFP, retPC, argN-arg1, next, ...
+*/
+static int callSubroutine(void)
+{
+    Symbol *sym;
+    int nArgs;
+    int n;
+
+    sym = PC++->sym;
+    nArgs = PC++->value;
+
+    DISASM_RT(PC-3, 3);
+    STACKDUMP(nArgs, 3);
+
+    return callSubroutineFromSymbol(sym, nArgs);
+}
+
+/*
+** Assumes a valid symbol. Invokes callSubroutineFromSymbol(), correcting nArgs
+** to match that routine's expectations. This allows a callMS() function to be
+** written in macro.c. If the caller has already "consumed" stack elements,
+** removeArgs must indicate how many.
+*/
+
+int OverlayRoutineFromSymbol(Symbol *sym, int nArgs, int removeArgs)
+{
+    DataValue *stackTop = StackP + nArgs - removeArgs;
+
+    if (removeArgs > 0) {
+        DataValue *from = StackP + removeArgs;
+        DataValue *to = StackP;
+        int n = nArgs - removeArgs;
+
+        nArgs = n;
+        while (n--) {
+            *to++ = *from++;
+        }
+    }
+
+    StackP = stackTop;
+    return callSubroutineFromSymbol(sym, nArgs);
+}
+
+/*
+** Assumes a valid prog. Wraps the program in a dummy symbol then calls
+** OverlayRoutineFromSymbol(). In this way a piece of compiled code can be
+** executed in the caller's context from a function in macro.c.
+*/
+
+int OverlayRoutineFromProg(Program *prog, int nArgs, int removeArgs)
+{
+    Symbol sym;
+
+    sym.type = MACRO_FUNCTION_SYM;
+    sym.name = "<overlaid function>";
+    sym.value.val.str.rep = (char *)prog;
+    sym.next = NULL;
+
+    return OverlayRoutineFromSymbol(&sym, nArgs, removeArgs);
+}
+
+/*
 ** This should never be executed, returnVal checks for the presence of this
 ** instruction at the PC to decide whether to push the function's return
 ** value, then skips over it without executing.
diff -ur nedit_official/source/interpret.h nedit_mod/source/interpret.h
--- nedit_official/source/interpret.h	2007-01-12 17:17:42.000000000 +0100
+++ nedit_mod/source/interpret.h	2007-02-20 00:03:25.149387200 +0100
@@ -158,6 +158,10 @@
 int ContinueMacro(RestartData *continuation, DataValue *result, char **msg);
 void RunMacroAsSubrCall(Program *prog);
 void PreemptMacro(void);
+
+int OverlayRoutineFromProg(Program *prog, int nArgs, int removeArgs);
+int OverlayRoutineFromSymbol(Symbol *sym, int nArgs, int removeArgs);
+
 char *AllocString(int length);
 char *AllocStringNCpy(const char *s, int length);
 char *AllocStringCpy(const char *s);
diff -ur nedit_official/source/macro.c nedit_mod/source/macro.c
--- nedit_official/source/macro.c	2007-01-26 00:51:56.000000000 +0100
+++ nedit_mod/source/macro.c	2007-02-20 00:04:26.878148800 +0100
@@ -403,6 +403,8 @@
         DataValue *result, char **errMsg);
 static int filenameDialogMS(WindowInfo* window, DataValue* argList, int nArgs,
         DataValue* result, char** errMsg);
+static int callMS(WindowInfo *window, DataValue *argList,
+        int nArgs, DataValue *result, char **errMsg);
 
 /* Built-in subroutines and variables for the macro language */
 static BuiltInSubr MacroSubrs[] = {lengthMS, getRangeMS, tPrintMS,
@@ -421,7 +423,8 @@
         rangesetSetColorMS, rangesetSetNameMS, rangesetSetModeMS,
         rangesetGetByNameMS,
         getPatternByNameMS, getPatternAtPosMS,
-        getStyleByNameMS, getStyleAtPosMS, filenameDialogMS
+        getStyleByNameMS, getStyleAtPosMS, filenameDialogMS,
+        callMS
     };
 #define N_MACRO_SUBRS (sizeof MacroSubrs/sizeof *MacroSubrs)
 static const char *MacroSubrNames[N_MACRO_SUBRS] = {"length", "get_range", "t_print",
@@ -440,7 +443,8 @@
         "rangeset_set_color", "rangeset_set_name", "rangeset_set_mode",
         "rangeset_get_by_name",
         "get_pattern_by_name", "get_pattern_at_pos",
-        "get_style_by_name", "get_style_at_pos", "filename_dialog"
+        "get_style_by_name", "get_style_at_pos", "filename_dialog",
+        "call"
     };
 static BuiltInSubr SpecialVars[] = {cursorMV, lineMV, columnMV,
         fileNameMV, filePathMV, lengthMV, selectionStartMV, selectionEndMV,
@@ -3477,6 +3481,31 @@
     return True;
 }
 
+/* 
+ * call(fnname, arg, ...)
+ */
+static int callMS(WindowInfo *window, DataValue *argList,
+        int nArgs, DataValue *result, char **errMsg)
+{
+    char stringStorage[TYPE_INT_STR_SIZE(int)];
+    Symbol *sym;
+    char *fnname;
+
+    if (nArgs < 1) {
+        *errMsg = "subroutine %s called without arguments";
+        return False;
+    }
+    if (!readStringArg(argList[0], &fnname, stringStorage, errMsg)) {
+        return False;
+    }
+    sym = LookupSymbol(fnname);
+    if (!sym) {
+        *errMsg = "subroutine name invalid";
+        return False;
+    }
+    return OverlayRoutineFromSymbol(sym, nArgs, 1);
+}
+
 /* T Balinski */
 static int listDialogMS(WindowInfo *window, DataValue *argList, int nArgs,
       DataValue *result, char **errMsg)
diff -ur nedit_official/source/macro.h nedit_mod/source/macro.h
--- nedit_official/source/macro.h	2004-11-09 22:58:44.000000000 +0100
+++ nedit_mod/source/macro.h	2007-02-20 00:05:33.904528000 +0100
@@ -28,7 +28,7 @@
 #ifndef NEDIT_MACRO_H_INCLUDED
 #define NEDIT_MACRO_H_INCLUDED
 
-#include "nedit.h"
+#include "interpret.h"
 
 #include <X11/Intrinsic.h>
 
