SYSTEM.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. #ifndef SYSTEM__h
  2. #define SYSTEM__h
  3. // 64 bit system detection
  4. #if (__SIZEOF_POINTER__ == 8) || defined (_LP64) || defined(__LP64__) || defined(_WIN64)
  5. #define o__64
  6. #endif
  7. // Declare memcpy in a way compatible with C compilers intrinsic
  8. // built in implementations.
  9. #if defined (o__64)
  10. #if defined(_WIN64)
  11. typedef unsigned long long size_t;
  12. #else
  13. typedef unsigned long size_t;
  14. #endif
  15. #else
  16. #if defined(__OpenBSD__)
  17. typedef unsigned long size_t;
  18. #else
  19. typedef unsigned int size_t;
  20. #endif
  21. #endif
  22. #define _SIZE_T_DECLARED // For FreeBSD
  23. #define _SIZE_T_DEFINED_ // For OpenBSD
  24. void *memcpy(void *dest, const void *source, size_t size);
  25. #if defined _MSC_VER
  26. #define alloca _alloca
  27. #endif
  28. void *alloca(size_t size);
  29. // Declare fixed size versions of basic intger types
  30. #if defined (o__64) && !defined(_WIN64)
  31. // LP64
  32. typedef long INT64;
  33. typedef unsigned long UINT64;
  34. #else
  35. // ILP32 or LLP64
  36. typedef long long INT64;
  37. typedef unsigned long long UINT64;
  38. #endif
  39. typedef int INT32;
  40. typedef unsigned int UINT32;
  41. typedef short int INT16;
  42. typedef unsigned short int UINT16;
  43. typedef signed char INT8;
  44. typedef unsigned char UINT8;
  45. // The compiler uses 'import' and 'export' which translate to 'extern' and
  46. // nothing respectively.
  47. #define import extern
  48. #define export
  49. // Known constants
  50. #define NIL ((void*)0)
  51. #define __MAXEXT 16
  52. #define POINTER__typ ((ADDRESS*)(1)) // not NIL and not a valid type
  53. // Oberon types
  54. typedef INT8 BOOLEAN;
  55. typedef INT8 SYSTEM_BYTE;
  56. typedef UINT8 CHAR;
  57. typedef float REAL;
  58. typedef double LONGREAL;
  59. typedef void* SYSTEM_PTR;
  60. // 'ADDRESS' is a synonym for an integer of pointer size
  61. #if defined (o__64)
  62. #define ADDRESS INT64
  63. #else
  64. #define ADDRESS INT32
  65. #endif
  66. // ----------------------------------------------------------------------
  67. // ----------------------------------------------------------------------
  68. // OS Memory allocation interfaces are in PlatformXXX.Mod
  69. extern ADDRESS Platform_OSAllocate (ADDRESS size);
  70. extern void Platform_OSFree (ADDRESS addr);
  71. // Assertions and Halts
  72. extern void Modules_Halt(INT32 x);
  73. extern void Modules_AssertFail(INT32 x);
  74. #define __HALT(x) Modules_Halt((INT32)(x))
  75. #define __ASSERT(cond, x) if (!(cond)) Modules_AssertFail((INT32)(x))
  76. // Index checking
  77. static inline INT64 __XF(UINT64 i, UINT64 ub) {if (i >= ub) {__HALT(-2);} return i;}
  78. #define __X(i, ub) (((i)<(ub))?i:(__HALT(-2),0))
  79. // Range checking, and checked SHORT and CHR functions
  80. static inline INT64 __RF(UINT64 i, UINT64 ub) {if (i >= ub) {__HALT(-8);} return i;}
  81. #define __R(i, ub) (((i)<(ub))?i:(__HALT(-8),0))
  82. #define __SHORT(x, ub) ((int)((UINT64)(x)+(ub)<(ub)+(ub)?(x):(__HALT(-8),0)))
  83. #define __SHORTF(x, ub) ((int)(__RF((x)+(ub),(ub)+(ub))-(ub)))
  84. #define __CHR(x) ((CHAR)__R(x, 256))
  85. #define __CHRF(x) ((CHAR)__RF(x, 256))
  86. // Signal handling in SYSTEM.c
  87. #ifndef _WIN32
  88. extern void SystemSetHandler(int s, ADDRESS h);
  89. #else
  90. extern void SystemSetInterruptHandler(ADDRESS h);
  91. extern void SystemSetQuitHandler (ADDRESS h);
  92. #endif
  93. // String comparison
  94. static inline int __str_cmp(CHAR *x, CHAR *y){
  95. INT64 i = 0;
  96. CHAR ch1, ch2;
  97. do {ch1 = x[i]; ch2 = y[i]; i++;
  98. if (!ch1) return -(int)ch2;
  99. } while (ch1==ch2);
  100. return (int)ch1 - (int)ch2;
  101. }
  102. #define __STRCMP(a,b) __str_cmp((CHAR*)(a), (CHAR*)(b))
  103. // Inline string, record and array copy
  104. #define __COPY(s, d, n) {char*_a=(void*)s,*_b=(void*)d; LONGINT _i=0,_t=n-1; \
  105. while(_i<_t&&((_b[_i]=_a[_i])!=0)){_i++;};_b[_i]=0;}
  106. #define __DUPARR(v, t) v=(void*)memcpy(v##__copy,v,sizeof(t))
  107. #define __DUP(x, l, t) x=(void*)memcpy(alloca(l*sizeof(t)),x,l*sizeof(t))
  108. #define __DEL(x)
  109. /* SYSTEM ops */
  110. #define __VAL(t, x) (*(t*)&(x))
  111. #define __GET(a, x, t) x=*(t*)(ADDRESS)(a)
  112. #define __PUT(a, x, t) *(t*)(ADDRESS)(a)=x
  113. #define __LSHL(x, n, s) ((INT##s)((UINT##s)(x)<<(n)))
  114. #define __LSHR(x, n, s) ((INT##s)((UINT##s)(x)>>(n)))
  115. #define __LSH(x, n, s) ((n)>=0? __LSHL(x, n, s): __LSHR(x, -(n), s))
  116. #define __ROTL(x, n, s) ((INT##s)((UINT##s)(x)<<(n)|(UINT##s)(x)>>(s-(n))))
  117. #define __ROTR(x, n, s) ((INT##s)((UINT##s)(x)>>(n)|(UINT##s)(x)<<(s-(n))))
  118. #define __ROT(x, n, s) ((n)>=0? __ROTL(x, n, s): __ROTR(x, -(n), s))
  119. #define __ASHL(x, n) ((INT32)(x)<<(n))
  120. #define __ASHR(x, n) ((INT32)(x)>>(n))
  121. #define __ASH(x, n) ((n)>=0?__ASHL(x,n):__ASHR(x,-(n)))
  122. static inline INT32 SYSTEM_ASH(INT32 x, INT32 n) {return __ASH(x,n);}
  123. #define __ASHF(x, n) SYSTEM_ASH((INT32)(x), (INT32)(n))
  124. #define __MOVE(s, d, n) memcpy((char*)(ADDRESS)(d),(char*)(ADDRESS)(s),n)
  125. extern INT64 SYSTEM_DIV(INT64 x, INT64 y);
  126. #define __DIVF(x, y) SYSTEM_DIV(x, y)
  127. #define __DIV(x, y) (((x)>0 && (y)>0) ? (x)/(y) : __DIVF(x, y))
  128. extern INT64 SYSTEM_MOD(INT64 x, INT64 y);
  129. #define __MODF(x, y) SYSTEM_MOD(x, y)
  130. #define __MOD(x, y) (((x)>0 && (y)>0) ? (x)%(y) : __MODF(x, y))
  131. extern INT64 SYSTEM_ENTIER (double x);
  132. #define __ENTIER(x) SYSTEM_ENTIER(x)
  133. #define __ABS(x) (((x)<0)?-(x):(x))
  134. static inline INT32 SYSTEM_ABS64(INT64 i) {return i >= 0 ? i : -i;}
  135. static inline INT64 SYSTEM_ABS32(INT32 i) {return i >= 0 ? i : -i;}
  136. #define __ABSF(x) ((sizeof(x) <= 4) ? SYSTEM_ABS32(x) : SYSTEM_ABS64(x))
  137. static inline double SYSTEM_ABSD(double i) {return i >= 0.0 ? i : -i;}
  138. #define __ABSFD(x) SYSTEM_ABSD(x)
  139. #define __CAP(ch) ((CHAR)((ch)&0x5f))
  140. #define __ODD(x) ((x)&1)
  141. #define __IN(x, s, size) (((unsigned int)(x))<size && ((((UINT##size)(s))>>(x))&1))
  142. // todo tested versions of SETOF and SETRNG: check that x, l and h fit size
  143. #define __SETOF(x, size) ((UINT##size)1<<(x))
  144. #define __SETRNG(l, h, size) ((~(UINT##size)0<<(l))&~(UINT##size)0>>(size-1-(h)))
  145. #define __MASK(x, m) ((x)&~(m))
  146. #define __BIT(x, n) (*(UINT64*)(x)>>(n)&1)
  147. // Runtime checks
  148. #define __RETCHK __retchk: __HALT(-3); return 0;
  149. #define __CASECHK __HALT(-4)
  150. #define __WITHCHK __HALT(-7)
  151. #define __IS(tag, typ, level) (*(tag-(__BASEOFF-level))==(ADDRESS)typ##__typ)
  152. #define __TYPEOF(p) (*(((ADDRESS**)(p))-1))
  153. #define __ISP(p, typ, level) __IS(__TYPEOF(p),typ,level)
  154. #define __GUARDP(p, typ, level) ((typ*)(__ISP(p,typ,level)?p:(__HALT(-5),p)))
  155. #define __GUARDR(r, typ, level) (*((typ*)(__IS(r##__typ,typ,level)?r:(__HALT(-5),r))))
  156. #define __GUARDA(p, typ, level) ((struct typ*)(__IS(__TYPEOF(p),typ,level)?p:(__HALT(-5),p)))
  157. #define __GUARDEQR(p, dyntyp, typ) if(dyntyp!=typ##__typ) __HALT(-6);*(p)
  158. #define __GUARDEQP(p, typ) if(__TYPEOF(p)!=typ##__typ)__HALT(-6);*((typ*)p)
  159. // Module entry/registration/exit
  160. extern void Heap_REGCMD();
  161. extern SYSTEM_PTR Heap_REGMOD();
  162. extern void Heap_REGTYP();
  163. extern void Heap_INCREF();
  164. #define __DEFMOD static void *m; if (m!=0) {return m;}
  165. #define __REGCMD(name, cmd) Heap_REGCMD(m, (CHAR*)name, cmd)
  166. #define __REGMOD(name, enum) if (m==0) {m = Heap_REGMOD((CHAR*)name,enum);}
  167. #define __ENDMOD return m
  168. #define __MODULE_IMPORT(name) Heap_INCREF(name##__init())
  169. // Main module initialisation, registration and finalisation
  170. extern void Modules_Init(INT32 argc, ADDRESS argv);
  171. extern void Heap_FINALL();
  172. #define __INIT(argc, argv) static void *m; Modules_Init(argc, (ADDRESS)&argv);
  173. #define __REGMAIN(name, enum) m = Heap_REGMOD((CHAR*)name,enum)
  174. #define __FINI Heap_FINALL(); return 0
  175. // Memory allocation
  176. extern SYSTEM_PTR Heap_NEWBLK (ADDRESS size);
  177. extern SYSTEM_PTR Heap_NEWREC (ADDRESS tag);
  178. extern SYSTEM_PTR SYSTEM_NEWARR(ADDRESS*, ADDRESS, int, int, int, ...);
  179. #define __SYSNEW(p, len) p = Heap_NEWBLK((ADDRESS)(len))
  180. #define __NEW(p, t) p = Heap_NEWREC((ADDRESS)t##__typ)
  181. #define __NEWARR SYSTEM_NEWARR
  182. /* Type handling */
  183. extern void SYSTEM_INHERIT(ADDRESS *t, ADDRESS *t0);
  184. extern void SYSTEM_ENUMP (void *adr, ADDRESS n, void (*P)());
  185. extern void SYSTEM_ENUMR (void *adr, ADDRESS *typ, ADDRESS size, ADDRESS n, void (*P)());
  186. #define __TDESC(t, m, n) \
  187. static struct t##__desc { \
  188. ADDRESS tproc[m]; /* Proc for each ptr field */ \
  189. ADDRESS tag; \
  190. ADDRESS next; /* Module table type list points here */ \
  191. ADDRESS level; \
  192. ADDRESS module; \
  193. char name[24]; \
  194. ADDRESS basep[__MAXEXT]; /* List of bases this extends */ \
  195. ADDRESS reserved; \
  196. ADDRESS blksz; /* xxx_typ points here */ \
  197. ADDRESS ptr[n+1]; /* Offsets of ptrs up to -ve sentinel */ \
  198. } t##__desc
  199. #define __BASEOFF (__MAXEXT+1) // blksz as index to base.
  200. #define __TPROC0OFF (__BASEOFF+24/sizeof(ADDRESS)+5) // blksz as index to tproc IFF m=1.
  201. #define __EOM 1
  202. #define __TDFLDS(name, size) {__EOM}, 1, 0, 0, 0, name, {0}, 0, size
  203. #define __ENUMP(adr, n, P) SYSTEM_ENUMP(adr, (ADDRESS)(n), P)
  204. #define __ENUMR(adr, typ, size, n, P) SYSTEM_ENUMR(adr, typ, (ADDRESS)(size), (ADDRESS)(n), P)
  205. #define __INITYP(t, t0, level) \
  206. t##__typ = (ADDRESS*)&t##__desc.blksz; \
  207. memcpy(t##__desc.basep, t0##__typ - __BASEOFF, level*sizeof(ADDRESS)); \
  208. t##__desc.basep[level] = (ADDRESS)t##__typ; \
  209. t##__desc.module = (ADDRESS)m; \
  210. if(t##__desc.blksz!=sizeof(struct t)) __HALT(-15); \
  211. t##__desc.blksz = (t##__desc.blksz+5*sizeof(ADDRESS)-1)/(4*sizeof(ADDRESS))*(4*sizeof(ADDRESS)); \
  212. Heap_REGTYP(m, (ADDRESS)&t##__desc.next); \
  213. SYSTEM_INHERIT(t##__typ, t0##__typ)
  214. // Oberon-2 type bound procedures support
  215. #define __INITBP(t, proc, num) *(t##__typ-(__TPROC0OFF+num))=(ADDRESS)proc
  216. #define __SEND(typ, num, funtyp, parlist) ((funtyp)((ADDRESS)*(typ-(__TPROC0OFF+num))))parlist
  217. #endif