move around - flatter.
[framework/uifw/embryo.git] / src / lib / embryo_private.h
1 #ifndef _EMBRYO_PRIVATE_H
2 #define _EMBRYO_PRIVATE_H
3
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <sys/types.h>
7 #include <unistd.h>
8 #include <limits.h>
9 #include <stdarg.h>
10 #include <string.h>
11
12 #ifdef HAVE_CONFIG_H
13 # include "config.h"
14 #endif
15
16 #ifdef HAVE_ALLOCA_H
17 # include <alloca.h>
18 #elif defined __GNUC__
19 # define alloca __builtin_alloca
20 #elif defined _AIX
21 # define alloca __alloca
22 #elif defined _MSC_VER
23 # include <malloc.h>
24 # define alloca _alloca
25 #else
26 # include <stddef.h>
27 # ifdef  __cplusplus
28 extern "C"
29 # endif
30 void *alloca (size_t);
31 #endif
32
33 #include "Embryo.h"
34
35 #ifdef __GNUC__
36 # if __GNUC__ >= 4
37 // BROKEN in gcc 4 on amd64
38 //#  pragma GCC visibility push(hidden)
39 # endif
40 #endif
41
42 #if HAVE___ATTRIBUTE__
43 #define __UNUSED__ __attribute__((unused))
44 #else
45 #define __UNUSED__
46 #endif
47
48 typedef enum _Embryo_Opcode Embryo_Opcode;
49
50 enum _Embryo_Opcode
51 {
52    EMBRYO_OP_NONE,
53      EMBRYO_OP_LOAD_PRI,
54      EMBRYO_OP_LOAD_ALT,
55      EMBRYO_OP_LOAD_S_PRI,
56      EMBRYO_OP_LOAD_S_ALT,
57      EMBRYO_OP_LREF_PRI,
58      EMBRYO_OP_LREF_ALT,
59      EMBRYO_OP_LREF_S_PRI,
60      EMBRYO_OP_LREF_S_ALT,
61      EMBRYO_OP_LOAD_I,
62      EMBRYO_OP_LODB_I,
63      EMBRYO_OP_CONST_PRI,
64      EMBRYO_OP_CONST_ALT,
65      EMBRYO_OP_ADDR_PRI,
66      EMBRYO_OP_ADDR_ALT,
67      EMBRYO_OP_STOR_PRI,
68      EMBRYO_OP_STOR_ALT,
69      EMBRYO_OP_STOR_S_PRI,
70      EMBRYO_OP_STOR_S_ALT,
71      EMBRYO_OP_SREF_PRI,
72      EMBRYO_OP_SREF_ALT,
73      EMBRYO_OP_SREF_S_PRI,
74      EMBRYO_OP_SREF_S_ALT,
75      EMBRYO_OP_STOR_I,
76      EMBRYO_OP_STRB_I,
77      EMBRYO_OP_LIDX,
78      EMBRYO_OP_LIDX_B,
79      EMBRYO_OP_IDXADDR,
80      EMBRYO_OP_IDXADDR_B,
81      EMBRYO_OP_ALIGN_PRI,
82      EMBRYO_OP_ALIGN_ALT,
83      EMBRYO_OP_LCTRL,
84      EMBRYO_OP_SCTRL,
85      EMBRYO_OP_MOVE_PRI,
86      EMBRYO_OP_MOVE_ALT,
87      EMBRYO_OP_XCHG,
88      EMBRYO_OP_PUSH_PRI,
89      EMBRYO_OP_PUSH_ALT,
90      EMBRYO_OP_PUSH_R,
91      EMBRYO_OP_PUSH_C,
92      EMBRYO_OP_PUSH,
93      EMBRYO_OP_PUSH_S,
94      EMBRYO_OP_POP_PRI,
95      EMBRYO_OP_POP_ALT,
96      EMBRYO_OP_STACK,
97      EMBRYO_OP_HEAP,
98      EMBRYO_OP_PROC,
99      EMBRYO_OP_RET,
100      EMBRYO_OP_RETN,
101      EMBRYO_OP_CALL,
102      EMBRYO_OP_CALL_PRI,
103      EMBRYO_OP_JUMP,
104      EMBRYO_OP_JREL,
105      EMBRYO_OP_JZER,
106      EMBRYO_OP_JNZ,
107      EMBRYO_OP_JEQ,
108      EMBRYO_OP_JNEQ,
109      EMBRYO_OP_JLESS,
110      EMBRYO_OP_JLEQ,
111      EMBRYO_OP_JGRTR,
112      EMBRYO_OP_JGEQ,
113      EMBRYO_OP_JSLESS,
114      EMBRYO_OP_JSLEQ,
115      EMBRYO_OP_JSGRTR,
116      EMBRYO_OP_JSGEQ,
117      EMBRYO_OP_SHL,
118      EMBRYO_OP_SHR,
119      EMBRYO_OP_SSHR,
120      EMBRYO_OP_SHL_C_PRI,
121      EMBRYO_OP_SHL_C_ALT,
122      EMBRYO_OP_SHR_C_PRI,
123      EMBRYO_OP_SHR_C_ALT,
124      EMBRYO_OP_SMUL,
125      EMBRYO_OP_SDIV,
126      EMBRYO_OP_SDIV_ALT,
127      EMBRYO_OP_UMUL,
128      EMBRYO_OP_UDIV,
129      EMBRYO_OP_UDIV_ALT,
130      EMBRYO_OP_ADD,
131      EMBRYO_OP_SUB,
132      EMBRYO_OP_SUB_ALT,
133      EMBRYO_OP_AND,
134      EMBRYO_OP_OR,
135      EMBRYO_OP_XOR,
136      EMBRYO_OP_NOT,
137      EMBRYO_OP_NEG,
138      EMBRYO_OP_INVERT,
139      EMBRYO_OP_ADD_C,
140      EMBRYO_OP_SMUL_C,
141      EMBRYO_OP_ZERO_PRI,
142      EMBRYO_OP_ZERO_ALT,
143      EMBRYO_OP_ZERO,
144      EMBRYO_OP_ZERO_S,
145      EMBRYO_OP_SIGN_PRI,
146      EMBRYO_OP_SIGN_ALT,
147      EMBRYO_OP_EQ,
148      EMBRYO_OP_NEQ,
149      EMBRYO_OP_LESS,
150      EMBRYO_OP_LEQ,
151      EMBRYO_OP_GRTR,
152      EMBRYO_OP_GEQ,
153      EMBRYO_OP_SLESS,
154      EMBRYO_OP_SLEQ,
155      EMBRYO_OP_SGRTR,
156      EMBRYO_OP_SGEQ,
157      EMBRYO_OP_EQ_C_PRI,
158      EMBRYO_OP_EQ_C_ALT,
159      EMBRYO_OP_INC_PRI,
160      EMBRYO_OP_INC_ALT,
161      EMBRYO_OP_INC,
162      EMBRYO_OP_INC_S,
163      EMBRYO_OP_INC_I,
164      EMBRYO_OP_DEC_PRI,
165      EMBRYO_OP_DEC_ALT,
166      EMBRYO_OP_DEC,
167      EMBRYO_OP_DEC_S,
168      EMBRYO_OP_DEC_I,
169      EMBRYO_OP_MOVS,
170      EMBRYO_OP_CMPS,
171      EMBRYO_OP_FILL,
172      EMBRYO_OP_HALT,
173      EMBRYO_OP_BOUNDS,
174      EMBRYO_OP_SYSREQ_PRI,
175      EMBRYO_OP_SYSREQ_C,
176      EMBRYO_OP_FILE,
177      EMBRYO_OP_LINE,
178      EMBRYO_OP_SYMBOL,
179      EMBRYO_OP_SRANGE,
180      EMBRYO_OP_JUMP_PRI,
181      EMBRYO_OP_SWITCH,
182      EMBRYO_OP_CASETBL,
183      EMBRYO_OP_SWAP_PRI,
184      EMBRYO_OP_SWAP_ALT,
185      EMBRYO_OP_PUSHADDR,
186      EMBRYO_OP_NOP,
187      EMBRYO_OP_SYSREQ_D,
188      EMBRYO_OP_SYMTAG,
189      /* ----- */
190      EMBRYO_OP_NUM_OPCODES
191 };
192
193 #define NUMENTRIES(hdr, field, nextfield) \
194 (int)(((hdr)->nextfield - (hdr)->field) / (hdr)->defsize)
195 #define GETENTRY(hdr, table, index) \
196 (Embryo_Func_Stub *)((unsigned char*)(hdr) + \
197 (int)(hdr)->table + index * (hdr)->defsize)
198 #ifdef WORDS_BIGENDIAN
199 static int __inline __entryswap32(int v)
200 {int vv; vv = v; embryo_swap_32((unsigned int *)&vv); return vv;}
201 # define GETENTRYNAME(hdr, entry) \
202 (((hdr)->defsize == 2 * sizeof(unsigned int)) \
203 ? (char *)((unsigned char*)(hdr) + \
204 __entryswap32(*((unsigned int *)(entry) + 1))) \
205 : (entry)->name)
206 #else
207 # define GETENTRYNAME(hdr, entry) \
208 (((hdr)->defsize == 2 * sizeof(unsigned int)) \
209 ? (char *)((unsigned char*)(hdr) + *((unsigned int *)(entry) + 1)) \
210 : (entry)->name)
211 #endif
212
213 #define CUR_FILE_VERSION    7      /* current file version; also the current Embryo_Program version */
214 #define MIN_FILE_VERSION    7      /* lowest supported file format version for the current Embryo_Program version */
215 #define MIN_AMX_VERSION     7      /* minimum Embryo_Program version needed to support the current file format */
216 #define sEXPMAX             19     /* maximum name length for file version <= 6 */
217 #define sNAMEMAX            31     /* maximum name length of symbol name */
218 #define EMBRYO_MAGIC        0xf1e0 /* magic byte pattern */
219 #define EMBRYO_FLAG_COMPACT 0x04   /* compact encoding */
220 #define EMBRYO_FLAG_RELOC   0x8000 /* jump/call addresses relocated */
221 #define GETPARAM(v)         (v = *(Embryo_Cell *)cip++)
222 #define PUSH(v)             (stk -= sizeof(Embryo_Cell), *(Embryo_Cell *)(data + (int)stk) = v)
223 #define POP(v)              (v = *(Embryo_Cell *)(data + (int)stk), stk += sizeof(Embryo_Cell))
224 #define ABORT(ep,v)         {(ep)->stk = reset_stk; (ep)->hea = reset_hea; (ep)->run_count--; ep->error = v; (ep)->max_run_cycles = max_run_cycles; return EMBRYO_PROGRAM_FAIL;}
225 #define OK(ep,v)            {(ep)->stk = reset_stk; (ep)->hea = reset_hea; (ep)->run_count--; ep->error = v; (ep)->max_run_cycles = max_run_cycles; return EMBRYO_PROGRAM_OK;}
226 #define TOOLONG(ep)         {(ep)->pri = pri; (ep)->cip = (Embryo_Cell)((unsigned char *)cip - code); (ep)->alt = alt; (ep)->frm = frm; (ep)->stk = stk; (ep)->hea = hea; (ep)->reset_stk = reset_stk; (ep)->reset_hea = reset_hea; (ep)->run_count--; (ep)->max_run_cycles = max_run_cycles; return EMBRYO_PROGRAM_TOOLONG;}
227 #define STKMARGIN           ((Embryo_Cell)(16 * sizeof(Embryo_Cell)))
228 #define CHKMARGIN()         if ((hea + STKMARGIN) > stk) {ep->error = EMBRYO_ERROR_STACKERR; return 0;}
229 #define CHKSTACK()          if (stk > ep->stp) {ep->run_count--; ep->error = EMBRYO_ERROR_STACKLOW; return 0;}
230 #define CHKHEAP()           if (hea < ep->hlw) {ep->run_count--; ep->error = EMBRYO_ERROR_HEAPLOW; return 0;}
231 #define CHKMEM(x)           if ((((x) >= hea) && ((x) < stk)) || ((Embryo_UCell)(x) >= (Embryo_UCell)ep->stp)) ABORT(ep, EMBRYO_ERROR_MEMACCESS);
232
233 typedef struct _Embryo_Param        Embryo_Param;
234 typedef struct _Embryo_Header       Embryo_Header;
235 typedef struct _Embryo_Func_Stub    Embryo_Func_Stub;
236
237 typedef Embryo_Cell (*Embryo_Native)(Embryo_Program *ep, Embryo_Cell *params);
238
239 struct _Embryo_Param
240 {
241    char        *string;
242    Embryo_Cell *cell_array;
243    int          cell_array_size;
244    Embryo_Cell  cell;
245 };
246
247 struct _Embryo_Program
248 {
249    unsigned char *base; /* points to the Embryo_Program header ("ephdr") plus the code, optionally also the data */
250    int pushes; /* number of pushes - pops */
251    /* for external functions a few registers must be accessible from the outside */
252    Embryo_Cell cip; /* instruction pointer: relative to base + ephdr->cod */
253    Embryo_Cell frm; /* stack frame base: relative to base + ephdr->dat */
254    Embryo_Cell hea; /* top of the heap: relative to base + ephdr->dat */
255    Embryo_Cell hlw; /* bottom of the heap: relative to base + ephdr->dat */
256    Embryo_Cell stk; /* stack pointer: relative to base + ephdr->dat */
257    Embryo_Cell stp; /* top of the stack: relative to base + ephdr->dat */
258    int flags; /* current status  */
259    /* native functions can raise an error */
260    int error;
261    /* the sleep opcode needs to store the full Embryo_Program status */
262    Embryo_Cell pri;
263    Embryo_Cell alt;
264    Embryo_Cell reset_stk;
265    Embryo_Cell reset_hea;
266    Embryo_Cell *syscall_d; /* relocated value/address for the SYSCALL.D opcode */
267
268    /* extended stuff */
269    Embryo_Native *native_calls;
270    int            native_calls_size;
271    int            native_calls_alloc;
272
273    unsigned char *code;
274    unsigned char  dont_free_code : 1;
275    Embryo_Cell    retval;
276
277    Embryo_Param  *params;
278    int            params_size;
279    int            params_alloc;
280
281    int            run_count;
282
283    int            max_run_cycles;
284
285    void          *data;
286 };
287
288 struct _Embryo_Func_Stub
289 {
290    int  address;
291    char name[sEXPMAX+1];
292 } __attribute__((packed));
293
294 struct _Embryo_Header
295 {
296    unsigned int size; /* size of the "file" */
297    unsigned short magic; /* signature */
298    char file_version; /* file format version */
299    char ep_version; /* required version of the Embryo_Program */
300    short flags;
301    short defsize; /* size of a definition record */
302    int cod; /* initial value of COD - code block */
303    int dat; /* initial value of DAT - data block */
304    int hea; /* initial value of HEA - start of the heap */
305    int stp; /* initial value of STP - stack top */
306    int cip; /* initial value of CIP - the instruction pointer */
307    int publics; /* offset to the "public functions" table */
308    int natives; /* offset to the "native functions" table */
309    int libraries; /* offset to the table of libraries */
310    int pubvars; /* the "public variables" table */
311    int tags; /* the "public tagnames" table */
312    int nametable; /* name table, file version 7 only */
313 } __attribute__((packed));
314
315 void _embryo_args_init(Embryo_Program *ep);
316 void _embryo_fp_init(Embryo_Program *ep);
317 void _embryo_rand_init(Embryo_Program *ep);
318 void _embryo_str_init(Embryo_Program *ep);
319 void _embryo_time_init(Embryo_Program *ep);
320
321 #endif