ArchWizard

DGD/

source navigation ]
diff markup ]
identifier search ]
file search ]
Version: [ 1.0.a0 ] [ 1.1 ] [ 1.2 ] [ 1.2p1 ] [ 1.2p2 ] [ 1.2p3 ] [ 1.2p4 ] [ 1.2.151 ]

  1                         DGD extension interface
  2 
  3 1. Introduction
  4 
  5 DGD presents an interface for extending the driver with new kfuns and special
  6 object types.  To enable this interface, DGD should be compiled with the macro
  7 DGD_EXTENSION defined.  The driver will then call an external function at
  8 initialization time:
  9 
 10     void extension_init();
 11 
 12 From this function, new kfuns may be added to the driver, and callback
 13 functions may be set.  The interface furthermore allows objects to be marked
 14 as `special', associating the object with some sort of user-defined external
 15 state.
 16 
 17 The extension code must be linked with DGD at compile time.  The include file
 18 `dgd_ext.h' defines the entire interface with the driver, using macros that
 19 all start with the prefix `DGD_'.  Compliant extensions should use these
 20 macros, only.  Some of these macros will evaluate their arguments several
 21 times; to be compatible with future releases, extensions should assume that
 22 all DGD_* macros with arguments may do so.
 23 
 24 
 25 2. Kernel functions
 26 
 27 Kernel functions may be added during the initialization phase by calling the
 28 following function:
 29 
 30     void DGD_EXT_KFUN(DGD_EXTKFUN_T *kf, int n);
 31 
 32 where `kf' is an array of DGD_EXTFUN_T structs, and `n' the number of elements
 33 in that array.  DGD_EXT_KFUN() should be called only once, and must not
 34 redeclare any existing kfuns.
 35 
 36 The DGD_EXTKFUN_T struct has the following fields:
 37 
 38     char *name;         /* kfun name */
 39     char *proto;        /* kfun prototype */
 40     func;               /* kfun function pointer */
 41 
 42 Here `func' is a pointer to a C function with the following prototype:
 43 
 44     void func(DGD_FRAME_T f, int nargs, DGD_VALUE_T *retval);
 45 
 46 Calls to the kfun with name `name' will be routed to that C function.  The
 47 `f' argument contains the function context, `nargs' is the number of
 48 arguments on the stack, and `retval' is a pointer to the return value.  The
 49 function should not attempt to push or pop arguments; instead, arguments
 50 should be accessed using the relevant DGD_FRAME_* macros listed below, and the
 51 return value, if any, should be stored in the retval value using one of the
 52 DGD_RETVAL_* macros.  The default return value is nil.
 53 
 54 Kfuns can call DGD_ERROR() to indicate that an error happened.  Errors will
 55 interrupt the flow of execution, so DGD_ERROR() should be called before any
 56 LPC values are constructed or changed, including the return value of the
 57 kfun.  Note that at present, the extension interface does not define a way to
 58 call an LPC function from a kfun.
 59 
 60     DGD_OBJECT_T DGD_FRAME_OBJECT(DGD_FRAME_T f);       /* current object */
 61     DGD_OBJECT_T DGD_FRAME_PROGRAM(DGD_FRAME_T f);      /* current program */
 62     DGD_DATA_T   DGD_FRAME_DATASPACE(DGD_FRAME_T f);    /* current dataspace */
 63     DGD_VALUE_T  DGD_FRAME_ARG(DGD_FRAME_T f, int nargs, int n);/* argument n */
 64     bool         DGD_FRAME_ATOMIC(DGD_FRAME_T f);       /* atomic? */
 65 
 66     void         DGD_RETVAL_INT(DGD_VALUE_T *retval, DGD_INT_T num);
 67     void         DGD_RETVAL_FLT(DGD_VALUE_T *retval, DGD_FLOAT_T flt);
 68     void         DGD_RETVAL_STR(DGD_VALUE_T *retval, DGD_STRING_T str);
 69     void         DGD_RETVAL_OBJ(DGD_VALUE_T *retval, DGD_OBJECT_T obj);
 70     void         DGD_RETVAL_ARR(DGD_VALUE_T *retval, DGD_ARRAY_T arr);
 71     void         DGD_RETVAL_MAP(DGD_VALUE_T *retval, DGD_MAPPING_T map);
 72 
 73     void         DGD_ERROR(char *mesg);
 74 
 75 The `proto' field of the DGD_EXTKFUN_T struct is a prototype for the function,
 76 represented as a 0-terminated array of chars.  For example, the LPC prototypes
 77 
 78     string lower_case(string str);
 79     string concat(string str...);
 80     int foo(int *a, varargs object **b);
 81     void bar(void);
 82     void gnu();
 83 
 84 would be represented as
 85 
 86     char lower_case_proto[] = { DGD_TYPE_STRING, DGD_TYPE_STRING, 0 };
 87     char concat_proto[] = { DGD_TYPE_STRING, DGD_TYPE_STRING,
 88                             DGD_TYPE_ELLIPSIS, 0 };
 89     char foo_proto[] = { DGD_TYPE_INT, DGD_TYPE_ARRAY_OF(DGD_TYPE_INT),
 90                          DGD_TYPE_VARARGS,
 91                          DGD_TYPE_ARRAY_OF(DGD_TYPE_ARRAY_OF(DGD_TYPE_OBJECT)),
 92                          0 };
 93     char bar_proto[] = { DGD_TYPE_VOID, DGD_TYPE_VOID, 0 };
 94     char gnu_proto[] = { DGD_TYPE_VOID, 0 };
 95 
 96 Note that the prototypes of bar() and gnu() are effectively identical, just
 97 as they would be for LPC functions; also note that varargs must be specified
 98 in the new way, among the arguments of the prototype rather than in front of
 99 the return type.
100 
101 The building blocks for prototypes are:
102 
103     DGD_TYPE_VOID
104     DGD_TYPE_INT
105     DGD_TYPE_FLOAT
106     DGD_TYPE_STRING
107     DGD_TYPE_OBJECT
108     DGD_TYPE_ARRAY_OF(dgd_type)
109     DGD_TYPE_MAPPING
110     DGD_TYPE_VARARGS
111     DGD_TYPE_ELLIPSIS
112 
113 
114 3. Special objects
115 
116 DGD defines various types of special objects: user objects, editor objects
117 and parser objects.  Extensions may define their own additional special
118 object type.  Special objects have an associated DGD_EINDEX_T value (normally
119 an 8-bit value), and an additional arbitrary LPC value.  Furthermore,
120 user-defined special objects may have various callbacks defined for them, as
121 explained in section 4.
122 
123 Objects should only be marked as special if they are not special already.
124 If an object is to be unmarked, and a special LPC value has been set, it
125 should be reset to DGD_NIL_VALUE first.
126 
127     bool DGD_OBJECT_ISSPECIAL(DGD_OBJECT_T obj);        /* special object */
128     bool DGD_OBJECT_ISMARKED(DGD_OBJECT_T obj);         /* user-def special */
129     void DGD_OBJECT_MARK(DGD_OBJECT_T obj);             /* mark as special */
130     void DGD_OBJECT_UNMARK(DGD_OBJECT_T obj);           /* unmark as special */
131 
132     DGD_EINDEX_T DGD_OBJECT_GET_EINDEX(DGD_OBJECT_T obj); /* get eindex value */
133     void         DGD_OBJECT_SET_EINDEX(DGD_OBJECT_T obj, DGD_EINDEX_T etabi);
134 
135 To retrieve or set the LPC value associated with a special object, first
136 get the object's dataspace, and then manipulate the value.
137 
138     DGD_DATASPACE_T DGD_OBJECT_DATASPACE(DGD_OBJECT_T obj);
139     DGD_VALUE_T     DGD_DATA_GET_VAL(DGD_DATASPACE_T data);
140     void            DGD_DATA_SET_VAL(DGD_DATASPACE_T data, DGD_VALUE_T val);
141 
142 
143 4. Callbacks
144 
145 Callbacks can be set with the following function:
146 
147     void DGD_EXT_CALLBACK(restore, swapout, destruct, funcall, cleanup,
148                           finish);
149 
150 The arguments are pointers to C functions, which may be NULL if no function is
151 to be called.  Each function pointer is explained below.
152 
153     void restore(DGD_OBJECT_T obj);
154 
155 This function is called when a user-defined special object is restored from a
156 state dump file.  At this point, the DGD_EINDEX_T value is no longer valid,
157 but the associated LPC value is.
158 
159     void swapout(DGD_OBJECT_T obj);
160 
161 This function is called when a user-defined special object is about to be
162 swapped out (including any associated LPC value).
163 
164     void destruct(DGD_OBJECT_T obj);
165 
166 This function is called when a user-defined special object is about to be
167 destructed.  DGD_ERROR() may be called from here to prevent destruction.
168 
169     bool funcall(DGD_FRAME_T f, int nargs, DGD_VALUE_T *retval, char *name);
170 
171 This function is called when the LPC function with name `name' is called,
172 and that function is defined by a user-defined special object.  If you want
173 to override this LPC function with one of your own, call that function and
174 return TRUE.  Otherwise, return FALSE, and the normal LPC function will be
175 called.
176 
177     void cleanup(void);
178 
179 This function is called at the end of each LPC thread.
180 
181     void finish(void);
182 
183 This function is called just before the driver is about to shut down.
184 
185 
186 5. Operations on LPC values
187 
188 The type of an LPC value can be determined with
189 
190     int DGD_TYPEOF(DGD_VALUE_T val);
191 
192 The types can be:
193 
194     DGD_TYPE_NIL
195     DGD_TYPE_INT
196     DGD_TYPE_FLOAT
197     DGD_TYPE_STRING
198     DGD_TYPE_OBJECT
199     DGD_TYPE_ARRAY
200     DGD_TYPE_MAPPING
201 
202 Each type has its own set of macros.
203 
204     DGD_NIL_VALUE               /* the nil value */
205 
206     DGD_INT_T DGD_INT_GETVAL(DGD_VALUE_T val);
207     void      DGD_INT_PUTVAL(DGD_VALUE_T val, DGD_INT_T num);
208 
209 Floats consist of a 1-bit sign, a 11-bit exponent, and a 36-bit mantissa.
210 To make a C double out of a sign, exponent and mantissa, use this expression:
211 
212         ((sign) ? -1 : 1) * ldexp(mantissa, exponent - 36)
213 
214 To convert in the other direction, use the following code:
215 
216         sign = (Cfloatval < 0);
217         mantissa = ldexp(frexp(fabs(Cfloatval), &exponent), 37);
218         --exponent;
219 
220     void        DGD_FLOAT_GETVAL(DGD_VALUE_T val, DGD_FLOAT_T flt);
221     void        DGD_FLOAT_PUTVAL(DGD_VALUE_T val, DGD_FLOAT_T flt);
222     void        DGD_FLOAT_GET(DGD_FLOAT_T flt, int sign, int exp,
223                               int64 mantissa); /* assign to sign/exp/mantissa */
224     void        DGD_FLOAT_PUT(DGD_FLOAT_T flt, int sign, int exp,
225                               int64 mantissa);
226 
227     DGD_STRING_T DGD_STRING_GETVAL(DGD_VALUE_T val);
228     void         DGD_STRING_PUTVAL(DGD_VALUE_T val, DGD_STRING_T str);
229     DGD_STRING_T DGD_STRING_NEW(char *text, int len);
230     char        *DGD_STRING_TEXT(DGD_STRING_T str);
231     unsigned int DGD_STRING_LENGTH(DGD_STRING_T str);
232 
233 An object retrieved from an array or mapping element may be invalid.  Use
234 DGD_OBJECT_CHECKVAL() to check the validity of such an object.
235 
236     DGD_OBJECT_T DGD_OBJECT_GETVAL(DGD_VALUE_T val);
237     void         DGD_OBJECT_PUTVAL(DGD_VALUE_T val, DGD_OBJECT_T obj);
238     bool         DGD_OBJECT_CHECKVAL(DGD_VALUE_T val, DGD_OBJECT_T obj);
239     void         DGD_OBJECT_NAME(char *buffer, DGD_OBJECT_T obj);
240 
241     DGD_ARRAY_T  DGD_ARRAY_GETVAL(DGD_VALUE_T val);
242     void         DGD_ARRAY_PUTVAL(DGD_VALUE_T val, DGD_ARRAY_T arr);
243     DGD_ARRAY_T  DGD_ARRAY_NEW(DGD_DATASPACE_T data, int size);
244     DGD_VALUE_T *DGD_ARRAY_ELTS(DGD_ARRAY_T arr);
245     DGD_VALUE_T  DGD_ARRAY_INDEX(DGD_ARRAY_T arr, int i);
246     void         DGD_ARRAY_ASSIGN(DGD_DATASPACE_T data, DGD_ARRAY_T arr,
247                                   int index, DGD_VALUE_T val);
248 
249 The elements of a mapping may be retrieved as a sorted array of alternate
250 index-value pairs with DGD_MAPPING_ELTS().
251 
252     DGD_MAPPING_T DGD_MAPPING_GETVAL(DGD_VALUE_T val);
253     void          DGD_MAPPING_PUTVAL(DGD_VALUE_T val, DGD_MAPPING_T map);
254     DGD_MAPPING_T DGD_MAPPING_NEW(DGD_DATASPACE_T data);
255     DGD_VALUE_T  *DGD_MAPPING_ELTS(DGD_MAPPING_T map);
256     DGD_VALUE_T   DGD_MAPPING_INDEX(DGD_MAPPING_T map, DGD_VALUE_T index);
257     void          DGD_MAPPING_ASSIGN(DGD_DATASPACE_T data, DGD_MAPPING_T map,
258                                      DGD_VALUE_T index, DGD_VALUE_T val);
259 
260 
261 6. Example
262 
263 The following code implements a lower_case() kfun.
264 
265 # include "dgd_ext.h"
266 
267 static void lower_case(DGD_FRAME_T f, int nargs, DGD_VALUE_T *retval)
268 {
269     DGD_VALUE_T val;
270     DGD_STRING_T str;
271     char *p;
272     unsigned int i;
273 
274     /* fetch the argument string */
275     val = DGD_FRAME_ARG(f, nargs, 0);
276     str = DGD_STRING_GETVAL(val);
277 
278     /* make a copy */
279     str = DGD_STRING_NEW(DGD_STRING_TEXT(str), DGD_STRING_LENGTH(str));
280 
281     /* turn to lowercase */
282     p = DGD_STRING_TEXT(str);
283     for (i = DGD_STRING_LENGTH(str); i != 0; --i) {
284         if (*p >= 'A' && *p <= 'Z') {
285             *p += 'a' - 'A';
286         }
287         p++;
288     }
289 
290     /* put result in return value */
291     DGD_RETVAL_STR(retval, str);
292 }
293 
294 static char lower_case_proto[] = { DGD_TYPE_STRING, DGD_TYPE_STRING, 0 };
295 static DGD_EXTKFUN_T kf[1] = {
296     "lower_case",
297     lower_case_proto,
298     &lower_case
299 };
300 
301 void extension_init(void)
302 {
303     DGD_EXT_KFUN(kf, 1);
304 }

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.