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