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