Lugaru's Epsilon
Programmer's
Editor

Context:
Epsilon User's Manual and Reference
   Primitives and EEL Subroutines
      . . .
      Operating System Primitives
         System Primitives
         Window System Primitives
         Timing
         Calling Windows DLLs
         Running a Process
      Control Primitives
         . . .
         Byte Arrays
         Memory Allocation
         The Name Table
         Built-in and User Variables
         Buffer-specific Variables
         . . .
      Input Primitives
         Keys
         The Mouse
         Window Events
         . . .
         Binding Primitives
      . . .

Previous   Up    Next
Memory Allocation  Primitives and EEL Subroutines   Built-in and User Variables


Epsilon User's Manual and Reference > Primitives and EEL Subroutines > Control Primitives >

The Name Table

int final_index()

Epsilon keeps track of all EEL variables, commands, subroutines, key tables, color schemes, and keyboard macros in its name table. Each of these items has an entry there that lists its name, type, value, and additional information. An EEL program can access the table using a numeric index, like an array index. The first valid index to the name table is 1, and the final_index( ) primitive returns the last valid index. The index is based on the order in which the names were defined.

All variables appear in the name table, including primitive variables. Primitive functions (like most of those defined in this chapter) and EEL's #define textual macros are not in the name table. A state file contains an exact copy of a name table (plus some additional information).

Each entry contains the name of the item, a type code, a debugging flag, a help file offset, and whatever information Epsilon needs internally to make use of the item. When executing an EEL program, Epsilon automatically uses the table to find the value of a variable, for example, or execute a command. You can manipulate the table with EEL functions.

int find_index(char *name)

There are two ways to get an index if you have the name of an item. The find_index( ) primitive takes an item name as a string and returns the index of that item, or 0 if there is no such item. If the item is an EEL command or subroutine, casting its function pointer to a short also yields the index. For example, (short) forward_word gives the index of the command forward-word if forward_word() has been declared previously in the source file the expression appears in.

char *name_name(int index)
int name_type(int index)      /* codes: */
#define NT_COMMAND     1      /* normal bytecode function */
#define NT_SUBR        2      /* hidden bytecode function */
#define NT_MACRO       3      /* keyboard macro */
#define NT_TABLE       4      /* key table */
#define NT_VAR         5      /* normal variable */
#define NT_BUFVAR      6      /* buffer-specific variable */
#define NT_WINVAR      7      /* window-specific variable */
#define NT_COLSCHEME   8      /* color scheme */
#define NT_BUILTVAR    9      /* built-in variable */
#define NT_AUTOLOAD    10     /* load cmd from file */
#define NT_AUTOSUBR    11     /* load subr from file */

The primitives name_name( ) and name_type( ) return the name and type of a table entry, respectively. They each take an index into the name table and return the desired information. The value returned by name_name( ) is only valid until the next call to this function. Copy the name if you want to preserve it.

The codes for name_type( ) are in the standard include file codes.h.

int try_calling(char *name)

The try_calling( ) primitive calls a subroutine or command if it exists and doesn't complain if the function does not exist. It takes the name of the function to call. It returns 0 if the function doesn't exist. The function it calls must not require arguments.

int call_with_arg_list(int func, char *argtypes, int intargs[],
                       char *strargs[], ?char **res)

The call_with_arg_list( ) primitive can call an EEL function that takes only integer and string parameters, specified by its name table index func. The caller must specify the types of the parameters to pass in argtypes, and supply the integer and string parameters in the arrays intargs and strargs, respectively. The argtypes value is a list of characters: "i" for an integer, or "s" for a string. For each "i", Epsilon uses the next entry in the intargs array, and for each "s", the strargs array.

If the EEL function returns an integer, the call_with_arg_list( ) primitive returns it. If it returns a character pointer, pass the address of a character pointer, and the primitive will fill it in with the return value.

The func parameter may refer to a keyboard macro if argtypes is empty.

int drop_name(char *name)

To delete an item from the name table, use the drop_name( ) primitive. It returns 0 if it deleted the name, 1 if there was no such name in the name table, and 2 if there was such a name but it couldn't be deleted because it is currently in use.

int replace_name(char *old, char *new)

The replace_name( ) primitive renames an item in the name table. It returns 0 if the name change was successful, 1 if the original name did not exist, and 2 if the name change was unsuccessful because another item had the new name already. Any references to the original item result in an error, unless you provide a new definition for it later.

Sometimes when writing an Epsilon extension, you may wish to redefine one of Epsilon's built-in subroutines (getkey( ), for example) to do something in addition to its usual action. You can, of course, simply modify the definition of the function, adding whatever you want. Unfortunately, if someone else gives you an extension that modifies the same function, it will overwrite your version. You'll have the same problem when you get a new version of Epsilon--you'll have to merge your change by hand.

#define REPLACE_FUNC(ext, func)  ....
        /* definition omitted */

Alternatively, you can create an extension that modifies the existing version of a function, even if it's already been modified. The trick is to replace it with a function that calls the original function. This can be done from a when_loading( ) function by using the replace_name( ) and drop_name( ) primitives, but eel.h defines a macro that does all of this. The REPLACE_FUNC() macro takes the name of the extension you're writing, and the name of the existing subroutine you want to replace. It doesn't really matter what the extension name is, just so long as no other extension uses it.

Here's an example. Suppose you're writing an extension that displays "Hello, world" whenever you start Epsilon. You've decided to name the extension "hello", and you want Epsilon's start_up( ) function to do the work. Here's what you do:

new_hello_start_up()    /* will be renamed to start_up */
{
   say("Hello, world");
   hello_start_up(); /* call old (which will have this name) */
}

REPLACE_FUNC("hello", "start-up")

Notice the steps: first you have to define a function with a name of the form new_<extension-name>_<replaced-function-name>. Make sure it calls a function named <extension-name>_<replaced-function-name>. Then do the REPLACE_FUNC( ), providing the two names. This will rename the current <replaced-function-name> to <extension-name>_<replaced-function-name>, then rename your function to <replaced-function-name>.



Previous   Up    Next
Memory Allocation  Primitives and EEL Subroutines   Built-in and User Variables


Lugaru Copyright (C) 1984, 2012 Lugaru Software Ltd. All Rights Reserved.