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