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