1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
|
/* $Header: d:/cvsroot/tads/tads3/vmbif.h,v 1.2 1999/05/17 02:52:29 MJRoberts Exp $ */
/*
* Copyright (c) 1998, 2002 Michael J. Roberts. All Rights Reserved.
*
* Please see the accompanying license file, LICENSE.TXT, for information
* on using and copying this software.
*/
/*
Name
vmbif.h - built-in function interface
Function
Provides the interface to built-in function sets.
The host application environment may provide more than one set of
built-in functions. Each function set is identified by a universally
unique identifier; the program image specifies one or more function
sets using these identifiers and maps each set to an image-specific
index. At run-time, the byte-code program calls built-in functions
by specifying a function set index and a function index within the
set.
A particular function set may use more than one universal identifier,
because of version evolution. If new functions are added to a function
set, the new function set can continue to use its original universal
identifier, as long as the function set continues to provide the
original set of functions as a subset of its new vector, and as long
as the functions in the original set are at the same index positions
in the modified function set.
Notes
Modified
12/05/98 MJRoberts - Creation
*/
#ifndef VMBIF_H
#define VMBIF_H
#include "t3std.h"
#include "vmglob.h"
#include "vmtype.h"
/* ------------------------------------------------------------------------ */
/*
* Image function set table. We maintain one global function set table,
* which we create when we load the image file.
*/
class CVmBifTable
{
public:
/*
* Create a table with a given number of initial entries. The table
* may be expanded in the future if necessary, but if the caller can
* predict the maximum number of entries required, we can
* preallocate the table at its final size and thus avoid the
* overhead and memory fragmentation of expanding the table.
*/
CVmBifTable(size_t init_entries);
/* delete the table */
~CVmBifTable();
/* clear all entries from the table */
void clear();
/*
* Add an entry to the table, given the function set identifier (a
* string giving the universally unique name for the function set).
* Fills in the next available slot. Throws an error if the
* function set is not present in the system. A function set may
* not be present because it's a newer version than this
* implementation provides, or because this particular host
* application environment does not provide the function set.
*/
void add_entry(const char *func_set_id);
/* get the total number of entries in the table */
size_t get_count() const { return count_; }
/* call the given function from the given function set */
void call_func(VMG_ uint set_index, uint func_index, uint argc);
private:
/*
* Ensure we have space for a given number of entries, allocating
* more if necessary. If we must allocate more space, we'll
* increase the current allocation size by at least the given
* increment (more if necessary to bring it up to the required
* size).
*/
void ensure_space(size_t entries, size_t increment);
/*
* Add an unresolved function set to the table, or throw an error if
* this isn't allowed. If we require resolution of function sets at
* load time, this should simply throw an error; otherwise, this
* should make a null entry in the function set table so that we can
* recognize the missing function set if one of its functions is
* ever invoked.
*/
void add_entry_unresolved(const char *func_set_id);
/* the table array - we keep an array of pointers */
struct vm_bif_entry_t **table_;
/*
* Name array - this is a list of the global function set names;
* each entry corresponds to the entry of the table_ array at the
* same index. We use this only for call-time resolution, so that
* we can report the name of an unavailable function set when a
* function from the unavailable set is invoked.
*/
char **names_;
/* number of entries defined in the table */
size_t count_;
/* number of entries allocated for the table */
size_t alloc_;
};
/* ------------------------------------------------------------------------ */
/*
* Function set table entry. This contains information on the function
* set at one index in the table.
*/
struct vm_bif_entry_t
{
/*
* Function set identifier - a string of 7-bit ASCII characters, one
* byte per character, in the range 32 to 126 inclusive, of length 1
* to 255 characters, null-terminated.
*/
const char *func_set_id;
/* number of functions in the function set */
size_t func_count;
/*
* Function vector. Each function has a common C interface, because
* the functions take arguments and return values on the VM stack.
* The order of the functions within the vector is defined by the
* function set specification; a function set which uses a
* particular universal identifier must always conform to the
* specification for that universal identifier.
*
* For each function, 'argc' is the number of actual parameters
* passed to the function by the caller. The function receives its
* parameters from the VM stack; the first argument is at the top of
* the stack, the second argument is the next item on the stack, and
* so on. The function must remove all of the arguments from the
* stack before returning, and must push a return value if
* appropriate.
*/
void (**func)(VMG_ uint argc);
};
/* ------------------------------------------------------------------------ */
/*
* Base class for function set collections. This class provides some
* utility functions that intrinsics might find useful.
*/
class CVmBif
{
public:
/*
* check arguments; throws an error if the argument count doesn't
* match the given value
*/
static void check_argc(VMG_ uint argc, uint needed_argc);
/*
* check arguments; throws an error if the argument count is outside
* of the given range
*/
static void check_argc_range(VMG_ uint argc,
uint argc_min, uint argc_max);
/* pop an integer/long value */
static int pop_int_val(VMG0_);
static int pop_long_val(VMG0_);
/* pop a true/nil logical value */
static int pop_bool_val(VMG0_);
/* pop an object ID value */
static vm_obj_id_t pop_obj_val(VMG0_);
/* pop a property ID value */
static vm_prop_id_t pop_propid_val(VMG0_);
/*
* Pop a string or list value, returning a pointer to the
* string/list data. If the value is a constant string or constant
* list, as appropriate, we'll return the constant pool pointer; if
* the value is an object of metaclass String or List, as
* appropriate, we'll return the metaclass data. Throws an error if
* the value is of any other type.
*/
static const char *pop_str_val(VMG0_);
static const char *pop_list_val(VMG0_);
/*
* Pop a null-terminated string into the given buffer. If the
* string is too long for the buffer, we'll truncate it to the given
* size.
*/
static void pop_str_val_buf(VMG_ char *buf, size_t buflen);
/*
* Pop a null-terminated string into the given buffer, converting
* the string to the filename character set. Null-terminates the
* resulting string.
*/
static void pop_str_val_fname(VMG_ char *buf, size_t buflen);
/*
* Pop a null-terminated string into the given buffer, converting the
* string to the UI character set. Null-terminates the resulting
* string. If the given buffer is null, we'll allocate a buffer with
* t3malloc() and return it; the caller is responsible for freeing the
* buffer with t3free(). In any case, returns the buffer into which we
* store the results.
*/
static char *pop_str_val_ui(VMG_ char *buf, size_t buflen);
/* create a string object from a C-style string in the UI character set */
static vm_obj_id_t str_from_ui_str(VMG_ const char *str);
static vm_obj_id_t str_from_ui_str(VMG_ const char *str, size_t len);
/*
* Return a value
*/
static void retval(VMG_ const struct vm_val_t *val);
static void retval_nil(VMG0_);
static void retval_true(VMG0_);
static void retval_bool(VMG_ int val);
static void retval_int(VMG_ long val);
static void retval_obj(VMG_ vm_obj_id_t obj);
static void retval_prop(VMG_ vm_prop_id_t prop);
static void retval_str(VMG_ const char *str);
static void retval_str(VMG_ const char *str, size_t len);
static void retval_ui_str(VMG_ const char *str);
static void retval_ui_str(VMG_ const char *str, size_t len);
static void retval_fnptr(VMG_ pool_ofs_t func);
};
#endif /* VMBIF_H */
|