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