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