warnings--
[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, int 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 int
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(int 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 ((error < 0) || (error >= (int)(sizeof(messages) / sizeof(messages[0]))))
803      return (const char *)"(unknown)";
804    return messages[error];
805 }
806
807 /**
808  * @defgroup Embryo_Data_String_Group Embryo Data String Functions
809  *
810  * Functions that operate on strings in the memory of a virtual machine.
811  */
812
813 /**
814  * Retrieves the length of the string starting at the given cell.
815  * @param   ep       The program the cell is part of.
816  * @param   str_cell Pointer to the first cell of the string.
817  * @return  The length of the string.  @c 0 is returned if there is an error.
818  * @ingroup Embryo_Data_String_Group
819  */
820 EAPI int
821 embryo_data_string_length_get(Embryo_Program *ep, Embryo_Cell *str_cell)
822 {
823    int            len;
824    Embryo_Header *hdr;
825
826    if ((!ep) || (!ep->base)) return 0;
827    hdr = (Embryo_Header *)ep->base;
828    if ((!str_cell) ||
829        ((void *)str_cell >= (void *)(ep->base + hdr->stp)) ||
830        ((void *)str_cell < (void *)ep->base))
831      return 0;
832    for (len = 0; str_cell[len] != 0; len++);
833    return len;
834 }
835
836 /**
837  * Copies the string starting at the given cell to the given buffer.
838  * @param   ep       The program the cell is part of.
839  * @param   str_cell Pointer to the first cell of the string.
840  * @param   dst      The given buffer.
841  * @ingroup Embryo_Data_String_Group
842  */
843 EAPI void
844 embryo_data_string_get(Embryo_Program *ep, Embryo_Cell *str_cell, char *dst)
845 {
846    int            i;
847    Embryo_Header *hdr;
848
849    if (!dst) return;
850    if ((!ep) || (!ep->base))
851      {
852         dst[0] = 0;
853         return;
854      }
855    hdr = (Embryo_Header *)ep->base;
856    if ((!str_cell) ||
857        ((void *)str_cell >= (void *)(ep->base + hdr->stp)) ||
858        ((void *)str_cell < (void *)ep->base))
859      {
860         dst[0] = 0;
861         return;
862      }
863    for (i = 0; str_cell[i] != 0; i++)
864      {
865 #ifdef WORDS_BIGENDIAN
866           {
867              Embryo_Cell tmp;
868
869              tmp = str_cell[i];
870              _embryo_byte_swap_32(&tmp);
871              dst[i] = tmp;
872           }
873 #else
874         dst[i] = str_cell[i];
875 #endif
876      }
877    dst[i] = 0;
878 }
879
880 /**
881  * Copies string in the given buffer into the virtual machine memory
882  * starting at the given cell.
883  * @param ep       The program the cell is part of.
884  * @param src      The given buffer.
885  * @param str_cell Pointer to the first cell to copy the string to.
886  * @ingroup Embryo_Data_String_Group
887  */
888 EAPI void
889 embryo_data_string_set(Embryo_Program *ep, const char *src, Embryo_Cell *str_cell)
890 {
891    int            i;
892    Embryo_Header *hdr;
893
894    if (!ep) return;
895    if (!ep->base) return;
896    hdr = (Embryo_Header *)ep->base;
897    if ((!str_cell) ||
898        ((void *)str_cell >= (void *)(ep->base + hdr->stp)) ||
899        ((void *)str_cell < (void *)ep->base))
900      return;
901    if (!src)
902      {
903         str_cell[0] = 0;
904         return;
905      }
906    for (i = 0; src[i] != 0; i++)
907      {
908         if ((void *)(&(str_cell[i])) >= (void *)(ep->base + hdr->stp)) return;
909         else if ((void *)(&(str_cell[i])) == (void *)(ep->base + hdr->stp - 1))
910           {
911              str_cell[i] = 0;
912              return;
913           }
914 #ifdef WORDS_BIGENDIAN
915           {
916              Embryo_Cell tmp;
917
918              tmp = src[i];
919              _embryo_byte_swap_32(&tmp);
920              str_cell[i] = tmp;
921           }
922 #else
923         str_cell[i] = src[i];
924 #endif
925      }
926    str_cell[i] = 0;
927 }
928
929 /**
930  * Retreives a pointer to the address in the virtual machine given by the
931  * given cell.
932  * @param   ep   The program whose virtual machine address is being queried.
933  * @param   addr The given cell.
934  * @return  A pointer to the cell at the given address.
935  * @ingroup Embryo_Data_String_Group
936  */
937 EAPI Embryo_Cell *
938 embryo_data_address_get(Embryo_Program *ep, Embryo_Cell addr)
939 {
940    Embryo_Header *hdr;
941    unsigned char *data;
942
943    if ((!ep) || (!ep->base)) return NULL;
944    hdr = (Embryo_Header *)ep->base;
945    data = ep->base + (int)hdr->dat;
946    if ((addr < 0) || (addr >= hdr->stp)) return NULL;
947    return (Embryo_Cell *)(data + (int)addr);
948 }
949
950 /**
951  * @defgroup Embryo_Heap_Group Heap Functions
952  *
953  * The heap is an area of memory that can be allocated for program
954  * use at runtime.  The heap functions here change the amount of heap
955  * memory available.
956  */
957
958 /**
959  * Increases the size of the heap of the given virtual machine by the given
960  * number of Embryo_Cells.
961  * @param   ep    The program with the given virtual machine.
962  * @param   cells The given number of Embryo_Cells.
963  * @return  The address of the new memory region on success.
964  *          @c EMBRYO_CELL_NONE otherwise.
965  * @ingroup Embryo_Heap_Group
966  */
967 EAPI Embryo_Cell
968 embryo_data_heap_push(Embryo_Program *ep, int cells)
969 {
970    Embryo_Header *hdr;
971    Embryo_Cell    addr;
972
973    if ((!ep) || (!ep->base)) return EMBRYO_CELL_NONE;
974    hdr = (Embryo_Header *)ep->base;
975    if (ep->stk - ep->hea - (cells * sizeof(Embryo_Cell)) < STKMARGIN)
976      return EMBRYO_CELL_NONE;
977    addr = ep->hea;
978    ep->hea += (cells * sizeof(Embryo_Cell));
979    return addr;
980 }
981
982 /**
983  * Decreases the size of the heap of the given virtual machine down to the
984  * given size.
985  * @param   ep      The program with the given virtual machine.
986  * @param   down_to The given size.
987  * @ingroup Embryo_Heap_Group
988  */
989 EAPI void
990 embryo_data_heap_pop(Embryo_Program *ep, Embryo_Cell down_to)
991 {
992    if (!ep) return;
993    if (down_to < 0) down_to = 0;
994    if (ep->hea > down_to) ep->hea = down_to;
995 }
996
997 /**
998  * @defgroup Embryo_Run_Group Program Run Functions
999  *
1000  * Functions that are involved in actually running functions in an
1001  * Embryo program.
1002  */
1003
1004 /**
1005  * Returns the number of virtual machines are running for the given program.
1006  * @param   ep The given program.
1007  * @return  The number of virtual machines running.
1008  * @ingroup Embryo_Run_Group
1009  */
1010 EAPI int
1011 embryo_program_recursion_get(Embryo_Program *ep)
1012 {
1013    return ep->run_count;
1014 }
1015
1016 #ifdef __GNUC__
1017 #if 1
1018 #define EMBRYO_EXEC_JUMPTABLE
1019 #endif
1020 #endif
1021
1022 /* jump table optimization - only works for gcc though */
1023 #ifdef EMBRYO_EXEC_JUMPTABLE
1024 #define SWITCH(x) while (1) { goto *switchtable[x];
1025 #define SWITCHEND break; }
1026 #define CASE(x) SWITCHTABLE_##x:
1027 #define BREAK break;
1028 #else
1029 #define SWITCH(x) switch (x) {
1030 #define SWITCHEND }
1031 #define CASE(x) case x:
1032 #define BREAK break
1033 #endif
1034
1035 /**
1036  * Runs the given function of the given Embryo program in the current
1037  * virtual machine.  The parameter @p fn can be found using
1038  * @ref embryo_program_function_find.
1039  *
1040  * @note For Embryo to be able to run a function, it must have been
1041  *       declared @c public in the Small source code.
1042  *
1043  * @param   ep The given program.
1044  * @param   fn The given function.  Normally "main", in which case the
1045  *             constant @c EMBRYO_FUNCTION_MAIN can be used.
1046  * @return  @c EMBRYO_PROGRAM_OK on success.  @c EMBRYO_PROGRAM_SLEEP if the
1047  *          program is halted by the Small @c sleep call.
1048  *          @c EMBRYO_PROGRAM_FAIL if there is an error.
1049  *          @c EMBRYO_PROGRAM_TOOLONG if the program executes for longer than
1050  *          it is allowed to in abstract machine instruction count.
1051  * @ingroup Embryo_Run_Group
1052  */
1053 EAPI int
1054 embryo_program_run(Embryo_Program *ep, Embryo_Function fn)
1055 {
1056    Embryo_Header    *hdr;
1057    Embryo_Func_Stub *func;
1058    unsigned char    *code, *data;
1059    Embryo_Cell      pri, alt, stk, frm, hea, hea_start;
1060    Embryo_Cell      reset_stk, reset_hea, *cip;
1061    Embryo_UCell     codesize;
1062    int              i;
1063    unsigned char    op;
1064    Embryo_Cell      offs;
1065    int              num;
1066    int              max_run_cycles;
1067    int              cycle_count;
1068 #ifdef EMBRYO_EXEC_JUMPTABLE
1069    /* we limit the jumptable to 256 elements. why? above we forced "op" to be
1070     * a unsigned char - that means 256 max values. we limit opcode overflow
1071     * here, so eliminating crashes on table lookups with bad/corrupt bytecode.
1072     * no need to atuall do compares, branches etc. the datatype does the work
1073     * for us. so that means EXCESS elements are all declared as OP_NONE to
1074     * keep them innocuous.
1075     */
1076    static const void *switchtable[256] =
1077      {
1078            &&SWITCHTABLE_EMBRYO_OP_NONE,
1079                &&SWITCHTABLE_EMBRYO_OP_LOAD_PRI,
1080                &&SWITCHTABLE_EMBRYO_OP_LOAD_ALT,
1081                &&SWITCHTABLE_EMBRYO_OP_LOAD_S_PRI,
1082                &&SWITCHTABLE_EMBRYO_OP_LOAD_S_ALT,
1083                &&SWITCHTABLE_EMBRYO_OP_LREF_PRI,
1084                &&SWITCHTABLE_EMBRYO_OP_LREF_ALT,
1085                &&SWITCHTABLE_EMBRYO_OP_LREF_S_PRI,
1086                &&SWITCHTABLE_EMBRYO_OP_LREF_S_ALT,
1087                &&SWITCHTABLE_EMBRYO_OP_LOAD_I,
1088                &&SWITCHTABLE_EMBRYO_OP_LODB_I,
1089                &&SWITCHTABLE_EMBRYO_OP_CONST_PRI,
1090                &&SWITCHTABLE_EMBRYO_OP_CONST_ALT,
1091                &&SWITCHTABLE_EMBRYO_OP_ADDR_PRI,
1092                &&SWITCHTABLE_EMBRYO_OP_ADDR_ALT,
1093                &&SWITCHTABLE_EMBRYO_OP_STOR_PRI,
1094                &&SWITCHTABLE_EMBRYO_OP_STOR_ALT,
1095                &&SWITCHTABLE_EMBRYO_OP_STOR_S_PRI,
1096                &&SWITCHTABLE_EMBRYO_OP_STOR_S_ALT,
1097                &&SWITCHTABLE_EMBRYO_OP_SREF_PRI,
1098                &&SWITCHTABLE_EMBRYO_OP_SREF_ALT,
1099                &&SWITCHTABLE_EMBRYO_OP_SREF_S_PRI,
1100                &&SWITCHTABLE_EMBRYO_OP_SREF_S_ALT,
1101                &&SWITCHTABLE_EMBRYO_OP_STOR_I,
1102                &&SWITCHTABLE_EMBRYO_OP_STRB_I,
1103                &&SWITCHTABLE_EMBRYO_OP_LIDX,
1104                &&SWITCHTABLE_EMBRYO_OP_LIDX_B,
1105                &&SWITCHTABLE_EMBRYO_OP_IDXADDR,
1106                &&SWITCHTABLE_EMBRYO_OP_IDXADDR_B,
1107                &&SWITCHTABLE_EMBRYO_OP_ALIGN_PRI,
1108                &&SWITCHTABLE_EMBRYO_OP_ALIGN_ALT,
1109                &&SWITCHTABLE_EMBRYO_OP_LCTRL,
1110                &&SWITCHTABLE_EMBRYO_OP_SCTRL,
1111                &&SWITCHTABLE_EMBRYO_OP_MOVE_PRI,
1112                &&SWITCHTABLE_EMBRYO_OP_MOVE_ALT,
1113                &&SWITCHTABLE_EMBRYO_OP_XCHG,
1114                &&SWITCHTABLE_EMBRYO_OP_PUSH_PRI,
1115                &&SWITCHTABLE_EMBRYO_OP_PUSH_ALT,
1116                &&SWITCHTABLE_EMBRYO_OP_PUSH_R,
1117                &&SWITCHTABLE_EMBRYO_OP_PUSH_C,
1118                &&SWITCHTABLE_EMBRYO_OP_PUSH,
1119                &&SWITCHTABLE_EMBRYO_OP_PUSH_S,
1120                &&SWITCHTABLE_EMBRYO_OP_POP_PRI,
1121                &&SWITCHTABLE_EMBRYO_OP_POP_ALT,
1122                &&SWITCHTABLE_EMBRYO_OP_STACK,
1123                &&SWITCHTABLE_EMBRYO_OP_HEAP,
1124                &&SWITCHTABLE_EMBRYO_OP_PROC,
1125                &&SWITCHTABLE_EMBRYO_OP_RET,
1126                &&SWITCHTABLE_EMBRYO_OP_RETN,
1127                &&SWITCHTABLE_EMBRYO_OP_CALL,
1128                &&SWITCHTABLE_EMBRYO_OP_CALL_PRI,
1129                &&SWITCHTABLE_EMBRYO_OP_JUMP,
1130                &&SWITCHTABLE_EMBRYO_OP_JREL,
1131                &&SWITCHTABLE_EMBRYO_OP_JZER,
1132                &&SWITCHTABLE_EMBRYO_OP_JNZ,
1133                &&SWITCHTABLE_EMBRYO_OP_JEQ,
1134                &&SWITCHTABLE_EMBRYO_OP_JNEQ,
1135                &&SWITCHTABLE_EMBRYO_OP_JLESS,
1136                &&SWITCHTABLE_EMBRYO_OP_JLEQ,
1137                &&SWITCHTABLE_EMBRYO_OP_JGRTR,
1138                &&SWITCHTABLE_EMBRYO_OP_JGEQ,
1139                &&SWITCHTABLE_EMBRYO_OP_JSLESS,
1140                &&SWITCHTABLE_EMBRYO_OP_JSLEQ,
1141                &&SWITCHTABLE_EMBRYO_OP_JSGRTR,
1142                &&SWITCHTABLE_EMBRYO_OP_JSGEQ,
1143                &&SWITCHTABLE_EMBRYO_OP_SHL,
1144                &&SWITCHTABLE_EMBRYO_OP_SHR,
1145                &&SWITCHTABLE_EMBRYO_OP_SSHR,
1146                &&SWITCHTABLE_EMBRYO_OP_SHL_C_PRI,
1147                &&SWITCHTABLE_EMBRYO_OP_SHL_C_ALT,
1148                &&SWITCHTABLE_EMBRYO_OP_SHR_C_PRI,
1149                &&SWITCHTABLE_EMBRYO_OP_SHR_C_ALT,
1150                &&SWITCHTABLE_EMBRYO_OP_SMUL,
1151                &&SWITCHTABLE_EMBRYO_OP_SDIV,
1152                &&SWITCHTABLE_EMBRYO_OP_SDIV_ALT,
1153                &&SWITCHTABLE_EMBRYO_OP_UMUL,
1154                &&SWITCHTABLE_EMBRYO_OP_UDIV,
1155                &&SWITCHTABLE_EMBRYO_OP_UDIV_ALT,
1156                &&SWITCHTABLE_EMBRYO_OP_ADD,
1157                &&SWITCHTABLE_EMBRYO_OP_SUB,
1158                &&SWITCHTABLE_EMBRYO_OP_SUB_ALT,
1159                &&SWITCHTABLE_EMBRYO_OP_AND,
1160                &&SWITCHTABLE_EMBRYO_OP_OR,
1161                &&SWITCHTABLE_EMBRYO_OP_XOR,
1162                &&SWITCHTABLE_EMBRYO_OP_NOT,
1163                &&SWITCHTABLE_EMBRYO_OP_NEG,
1164                &&SWITCHTABLE_EMBRYO_OP_INVERT,
1165                &&SWITCHTABLE_EMBRYO_OP_ADD_C,
1166                &&SWITCHTABLE_EMBRYO_OP_SMUL_C,
1167                &&SWITCHTABLE_EMBRYO_OP_ZERO_PRI,
1168                &&SWITCHTABLE_EMBRYO_OP_ZERO_ALT,
1169                &&SWITCHTABLE_EMBRYO_OP_ZERO,
1170                &&SWITCHTABLE_EMBRYO_OP_ZERO_S,
1171                &&SWITCHTABLE_EMBRYO_OP_SIGN_PRI,
1172                &&SWITCHTABLE_EMBRYO_OP_SIGN_ALT,
1173                &&SWITCHTABLE_EMBRYO_OP_EQ,
1174                &&SWITCHTABLE_EMBRYO_OP_NEQ,
1175                &&SWITCHTABLE_EMBRYO_OP_LESS,
1176                &&SWITCHTABLE_EMBRYO_OP_LEQ,
1177                &&SWITCHTABLE_EMBRYO_OP_GRTR,
1178                &&SWITCHTABLE_EMBRYO_OP_GEQ,
1179                &&SWITCHTABLE_EMBRYO_OP_SLESS,
1180                &&SWITCHTABLE_EMBRYO_OP_SLEQ,
1181                &&SWITCHTABLE_EMBRYO_OP_SGRTR,
1182                &&SWITCHTABLE_EMBRYO_OP_SGEQ,
1183                &&SWITCHTABLE_EMBRYO_OP_EQ_C_PRI,
1184                &&SWITCHTABLE_EMBRYO_OP_EQ_C_ALT,
1185                &&SWITCHTABLE_EMBRYO_OP_INC_PRI,
1186                &&SWITCHTABLE_EMBRYO_OP_INC_ALT,
1187                &&SWITCHTABLE_EMBRYO_OP_INC,
1188                &&SWITCHTABLE_EMBRYO_OP_INC_S,
1189                &&SWITCHTABLE_EMBRYO_OP_INC_I,
1190                &&SWITCHTABLE_EMBRYO_OP_DEC_PRI,
1191                &&SWITCHTABLE_EMBRYO_OP_DEC_ALT,
1192                &&SWITCHTABLE_EMBRYO_OP_DEC,
1193                &&SWITCHTABLE_EMBRYO_OP_DEC_S,
1194                &&SWITCHTABLE_EMBRYO_OP_DEC_I,
1195                &&SWITCHTABLE_EMBRYO_OP_MOVS,
1196                &&SWITCHTABLE_EMBRYO_OP_CMPS,
1197                &&SWITCHTABLE_EMBRYO_OP_FILL,
1198                &&SWITCHTABLE_EMBRYO_OP_HALT,
1199                &&SWITCHTABLE_EMBRYO_OP_BOUNDS,
1200                &&SWITCHTABLE_EMBRYO_OP_SYSREQ_PRI,
1201                &&SWITCHTABLE_EMBRYO_OP_SYSREQ_C,
1202                &&SWITCHTABLE_EMBRYO_OP_FILE,
1203                &&SWITCHTABLE_EMBRYO_OP_LINE,
1204                &&SWITCHTABLE_EMBRYO_OP_SYMBOL,
1205                &&SWITCHTABLE_EMBRYO_OP_SRANGE,
1206                &&SWITCHTABLE_EMBRYO_OP_JUMP_PRI,
1207                &&SWITCHTABLE_EMBRYO_OP_SWITCH,
1208                &&SWITCHTABLE_EMBRYO_OP_CASETBL,
1209                &&SWITCHTABLE_EMBRYO_OP_SWAP_PRI,
1210                &&SWITCHTABLE_EMBRYO_OP_SWAP_ALT,
1211                &&SWITCHTABLE_EMBRYO_OP_PUSHADDR,
1212                &&SWITCHTABLE_EMBRYO_OP_NOP,
1213                &&SWITCHTABLE_EMBRYO_OP_SYSREQ_D,
1214                &&SWITCHTABLE_EMBRYO_OP_SYMTAG,
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, &&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
1239      };
1240 #endif
1241    if (!ep) return EMBRYO_PROGRAM_FAIL;
1242    if (!(ep->flags & EMBRYO_FLAG_RELOC))
1243      {
1244         ep->error = EMBRYO_ERROR_INIT;
1245         return EMBRYO_PROGRAM_FAIL;
1246      }
1247    if (!ep->base)
1248      {
1249         ep->error = EMBRYO_ERROR_INIT;
1250         return EMBRYO_PROGRAM_FAIL;
1251      }
1252    if (ep->run_count > 0)
1253      {
1254         /* return EMBRYO_PROGRAM_BUSY; */
1255         /* FIXME: test C->vm->C->vm recursion more fully */
1256         /* it seems to work... just fine!!! - strange! */
1257      }
1258
1259    /* set up the registers */
1260    hdr = (Embryo_Header *)ep->base;
1261    codesize = (Embryo_UCell)(hdr->dat - hdr->cod);
1262    code = ep->base + (int)hdr->cod;
1263    data = ep->base + (int)hdr->dat;
1264    hea_start = hea = ep->hea;
1265    stk = ep->stk;
1266    reset_stk = stk;
1267    reset_hea = hea;
1268    frm = alt = pri = 0;
1269
1270    /* get the start address */
1271    if (fn == EMBRYO_FUNCTION_MAIN)
1272      {
1273         if (hdr->cip < 0)
1274           {
1275              ep->error = EMBRYO_ERROR_INDEX;
1276              return EMBRYO_PROGRAM_FAIL;
1277           }
1278         cip = (Embryo_Cell *)(code + (int)hdr->cip);
1279      }
1280    else if (fn == EMBRYO_FUNCTION_CONT)
1281      {
1282         /* all registers: pri, alt, frm, cip, hea, stk, reset_stk, reset_hea */
1283         frm = ep->frm;
1284         stk = ep->stk;
1285         hea = ep->hea;
1286         pri = ep->pri;
1287         alt = ep->alt;
1288         reset_stk = ep->reset_stk;
1289         reset_hea = ep->reset_hea;
1290         cip = (Embryo_Cell *)(code + (int)ep->cip);
1291      }
1292    else if (fn < 0)
1293      {
1294         ep->error = EMBRYO_ERROR_INDEX;
1295         return EMBRYO_PROGRAM_FAIL;
1296      }
1297    else
1298      {
1299         if (fn >= (Embryo_Cell)NUMENTRIES(hdr, publics, natives))
1300           {
1301              ep->error = EMBRYO_ERROR_INDEX;
1302              return EMBRYO_PROGRAM_FAIL;
1303           }
1304         func = GETENTRY(hdr, publics, fn);
1305         cip = (Embryo_Cell *)(code + (int)func->address);
1306      }
1307    /* check values just copied */
1308    CHKSTACK();
1309    CHKHEAP();
1310
1311    if (fn != EMBRYO_FUNCTION_CONT)
1312      {
1313         int i;
1314
1315         for (i = ep->params_size - 1; i >= 0; i--)
1316           {
1317              Embryo_Param *pr;
1318
1319              pr = &(ep->params[i]);
1320              if (pr->string)
1321                {
1322                   int len;
1323                   Embryo_Cell ep_addr, *addr;
1324
1325                   len = strlen(pr->string);
1326                   ep_addr = embryo_data_heap_push(ep, len + 1);
1327                   if (ep_addr == EMBRYO_CELL_NONE)
1328                     {
1329                        ep->error = EMBRYO_ERROR_HEAPLOW;
1330                        return EMBRYO_PROGRAM_FAIL;
1331                     }
1332                   addr = embryo_data_address_get(ep, ep_addr);
1333                   if (addr)
1334                     embryo_data_string_set(ep, pr->string, addr);
1335                   else
1336                     {
1337                        ep->error = EMBRYO_ERROR_HEAPLOW;
1338                        return EMBRYO_PROGRAM_FAIL;
1339                     }
1340                   PUSH(ep_addr);
1341                   free(pr->string);
1342                }
1343              else if (pr->cell_array)
1344                {
1345                   int len;
1346                   Embryo_Cell ep_addr, *addr;
1347
1348                   len = pr->cell_array_size;
1349                   ep_addr = embryo_data_heap_push(ep, len + 1);
1350                   if (ep_addr == EMBRYO_CELL_NONE)
1351                     {
1352                        ep->error = EMBRYO_ERROR_HEAPLOW;
1353                        return EMBRYO_PROGRAM_FAIL;
1354                     }
1355                   addr = embryo_data_address_get(ep, ep_addr);
1356                   if (addr)
1357                     memcpy(addr, pr->cell_array,
1358                            pr->cell_array_size * sizeof(Embryo_Cell));
1359                   else
1360                     {
1361                        ep->error = EMBRYO_ERROR_HEAPLOW;
1362                        return EMBRYO_PROGRAM_FAIL;
1363                     }
1364                   PUSH(ep_addr);
1365                   free(pr->cell_array);
1366                }
1367              else
1368                {
1369                   PUSH(pr->cell);
1370                }
1371           }
1372         PUSH(ep->params_size * sizeof(Embryo_Cell));
1373         PUSH(0);
1374         if (ep->params)
1375           {
1376              free(ep->params);
1377              ep->params = NULL;
1378           }
1379         ep->params_size = ep->params_alloc = 0;
1380      }
1381    /* check stack/heap before starting to run */
1382    CHKMARGIN();
1383
1384    /* track recursion depth */
1385    ep->run_count++;
1386
1387    max_run_cycles = ep->max_run_cycles;
1388    /* start running */
1389    for (cycle_count = 0;;)
1390      {
1391         if (max_run_cycles > 0)
1392           {
1393              if (cycle_count >= max_run_cycles)
1394                {
1395                   TOOLONG(ep);
1396                }
1397              cycle_count++;
1398           }
1399         op = (Embryo_Opcode)*cip++;
1400         SWITCH(op);
1401         CASE(EMBRYO_OP_LOAD_PRI);
1402         GETPARAM(offs);
1403         pri = *(Embryo_Cell *)(data + (int)offs);
1404         BREAK;
1405         CASE(EMBRYO_OP_LOAD_ALT);
1406         GETPARAM(offs);
1407         alt = *(Embryo_Cell *)(data + (int)offs);
1408         BREAK;
1409         CASE(EMBRYO_OP_LOAD_S_PRI);
1410         GETPARAM(offs);
1411         pri = *(Embryo_Cell *)(data + (int)frm + (int)offs);
1412         BREAK;
1413         CASE(EMBRYO_OP_LOAD_S_ALT);
1414         GETPARAM(offs);
1415         alt = *(Embryo_Cell *)(data + (int)frm + (int)offs);
1416         BREAK;
1417         CASE(EMBRYO_OP_LREF_PRI);
1418         GETPARAM(offs);
1419         offs = *(Embryo_Cell *)(data + (int)offs);
1420         pri = *(Embryo_Cell *)(data + (int)offs);
1421         BREAK;
1422         CASE(EMBRYO_OP_LREF_ALT);
1423         GETPARAM(offs);
1424         offs = *(Embryo_Cell *)(data + (int)offs);
1425         alt = *(Embryo_Cell *)(data + (int)offs);
1426         BREAK;
1427         CASE(EMBRYO_OP_LREF_S_PRI);
1428         GETPARAM(offs);
1429         offs = *(Embryo_Cell *)(data + (int)frm + (int)offs);
1430         pri = *(Embryo_Cell *)(data + (int)offs);
1431         BREAK;
1432         CASE(EMBRYO_OP_LREF_S_ALT);
1433         GETPARAM(offs);
1434         offs = *(Embryo_Cell *)(data + (int)frm + (int)offs);
1435         alt = *(Embryo_Cell *)(data + (int)offs);
1436         BREAK;
1437         CASE(EMBRYO_OP_LOAD_I);
1438         CHKMEM(pri);
1439         pri = *(Embryo_Cell *)(data + (int)pri);
1440         BREAK;
1441         CASE(EMBRYO_OP_LODB_I);
1442         GETPARAM(offs);
1443         CHKMEM(pri);
1444         switch (offs)
1445           {
1446            case 1:
1447              pri = *(data + (int)pri);
1448              break;
1449            case 2:
1450              pri = *(unsigned short *)(data + (int)pri);
1451              break;
1452            case 4:
1453              pri = *(unsigned int *)(data + (int)pri);
1454              break;
1455            default:
1456              ABORT(ep, EMBRYO_ERROR_INVINSTR);
1457              break;
1458           }
1459         BREAK;
1460         CASE(EMBRYO_OP_CONST_PRI);
1461         GETPARAM(pri);
1462         BREAK;
1463         CASE(EMBRYO_OP_CONST_ALT);
1464         GETPARAM(alt);
1465         BREAK;
1466         CASE(EMBRYO_OP_ADDR_PRI);
1467         GETPARAM(pri);
1468         pri += frm;
1469         BREAK;
1470         CASE(EMBRYO_OP_ADDR_ALT);
1471         GETPARAM(alt);
1472         alt += frm;
1473         BREAK;
1474         CASE(EMBRYO_OP_STOR_PRI);
1475         GETPARAM(offs);
1476         *(Embryo_Cell *)(data + (int)offs) = pri;
1477         BREAK;
1478         CASE(EMBRYO_OP_STOR_ALT);
1479         GETPARAM(offs);
1480         *(Embryo_Cell *)(data + (int)offs) = alt;
1481         BREAK;
1482         CASE(EMBRYO_OP_STOR_S_PRI);
1483         GETPARAM(offs);
1484         *(Embryo_Cell *)(data + (int)frm + (int)offs) = pri;
1485         BREAK;
1486         CASE(EMBRYO_OP_STOR_S_ALT);
1487         GETPARAM(offs);
1488         *(Embryo_Cell *)(data + (int)frm + (int)offs) = alt;
1489         BREAK;
1490         CASE(EMBRYO_OP_SREF_PRI);
1491         GETPARAM(offs);
1492         offs = *(Embryo_Cell *)(data + (int)offs);
1493         *(Embryo_Cell *)(data + (int)offs) = pri;
1494         BREAK;
1495         CASE(EMBRYO_OP_SREF_ALT);
1496         GETPARAM(offs);
1497         offs = *(Embryo_Cell *)(data + (int)offs);
1498         *(Embryo_Cell *)(data + (int)offs) = alt;
1499         BREAK;
1500         CASE(EMBRYO_OP_SREF_S_PRI);
1501         GETPARAM(offs);
1502         offs = *(Embryo_Cell *)(data + (int)frm + (int)offs);
1503         *(Embryo_Cell *)(data + (int)offs) = pri;
1504         BREAK;
1505         CASE(EMBRYO_OP_SREF_S_ALT);
1506         GETPARAM(offs);
1507         offs = *(Embryo_Cell *)(data + (int)frm + (int)offs);
1508         *(Embryo_Cell *)(data + (int)offs) = alt;
1509         BREAK;
1510         CASE(EMBRYO_OP_STOR_I);
1511         CHKMEM(alt);
1512         *(Embryo_Cell *)(data + (int)alt) = pri;
1513         BREAK;
1514         CASE(EMBRYO_OP_STRB_I);
1515         GETPARAM(offs);
1516         CHKMEM(alt);
1517         switch (offs)
1518           {
1519            case 1:
1520              *(data + (int)alt) = (unsigned char)pri;
1521              break;
1522            case 2:
1523              *(unsigned short *)(data + (int)alt) = (unsigned short)pri;
1524              break;
1525            case 4:
1526              *(unsigned int *)(data + (int)alt) = (unsigned int)pri;
1527              break;
1528            default:
1529              ABORT(ep, EMBRYO_ERROR_INVINSTR);
1530              break;
1531           }
1532         BREAK;
1533         CASE(EMBRYO_OP_LIDX);
1534         offs = (pri * sizeof(Embryo_Cell)) + alt;
1535         CHKMEM(offs);
1536         pri = *(Embryo_Cell *)(data + (int)offs);
1537         BREAK;
1538         CASE(EMBRYO_OP_LIDX_B);
1539         GETPARAM(offs);
1540         offs = (pri << (int)offs) + alt;
1541         CHKMEM(offs);
1542         pri = *(Embryo_Cell *)(data + (int)offs);
1543         BREAK;
1544         CASE(EMBRYO_OP_IDXADDR);
1545         pri = (pri * sizeof(Embryo_Cell)) + alt;
1546         BREAK;
1547         CASE(EMBRYO_OP_IDXADDR_B);
1548         GETPARAM(offs);
1549         pri = (pri << (int)offs) + alt;
1550         BREAK;
1551         CASE(EMBRYO_OP_ALIGN_PRI);
1552         GETPARAM(offs);
1553 #ifdef WORDS_BIGENDIAN
1554         if ((size_t)offs < sizeof(Embryo_Cell))
1555           pri ^= sizeof(Embryo_Cell) - offs;
1556 #endif
1557         BREAK;
1558         CASE(EMBRYO_OP_ALIGN_ALT);
1559         GETPARAM(offs);
1560 #ifdef WORDS_BIGENDIAN
1561         if ((size_t)offs < sizeof(Embryo_Cell))
1562           alt ^= sizeof(Embryo_Cell) - offs;
1563 #endif
1564         BREAK;
1565         CASE(EMBRYO_OP_LCTRL);
1566         GETPARAM(offs);
1567         switch (offs)
1568           {
1569            case 0:
1570              pri = hdr->cod;
1571              break;
1572            case 1:
1573              pri = hdr->dat;
1574              break;
1575            case 2:
1576              pri = hea;
1577              break;
1578            case 3:
1579              pri = ep->stp;
1580              break;
1581            case 4:
1582              pri = stk;
1583              break;
1584            case 5:
1585              pri = frm;
1586              break;
1587            case 6:
1588              pri = (Embryo_Cell)((unsigned char *)cip - code);
1589              break;
1590            default:
1591              ABORT(ep, EMBRYO_ERROR_INVINSTR);
1592              break;
1593           }
1594         BREAK;
1595         CASE(EMBRYO_OP_SCTRL);
1596         GETPARAM(offs);
1597         switch (offs)
1598           {
1599            case 0:
1600            case 1:
1601            case 2:
1602              hea = pri;
1603              break;
1604            case 3:
1605              /* cannot change these parameters */
1606              break;
1607            case 4:
1608              stk = pri;
1609              break;
1610            case 5:
1611              frm = pri;
1612              break;
1613            case 6:
1614              cip = (Embryo_Cell *)(code + (int)pri);
1615              break;
1616            default:
1617              ABORT(ep, EMBRYO_ERROR_INVINSTR);
1618              break;
1619           }
1620         BREAK;
1621         CASE(EMBRYO_OP_MOVE_PRI);
1622         pri = alt;
1623         BREAK;
1624         CASE(EMBRYO_OP_MOVE_ALT);
1625         alt = pri;
1626         BREAK;
1627         CASE(EMBRYO_OP_XCHG);
1628         offs = pri;         /* offs is a temporary variable */
1629         pri = alt;
1630         alt = offs;
1631         BREAK;
1632         CASE(EMBRYO_OP_PUSH_PRI);
1633         PUSH(pri);
1634         BREAK;
1635         CASE(EMBRYO_OP_PUSH_ALT);
1636         PUSH(alt);
1637         BREAK;
1638         CASE(EMBRYO_OP_PUSH_C);
1639         GETPARAM(offs);
1640         PUSH(offs);
1641         BREAK;
1642         CASE(EMBRYO_OP_PUSH_R);
1643         GETPARAM(offs);
1644         while (offs--) PUSH(pri);
1645         BREAK;
1646         CASE(EMBRYO_OP_PUSH);
1647         GETPARAM(offs);
1648         PUSH(*(Embryo_Cell *)(data + (int)offs));
1649         BREAK;
1650         CASE(EMBRYO_OP_PUSH_S);
1651         GETPARAM(offs);
1652         PUSH(*(Embryo_Cell *)(data + (int)frm + (int)offs));
1653         BREAK;
1654         CASE(EMBRYO_OP_POP_PRI);
1655         POP(pri);
1656         BREAK;
1657         CASE(EMBRYO_OP_POP_ALT);
1658         POP(alt);
1659         BREAK;
1660         CASE(EMBRYO_OP_STACK);
1661         GETPARAM(offs);
1662         alt = stk;
1663         stk += offs;
1664         CHKMARGIN();
1665         CHKSTACK();
1666         BREAK;
1667         CASE(EMBRYO_OP_HEAP);
1668         GETPARAM(offs);
1669         alt = hea;
1670         hea += offs;
1671         CHKMARGIN();
1672         CHKHEAP();
1673         BREAK;
1674         CASE(EMBRYO_OP_PROC);
1675         PUSH(frm);
1676         frm = stk;
1677         CHKMARGIN();
1678         BREAK;
1679         CASE(EMBRYO_OP_RET);
1680         POP(frm);
1681         POP(offs);
1682         if ((Embryo_UCell)offs >= codesize)
1683           ABORT(ep, EMBRYO_ERROR_MEMACCESS);
1684         cip = (Embryo_Cell *)(code + (int)offs);
1685         BREAK;
1686         CASE(EMBRYO_OP_RETN);
1687         POP(frm);
1688         POP(offs);
1689         if ((Embryo_UCell)offs >= codesize)
1690           ABORT(ep, EMBRYO_ERROR_MEMACCESS);
1691         cip = (Embryo_Cell *)(code + (int)offs);
1692         stk += *(Embryo_Cell *)(data + (int)stk) + sizeof(Embryo_Cell); /* remove parameters from the stack */
1693         ep->stk = stk;
1694         BREAK;
1695         CASE(EMBRYO_OP_CALL);
1696         PUSH(((unsigned char *)cip - code) + sizeof(Embryo_Cell));/* skip address */
1697         cip = JUMPABS(code, cip); /* jump to the address */
1698         BREAK;
1699         CASE(EMBRYO_OP_CALL_PRI);
1700         PUSH((unsigned char *)cip - code);
1701         cip = (Embryo_Cell *)(code + (int)pri);
1702         BREAK;
1703         CASE(EMBRYO_OP_JUMP);
1704         /* since the GETPARAM() macro modifies cip, you cannot
1705          * do GETPARAM(cip) directly */
1706         cip = JUMPABS(code, cip);
1707         BREAK;
1708         CASE(EMBRYO_OP_JREL);
1709         offs = *cip;
1710         cip = (Embryo_Cell *)((unsigned char *)cip + (int)offs + sizeof(Embryo_Cell));
1711         BREAK;
1712         CASE(EMBRYO_OP_JZER);
1713         if (pri == 0)
1714           cip = JUMPABS(code, cip);
1715         else
1716           cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1717         BREAK;
1718         CASE(EMBRYO_OP_JNZ);
1719         if (pri != 0)
1720           cip = JUMPABS(code, cip);
1721         else
1722           cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1723         BREAK;
1724         CASE(EMBRYO_OP_JEQ);
1725         if (pri==alt)
1726           cip = JUMPABS(code, cip);
1727         else
1728           cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1729         BREAK;
1730         CASE(EMBRYO_OP_JNEQ);
1731         if (pri != alt)
1732           cip = JUMPABS(code, cip);
1733         else
1734           cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1735         BREAK;
1736         CASE(EMBRYO_OP_JLESS);
1737         if ((Embryo_UCell)pri < (Embryo_UCell)alt)
1738           cip = JUMPABS(code, cip);
1739         else
1740           cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1741         BREAK;
1742         CASE(EMBRYO_OP_JLEQ);
1743         if ((Embryo_UCell)pri <= (Embryo_UCell)alt)
1744           cip = JUMPABS(code, cip);
1745         else
1746           cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1747         BREAK;
1748         CASE(EMBRYO_OP_JGRTR);
1749         if ((Embryo_UCell)pri > (Embryo_UCell)alt)
1750           cip = JUMPABS(code, cip);
1751         else
1752           cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1753         BREAK;
1754         CASE(EMBRYO_OP_JGEQ);
1755         if ((Embryo_UCell)pri >= (Embryo_UCell)alt)
1756           cip = JUMPABS(code, cip);
1757         else
1758           cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1759         BREAK;
1760         CASE(EMBRYO_OP_JSLESS);
1761         if (pri < alt)
1762           cip = JUMPABS(code, cip);
1763         else
1764           cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1765         BREAK;
1766         CASE(EMBRYO_OP_JSLEQ);
1767         if (pri <= alt)
1768           cip = JUMPABS(code, cip);
1769         else
1770           cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1771         BREAK;
1772         CASE(EMBRYO_OP_JSGRTR);
1773         if (pri > alt)
1774           cip = JUMPABS(code, cip);
1775         else
1776           cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1777         BREAK;
1778         CASE(EMBRYO_OP_JSGEQ);
1779         if (pri >= alt)
1780           cip = JUMPABS(code, cip);
1781         else
1782           cip = (Embryo_Cell *)((unsigned char *)cip + sizeof(Embryo_Cell));
1783         BREAK;
1784         CASE(EMBRYO_OP_SHL);
1785         pri <<= alt;
1786         BREAK;
1787         CASE(EMBRYO_OP_SHR);
1788         pri = (Embryo_UCell)pri >> (int)alt;
1789         BREAK;
1790         CASE(EMBRYO_OP_SSHR);
1791         pri >>= alt;
1792         BREAK;
1793         CASE(EMBRYO_OP_SHL_C_PRI);
1794         GETPARAM(offs);
1795         pri <<= offs;
1796         BREAK;
1797         CASE(EMBRYO_OP_SHL_C_ALT);
1798         GETPARAM(offs);
1799         alt <<= offs;
1800         BREAK;
1801         CASE(EMBRYO_OP_SHR_C_PRI);
1802         GETPARAM(offs);
1803         pri = (Embryo_UCell)pri >> (int)offs;
1804         BREAK;
1805         CASE(EMBRYO_OP_SHR_C_ALT);
1806         GETPARAM(offs);
1807         alt = (Embryo_UCell)alt >> (int)offs;
1808         BREAK;
1809         CASE(EMBRYO_OP_SMUL);
1810         pri *= alt;
1811         BREAK;
1812         CASE(EMBRYO_OP_SDIV);
1813         if (alt == 0) ABORT(ep, EMBRYO_ERROR_DIVIDE);
1814         /* divide must always round down; this is a bit
1815          * involved to do in a machine-independent way.
1816          */
1817         offs = ((pri % alt) + alt) % alt; /* true modulus */
1818         pri = (pri - offs) / alt;         /* division result */
1819         alt = offs;
1820         BREAK;
1821         CASE(EMBRYO_OP_SDIV_ALT);
1822         if (pri == 0) ABORT(ep, EMBRYO_ERROR_DIVIDE);
1823         /* divide must always round down; this is a bit
1824          * involved to do in a machine-independent way.
1825          */
1826         offs = ((alt % pri) + pri) % pri; /* true modulus */
1827         pri = (alt - offs) / pri;         /* division result */
1828         alt = offs;
1829         BREAK;
1830         CASE(EMBRYO_OP_UMUL);
1831         pri = (Embryo_UCell)pri * (Embryo_UCell)alt;
1832         BREAK;
1833         CASE(EMBRYO_OP_UDIV);
1834         if (alt == 0) ABORT(ep, EMBRYO_ERROR_DIVIDE);
1835         offs = (Embryo_UCell)pri % (Embryo_UCell)alt; /* temporary storage */
1836         pri = (Embryo_UCell)pri / (Embryo_UCell)alt;
1837         alt = offs;
1838         BREAK;
1839         CASE(EMBRYO_OP_UDIV_ALT);
1840         if (pri == 0) ABORT(ep, EMBRYO_ERROR_DIVIDE);
1841         offs = (Embryo_UCell)alt % (Embryo_UCell)pri; /* temporary storage */
1842         pri = (Embryo_UCell)alt / (Embryo_UCell)pri;
1843         alt = offs;
1844         BREAK;
1845         CASE(EMBRYO_OP_ADD);
1846         pri += alt;
1847         BREAK;
1848         CASE(EMBRYO_OP_SUB);
1849         pri -= alt;
1850         BREAK;
1851         CASE(EMBRYO_OP_SUB_ALT);
1852         pri = alt - pri;
1853         BREAK;
1854         CASE(EMBRYO_OP_AND);
1855         pri &= alt;
1856         BREAK;
1857         CASE(EMBRYO_OP_OR);
1858         pri |= alt;
1859         BREAK;
1860         CASE(EMBRYO_OP_XOR);
1861         pri ^= alt;
1862         BREAK;
1863         CASE(EMBRYO_OP_NOT);
1864         pri = !pri;
1865         BREAK;
1866         CASE(EMBRYO_OP_NEG);
1867         pri = -pri;
1868         BREAK;
1869         CASE(EMBRYO_OP_INVERT);
1870         pri = ~pri;
1871         BREAK;
1872         CASE(EMBRYO_OP_ADD_C);
1873         GETPARAM(offs);
1874         pri += offs;
1875         BREAK;
1876         CASE(EMBRYO_OP_SMUL_C);
1877         GETPARAM(offs);
1878         pri *= offs;
1879         BREAK;
1880         CASE(EMBRYO_OP_ZERO_PRI);
1881         pri = 0;
1882         BREAK;
1883         CASE(EMBRYO_OP_ZERO_ALT);
1884         alt = 0;
1885         BREAK;
1886         CASE(EMBRYO_OP_ZERO);
1887         GETPARAM(offs);
1888         *(Embryo_Cell *)(data + (int)offs) = 0;
1889         BREAK;
1890         CASE(EMBRYO_OP_ZERO_S);
1891         GETPARAM(offs);
1892         *(Embryo_Cell *)(data + (int)frm + (int)offs) = 0;
1893         BREAK;
1894         CASE(EMBRYO_OP_SIGN_PRI);
1895         if ((pri & 0xff) >= 0x80) pri |= ~(Embryo_UCell)0xff;
1896         BREAK;
1897         CASE(EMBRYO_OP_SIGN_ALT);
1898         if ((alt & 0xff) >= 0x80) alt |= ~(Embryo_UCell)0xff;
1899         BREAK;
1900         CASE(EMBRYO_OP_EQ);
1901         pri = (pri == alt) ? 1 : 0;
1902         BREAK;
1903         CASE(EMBRYO_OP_NEQ);
1904         pri = (pri != alt) ? 1 : 0;
1905         BREAK;
1906         CASE(EMBRYO_OP_LESS);
1907         pri = ((Embryo_UCell)pri < (Embryo_UCell)alt) ? 1 : 0;
1908         BREAK;
1909         CASE(EMBRYO_OP_LEQ);
1910         pri = ((Embryo_UCell)pri <= (Embryo_UCell)alt) ? 1 : 0;
1911         BREAK;
1912         CASE(EMBRYO_OP_GRTR);
1913         pri = ((Embryo_UCell)pri > (Embryo_UCell)alt) ? 1 : 0;
1914         BREAK;
1915         CASE(EMBRYO_OP_GEQ);
1916         pri = ((Embryo_UCell)pri >= (Embryo_UCell)alt) ? 1 : 0;
1917         BREAK;
1918         CASE(EMBRYO_OP_SLESS);
1919         pri = (pri < alt) ? 1 : 0;
1920         BREAK;
1921         CASE(EMBRYO_OP_SLEQ);
1922         pri = (pri <= alt) ? 1 : 0;
1923         BREAK;
1924         CASE(EMBRYO_OP_SGRTR);
1925         pri = (pri > alt) ? 1 : 0;
1926         BREAK;
1927         CASE(EMBRYO_OP_SGEQ);
1928         pri = (pri >= alt) ? 1 : 0;
1929         BREAK;
1930         CASE(EMBRYO_OP_EQ_C_PRI);
1931         GETPARAM(offs);
1932         pri = (pri == offs) ? 1 : 0;
1933         BREAK;
1934         CASE(EMBRYO_OP_EQ_C_ALT);
1935         GETPARAM(offs);
1936         pri = (alt == offs) ? 1 : 0;
1937         BREAK;
1938         CASE(EMBRYO_OP_INC_PRI);
1939         pri++;
1940         BREAK;
1941         CASE(EMBRYO_OP_INC_ALT);
1942         alt++;
1943         BREAK;
1944         CASE(EMBRYO_OP_INC);
1945         GETPARAM(offs);
1946         *(Embryo_Cell *)(data + (int)offs) += 1;
1947         BREAK;
1948         CASE(EMBRYO_OP_INC_S);
1949         GETPARAM(offs);
1950         *(Embryo_Cell *)(data + (int)frm + (int)offs) += 1;
1951         BREAK;
1952         CASE(EMBRYO_OP_INC_I);
1953         *(Embryo_Cell *)(data + (int)pri) += 1;
1954         BREAK;
1955         CASE(EMBRYO_OP_DEC_PRI);
1956         pri--;
1957         BREAK;
1958         CASE(EMBRYO_OP_DEC_ALT);
1959         alt--;
1960         BREAK;
1961         CASE(EMBRYO_OP_DEC);
1962         GETPARAM(offs);
1963         *(Embryo_Cell *)(data + (int)offs) -= 1;
1964         BREAK;
1965         CASE(EMBRYO_OP_DEC_S);
1966         GETPARAM(offs);
1967         *(Embryo_Cell *)(data + (int)frm + (int)offs) -= 1;
1968         BREAK;
1969         CASE(EMBRYO_OP_DEC_I);
1970         *(Embryo_Cell *)(data + (int)pri) -= 1;
1971         BREAK;
1972         CASE(EMBRYO_OP_MOVS);
1973         GETPARAM(offs);
1974         CHKMEM(pri);
1975         CHKMEM(pri + offs);
1976         CHKMEM(alt);
1977         CHKMEM(alt + offs);
1978         memcpy(data+(int)alt, data+(int)pri, (int)offs);
1979         BREAK;
1980         CASE(EMBRYO_OP_CMPS);
1981         GETPARAM(offs);
1982         CHKMEM(pri);
1983         CHKMEM(pri + offs);
1984         CHKMEM(alt);
1985         CHKMEM(alt + offs);
1986         pri = memcmp(data + (int)alt, data + (int)pri, (int)offs);
1987         BREAK;
1988         CASE(EMBRYO_OP_FILL);
1989         GETPARAM(offs);
1990         CHKMEM(alt);
1991         CHKMEM(alt + offs);
1992         for (i = (int)alt;
1993              (size_t)offs >= sizeof(Embryo_Cell);
1994              i += sizeof(Embryo_Cell), offs -= sizeof(Embryo_Cell))
1995           *(Embryo_Cell *)(data + i) = pri;
1996         BREAK;
1997         CASE(EMBRYO_OP_HALT);
1998         GETPARAM(offs);
1999         ep->retval = pri;
2000         /* store complete status */
2001         ep->frm = frm;
2002         ep->stk = stk;
2003         ep->hea = hea;
2004         ep->pri = pri;
2005         ep->alt = alt;
2006         ep->cip = (Embryo_Cell)((unsigned char*)cip - code);
2007         if (offs == EMBRYO_ERROR_SLEEP)
2008           {
2009              ep->reset_stk = reset_stk;
2010              ep->reset_hea = reset_hea;
2011              ep->run_count--;
2012              return EMBRYO_PROGRAM_SLEEP;
2013           }
2014         OK(ep, (int)offs);
2015         CASE(EMBRYO_OP_BOUNDS);
2016         GETPARAM(offs);
2017         if ((Embryo_UCell)pri > (Embryo_UCell)offs)
2018           ABORT(ep, EMBRYO_ERROR_BOUNDS);
2019         BREAK;
2020         CASE(EMBRYO_OP_SYSREQ_PRI);
2021         /* save a few registers */
2022         ep->cip = (Embryo_Cell)((unsigned char *)cip - code);
2023         ep->hea = hea;
2024         ep->frm = frm;
2025         ep->stk = stk;
2026         num = _embryo_native_call(ep, pri, &pri, (Embryo_Cell *)(data + (int)stk));
2027         if (num != EMBRYO_ERROR_NONE)
2028           {
2029              if (num == EMBRYO_ERROR_SLEEP)
2030                {
2031                   ep->pri = pri;
2032                   ep->alt = alt;
2033                   ep->reset_stk = reset_stk;
2034                   ep->reset_hea = reset_hea;
2035                   ep->run_count--;
2036                   return EMBRYO_PROGRAM_SLEEP;
2037                }
2038              ABORT(ep, num);
2039           }
2040         BREAK;
2041         CASE(EMBRYO_OP_SYSREQ_C);
2042         GETPARAM(offs);
2043         /* save a few registers */
2044         ep->cip = (Embryo_Cell)((unsigned char *)cip - code);
2045         ep->hea = hea;
2046         ep->frm = frm;
2047         ep->stk = stk;
2048         num = _embryo_native_call(ep, offs, &pri, (Embryo_Cell *)(data + (int)stk));
2049         if (num != EMBRYO_ERROR_NONE)
2050           {
2051              if (num == EMBRYO_ERROR_SLEEP)
2052                {
2053                   ep->pri = pri;
2054                   ep->alt = alt;
2055                   ep->reset_stk = reset_stk;
2056                   ep->reset_hea = reset_hea;
2057                   ep->run_count--;
2058                   return EMBRYO_PROGRAM_SLEEP;
2059                }
2060                {
2061                   Embryo_Header    *hdr;
2062                   int i, num;
2063                   Embryo_Func_Stub *func_entry;
2064
2065                   hdr = (Embryo_Header *)ep->code;
2066                   num = NUMENTRIES(hdr, natives, libraries);
2067                   func_entry = GETENTRY(hdr, natives, 0);
2068                   for (i = 0; i < num; i++)
2069                     {
2070                        char *entry_name;
2071
2072                        entry_name = GETENTRYNAME(hdr, func_entry);
2073                        if (i == offs)
2074                          printf("EMBRYO: CALL [%i] %s() non-existent!\n", i, entry_name);
2075                        func_entry =
2076                          (Embryo_Func_Stub *)((unsigned char *)func_entry + hdr->defsize);
2077                     }
2078                }
2079              ABORT(ep, num);
2080           }
2081         BREAK;
2082         CASE(EMBRYO_OP_SYSREQ_D);
2083         GETPARAM(offs);
2084         /* save a few registers */
2085         ep->cip = (Embryo_Cell)((unsigned char *)cip - code);
2086         ep->hea = hea;
2087         ep->frm = frm;
2088         ep->stk = stk;
2089         num = _embryo_native_call(ep, offs, &pri, (Embryo_Cell *)(data + (int)stk));
2090         if (num != EMBRYO_ERROR_NONE)
2091           {
2092              if (num == EMBRYO_ERROR_SLEEP)
2093                {
2094                   ep->pri = pri;
2095                   ep->alt = alt;
2096                   ep->reset_stk = reset_stk;
2097                   ep->reset_hea = reset_hea;
2098                   ep->run_count--;
2099                   return EMBRYO_PROGRAM_SLEEP;
2100                }
2101              ABORT(ep, ep->error);
2102           }
2103         BREAK;
2104         CASE(EMBRYO_OP_JUMP_PRI);
2105         cip = (Embryo_Cell *)(code + (int)pri);
2106         BREAK;
2107         CASE(EMBRYO_OP_SWITCH);
2108           {
2109              Embryo_Cell *cptr;
2110
2111              /* +1, to skip the "casetbl" opcode */
2112              cptr = (Embryo_Cell *)(code + (*cip)) + 1;
2113              /* number of records in the case table */
2114              num = (int)(*cptr);
2115              /* preset to "none-matched" case */
2116              cip = (Embryo_Cell *)(code + *(cptr + 1));
2117              for (cptr += 2;
2118                   (num > 0) && (*cptr != pri);
2119                   num--, cptr += 2);
2120              /* case found */
2121              if (num > 0)
2122                cip = (Embryo_Cell *)(code + *(cptr + 1));
2123           }
2124         BREAK;
2125         CASE(EMBRYO_OP_SWAP_PRI);
2126         offs = *(Embryo_Cell *)(data + (int)stk);
2127         *(Embryo_Cell *)(data + (int)stk) = pri;
2128         pri = offs;
2129         BREAK;
2130         CASE(EMBRYO_OP_SWAP_ALT);
2131         offs = *(Embryo_Cell *)(data + (int)stk);
2132         *(Embryo_Cell *)(data + (int)stk) = alt;
2133         alt = offs;
2134         BREAK;
2135         CASE(EMBRYO_OP_PUSHADDR);
2136         GETPARAM(offs);
2137         PUSH(frm + offs);
2138         BREAK;
2139         CASE(EMBRYO_OP_NOP);
2140         BREAK;
2141         CASE(EMBRYO_OP_NONE);
2142         CASE(EMBRYO_OP_FILE);
2143         CASE(EMBRYO_OP_LINE);
2144         CASE(EMBRYO_OP_SYMBOL);
2145         CASE(EMBRYO_OP_SRANGE);
2146         CASE(EMBRYO_OP_CASETBL);
2147         CASE(EMBRYO_OP_SYMTAG);
2148         BREAK;
2149 #ifndef EMBRYO_EXEC_JUMPTABLE
2150       default:
2151         ABORT(ep, EMBRYO_ERROR_INVINSTR);
2152 #endif
2153         SWITCHEND;
2154      }
2155    ep->max_run_cycles = max_run_cycles;
2156    ep->run_count--;
2157    ep->hea = hea_start;
2158    return EMBRYO_PROGRAM_OK;
2159 }
2160
2161 /**
2162  * Retreives the return value of the last called function of the given
2163  * program.
2164  * @param   ep The given program.
2165  * @return  An Embryo_Cell representing the return value of the function
2166  *          that was last called.
2167  * @ingroup Embryo_Run_Group
2168  */
2169 EAPI Embryo_Cell
2170 embryo_program_return_value_get(Embryo_Program *ep)
2171 {
2172    if (!ep) return 0;
2173    return ep->retval;
2174 }
2175
2176 /**
2177  * Sets the maximum number of abstract machine cycles any given program run
2178  * can execute before being put to sleep and returning.
2179  *
2180  * @param   ep The given program.
2181  * @param   max The number of machine cycles as a limit.
2182  *
2183  * This sets the maximum number of abstract machine (virtual machine)
2184  * instructions that a single run of an embryo function (even if its main)
2185  * can use before embryo embryo_program_run() reutrns with the value
2186  * EMBRYO_PROGRAM_TOOLONG. If the function fully executes within this number
2187  * of cycles, embryo_program_run() will return as normal with either
2188  * EMBRYO_PROGRAM_OK, EMBRYO_PROGRAM_FAIL or EMBRYO_PROGRAM_SLEEP. If the
2189  * run exceeds this instruction count, then EMBRYO_PROGRAM_TOOLONG will be
2190  * returned indicating the program exceeded its run count. If the app wishes
2191  * to continue running this anyway - it is free to process its own events or
2192  * whatever it wants and continue the function by calling
2193  * embryo_program_run(program, EMBRYO_FUNCTION_CONT); which will start the
2194  * run again until the instruction count is reached. This can keep being done
2195  * to allow the calling program to still be able to control things outside the
2196  * embryo function being called. If the maximum run cycle count is 0 then the
2197  * program is allowed to run forever only returning when it is done.
2198  *
2199  * It is important to note that abstract machine cycles are NOT the same as
2200  * the host machine cpu cycles. They are not fixed in runtime per cycle, so
2201  * this is more of a helper tool than a way to HARD-FORCE a script to only
2202  * run for a specific period of time. If the cycle count is set to something
2203  * low like 5000 or 1000, then every 1000 (or 5000) cycles control will be
2204  * returned to the calling process where it can check a timer to see if a
2205  * physical runtime limit has been elapsed and then abort running further
2206  * assuming a "runaway script" or keep continuing the script run. This
2207  * limits resolution to only that many cycles which do not take a determined
2208  * amount of time to execute, as this varies from cpu to cpu and also depends
2209  * on how loaded the system is. Making the max cycle run too low will
2210  * impact performance requiring the abstract machine to do setup and teardown
2211  * cycles too often comapred to cycles actually executed.
2212  *
2213  * Also note it does NOT include nested abstract machines. IF this abstract
2214  * machine run calls embryo script that calls a native function that in turn
2215  * calls more embryo script, then the 2nd (and so on) levels are not included
2216  * in this run count. They can set their own max instruction count values
2217  * separately.
2218  *
2219  * The default max cycle run value is 0 in any program until set with this
2220  * function.
2221  *
2222  * @ingroup Embryo_Run_Group
2223  */
2224 EAPI void
2225 embryo_program_max_cycle_run_set(Embryo_Program *ep, int max)
2226 {
2227    if (!ep) return;
2228    if (max < 0) max = 0;
2229    ep->max_run_cycles = max;
2230 }
2231
2232 /**
2233  * Retreives the maximum number of abstract machine cycles a program is allowed
2234  * to run.
2235  * @param   ep The given program.
2236  * @return  The number of cycles a run cycle is allowed to run for this
2237  *          program.
2238  *
2239  * This returns the value set by embryo_program_max_cycle_run_set(). See
2240  * embryo_program_max_cycle_run_set() for more information.
2241  *
2242  * @ingroup Embryo_Run_Group
2243  */
2244 EAPI int
2245 embryo_program_max_cycle_run_get(Embryo_Program *ep)
2246 {
2247    if (!ep) return 0;
2248    return ep->max_run_cycles;
2249 }
2250
2251 /**
2252  * @defgroup Embryo_Parameter_Group Function Parameter Functions
2253  *
2254  * Functions that set parameters for the next function that is called.
2255  */
2256
2257 /**
2258  * Pushes an Embryo_Cell onto the function stack to use as a parameter for
2259  * the next function that is called in the given program.
2260  * @param   ep   The given program.
2261  * @param   cell The Embryo_Cell to push onto the stack.
2262  * @return  @c 1 if successful.  @c 0 otherwise.
2263  * @ingroup Embryo_Parameter_Group
2264  */
2265 EAPI int
2266 embryo_parameter_cell_push(Embryo_Program *ep, Embryo_Cell cell)
2267 {
2268    Embryo_Param *pr;
2269
2270    ep->params_size++;
2271    if (ep->params_size > ep->params_alloc)
2272      {
2273         ep->params_alloc += 8;
2274         pr = realloc(ep->params, ep->params_alloc * sizeof(Embryo_Param));
2275         if (!pr) return 0;
2276         ep->params = pr;
2277      }
2278    pr = &(ep->params[ep->params_size - 1]);
2279    pr->string = NULL;
2280    pr->cell_array = NULL;
2281    pr->cell_array_size = 0;
2282    pr->cell = 0;
2283    pr->cell = cell;
2284    return 1;
2285 }
2286
2287 /**
2288  * Pushes a string onto the function stack to use as a parameter for the
2289  * next function that is called in the given program.
2290  * @param   ep The given program.
2291  * @param   str The string to push onto the stack.
2292  * @return  @c 1 if successful.  @c 0 otherwise.
2293  * @ingroup Embryo_Parameter_Group
2294  */
2295 EAPI int
2296 embryo_parameter_string_push(Embryo_Program *ep, const char *str)
2297 {
2298    Embryo_Param *pr;
2299    char *str_dup;
2300
2301    if (!str)
2302      return embryo_parameter_string_push(ep, "");
2303    str_dup = strdup(str);
2304    if (!str_dup) return 0;
2305    ep->params_size++;
2306    if (ep->params_size > ep->params_alloc)
2307      {
2308         ep->params_alloc += 8;
2309         pr = realloc(ep->params, ep->params_alloc * sizeof(Embryo_Param));
2310         if (!pr)
2311           {
2312              free(str_dup);
2313              return 0;
2314           }
2315         ep->params = pr;
2316      }
2317    pr = &(ep->params[ep->params_size - 1]);
2318    pr->string = NULL;
2319    pr->cell_array = NULL;
2320    pr->cell_array_size = 0;
2321    pr->cell = 0;
2322    pr->string = str_dup;
2323    return 1;
2324 }
2325
2326 /**
2327  * Pushes an array of Embryo_Cells onto the function stack to be used as
2328  * parameters for the next function that is called in the given program.
2329  * @param   ep    The given program.
2330  * @param   cells The array of Embryo_Cells.
2331  * @param   num   The number of cells in @p cells.
2332  * @return  @c 1 if successful.  @c 0 otherwise.
2333  * @ingroup Embryo_Parameter_Group
2334  */
2335 EAPI int
2336 embryo_parameter_cell_array_push(Embryo_Program *ep, Embryo_Cell *cells, int num)
2337 {
2338    Embryo_Param *pr;
2339    Embryo_Cell *cell_array;
2340
2341    if ((!cells) || (num <= 0))
2342      return embryo_parameter_cell_push(ep, 0);
2343    cell_array = malloc(num * sizeof(Embryo_Cell));
2344    ep->params_size++;
2345    if (ep->params_size > ep->params_alloc)
2346      {
2347         ep->params_alloc += 8;
2348         pr = realloc(ep->params, ep->params_alloc * sizeof(Embryo_Param));
2349         if (!pr)
2350           {
2351              free(cell_array);
2352              return 0;
2353           }
2354         ep->params = pr;
2355      }
2356    pr = &(ep->params[ep->params_size - 1]);
2357    pr->string = NULL;
2358    pr->cell_array = NULL;
2359    pr->cell_array_size = 0;
2360    pr->cell = 0;
2361    pr->cell_array = cell_array;
2362    pr->cell_array_size = num;
2363    memcpy(pr->cell_array, cells, num * sizeof(Embryo_Cell));
2364    return 1;
2365 }