1 /*
2  * $Id: ydata.h,v 1.9 2010-07-03 19:42:31 dhmunro Exp $
3  * Declare structures and functions for Yorick's "private" data.
4  */
5 /* Copyright (c) 2005, The Regents of the University of California.
6  * All rights reserved.
7  * This file is part of yorick (http://yorick.sourceforge.net).
8  * Read the accompanying LICENSE file for details.
9  */
10 
11 /* use the functions declared in yapi.h to retrieve information
12  * for use by new built-in functions - the functions and data
13  * structures here are for internal use by the interpreter, and
14  * are subject to change as the interpreter evolves
15  */
16 
17 #ifndef YDATA_H
18 #define YDATA_H
19 
20 #include "yapi.h"
21 
22 #include "hash.h"
23 #include "binio.h"
24 
25 /* "Universal" data types -- arrays of numbers, text strings, and
26    data structures compounded of these -- are declared in binio.h.
27    This file contains declarations of Yorick's "private" data types
28    -- interpreted functions, built-in functions, index ranges --
29    the virtual function tables, Yorick's program stack, and the like.  */
30 
31 /*--------------------------------------------------------------------------*/
32 
33 /* The DataBlock and Symbol structures are fundamental to the
34    Yorick interpreter.
35 
36    A DataBlock is a virtual base class (in C++ parlance) for storing
37    information of an unknown data type.  The 2nd edition of K&R blesses
38    the programming style I have adopted here in the last paragraph of
39    section A8.3; namely, a struct is derived (in the sense of a C++
40    derived class) from a DataBlock if its first members match the
41    members of the generic DataBlock struct.  In this case, a DataBlock
42    consists of a reference counter and an Operations table.  The
43    Operations table is a virtual function table defining all of the
44    operations whose precise meaning depends on the particular data
45    type.  For example, addition of two ints is quite a different thing
46    than addition of two doubles, so the Add member of the Operations
47    table for an int and the Add member of the Operations table for a
48    double will point to different functions.
49 
50    A Symbol represents a variable or an intermediate result in an
51    expression evaluation; Yorick's global symtab and program stack
52    consist of Symbols.  Symbols are distinct from DataBlocks in an
53    attempt to speed up simple operations on common data types (that is,
54    on ints, longs, and doubles), without drastically increasing the
55    number of virtual functions.  Binary operations cause the conflict
56    between table size and speed, since for a fast binary function, each
57    possible ordered *pair* of operand types requires a separate function.
58    Since there are only 4 different Symbol types, the OpTable virtual
59    function table is not too unwieldy; with about 16 DataBlock types,
60    a comparable Operations table would have to be 10 times as large.
61  */
62 
63 typedef struct DataBlock DataBlock;
64 struct DataBlock {
65   int references;   /* reference counter */
66   Operations *ops;  /* virtual function table */
67 };
68 
69 typedef struct Symbol Symbol;
70 
71 /* OpTable is required to define Symbol, and is itself defined below. */
72 typedef struct OpTable OpTable;     /* operations on a Symbol */
73 
74 /* A range function takes an Array and an integer indicating which index
75    of the array to operate on (0 for fastest varying, 1 for next, etc.).
76    The result of the operation is placed on top of the stack, and the
77    function returns 0 if the result Array (the result MUST be an Array)
78    has the same rank as the input Array, 1 if the result array has
79    reduced rank (the input index is missing in the result).  */
80 typedef int RangeFunc(Array *array, int index);  /* also in yio.h */
81 
82 typedef void VMaction(void);
83 typedef union Instruction Instruction;
84 union Instruction {
85   VMaction *Action;      /* do something */
86   int count;             /* parameter count */
87   long index;            /* index into global symbol table */
88   long displace;         /* branch displacement */
89   Symbol *constant;      /* pointer into function's constant table */
90   RangeFunc *rf;
91 };
92 
93 typedef union SymbolValue SymbolValue;
94 union SymbolValue {
95   int i;            /* intScalar */
96   long l;           /* longScalar */
97   double d;         /* doubleScalar */
98   DataBlock *db;    /* dataBlockSym */
99 
100   /* A fifth Symbol type, referenceSym, is used ONLY on the stack in
101      function parameter lists, i.e.- as an argument to the Eval function
102      (see array.c and fnctn.c).  On the stack, a Symbol with ops==0
103      is used to mark keyword parameters and function return addresses
104      as well (again, see array.c and fnctn.c).  */
105 
106   /* The offset and pc are used keywords and returnSym;
107      offset is also used in referenceSym (see referenceSym below): */
108   Instruction *pc;
109   long offset;
110 };
111 
112 struct Symbol {
113   OpTable *ops;                             /* virtual function table */
114   long index;   /* into global symtab (for replacing local variables) */
115   SymbolValue value;            /* appropriate member selected by ops */
116 };
117 
118 /*--------------------------------------------------------------------------*/
119 
120 /* The structures derived from DataBlock are the objects the Yorick
121    interpreter works with.
122 
123    Array, StructDef, and IOStream are DataBlocks defined in
124    binio.h.  These are the types necessary for representing "universal"
125    data in memory and on disk.
126 
127    Function is a list of virtual machine instructions, which results
128    from parsing interpreter input.  The source file and line numbers
129    corresponding to the function are recorded, although this information
130    is only used for error messages.
131 
132    BIFunction points to a builtin (i.e.- compiled) function, which
133    must have type BuiltIn.  A compiled function may be called from the
134    Yorick interpreter by defining a wrapper of type BuiltIn which pulls
135    its arguments off of the Yorick program stack, converts them to the
136    appropriate types, then calls the compiled function.  The Codger
137    code generator can generate simple wrapper functions automatically.
138  */
139 
140 /* LValue represents an object into which an Array may be stored, or
141    from which an Array can be fetched.  It has a data type (StructDef),
142    dimensions, and an optional list of Strider (see below) specifications
143    to indicate how the data is to be extracted as a multidimensional
144    subset of a larger object.  An LValue represents data on disk or in
145    memory, according to whether its type is a disk or memory StructDef.
146 
147     LValues are used for 3 purposes:
148     (1) As a temporary describing the result of an indexing operation.
149         Further indexing, or other operations not immediately
150         requiring data, may then procede without actually fetching
151         the data.  This is crucial for extracting parts of complicated
152         data structures (especially data in disk files), which
153         often requires several member extractions and/or subarray
154         specifications to get to the interesting data.
155     (2) As an Array with "remote" data -- the result of a reshape
156         operation.  This is Yorick's version of FORTRAN equivalence
157         statements.
158     (3) To point to data not owned by the Yorick interpreter --
159         for example, a global data structure from a compiled routine,
160         like a FORTRAN common block.
161  */
162 typedef struct LValue LValue;
163 struct LValue {
164   int references;   /* reference counter */
165   Operations *ops;  /* virtual function table */
166   Array *owner;     /* 0 if data is in disk file or unowned */
167   Member type;      /* full data type of result, base x[]..[] */
168   union {
169     long d;         /* byte address on disk if file!=0 */
170     char *m;        /* memory address if file==0 */
171   } address;
172   Strider *strider; /* hierachy of strides to take */
173   /* If non-0, the strider MUST be set up to include a list element
174      for any contiguous blocks of type->base.size;
175      the Gather and Scatter routines in bcast.c, and the YRead and
176      YWrite routines recognize that no loop is required for
177      contiguous blocks. */
178 };
179 
180 typedef struct Function Function;
181 struct Function {
182   int references;     /* reference counter */
183   Operations *ops;    /* pointer to virtual functions */
184   Symbol *constantTable;  /* constants used by this function */
185   long nConstants;        /* length of constantTable */
186   int nReq;               /* worst case number of stack elements required */
187   int nPos, nKey, nLocal; /* number of positionals, keywords, and locals */
188   long hasPosList;        /* bit 0- 0 unless declared with .. parameter
189                              bits 1-30 set if that positional parameter
190                              marked as an output */
191   int errup;              /* to mark func to enter caller for dbug */
192   long isrc;              /* index of source file from RecordSource */
193   Instruction code[1];    /* virtual machine instructions begin here */
194   /* First 1+nPos+hasPosList+nKey+nLocal instructions are code[i].index
195      for function name (in definition), positional parameters,
196      optional .. ("*va*") parameter, keyword parameters, and local variables.
197      End of code is marked by code[i].Action==&Return, code[i+1].Action==0,
198      code[i+2].index==(length of code).  */
199 };
200 
201 /* Built-in functions are called with a single argument -- the number
202    of actual parameters on the top of the stack (keyword parameters
203    count as two).  The function should leave its result on the top of
204    the stack.  As many other items may be left on the stack as
205    necessary, but if more than the input parameters plus one scratch
206    plus the return value are necessary, then the built-in must call
207    CheckStack.  (The built-in may clean up the stack itself, as long
208    as its result is at or above sp-n when it returns.)  */
209 typedef void BuiltIn(int);
210 
211 typedef struct BIFunction BIFunction;
212 struct BIFunction {
213   int references;     /* reference counter */
214   Operations *ops;    /* pointer to virtual functions */
215   BuiltIn *function;
216   long index;         /* to globTab -- shorthand for function name */
217 };
218 
219 /* Auto-loaded functions are special interpreted functions which
220    trigger parsing of their source file when first used.  */
221 typedef struct autoload_t autoload_t;
222 struct autoload_t {
223   int references;      /* reference counter */
224   Operations *ops;     /* virtual function table */
225   long ifile;          /* index into table of autoload files */
226   long isymbol;        /* global symtab index */
227   autoload_t *next;    /* linked list for each ifile */
228 };
229 
230 /* TextStream is a "foreign" data block defined in ascio.c */
231 typedef struct TextStream TextStream;
232 
233 /*--------------------------------------------------------------------------*/
234 
235 /* Range     - A range triple min:max:inc or rf:min:max:inc
236 
237     Memory management for these objects is via a special block allocator
238     for reasons of efficiency.
239  */
240 
241 typedef struct Range Range;
242 struct Range {
243   int references;     /* reference counter */
244   Operations *ops;    /* virtual function table */
245   long min, max, inc; /* min:max:inc, inc guaranteed non-zero */
246   int nilFlags;       /* + 1 if min is nil (:N)
247                          + 2 if max is nil (N:)
248                              Note: if inc is nil, inc==1
249                          + 4 if marked index (+:min:max:inc)
250                          + 8 if pseudo index (-:min:max:inc)
251                          +16 if rubber index (..)
252                          +32 if nullifying index, e.g.-  where(0)  */
253 #define R_MINNIL 1
254 #define R_MAXNIL 2
255 #define R_MARKED 4
256 #define R_PSEUDO 8
257 #define R_RUBBER 16
258 #define R_NULLER 32
259   RangeFunc *rf;      /* possible range function,  rf:min:max:inc */
260 };
261 
262 /*--------------------------------------------------------------------------*/
263 
264 /* Operations on DataBlocks take Operand arguments -- this is an
265    abbreviated sort of LValue, allowing reshaped Arrays (in LValues) or
266    scalar Symbols to interact efficiently with DataBlocks.  The data
267    type of an operand may mutate before it is actually used, hence
268    an Operand includes the Symbol *owner, which will be updated as
269    the Operand changes.  */
270 typedef struct Operand Operand;
271 struct Operand {
272   Symbol *owner;
273   Operations *ops;  /* NEVER &lvalueOps */
274   int references;   /* 0 if owner points to temporary Array */
275   Member type;      /* all 0 unless ops is an Array type */
276   void *value;      /* 0 unless ops is an Array type */
277 };
278 
279 typedef void StackOp(void);
280 
281 struct OpTable {  /* virtual function table for Symbol */
282   int id;  /* index into binary operations array (0-3) */
283   Operand *(*FormOperand)(Symbol *owner, Operand *op);
284   StackOp *ToChar, *ToShort, *ToInt, *ToLong, *ToFloat, *ToDouble, *ToComplex;
285   StackOp *Negate, *Complement, *Not, *True;
286   StackOp *Add[4], *Subtract[4], *Multiply[4], *Divide[4], *Modulo[4],
287           *Power[4];
288   StackOp *Equal[4], *NotEqual[4],
289           *Greater[4], *Less[4], *GreaterEQ[4], *LessEQ[4];
290   StackOp *ShiftL[4], *ShiftR[4];
291   StackOp *Or[4], *And[4], *Xor[4];
292 };
293 
294 /* Virtual function tables for the 5 Symbol types: */
295 PLUG_API OpTable intScalar;
296 PLUG_API OpTable longScalar;
297 PLUG_API OpTable doubleScalar;
298 PLUG_API OpTable dataBlockSym;
299 PLUG_API OpTable referenceSym;   /* referenceSym is not a "complete" Symbol
300                                     in the sense that the parser ensures it
301                                     never appears in a binary operation
302                         ops          - &referenceSym
303                         index        - to globTab entry
304                         value.offset - stack offset (for Return only)  */
305 PLUG_API OpTable returnSym;      /* returnSym is not a "complete" Symbol
306                                     in the sense that the parser ensures it
307                                     never appears in a binary operation
308                         ops      - &returnSym
309                         index    - (unused)
310                         value.pc - VM program counter (for Return only)  */
311 /* Keywords may also appear on the program stack--
312    these are marked by ops==0.  */
313 
314 /*--------------------------------------------------------------------------*/
315 
316 /* Unary operators take an Operand*, perform the required operation,
317    and replace the Symbol at op->owner with the result.  */
318 typedef void UnaryOp(Operand *op);
319 
320 /* Binary operators take two Operand* representing the left and right
321    operands, perform the required operation, and replace the Symbol
322    at l->owner with the result.  The r->owner may be changed as well,
323    if the right operand had to be type converted or broadcast.  */
324 typedef void BinaryOp(Operand *l, Operand *r);
325 
326 /* Type promotion operators take two Operand*s, and do
327    arithmetic promotion (using one stack element for protected
328    scratch space).  Either the left or the right Symbol (but not both)
329    is updated, and the operator returns the Operations* for the result
330    type, or 0 if the required promotion operation was impossible.
331    Legal types for promotion are: char, short, int, long, float, double,
332    complex, for either Array or LValue (7 Array types plus LValue).
333    Non-numeric types return dl->ops if the dl->ops==dr->ops, else 0.  */
334 typedef Operations *PromoteOp(Operand *l, Operand *r);
335 
336 typedef void MemberOp(Operand *op, char *name);
337 
338 struct Operations {                 /* virtual function table for DataBlock */
339   void (*Free)(void *);  /* crucial member for Unref -- first in struct
340                             to allow alternate Operations to be used */
341   int typeID;     /* unique type ID number */
342   int isArray;    /* 1 if this is one of the Array DataBlocks */
343   int promoteID;  /* index into Promote array (0-7, 7 means illegal) */
344   char *typeName; /* ASCII name describing this data type */
345   PromoteOp *Promote[8];
346   UnaryOp *ToChar, *ToShort, *ToInt, *ToLong, *ToFloat, *ToDouble, *ToComplex;
347   UnaryOp *Negate, *Complement, *Not, *True;
348   BinaryOp *Add, *Subtract, *Multiply, *Divide, *Modulo, *Power;
349   BinaryOp *Equal, *NotEqual, *Greater, *GreaterEQ;
350   BinaryOp *ShiftL, *ShiftR, *Or, *And, *Xor;
351   BinaryOp *Assign;    /* WARNING- first parameter non-standard, see ops3.c */
352   UnaryOp *Eval;       /* WARNING- parameter non-standard, see ops3.c */
353   UnaryOp *Setup;      /* see array.c -- set up for array indexing */
354   MemberOp *GetMember; /* WARNING- parameter non-standard, see ops3.c */
355   BinaryOp *MatMult;   /* WARNING- non-standard semantics, see ops.c */
356   UnaryOp *Print;      /* uses PrintFunc to output each line, see yio.h */
357 };
358 
359 /* Virtual function tables for the DataBlock types: */
360 PLUG_API Operations charOps;
361 PLUG_API Operations shortOps;
362 PLUG_API Operations intOps;
363 PLUG_API Operations longOps;
364 PLUG_API Operations floatOps;
365 PLUG_API Operations doubleOps;
366 PLUG_API Operations complexOps;
367 PLUG_API Operations stringOps;
368 PLUG_API Operations pointerOps;
369 PLUG_API Operations structOps;
370 
371 PLUG_API Operations rangeOps;
372 PLUG_API Operations lvalueOps;
373 PLUG_API Operations voidOps;
374 PLUG_API Operations functionOps;
375 PLUG_API Operations builtinOps;
376 PLUG_API Operations structDefOps;
377 PLUG_API Operations streamOps;
378 PLUG_API Operations textOps;
379 PLUG_API Operations listOps;
380 PLUG_API Operations auto_ops;
381 
382 /* generic operators are needed to implement foreign objects */
383 PLUG_API UnaryOp ComplementX, NegateX, NotX, TrueX, ToAnyX, EvalX, SetupX;
384 PLUG_API BinaryOp AddX, SubtractX, MultiplyX, DivideX, ModuloX, PowerX;
385 PLUG_API BinaryOp GreaterX, GreaterEQX, EqualX, NotEqualX, AssignX;
386 PLUG_API BinaryOp OrX, AndX, XorX, ShiftLX, ShiftRX, MatMultX;
387 PLUG_API MemberOp GetMemberX;
388 PLUG_API PromoteOp PromXX;
389 PLUG_API UnaryOp PrintX;
390 PLUG_API UnaryOp y_setup_func_hack; /* do not use y_setup_func_hack */
391 
392 /*--------------------------------------------------------------------------*/
393 
394 PLUG_API DataBlock nilDB;       /* Nil, or [], the one instance of a void.  */
395 
396 PLUG_API Instruction *pc;       /* virtual machine program counter */
397 PLUG_API Symbol *sp;            /* virtual machine stack pointer */
398 PLUG_API Symbol *spBottom;      /* current bottom of stack */
399 PLUG_API HashTable globalTable; /* hash table for globTab symbols */
400 PLUG_API Symbol *globTab;       /* global symbol table, contains any
401                                    variable referenced by a Function */
402 
403 PLUG_API Function *y_idler_function;  /* used by yorick-gl */
404 
405 /*--------------------------------------------------------------------------*/
406 
407 /* typeIDs for the basic Array data types */
408 #define T_CHAR 0
409 #define T_SHORT 1
410 #define T_INT 2
411 #define T_LONG 3
412 #define T_FLOAT 4
413 #define T_DOUBLE 5
414 #define T_COMPLEX 6
415 #define T_STRING 7
416 #define T_POINTER 8
417 #define T_STRUCT 9
418 
419 /* typeIDs for the non-Array data types */
420 #define T_RANGE 10
421 #define T_LVALUE 11
422 #define T_VOID 12
423 #define T_FUNCTION 13
424 #define T_BUILTIN 14
425 #define T_STRUCTDEF 15
426 #define T_STREAM 16
427 
428 /* typeID for data types which are opaque to Yorick */
429 #define T_OPAQUE 17
430 
431 /*--------------------------------------------------------------------------*/
432 
433 PLUG_API LValue *NewLValueD(long address, StructDef *base, Dimension *dims);
434 PLUG_API LValue *NewLValueM(Array *owner, void *address,
435                             StructDef *base, Dimension *dims);
436 PLUG_API void FreeLValue(void *lvalue);     /* *** Use Unref(lvalue) *** */
437 
438 PLUG_API Function *NewFunction(Symbol *consts, long nConsts,int nPos,int nKey,
439                                int nLocal, long hasPL, int maxStackDepth,
440                                Instruction *code, long codeSize);
441 PLUG_API void FreeFunction(void *func);       /* *** Use Unref(func) *** */
442 
443 PLUG_API Range *NewRange(long min, long max, long inc, int nilFlags);
444 PLUG_API void FreeRange(void *range);        /* *** Use Unref(range) *** */
445 
446 PLUG_API BIFunction *NewBIFunction(BuiltIn *bi, long index);
447 PLUG_API void FreeBIFunction(void *bif);    /* *** Use Unref(bif) *** */
448 
449 PLUG_API int yDebugLevel;
450 
451 /* ------------------------------------------------------------------------ */
452 /* mixed old-new functions for oxy object extension, wrap_args */
453 PLUG_API void *yget_obj_s(DataBlock *db);
454 PLUG_API void yo_cupdate(int iarg);
455 
456 /*--------------------------------------------------------------------------*/
457 /* following are deprecated -- use alternatives in yapi.h */
458 
459 PLUG_API long Globalize(const char *name, long n);
460 PLUG_API long GlobalizeDB(const char *name, long n, void *db);
461 
462 /* CheckStack ensures that at least n more elements are available at
463    the top of the virtual machine stack.  It returns 1 if the stack had
464    to be copied to get more space (so that sp changed), else 0.  */
465 PLUG_API int CheckStack(int n);
466 PLUG_API void PushIntValue(int i);
467 PLUG_API void PushLongValue(long l);
468 PLUG_API void PushDoubleValue(double d);
469 PLUG_API int PushCopy(Symbol *s);  /* returns 1 if s is DataBlock, else 0 */
470 PLUG_API void *PushDataBlock(void *db);  /* returns db */
471 PLUG_API void Drop(int n);
472 PLUG_API void PopTo(Symbol *s);
473 
474 PLUG_API void ReplaceRef(Symbol *stack);
475 PLUG_API DataBlock *ForceToDB(Symbol *s);
476 
477 /* Conform sets 4 bit if not conformable, sets 1 bit if ldims==1 where
478    rdims>1, sets 2 bit if rdims==1 where ldims>1.  The result dimension
479    list is returned in tmpDims.  */
480 PLUG_API int Conform(Dimension *ldims, Dimension *rdims);
481 /* BinaryConform assures that the operands are conformable; either or
482    both may be broadcast.  Result dimensions are left in tmpDims.
483    RightConform is the same except an error is signaled if ldims would
484    need to be broadcast.
485    Both functions return 0 on success, 1 on failure.   */
486 PLUG_API int BinaryConform(Operand *l, Operand *r);
487 PLUG_API int RightConform(Dimension *ldims, Operand *r);
488 
489 PLUG_API Array *FetchLValue(void *db, Symbol *dsts);
490 PLUG_API void StoreLValue(void *db, void *data);
491 
492 /*--------------------------------------------------------------------------*/
493 
494 PLUG_API void PushTask(Function *task);
495 PLUG_API void RunTaskNow(Function *task);
496 
497 PLUG_API int CalledAsSubroutine(void);
498 
499 /* Extract scalar integers, reals, and strings from the stack */
500 PLUG_API long YGetInteger(Symbol *s);
501 PLUG_API double YGetReal(Symbol *s);
502 PLUG_API char *YGetString(Symbol *s);
503 
504 PLUG_API int YNotNil(Symbol *s);
505 
506 /* Scan stack[0],...,stack[nArgs-1] for keywords with names in the
507    0-terminated list keyNames, putting the corresponding Symbol*s in
508    the array symbols, or 0 if the keyName was not found.  Returns the
509    Symbol* of the first non-keyword in the input stack list, or 0 if
510    none.  */
511 PLUG_API Symbol *YGetKeywords(Symbol *stack, int nArgs, char **keyNames,
512                               Symbol **symbols);
513 
514 PLUG_API IOStream *YGetFile(Symbol *stack);
515 
516 /* Retrieve array arguments for foreign code wrappers,
517    applying type conversion (modifies s) if necessary.
518    If dims is non-zero, *dims is set to the Dimension * for the argument.
519    -- Just cast YGetInteger, YGetReal for scalar arguments, and
520       use YGetString for scalar strings.  */
521 PLUG_API char *YGet_C(Symbol *s, int nilOK, Dimension **dims);
522 PLUG_API short *YGet_S(Symbol *s, int nilOK, Dimension **dims);
523 PLUG_API int *YGet_I(Symbol *s, int nilOK, Dimension **dims);
524 PLUG_API long *YGet_L(Symbol *s, int nilOK, Dimension **dims);
525 PLUG_API float *YGet_F(Symbol *s, int nilOK, Dimension **dims);
526 PLUG_API double *YGet_D(Symbol *s, int nilOK, Dimension **dims);
527 PLUG_API double *YGet_Z(Symbol *s, int nilOK, Dimension **dims);
528 PLUG_API char **YGet_Q(Symbol *s, int nilOK, Dimension **dims);
529 PLUG_API void **YGet_P(Symbol *s, int nilOK, Dimension **dims);
530 /* Convenience routine YGet_dims converts a Dimension * linked list
531    to a dimension list dlist --
532    dlist[0] is the first dimension length, dlist[1] the second, and so on.
533    The return value is the actual number of dimensions.
534    No dimensions beyond dlist[maxDims-1] will be set, so dlist need have
535    at most maxDims elements.
536    Use the TotalNumber and CountDims functions to get just the length
537    or number of dimensions of an array.  */
538 PLUG_API int YGet_dims(const Dimension *dims, long *dlist, int maxDims);
539 /* If a compiled function is to treat a parameter as an update or an
540    output, call YPut_Result after you call the function.  The required
541    index is obtained from YGet_Ref, which must be called BEFORE YGet_...
542    gets the corresponding data:
543       long index= YGet_Ref(sp);
544       double *x= YGet_D(sp, 0, (Dimension **)0);
545       your_function(sp);
546       YPut_Result(sp, index);                */
547 PLUG_API long YGet_Ref(Symbol *s);
548 PLUG_API void YPut_Result(Symbol *s, long index);
549 
550 /* generic temporary object has only a free method (zapper)
551  * its data structure must begin with
552  *   int references;
553  *   Operations *ops;
554  *   void (*zapper)(void *to);
555  * pass sizeof(its structure) to y_new_tmpobj and it will
556  *   be allocated and the first three elements initialized
557  * you can then use PushDataBlock to put it on the stack
558  *   where Drop will call your zapper
559  */
560 PLUG_API void *y_new_tmpobj(unsigned long size, void (*zapper)(void *to));
561 PLUG_API Operations yo_tmpobj;
562 
563 /* new improved (1.6) argument retrieval functions (no sp reference)
564  * all return 0 for iarg (=number of spots below top of stack) < 0
565  * need to check yarg_nil separately if required
566  */
567 /* note that yarg_c, yarg_s, and yarg_f are nowhere referenced in yorick */
568 PLUG_API char *yarg_c(int iarg, Dimension **dims);
569 PLUG_API short *yarg_s(int iarg, Dimension **dims);
570 PLUG_API int *yarg_i(int iarg, Dimension **dims);
571 PLUG_API long *yarg_l(int iarg, Dimension **dims);
572 PLUG_API float *yarg_f(int iarg, Dimension **dims);
573 PLUG_API double *yarg_d(int iarg, Dimension **dims);
574 PLUG_API double *yarg_z(int iarg, Dimension **dims);
575 PLUG_API char **yarg_q(int iarg, Dimension **dims);
576 PLUG_API void **yarg_p(int iarg, Dimension **dims);
577 #define yarg_sc(iarg) ((char)yarg_sl(iarg))
578 #define yarg_ss(iarg) ((short)yarg_sl(iarg))
579 #define yarg_si(iarg) ((int)yarg_sl(iarg))
580 PLUG_API long yarg_sl(int iarg);
581 #define yarg_sf(iarg) ((float)yarg_sd(iarg))
582 PLUG_API double yarg_sd(int iarg);
583 PLUG_API char *yarg_sq(int iarg);
584 #define yarg_sp(iarg) (yarg_p(iarg,0)[0])
585 PLUG_API IOStream *yarg_file(int iarg);
586 PLUG_API Operand *yarg_op(int iarg, Operand *op);
587 /* yarg_keys returns next non-keyword iarg, or <0 if none */
588 PLUG_API int yarg_keys(int iarg, char **knames, Symbol **ksymbols);
589 
590 /*--------------------------------------------------------------------------*/
591 
592 typedef char *y_pkg_t(char ***ifiles, BuiltIn ***code, void ***data,
593                       char ***varname);
594 PLUG_API void y_pkg_add(y_pkg_t *init);
595 PLUG_API y_pkg_t *y_pkg_lookup(char *name);
596 /* use name==0 to link or include all packages (static and dynamic) */
597 PLUG_API void y_pkg_link(char *name);
598 PLUG_API void y_pkg_include(char *name, int now);
599 PLUG_API char *y_pkg_name(int i);
600 PLUG_API int y_pkg_count(int i);
601 
602 /* called by on_launch generated by codger in yinit.c */
603 PLUG_API int y_launch(int argc, char *argv[],
604                       char *home, char *site, y_pkg_t **pkgs);
605 
606 PLUG_API int ym_argc;
607 PLUG_API char **ym_argv;
608 
609 #ifdef Y_FOR_YORAPI
610 PLUG_API y_pkg_t yk_yor;
611 #endif
612 
613 /*--------------------------------------------------------------------------*/
614 
615 #endif
616