1 /* 2 * $Id: yapi.h,v 1.20 2010-07-04 23:07:05 dhmunro Exp $ 3 * API for interfacing yorick packages to the interpreter 4 * - yorick package source should not need to include anything 5 * not here or in the play headers 6 */ 7 /* Copyright (c) 2005, The Regents of the University of California. 8 * All rights reserved. 9 * This file is part of yorick (http://yorick.sourceforge.net). 10 * Read the accompanying LICENSE file for details. 11 */ 12 13 #ifndef YAPI_H 14 #define YAPI_H 15 16 #include "plugin.h" 17 18 typedef char *ystring_t; 19 typedef void *ypointer_t; 20 typedef void ybuiltin_t(int argc); 21 22 BEGIN_EXTERN_C 23 /* 24 The interpreter can only call compiled functions with this prototype: 25 void my_builtin(int argc); 26 You can check whether my_builtin was invoked as a subroutine (so that 27 its return value is discarded) or a function (so that its return value 28 is used) with 29 */ 30 PLUG_API int yarg_subroutine(void); 31 /* 32 The argc arguments are on the interpreter stack. When you return 33 from my_builtin, the top of the stack becomes the return value of your 34 function. This API refers to elements on the stack by an index iarg; 35 iarg=0 means the top of the stack, iarg=1 is the second stack element, 36 iarg=2 is the third, and so on down to iarg=argc-1. (The my_builtin 37 function itself is normally at iarg=argc when the interpreter calls 38 the function.) On entry to my_builtin, its arguments are in reverse 39 order on the stack (in other words, the interpreter has pushed them 40 onto the stack in order), so that iarg=argc-1 is the first argument, 41 and iarg=0 is the last argument. However, if your function accepts 42 keywords, the keywords will be randomly interspersed with the 43 positional arguments, and you must use the yarg_kw function in order 44 to parse the argument list. 45 */ 46 PLUG_API void yarg_kw_init(char **knames, long *kglobs, int *kiargs); 47 PLUG_API int yarg_kw(int iarg, long *kglobs, int *kiargs); 48 /* 49 To use yarg_kw, declare knames and kglobs as static arrays: 50 static char *knames[NKEYS+1] = { "keyname1", "keyname2", ..., 0 }; 51 static long kglobs[NKEYS+1]; 52 The kiargs array is an automatic (local) array 53 int kiargs[NKEYS]; 54 You must call yarg_kw_init before the first call to yarg_kw. If 55 kglobs[0]=0 (as it will be with the above static definition), then 56 yarg_kw_init initializes it to [NKEYS, index1, index2, ...], where 57 indexN is the global symbol table index corresponding to the variable 58 named "keynameN". If kglobs[0] != 0, yarg_kw_init ignores knames. 59 The yarg_kw_init function always initializes all kiargs[i] to -1. 60 Beginning with iarg=argc-1, you call 61 iarg = yarg_kw(iarg, kglobs, kiargs); 62 If the return iarg>=0, it represents the first positional argument; 63 process it, then decrement iarg and call yarg_kw again, repeating this 64 process until iarg<0. At this point you have processed all the 65 positional arguments, and yarg_kw has stored the iarg value for any 66 keyword arguments in the kiargs array. That is, kiargs[i] will be the 67 iarg corresponding to keyword knames[i], or -1 if that keyword was not 68 present. 69 70 An alternative more primitive function yarg_key simply returns the 71 index of a keyword in the global symbol table, or -1 if iarg is 72 positional. If the return value is not -1, then iarg-1 is the 73 corresponding key value, and you can continue parsing the argument 74 list with iarg-2. 75 */ 76 PLUG_API long yarg_key(int iarg); 77 /* 78 Several other functions are supplied to test stack elements. The nil 79 test is the same as the interpreted is_void, rank returns -1 if not an 80 array, otherwise its dimensionality, number returns 0 if not a number, 81 1 if integer, 2 if floating point, or 3 if complex. The string test 82 returns 0 if iarg is not a string, 1 if it is a scalar string, 2 if it 83 is a string array. The func test is the same as is_func. The typeid 84 returns the typeid as listed above, or some other value for internal 85 objects. The scratch test returns 1 if iarg is an array which will be 86 destroyed when this stack element is dropped (such an array can be 87 reused as a return value). The list test is the same as is_list. 88 The yarg_true function returns 1 whenever if(x) would be true. 89 */ 90 PLUG_API int yarg_nil(int iarg); 91 PLUG_API int yarg_rank(int iarg); 92 PLUG_API int yarg_number(int iarg); 93 PLUG_API int yarg_string(int iarg); 94 PLUG_API int yarg_func(int iarg); 95 PLUG_API int yarg_typeid(int iarg); 96 PLUG_API int yarg_scratch(int iarg); 97 PLUG_API int yarg_list(int iarg); 98 PLUG_API int yarg_true(int iarg); 99 /* 100 There are ten possible array data types, internally identified by the 101 typeid value 0-9. The char, short, int, long, float, complex, string, 102 and pointer types are primitive; struct types are built up from 103 combinations of the primitive types and other structs. A typeid 104 greater than 9 represents a non-array internal data type, which in 105 general is beyond the scope of this API for yorick packages. 106 */ 107 #define Y_CHAR 0 108 #define Y_SHORT 1 109 #define Y_INT 2 110 #define Y_LONG 3 111 #define Y_FLOAT 4 112 #define Y_DOUBLE 5 113 #define Y_COMPLEX 6 114 #define Y_STRING 7 115 #define Y_POINTER 8 116 #define Y_STRUCT 9 117 /* 118 The typeid of six other interpreted objects may be useful. Note that 119 a Y_STREAM is a binary file, not a text file. 120 */ 121 #define Y_RANGE 10 122 #define Y_VOID 12 123 #define Y_FUNCTION 13 124 #define Y_BUILTIN 14 125 #define Y_STRUCTDEF 15 126 #define Y_STREAM 16 127 #define Y_OPAQUE 17 128 /* 129 Arrays can have from 0 (scalar) to Y_DIMSIZE-1 dimensions, except for 130 complex and struct arrays, which are limited to Y_DIMSIZE-2 131 dimensions. 132 */ 133 #define Y_DIMSIZE 11 134 /* 135 Dimension lists in this API have the same format as the interpreted 136 dimsof function, that is, [rank, len1, len2, ...], where rank is the 137 number of dimensions (zero for a scalar), and lenN is the length of 138 the Nth dimension, with len1 incrementing fastest in memory, len2 next 139 fastest, and so on. Functions returning dims expect it to be 140 declared like this: 141 long dims[Y_DIMSIZE]; 142 Functions which accept dims as input, on the other hand, can accept 143 a dims array shorter than Y_DIMSIZE, if their rank is lower than the 144 maximum. 145 146 Next are a set of routines for retrieving usable data from the stack. 147 The ygets functions return scalar values, while ygeta functions return 148 array values. The ygeta functions have two output arguments: If ntot 149 is non-zero, *ntot is set to the total number of array elements, and 150 if dims is non-zero, dims[0] is set to rank and dims[1:rank] are set 151 to the dimension lengths. As noted above, dims should be dimensioned 152 using Y_DIMSIZE (although by checking yarg_rank first, you could 153 safely use a smaller dims). Except as noted, all the yget functions 154 perform type conversions as necessary to force the argument to the 155 requested data type. The sole exceptions are ygets_l and ygets_d, 156 which will not demote the type, although they will promote it. In all 157 cases, if iarg cannot be convrted to the requested type, or if it is 158 not a scalar in a ygets, YError will be called and the function will 159 never return. If you care, you need to use the query functions first. 160 */ 161 PLUG_API long ygets_l(int iarg); 162 PLUG_API double ygets_d(int iarg); 163 PLUG_API ystring_t ygets_q(int iarg); 164 PLUG_API ypointer_t ygets_p(int iarg); 165 #define ygets_c(iarg) ((char)ygets_l(iarg)) 166 #define ygets_uc(iarg) ((unsigned char)ygets_l(iarg)) 167 #define ygets_s(iarg) ((short)ygets_l(iarg)) 168 #define ygets_i(iarg) ((int)ygets_l(iarg)) 169 #define ygets_f(iarg) ((float)ygets_d(iarg)) 170 171 PLUG_API char *ygeta_c(int iarg, long *ntot, long *dims); 172 #define ygeta_uc (unsigned char *)ygeta_c 173 PLUG_API short *ygeta_s(int iarg, long *ntot, long *dims); 174 PLUG_API int *ygeta_i(int iarg, long *ntot, long *dims); 175 PLUG_API long *ygeta_l(int iarg, long *ntot, long *dims); 176 PLUG_API float *ygeta_f(int iarg, long *ntot, long *dims); 177 PLUG_API double *ygeta_d(int iarg, long *ntot, long *dims); 178 PLUG_API double *ygeta_z(int iarg, long *ntot, long *dims); 179 PLUG_API ystring_t *ygeta_q(int iarg, long *ntot, long *dims); 180 PLUG_API ypointer_t *ygeta_p(int iarg, long *ntot, long *dims); 181 /* 182 Two ygeta functions do not return a specific data type: ygeta_dz 183 returns either a double (possibly promoting its argument) or a 184 complex, and yget_any returns any array (never converting its type). 185 */ 186 PLUG_API double *ygeta_dz(int iarg, long *ntot, long *dims, int *is_z); 187 PLUG_API void *ygeta_any(int iarg, long *ntot, long *dims, int *the_typeid); 188 /* 189 The ygeta_coerce function allows you to convert a numeric array to any 190 other numeric data type, after you have retrieved it using ygeta_any. 191 The arguments except for new_typeid must be returned by a previous 192 call to ygeta_any. 193 The yarg_reform function permits you to change the dimensionality 194 of an array without reallocating it; the new dims must have the 195 same total element count as the old dims. 196 */ 197 PLUG_API void *ygeta_coerce(int iarg, void *old_data, long ntot, long *dims, 198 int old_typeid, int new_typeid); 199 PLUG_API int yarg_reform(int iarg, long *dims); 200 /* 201 Finally, the yget_range function returns the mn:mx:step for an index 202 range, its return value is the union of a set of flags (or 0 if iarg 203 is not an index range). MMMARK is the + matrix multiply marker, which 204 is almost certainly a syntax error in any other context, PSEUDO is the 205 - pseudo-range index, RUBBER is the .. index, RUBBER1 is the * index, 206 and NULLER is the result of where(0). The Y_MIN_DFLT and Y_MAX_DFLT 207 are or-ed on if the minimum or maximum is defaulted; there is no flag 208 for a default step, so there is no way to tell the difference between 209 x(:) and x(::1). 210 */ 211 PLUG_API int yget_range(int iarg, long min_max_step[3]); 212 #define Y_MMMARK 2 213 #define Y_PSEUDO 3 214 #define Y_RUBBER 4 215 #define Y_RUBBER1 5 216 #define Y_NULLER 6 217 #define Y_MIN_DFLT 16 218 #define Y_MAX_DFLT 32 219 /* 220 There is also a family of ypush functions which create and push new 221 items onto the top of the stack. Note that this changes the numbering 222 of the iarg; the new array will always be at iarg=0, and everything 223 else will have one larger iarg than before. The interpreter always 224 ensures that the stack has space for at least 8 new elements before 225 calling any compiled builtin function. If you need more than 8 stack 226 elements, you must call ypush_check to prevent stack overflow; its 227 argument is the number of new elements you plan to create. 228 */ 229 PLUG_API void ypush_check(int n); 230 /* 231 In order to push a nil [] or one of the three high-performance scalar 232 types, just call one of the four routines with the value you want to 233 push. 234 */ 235 PLUG_API void ypush_nil(void); 236 237 PLUG_API void ypush_int(int value); 238 PLUG_API void ypush_long(long value); 239 PLUG_API void ypush_double(double value); 240 /* 241 In order to push an array onto the stack, use one of these functions; 242 dims=0 is acceptable for pushing a scalar value. The arrays are 243 always initialized to zero; you fill in the values after the ypush in 244 this case. 245 */ 246 PLUG_API char *ypush_c(long *dims); 247 #define ypush_uc (unsigned char *)ypush_c 248 PLUG_API short *ypush_s(long *dims); 249 PLUG_API int *ypush_i(long *dims); 250 PLUG_API long *ypush_l(long *dims); 251 PLUG_API float *ypush_f(long *dims); 252 PLUG_API double *ypush_d(long *dims); 253 PLUG_API double *ypush_z(long *dims); 254 PLUG_API ystring_t *ypush_q(long *dims); 255 PLUG_API ypointer_t *ypush_p(long *dims); 256 257 PLUG_API void ypush_range(long min_max_step[3], int flags); 258 /* 259 The ypush_ptr function allows you to push the pointee (object pointed to) 260 corresponding to a ypointer_t pointer onto the stack, where you can use 261 the yarg_* or ygeta_any functions to query its data type and dimensions. 262 The return value is the typeid and the number of elements is also returned, 263 in anticipation of at least those simple queries. 264 */ 265 PLUG_API int ypush_ptr(ypointer_t ptr, long *number); 266 /* 267 You can also create scratch space on the stack. If your function 268 faults (or run long enough that the user types C-c to abort it), 269 anything you allocate that is not on the interpreted stack will be 270 lost, causing a memory leak. The ypush_scratch function is a 271 protected malloc; you can optionally provide an on_free which will be 272 invoked to do any cleanup; the on_free function must not attempt to 273 free the object itself - that will happen automatically after on_free. 274 */ 275 PLUG_API void *ypush_scratch(unsigned long size, void (*on_free)(void *)); 276 /* 277 Two simple stack manipulation functions, yarg_drop discarding the top 278 n stack elements, and yarg_swap for interchanging stack elements 279 (generally to set up for yarg_drop). As long as you make sure your 280 return value is at the top of the stack when you return from 281 my_builtin, you probably will not need these. 282 */ 283 PLUG_API void yarg_drop(int n); 284 PLUG_API void yarg_swap(int iarg1, int iarg2); 285 /* 286 The yarg_dims function retrieves argument dimensions, optionally 287 checking for conformability with a cfmdims model. It returns -1 288 on failure (either because iarg is not an array or because cfmdims 289 was specified and it is not conformable), 0 on success if cfmdims=0, 290 and the same return value as yarg_conform(dims, cfmdims, cfmdims) 291 if cfmdims was specified. Note that cfmdims is both an input and 292 an output to yarg_dims (unlike yarg_conform, where it is an output). 293 294 The yarg_conform routine checks array conformability. The return 295 argument of yarg_conform is the cfmdims dimension list of the result 296 of a binary operation on arrays of dims1 and dims2- its return value 297 is -1 if dims1 and dims2 are not conformable, or the union of zero to 298 three of the flags Y_1_BCAST, Y_2_BCAST, Y_1_EXTEND, or Y_2_EXTEND. 299 If the Y_1_BCAST flags is set, it means that one or more of the dims1 300 dimensions has length 1 and the corresponding dims2 dimension has 301 length>1. The Y_1_EXTEND flag means that the rank of dims1 is lower 302 than the rank of dims2; ordinarily, this also means that the Y_1_BCAST 303 flag will be set, but if all the trailing dimensions of dims2 have 304 length 1, Y_1_EXTEND could be set while Y_1_BCAST was not. The 305 cfmdims array can be the same as dims1 or dims2, in which case the 306 original dimension list is overwritten. If cfmdims=0, the check is 307 performed without returning the result dimension list. In the case 308 309 The yarg_bcast routine broadcasts an array to a larger size. The 310 return value of yarg_bcast is 0 if the broadcast is possible, non-zero 311 on a conformability error. (The case that dims1 or dims2 requires no 312 broadcast, but has lower rank than the result is a no-op.) 313 */ 314 PLUG_API int yarg_dims(int iarg, long *dims, long *cfmdims); 315 PLUG_API int yarg_conform(long *dims1, long *dims2, long *cfmdims); 316 #define Y_1_BCAST 1 317 #define Y_1_EXTEND 2 318 #define Y_2_BCAST 4 319 #define Y_2_EXTEND 8 320 #define Y_12_NOT 16 321 PLUG_API int yarg_bcast(int iarg, long *newdims); 322 /* 323 Interpreted variables are generally either on the stack, or in the 324 global symbol table (even variables local to an interpreted function 325 are in the global symbol table when the function is active - the 326 corresponding external variables are pushed onto the stack until the 327 function returns). Global symbols are identified by their index in 328 the symbol table, which never changes and corresponds to a particular 329 name. The yfind_name function returns the variable name corresponding 330 to an index, while yfind_global returns the index corresponding to a 331 given name (len=0 means the name is 0-terminated), or -1 if there is 332 no such variable. The yget_global function is like yfind_global, 333 except it creates the variable (initializing its value to nil []) if 334 it does not exist. The ypush_global function pushes a global variable 335 onto the stack. The yput_global function sets a global variable from 336 the stack, discarding any previous value. 337 */ 338 PLUG_API char *yfind_name(long index); 339 PLUG_API long yfind_global(const char *name, long len); 340 PLUG_API long yget_global(const char *name, long len); 341 PLUG_API int ypush_global(long index); 342 PLUG_API void yput_global(long index, int iarg); 343 /* 344 You may need to use some of your arguments as output variables, like 345 interpreted function parameters declared as &x. To do this, you need 346 to call yget_ref on the corresponding iarg before using any other 347 function to retrieve the associated data. If iarg was a simple 348 variable reference, then yget_ref returns its global symbol table 349 reference; if iarg was a temporary expression, yget_ref returns -1. 350 Use this index in yput_global to set the output value before you 351 return. 352 */ 353 PLUG_API long yget_ref(int iarg); 354 /* 355 Six API functions manipulate lists: 356 357 ypush_list replaces the n elements at the top of the stack by a single 358 stack element which is a list containing them, like the _lst 359 interpreted function. If n<0, -n elements are replaced but like 360 the _cat interpreted function, namely, any lists are concatenated 361 rather than becoming single list elements. Finally, if n==0, ypush_list 362 is the same as ypush_nil. 363 yarg_nlist returns the length of the list iarg. 364 ypush_car pushes the n-th car of iarg onto the top of the stack. 365 yput_car sets the n-th car of iarg to jarg. 366 ypush_cdr pushes the n-th cdr of iarg onto the top of the stack, if n>=0. 367 If n==-1, ypush_cdr pushes a copy of the whole list, like _cpy. 368 yput_cdr sets the n-th cdr of iarg to jarg. 369 370 If iarg is not a list or nil, yarg_list returns -1, and ypush_car, yput_car, 371 ypush_cdr, and yput_cdr return non-zero. The yput_cdr function also returns 372 non-zero if jarg is not a list or nil. 373 */ 374 PLUG_API void ypush_list(int n); 375 PLUG_API long yarg_nlist(int iarg); 376 PLUG_API int ypush_car(int iarg, long n); 377 PLUG_API int yput_car(int iarg, long n, int jarg); 378 PLUG_API int ypush_cdr(int iarg, long n); 379 PLUG_API int yput_cdr(int iarg, long n, int jarg); 380 /* 381 Many packages need to create persistent objects to store state 382 information for future calls. In order to do that, you must create an 383 object of a new data type. The interpreter recognizes your objects 384 enough to be able to store them in interpreted variables, delete them, 385 and pass them back to you as arguments to future calls. You can also 386 supply four optional operations: on_free, on_print, on_eval, and 387 on_extract. 388 */ 389 typedef struct y_userobj_t y_userobj_t; 390 struct y_userobj_t { 391 char *type_name; 392 void (*on_free)(void *); 393 void (*on_print)(void *); 394 void (*on_eval)(void *, int); 395 void (*on_extract)(void *, char *); 396 void *uo_ops; 397 }; 398 PLUG_API void *ypush_obj(y_userobj_t *uo_type, unsigned long size); 399 PLUG_API y_userobj_t *yfunc_obj(y_userobj_t *uo_type); 400 PLUG_API void *yget_obj(int iarg, y_userobj_t *uo_type); 401 PLUG_API void y_print(const char *text, int newline); 402 /* 403 You should statically initialize the uo_type structure (with 404 uo_ops=0). For function-like objects, the uo_ops member must then be 405 initialized in a special way by calling yfunc_obj; otherwise, the 406 uo_ops member will be initialized on the first call to ypush_obj. 407 Before applying yfunc_obj or before the first call to ypush_obj, make 408 sure uo_ops=0, and do not touch it afterwards. The virtual functions 409 for your object can be 0 to get default behavior. Like ypush_scratch, 410 the on_free, if present, should not attempt to free the object itself, 411 just its contents. If no special action is required to free your 412 object, use on_free=0. If on_print=0, printing the object will print 413 a generic phrase including its type_name. The on_eval is invoked like 414 a builtin function: 415 object(arg1, arg2, ...) 416 in the interpreted code will invoke 417 on_eval(object, argc) 418 with the argc arguments on the stack; you should leave the result on 419 the top of the stack, and treat this like any other my_builtin. The 420 member on_extract is called as a result of interpreted code 421 object.member_name 422 producing the compiled call 423 on_extract(object, member_name) 424 Again, you should leave the result on the top of the stack. If 425 on_eval or on_extract is zero, that operation will cause a runtime 426 error (the default behavior). Note that you can use the yarg_kw_init 427 function (with kiargs=0) to retrieve name indices. 428 429 An object created by ypush_obj can be retrieved by yget_obj. Passing 430 uo_type=0 to yget_obj returns the type_name for the object at iarg; 431 otherwise it returns the pointer to the object itself, as created by 432 ypush_obj. For example, 433 y_userobj_t examp1_ops = { "example1 user object", 434 &examp1_free, &examp1_print, &examp1_eval, &examp1_extract, 0 }; 435 y_userobj_t examp2_ops = { "example2 user object", 436 &examp2_free, &examp2_print, &examp2_eval, &examp2_extract, 0 }; 437 A function which expects an example1 object at iarg=0 would simply 438 call yget_obj(iarg, &examp1_ops). However, if either an example1 or 439 an example2 object were an acceptable iarg=0 argument, you would call 440 name=yget_obj(iarg,0), then check whether name==examp1_ops.type_name or 441 name==examp2_ops.type_name. Note that the string itself is irrelevant -- 442 checking the string value is not only a waste of time, but also there is no 443 guarantee the value is unique. Instead, you want to check that the 444 address examp1_ops.type_name (or examp2_ops.type_name) is returned. Note 445 that you can easily write your own yarg_examp1(iarg) or yarg_examp2(iarg) 446 function that retrieves specific object types with whatever semantics 447 you like if the actual argument is not the correct type. Similarly, you 448 can write ypush_examp1 or ypush_examp2, with whatever constructor arguments 449 make sense. 450 451 The y_print function must be used by the on_print callback to produce 452 output. Do not attempt to use y_print except in a on_print callback. 453 Set newline to 1 to force a newline after text; your message will 454 always start on a newline, and a newline will be forced after the 455 final text you emit (whether or not your final call to y_print sets 456 newline). 457 458 Yorick memory management works by reference counting. Your compiled 459 code may need to own a use of a yorick object, for example, when one 460 user object type contains a pointer to another and both are visible 461 to interpreted code. The yget_use function obtains a private use of 462 an object on the stack. You can obtain a use of a yorick user defined 463 persistent object or array (but not a double, long, or int scalar) 464 by calling yget_use. The returned handle is opaque -- you must save it 465 and call ypush_use to push the object back onto the stack and give up 466 your use. After calling ypush_use, you must zero all your copies of 467 the opaque handle. You can use the ygeta_* or yget_obj functions to 468 get the pointers to the actual data. As a side effect, yget_use converts 469 a scalar double, long, or int stack element into a rank 0 array, since 470 you cannot own a use of the scalars. This invalidates any existing pointer 471 you may have retrieved using ygeta_*, so call yget_use first. The 472 ykeep_use function is like ypush_use, except you do not give up your 473 use of the object; ydrop_use discards your use (like ypush_use) without 474 pushing the object onto the stack. 475 */ 476 PLUG_API void *yget_use(int iarg); 477 PLUG_API void ypush_use(void *handle); 478 PLUG_API void ykeep_use(void *handle); 479 PLUG_API void ydrop_use(void *handle); 480 /* 481 Your compiled package may need to execute code after the interpreter 482 shuts down on a quit operation or after a fatal error. This function 483 cannot use the interpreted stack or variables, so you must take care 484 to store any required information as compiled variables. An on_quit 485 function must execute in a short time and be bullet-proof -- no error 486 recovery is possible, and yorick may be in the process of exiting after 487 a fatal error. The on_quit functions are executed in reverse order 488 to the ycall_on_quit calls. Use ycancel_on_quit to remove an on_quit 489 function. Multiple calls to ycall_on_quit do no harm, but on_quit 490 will only be called once. 491 */ 492 PLUG_API void ycall_on_quit(void (*on_quit)(void)); 493 PLUG_API void ycancel_on_quit(void (*on_quit)(void)); 494 /* 495 The ypush_func function is the compiled version of the interpreted 496 funcdef function; it pushes the resulting anonymous function onto the 497 top of the stack. If the funcdef string cannot be parsed, ypush_func 498 returns non-zero and pushes nil [] onto the stack. 499 */ 500 PLUG_API int ypush_func(char *funcdef); 501 /* 502 The y_error function emits a standard error message, and does not 503 return to the caller. This is intended as a replacement for the 504 original YError API. The y_errorn and y_errorq variants handle the 505 frequent cases for which the message is a format string including a 506 %ld or %s descriptor. The y_errquiet variant emits no error message; 507 use it to transfer control to a catch or after_error handler. 508 */ 509 PLUG_API void y_error(const char *msg); 510 PLUG_API void y_errorn(const char *msg_format, long n); 511 PLUG_API void y_errorq(const char *msg_format, const char *q); 512 PLUG_API void y_errquiet(void); 513 PLUG_API void y_warn(const char *msg); 514 PLUG_API void y_warnn(const char *msg_format, long n); 515 PLUG_API void y_warnq(const char *msg_format, const char *q); 516 517 /* hook function called inside y_error 518 * return value bits: 519 * 1 - suppress printing error message or entering dbug mode 520 * (one time override of set_idler flag) 521 * 2 - use output after as index into global symbol table of 522 * alternate after_error function 523 * 4 - if bit 2 set, after_error left in dbug mode iff bit 4 set 524 */ 525 PLUG_API int (*y_errhook)(const char *fullmsg, long *after); 526 527 /* ------------------------------------------------------------------------ */ 528 /* oxy: object-oriented extension to yorick */ 529 530 /* here are the methods all oxy_objects share 531 * 532 * arguments and return values: 533 * obj - the oxy_object 534 * nmemb - number of object members 535 * mndx - object member index (1-origin, 1 <= mndx <= nmemb) 536 * name - object member name 537 * iname - index into globtab corresponding to name (yfind_global) 538 * iname=-1 on input or output means unknown correspondence 539 * there are two ways to indicate an object member: 540 * by name (or iname) 541 * by 1-origin index (mndx) into the object 542 * multiple anonymous members permitted, but otherwise name is unique 543 * objects not required to assign a fixed mndx to each member, 544 * but if they do not, no anonymous members permitted 545 * iarg - stack position (for arguments on stack, 0 = top, 1 = next, etc) 546 * flag - 0 means success, non-0 various sorts of failure 547 */ 548 typedef struct yo_ops_t yo_ops_t; 549 struct yo_ops_t { 550 char *type_name; 551 void (*dealloc)(void *obj); /* deallocate obj */ 552 long (*count)(void *obj); /* return number of members */ 553 long (*find_mndx)(void *obj, const char *name, long iname); 554 /* iname=-1 if correspondence with globtab unknown 555 * find_mndx==0 permitted, means no fixed member indices 556 */ 557 char *(*find_name)(void *obj, long mndx, long *iname); 558 /* returns iname=-1 if correspondence with globtab unknown 559 * return value owned by obj, caller must copy string 560 * next call to find_name may invalidate return value 561 * if find_mndx==0, this will only be called in a sequence 562 * from mndx=1 to mndx=count(obj) to list all names 563 * get_q or set_q may be called during listing sequence, 564 * but only with name just returned 565 */ 566 int (*get_i)(void *obj, long mndx); 567 int (*get_q)(void *obj, const char *name, long iname); 568 /* push member onto stack 569 * get_i unused (0 permitted) when find_mndx==0 570 * pass iname=-1 if correspondence with globtab unknown 571 * returns 0 on success, otherwise push nil and return: 572 * 1 if no such member 573 */ 574 int (*set_i)(void *obj, long mndx, int iarg); 575 int (*set_q)(void *obj, const char *name, long iname, int iarg); 576 /* set member to value at iarg on stack 577 * set_i unused (0 permitted) when find_mndx==0 578 * both set_i==0, set_q==0 permitted if changing values unsupported 579 * pass iname=-1 if correspondence with globtab unknown 580 * returns 0 on success, otherwise return: 581 * 1 if no such member and creating member not allowed 582 * 2 if member is read-only 583 * 3 if type or shape of iarg cannot be converted to member type 584 * 4 if type not supported by this object 585 */ 586 void (*get_atts)(void *obj); 587 /* push (possibly empty) attribute oxy_object 588 * may push nil to indicate no attributes present or writable 589 * get_atts==0 permitted if attributes unsupported 590 * attribute oxy_object may be read-only or read-write 591 */ 592 void (*print)(void *obj); /* print obj, print==0 uses default method */ 593 void (*sr_hook)(void *obj, int flags); 594 /* called at end of save/restore, flags&1 == 1 if restore 595 * required for back compatibilty with IOStream, which flushes to file 596 * at end of save/restore operation 597 */ 598 599 /* more optional methods may be added to support LValue oxy_objects */ 600 }; 601 602 /* yo_push_alloc makes obj part of data block, initialize in place 603 * yo_push makes data block with pointer to obj (returning obj) 604 * yo_ops_t method functions obviously know how to distinguish 605 * - in particular, dealloc erases obj contents for yo_push_alloc, 606 * but must also free obj pointer for yo_push 607 * yo_get returns obj and ops, making it possible to call method functions 608 * - returns 0 if iarg (on stack) not an oxy_object 609 * - for legacy support, returns oxy wrapper if iarg is IOStream 610 * 611 * note that you can use yget_use, ypush_use to pluck your own use of 612 * an object off the stack, then give it back 613 */ 614 PLUG_API void *yo_push_alloc(yo_ops_t *ops, unsigned long size); 615 PLUG_API void *yo_push(yo_ops_t *ops, void *obj); 616 PLUG_API void *yo_get(int iarg, yo_ops_t **ops); 617 618 /* yo_use is the compiled equivalent of the interpreted use function 619 * you should call it before reading or writing (with ypush_global 620 * or yput_global) in order to be sure interpreted functions actually 621 * pick up changes 622 * - return value is 0 on success, 1 if index (globtab index) is not in 623 * globtab, 2 if index is not in the context object, and 3 if there is 624 * no context 625 */ 626 PLUG_API int yo_use(long index); 627 /* yo_get_context returns the context object for the current function 628 * iarg>=0 means get the context object for the builtin function at iarg 629 * normally called with iarg=argc, the argument to the builtin 630 * iarg<0 means return the context for the current interpreted func, 631 * which was called as an object method 632 * allows compiled functions to examine and set context objects, 633 * like interpreted functions can do with use function 634 * 635 * non-0 push flag pushes context (or nil) onto stack as side effect 636 */ 637 PLUG_API void *yo_get_context(int iarg, yo_ops_t **ops, int push); 638 639 /* yo_new_group pushes empty group object onto stack, returning obj,ops */ 640 PLUG_API void *yo_new_group(yo_ops_t **ops); 641 642 /* ------------------------------------------------------------------------ */ 643 /* closure, invented by Eric Thiebaut, see closure doc in i0/std.i */ 644 645 /* create a closure on top of stack from function at farg, data at darg 646 * returns 0 on success, 1 if farg is not a function or darg is not data 647 */ 648 PLUG_API int yo_closure(int farg, int darg); 649 PLUG_API int yo_is_closure(int iarg); 650 651 /* ------------------------------------------------------------------------ */ 652 653 /* compiled interface to interpreted after function 654 * secs = delay time until fndx/farg executes 655 * = 0.0 to execute on idle 656 * < 0.0 to remove existing after function from queue (after,-) 657 * fndx = index into global symbol table for function or object 658 * = -1 to use farg instead of fndx (recommended) 659 * farg = iarg stack position of function to call (unused if fndx>=0) 660 * dndx = index into global symbol table for data (recommended for object) 661 * = -1 to use darg instead of dndx (recommended for function) 662 * = -2 to pass no argument to function 663 * darg = iarg stack position of data for farg/fndx (unused if dndx!=-1) 664 */ 665 PLUG_API void yexec_after(double secs, long fndx, int farg, long dndx, int darg); 666 /* compiled interface to interpreted include function */ 667 PLUG_API void yexec_include(int iarg, int now); 668 /* push interpreted function onto task stack as *main* */ 669 PLUG_API void ytask_push(int iarg); 670 /* run interpreted function as *main* immediately, for event callbacks */ 671 PLUG_API void ytask_run(int iarg); 672 673 /* ------------------------------------------------------------------------ */ 674 675 END_EXTERN_C 676 677 #endif 678