8b4325ca422be2a131e623c0f8d33f50b75c1ef7
[framework/uifw/embryo.git] / src / lib / embryo_amx.c
1 /*  Abstract Machine for the Small compiler
2  *
3  *  Copyright (c) ITB CompuPhase, 1997-2003
4  *  Portions Copyright (c) Carsten Haitzler, 2004 <raster@rasterman.com>
5  *
6  *  This software is provided "as-is", without any express or implied warranty.
7  *  In no event will the authors be held liable for any damages arising from
8  *  the use of this software.
9  *
10  *  Permission is granted to anyone to use this software for any purpose,
11  *  including commercial applications, and to alter it and redistribute it
12  *  freely, subject to the following restrictions:
13  *
14  *  1.  The origin of this software must not be misrepresented; you must not
15  *      claim that you wrote the original software. If you use this software in
16  *      a product, an acknowledgment in the product documentation would be
17  *      appreciated but is not required.
18  *  2.  Altered source versions must be plainly marked as such, and must not be
19  *      misrepresented as being the original software.
20  *  3.  This notice may not be removed or altered from any source distribution.
21  */
22
23 /*
24  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
25  */
26
27 #include "embryo_private.h"
28
29 #define JUMPABS(base, ip)     ((Embryo_Cell *)(code + (*ip)))
30
31 #ifdef WORDS_BIGENDIAN
32 static void _embryo_byte_swap_16 (unsigned short *v);
33 static void _embryo_byte_swap_32 (unsigned int *v);
34 #endif
35 static int  _embryo_native_call  (Embryo_Program *ep, Embryo_Cell index, Embryo_Cell *result, Embryo_Cell *params);
36 static int  _embryo_func_get     (Embryo_Program *ep, int index, char *funcname);
37 static int  _embryo_var_get      (Embryo_Program *ep, int index, char *varname, Embryo_Cell *ep_addr);
38 static int  _embryo_program_init (Embryo_Program *ep, void *code);
39
40 #ifdef WORDS_BIGENDIAN
41 static void
42 _embryo_byte_swap_16(unsigned short *v)
43 {
44    unsigned char *s, t;
45
46    s = (unsigned char *)v;
47    t = s[0]; s[0] = s[1]; s[1] = t;
48 }
49
50 static void
51 _embryo_byte_swap_32(unsigned int *v)
52 {
53    unsigned char *s, t;
54
55    s = (unsigned char *)v;
56    t = s[0]; s[0] = s[3]; s[3] = t;
57    t = s[1]; s[1] = s[2]; s[2] = t;
58 }
59 #endif
60
61 static int
62 _embryo_native_call(Embryo_Program *ep, Embryo_Cell index, Embryo_Cell *result, Embryo_Cell *params)
63 {
64    Embryo_Header    *hdr;
65    Embryo_Func_Stub *func_entry;
66    Embryo_Native     f;
67
68    hdr = (Embryo_Header *)ep->base;
69    func_entry = GETENTRY(hdr, natives, index);
70    if ((func_entry->address <= 0) ||
71        (func_entry->address > ep->native_calls_size))
72      {
73         ep->error = EMBRYO_ERROR_CALLBACK;
74         return ep->error;
75      }
76    f = ep->native_calls[func_entry->address - 1];
77    if (!f)
78      {
79         ep->error = EMBRYO_ERROR_CALLBACK;
80         return ep->error;
81      }
82    ep->error = EMBRYO_ERROR_NONE;
83    *result = f(ep, params);
84    return ep->error;
85 }
86
87 static int
88 _embryo_func_get(Embryo_Program *ep, int index, char *funcname)
89 {
90    Embryo_Header    *hdr;
91    Embryo_Func_Stub *func;
92
93    hdr = (Embryo_Header *)ep->code;
94    if (index >= (Embryo_Cell)NUMENTRIES(hdr, publics, natives))
95      return EMBRYO_ERROR_INDEX;
96
97    func = GETENTRY(hdr, publics, index);
98    strcpy(funcname, GETENTRYNAME(hdr, func));
99    return EMBRYO_ERROR_NONE;
100 }
101
102 static int
103 _embryo_var_get(Embryo_Program *ep, int index, char *varname, Embryo_Cell *ep_addr)
104 {
105
106   Embryo_Header    *hdr;
107   Embryo_Func_Stub *var;
108
109   hdr=(Embryo_Header *)ep->base;
110   if (index >= (Embryo_Cell)NUMENTRIES(hdr, pubvars, tags))
111      return EMBRYO_ERROR_INDEX;
112
113   var = GETENTRY(hdr, pubvars, index);
114   strcpy(varname, GETENTRYNAME(hdr, var));
115   *ep_addr = var->address;
116   return EMBRYO_ERROR_NONE;
117 }
118
119 static int
120 _embryo_program_init(Embryo_Program *ep, void *code)
121 {
122    Embryo_Header    *hdr;
123
124    if ((ep->flags & EMBRYO_FLAG_RELOC)) return 1;
125    ep->code = (unsigned char *)code;
126    hdr = (Embryo_Header *)ep->code;
127 #ifdef WORDS_BIGENDIAN
128    embryo_swap_32((unsigned int *)&hdr->size);
129    embryo_swap_16((unsigned short *)&hdr->magic);
130    embryo_swap_16((unsigned short *)&hdr->flags);
131    embryo_swap_16((unsigned short *)&hdr->defsize);
132    embryo_swap_32((unsigned int *)&hdr->cod);
133    embryo_swap_32((unsigned int *)&hdr->dat);
134    embryo_swap_32((unsigned int *)&hdr->hea);
135    embryo_swap_32((unsigned int *)&hdr->stp);
136    embryo_swap_32((unsigned int *)&hdr->cip);
137    embryo_swap_32((unsigned int *)&hdr->publics);
138    embryo_swap_32((unsigned int *)&hdr->natives);
139    embryo_swap_32((unsigned int *)&hdr->libraries);
140    embryo_swap_32((unsigned int *)&hdr->pubvars);
141    embryo_swap_32((unsigned int *)&hdr->tags);
142    embryo_swap_32((unsigned int *)&hdr->nametable);
143 #endif
144
145    if (hdr->magic != EMBRYO_MAGIC) return 0;
146    if ((hdr->file_version < MIN_FILE_VERSION) ||
147       (hdr->ep_version > CUR_FILE_VERSION)) return 0;
148    if ((hdr->defsize != sizeof(Embryo_Func_Stub)) &&
149       (hdr->defsize != (2 * sizeof(unsigned int)))) return 0;
150    if (hdr->defsize == (2 * sizeof(unsigned int)))
151      {
152         unsigned short *len;
153
154         len = (unsigned short*)((unsigned char*)ep->code + hdr->nametable);
155 #ifdef WORDS_BIGENDIAN
156         embryo_swap_16((unsigned short *)len);
157 #endif
158         if (*len > sNAMEMAX) return 0;
159      }
160    if (hdr->stp <= 0) return 0;
161    if ((hdr->flags & EMBRYO_FLAG_COMPACT)) return 0;
162
163 #ifdef WORDS_BIGENDIAN
164      {
165         Embryo_Func_Stub *fs;
166         int i, num;
167
168         /* also align all addresses in the public function, public variable and */
169         /* public tag tables */
170         fs = GETENTRY(hdr, publics, 0);
171         num = NUMENTRIES(hdr, publics, natives);
172         for (i = 0; i < num; i++)
173           {
174              embryo_swap_32(&(fs->address));
175              fs = (Embryo_Func_Stub *)((unsigned char *)fs + hdr->defsize);
176           }
177
178         fs = GETENTRY(hdr, pubvars, 0);
179         num = NUMENTRIES(hdr, pubvars, tags);
180         for (i = 0; i < num; i++)
181           {
182              embryo_swap_32(&(fs->address));
183              fs = (Embryo_Func_Stub *)((unsigned char *)fs + hdr->defsize);
184           }
185
186         fs = GETENTRY(hdr, tags, 0);
187         num = NUMENTRIES(hdr, tags, nametable);
188         for (i = 0; i < num; i++)
189           {
190              embryo_swap_32(&(fs->address));
191              fs = (Embryo_Func_Stub *)((unsigned char *)fs + hdr->defsize);
192           }
193      }
194 #endif
195    ep->flags = EMBRYO_FLAG_RELOC;
196
197      {
198         Embryo_Cell cip, code_size;
199         Embryo_Cell *code;
200
201         code_size = hdr->dat - hdr->cod;
202         code = (Embryo_Cell *)((unsigned char *)ep->code + (int)hdr->cod);
203         for (cip = 0; cip < (code_size / sizeof(Embryo_Cell)); cip++)
204           {
205 /* move this here - later we probably want something that verifies opcodes
206  * are valid and ok...
207  */
208 #ifdef WORDS_BIGENDIAN
209              embryo_swap_32(&(code[cip]));
210 #endif
211
212           }
213      }
214    /* init native api for handling floating point - default in embryo */
215    _embryo_args_init(ep);
216    _embryo_fp_init(ep);
217    _embryo_rand_init(ep);
218    _embryo_str_init(ep);
219    _embryo_time_init(ep);
220    return 1;
221 }
222
223 /*** EXPORTED CALLS ***/
224
225 /**
226  * @defgroup Embryo_Program_Creation_Group Program Creation and Destruction Functions
227  *
228  * Functions that set up programs, and destroy them.
229  */
230
231 /**
232  * Creates a new Embryo program, with bytecode data that can be freed.
233  * @param   data Pointer to the bytecode of the program.
234  * @param   size Number of bytes of bytecode.
235  * @return  A new Embryo program.
236  * @ingroup Embryo_Program_Creation_Group
237  */
238 EAPI Embryo_Program *
239 embryo_program_new(void *data, int size)
240 {
241    Embryo_Program *ep;
242    void *code_data;
243
244    if (size < (int)sizeof(Embryo_Header)) return NULL;
245
246    ep = calloc(1, sizeof(Embryo_Program));
247    if (!ep) return NULL;
248
249    code_data = malloc(size);
250    if (!code_data)
251      {
252         free(ep);
253         return NULL;
254      }
255    memcpy(code_data, data, size);
256    if (_embryo_program_init(ep, code_data)) return ep;
257    free(code_data);
258    free(ep);
259    return NULL;
260 }
261
262 /**
263  * Creates a new Embryo program, with bytecode data that cannot be
264  * freed.
265  * @param   data Pointer to the bytecode of the program.
266  * @param   size Number of bytes of bytecode.
267  * @return  A new Embryo program.
268  * @ingroup Embryo_Program_Creation_Group
269  */
270 EAPI Embryo_Program *
271 embryo_program_const_new(void *data, int size)
272 {
273    Embryo_Program *ep;
274
275    if (size < (int)sizeof(Embryo_Header)) return NULL;
276
277    ep = calloc(1, sizeof(Embryo_Program));
278    if (!ep) return NULL;
279
280    if (_embryo_program_init(ep, data))
281      {
282         ep->dont_free_code = 1;
283         return ep;
284      }
285    free(ep);
286    return NULL;
287 }
288
289 /**
290  * Creates a new Embryo program based on the bytecode data stored in the
291  * given file.
292  * @param   file Filename of the given file.
293  * @return  A new Embryo program.
294  * @ingroup Embryo_Program_Creation_Group
295  */
296 EAPI Embryo_Program *
297 embryo_program_load(char *file)
298 {
299    Embryo_Program *ep;
300    Embryo_Header   hdr;
301    FILE *f;
302    void *program = NULL;
303    int program_size = 0;
304
305    f = fopen(file, "rb");
306    if (!f) return NULL;
307    fseek(f, 0, SEEK_END);
308    program_size = ftell(f);
309    rewind(f);
310    if (program_size < (int)sizeof(Embryo_Header))
311      {
312         fclose(f);
313         return NULL;
314      }
315    if (fread(&hdr, sizeof(Embryo_Header), 1, f) != 1)
316      {
317         fclose(f);
318         return NULL;
319      }
320    rewind(f);
321 #ifdef WORDS_BIGENDIAN
322    embryo_swap_32((unsigned int *)(&hdr.size));
323 #endif
324    if ((int)hdr.size < program_size) program_size = hdr.size;
325    program = malloc(program_size);
326    if (!program)
327      {
328         fclose(f);
329         return NULL;
330      }
331    if (fread(program, program_size, 1, f) != 1)
332      {
333         free(program);
334         fclose(f);
335         return NULL;
336      }
337    ep = embryo_program_new(program, program_size);
338    free(program);
339    fclose(f);
340    return ep;
341 }
342
343 /**
344  * Frees the given Embryo program.
345  * @param   ep The given program.
346  * @ingroup Embryo_Program_Creation_Group
347  */
348 EAPI void
349 embryo_program_free(Embryo_Program *ep)
350 {
351    int i;
352
353    if (ep->base) free(ep->base);
354    if ((!ep->dont_free_code) && (ep->code)) free(ep->code);
355    if (ep->native_calls) free(ep->native_calls);
356    for (i = 0; i < ep->params_size; i++)
357      {
358         if (ep->params[i].string) free(ep->params[i].string);
359         if (ep->params[i].cell_array) free(ep->params[i].cell_array);
360      }
361    if (ep->params) free(ep->params);
362    free(ep);
363 }
364
365 /**
366  * @defgroup Embryo_Func_Group Function Functions
367  *
368  * Functions that deal with Embryo program functions.
369  */
370
371 /**
372  * Adds a native program call to the given Embryo program.
373  * @param   ep   The given Embryo program.
374  * @param   name The name for the call used in the script.
375  * @param   func The function to use when the call is made.
376  * @ingroup Embryo_Func_Group
377  */
378 EAPI void
379 embryo_program_native_call_add(Embryo_Program *ep, const char *name, Embryo_Cell (*func) (Embryo_Program *ep, Embryo_Cell *params))
380 {
381    Embryo_Func_Stub *func_entry;
382    Embryo_Header    *hdr;
383    int               i, num;
384
385    if ((ep == NULL ) || (name == NULL) || (func == NULL)) return;
386    if (strlen(name) > sNAMEMAX) return;
387
388    hdr = (Embryo_Header *)ep->code;
389    if (hdr->defsize < 1) return;
390    num = NUMENTRIES(hdr, natives, libraries);
391    if (num <= 0) return;
392
393    ep->native_calls_size++;
394    if (ep->native_calls_size > ep->native_calls_alloc)
395      {
396         Embryo_Native *calls;
397
398         ep->native_calls_alloc += 16;
399         calls = realloc(ep->native_calls,
400                         ep->native_calls_alloc * sizeof(Embryo_Native));
401         if (!calls)
402           {
403              ep->native_calls_size--;
404              ep->native_calls_alloc -= 16;
405              return;
406           }
407         ep->native_calls = calls;
408      }
409    ep->native_calls[ep->native_calls_size - 1] = func;
410
411    func_entry = GETENTRY(hdr, natives, 0);
412    for (i = 0; i < num; i++)
413      {
414         if (func_entry->address == 0)
415           {
416              char *entry_name;
417
418              entry_name = GETENTRYNAME(hdr, func_entry);
419              if ((entry_name) && (!strcmp(entry_name, name)))
420                {
421                   func_entry->address = ep->native_calls_size;
422                   /* FIXME: embryo_cc is putting in multiple native */
423                   /* function call entries - so we need to fill in all */
424                   /* of them!!! */
425                   /* return; */
426                }
427           }
428         func_entry =
429           (Embryo_Func_Stub *)((unsigned char *)func_entry + hdr->defsize);
430      }
431 }
432
433 /**
434  * @defgroup Embryo_Program_VM_Group Virtual Machine Functions
435  *
436  * Functions that deal with creating and destroying virtual machine sessions
437  * for a given program.
438  *
439  * A given embryo program can have multiple virtual machine sessions running.
440  * This is useful when you have a native call that in turn calls a function in
441  * the embryo program.  The native call can start a new virtual machine
442  * session to run the function it needs.  Once completed, the session can be
443  * popped off the program's stack, and the native call can return its value
444  * to the old session.
445  *
446  * A new virtual machine session is created by pushing a new virtual machine
447  * onto the session stack of a program using @ref embryo_program_vm_push.
448  * The current virtual machine session can be destroyed by calling
449  * @ref embryo_program_vm_pop.
450  */
451
452 /**
453  * Resets the current virtual machine session of the given program.
454  * @param   ep The given program.
455  * @ingroup Embryo_Program_VM_Group
456  */
457 EAPI void
458 embryo_program_vm_reset(Embryo_Program *ep)
459 {
460    Embryo_Header *hdr;
461
462    if ((!ep) || (!ep->base)) return;
463    hdr = (Embryo_Header *)ep->code;
464    memcpy(ep->base, hdr, hdr->size);
465    *(Embryo_Cell *)(ep->base + (int)hdr->stp - sizeof(Embryo_Cell)) = 0;
466
467    ep->hlw = hdr->hea - hdr->dat; /* stack and heap relative to data segment */
468    ep->stp = hdr->stp - hdr->dat - sizeof(Embryo_Cell);
469    ep->hea = ep->hlw;
470    ep->stk = ep->stp;
471 }
472
473 /**
474  * Starts a new virtual machine session for the given program.
475  *
476  * See @ref Embryo_Program_VM_Group for more information about how this works.
477  *
478  * @param   ep The given program.
479  * @ingroup Embryo_Program_VM_Group
480  */
481 EAPI void
482 embryo_program_vm_push(Embryo_Program *ep)
483 {
484    Embryo_Header *hdr;
485
486    if (!ep) return;
487    ep->pushes++;
488    if (ep->pushes > 1)
489      {
490         embryo_program_vm_reset(ep);
491         return;
492      }
493    hdr = (Embryo_Header *)ep->code;
494    ep->base = malloc(hdr->stp);
495    if (!ep->base)
496      {
497         ep->pushes = 0;
498         return;
499      }
500    embryo_program_vm_reset(ep);
501 }
502
503 /**
504  * Frees the current virtual machine session associated with the given program.
505  *
506  * See @ref Embryo_Program_VM_Group for more information about how this works.
507  * Note that you will need to retrieve any return data or data on the stack
508  * before you pop.
509  *
510  * @param   ep The given program.
511  * @ingroup Embryo_Program_VM_Group
512  */
513 EAPI void
514 embryo_program_vm_pop(Embryo_Program *ep)
515 {
516    if ((!ep) || (!ep->base)) return;
517    ep->pushes--;
518    if (ep->pushes >= 1) return;
519    free(ep->base);
520    ep->base = NULL;
521 }
522
523 /**
524  * @defgroup Embryo_Swap_Group Byte Swapping Functions
525  *
526  * Functions that are used to ensure that integers passed to the
527  * virtual machine are in small endian format.  These functions are
528  * used to ensure that the virtual machine operates correctly on big
529  * endian machines.
530  */
531
532 /**
533  * Ensures that the given unsigned short integer is in the small
534  * endian format.
535  * @param   v Pointer to the given integer.
536  * @ingroup Embryo_Swap_Group
537  */
538 EAPI void
539 embryo_swap_16(unsigned short *v)
540 {
541 #ifdef WORDS_BIGENDIAN
542    _embryo_byte_swap_16(v);
543 #endif
544 }
545
546 /**
547  * Ensures that the given unsigned integer is in the small endian
548  * format.
549  * @param   v Pointer to the given integer.
550  * @ingroup Embryo_Swap_Group
551  */
552 EAPI void
553 embryo_swap_32(unsigned int *v)
554 {
555 #ifdef WORDS_BIGENDIAN
556    _embryo_byte_swap_32(v);
557 #endif
558 }
559
560 /**
561  * Returns the function in the given program with the given name.
562  * @param   ep The given program.
563  * @param   name The given function name.
564  * @return  The function if successful.  Otherwise, @c EMBRYO_FUNCTION_NONE.
565  * @ingroup Embryo_Func_Group
566  */
567 EAPI Embryo_Function
568 embryo_program_function_find(Embryo_Program *ep, const char *name)
569 {
570    int            first, last, mid, result;
571    char           pname[sNAMEMAX + 1];
572    Embryo_Header *hdr;
573
574    if (!ep) return EMBRYO_FUNCTION_NONE;
575    hdr = (Embryo_Header *)ep->code;
576    last = NUMENTRIES(hdr, publics, natives) - 1;
577    first = 0;
578    /* binary search */
579    while (first <= last)
580      {
581         mid = (first + last) / 2;
582         if (_embryo_func_get(ep, mid, pname) == EMBRYO_ERROR_NONE)
583           result = strcmp(pname, name);
584         else
585           return EMBRYO_FUNCTION_NONE;
586 /*        result = -1;*/
587         if (result > 0) last = mid - 1;
588         else if (result < 0) first = mid + 1;
589         else return mid;
590      }
591    return EMBRYO_FUNCTION_NONE;
592 }
593
594 /**
595  * @defgroup Embryo_Public_Variable_Group Public Variable Access Functions
596  *
597  * In an Embryo program, a global variable can be declared public, as
598  * described in @ref Small_Scope_Subsection.  The functions here allow
599  * the host program to access these public variables.
600  */
601
602 /**
603  * Retrieves the location of the public variable in the given program
604  * with the given name.
605  * @param   ep   The given program.
606  * @param   name The given name.
607  * @return  The address of the variable if found.  @c EMBRYO_CELL_NONE
608  *          otherwise.
609  * @ingroup Embryo_Public_Variable_Group
610  */
611 EAPI Embryo_Cell
612 embryo_program_variable_find(Embryo_Program *ep, const char *name)
613 {
614    int            first, last, mid, result;
615    char           pname[sNAMEMAX + 1];
616    Embryo_Cell    paddr;
617    Embryo_Header *hdr;
618
619    if (!ep) return EMBRYO_CELL_NONE;
620    if (!ep->base) return EMBRYO_CELL_NONE;
621    hdr = (Embryo_Header *)ep->base;
622    last = NUMENTRIES(hdr, pubvars, tags) - 1;
623    first = 0;
624    /* binary search */
625    while (first <= last)
626      {
627         mid = (first + last) / 2;
628         if (_embryo_var_get(ep, mid, pname, &paddr) == EMBRYO_ERROR_NONE)
629           result = strcmp(pname, name);
630         else
631           return EMBRYO_CELL_NONE;
632 /*        result = -1;*/
633         if (result > 0) last = mid - 1;
634         else if (result < 0) first = mid + 1;
635         else return paddr;
636      }
637    return EMBRYO_CELL_NONE;
638 }
639
640 /**
641  * Retrieves the number of public variables in the given program.
642  * @param   ep The given program.
643  * @return  The number of public variables.
644  * @ingroup Embryo_Public_Variable_Group
645  */
646 EAPI int
647 embryo_program_variable_count_get(Embryo_Program *ep)
648 {
649    Embryo_Header *hdr;
650
651    if (!ep) return 0;
652    if (!ep->base) return 0;
653    hdr = (Embryo_Header *)ep->base;
654    return NUMENTRIES(hdr, pubvars, tags);
655 }
656
657 /**
658  * Retrieves the location of the public variable in the given program
659  * with the given identifier.
660  * @param   ep  The given program.
661  * @param   num The identifier of the public variable.
662  * @return  The virtual machine address of the variable if found.
663  *          @c EMBRYO_CELL_NONE otherwise.
664  * @ingroup Embryo_Public_Variable_Group
665  */
666 EAPI Embryo_Cell
667 embryo_program_variable_get(Embryo_Program *ep, int num)
668 {
669    Embryo_Header *hdr;
670    Embryo_Cell    paddr;
671    char           pname[sNAMEMAX + 1];
672
673    if (!ep) return EMBRYO_CELL_NONE;
674    if (!ep->base) return EMBRYO_CELL_NONE;
675    hdr = (Embryo_Header *)ep->base;
676    if (_embryo_var_get(ep, num, pname, &paddr) == EMBRYO_ERROR_NONE)
677      return paddr;
678    return EMBRYO_CELL_NONE;
679 }
680
681 /**
682  * @defgroup Embryo_Error_Group Error Functions
683  *
684  * Functions that set and retrieve error codes in Embryo programs.
685  */
686
687 /**
688  * Sets the error code for the given program to the given code.
689  * @param   ep The given program.
690  * @param   error The given error code.
691  * @ingroup Embryo_Error_Group
692  */
693 EAPI void
694 embryo_program_error_set(Embryo_Program *ep, int error)
695 {
696    if (!ep) return;
697    ep->error = error;
698 }
699
700 /**
701  * Retrieves the current error code for the given program.
702  * @param   ep The given program.
703  * @return  The current error code.
704  * @ingroup Embryo_Error_Group
705  */
706 EAPI int
707 embryo_program_error_get(Embryo_Program *ep)
708 {
709    if (!ep) return EMBRYO_ERROR_NONE;
710    return ep->error;
711 }
712
713 /**
714  * @defgroup Embryo_Program_Data_Group Program Data Functions
715  *
716  * Functions that set and retrieve data associated with the given
717  * program.
718  */
719
720 /**
721  * Sets the data associated to the given program.
722  * @param   ep   The given program.
723  * @param   data New bytecode data.
724  * @ingroup Embryo_Program_Data_Group
725  */
726 EAPI void
727 embryo_program_data_set(Embryo_Program *ep, void *data)
728 {
729    if (!ep) return;
730    ep->data = data;
731 }
732
733 /**
734  * Retrieves the data associated to the given program.
735  * @param   ep The given program.
736  * @ingroup Embryo_Program_Data_Group
737  */
738 EAPI void *
739 embryo_program_data_get(Embryo_Program *ep)
740 {
741    if (!ep) return NULL;
742    return ep->data;
743 }
744
745 /**
746  * Retrieves a string describing the given error code.
747  * @param   error The given error code.
748  * @return  String describing the given error code.  If the given code is not
749  *          known, the string "(unknown)" is returned.
750  * @ingroup Embryo_Error_Group
751  */
752 EAPI const char *
753 embryo_error_string_get(int error)
754 {
755    const char *messages[] =
756      {
757         /* EMBRYO_ERROR_NONE      */ "(none)",
758           /* EMBRYO_ERROR_EXIT      */ "Forced exit",
759           /* EMBRYO_ERROR_ASSERT    */ "Assertion failed",
760           /* EMBRYO_ERROR_STACKERR  */ "Stack/heap collision (insufficient stack size)",
761           /* EMBRYO_ERROR_BOUNDS    */ "Array index out of bounds",
762           /* EMBRYO_ERROR_MEMACCESS */ "Invalid memory access",
763           /* EMBRYO_ERROR_INVINSTR  */ "Invalid instruction",
764           /* EMBRYO_ERROR_STACKLOW  */ "Stack underflow",
765           /* EMBRYO_ERROR_HEAPLOW   */ "Heap underflow",
766           /* EMBRYO_ERROR_CALLBACK  */ "No (valid) native function callback",
767           /* EMBRYO_ERROR_NATIVE    */ "Native function failed",
768           /* EMBRYO_ERROR_DIVIDE    */ "Divide by zero",
769           /* EMBRYO_ERROR_SLEEP     */ "(sleep mode)",
770           /* 13 */                     "(reserved)",
771           /* 14 */                     "(reserved)",
772           /* 15 */                     "(reserved)",
773           /* EMBRYO_ERROR_MEMORY    */ "Out of memory",
774           /* EMBRYO_ERROR_FORMAT    */ "Invalid/unsupported P-code file format",
775           /* EMBRYO_ERROR_VERSION   */ "File is for a newer version of the Embryo_Program",
776           /* EMBRYO_ERROR_NOTFOUND  */ "Native/Public function is not found",
777           /* EMBRYO_ERROR_INDEX     */ "Invalid index parameter (bad entry point)",
778           /* EMBRYO_ERROR_DEBUG     */ "Debugger cannot run",
779           /* EMBRYO_ERROR_INIT      */ "Embryo_Program not initialized (or doubly initialized)",
780           /* EMBRYO_ERROR_USERDATA  */ "Unable to set user data field (table full)",
781           /* EMBRYO_ERROR_INIT_JIT  */ "Cannot initialize the JIT",
782           /* EMBRYO_ERROR_PARAMS    */ "Parameter error",
783      };
784    if ((error < 0) || (error >= (int)(sizeof(messages) / sizeof(messages[0]))))
785      return (const char *)"(unknown)";
786    return messages[error];
787 }
788
789 /**
790  * @defgroup Embryo_Data_String_Group Embryo Data String Functions
791  *
792  * Functions that operate on strings in the memory of a virtual machine.
793  */
794
795 /**
796  * Retrieves the length of the string starting at the given cell.
797  * @param   ep       The program the cell is part of.
798  * @param   str_cell Pointer to the first cell of the string.
799  * @return  The length of the string.  @c 0 is returned if there is an error.
800  * @ingroup Embryo_Data_String_Group
801  */
802 EAPI int
803 embryo_data_string_length_get(Embryo_Program *ep, Embryo_Cell *str_cell)
804 {
805    int            len;
806    Embryo_Header *hdr;
807
808    if ((!ep) || (!ep->base)) return 0;
809    hdr = (Embryo_Header *)ep->base;
810    if ((!str_cell) ||
811        ((void *)str_cell >= (void *)(ep->base + hdr->stp)) ||
812        ((void *)str_cell < (void *)ep->base))
813      return 0;
814    for (len = 0; str_cell[len] != 0; len++);
815    return len;
816 }
817
818 /**
819  * Copies the string starting at the given cell to the given buffer.
820  * @param   ep       The program the cell is part of.
821  * @param   str_cell Pointer to the first cell of the string.
822  * @param   dst      The given buffer.
823  * @ingroup Embryo_Data_String_Group
824  */
825 EAPI void
826 embryo_data_string_get(Embryo_Program *ep, Embryo_Cell *str_cell, char *dst)
827 {
828    int            i;
829    Embryo_Header *hdr;
830
831    if (!dst) return;
832    if ((!ep) || (!ep->base))
833      {
834         dst[0] = 0;
835         return;
836      }
837    hdr = (Embryo_Header *)ep->base;
838    if ((!str_cell) ||
839        ((void *)str_cell >= (void *)(ep->base + hdr->stp)) ||
840        ((void *)str_cell < (void *)ep->base))
841      {
842         dst[0] = 0;
843         return;
844      }
845    for (i = 0; str_cell[i] != 0; i++)
846      {
847 #ifdef WORDS_BIGENDIAN
848           {
849              Embryo_Cell tmp;
850
851              tmp = str_cell[i];
852              _embryo_byte_swap_32(&tmp);
853              dst[i] = tmp;
854           }
855 #else
856         dst[i] = str_cell[i];
857 #endif
858      }
859    dst[i] = 0;
860 }
861
862 /**
863  * Copies string in the given buffer into the virtual machine memory
864  * starting at the given cell.
865  * @param ep       The program the cell is part of.
866  * @param src      The given buffer.
867  * @param str_cell Pointer to the first cell to copy the string to.
868  * @ingroup Embryo_Data_String_Group
869  */
870 EAPI void
871 embryo_data_string_set(Embryo_Program *ep, const char *src, Embryo_Cell *str_cell)
872 {
873    int            i;
874    Embryo_Header *hdr;
875
876    if (!ep) return;
877    if (!ep->base) return;
878    hdr = (Embryo_Header *)ep->base;
879    if ((!str_cell) ||
880        ((void *)str_cell >= (void *)(ep->base + hdr->stp)) ||
881        ((void *)str_cell < (void *)ep->base))
882      return;
883    if (!src)
884      {
885         str_cell[0] = 0;
886         return;
887      }
888    for (i = 0; src[i] != 0; i++)
889      {
890         if ((void *)(&(str_cell[i])) >= (void *)(ep->base + hdr->stp)) return;
891         else if ((void *)(&(str_cell[i])) == (void *)(ep->base + hdr->stp - 1))
892           {
893              str_cell[i] = 0;
894              return;
895           }
896 #ifdef WORDS_BIGENDIAN
897           {
898              Embryo_Cell tmp;
899
900              tmp = src[i];
901              _embryo_byte_swap_32(&tmp);
902              str_cell[i] = tmp;
903           }
904 #else
905         str_cell[i] = src[i];
906 #endif
907      }
908    str_cell[i] = 0;
909 }
910
911 /**
912  * Retreives a pointer to the address in the virtual machine given by the
913  * given cell.
914  * @param   ep   The program whose virtual machine address is being queried.
915  * @param   addr The given cell.
916  * @return  A pointer to the cell at the given address.
917  * @ingroup Embryo_Data_String_Group
918  */
919 EAPI Embryo_Cell *
920 embryo_data_address_get(Embryo_Program *ep, Embryo_Cell addr)
921 {
922    Embryo_Header *hdr;
923    unsigned char *data;
924
925    if ((!ep) || (!ep->base)) return NULL;
926    hdr = (Embryo_Header *)ep->base;
927    data = ep->base + (int)hdr->dat;
928    if ((addr < 0) || (addr >= hdr->stp)) return NULL;
929    return (Embryo_Cell *)(data + (int)addr);
930 }
931
932 /**
933  * @defgroup Embryo_Heap_Group Heap Functions
934  *
935  * The heap is an area of memory that can be allocated for program
936  * use at runtime.  The heap functions here change the amount of heap
937  * memory available.
938  */
939
940 /**
941  * Increases the size of the heap of the given virtual machine by the given
942  * number of Embryo_Cells.
943  * @param   ep    The program with the given virtual machine.
944  * @param   cells The given number of Embryo_Cells.
945  * @return  The address of the new memory region on success.
946  *          @c EMBRYO_CELL_NONE otherwise.
947  * @ingroup Embryo_Heap_Group
948  */
949 EAPI Embryo_Cell
950 embryo_data_heap_push(Embryo_Program *ep, int cells)
951 {
952    Embryo_Header *hdr;
953    unsigned char *data;
954    Embryo_Cell    addr;
955
956    if ((!ep) || (!ep->base)) return EMBRYO_CELL_NONE;
957    hdr = (Embryo_Header *)ep->base;
958    data = ep->base + (int)hdr->dat;
959    if (ep->stk - ep->hea - (cells * sizeof(Embryo_Cell)) < STKMARGIN)
960      return EMBRYO_CELL_NONE;
961    addr = ep->hea;
962    ep->hea += (cells * sizeof(Embryo_Cell));
963    return addr;
964 }
965
966 /**
967  * Decreases the size of the heap of the given virtual machine down to the
968  * given size.
969  * @param   ep      The program with the given virtual machine.
970  * @param   down_to The given size.
971  * @ingroup Embryo_Heap_Group
972  */
973 EAPI void
974 embryo_data_heap_pop(Embryo_Program *ep, Embryo_Cell down_to)
975 {
976    if (!ep) return;
977    if (down_to < 0) down_to = 0;
978    if (ep->hea > down_to) ep->hea = down_to;
979 }
980
981 /**
982  * @defgroup Embryo_Run_Group Program Run Functions
983  *
984  * Functions that are involved in actually running functions in an
985  * Embryo program.
986  */
987
988 /**
989  * Returns the number of virtual machines are running for the given program.
990  * @param   ep The given program.
991  * @return  The number of virtual machines running.
992  * @ingroup Embryo_Run_Group
993  */
994 EAPI int
995 embryo_program_recursion_get(Embryo_Program *ep)
996 {
997    return ep->run_count;
998 }
999
1000 #ifdef __GNUC__
1001 #if 1
1002 #define EMBRYO_EXEC_JUMPTABLE
1003 #endif
1004 #endif
1005
1006 /* jump table optimization - only works for gcc though */
1007 #ifdef EMBRYO_EXEC_JUMPTABLE
1008 #define SWITCH(x) while (1) { goto *switchtable[x];
1009 #define SWITCHEND break; }
1010 #define CASE(x) SWITCHTABLE_##x:
1011 #define BREAK break;
1012 #else
1013 #define SWITCH(x) switch (x) {
1014 #define SWITCHEND }
1015 #define CASE(x) case x:
1016 #define BREAK break
1017 #endif
1018
1019 /**
1020  * Runs the given function of the given Embryo program in the current
1021  * virtual machine.  The parameter @p fn can be found using
1022  * @ref embryo_program_function_find.
1023  *
1024  * @note For Embryo to be able to run a function, it must have been
1025  *       declared @c public in the Small source code.
1026  *
1027  * @param   ep The given program.
1028  * @param   fn The given function.  Normally "main", in which case the
1029  *             constant @c EMBRYO_FUNCTION_MAIN can be used.
1030  * @return  @c EMBRYO_PROGRAM_OK on success.  @c EMBRYO_PROGRAM_SLEEP if the
1031  *          program is halted by the Small @c sleep call.
1032  *          @c EMBRYO_PROGRAM_FAIL if there is an error.
1033  *          @c EMBRYO_PROGRAM_TOOLONG if the program executes for longer than
1034  *          it is allowed to in abstract machine instruction count.
1035  * @ingroup Embryo_Run_Group
1036  */
1037 EAPI int
1038 embryo_program_run(Embryo_Program *ep, Embryo_Function fn)
1039 {
1040    Embryo_Header    *hdr;
1041    Embryo_Func_Stub *func;
1042    unsigned char    *code, *data;
1043    Embryo_Cell      pri, alt, stk, frm, hea, hea_start;
1044    Embryo_Cell      reset_stk, reset_hea, *cip;
1045    Embryo_UCell     codesize;
1046    int              i;
1047    unsigned char    op;
1048    Embryo_Cell      offs;
1049    int              num;
1050    int              max_run_cycles;
1051    int              cycle_count;
1052 #ifdef EMBRYO_EXEC_JUMPTABLE
1053    /* we limit the jumptable to 256 elements. why? above we forced "op" to be
1054     * a unsigned char - that means 256 max values. we limit opcode overflow
1055     * here, so eliminating crashes on table lookups with bad/corrupt bytecode.
1056     * no need to atuall do compares, branches etc. the datatype does the work
1057     * for us. so that means EXCESS elements are all declared as OP_NONE to
1058     * keep them innocuous.
1059     */
1060    static const void *switchtable[256] =
1061      {
1062            &&SWITCHTABLE_EMBRYO_OP_NONE,
1063                &&SWITCHTABLE_EMBRYO_OP_LOAD_PRI,
1064                &&SWITCHTABLE_EMBRYO_OP_LOAD_ALT,
1065                &&SWITCHTABLE_EMBRYO_OP_LOAD_S_PRI,
1066                &&SWITCHTABLE_EMBRYO_OP_LOAD_S_ALT,
1067                &&SWITCHTABLE_EMBRYO_OP_LREF_PRI,
1068                &&SWITCHTABLE_EMBRYO_OP_LREF_ALT,
1069                &&SWITCHTABLE_EMBRYO_OP_LREF_S_PRI,
1070                &&SWITCHTABLE_EMBRYO_OP_LREF_S_ALT,
1071                &&SWITCHTABLE_EMBRYO_OP_LOAD_I,
1072                &&SWITCHTABLE_EMBRYO_OP_LODB_I,
1073                &&SWITCHTABLE_EMBRYO_OP_CONST_PRI,
1074                &&SWITCHTABLE_EMBRYO_OP_CONST_ALT,
1075                &&SWITCHTABLE_EMBRYO_OP_ADDR_PRI,
1076                &&SWITCHTABLE_EMBRYO_OP_ADDR_ALT,
1077                &&SWITCHTABLE_EMBRYO_OP_STOR_PRI,
1078                &&SWITCHTABLE_EMBRYO_OP_STOR_ALT,
1079                &&SWITCHTABLE_EMBRYO_OP_STOR_S_PRI,
1080                &&SWITCHTABLE_EMBRYO_OP_STOR_S_ALT,
1081                &&SWITCHTABLE_EMBRYO_OP_SREF_PRI,
1082                &&SWITCHTABLE_EMBRYO_OP_SREF_ALT,
1083                &&SWITCHTABLE_EMBRYO_OP_SREF_S_PRI,
1084                &&SWITCHTABLE_EMBRYO_OP_SREF_S_ALT,
1085                &&SWITCHTABLE_EMBRYO_OP_STOR_I,
1086                &&SWITCHTABLE_EMBRYO_OP_STRB_I,
1087                &&SWITCHTABLE_EMBRYO_OP_LIDX,
1088                &&SWITCHTABLE_EMBRYO_OP_LIDX_B,
1089                &&SWITCHTABLE_EMBRYO_OP_IDXADDR,
1090                &&SWITCHTABLE_EMBRYO_OP_IDXADDR_B,
1091                &&SWITCHTABLE_EMBRYO_OP_ALIGN_PRI,
1092                &&SWITCHTABLE_EMBRYO_OP_ALIGN_ALT,
1093                &&SWITCHTABLE_EMBRYO_OP_LCTRL,
1094                &&SWITCHTABLE_EMBRYO_OP_SCTRL,
1095                &&SWITCHTABLE_EMBRYO_OP_MOVE_PRI,
1096                &&SWITCHTABLE_EMBRYO_OP_MOVE_ALT,
1097                &&SWITCHTABLE_EMBRYO_OP_XCHG,
1098                &&SWITCHTABLE_EMBRYO_OP_PUSH_PRI,
1099                &&SWITCHTABLE_EMBRYO_OP_PUSH_ALT,
1100                &&SWITCHTABLE_EMBRYO_OP_PUSH_R,
1101                &&SWITCHTABLE_EMBRYO_OP_PUSH_C,
1102                &&SWITCHTABLE_EMBRYO_OP_PUSH,
1103                &&SWITCHTABLE_EMBRYO_OP_PUSH_S,
1104                &&SWITCHTABLE_EMBRYO_OP_POP_PRI,
1105                &&SWITCHTABLE_EMBRYO_OP_POP_ALT,
1106                &&SWITCHTABLE_EMBRYO_OP_STACK,
1107                &&SWITCHTABLE_EMBRYO_OP_HEAP,
1108                &&SWITCHTABLE_EMBRYO_OP_PROC,
1109                &&SWITCHTABLE_EMBRYO_OP_RET,
1110                &&SWITCHTABLE_EMBRYO_OP_RETN,
1111                &&SWITCHTABLE_EMBRYO_OP_CALL,
1112                &&SWITCHTABLE_EMBRYO_OP_CALL_PRI,
1113                &&SWITCHTABLE_EMBRYO_OP_JUMP,
1114                &&SWITCHTABLE_EMBRYO_OP_JREL,
1115                &&SWITCHTABLE_EMBRYO_OP_JZER,
1116                &&SWITCHTABLE_EMBRYO_OP_JNZ,
1117                &&SWITCHTABLE_EMBRYO_OP_JEQ,
1118                &&SWITCHTABLE_EMBRYO_OP_JNEQ,
1119                &&SWITCHTABLE_EMBRYO_OP_JLESS,
1120                &&SWITCHTABLE_EMBRYO_OP_JLEQ,
1121                &&SWITCHTABLE_EMBRYO_OP_JGRTR,
1122                &&SWITCHTABLE_EMBRYO_OP_JGEQ,
1123                &&SWITCHTABLE_EMBRYO_OP_JSLESS,
1124                &&SWITCHTABLE_EMBRYO_OP_JSLEQ,
1125                &&SWITCHTABLE_EMBRYO_OP_JSGRTR,
1126                &&SWITCHTABLE_EMBRYO_OP_JSGEQ,
1127                &&SWITCHTABLE_EMBRYO_OP_SHL,
1128                &&SWITCHTABLE_EMBRYO_OP_SHR,
1129                &&SWITCHTABLE_EMBRYO_OP_SSHR,
1130                &&SWITCHTABLE_EMBRYO_OP_SHL_C_PRI,
1131                &&SWITCHTABLE_EMBRYO_OP_SHL_C_ALT,
1132                &&SWITCHTABLE_EMBRYO_OP_SHR_C_PRI,
1133                &&SWITCHTABLE_EMBRYO_OP_SHR_C_ALT,
1134                &&SWITCHTABLE_EMBRYO_OP_SMUL,
1135                &&SWITCHTABLE_EMBRYO_OP_SDIV,
1136                &&SWITCHTABLE_EMBRYO_OP_SDIV_ALT,
1137                &&SWITCHTABLE_EMBRYO_OP_UMUL,
1138                &&SWITCHTABLE_EMBRYO_OP_UDIV,
1139                &&SWITCHTABLE_EMBRYO_OP_UDIV_ALT,
1140                &&SWITCHTABLE_EMBRYO_OP_ADD,
1141                &&SWITCHTABLE_EMBRYO_OP_SUB,
1142                &&SWITCHTABLE_EMBRYO_OP_SUB_ALT,
1143                &&SWITCHTABLE_EMBRYO_OP_AND,
1144                &&SWITCHTABLE_EMBRYO_OP_OR,
1145                &&SWITCHTABLE_EMBRYO_OP_XOR,
1146                &&SWITCHTABLE_EMBRYO_OP_NOT,
1147                &&SWITCHTABLE_EMBRYO_OP_NEG,
1148                &&SWITCHTABLE_EMBRYO_OP_INVERT,
1149                &&SWITCHTABLE_EMBRYO_OP_ADD_C,
1150                &&SWITCHTABLE_EMBRYO_OP_SMUL_C,
1151                &&SWITCHTABLE_EMBRYO_OP_ZERO_PRI,
1152                &&SWITCHTABLE_EMBRYO_OP_ZERO_ALT,
1153                &&SWITCHTABLE_EMBRYO_OP_ZERO,
1154                &&SWITCHTABLE_EMBRYO_OP_ZERO_S,
1155                &&SWITCHTABLE_EMBRYO_OP_SIGN_PRI,
1156                &&SWITCHTABLE_EMBRYO_OP_SIGN_ALT,
1157                &&SWITCHTABLE_EMBRYO_OP_EQ,
1158                &&SWITCHTABLE_EMBRYO_OP_NEQ,
1159                &&SWITCHTABLE_EMBRYO_OP_LESS,
1160                &&SWITCHTABLE_EMBRYO_OP_LEQ,
1161                &&SWITCHTABLE_EMBRYO_OP_GRTR,
1162                &&SWITCHTABLE_EMBRYO_OP_GEQ,
1163                &&SWITCHTABLE_EMBRYO_OP_SLESS,
1164                &&SWITCHTABLE_EMBRYO_OP_SLEQ,
1165                &&SWITCHTABLE_EMBRYO_OP_SGRTR,
1166                &&SWITCHTABLE_EMBRYO_OP_SGEQ,
1167                &&SWITCHTABLE_EMBRYO_OP_EQ_C_PRI,
1168                &&SWITCHTABLE_EMBRYO_OP_EQ_C_ALT,
1169                &&SWITCHTABLE_EMBRYO_OP_INC_PRI,
1170                &&SWITCHTABLE_EMBRYO_OP_INC_ALT,
1171                &&SWITCHTABLE_EMBRYO_OP_INC,
1172                &&SWITCHTABLE_EMBRYO_OP_INC_S,
1173                &&SWITCHTABLE_EMBRYO_OP_INC_I,
1174                &&SWITCHTABLE_EMBRYO_OP_DEC_PRI,
1175                &&SWITCHTABLE_EMBRYO_OP_DEC_ALT,
1176                &&SWITCHTABLE_EMBRYO_OP_DEC,
1177                &&SWITCHTABLE_EMBRYO_OP_DEC_S,
1178                &&SWITCHTABLE_EMBRYO_OP_DEC_I,
1179                &&SWITCHTABLE_EMBRYO_OP_MOVS,
1180                &&SWITCHTABLE_EMBRYO_OP_CMPS,
1181                &&SWITCHTABLE_EMBRYO_OP_FILL,
1182                &&SWITCHTABLE_EMBRYO_OP_HALT,
1183                &&SWITCHTABLE_EMBRYO_OP_BOUNDS,
1184                &&SWITCHTABLE_EMBRYO_OP_SYSREQ_PRI,
1185                &&SWITCHTABLE_EMBRYO_OP_SYSREQ_C,
1186                &&SWITCHTABLE_EMBRYO_OP_FILE,
1187                &&SWITCHTABLE_EMBRYO_OP_LINE,
1188                &&SWITCHTABLE_EMBRYO_OP_SYMBOL,
1189                &&SWITCHTABLE_EMBRYO_OP_SRANGE,
1190                &&SWITCHTABLE_EMBRYO_OP_JUMP_PRI,
1191                &&SWITCHTABLE_EMBRYO_OP_SWITCH,
1192                &&SWITCHTABLE_EMBRYO_OP_CASETBL,
1193                &&SWITCHTABLE_EMBRYO_OP_SWAP_PRI,
1194                &&SWITCHTABLE_EMBRYO_OP_SWAP_ALT,
1195                &&SWITCHTABLE_EMBRYO_OP_PUSHADDR,
1196                &&SWITCHTABLE_EMBRYO_OP_NOP,
1197                &&SWITCHTABLE_EMBRYO_OP_SYSREQ_D,
1198                &&SWITCHTABLE_EMBRYO_OP_SYMTAG,
1199           &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE,
1200           &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE,
1201           &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE,
1202           &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE,
1203           &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE,
1204           &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE,
1205           &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE,
1206           &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE,
1207           &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE,
1208           &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE,
1209           &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE,
1210           &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE,
1211           &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE,
1212           &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE,
1213           &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE,
1214           &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE,
1215           &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE,
1216           &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE,
1217           &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE,
1218           &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE,
1219           &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE,
1220           &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE,
1221           &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE,
1222           &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE, &&SWITCHTABLE_EMBRYO_OP_NONE
1223      };
1224 #endif
1225    if (!ep) return EMBRYO_PROGRAM_FAIL;
1226    if (!(ep->flags & EMBRYO_FLAG_RELOC))
1227      {
1228         ep->error = EMBRYO_ERROR_INIT;
1229         return EMBRYO_PROGRAM_FAIL;
1230      }
1231    if (!ep->base)
1232      {
1233         ep->error = EMBRYO_ERROR_INIT;
1234         return EMBRYO_PROGRAM_FAIL;
1235      }
1236    if (ep->run_count > 0)
1237      {
1238         /* return EMBRYO_PROGRAM_BUSY; */
1239         /* FIXME: test C->vm->C->vm recursion more fully */
1240         /* it seems to work... just fine!!! - strange! */
1241      }
1242
1243    /* set up the registers */
1244    hdr = (Embryo_Header *)ep->base;
1245    codesize = (Embryo_UCell)(hdr->dat - hdr->cod);
1246    code = ep->base + (int)hdr->cod;
1247    data = ep->base + (int)hdr->dat;
1248    hea_start = hea = ep->hea;
1249    stk = ep->stk;
1250    reset_stk = stk;
1251    reset_hea = hea;
1252    frm = alt = pri = 0;
1253
1254    /* get the start address */
1255    if (fn == EMBRYO_FUNCTION_MAIN)
1256      {
1257         if (hdr->cip < 0)
1258           {
1259              ep->error = EMBRYO_ERROR_INDEX;
1260              return EMBRYO_PROGRAM_FAIL;
1261           }
1262         cip = (Embryo_Cell *)(code + (int)hdr->cip);
1263      }
1264    else if (fn == EMBRYO_FUNCTION_CONT)
1265      {
1266         /* all registers: pri, alt, frm, cip, hea, stk, reset_stk, reset_hea */
1267         frm = ep->frm;
1268         stk = ep->stk;
1269         hea = ep->hea;
1270         pri = ep->pri;
1271         alt = ep->alt;
1272         reset_stk = ep->reset_stk;
1273         reset_hea = ep->reset_hea;
1274         cip = (Embryo_Cell *)(code + (int)ep->cip);
1275      }
1276    else if (fn < 0)
1277      {
1278         ep->error = EMBRYO_ERROR_INDEX;
1279         return EMBRYO_PROGRAM_FAIL;
1280      }
1281    else
1282      {
1283         if (fn >= (Embryo_Cell)NUMENTRIES(hdr, publics, natives))
1284           {
1285              ep->error = EMBRYO_ERROR_INDEX;
1286              return EMBRYO_PROGRAM_FAIL;
1287           }
1288         func = GETENTRY(hdr, publics, fn);
1289         cip = (Embryo_Cell *)(code + (int)func->address);
1290      }
1291    /* check values just copied */
1292    CHKSTACK();
1293    CHKHEAP();
1294
1295    if (fn != EMBRYO_FUNCTION_CONT)
1296      {
1297         int i;
1298
1299         for (i = ep->params_size - 1; i >= 0; i--)
1300           {
1301              Embryo_Param *pr;
1302
1303              pr = &(ep->params[i]);
1304              if (pr->string)
1305                {
1306                   int len;
1307                   Embryo_Cell ep_addr, *addr;
1308
1309                   len = strlen(pr->string);
1310                   ep_addr = embryo_data_heap_push(ep, len + 1);
1311                   if (ep_addr == EMBRYO_CELL_NONE)
1312                     {
1313                        ep->error = EMBRYO_ERROR_HEAPLOW;
1314                        return EMBRYO_PROGRAM_FAIL;
1315                     }
1316                   addr = embryo_data_address_get(ep, ep_addr);
1317                   if (addr)
1318                     embryo_data_string_set(ep, pr->string, addr);
1319                   else
1320                     {
1321                        ep->error = EMBRYO_ERROR_HEAPLOW;
1322                        return EMBRYO_PROGRAM_FAIL;
1323                     }
1324                   PUSH(ep_addr);
1325                   free(pr->string);
1326                }
1327              else if (pr->cell_array)
1328                {
1329                   int len;
1330                   Embryo_Cell ep_addr, *addr;
1331
1332                   len = pr->cell_array_size;
1333                   ep_addr = embryo_data_heap_push(ep, len + 1);
1334                   if (ep_addr == EMBRYO_CELL_NONE)
1335                     {
1336                        ep->error = EMBRYO_ERROR_HEAPLOW;
1337                        return EMBRYO_PROGRAM_FAIL;
1338                     }
1339                   addr = embryo_data_address_get(ep, ep_addr);
1340                   if (addr)
1341                     memcpy(addr, pr->cell_array,
1342                            pr->cell_array_size * sizeof(Embryo_Cell));
1343                   else
1344                     {
1345                        ep->error = EMBRYO_ERROR_HEAPLOW;
1346                        return EMBRYO_PROGRAM_FAIL;
1347                     }
1348                   PUSH(ep_addr);
1349                   free(pr->cell_array);
1350                }
1351              else
1352                {
1353                   PUSH(pr->cell);
1354                }
1355           }
1356         PUSH(ep->params_size * sizeof(Embryo_Cell));
1357         PUSH(0);
1358         if (ep->params)
1359           {
1360              free(ep->params);
1361              ep->params = NULL;
1362           }
1363         ep->params_size = ep->params_alloc = 0;
1364      }
1365    /* check stack/heap before starting to run */
1366    CHKMARGIN();
1367
1368    /* track recursion depth */
1369    ep->run_count++;
1370
1371    max_run_cycles = ep->max_run_cycles;
1372    /* start running */
1373    for (cycle_count = 0;;)
1374      {
1375         if (max_run_cycles > 0)
1376           {
1377              if (cycle_count >= max_run_cycles)
1378                {
1379                   TOOLONG(ep);
1380                }
1381              cycle_count++;
1382           }
1383         op = (Embryo_Opcode)*cip++;
1384         SWITCH(op);
1385         CASE(EMBRYO_OP_LOAD_PRI);
1386         GETPARAM(offs);
1387         pri = *(Embryo_Cell *)(data + (int)offs);
1388         BREAK;
1389         CASE(EMBRYO_OP_LOAD_ALT);
1390         GETPARAM(offs);
1391         alt = *(Embryo_Cell *)(data + (int)offs);
1392         BREAK;
1393         CASE(EMBRYO_OP_LOAD_S_PRI);
1394         GETPARAM(offs);
1395         pri = *(Embryo_Cell *)(data + (int)frm + (int)offs);
1396         BREAK;
1397         CASE(EMBRYO_OP_LOAD_S_ALT);
1398         GETPARAM(offs);
1399         alt = *(Embryo_Cell *)(data + (int)frm + (int)offs);
1400         BREAK;
1401         CASE(EMBRYO_OP_LREF_PRI);
1402         GETPARAM(offs);
1403         offs = *(Embryo_Cell *)(data + (int)offs);
1404         pri = *(Embryo_Cell *)(data + (int)offs);
1405         BREAK;
1406         CASE(EMBRYO_OP_LREF_ALT);
1407         GETPARAM(offs);
1408         offs = *(Embryo_Cell *)(data + (int)offs);
1409         alt = *(Embryo_Cell *)(data + (int)offs);
1410         BREAK;
1411         CASE(EMBRYO_OP_LREF_S_PRI);
1412         GETPARAM(offs);
1413         offs = *(Embryo_Cell *)(data + (int)frm + (int)offs);
1414         pri = *(Embryo_Cell *)(data + (int)offs);
1415         BREAK;
1416         CASE(EMBRYO_OP_LREF_S_ALT);
1417         GETPARAM(offs);
1418         offs = *(Embryo_Cell *)(data + (int)frm + (int)offs);
1419         alt = *(Embryo_Cell *)(data + (int)offs);
1420         BREAK;
1421         CASE(EMBRYO_OP_LOAD_I);
1422         CHKMEM(pri);
1423         pri = *(Embryo_Cell *)(data + (int)pri);
1424         BREAK;
1425         CASE(EMBRYO_OP_LODB_I);
1426         GETPARAM(offs);
1427         CHKMEM(pri);
1428         switch (offs)
1429           {
1430            case 1:
1431              pri = *(data + (int)pri);
1432              break;
1433            case 2:
1434              pri = *(unsigned short *)(data + (int)pri);
1435              break;
1436            case 4:
1437              pri = *(unsigned int *)(data + (int)pri);
1438              break;
1439            default:
1440              ABORT(ep, EMBRYO_ERROR_INVINSTR);
1441              break;
1442           }
1443         BREAK;
1444         CASE(EMBRYO_OP_CONST_PRI);
1445         GETPARAM(pri);
1446         BREAK;
1447         CASE(EMBRYO_OP_CONST_ALT);
1448         GETPARAM(alt);
1449         BREAK;
1450         CASE(EMBRYO_OP_ADDR_PRI);
1451         GETPARAM(pri);
1452         pri += frm;
1453         BREAK;
1454         CASE(EMBRYO_OP_ADDR_ALT);
1455         GETPARAM(alt);
1456         alt += frm;
1457         BREAK;
1458         CASE(EMBRYO_OP_STOR_PRI);
1459         GETPARAM(offs);
1460         *(Embryo_Cell *)(data + (int)offs) = pri;
1461         BREAK;
1462         CASE(EMBRYO_OP_STOR_ALT);
1463         GETPARAM(offs);
1464         *(Embryo_Cell *)(data + (int)offs) = alt;
1465         BREAK;
1466         CASE(EMBRYO_OP_STOR_S_PRI);
1467         GETPARAM(offs);
1468         *(Embryo_Cell *)(data + (int)frm + (int)offs) = pri;
1469         BREAK;
1470         CASE(EMBRYO_OP_STOR_S_ALT);
1471         GETPARAM(offs);
1472         *(Embryo_Cell *)(data + (int)frm + (int)offs) = alt;
1473         BREAK;
1474         CASE(EMBRYO_OP_SREF_PRI);
1475         GETPARAM(offs);
1476         offs = *(Embryo_Cell *)(data + (int)offs);
1477         *(Embryo_Cell *)(data + (int)offs) = pri;
1478         BREAK;
1479         CASE(EMBRYO_OP_SREF_ALT);
1480         GETPARAM(offs);
1481         offs = *(Embryo_Cell *)(data + (int)offs);
1482         *(Embryo_Cell *)(data + (int)offs) = alt;
1483         BREAK;
1484         CASE(EMBRYO_OP_SREF_S_PRI);
1485         GETPARAM(offs);
1486         offs = *(Embryo_Cell *)(data + (int)frm + (int)offs);
1487         *(Embryo_Cell *)(data + (int)offs) = pri;
1488         BREAK;
1489         CASE(EMBRYO_OP_SREF_S_ALT);
1490         GETPARAM(offs);
1491         offs = *(Embryo_Cell *)(data + (int)frm + (int)offs);
1492         *(Embryo_Cell *)(data + (int)offs) = alt;
1493         BREAK;
1494         CASE(EMBRYO_OP_STOR_I);
1495         CHKMEM(alt);
1496         *(Embryo_Cell *)(data + (int)alt) = pri;
1497         BREAK;
1498         CASE(EMBRYO_OP_STRB_I);
1499         GETPARAM(offs);
1500         CHKMEM(alt);
1501         switch (offs)
1502           {
1503            case 1:
1504              *(data + (int)alt) = (unsigned char)pri;
1505              break;
1506            case 2:
1507              *(unsigned short *)(data + (int)alt) = (unsigned short)pri;
1508              break;
1509            case 4:
1510              *(unsigned int *)(data + (int)alt) = (unsigned int)pri;
1511              break;
1512            default:
1513              ABORT(ep, EMBRYO_ERROR_INVINSTR);
1514              break;
1515           }
1516         BREAK;
1517         CASE(EMBRYO_OP_LIDX);
1518         offs = (pri * sizeof(Embryo_Cell)) + alt;
1519         CHKMEM(offs);
1520         pri = *(Embryo_Cell *)(data + (int)offs);
1521         BREAK;
1522         CASE(EMBRYO_OP_LIDX_B);
1523         GETPARAM(offs);
1524         offs = (pri << (int)offs) + alt;
1525         CHKMEM(offs);
1526         pri = *(Embryo_Cell *)(data + (int)offs);
1527         BREAK;
1528         CASE(EMBRYO_OP_IDXADDR);
1529         pri = (pri * sizeof(Embryo_Cell)) + alt;
1530         BREAK;
1531         CASE(EMBRYO_OP_IDXADDR_B);
1532         GETPARAM(offs);
1533         pri = (pri << (int)offs) + alt;
1534         BREAK;
1535         CASE(EMBRYO_OP_ALIGN_PRI);
1536         GETPARAM(offs);
1537 #ifdef WORDS_BIGENDIAN
1538         if ((size_t)offs < sizeof(Embryo_Cell))
1539           pri ^= sizeof(Embryo_Cell) - offs;
1540 #endif
1541         BREAK;
1542         CASE(EMBRYO_OP_ALIGN_ALT);
1543         GETPARAM(offs);
1544 #ifdef WORDS_BIGENDIAN
1545         if ((size_t)offs < sizeof(Embryo_Cell))
1546           alt ^= sizeof(Embryo_Cell) - offs;
1547 #endif
1548         BREAK;
1549         CASE(EMBRYO_OP_LCTRL);
1550         GETPARAM(offs);
1551         switch (offs)
1552           {
1553            case 0:
1554              pri = hdr->cod;
1555              break;
1556            case 1:
1557              pri = hdr->dat;
1558              break;
1559            case 2:
1560              pri = hea;
1561              break;
1562            case 3:
1563              pri = ep->stp;
1564              break;
1565            case 4:
1566              pri = stk;
1567              break;
1568            case 5:
1569              pri = frm;
1570              break;
1571            case 6:
1572              pri = (Embryo_Cell)((unsigned char *)cip - code);
1573              break;
1574            default:
1575              ABORT(ep, EMBRYO_ERROR_INVINSTR);
1576              break;
1577           }
1578         BREAK;
1579         CASE(EMBRYO_OP_SCTRL);
1580         GETPARAM(offs);
1581         switch (offs)
1582           {
1583            case 0:
1584            case 1:
1585            case 2:
1586              hea = pri;
1587              break;
1588            case 3:
1589              /* cannot change these parameters */
1590              break;
1591            case 4:
1592              stk = pri;
1593              break;
1594            case 5:
1595              frm = pri;
1596              break;
1597            case 6:
1598              cip = (Embryo_Cell *)(code + (int)pri);
1599              break;
1600            default:
1601              ABORT(ep, EMBRYO_ERROR_INVINSTR);
1602              break;
1603           }
1604         BREAK;
1605         CASE(EMBRYO_OP_MOVE_PRI);
1606         pri = alt;
1607         BREAK;
1608         CASE(EMBRYO_OP_MOVE_ALT);
1609         alt = pri;
1610         BREAK;
1611         CASE(EMBRYO_OP_XCHG);
1612         offs = pri;         /* offs is a temporary variable */
1613         pri = alt;
1614         alt = offs;
1615         BREAK;
1616         CASE(EMBRYO_OP_PUSH_PRI);
1617         PUSH(pri);
1618         BREAK;
1619         CASE(EMBRYO_OP_PUSH_ALT);
1620         PUSH(alt);
1621         BREAK;
1622         CASE(EMBRYO_OP_PUSH_C);
1623         GETPARAM(offs);
1624         PUSH(offs);
1625         BREAK;
1626         CASE(EMBRYO_OP_PUSH_R);
1627         GETPARAM(offs);
1628         while (offs--) PUSH(pri);
1629         BREAK;
1630         CASE(EMBRYO_OP_PUSH);
1631         GETPARAM(offs);
1632         PUSH(*(Embryo_Cell *)(data + (int)offs));
1633         BREAK;
1634         CASE(EMBRYO_OP_PUSH_S);
1635         GETPARAM(offs);
1636         PUSH(*(Embryo_Cell *)(data + (int)frm + (int)offs));
1637         BREAK;
1638         CASE(EMBRYO_OP_POP_PRI);
1639         POP(pri);
1640         BREAK;
1641         CASE(EMBRYO_OP_POP_ALT);
1642         POP(alt);
1643         BREAK;
1644         CASE(EMBRYO_OP_STACK);
1645         GETPARAM(offs);
1646         alt = stk;
1647         stk += offs;
1648         CHKMARGIN();
1649         CHKSTACK();
1650         BREAK;
1651         CASE(EMBRYO_OP_HEAP);
1652         GETPARAM(offs);
1653         alt = hea;
1654         hea += offs;
1655         CHKMARGIN();
1656         CHKHEAP();
1657         BREAK;
1658         CASE(EMBRYO_OP_PROC);
1659         PUSH(frm);
1660         frm = stk;
1661         CHKMARGIN();
1662         BREAK;
1663         CASE(EMBRYO_OP_RET);
1664         POP(frm);
1665         POP(offs);
1666         if ((Embryo_UCell)offs >= codesize)
1667           ABORT(ep, EMBRYO_ERROR_MEMACCESS);
1668         cip = (Embryo_Cell *)(code + (int)offs);
1669         BREAK;
1670         CASE(EMBRYO_OP_RETN);
1671         POP(frm);
1672         POP(offs);
1673         if ((Embryo_UCell)offs >= codesize)
1674           ABORT(ep, EMBRYO_ERROR_MEMACCESS);
1675         cip = (Embryo_Cell *)(code + (int)offs);
1676         stk += *(Embryo_Cell *)(data + (int)stk) + sizeof(Embryo_Cell); /* remove parameters from the stack */
1677         ep->stk = stk;
1678         BREAK;
1679         CASE(EMBRYO_OP_CALL);
1680         PUSH(((unsigned char *)cip - code) + sizeof(Embryo_Cell));/* skip address */
1681         cip = JUMPABS(code, cip); /* jump to the address */
1682         BREAK;
1683         CASE(EMBRYO_OP_CALL_PRI);
1684         PUSH((unsigned char *)cip - code);
1685         cip = (Embryo_Cell *)(code + (int)pri);
1686         BREAK;
1687         CASE(EMBRYO_OP_JUMP);
1688         /* since the GETPARAM() macro modifies cip, you cannot
1689          * do GETPARAM(cip) directly */
1690         cip = JUMPABS(code, cip);
1691         BREAK;
1692         CASE(EMBRYO_OP_JREL);
1693         offs = *cip;
1694         cip = (Embryo_Cell *)((unsigned char *)cip + (int)offs + sizeof(Embryo_Cell));
1695         BREAK;
1696         CASE(EMBRYO_OP_JZER);
1697         if (pri == 0)
1698           cip = JUMPABS(code, cip);
1699         else
1700           cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1701         BREAK;
1702         CASE(EMBRYO_OP_JNZ);
1703         if (pri != 0)
1704           cip = JUMPABS(code, cip);
1705         else
1706           cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1707         BREAK;
1708         CASE(EMBRYO_OP_JEQ);
1709         if (pri==alt)
1710           cip = JUMPABS(code, cip);
1711         else
1712           cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1713         BREAK;
1714         CASE(EMBRYO_OP_JNEQ);
1715         if (pri != alt)
1716           cip = JUMPABS(code, cip);
1717         else
1718           cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1719         BREAK;
1720         CASE(EMBRYO_OP_JLESS);
1721         if ((Embryo_UCell)pri < (Embryo_UCell)alt)
1722           cip = JUMPABS(code, cip);
1723         else
1724           cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1725         BREAK;
1726         CASE(EMBRYO_OP_JLEQ);
1727         if ((Embryo_UCell)pri <= (Embryo_UCell)alt)
1728           cip = JUMPABS(code, cip);
1729         else
1730           cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1731         BREAK;
1732         CASE(EMBRYO_OP_JGRTR);
1733         if ((Embryo_UCell)pri > (Embryo_UCell)alt)
1734           cip = JUMPABS(code, cip);
1735         else
1736           cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1737         BREAK;
1738         CASE(EMBRYO_OP_JGEQ);
1739         if ((Embryo_UCell)pri >= (Embryo_UCell)alt)
1740           cip = JUMPABS(code, cip);
1741         else
1742           cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1743         BREAK;
1744         CASE(EMBRYO_OP_JSLESS);
1745         if (pri < alt)
1746           cip = JUMPABS(code, cip);
1747         else
1748           cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1749         BREAK;
1750         CASE(EMBRYO_OP_JSLEQ);
1751         if (pri <= alt)
1752           cip = JUMPABS(code, cip);
1753         else
1754           cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1755         BREAK;
1756         CASE(EMBRYO_OP_JSGRTR);
1757         if (pri > alt)
1758           cip = JUMPABS(code, cip);
1759         else
1760           cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1761         BREAK;
1762         CASE(EMBRYO_OP_JSGEQ);
1763         if (pri >= alt)
1764           cip = JUMPABS(code, cip);
1765         else
1766           cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1767         BREAK;
1768         CASE(EMBRYO_OP_SHL);
1769         pri <<= alt;
1770         BREAK;
1771         CASE(EMBRYO_OP_SHR);
1772         pri = (Embryo_UCell)pri >> (int)alt;
1773         BREAK;
1774         CASE(EMBRYO_OP_SSHR);
1775         pri >>= alt;
1776         BREAK;
1777         CASE(EMBRYO_OP_SHL_C_PRI);
1778         GETPARAM(offs);
1779         pri <<= offs;
1780         BREAK;
1781         CASE(EMBRYO_OP_SHL_C_ALT);
1782         GETPARAM(offs);
1783         alt <<= offs;
1784         BREAK;
1785         CASE(EMBRYO_OP_SHR_C_PRI);
1786         GETPARAM(offs);
1787         pri = (Embryo_UCell)pri >> (int)offs;
1788         BREAK;
1789         CASE(EMBRYO_OP_SHR_C_ALT);
1790         GETPARAM(offs);
1791         alt = (Embryo_UCell)alt >> (int)offs;
1792         BREAK;
1793         CASE(EMBRYO_OP_SMUL);
1794         pri *= alt;
1795         BREAK;
1796         CASE(EMBRYO_OP_SDIV);
1797         if (alt == 0) ABORT(ep, EMBRYO_ERROR_DIVIDE);
1798         /* divide must always round down; this is a bit
1799          * involved to do in a machine-independent way.
1800          */
1801         offs = ((pri % alt) + alt) % alt; /* true modulus */
1802         pri = (pri - offs) / alt;         /* division result */
1803         alt = offs;
1804         BREAK;
1805         CASE(EMBRYO_OP_SDIV_ALT);
1806         if (pri == 0) ABORT(ep, EMBRYO_ERROR_DIVIDE);
1807         /* divide must always round down; this is a bit
1808          * involved to do in a machine-independent way.
1809          */
1810         offs = ((alt % pri) + pri) % pri; /* true modulus */
1811         pri = (alt - offs) / pri;         /* division result */
1812         alt = offs;
1813         BREAK;
1814         CASE(EMBRYO_OP_UMUL);
1815         pri = (Embryo_UCell)pri * (Embryo_UCell)alt;
1816         BREAK;
1817         CASE(EMBRYO_OP_UDIV);
1818         if (alt == 0) ABORT(ep, EMBRYO_ERROR_DIVIDE);
1819         offs = (Embryo_UCell)pri % (Embryo_UCell)alt; /* temporary storage */
1820         pri = (Embryo_UCell)pri / (Embryo_UCell)alt;
1821         alt = offs;
1822         BREAK;
1823         CASE(EMBRYO_OP_UDIV_ALT);
1824         if (pri == 0) ABORT(ep, EMBRYO_ERROR_DIVIDE);
1825         offs = (Embryo_UCell)alt % (Embryo_UCell)pri; /* temporary storage */
1826         pri = (Embryo_UCell)alt / (Embryo_UCell)pri;
1827         alt = offs;
1828         BREAK;
1829         CASE(EMBRYO_OP_ADD);
1830         pri += alt;
1831         BREAK;
1832         CASE(EMBRYO_OP_SUB);
1833         pri -= alt;
1834         BREAK;
1835         CASE(EMBRYO_OP_SUB_ALT);
1836         pri = alt - pri;
1837         BREAK;
1838         CASE(EMBRYO_OP_AND);
1839         pri &= alt;
1840         BREAK;
1841         CASE(EMBRYO_OP_OR);
1842         pri |= alt;
1843         BREAK;
1844         CASE(EMBRYO_OP_XOR);
1845         pri ^= alt;
1846         BREAK;
1847         CASE(EMBRYO_OP_NOT);
1848         pri = !pri;
1849         BREAK;
1850         CASE(EMBRYO_OP_NEG);
1851         pri = -pri;
1852         BREAK;
1853         CASE(EMBRYO_OP_INVERT);
1854         pri = ~pri;
1855         BREAK;
1856         CASE(EMBRYO_OP_ADD_C);
1857         GETPARAM(offs);
1858         pri += offs;
1859         BREAK;
1860         CASE(EMBRYO_OP_SMUL_C);
1861         GETPARAM(offs);
1862         pri *= offs;
1863         BREAK;
1864         CASE(EMBRYO_OP_ZERO_PRI);
1865         pri = 0;
1866         BREAK;
1867         CASE(EMBRYO_OP_ZERO_ALT);
1868         alt = 0;
1869         BREAK;
1870         CASE(EMBRYO_OP_ZERO);
1871         GETPARAM(offs);
1872         *(Embryo_Cell *)(data + (int)offs) = 0;
1873         BREAK;
1874         CASE(EMBRYO_OP_ZERO_S);
1875         GETPARAM(offs);
1876         *(Embryo_Cell *)(data + (int)frm + (int)offs) = 0;
1877         BREAK;
1878         CASE(EMBRYO_OP_SIGN_PRI);
1879         if ((pri & 0xff) >= 0x80) pri |= ~(Embryo_UCell)0xff;
1880         BREAK;
1881         CASE(EMBRYO_OP_SIGN_ALT);
1882         if ((alt & 0xff) >= 0x80) alt |= ~(Embryo_UCell)0xff;
1883         BREAK;
1884         CASE(EMBRYO_OP_EQ);
1885         pri = (pri == alt) ? 1 : 0;
1886         BREAK;
1887         CASE(EMBRYO_OP_NEQ);
1888         pri = (pri != alt) ? 1 : 0;
1889         BREAK;
1890         CASE(EMBRYO_OP_LESS);
1891         pri = ((Embryo_UCell)pri < (Embryo_UCell)alt) ? 1 : 0;
1892         BREAK;
1893         CASE(EMBRYO_OP_LEQ);
1894         pri = ((Embryo_UCell)pri <= (Embryo_UCell)alt) ? 1 : 0;
1895         BREAK;
1896         CASE(EMBRYO_OP_GRTR);
1897         pri = ((Embryo_UCell)pri > (Embryo_UCell)alt) ? 1 : 0;
1898         BREAK;
1899         CASE(EMBRYO_OP_GEQ);
1900         pri = ((Embryo_UCell)pri >= (Embryo_UCell)alt) ? 1 : 0;
1901         BREAK;
1902         CASE(EMBRYO_OP_SLESS);
1903         pri = (pri < alt) ? 1 : 0;
1904         BREAK;
1905         CASE(EMBRYO_OP_SLEQ);
1906         pri = (pri <= alt) ? 1 : 0;
1907         BREAK;
1908         CASE(EMBRYO_OP_SGRTR);
1909         pri = (pri > alt) ? 1 : 0;
1910         BREAK;
1911         CASE(EMBRYO_OP_SGEQ);
1912         pri = (pri >= alt) ? 1 : 0;
1913         BREAK;
1914         CASE(EMBRYO_OP_EQ_C_PRI);
1915         GETPARAM(offs);
1916         pri = (pri == offs) ? 1 : 0;
1917         BREAK;
1918         CASE(EMBRYO_OP_EQ_C_ALT);
1919         GETPARAM(offs);
1920         pri = (alt == offs) ? 1 : 0;
1921         BREAK;
1922         CASE(EMBRYO_OP_INC_PRI);
1923         pri++;
1924         BREAK;
1925         CASE(EMBRYO_OP_INC_ALT);
1926         alt++;
1927         BREAK;
1928         CASE(EMBRYO_OP_INC);
1929         GETPARAM(offs);
1930         *(Embryo_Cell *)(data + (int)offs) += 1;
1931         BREAK;
1932         CASE(EMBRYO_OP_INC_S);
1933         GETPARAM(offs);
1934         *(Embryo_Cell *)(data + (int)frm + (int)offs) += 1;
1935         BREAK;
1936         CASE(EMBRYO_OP_INC_I);
1937         *(Embryo_Cell *)(data + (int)pri) += 1;
1938         BREAK;
1939         CASE(EMBRYO_OP_DEC_PRI);
1940         pri--;
1941         BREAK;
1942         CASE(EMBRYO_OP_DEC_ALT);
1943         alt--;
1944         BREAK;
1945         CASE(EMBRYO_OP_DEC);
1946         GETPARAM(offs);
1947         *(Embryo_Cell *)(data + (int)offs) -= 1;
1948         BREAK;
1949         CASE(EMBRYO_OP_DEC_S);
1950         GETPARAM(offs);
1951         *(Embryo_Cell *)(data + (int)frm + (int)offs) -= 1;
1952         BREAK;
1953         CASE(EMBRYO_OP_DEC_I);
1954         *(Embryo_Cell *)(data + (int)pri) -= 1;
1955         BREAK;
1956         CASE(EMBRYO_OP_MOVS);
1957         GETPARAM(offs);
1958         CHKMEM(pri);
1959         CHKMEM(pri + offs);
1960         CHKMEM(alt);
1961         CHKMEM(alt + offs);
1962         memcpy(data+(int)alt, data+(int)pri, (int)offs);
1963         BREAK;
1964         CASE(EMBRYO_OP_CMPS);
1965         GETPARAM(offs);
1966         CHKMEM(pri);
1967         CHKMEM(pri + offs);
1968         CHKMEM(alt);
1969         CHKMEM(alt + offs);
1970         pri = memcmp(data + (int)alt, data + (int)pri, (int)offs);
1971         BREAK;
1972         CASE(EMBRYO_OP_FILL);
1973         GETPARAM(offs);
1974         CHKMEM(alt);
1975         CHKMEM(alt + offs);
1976         for (i = (int)alt;
1977              (size_t)offs >= sizeof(Embryo_Cell);
1978              i += sizeof(Embryo_Cell), offs -= sizeof(Embryo_Cell))
1979           *(Embryo_Cell *)(data + i) = pri;
1980         BREAK;
1981         CASE(EMBRYO_OP_HALT);
1982         GETPARAM(offs);
1983         ep->retval = pri;
1984         /* store complete status */
1985         ep->frm = frm;
1986         ep->stk = stk;
1987         ep->hea = hea;
1988         ep->pri = pri;
1989         ep->alt = alt;
1990         ep->cip = (Embryo_Cell)((unsigned char*)cip - code);
1991         if (offs == EMBRYO_ERROR_SLEEP)
1992           {
1993              ep->reset_stk = reset_stk;
1994              ep->reset_hea = reset_hea;
1995              ep->run_count--;
1996              return EMBRYO_PROGRAM_SLEEP;
1997           }
1998         OK(ep, (int)offs);
1999         CASE(EMBRYO_OP_BOUNDS);
2000         GETPARAM(offs);
2001         if ((Embryo_UCell)pri > (Embryo_UCell)offs)
2002           ABORT(ep, EMBRYO_ERROR_BOUNDS);
2003         BREAK;
2004         CASE(EMBRYO_OP_SYSREQ_PRI);
2005         /* save a few registers */
2006         ep->cip = (Embryo_Cell)((unsigned char *)cip - code);
2007         ep->hea = hea;
2008         ep->frm = frm;
2009         ep->stk = stk;
2010         num = _embryo_native_call(ep, pri, &pri, (Embryo_Cell *)(data + (int)stk));
2011         if (num != EMBRYO_ERROR_NONE)
2012           {
2013              if (num == EMBRYO_ERROR_SLEEP)
2014                {
2015                   ep->pri = pri;
2016                   ep->alt = alt;
2017                   ep->reset_stk = reset_stk;
2018                   ep->reset_hea = reset_hea;
2019                   ep->run_count--;
2020                   return EMBRYO_PROGRAM_SLEEP;
2021                }
2022              ABORT(ep, num);
2023           }
2024         BREAK;
2025         CASE(EMBRYO_OP_SYSREQ_C);
2026         GETPARAM(offs);
2027         /* save a few registers */
2028         ep->cip = (Embryo_Cell)((unsigned char *)cip - code);
2029         ep->hea = hea;
2030         ep->frm = frm;
2031         ep->stk = stk;
2032         num = _embryo_native_call(ep, offs, &pri, (Embryo_Cell *)(data + (int)stk));
2033         if (num != EMBRYO_ERROR_NONE)
2034           {
2035              if (num == EMBRYO_ERROR_SLEEP)
2036                {
2037                   ep->pri = pri;
2038                   ep->alt = alt;
2039                   ep->reset_stk = reset_stk;
2040                   ep->reset_hea = reset_hea;
2041                   ep->run_count--;
2042                   return EMBRYO_PROGRAM_SLEEP;
2043                }
2044                {
2045                   Embryo_Header    *hdr;
2046                   int i, num;
2047                   Embryo_Func_Stub *func_entry;
2048
2049                   hdr = (Embryo_Header *)ep->code;
2050                   num = NUMENTRIES(hdr, natives, libraries);
2051                   func_entry = GETENTRY(hdr, natives, 0);
2052                   for (i = 0; i < num; i++)
2053                     {
2054                        char *entry_name;
2055
2056                        entry_name = GETENTRYNAME(hdr, func_entry);
2057                        if (i == offs)
2058                          printf("EMBRYO: CALL [%i] %s() non-existant!\n", i, entry_name);
2059                        func_entry =
2060                          (Embryo_Func_Stub *)((unsigned char *)func_entry + hdr->defsize);
2061                     }
2062                }
2063              ABORT(ep, num);
2064           }
2065         BREAK;
2066         CASE(EMBRYO_OP_SYSREQ_D);
2067         GETPARAM(offs);
2068         /* save a few registers */
2069         ep->cip = (Embryo_Cell)((unsigned char *)cip - code);
2070         ep->hea = hea;
2071         ep->frm = frm;
2072         ep->stk = stk;
2073         num = _embryo_native_call(ep, offs, &pri, (Embryo_Cell *)(data + (int)stk));
2074         if (num != EMBRYO_ERROR_NONE)
2075           {
2076              if (num == EMBRYO_ERROR_SLEEP)
2077                {
2078                   ep->pri = pri;
2079                   ep->alt = alt;
2080                   ep->reset_stk = reset_stk;
2081                   ep->reset_hea = reset_hea;
2082                   ep->run_count--;
2083                   return EMBRYO_PROGRAM_SLEEP;
2084                }
2085              ABORT(ep, ep->error);
2086           }
2087         BREAK;
2088         CASE(EMBRYO_OP_JUMP_PRI);
2089         cip = (Embryo_Cell *)(code + (int)pri);
2090         BREAK;
2091         CASE(EMBRYO_OP_SWITCH);
2092           {
2093              Embryo_Cell *cptr;
2094
2095              /* +1, to skip the "casetbl" opcode */
2096              cptr = (Embryo_Cell *)(code + (*cip)) + 1;
2097              /* number of records in the case table */
2098              num = (int)(*cptr);
2099              /* preset to "none-matched" case */
2100              cip = (Embryo_Cell *)(code + *(cptr + 1));
2101              for (cptr += 2;
2102                   (num > 0) && (*cptr != pri);
2103                   num--, cptr += 2);
2104              /* case found */
2105              if (num > 0)
2106                cip = (Embryo_Cell *)(code + *(cptr + 1));
2107           }
2108         BREAK;
2109         CASE(EMBRYO_OP_SWAP_PRI);
2110         offs = *(Embryo_Cell *)(data + (int)stk);
2111         *(Embryo_Cell *)(data + (int)stk) = pri;
2112         pri = offs;
2113         BREAK;
2114         CASE(EMBRYO_OP_SWAP_ALT);
2115         offs = *(Embryo_Cell *)(data + (int)stk);
2116         *(Embryo_Cell *)(data + (int)stk) = alt;
2117         alt = offs;
2118         BREAK;
2119         CASE(EMBRYO_OP_PUSHADDR);
2120         GETPARAM(offs);
2121         PUSH(frm + offs);
2122         BREAK;
2123         CASE(EMBRYO_OP_NOP);
2124         BREAK;
2125         CASE(EMBRYO_OP_NONE);
2126         CASE(EMBRYO_OP_FILE);
2127         CASE(EMBRYO_OP_LINE);
2128         CASE(EMBRYO_OP_SYMBOL);
2129         CASE(EMBRYO_OP_SRANGE);
2130         CASE(EMBRYO_OP_CASETBL);
2131         CASE(EMBRYO_OP_SYMTAG);
2132         BREAK;
2133 #ifndef EMBRYO_EXEC_JUMPTABLE
2134       default:
2135         ABORT(ep, EMBRYO_ERROR_INVINSTR);
2136 #endif
2137         SWITCHEND;
2138      }
2139    ep->max_run_cycles = max_run_cycles;
2140    ep->run_count--;
2141    ep->hea = hea_start;
2142    return EMBRYO_PROGRAM_OK;
2143 }
2144
2145 /**
2146  * Retreives the return value of the last called function of the given
2147  * program.
2148  * @param   ep The given program.
2149  * @return  An Embryo_Cell representing the return value of the function
2150  *          that was last called.
2151  * @ingroup Embryo_Run_Group
2152  */
2153 EAPI Embryo_Cell
2154 embryo_program_return_value_get(Embryo_Program *ep)
2155 {
2156    if (!ep) return 0;
2157    return ep->retval;
2158 }
2159
2160 /**
2161  * Sets the maximum number of abstract machine cycles any given program run
2162  * can execute before being put to sleep and returning.
2163  *
2164  * @param   ep The given program.
2165  * @param   max The number of machine cycles as a limit.
2166  *
2167  * This sets the maximum number of abstract machine (virtual machine)
2168  * instructions that a single run of an embryo function (even if its main)
2169  * can use before embryo embryo_program_run() reutrns with the value
2170  * EMBRYO_PROGRAM_TOOLONG. If the function fully executes within this number
2171  * of cycles, embryo_program_run() will return as normal with either
2172  * EMBRYO_PROGRAM_OK, EMBRYO_PROGRAM_FAIL or EMBRYO_PROGRAM_SLEEP. If the
2173  * run exceeds this instruction count, then EMBRYO_PROGRAM_TOOLONG will be
2174  * returned indicating the program exceeded its run count. If the app wishes
2175  * to continue running this anyway - it is free to process its own events or
2176  * whatever it wants and continue the function by calling
2177  * embryo_program_run(program, EMBRYO_FUNCTION_CONT); which will start the
2178  * run again until the instruction count is reached. This can keep being done
2179  * to allow the calling program to still be able to control things outside the
2180  * embryo function being called. If the maximum run cycle count is 0 then the
2181  * program is allowed to run forever only returning when it is done.
2182  *
2183  * It is important to note that abstract machine cycles are NOT the same as
2184  * the host machine cpu cycles. They are not fixed in runtime per cycle, so
2185  * this is more of a helper tool than a way to HARD-FORCE a script to only
2186  * run for a specific period of time. If the cycle count is set to something
2187  * low like 5000 or 1000, then every 1000 (or 5000) cycles control will be
2188  * returned to the calling process where it can check a timer to see if a
2189  * physical runtime limit has been elapsed and then abort runing further
2190  * assuming a "runaway script" or keep continuing the script run. This
2191  * limits resolution to only that many cycles which do not take a determined
2192  * amount of time to execute, as this varies from cpu to cpu and also depends
2193  * on how loaded the system is. Making the max cycle run too low will
2194  * impact performance requiring the abstract machine to do setup and teardown
2195  * cycles too often comapred to cycles actually executed.
2196  *
2197  * Also note it does NOT include nested abstract machines. IF this abstract
2198  * machine run calls embryo script that calls a native function that in turn
2199  * calls more embryo script, then the 2nd (and so on) levels are not included
2200  * in this run count. They can set their own max instruction count values
2201  * separately.
2202  *
2203  * The default max cycle run value is 0 in any program until set with this
2204  * function.
2205  *
2206  * @ingroup Embryo_Run_Group
2207  */
2208 EAPI void
2209 embryo_program_max_cycle_run_set(Embryo_Program *ep, int max)
2210 {
2211    if (!ep) return;
2212    if (max < 0) max = 0;
2213    ep->max_run_cycles = max;
2214 }
2215
2216 /**
2217  * Retreives the maximum number of abstract machine cycles a program is allowed
2218  * to run.
2219  * @param   ep The given program.
2220  * @return  The number of cycles a run cycle is allowed to run for this
2221  *          program.
2222  *
2223  * This returns the value set by embryo_program_max_cycle_run_set(). See
2224  * embryo_program_max_cycle_run_set() for more information.
2225  *
2226  * @ingroup Embryo_Run_Group
2227  */
2228 EAPI int
2229 embryo_program_max_cycle_run_get(Embryo_Program *ep)
2230 {
2231    if (!ep) return 0;
2232    return ep->max_run_cycles;
2233 }
2234
2235 /**
2236  * @defgroup Embryo_Parameter_Group Function Parameter Functions
2237  *
2238  * Functions that set parameters for the next function that is called.
2239  */
2240
2241 /**
2242  * Pushes an Embryo_Cell onto the function stack to use as a parameter for
2243  * the next function that is called in the given program.
2244  * @param   ep   The given program.
2245  * @param   cell The Embryo_Cell to push onto the stack.
2246  * @return  @c 1 if successful.  @c 0 otherwise.
2247  * @ingroup Embryo_Parameter_Group
2248  */
2249 EAPI int
2250 embryo_parameter_cell_push(Embryo_Program *ep, Embryo_Cell cell)
2251 {
2252    Embryo_Param *pr;
2253
2254    ep->params_size++;
2255    if (ep->params_size > ep->params_alloc)
2256      {
2257         ep->params_alloc += 8;
2258         pr = realloc(ep->params, ep->params_alloc * sizeof(Embryo_Param));
2259         if (!pr) return 0;
2260         ep->params = pr;
2261      }
2262    pr = &(ep->params[ep->params_size - 1]);
2263    pr->string = NULL;
2264    pr->cell_array = NULL;
2265    pr->cell_array_size = 0;
2266    pr->cell = 0;
2267    pr->cell = cell;
2268    return 1;
2269 }
2270
2271 /**
2272  * Pushes a string onto the function stack to use as a parameter for the
2273  * next function that is called in the given program.
2274  * @param   ep The given program.
2275  * @param   str The string to push onto the stack.
2276  * @return  @c 1 if successful.  @c 0 otherwise.
2277  * @ingroup Embryo_Parameter_Group
2278  */
2279 EAPI int
2280 embryo_parameter_string_push(Embryo_Program *ep, const char *str)
2281 {
2282    Embryo_Param *pr;
2283    char *str_dup;
2284
2285    if (!str)
2286      return embryo_parameter_string_push(ep, "");
2287    str_dup = strdup(str);
2288    if (!str_dup) return 0;
2289    ep->params_size++;
2290    if (ep->params_size > ep->params_alloc)
2291      {
2292         ep->params_alloc += 8;
2293         pr = realloc(ep->params, ep->params_alloc * sizeof(Embryo_Param));
2294         if (!pr)
2295           {
2296              free(str_dup);
2297              return 0;
2298           }
2299         ep->params = pr;
2300      }
2301    pr = &(ep->params[ep->params_size - 1]);
2302    pr->string = NULL;
2303    pr->cell_array = NULL;
2304    pr->cell_array_size = 0;
2305    pr->cell = 0;
2306    pr->string = str_dup;
2307    return 1;
2308 }
2309
2310 /**
2311  * Pushes an array of Embryo_Cells onto the function stack to be used as
2312  * parameters for the next function that is called in the given program.
2313  * @param   ep    The given program.
2314  * @param   cells The array of Embryo_Cells.
2315  * @param   num   The number of cells in @p cells.
2316  * @return  @c 1 if successful.  @c 0 otherwise.
2317  * @ingroup Embryo_Parameter_Group
2318  */
2319 EAPI int
2320 embryo_parameter_cell_array_push(Embryo_Program *ep, Embryo_Cell *cells, int num)
2321 {
2322    Embryo_Param *pr;
2323    Embryo_Cell *cell_array;
2324
2325    cell_array = malloc(num * sizeof(Embryo_Cell));
2326    if ((!cells) || (num <= 0))
2327      return embryo_parameter_cell_push(ep, 0);
2328    ep->params_size++;
2329    if (ep->params_size > ep->params_alloc)
2330      {
2331         ep->params_alloc += 8;
2332         pr = realloc(ep->params, ep->params_alloc * sizeof(Embryo_Param));
2333         if (!pr)
2334           {
2335              free(cell_array);
2336              return 0;
2337           }
2338         ep->params = pr;
2339      }
2340    pr = &(ep->params[ep->params_size - 1]);
2341    pr->string = NULL;
2342    pr->cell_array = NULL;
2343    pr->cell_array_size = 0;
2344    pr->cell = 0;
2345    pr->cell_array = cell_array;
2346    pr->cell_array_size = num;
2347    memcpy(pr->cell_array, cells, num * sizeof(Embryo_Cell));
2348    return 1;
2349 }