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