Lugaru's Epsilon Programmer's Editor 14b12
Context:
| Built-in and User Variables
|
|
Previous
|
Up
|
Next
|
The Name Table |
Primitives and EEL Subroutines |
Buffer-specific Variables |
Epsilon User's Manual and Reference >
Primitives and EEL Subroutines >
Control Primitives >
Built-in and User Variables
Variables that are automatically defined by Epsilon, and have no
definition in eel.h, are called built-in variables. These include
point, bufnum, and most of the primitive variables
described in this chapter. All such built-in variables have entries
in Epsilon's name table, so that you can see and set them using
commands like set-variable or set-any-variable.
Built-in variables have a name_type( ) code of
NT_BUILTVAR .
int get_num_var(int i)
set_num_var(int i, int value)
char *get_str_var(int i)
set_str_var(int i, char *value)
Epsilon has several primitives that let you get and set the value of
numeric and string global variables (including both built-in and
ordinary, user-defined variables). Each primitive takes a name table
index i . The get_num_var( ) and get_str_var( )
primitives return the numeric or string value (respectively) of the
indicated variable, while the set_num_var( ) and
set_str_var( ) primitives set the variable. If you provide
an index that doesn't refer to a variable of the correct type, the
setting functions do nothing, while the getting functions return zero.
(See the vartype( ) primitive below.) The set_str_var( )
primitive only operates on variables with a character pointer data
type, not on character arrays. Use varptr( ) below to modify
character arrays.
The set-variable command and similar functions
look for and try to call a function named
when_setting_varname() after setting a variable named
varname . For most variables a function with that name
doesn't exist, and nothing happens. The want-code-coloring
variable is an example of a variable with a when_setting()
function. Its when_setting() function sets various other
variables to match want-code-coloring's new value.
Any user attempts to set a variable (such as running
set-variable or loading a command file) will call such a
function, but an ordinary assignment statement in an EEL function
will not. If you write an EEL function that sets a variable with a
when_setting() function, you should call the function explicitly
after setting the variable.
int name_user(int i)
set_name_user(int i, int is_user)
For each global variable, built-in or not, Epsilon
records whether or not it is a "user" variable. Some commands such
as set-variable only show user variables. Otherwise, Epsilon
treats user variables the same as others. The name_user( )
primitive returns non-zero if the variable with the given name table
index is a user variable, and the set_name_user( ) primitive
sets whether a variable with a particular name table index is a user
variable.
user int my_var; // sample declaration
By default, variables you declare with EEL are all non-user
variables, hidden from the user. If the user is supposed to set a
variable directly in order to alter a command's behavior, put the
user keyword before its global variable definition to make
it a user variable. (In previous versions, Epsilon used a convention
that any non-user variables you defined had to start with an
underscore character, and all others were effectively user variables.
This convention still works: set-variable will still exclude
such variables from normal completion lists.)
int ptrlen(char *p, ?int in_bytes)
typedef struct eel_pointer { /* format of EEL pointer */
int base, size, value;
} EEL_PTR;
The ptrlen( ) primitive takes a pointer of any
type and returns the size in characters of the object it points to.
The value of ptrlen(p) is the lowest value i for which
((char *)p)[i] is an illegal dereference. If its optional second
argument is nonzero, it returns its count in bytes, not characters.
(Characters are 16 bits wide, while bytes are 8 bits wide.)
The EEL_PTR type,
defined in lowlevel.h, is a structure representing the internal format
of an EEL pointer (except for function pointers, which are represented
as short integers internally). An EEL pointer consists of a base, a
size, and a value. The base and value are standard system pointers,
and the size is an integer. Epsilon compares the three fields to
catch invalid pointer usage.
Whenever a function dereferences a pointer, Epsilon checks that the
fields are consistent. That is, it makes sure that value is
greater than or equal to base , and that value is less than
base +size . Epsilon will report an illegal dereference if
these conditions are not met.
When Epsilon constructs a pointer, it sets the base field to the start
of the block of storage within which the pointer points, and sets the
size field to the size of the block of storage, in bytes. Epsilon
then sets the value field to the actual address to which the pointer
points. For example, if an EEL pointer p points to the letter "c"
in the string "abcd" (which is terminated by a null character),
the size field of p will contain 10 (since five 16-bit characters
require ten bytes), the base field will point to the "a", and the
value field will point to the "c". Adding an integer to p will
change only the value field. Notice that the modified version of
p is "consistent" according to the rules above exactly when
dereferencing it would be legal: *(p - 2) , *(p - 1) ,
*p , *(p + 1) and *(p + 2) . The ptrlen( )
primitive above is often a better way to access pointer boundary
information, and is less likely to change in future versions.
#include "eel.h"
#include "lowlevel.h"
command eel_ptr_example()
{
char *hello = "Hello world";
char *p = hello + 6;
EEL_PTR *ptr = (EEL_PTR *) &p;
say("Hello's value is %x, size in bytes is %d, base is %x", hello);
say("P's value is %x, size in bytes is %d, base is %x", p);
say("P's value is %x, size in bytes is %d, base is %x",
ptr->value, ptr->size, ptr->base);
say("P's value is %x", ((int *)&p)[2]);
}
The above example shows various ways to display the internal structure
of pointers for debugging purposes.
char *varptr(int i)
int pointer_to_index(void *)
The varptr( ) primitive returns a pointer to any global
variable given its index in the name table. The pointer is always a
character pointer and should be cast to the correct type before it's
used. When varptr( ) is applied to a buffer-specific or
window-specific variable, Epsilon checks the use_default
variable to determine if a pointer to the default or current value
should be returned (see Buffer-specific Variables). This function
doesn't operate with built-in variables--use get_num_var( ) and
similar functions for these.
The pointer_to_index( ) primitive does the reverse. It takes
a pointer and checks to see if it refers to a global variable. If a
global variable is an array or structure, the pointer can point
anywhere within. It returns the name table index of the global
variable, or 0 if the pointer doesn't point to the contents of any
global variable.
int vartype(int i)
#define TYPE_BYTE 1 /* an 8-bit unsigned integer */
#define TYPE_CHAR 2 /* a 16-bit unsigned character */
#define TYPE_SHORT 3 /* a 16-bit signed integer */
#define TYPE_INT32 4 /* a 32-bit signed integer */
#define TYPE_INT 5 /* a 64-bit signed integer */
#define TYPE_CARRAY 6 /* character array */
#define TYPE_CPTR 7 /* character pointer */
#define TYPE_POINTER 8 /* contains pointers or spots */
#define TYPE_OTHER 9 /* none of the other categories */
int vartype_class(int i)
The vartype( )
primitive
returns information on the
type of a global variable (or buffer-specific or window-specific
variable). It takes the index of the variable in the name table and
returns one of the above codes if the variable's type is byte,
character, short, in32, integer, character array, or character
pointer. It returns TYPE_POINTER if the variable is a spot
or pointer, or a structure or union containing a spot or pointer. For
other types of variables, it returns TYPE_OTHER . It returns
0 if the given index doesn't refer to a variable.
The vartype_class( ) subroutine can be more convenient than
vartype( ). It returns 1 if the variable (specified by its
name table index) has a numeric type, 2 if it has a string type
(TYPE_CARRAY or TYPE_CPTR ), and 0 otherwise.
int new_variable(char *name, int type, int vtype, ?int length)
The new_variable( ) primitive provides a way to create a new
variable without having to load a bytecode file. The first argument
specifies the name of the variable. The second argument is a type code
of the kind returned by the name_type( ) primitive. The code must
be NT_VAR for a normal variable, NT_BUFVAR for a
buffer-specific variable, NT_WINVAR for a window-specific
variable, or NT_COLSCHEME for a color scheme. The third
argument is a type code of the kind returned by the vartype( )
primitive described above. This code must be one of the following:
TYPE_BYTE , TYPE_CHAR , TYPE_SHORT ,
TYPE_INT32 , TYPE_INT , or TYPE_CARRAY .
(This parameter is not used when defining a color scheme.) The last
argument is a size, which is used only for TYPE_CARRAY. The
primitive returns the name table index of the new variable, or -1
if it couldn't create the variable.
Previous
|
Up
|
Next
|
The Name Table |
Primitives and EEL Subroutines |
Buffer-specific Variables |
Epsilon Programmer's Editor 14b12 manual. Copyright (C) 1984, 2020 by Lugaru Software Ltd. All rights reserved.
|