From 4de97bf7ae01a78248a15ff69031824c5b089e31 Mon Sep 17 00:00:00 2001 From: DeaDDooMER Date: Sun, 9 Jun 2019 21:20:34 +0300 Subject: [PATCH] first cpc release --- C/SYSTEM.c | 413 +++++ C/SYSTEM.h | 356 ++++ C/_windows.h | 18 + CHANGELOG | 5 + LICENSE | 674 ++++++++ README | 33 + crux/cpc-32/.32bit | 0 crux/cpc-32/Pkgfile | 30 + make-bootstrap.sh | 190 +++ make-stage0.sh | 113 ++ make-stage0c.sh | 70 + make-stage1.sh | 123 ++ make-stage2.sh | 123 ++ man/cpc.1 | 76 + man/cpl.1 | 54 + src/cpfront/linux/C99/Mod/dirent.cp | 64 + src/cpfront/linux/C99/Mod/dlfcn.cp | 49 + src/cpfront/linux/C99/Mod/errno.cp | 123 ++ src/cpfront/linux/C99/Mod/fcntl.cp | 119 ++ src/cpfront/linux/C99/Mod/iconv.cp | 48 + src/cpfront/linux/C99/Mod/libgen.cp | 41 + src/cpfront/linux/C99/Mod/locale.cp | 75 + src/cpfront/linux/C99/Mod/macro.cp | 15 + src/cpfront/linux/C99/Mod/setjmp.cp | 49 + src/cpfront/linux/C99/Mod/signal.cp | 297 ++++ src/cpfront/linux/C99/Mod/stdio.cp | 91 ++ src/cpfront/linux/C99/Mod/stdlib.cp | 66 + src/cpfront/linux/C99/Mod/sys_mman.cp | 86 + src/cpfront/linux/C99/Mod/sys_stat.cp | 119 ++ src/cpfront/linux/C99/Mod/sys_types.cp | 75 + src/cpfront/linux/C99/Mod/time.cp | 117 ++ src/cpfront/linux/C99/Mod/types.cp | 38 + src/cpfront/linux/C99/Mod/unistd.cp | 430 +++++ src/cpfront/linux/C99/Mod/wctype.cp | 58 + src/cpfront/posix/System/Mod/Kernel.cp | 1698 +++++++++++++++++++ src/cpfront/posix/System/Mod/Math.cp | 231 +++ src/cpfront/posix/System/Mod/SMath.cp | 231 +++ src/generic/CPfront/Mod/CPC.odc | Bin 0 -> 79409 bytes src/generic/CPfront/Mod/CPG.odc | Bin 0 -> 9887 bytes src/generic/CPfront/Mod/CPV.odc | Bin 0 -> 51097 bytes src/generic/Dev/Mod/CPB.odc | Bin 0 -> 85461 bytes src/generic/Dev/Mod/CPC486.odc | Bin 0 -> 87900 bytes src/generic/Dev/Mod/CPE.odc | Bin 0 -> 39817 bytes src/generic/Dev/Mod/CPH.odc | Bin 0 -> 12814 bytes src/generic/Dev/Mod/CPL486.odc | Bin 0 -> 36869 bytes src/generic/Dev/Mod/CPM.cp | 1194 ++++++++++++++ src/generic/Dev/Mod/CPP.odc | Bin 0 -> 63647 bytes src/generic/Dev/Mod/CPS.odc | Bin 0 -> 15376 bytes src/generic/Dev/Mod/CPT.odc | Bin 0 -> 76250 bytes src/generic/Dev/Mod/CPV486.odc | Bin 0 -> 68156 bytes src/generic/Dev2/Mod/LnkBase.odc | Bin 0 -> 17733 bytes src/generic/Dev2/Mod/LnkChmod.odc | Bin 0 -> 1949 bytes src/generic/Dev2/Mod/LnkLoad.odc | Bin 0 -> 15077 bytes src/generic/Dev2/Mod/LnkWriteElf.odc | Bin 0 -> 19719 bytes src/generic/Dev2/Mod/LnkWriteElfStatic.odc | Bin 0 -> 7370 bytes src/generic/Dev2/Mod/LnkWritePe.odc | Bin 0 -> 14363 bytes src/generic/Dsw/Mod/Compiler486Main.cp | 320 ++++ src/generic/Dsw/Mod/CompilerCPfrontMain.cp | 338 ++++ src/generic/Dsw/Mod/Debug.odc | Bin 0 -> 18325 bytes src/generic/Dsw/Mod/Documents.cp | 233 +++ src/generic/Dsw/Mod/EchoMain.cp | 44 + src/generic/Dsw/Mod/Linker486Main.cp | 259 +++ src/generic/Dsw/Mod/ListMain.cp | 48 + src/generic/Dsw/Mod/Log.odc | Bin 0 -> 6480 bytes src/generic/Dsw/Mod/LoopMain.cp | 45 + src/generic/System/Mod/Console.odc | Bin 0 -> 1938 bytes src/generic/System/Mod/Dates.odc | Bin 0 -> 7801 bytes src/generic/System/Mod/Files.odc | Bin 0 -> 6812 bytes src/generic/System/Mod/Int.odc | Bin 0 -> 2497 bytes src/generic/System/Mod/Integers.odc | Bin 0 -> 29326 bytes src/generic/System/Mod/Log.odc | Bin 0 -> 6537 bytes src/generic/System/Mod/Services.odc | Bin 0 -> 10737 bytes src/generic/System/Mod/Strings.odc | Bin 0 -> 27034 bytes src/i486/generic/System/Mod/Long.odc | Bin 0 -> 6568 bytes src/i486/generic/System/Mod/Math.odc | Bin 0 -> 21761 bytes src/i486/generic/System/Mod/SMath.odc | Bin 0 -> 16557 bytes src/i486/linux/C99/Mod/dirent.cp | 66 + src/i486/linux/C99/Mod/dlfcn.cp | 49 + src/i486/linux/C99/Mod/errno.cp | 123 ++ src/i486/linux/C99/Mod/fcntl.cp | 119 ++ src/i486/linux/C99/Mod/iconv.cp | 48 + src/i486/linux/C99/Mod/libgen.cp | 41 + src/i486/linux/C99/Mod/locale.cp | 75 + src/i486/linux/C99/Mod/macro.cp | 15 + src/i486/linux/C99/Mod/setjmp.cp | 49 + src/i486/linux/C99/Mod/signal.cp | 316 ++++ src/i486/linux/C99/Mod/stdio.cp | 91 ++ src/i486/linux/C99/Mod/stdlib.cp | 66 + src/i486/linux/C99/Mod/sys_mman.cp | 86 + src/i486/linux/C99/Mod/sys_stat.cp | 125 ++ src/i486/linux/C99/Mod/sys_types.cp | 75 + src/i486/linux/C99/Mod/time.cp | 118 ++ src/i486/linux/C99/Mod/types.cp | 40 + src/i486/linux/C99/Mod/unistd.cp | 430 +++++ src/i486/linux/C99/Mod/wctype.cp | 58 + src/i486/linux/System/Mod/Kernel.cp | 1708 ++++++++++++++++++++ src/i486/posix/System/Mod/Kernel.cp | 1696 +++++++++++++++++++ src/posix/Host/Mod/Console.cp | 41 + src/posix/Host/Mod/Dates.cp | 142 ++ src/posix/Host/Mod/Files.cp | 757 +++++++++ src/posix/Host/Mod/Lang.cp | 167 ++ 101 files changed, 15380 insertions(+) create mode 100644 C/SYSTEM.c create mode 100644 C/SYSTEM.h create mode 100644 C/_windows.h create mode 100644 CHANGELOG create mode 100644 LICENSE create mode 100644 README create mode 100644 crux/cpc-32/.32bit create mode 100644 crux/cpc-32/Pkgfile create mode 100755 make-bootstrap.sh create mode 100755 make-stage0.sh create mode 100755 make-stage0c.sh create mode 100755 make-stage1.sh create mode 100755 make-stage2.sh create mode 100644 man/cpc.1 create mode 100644 man/cpl.1 create mode 100644 src/cpfront/linux/C99/Mod/dirent.cp create mode 100644 src/cpfront/linux/C99/Mod/dlfcn.cp create mode 100644 src/cpfront/linux/C99/Mod/errno.cp create mode 100644 src/cpfront/linux/C99/Mod/fcntl.cp create mode 100644 src/cpfront/linux/C99/Mod/iconv.cp create mode 100644 src/cpfront/linux/C99/Mod/libgen.cp create mode 100644 src/cpfront/linux/C99/Mod/locale.cp create mode 100644 src/cpfront/linux/C99/Mod/macro.cp create mode 100644 src/cpfront/linux/C99/Mod/setjmp.cp create mode 100644 src/cpfront/linux/C99/Mod/signal.cp create mode 100644 src/cpfront/linux/C99/Mod/stdio.cp create mode 100644 src/cpfront/linux/C99/Mod/stdlib.cp create mode 100644 src/cpfront/linux/C99/Mod/sys_mman.cp create mode 100644 src/cpfront/linux/C99/Mod/sys_stat.cp create mode 100644 src/cpfront/linux/C99/Mod/sys_types.cp create mode 100644 src/cpfront/linux/C99/Mod/time.cp create mode 100644 src/cpfront/linux/C99/Mod/types.cp create mode 100644 src/cpfront/linux/C99/Mod/unistd.cp create mode 100644 src/cpfront/linux/C99/Mod/wctype.cp create mode 100644 src/cpfront/posix/System/Mod/Kernel.cp create mode 100644 src/cpfront/posix/System/Mod/Math.cp create mode 100644 src/cpfront/posix/System/Mod/SMath.cp create mode 100644 src/generic/CPfront/Mod/CPC.odc create mode 100644 src/generic/CPfront/Mod/CPG.odc create mode 100644 src/generic/CPfront/Mod/CPV.odc create mode 100644 src/generic/Dev/Mod/CPB.odc create mode 100644 src/generic/Dev/Mod/CPC486.odc create mode 100644 src/generic/Dev/Mod/CPE.odc create mode 100644 src/generic/Dev/Mod/CPH.odc create mode 100644 src/generic/Dev/Mod/CPL486.odc create mode 100644 src/generic/Dev/Mod/CPM.cp create mode 100644 src/generic/Dev/Mod/CPP.odc create mode 100644 src/generic/Dev/Mod/CPS.odc create mode 100644 src/generic/Dev/Mod/CPT.odc create mode 100644 src/generic/Dev/Mod/CPV486.odc create mode 100644 src/generic/Dev2/Mod/LnkBase.odc create mode 100644 src/generic/Dev2/Mod/LnkChmod.odc create mode 100644 src/generic/Dev2/Mod/LnkLoad.odc create mode 100644 src/generic/Dev2/Mod/LnkWriteElf.odc create mode 100644 src/generic/Dev2/Mod/LnkWriteElfStatic.odc create mode 100644 src/generic/Dev2/Mod/LnkWritePe.odc create mode 100644 src/generic/Dsw/Mod/Compiler486Main.cp create mode 100644 src/generic/Dsw/Mod/CompilerCPfrontMain.cp create mode 100644 src/generic/Dsw/Mod/Debug.odc create mode 100644 src/generic/Dsw/Mod/Documents.cp create mode 100644 src/generic/Dsw/Mod/EchoMain.cp create mode 100644 src/generic/Dsw/Mod/Linker486Main.cp create mode 100644 src/generic/Dsw/Mod/ListMain.cp create mode 100644 src/generic/Dsw/Mod/Log.odc create mode 100644 src/generic/Dsw/Mod/LoopMain.cp create mode 100644 src/generic/System/Mod/Console.odc create mode 100644 src/generic/System/Mod/Dates.odc create mode 100644 src/generic/System/Mod/Files.odc create mode 100644 src/generic/System/Mod/Int.odc create mode 100644 src/generic/System/Mod/Integers.odc create mode 100644 src/generic/System/Mod/Log.odc create mode 100644 src/generic/System/Mod/Services.odc create mode 100644 src/generic/System/Mod/Strings.odc create mode 100644 src/i486/generic/System/Mod/Long.odc create mode 100644 src/i486/generic/System/Mod/Math.odc create mode 100644 src/i486/generic/System/Mod/SMath.odc create mode 100644 src/i486/linux/C99/Mod/dirent.cp create mode 100644 src/i486/linux/C99/Mod/dlfcn.cp create mode 100644 src/i486/linux/C99/Mod/errno.cp create mode 100644 src/i486/linux/C99/Mod/fcntl.cp create mode 100644 src/i486/linux/C99/Mod/iconv.cp create mode 100644 src/i486/linux/C99/Mod/libgen.cp create mode 100644 src/i486/linux/C99/Mod/locale.cp create mode 100644 src/i486/linux/C99/Mod/macro.cp create mode 100644 src/i486/linux/C99/Mod/setjmp.cp create mode 100644 src/i486/linux/C99/Mod/signal.cp create mode 100644 src/i486/linux/C99/Mod/stdio.cp create mode 100644 src/i486/linux/C99/Mod/stdlib.cp create mode 100644 src/i486/linux/C99/Mod/sys_mman.cp create mode 100644 src/i486/linux/C99/Mod/sys_stat.cp create mode 100644 src/i486/linux/C99/Mod/sys_types.cp create mode 100644 src/i486/linux/C99/Mod/time.cp create mode 100644 src/i486/linux/C99/Mod/types.cp create mode 100644 src/i486/linux/C99/Mod/unistd.cp create mode 100644 src/i486/linux/C99/Mod/wctype.cp create mode 100644 src/i486/linux/System/Mod/Kernel.cp create mode 100644 src/i486/posix/System/Mod/Kernel.cp create mode 100644 src/posix/Host/Mod/Console.cp create mode 100644 src/posix/Host/Mod/Dates.cp create mode 100644 src/posix/Host/Mod/Files.cp create mode 100644 src/posix/Host/Mod/Lang.cp diff --git a/C/SYSTEM.c b/C/SYSTEM.c new file mode 100644 index 0000000..81f3ff6 --- /dev/null +++ b/C/SYSTEM.c @@ -0,0 +1,413 @@ +#include "SYSTEM.h" + +SYSTEM_MODDESC *SYSTEM_modlist = NIL; +SYSTEM_DLINK *SYSTEM_dlink = NIL; + +LONGINT SYSTEM_INF = 0x7FF0000000000000L; +INTEGER SYSTEM_INFS = 0x7F800000; + +CHAR SYSTEM_strBuf[32][256]; +INTEGER SYSTEM_actual; + +INTEGER SYSTEM_argCount; +void *SYSTEM_argVector; + +void SYSTEM_REGMOD(SYSTEM_MODDESC *mod) +{ + int i; + mod->next = SYSTEM_modlist; + SYSTEM_modlist = mod; + for (i = 0; i < mod->nofimps; i++) mod->imports[i]->refcnt++; +} + +typedef struct { + INTEGER gc[3], len[1]; +} Array; + +void *SYSTEM_NEWARR(INTEGER type, INTEGER n) +{ + int ptr = Kernel_NewArr(type, n, 1); + ((Array*)ptr)->len[0] = n; + return (void*)ptr; +} + +void *SYSTEM_NEWARR1(INTEGER type, INTEGER n0, INTEGER n) +{ + int ptr = Kernel_NewArr(type, n * n0, 1); + ((Array*)ptr)->len[0] = n0; + return (void*)ptr; +} + +void *SYSTEM_NEWARR2(INTEGER type, INTEGER n1, INTEGER n0, INTEGER n) +{ + int ptr = Kernel_NewArr(type, n * n0 * n1, 2); + ((Array*)ptr)->len[0] = n1; + ((Array*)ptr)->len[1] = n0; + return (void*)ptr; +} + +void *SYSTEM_NEWARR3(INTEGER type, INTEGER n2, INTEGER n1, INTEGER n0, INTEGER n) +{ + int ptr = Kernel_NewArr(type, n * n0 * n1 * n2, 3); + ((Array*)ptr)->len[0] = n2; + ((Array*)ptr)->len[1] = n1; + ((Array*)ptr)->len[2] = n0; + return (void*)ptr; +} + +void *SYSTEM_NEWARR4(INTEGER type, INTEGER n3, INTEGER n2, INTEGER n1, INTEGER n0, INTEGER n) +{ + int ptr = Kernel_NewArr(type, n * n0 * n1 * n2 * n3, 4); + ((Array*)ptr)->len[0] = n3; + ((Array*)ptr)->len[1] = n2; + ((Array*)ptr)->len[2] = n1; + ((Array*)ptr)->len[3] = n0; + return (void*)ptr; +} + +INTEGER SYSTEM_XCHK(INTEGER i, INTEGER ub) +{ + if ((unsigned)(i)>=(unsigned)(ub)) __HALT(-7); + return i; +} + + +CHAR* SYSTEM_LSTR(char *x) +{ + CHAR *str = SYSTEM_strBuf[SYSTEM_actual]; + int i = 0; + SYSTEM_actual = (SYSTEM_actual + 1) & 0x1F; + do { + if (i == 256) __HALT(-8); + str[i] = x[i]; + } while (x[i++] != 0); + return str; +} + +INTEGER SYSTEM_ASH(INTEGER x, INTEGER n) +{ + if (n >= 0) return x << n; + else return x >> (-n); +} + +LONGINT SYSTEM_ASHL(LONGINT x, INTEGER n) +{ + if (n >= 0) return x << n; + else return x >> (-n); +} + +INTEGER SYSTEM_ABS(INTEGER x) +{ + if (x<0) x=-x; + return x; +} + +LONGINT SYSTEM_ABSL(LONGINT x) +{ + if (x<0) x=-x; + return x; +} + +SHORTREAL SYSTEM_ABSF(SHORTREAL x) +{ + if (x<0) x=-x; + return x; +} + +REAL SYSTEM_ABSD(REAL x) +{ + if (x<0) x=-x; + return x; +} + +INTEGER SYSTEM_ENTIER(REAL x) +{ + INTEGER i; + i = (INTEGER)x; + if (i > x) i--; + return i; +} + +LONGINT SYSTEM_ENTIERL(REAL x) +{ + LONGINT i; + i = (LONGINT)x; + if (i > x) i--; + return i; +} + +INTEGER SYSTEM_DIV(INTEGER x, INTEGER y) +{ + if (y > 0) { + if (x < 0) return ~(~x / y); + else return x / y; + } else if (y < 0) { + if (x > 0) return ~((x - 1) / -y); + else return -x / -y; + } else { + __HALT(-5); + } +} + +LONGINT SYSTEM_DIVL(LONGINT x, LONGINT y) +{ + if (y > 0) { + if (x < 0) return ~(~x / y); + else return x / y; + } else if (y < 0) { + if (x > 0) return ~((x - 1) / -y); + else return -x / -y; + } else { + __HALT(-5); + } +} + +INTEGER SYSTEM_MOD(INTEGER x, INTEGER y) +{ + if (y > 0) { + if (x < 0) return y + ~(~x % y); + else return x % y; + } else if (y < 0) { + if (x > 0) return y + 1 + ((x - 1) % -y); + else return -(-x % -y); + } else { + __HALT(-5); + } +} + +LONGINT SYSTEM_MODL(LONGINT x, LONGINT y) +{ + if (y > 0) { + if (x < 0) return y + ~(~x % y); + else return x % y; + } else if (y < 0) { + if (x > 0) return y + 1 + ((x - 1) % -y); + else return -(-x % -y); + } else { + __HALT(-5); + } +} + +INTEGER SYSTEM_MIN(INTEGER x, INTEGER y) +{ + if (x > y) x = y; + return x; +} + +LONGINT SYSTEM_MINL(LONGINT x, LONGINT y) +{ + if (x > y) x = y; + return x; +} + +SHORTREAL SYSTEM_MINF(SHORTREAL x, SHORTREAL y) +{ + if (x > y) x = y; + return x; +} + +REAL SYSTEM_MIND(REAL x, REAL y) +{ + if (x > y) x = y; + return x; +} + +INTEGER SYSTEM_MAX(INTEGER x, INTEGER y) +{ + if (x < y) x = y; + return x; +} + +LONGINT SYSTEM_MAXL(LONGINT x, LONGINT y) +{ + if (x < y) x = y; + return x; +} + +SHORTREAL SYSTEM_MAXF(SHORTREAL x, SHORTREAL y) +{ + if (x < y) x = y; + return x; +} + +REAL SYSTEM_MAXD(REAL x, REAL y) +{ + if (x < y) x = y; + return x; +} + + +SHORTREAL SYSTEM_INT2SR(INTEGER x) +{ + return *(SHORTREAL*)&x; +} + +REAL SYSTEM_LONG2R(LONGINT x) +{ + return *(REAL*)&x; +} + +INTEGER SYSTEM_SR2INT(SHORTREAL x) +{ + return *(INTEGER*)&x; +} + +LONGINT SYSTEM_R2LONG(REAL x) +{ + return *(LONGINT*)&x; +} + + + + +INTEGER SYSTEM_STRLEN(CHAR x[]) /* LEN(lx$) */ +{ + int i = 0; + while (x[i] != 0) i++; + return i; +} + +INTEGER SYSTEM_STRLENS(SHORTCHAR x[]) /* LEN(sx$) */ +{ + int i = 0; + while (x[i] != 0) i++; + return i; +} + +INTEGER SYSTEM_STRCMPSS(SHORTCHAR x[], SHORTCHAR y[]) /* sx = sy */ +{ + int i = 0; + while (x[i] == y[i] && y[i] != 0) i++; + return x[i] - y[i]; +} + +INTEGER SYSTEM_STRCMPTS(CHAR x[], SHORTCHAR y[]) /* SHORT(lx) = sy */ +{ + int i = 0; + while ((x[i] & 0xff) == y[i] && y[i] != 0) i++; + return (x[i] & 0xff) - y[i]; +} + +INTEGER SYSTEM_STRCMPTT(CHAR x[], CHAR y[]) /* SHORT(lx) = SHORT(ly) */ +{ + int i = 0; + while ((x[i] & 0xff) == (y[i] & 0xff) && (y[i] & 0xff) != 0) i++; + return (x[i] & 0xff) - (y[i] & 0xff); +} + +INTEGER SYSTEM_STRCMPLL(CHAR x[], CHAR y[]) /* lx = ly */ +{ + int i = 0; + while (x[i] == y[i] && y[i] != 0) i++; + return x[i] - y[i]; +} + +INTEGER SYSTEM_STRCMPSL(SHORTCHAR x[], CHAR y[]) /* LONG(sx) = ly */ +{ + int i = 0; + while (x[i] == y[i] && y[i] != 0) i++; + return x[i] - y[i]; +} + +INTEGER SYSTEM_STRCMPTL(CHAR x[], CHAR y[]) /* LONG(SHORT(lx)) = ly */ +{ + int i = 0; + while ((x[i] & 0xff) == y[i] && y[i] != 0) i++; + return (x[i] & 0xff) - y[i]; +} + +void SYSTEM_STRCOPYSS(SHORTCHAR x[], SHORTCHAR y[], INTEGER n) /* sy := sx */ +{ + int i = 0; + do { + if (n-- == 0) __HALT(-8); + y[i] = x[i]; + } while (x[i++] != 0); +} + +void SYSTEM_STRCOPYTS(CHAR x[], SHORTCHAR y[], INTEGER n) /* sy := SHORT(lx) */ +{ + int i = 0; + do { + if (n-- == 0) __HALT(-8); + y[i] = (SHORTCHAR)x[i]; + } while ((x[i++] & 0xff) != 0); +} + +void SYSTEM_STRCOPYLL(CHAR x[], CHAR y[], INTEGER n) /* ly := lx */ +{ + int i = 0; + do { + if (n-- == 0) __HALT(-8); + y[i] = x[i]; + } while (x[i++] != 0); +} + +void SYSTEM_STRCOPYSL(SHORTCHAR x[], CHAR y[], INTEGER n) /* ly := LONG(sx) */ +{ + int i = 0; + do { + if (n-- == 0) __HALT(-8); + y[i] = x[i]; + } while (x[i++] != 0); +} + +void SYSTEM_STRCOPYTL(CHAR x[], CHAR y[], INTEGER n) /* ly := LONG(SHORT(lx)) */ +{ + int i = 0; + do { + if (n-- == 0) __HALT(-8); + y[i] = (x[i] & 0xff); + } while ((x[i++] & 0xff) != 0); +} + +void SYSTEM_STRAPNDSS(SHORTCHAR x[], SHORTCHAR y[], INTEGER n) /* sy := sy + sx */ +{ + int i = 0, j = 0; + while (y[j] != 0) j++; + do { + if (n-- == 0) __HALT(-8); + y[j++] = x[i]; + } while (x[i++] != 0); +} + +void SYSTEM_STRAPNDTS(CHAR x[], SHORTCHAR y[], INTEGER n) /* sy := sy + SHORT(lx) */ +{ + int i = 0, j = 0; + while (y[j] != 0) j++; + do { + if (n-- == 0) __HALT(-8); + y[j++] = (SHORTCHAR)x[i]; + } while ((x[i++] & 0xff) != 0); +} + +void SYSTEM_STRAPNDLL(CHAR x[], CHAR y[], INTEGER n) /* ly := ly + lx */ +{ + int i = 0, j = 0; + while (y[j] != 0) j++; + do { + if (n-- == 0) __HALT(-8); + y[j++] = x[i]; + } while (x[i++] != 0); +} + +void SYSTEM_STRAPNDSL(SHORTCHAR x[], CHAR y[], INTEGER n) /* ly := ly + LONG(sx) */ +{ + int i = 0, j = 0; + while (y[j] != 0) j++; + do { + if (n-- == 0) __HALT(-8); + y[j++] = x[i]; + } while (x[i++] != 0); +} + +void SYSTEM_STRAPNDTL(CHAR x[], CHAR y[], INTEGER n) /* ly := ly + LONG(SHORT(lx)) */ +{ + int i = 0, j = 0; + while (y[j] != 0) j++; + do { + if (n-- == 0) __HALT(-8); + y[j++] = (x[i] & 0xff); + } while ((x[i++] & 0xff) != 0); +} + diff --git a/C/SYSTEM.h b/C/SYSTEM.h new file mode 100644 index 0000000..183da76 --- /dev/null +++ b/C/SYSTEM.h @@ -0,0 +1,356 @@ +#ifndef SYSTEM__h +#define SYSTEM__h + +/* + +the CPfront runtime system interface and macro library +based on SYSTEM.h by Josef Templ +bh 20.12.1999 + +*/ + + +#pragma warning(disable:4101) // disable "unreferenced variable" warning + +#ifdef __GNUC__ +# include +#endif +#include +#include + +// extern char *memcpy(); + +#define export +#define import extern + +/* basic types */ +typedef unsigned char BOOLEAN; +typedef unsigned char SHORTCHAR; +typedef unsigned short CHAR; +typedef signed char BYTE; +typedef short SHORTINT; +typedef int INTEGER; +#if !defined(_WIN64) && ((__SIZEOF_POINTER__ == 8) || defined (_LP64) || defined(__LP64__)) + typedef long LONGINT; // LP64 + typedef unsigned long __U_LONGINT; +#else + typedef long long LONGINT; // ILP32 or LLP64 + typedef unsigned long long __U_LONGINT; +#endif +typedef float SHORTREAL; +typedef double REAL; +typedef unsigned int SET; +typedef void ANYREC; +typedef void *ANYPTR; +typedef void *SYSTEM_PTR; + +/* Unsigned variants are for use by shift and rotate macros */ +typedef unsigned char __U_SHORTCHAR; +typedef unsigned short __U_CHAR; +typedef unsigned char __U_BYTE; +typedef unsigned short __U_SHORTINT; +typedef unsigned int __U_INTEGER; +typedef unsigned int __U_SET; + +extern LONGINT SYSTEM_INF; +extern INTEGER SYSTEM_INFS; +extern INTEGER SYSTEM_argCount; +extern void *SYSTEM_argVector; + +/* constants */ +#define __MAXEXT 15 +#define NIL 0 +#define POINTER__typ (INTEGER*)1 /* not NIL and not a valid type */ +#define __INF (*(REAL*)&SYSTEM_INF) +#define __INFS (*(SHORTREAL*)&SYSTEM_INFS) + +#if defined _WIN32 || defined __CYGWIN__ +# ifdef __GNUC__ +# define __EXTERN __attribute__((dllimport)) +# else +# define __EXTERN __declspec(dllimport) +# endif +#else +# if __GNUC__ >= 4 && !defined(__OS2__) +# define __EXTERN __attribute__((visibility("default"))) +# else +# define __EXTERN +# endif +#endif +#define __CALLBACK __attribute__((__stdcall__)) + + +/* simple open array types */ + +typedef struct BOOLEAN_ARRAY { + INTEGER gc[3], len[1]; + BOOLEAN data[1]; +} BOOLEAN_ARRAY; +typedef struct CHAR_ARRAY { + INTEGER gc[3], len[1]; + CHAR data[1]; +} CHAR_ARRAY; +typedef struct SHORTCHAR_ARRAY { + INTEGER gc[3], len[1]; + SHORTCHAR data[1]; +} SHORTCHAR_ARRAY; +typedef struct BYTE_ARRAY { + INTEGER gc[3], len[1]; + BYTE data[1]; +} BYTE_ARRAY; +typedef struct SHORTINT_ARRAY { + INTEGER gc[3], len[1]; + SHORTINT data[1]; +} SHORTINT_ARRAY; +typedef struct INTEGER_ARRAY { + INTEGER gc[3], len[1]; + INTEGER data[1]; +} INTEGER_ARRAY; +typedef struct LONGINT_ARRAY { + INTEGER gc[3], len[1]; + LONGINT data[1]; +} LONGINT_ARRAY; +typedef struct REAL_ARRAY { + INTEGER gc[3], len[1]; + REAL data[1]; +} REAL_ARRAY; +typedef struct SHORTREAL_ARRAY { + INTEGER gc[3], len[1]; + SHORTREAL data[1]; +} SHORTREAL_ARRAY; +typedef struct SET_ARRAY { + INTEGER gc[3], len[1]; + SET data[1]; +} SET_ARRAY; + +/* meta info */ + +typedef struct SYSTEM_OBJDESC { + INTEGER fprint, offs, id, struc; +} SYSTEM_OBJDESC; +typedef struct SYSTEM_DIRECTORY { + INTEGER num; + struct SYSTEM_OBJDESC obj[1]; +} SYSTEM_DIRECTORY; +typedef struct SYSTEM_MODDESC { + struct SYSTEM_MODDESC *next; + SET opts; + INTEGER refcnt; + SHORTINT compTime[6], loadTime[6]; + void (*body) (); + void (*term) (); + INTEGER nofimps, nofptrs, size, dsize, rsize, code, data, refs, procBase, varBase; + char *names; + INTEGER *ptrs; + struct SYSTEM_MODDESC **imports; + struct SYSTEM_DIRECTORY *exp; + char name[256]; +} SYSTEM_MODDESC; +typedef struct SYSTEM_TYPEDESC { + INTEGER size; + struct SYSTEM_MODDESC *mod; + INTEGER id; + INTEGER base[16]; + struct SYSTEM_DIRECTORY *fields; + INTEGER ptroffs[1]; +} SYSTEM_TYPEDESC; + +/* dynamic link */ + +typedef struct SYSTEM_DLINK { + struct SYSTEM_DLINK *next; + char *name; +} SYSTEM_DLINK; +extern SYSTEM_DLINK *SYSTEM_dlink; + + +/* runtime system routines */ +extern CHAR* SYSTEM_LSTR(char *x); +extern INTEGER SYSTEM_DIV(INTEGER x, INTEGER y); +extern INTEGER SYSTEM_MOD(INTEGER x, INTEGER y); +extern INTEGER SYSTEM_MIN(INTEGER x, INTEGER y); +extern INTEGER SYSTEM_MAX(INTEGER x, INTEGER y); +extern INTEGER SYSTEM_ENTIER(REAL x); +extern INTEGER SYSTEM_ASH(INTEGER x, INTEGER n); +extern INTEGER SYSTEM_ABS(INTEGER x); +extern INTEGER SYSTEM_XCHK(INTEGER i, INTEGER ub); +extern void *SYSTEM_NEWARR(INTEGER type, INTEGER n); +extern void *SYSTEM_NEWARR1(INTEGER type, INTEGER n0, INTEGER n); +extern void *SYSTEM_NEWARR2(INTEGER type, INTEGER n1, INTEGER n0, INTEGER n); +extern void *SYSTEM_NEWARR3(INTEGER type, INTEGER n2, INTEGER n1, INTEGER n0, INTEGER n); +extern void *SYSTEM_NEWARR4(INTEGER type, INTEGER n3, INTEGER n2, INTEGER n1, INTEGER n0, INTEGER n); +extern void SYSTEM_REGMOD(struct SYSTEM_MODDESC *mod); +extern INTEGER SYSTEM_STRLEN(CHAR x[]); /* LEN(lx$) */ +extern INTEGER SYSTEM_STRLENS(SHORTCHAR x[]); /* LEN(sx$) */ +extern INTEGER SYSTEM_STRCMPSS(SHORTCHAR x[], SHORTCHAR y[]); /* sx = sy */ +extern INTEGER SYSTEM_STRCMPTS(CHAR x[], SHORTCHAR y[]); /* SHORT(lx) = sy */ +extern INTEGER SYSTEM_STRCMPTT(CHAR x[], CHAR y[]); /* SHORT(lx) = SHORT(ly) */ +extern INTEGER SYSTEM_STRCMPLL(CHAR x[], CHAR y[]); /* lx = ly */ +extern INTEGER SYSTEM_STRCMPSL(SHORTCHAR x[], CHAR y[]); /* LONG(sx) = ly */ +extern INTEGER SYSTEM_STRCMPTL(CHAR x[], CHAR y[]); /* LONG(SHORT(lx)) = ly */ +extern void SYSTEM_STRCOPYSS(SHORTCHAR x[], SHORTCHAR y[], INTEGER n); /* sy := sx */ +extern void SYSTEM_STRCOPYTS(CHAR x[], SHORTCHAR y[], INTEGER n); /* sy := SHORT(lx) */ +extern void SYSTEM_STRCOPYLL(CHAR x[], CHAR y[], INTEGER n); /* ly := lx */ +extern void SYSTEM_STRCOPYSL(SHORTCHAR x[], CHAR y[], INTEGER n); /* ly := LONG(sx) */ +extern void SYSTEM_STRCOPYTL(CHAR x[], CHAR y[], INTEGER n); /* ly := LONG(SHORT(lx)) */ +extern void SYSTEM_STRAPNDSS(SHORTCHAR x[], SHORTCHAR y[], INTEGER n); /* sy := sy + sx */ +extern void SYSTEM_STRAPNDTS(CHAR x[], SHORTCHAR y[], INTEGER n); /* sy := sy + SHORT(lx) */ +extern void SYSTEM_STRAPNDLL(CHAR x[], CHAR y[], INTEGER n); /* ly := ly + lx */ +extern void SYSTEM_STRAPNDSL(SHORTCHAR x[], CHAR y[], INTEGER n); /* ly := ly + LONG(sx) */ +extern void SYSTEM_STRAPNDTL(CHAR x[], CHAR y[], INTEGER n); /* ly := ly + LONG(SHORT(lx)) */ +extern LONGINT SYSTEM_DIVL(LONGINT x, LONGINT y); +extern LONGINT SYSTEM_MODL(LONGINT x, LONGINT y); +extern LONGINT SYSTEM_MINL(LONGINT x, LONGINT y); +extern LONGINT SYSTEM_MAXL(LONGINT x, LONGINT y); +extern LONGINT SYSTEM_ASHL(LONGINT x, INTEGER n); +extern LONGINT SYSTEM_ABSL(LONGINT x); +extern SHORTREAL SYSTEM_INT2SR(INTEGER x); +extern REAL SYSTEM_LONG2R(LONGINT x); +extern LONGINT SYSTEM_ENTIERL(REAL x); +extern INTEGER SYSTEM_SR2INT(SHORTREAL x); +extern LONGINT SYSTEM_R2LONG(REAL x); +extern SHORTREAL SYSTEM_ABSF(SHORTREAL x); +extern SHORTREAL SYSTEM_MINF(SHORTREAL x, SHORTREAL y); +extern SHORTREAL SYSTEM_MAXF(SHORTREAL x, SHORTREAL y); +extern REAL SYSTEM_ABSD(REAL x); +extern REAL SYSTEM_MIND(REAL x, REAL y); +extern REAL SYSTEM_MAXD(REAL x, REAL y); + +extern INTEGER Kernel_NewRec(INTEGER typ); +extern INTEGER Kernel_NewArr(INTEGER eltyp, INTEGER nofelem, INTEGER nofdim); +extern void Kernel_Trap(INTEGER n); + + +#define __INIT(argc, argv) SYSTEM_argCount = argc; SYSTEM_argVector = *(void**)&argv +#define __BEGREG(mod) if (mod.opts & 0x40000) return; mod.opts |= 0x40000; +#define __ENDREG +#define __REGMOD(mod) SYSTEM_REGMOD(&mod); +#define __BEGBODY(mod) if (mod.opts & 0x10000) return; mod.opts |= 0x10000; +#define __ENDBODY +#define __BEGCLOSE +#define __ENDCLOSE +#define __ENTER(name) SYSTEM_DLINK __dl = {SYSTEM_dlink, name}; SYSTEM_dlink = &__dl +#define __EXIT SYSTEM_dlink = __dl.next + +/* SYSTEM ops */ +#define __VAL(t, x) (*(t*)&(x)) +#define __VALSR(x) SYSTEM_INT2SR(x) +#define __VALR(x) SYSTEM_LONG2R(x) +#define __VALI(x) SYSTEM_SR2INT(x) +#define __VALL(x) SYSTEM_R2LONG(x) +#define __GET(a, x, t) x= *(t*)(a) +#define __PUT(a, x, t) *(t*)(a)=(t)x +#define __LSHL(x, n, t) ((t)((__U_##t)(x)<<(n))) +#define __LSHR(x, n, t) ((t)((__U_##t)(x)>>(n))) +#define __LSH(x, n, t) ((n)>=0? __LSHL(x, n, t): __LSHR(x, -(n), t)) +#define __ROTL(x, n, t) ((t)((__U_##t)(x)<<(n)|(__U_##t)(x)>>(8*sizeof(t)-(n)))) +#define __ROTR(x, n, t) ((t)((__U_##t)(x)>>(n)|(__U_##t)(x)<<(8*sizeof(t)-(n)))) +#define __ROT(x, n, t) ((n)>=0? __ROTL(x, n, t): __ROTR(x, -(n), t)) +#define __BIT(x, n) (*(unsigned*)(x)>>(n)&1) +#define __MOVE(s, d, n) memcpy((char*)(d),(char*)(s),n) + +/* std procs and operator mappings */ +// #define __SHORT(x, y) ((int)((unsigned)(x)+(y)<(y)+(y)?(x):(__HALT(-8),0))) +// #define __SHORTF(x, y) ((int)(__RF((x)+(y),(y)+(y))-(y))) +// #define __CHR(x) ((CHAR)__R(x, 256)) +// #define __CHRF(x) ((CHAR)__RF(x, 256)) +#define __DIV(x, y) ((x)>=0?(x)/(y):~(~(x)/(y))) +#define __DIVF(x, y) SYSTEM_DIV(x,y) +#define __DIVFL(x, y) SYSTEM_DIVL(x,y) +#define __MOD(x, y) ((x)>=0?(x)%(y):(y)+~(~(x)%(y))) +#define __MODF(x, y) SYSTEM_MOD(x,y) +#define __MODFL(x, y) SYSTEM_MODL(x,y) +#define __MIN(x, y) ((x)<(y)?(x):(y)) +#define __MINF(x, y) SYSTEM_MIN(x,y) +#define __MINFL(x, y) SYSTEM_MINL(x,y) +#define __MINFF(x, y) SYSTEM_MINF(x,y) +#define __MINFD(x, y) SYSTEM_MIND(x,y) +#define __MAX(x, y) ((x)>(y)?(x):(y)) +#define __MAXF(x, y) SYSTEM_MAX(x,y) +#define __MAXFL(x, y) SYSTEM_MAXL(x,y) +#define __MAXFF(x, y) SYSTEM_MAXF(x,y) +#define __MAXFD(x, y) SYSTEM_MAXD(x,y) +#define __NEW(t) (void*)Kernel_NewRec((INTEGER)t) +#define __NEWARR(t, n) (void*)SYSTEM_NEWARR(t, n) +#define __NEWARR0(t, n) (void*)Kernel_NewArr(t, n, 0) +#define __NEWARR1(t, n0, n) (void*)SYSTEM_NEWARR1(t, n0, n) +#define __NEWARR2(t, n1, n0, n) (void*)SYSTEM_NEWARR2(t, n1, n0, n) +#define __NEWARR3(t, n2, n1, n0, n) (void*)SYSTEM_NEWARR3(t, n2, n1, n0, n) +#define __NEWARR4(t, n3, n2, n1, n0, n) (void*)SYSTEM_NEWARR4(t, n3, n2, n1, n0, n) +#define __HALT(x) Kernel_Trap(x) +#define __ASSERT(cond, x) if (!(cond)) __HALT(x) +#define __ENTIER(x) SYSTEM_ENTIER(x) +#define __ENTIERL(x) SYSTEM_ENTIERL(x) +#define __ABS(x) (((x)<0)?-(x):(x)) +#define __ABSF(x) SYSTEM_ABS(x) +#define __ABSFL(x) SYSTEM_ABSL(x) +#define __ABSFF(x) SYSTEM_ABSF(x) +#define __ABSFD(x) SYSTEM_ABSD(x) +#define __CAP(ch) ((CHAR)((ch)&0x5f)) +#define __ODD(x) ((x)&1) +#define __IN(x, s) (((s)>>(x))&1) +#define __SETOF(x) ((SET)1<<(x)) +#define __SETRNG(l, h) ((~(SET)0<<(l))&~(SET)0>>(8*sizeof(SET)-1-(h))) +#define __MASK(x, m) ((x)&~(m)) +#define __LSTR(x) SYSTEM_LSTR(x) + +#define __STRLEN(x) SYSTEM_STRLEN(x) /* LEN(lx$) */ +#define __STRLENS(x) SYSTEM_STRLENS(x) /* LEN(sx$) */ +#define __STRCMPSS(x, y) SYSTEM_STRCMPSS(x, y) /* sx = sy */ +#define __STRCMPTS(x, y) SYSTEM_STRCMPTS(x, y) /* SHORT(lx) = sy */ +#define __STRCMPTT(x, y) SYSTEM_STRCMPTT(x, y) /* SHORT(lx) = SHORT(ly) */ +#define __STRCMPLL(x, y) SYSTEM_STRCMPLL(x, y) /* lx = ly */ +#define __STRCMPSL(x, y) SYSTEM_STRCMPSL(x, y) /* LONG(sx) = ly */ +#define __STRCMPTL(x, y) SYSTEM_STRCMPTL(x, y) /* LONG(SHORT(lx)) = ly */ +#define __STRCOPYSS(x, y, n) SYSTEM_STRCOPYSS(x, y, n) /* sy := sx */ +#define __STRCOPYTS(x, y, n) SYSTEM_STRCOPYTS(x, y, n) /* sy := SHORT(lx) */ +#define __STRCOPYLL(x, y, n) SYSTEM_STRCOPYLL(x, y, n) /* ly := lx */ +#define __STRCOPYSL(x, y, n) SYSTEM_STRCOPYSL(x, y, n) /* ly := LONG(sx) */ +#define __STRCOPYTL(x, y, n) SYSTEM_STRCOPYTL(x, y, n) /* ly := LONG(SHORT(lx)) */ +#define __STRAPNDSS(x, y, n) SYSTEM_STRAPNDSS(x, y, n) /* sy := sy + sx */ +#define __STRAPNDTS(x, y, n) SYSTEM_STRAPNDTS(x, y, n) /* sy := sy + SHORT(lx) */ +#define __STRAPNDLL(x, y, n) SYSTEM_STRAPNDLL(x, y, n) /* ly := ly + lx */ +#define __STRAPNDSL(x, y, n) SYSTEM_STRAPNDSL(x, y, n) /* ly := ly + LONG(sx) */ +#define __STRAPNDTL(x, y, n) SYSTEM_STRAPNDTL(x, y, n) /* ly := ly + LONG(SHORT(lx)) */ + +#define __ASH(x, n, t) ((n)>=0?__ASHL(x,n,t):__ASHR(x,-(n),t)) +#define __ASHL(x, n, t) ((t)(x)<<(n)) +#define __ASHR(x, n, t) ((t)(x)>>(n)) +#define __ASHF(x, n, t) SYSTEM_ASH(x, n) +#define __ASHFL(x, n, t) SYSTEM_ASHL(x, n) +#define __DUP(x, l) x=(void*)memcpy(alloca(l*sizeof(*x)),x,l*sizeof(*x)) +#define __DUPARR(v) v=(void*)memcpy(v##__copy,v,sizeof(v##__copy)) +#define __DEL(x) /* DUP with alloca frees storage automatically */ +#define __IS(tag, typ, level) ((tag->base[level])==(INTEGER)typ) +#define __TYPEOF(p) (*(((SYSTEM_TYPEDESC**)(p))-1)) +#define __ISP(p, typ, level) __IS(__TYPEOF(p),typ,level) + +/* runtime checks */ +#define __X(i, ub) (((unsigned)(i)<(unsigned)(ub))?i:(__HALT(-7),0)) +#define __XF(i, ub) SYSTEM_XCHK((INTEGER)(i), (INTEGER)(ub)) +// #define __RETCHK __retchk: __HALT(-3) +#define __RETCHK __HALT(-3) +#define __CASECHK __HALT(-2) +#define __GUARDP(p, typ, level) ((typ*)(__ISP(p,typ,level)?p:(__HALT(-4),p))) +#define __GUARDR(r, typ, level) (*((typ*)(__IS(r##__typ,typ,level)?r:(__HALT(-4),r)))) +#define __GUARDA(p, typ, level) ((struct typ*)(__IS(__TYPEOF(p),typ,level)?p:(__HALT(-4),p))) +#define __WITHCHK __HALT(-1) + +/* Oberon-2 type bound procedures support */ +#define __SEND(typ, num, funtyp, parlist) ((funtyp)(*((INTEGER*)typ-(num+1))))parlist + +/* runtime system variables */ +extern SYSTEM_MODDESC *SYSTEM_modlist; +extern LONGINT SYSTEM_argc; +extern LONGINT SYSTEM_argv; +extern void (*SYSTEM_Halt)(); +extern LONGINT SYSTEM_halt; +extern LONGINT SYSTEM_assert; +extern SYSTEM_PTR SYSTEM_modules; +extern LONGINT SYSTEM_heapsize; +extern LONGINT SYSTEM_allocated; +extern LONGINT SYSTEM_lock; +extern SHORTINT SYSTEM_gclock; +extern BOOLEAN SYSTEM_interrupted; + +#endif diff --git a/C/_windows.h b/C/_windows.h new file mode 100644 index 0000000..74a04c3 --- /dev/null +++ b/C/_windows.h @@ -0,0 +1,18 @@ +// windows.h wrapper +// Includes windows.h while avoiding conflicts with Component Pascal types. + +#define BOOLEAN _BOOLEAN +#define BYTE _BYTE +#define CHAR _CHAR + +#undef _WIN32_WINNT +// 0x0501 is for Windows XP (no service pack) +#define _WIN32_WINNT 0x0501 +#include + +#undef BOOLEAN +#undef BYTE +#undef CHAR + +typedef void *PtrVoid; +typedef CHAR *PtrWSTR; diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..78c9b44 --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,5 @@ +v0.1: +* implemented true command line versions of DevCompiler, Dev2Linker and CPfront +* implemented new generic Host for POSIX-compatible systems +* implemented Kernel for CPfront +* implemented generic Int and 486-specific Long modules diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README b/README new file mode 100644 index 0000000..bb2d483 --- /dev/null +++ b/README @@ -0,0 +1,33 @@ +CPC +--------- + +A command line Component Pascal Compiler + +Building +--------- + +Requirements: +* x86 CPU +* GNU/Linux +* GNU GCC +* installed multilib + +1. Run make-stage0.sh to bootstrap using BlackBox Cross Platform +(https://github.com/bbcb/bbcp) or run make-stage0c.sh to bootstrap from +prebuilded C source code produced by CPfront +2. Run make-stage1.sh +3. Run make-stage2.sh +4. Grab your binaries from stage2/i486 + +Directory crux is a good example how of package for linux distro. + +Bugs +_________ + +Contact to me if you found some bugs. :) + +Licensing +--------- + +Any code and patches under GPLv3+ (see LICENSE file). Contact to me (DEADDOOMER) if you want +to use some code in your BSD-licensed BlackBox/CPfront fork or project. diff --git a/crux/cpc-32/.32bit b/crux/cpc-32/.32bit new file mode 100644 index 0000000..e69de29 diff --git a/crux/cpc-32/Pkgfile b/crux/cpc-32/Pkgfile new file mode 100644 index 0000000..2d84da6 --- /dev/null +++ b/crux/cpc-32/Pkgfile @@ -0,0 +1,30 @@ +# Description: A command line Copmponent Pascal Compiler +# URL: https://deadsoftware.ru +# Maintainer: DeaDDooMER, deaddoomer@deadsoftware.ru + +name=cpc-32 +version=0.1 +release=1 +source=(https://deadsoftware.ru/projects/cpc/release/cpc-v${version}.src.tar.gz) + +build() { + cd bootstrap-src + + ./make-stage0c.sh + ./make-stage1.sh + ./make-stage2.sh + + install -d $PKG/usr/bin + install -D -m755 stage2/i486/{cpc486,cpl486,cpfront} $PKG/usr/bin/ + ln -s cpc486 $PKG/usr/bin/cpc + ln -s cpl486 $PKG/usr/bin/cpl + + install -d $PKG/usr/share/man/man1 + install -D -m644 man/cp{c,l}.1 $PKG/usr/share/man/man1 + ln -s cpc.1.gz $PKG/usr/share/man/man1/cpc486.1.gz + ln -s cpc.1.gz $PKG/usr/share/man/man1/cpfront.1.gz + ln -s cpl.1.gz $PKG/usr/share/man/man1/cpl486.1.gz + + install -d $PKG/usr/share/cpfront/C + install -D -m644 C/SYSTEM.{c,h} $PKG/usr/share/cpfront/C +} diff --git a/make-bootstrap.sh b/make-bootstrap.sh new file mode 100755 index 0000000..8fdb3fd --- /dev/null +++ b/make-bootstrap.sh @@ -0,0 +1,190 @@ +#! /bin/sh + +set -e + +THIS="$(dirname "$(readlink -f "$0")")" +OUT="$THIS/bootstrap/i486" + +cpc() { + "$THIS/stage2/i486/cpfront" -outcode CodeC -outsym SymC "$@" +} + +importlist() { + echo + while [ "$1" != "" ]; do + echo -n "\t\t$1" + shift + if [ "$1" != "" ]; then + echo "," + fi + done +} + +mainmodule() { +local name="$1" +shift +cat < "$name.cp" + shift + + cpc -main "$name.cp" + + local list="" + for mod in "$@" "$name"; do + list="$list CodeC/$mod.c" + done +} + +###^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^### +### Prepare bbdsw sources for LINUX/i486 ### +###______________________________________### + +rm -rf "$OUT" +mkdir -p "$OUT" +cp -r -- \ + "$THIS/src/generic/"* \ + "$THIS/src/posix/"* \ + "$THIS/src/cpfront/posix/"* \ + "$THIS/src/cpfront/linux/"* \ + "$OUT" +cd "$OUT" + +###^^^^^^^^^^^^^^^^^^^^^^^^### +### Compile POSIX bindings ### +###________________________### + +cpc C99/Mod/types.cp \ + C99/Mod/sys_types.cp \ + C99/Mod/stdlib.cp C99/Mod/stdio.cp C99/Mod/unistd.cp \ + C99/Mod/dirent.cp C99/Mod/locale.cp C99/Mod/time.cp \ + C99/Mod/sys_stat.cp C99/Mod/fcntl.cp C99/Mod/errno.cp \ + C99/Mod/iconv.cp C99/Mod/wctype.cp C99/Mod/sys_mman.cp \ + C99/Mod/dlfcn.cp C99/Mod/signal.cp C99/Mod/setjmp.cp \ + C99/Mod/libgen.cp \ + C99/Mod/macro.cp + +###^^^^^^^^^^^^^^^^^^^^^^^^^^^^### +### Compile BlackBox Framework ### +###____________________________### + +cpc System/Mod/Math.cp System/Mod/SMath.cp System/Mod/Kernel.cp \ + System/Mod/Console.odc System/Mod/Files.odc System/Mod/Dates.odc \ + System/Mod/Log.odc System/Mod/Strings.odc System/Mod/Services.odc \ + System/Mod/Int.odc System/Mod/Integers.odc + +###^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^### +### Compile Linux Host subsystem ### +###______________________________### + +cpc Host/Mod/Lang.cp Host/Mod/Dates.cp Host/Mod/Console.cp Host/Mod/Files.cp + +###^^^^^^^^^^^^^^^^^^^^^^^### +### Compile Dev subsystem ### +###_______________________### + +cpc Dev/Mod/CPM.cp Dev/Mod/CPT.odc Dev/Mod/CPS.odc Dev/Mod/CPB.odc \ + Dev/Mod/CPP.odc Dev/Mod/CPE.odc Dev/Mod/CPH.odc Dev/Mod/CPL486.odc \ + Dev/Mod/CPC486.odc Dev/Mod/CPV486.odc + +###^^^^^^^^^^^^^^^^^^^^^^^^### +### Compile Dev2 subsystem ### +###________________________### + +cpc Dev2/Mod/LnkBase.odc Dev2/Mod/LnkChmod.odc Dev2/Mod/LnkLoad.odc \ + Dev2/Mod/LnkWriteElf.odc Dev2/Mod/LnkWriteElfStatic.odc \ + Dev2/Mod/LnkWritePe.odc + +###^^^^^^^^^^^^^^^^^^^^^^^^^^^### +### Compile CPfront subsystem ### +###___________________________### + +cpc CPfront/Mod/CPG.odc CPfront/Mod/CPC.odc CPfront/Mod/CPV.odc + +###^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^### +### Compile bbdsw-specific modules ### +###________________________________### + +cpc Dsw/Mod/Documents.cp Dsw/Mod/Log.odc Dsw/Mod/Compiler486Main.cp \ + Dsw/Mod/CompilerCPfrontMain.cp Dsw/Mod/Linker486Main.cp + +###^^^^^^^^^^^^^^^^^^^^^^^^^### +### Compile other utilities ### +###_________________________### + +cpc Dsw/Mod/ListMain.cp Dsw/Mod/EchoMain.cp Dsw/Mod/LoopMain.cp + +###^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^### +### Link Standalone Component Pascl Compiler & Dev2 Linker ### +###________________________________________________________### + +linkall cpfront \ + C99types C99macro \ + Kernel Console Files Dates Math Strings Services Log \ + HostLang HostConsole HostFiles HostDates DswLog \ + DevCPM DevCPT DevCPS DevCPB DevCPP DevCPE DevCPH \ + CPfrontCPG CPfrontCPC CPfrontCPV\ + DswDocuments DswCompilerCPfrontMain + +linkall cpc486 \ + C99types C99macro \ + Kernel Console Files Dates Math Strings Services Log \ + HostLang HostConsole HostFiles HostDates DswLog \ + DevCPM DevCPT DevCPS DevCPB DevCPP DevCPE DevCPH \ + DevCPL486 DevCPC486 DevCPV486 \ + DswDocuments DswCompiler486Main + +linkall cpl486 \ + C99types C99macro \ + Kernel Console Files Math Strings Services Log \ + HostLang HostConsole HostFiles DswLog \ + Dev2LnkBase Dev2LnkChmod Dev2LnkLoad Dev2LnkWriteElf \ + Dev2LnkWriteElfStatic Dev2LnkWritePe \ + DswLinker486Main + +#linkall cplist \ +# C99types C99macro \ +# Kernel Console Files Math Strings Services Log \ +# HostLang HostConsole HostFiles DswLog \ +# DswListMain + +#linkall cpecho \ +# C99types C99macro \ +# Kernel Console Files Math Strings Services Log \ +# HostLang HostConsole HostFiles DswLog \ +# DswEchoMain + +#linkall cploop \ +# C99types C99macro \ +# Kernel Console Files Math Strings Services Log \ +# HostLang HostConsole HostFiles DswLog \ +# DswLoopMain + +rm -rf "$THIS/bootstrap-src" +mkdir -p "$THIS/bootstrap-src" +cp -r -t "$THIS/bootstrap-src" -- \ + "$THIS/CHANGELOG" \ + "$THIS/LICENSE" \ + "$THIS/README" \ + "$THIS/man" \ + "$THIS/crux" \ + "$THIS/make-bootstrap.sh" \ + "$THIS/make-stage0.sh" \ + "$THIS/make-stage0c.sh" \ + "$THIS/make-stage1.sh" \ + "$THIS/make-stage2.sh" \ + "$THIS/src" \ + "$THIS/C" \ + CodeC + +cd "$THIS" +tar czf cpc-v0.1.src.tar.gz bootstrap-src diff --git a/make-stage0.sh b/make-stage0.sh new file mode 100755 index 0000000..d6a9a3e --- /dev/null +++ b/make-stage0.sh @@ -0,0 +1,113 @@ +#! /bin/sh + +set -e + +THIS="$(dirname "$(readlink -f "$0")")" +OUT="$THIS/stage0/i486" + +###^^^^^^^^^^^^^^^^^^### +### Check BBCP files ### +###__________________### + +mkdir -p "$THIS/stage0" +if ! [ -e "$THIS/stage0/bbcp" ]; then + echo "Please, clone bbcp repo:" + echo "-> git clone --depth=1 -b crux https://git.deadsoftware.ru/bbcp.git '$(realpath --relative-to="$PWD" "$THIS/stage0/bbcp")'" + echo "Than retry building using make-stage0.sh" + exit 1 +fi +cd "$THIS/stage0/bbcp/BlackBox" + +###^^^^^^^^^^^^^^^^^^^### +### Build BBCP itself ### +###___________________### + +./switch-target Linux Interp +./build + +###^^^^^^^^^^^^^^^^^^^^^^^^^^^^### +### Copy minimal bbdsw sources ### +###____________________________### + +rm -rf "$OUT" +mkdir -p "$OUT" +cp -r -- \ + "$THIS/src/generic/"* \ + "$THIS/src/posix/"* \ + "$THIS/src/i486/generic/"* \ + "$THIS/src/i486/posix/"* \ + "$THIS/src/i486/linux/"* \ + "$OUT" + +###^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^### +### Compile Stage0 Compiler & Linker ### +###__________________________________### + +./blackbox < SYSTEM_DLINK *) + DLink = POINTER TO RECORD [untagged] + next: DLink; + name: StrPtr + END; + ArrStrPtr = POINTER TO ARRAY [untagged] OF StrPtr; + + ADDRESS* = types.Pvoid; + + VAR + baseStack: INTEGER; + root: Cluster; + modList-: Module; + trapCount-: INTEGER; + err-, pc-, sp-, fp-, stack-, val-: INTEGER; + + isTry: BOOLEAN; + startEnv: setjmp.sigjmp_buf; + tryEnv: setjmp.jmp_buf; + startDLink, tryDLink: DLink; + + argc-: INTEGER; + argv-: ArrStrPtr; + pagesize: unistd.long; + + free: ARRAY N OF FreeBlock; (* free list *) + sentinelBlock: FreeDesc; + sentinel: FreeBlock; + candidates: ARRAY 1024 OF INTEGER; + nofcand: INTEGER; + allocated: INTEGER; (* bytes allocated on BlackBox heap *) + total: INTEGER; (* current total size of BlackBox heap *) + used: INTEGER; (* bytes allocated on system heap *) + finalizers: FList; + hotFinalizers: FList; + cleaners: CList; + reducers: Reducer; + trapStack: TrapCleaner; + actual: Module; (* valid during module initialization *) + + trapViewer, trapChecker: Handler; + trapped, guarded, secondTrap: BOOLEAN; + interrupted: BOOLEAN; + static, inDll, terminating: BOOLEAN; + restart: Command; + + loader: LoaderHook; + loadres: INTEGER; + + wouldFinalize: BOOLEAN; + + watcher*: PROCEDURE (event: INTEGER); (* for debugging *) + + PROCEDURE Erase (adr, words: INTEGER); + BEGIN + ASSERT(words >= 0, 20); + WHILE words > 0 DO + S.PUT(adr, 0); + INC(adr, 4); + DEC(words) + END + END Erase; + + + PROCEDURE (VAR id: Identifier) Identified* (): BOOLEAN, NEW, ABSTRACT; + PROCEDURE (r: Reducer) Reduce* (full: BOOLEAN), NEW, ABSTRACT; + PROCEDURE (c: TrapCleaner) Cleanup*, NEW, EMPTY; + + (* meta extension suport *) + + PROCEDURE (e: ItemExt) Lookup* (name: ARRAY OF CHAR; VAR i: ANYREC), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) Index* (index: INTEGER; VAR elem: ANYREC), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) Deref* (VAR ref: ANYREC), NEW, ABSTRACT; + + PROCEDURE (e: ItemExt) Valid* (): BOOLEAN, NEW, ABSTRACT; + PROCEDURE (e: ItemExt) Size* (): INTEGER, NEW, ABSTRACT; + PROCEDURE (e: ItemExt) BaseTyp* (): INTEGER, NEW, ABSTRACT; + PROCEDURE (e: ItemExt) Len* (): INTEGER, NEW, ABSTRACT; + + PROCEDURE (e: ItemExt) Call* (OUT ok: BOOLEAN), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) BoolVal* (): BOOLEAN, NEW, ABSTRACT; + PROCEDURE (e: ItemExt) PutBoolVal* (x: BOOLEAN), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) CharVal* (): CHAR, NEW, ABSTRACT; + PROCEDURE (e: ItemExt) PutCharVal* (x: CHAR), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) IntVal* (): INTEGER, NEW, ABSTRACT; + PROCEDURE (e: ItemExt) PutIntVal* (x: INTEGER), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) LongVal* (): LONGINT, NEW, ABSTRACT; + PROCEDURE (e: ItemExt) PutLongVal* (x: LONGINT), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) RealVal* (): REAL, NEW, ABSTRACT; + PROCEDURE (e: ItemExt) PutRealVal* (x: REAL), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) SetVal* (): SET, NEW, ABSTRACT; + PROCEDURE (e: ItemExt) PutSetVal* (x: SET), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) PtrVal* (): ANYPTR, NEW, ABSTRACT; + PROCEDURE (e: ItemExt) PutPtrVal* (x: ANYPTR), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) GetSStringVal* (OUT x: ARRAY OF SHORTCHAR; + OUT ok: BOOLEAN), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) PutSStringVal* (IN x: ARRAY OF SHORTCHAR; + OUT ok: BOOLEAN), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) GetStringVal* (OUT x: ARRAY OF CHAR; OUT ok: BOOLEAN), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) PutStringVal* (IN x: ARRAY OF CHAR; OUT ok: BOOLEAN), NEW, ABSTRACT; + + (* -------------------- miscellaneous tools -------------------- *) + + PROCEDURE IsUpper* (ch: CHAR): BOOLEAN; + BEGIN + RETURN wctype.iswupper(ORD(ch)) # 0 + END IsUpper; + + PROCEDURE Upper* (ch: CHAR): CHAR; + BEGIN + RETURN CHR(wctype.towupper(ORD(ch))) + END Upper; + + PROCEDURE IsLower* (ch: CHAR): BOOLEAN; + BEGIN + RETURN wctype.iswlower(ORD(ch)) # 0 + END IsLower; + + PROCEDURE Lower* (ch: CHAR): CHAR; + BEGIN + RETURN CHR(wctype.towlower(ORD(ch))) + END Lower; + + PROCEDURE IsAlpha* (ch: CHAR): BOOLEAN; + BEGIN + RETURN wctype.iswalpha(ORD(ch)) # 0 + END IsAlpha; + + PROCEDURE Utf8ToString* (IN in: ARRAY OF SHORTCHAR; OUT out: ARRAY OF CHAR; OUT res: INTEGER); + VAR i, j, val, max: INTEGER; ch: SHORTCHAR; + + PROCEDURE FormatError(); + BEGIN out := in$; res := 2 (*format error*) + END FormatError; + + BEGIN + ch := in[0]; i := 1; j := 0; max := LEN(out) - 1; + WHILE (ch # 0X) & (j < max) DO + IF ch < 80X THEN + out[j] := ch; INC(j) + ELSIF ch < 0E0X THEN + val := ORD(ch) - 192; + IF val < 0 THEN FormatError; RETURN END ; + ch := in[i]; INC(i); val := val * 64 + ORD(ch) - 128; + IF (ch < 80X) OR (ch >= 0E0X) THEN FormatError; RETURN END ; + out[j] := CHR(val); INC(j) + ELSIF ch < 0F0X THEN + val := ORD(ch) - 224; + ch := in[i]; INC(i); val := val * 64 + ORD(ch) - 128; + IF (ch < 80X) OR (ch >= 0E0X) THEN FormatError; RETURN END ; + ch := in[i]; INC(i); val := val * 64 + ORD(ch) - 128; + IF (ch < 80X) OR (ch >= 0E0X) THEN FormatError; RETURN END ; + out[j] := CHR(val); INC(j) + ELSE + FormatError; RETURN + END ; + ch := in[i]; INC(i) + END; + out[j] := 0X; + IF ch = 0X THEN res := 0 (*ok*) ELSE res := 1 (*truncated*) END + END Utf8ToString; + + PROCEDURE StringToUtf8* (IN in: ARRAY OF CHAR; OUT out: ARRAY OF SHORTCHAR; OUT res: INTEGER); + VAR i, j, val, max: INTEGER; + BEGIN + i := 0; j := 0; max := LEN(out) - 3; + WHILE (in[i] # 0X) & (j < max) DO + val := ORD(in[i]); INC(i); + IF val < 128 THEN + out[j] := SHORT(CHR(val)); INC(j) + ELSIF val < 2048 THEN + out[j] := SHORT(CHR(val DIV 64 + 192)); INC(j); + out[j] := SHORT(CHR(val MOD 64 + 128)); INC(j) + ELSE + out[j] := SHORT(CHR(val DIV 4096 + 224)); INC(j); + out[j] := SHORT(CHR(val DIV 64 MOD 64 + 128)); INC(j); + out[j] := SHORT(CHR(val MOD 64 + 128)); INC(j) + END; + END; + out[j] := 0X; + IF in[i] = 0X THEN res := 0 (*ok*) ELSE res := 1 (*truncated*) END + END StringToUtf8; + + PROCEDURE SplitName* (name: ARRAY OF CHAR; VAR head, tail: ARRAY OF CHAR); + (* portable *) + VAR i, j: INTEGER; ch, lch: CHAR; + BEGIN + i := 0; ch := name[0]; + IF ch # 0X THEN + REPEAT + head[i] := ch; lch := ch; INC(i); ch := name[i] + UNTIL (ch = 0X) OR (ch = ".") OR IsUpper(ch) & ~IsUpper(lch); + IF ch = "." THEN i := 0; ch := name[0] END; + head[i] := 0X; j := 0; + WHILE ch # 0X DO tail[j] := ch; INC(i); INC(j); ch := name[i] END; + tail[j] := 0X; + IF tail = "" THEN tail := head$; head := "" END + ELSE head := ""; tail := "" + END + END SplitName; + + PROCEDURE MakeFileName* (VAR name: ARRAY OF CHAR; type: ARRAY OF CHAR); + VAR i, j: INTEGER; ext: ARRAY 8 OF CHAR; ch: CHAR; + BEGIN + i := 0; + WHILE (name[i] # 0X) & (name[i] # ".") DO INC(i) END; + IF name[i] = "." THEN + IF name[i + 1] = 0X THEN name[i] := 0X END + ELSE + IF type = "" THEN ext := docType ELSE ext := type$ END; + IF i < LEN(name) - LEN(ext$) - 1 THEN + name[i] := "."; INC(i); j := 0; ch := ext[0]; + WHILE ch # 0X DO + name[i] := Lower(ch); INC(i); INC(j); ch := ext[j] + END; + name[i] := 0X + END + END + END MakeFileName; + + PROCEDURE Time* (): LONGINT; + VAR res: time.int; tp: time.struct_timespec; + BEGIN + ASSERT(timeResolution >= 1); + ASSERT(timeResolution <= 1000000000); + res := time.clock_gettime(time.CLOCK_MONOTONIC, tp); + ASSERT(res = 0, 100); + RETURN tp.tv_sec * LONG(timeResolution) + tp.tv_nsec DIV LONG(1000000000 DIV timeResolution) + END Time; + + PROCEDURE Beep*; + (* !!! *) + END Beep; + + PROCEDURE SearchProcVar* (var: INTEGER; VAR m: Module; VAR adr: INTEGER); + BEGIN + adr := var; m := NIL; + IF var # 0 THEN + m := modList; + WHILE (m # NIL) & ((var < m.code) OR (var >= m.code + m.csize)) DO m := m.next END; + IF m # NIL THEN DEC(adr, m.code) END + END + END SearchProcVar; + + (* -------------------- system memory management --------------------- *) + + PROCEDURE AllocMem (size: sysmman.size_t; VAR max: sysmman.size_t): ADDRESS; + VAR fd, flags, res: fcntl.int; ptr: ADDRESS; + BEGIN + max := (size + pagesize - 1) DIV pagesize * pagesize; + fd := fcntl.open("/dev/zero", fcntl.O_RDWR, 0); + IF fd # -1 THEN + flags := sysmman.PROT_READ + sysmman.PROT_WRITE; + ptr := sysmman.mmap(0, max, flags, sysmman.MAP_PRIVATE, fd, 0); + IF ptr = sysmman.MAP_FAILED THEN ptr := 0 END; + res := unistd.close(fd); + ASSERT(res = 0, 100) + ELSE + ptr := 0 + END; + RETURN ptr + END AllocMem; + + PROCEDURE FreeMem (adr: ADDRESS; size: sysmman.size_t); + VAR res: sysmman.int; + BEGIN + size := (size + pagesize - 1) DIV pagesize * pagesize; + res := sysmman.munmap(adr, size); + ASSERT(res = 0, 100) + END FreeMem; + + PROCEDURE AllocHeapMem (size: INTEGER; VAR c: Cluster); + CONST N = 65536; (* cluster size for dll *) + VAR adr, allocated: INTEGER; + BEGIN + INC(size, 16); + ASSERT(size > 0, 100); adr := 0; + IF size < N THEN adr := stdlib.malloc(N) END; + IF adr = 0 THEN adr := stdlib.malloc(size); allocated := size ELSE allocated := N END; + IF adr = 0 THEN c := NIL + ELSE + c := S.VAL(Cluster, (adr + 15) DIV 16 * 16); c.max := adr; + c.size := allocated - (S.VAL(INTEGER, c) - adr); + INC(used, c.size); INC(total, c.size) + END; + ASSERT((adr = 0) OR (adr MOD 16 = 0) & (c.size >= size), 101); + (* post: (c = NIL) OR (c MOD 16 = 0) & (c.size >= size) *) + END AllocHeapMem; + + PROCEDURE FreeHeapMem (c: Cluster); + BEGIN + DEC(used, c.size); DEC(total, c.size); + stdlib.free(S.VAL(ADDRESS, c.max)) + END FreeHeapMem; + + PROCEDURE HeapFull (size: INTEGER): BOOLEAN; + BEGIN + RETURN TRUE + END HeapFull; + + PROCEDURE AllocModMem* (descSize, modSize: INTEGER; VAR descAdr, modAdr: INTEGER); + BEGIN + descAdr := 0; modAdr := 0; + descAdr := AllocMem(descSize, descSize); + IF descAdr # 0 THEN + modAdr := AllocMem(modSize, modSize); + IF modAdr = 0 THEN + FreeMem(descAdr, descSize) + ELSE + INC(used, descSize + modSize) + END + END + END AllocModMem; + + PROCEDURE DeallocModMem* (descSize, modSize, descAdr, modAdr: INTEGER); + BEGIN + FreeMem(descAdr, descSize); + FreeMem(modAdr, modSize); + DEC(used, descSize + modSize) + END DeallocModMem; + + PROCEDURE InvalModMem (modSize, modAdr: INTEGER); + BEGIN + FreeMem(modAdr, modSize) + END InvalModMem; + + PROCEDURE TryRead (from, to, c: INTEGER); + VAR i: INTEGER; x: BYTE; + BEGIN + IF from <= to THEN + FOR i := from TO to DO + S.GET(i, x) + END + ELSE + FOR i := to TO from BY -1 DO + S.GET(i, x) + END + END; + END TryRead; + + PROCEDURE^ Try* (h: TryHandler; a, b, c: INTEGER); + + PROCEDURE IsReadable* (from, to: INTEGER): BOOLEAN; + VAR i: INTEGER; + BEGIN + i := trapCount; + Try(TryRead, from, to, 0); + RETURN trapCount = i + END IsReadable; + + (* --------------------- NEW implementation (portable) -------------------- *) + + PROCEDURE^ NewBlock (size: INTEGER): Block; + + PROCEDURE NewRec* (typ: INTEGER): INTEGER; (* implementation of NEW(ptr) *) + VAR size, adr: INTEGER; b: Block; tag: Type; l: FList; + BEGIN + IF ~ODD(typ) THEN + tag := S.VAL(Type, typ); + b := NewBlock(tag.size); + IF b # NIL THEN + b.tag := tag; + S.GET(typ - 4, size); + IF size # 0 THEN (* record uses a finalizer *) + l := S.VAL(FList, S.ADR(b.last)); (* anchor new object! *) + l := S.VAL(FList, NewRec(S.TYP(FList))); (* NEW(l) *) + l.blk := b; l.next := finalizers; finalizers := l + END; + adr := S.ADR(b.last) + ELSE + adr := 0 + END + ELSE + HALT(100) (* COM interface pointers not supported *) + END; + RETURN adr + END NewRec; + + PROCEDURE NewArr* (eltyp, nofelem, nofdim: INTEGER): INTEGER; (* impl. of NEW(ptr, dim0, dim1, ...) *) + VAR b: Block; size, headSize: INTEGER; t: Type; + BEGIN + CASE eltyp OF + | -1: HALT(100) (* COM interface pointers not supported *) + | 0: eltyp := S.ADR(PtrType) + | 1: eltyp := S.ADR(Char8Type) + | 2: eltyp := S.ADR(Int16Type) + | 3: eltyp := S.ADR(Int8Type) + | 4: eltyp := S.ADR(Int32Type) + | 5: eltyp := S.ADR(BoolType) + | 6: eltyp := S.ADR(SetType) + | 7: eltyp := S.ADR(Real32Type) + | 8: eltyp := S.ADR(Real64Type) + | 9: eltyp := S.ADR(Char16Type) + | 10: eltyp := S.ADR(Int64Type) + | 11: eltyp := S.ADR(ProcType) + | 12: HALT(101) (* COM interface pointers not supported *) + ELSE + ASSERT(~ODD(eltyp), 102) (* COM interface pointers not supported *) + END; + t := S.VAL(Type, eltyp); + headSize := 4 * nofdim + 12; + size := headSize + nofelem * t.size; + b := NewBlock(size); + IF b # NIL THEN + b.tag := S.VAL(Type, eltyp + 2); (* tag + array mark *) + b.last := S.ADR(b.last) + size - t.size; (* pointer to last elem *) + b.first := S.ADR(b.last) + headSize; (* pointer to first elem *) + RETURN S.ADR(b.last) + ELSE + RETURN 0 + END; + END NewArr; + + (* -------------------- handler installation (portable) --------------------- *) + + PROCEDURE ThisFinObj* (VAR id: Identifier): ANYPTR; + VAR l: FList; + BEGIN + ASSERT(id.typ # 0, 100); + l := finalizers; + WHILE l # NIL DO + IF S.VAL(INTEGER, l.blk.tag) = id.typ THEN + id.obj := S.VAL(ANYPTR, S.ADR(l.blk.last)); + IF id.Identified() THEN RETURN id.obj END + END; + l := l.next + END; + RETURN NIL + END ThisFinObj; + + PROCEDURE InstallReducer* (r: Reducer); + BEGIN + r.next := reducers; reducers := r + END InstallReducer; + + PROCEDURE InstallTrapViewer* (h: Handler); + BEGIN + trapViewer := h + END InstallTrapViewer; + + PROCEDURE InstallTrapChecker* (h: Handler); + BEGIN + trapChecker := h + END InstallTrapChecker; + + PROCEDURE PushTrapCleaner* (c: TrapCleaner); + VAR t: TrapCleaner; + BEGIN + t := trapStack; WHILE (t # NIL) & (t # c) DO t := t.next END; + ASSERT(t = NIL, 20); + c.next := trapStack; trapStack := c + END PushTrapCleaner; + + PROCEDURE PopTrapCleaner* (c: TrapCleaner); + VAR t: TrapCleaner; + BEGIN + t := NIL; + WHILE (trapStack # NIL) & (t # c) DO + t := trapStack; trapStack := trapStack.next + END + END PopTrapCleaner; + + PROCEDURE InstallCleaner* (p: Command); + VAR c: CList; + BEGIN + c := S.VAL(CList, NewRec(S.TYP(CList))); (* NEW(c) *) + c.do := p; c.trapped := FALSE; c.next := cleaners; cleaners := c + END InstallCleaner; + + PROCEDURE RemoveCleaner* (p: Command); + VAR c0, c: CList; + BEGIN + c := cleaners; c0 := NIL; + WHILE (c # NIL) & (c.do # p) DO c0 := c; c := c.next END; + IF c # NIL THEN + IF c0 = NIL THEN cleaners := cleaners.next ELSE c0.next := c.next END + END + END RemoveCleaner; + + PROCEDURE Cleanup*; + VAR c, c0: CList; + BEGIN + c := cleaners; c0 := NIL; + WHILE c # NIL DO + IF ~c.trapped THEN + c.trapped := TRUE; c.do; c.trapped := FALSE; c0 := c + ELSE + IF c0 = NIL THEN cleaners := cleaners.next + ELSE c0.next := c.next + END + END; + c := c.next + END + END Cleanup; + + (* -------------------- meta information (portable) --------------------- *) + + PROCEDURE (h: LoaderHook) ThisMod* (IN name: ARRAY OF CHAR): Module, NEW, ABSTRACT; + + PROCEDURE SetLoaderHook*(h: LoaderHook); + BEGIN + loader := h + END SetLoaderHook; + + PROCEDURE InitModule (mod: Module); (* initialize linked modules *) + VAR body: Command; + BEGIN + IF ~(dyn IN mod.opts) & (mod.next # NIL) & ~(init IN mod.next.opts) THEN InitModule(mod.next) END; + IF ~(init IN mod.opts) THEN + body := S.VAL(Command, mod.code); + INCL(mod.opts, init); + actual := mod; + body(); actual := NIL + END + END InitModule; + + PROCEDURE ThisLoadedMod* (IN name: ARRAY OF CHAR): Module; (* loaded modules only *) + VAR m: Module; res: INTEGER; n: Utf8Name; + BEGIN + StringToUtf8(name, n, res); ASSERT(res = 0); + loadres := done; + m := modList; + WHILE (m # NIL) & ((m.name # n) OR (m.refcnt < 0)) DO m := m.next END; + IF (m # NIL) & ~(init IN m.opts) THEN InitModule(m) END; + IF m = NIL THEN loadres := moduleNotFound END; + RETURN m + END ThisLoadedMod; + + PROCEDURE ThisMod* (IN name: ARRAY OF CHAR): Module; + BEGIN + IF loader # NIL THEN + loader.res := done; + RETURN loader.ThisMod(name) + ELSE + RETURN ThisLoadedMod(name) + END + END ThisMod; + + PROCEDURE LoadMod* (IN name: ARRAY OF CHAR); + VAR m: Module; + BEGIN + m := ThisMod(name) + END LoadMod; + + PROCEDURE GetLoaderResult* (OUT res: INTEGER; OUT importing, imported, object: ARRAY OF CHAR); + BEGIN + IF loader # NIL THEN + res := loader.res; + importing := loader.importing$; + imported := loader.imported$; + object := loader.object$ + ELSE + res := loadres; + importing := ""; + imported := ""; + object := "" + END + END GetLoaderResult; + + PROCEDURE ThisObject* (mod: Module; IN name: ARRAY OF CHAR): Object; + VAR l, r, m, res: INTEGER; p: StrPtr; n: Utf8Name; + BEGIN + StringToUtf8(name, n, res); ASSERT(res = 0); + l := 0; r := mod.export.num; + WHILE l < r DO (* binary search *) + m := (l + r) DIV 2; + p := S.VAL(StrPtr, S.ADR(mod.names[mod.export.obj[m].id DIV 256])); + IF p^ = n THEN RETURN S.VAL(Object, S.ADR(mod.export.obj[m])) END; + IF p^ < n THEN l := m + 1 ELSE r := m END + END; + RETURN NIL + END ThisObject; + + PROCEDURE ThisDesc* (mod: Module; fprint: INTEGER): Object; + VAR i, n: INTEGER; + BEGIN + i := 0; n := mod.export.num; + WHILE (i < n) & (mod.export.obj[i].id DIV 256 = 0) DO + IF mod.export.obj[i].offs = fprint THEN RETURN S.VAL(Object, S.ADR(mod.export.obj[i])) END; + INC(i) + END; + RETURN NIL + END ThisDesc; + + PROCEDURE ThisField* (rec: Type; IN name: ARRAY OF CHAR): Object; + VAR n, res: INTEGER; p: StrPtr; obj: Object; m: Module; nn: Utf8Name; + BEGIN + StringToUtf8(name, nn, res); ASSERT(res = 0); + m := rec.mod; + obj := S.VAL(Object, S.ADR(rec.fields.obj[0])); n := rec.fields.num; + WHILE n > 0 DO + p := S.VAL(StrPtr, S.ADR(m.names[obj.id DIV 256])); + IF p^ = nn THEN RETURN obj END; + DEC(n); INC(S.VAL(INTEGER, obj), 16) + END; + RETURN NIL + END ThisField; + + PROCEDURE ThisCommand* (mod: Module; IN name: ARRAY OF CHAR): Command; + VAR x: Object; sig: Signature; + BEGIN + x := ThisObject(mod, name); + IF (x # NIL) & (x.id MOD 16 = mProc) THEN + sig := S.VAL(Signature, x.struct); + IF (sig.retStruct = NIL) & (sig.num = 0) THEN RETURN S.VAL(Command, mod.procBase + x.offs) END + END; + RETURN NIL + END ThisCommand; + + PROCEDURE ThisType* (mod: Module; IN name: ARRAY OF CHAR): Type; + VAR x: Object; + BEGIN + x := ThisObject(mod, name); + IF (x # NIL) & (x.id MOD 16 = mTyp) & (S.VAL(INTEGER, x.struct) DIV 256 # 0) THEN + RETURN x.struct + ELSE + RETURN NIL + END + END ThisType; + + PROCEDURE TypeOf* (IN rec: ANYREC): Type; + BEGIN + RETURN S.VAL(Type, S.TYP(rec)) + END TypeOf; + + PROCEDURE LevelOf* (t: Type): SHORTINT; + BEGIN + RETURN SHORT(t.id DIV 16 MOD 16) + END LevelOf; + + PROCEDURE NewObj* (VAR o: S.PTR; t: Type); + VAR i: INTEGER; + BEGIN + IF t.size = -1 THEN o := NIL + ELSE + i := 0; WHILE t.ptroffs[i] >= 0 DO INC(i) END; + IF t.ptroffs[i+1] >= 0 THEN INC(S.VAL(INTEGER, t)) END; (* with interface pointers *) + o := S.VAL(S.PTR, NewRec(S.VAL(INTEGER, t))) (* generic NEW *) + END + END NewObj; + + PROCEDURE GetModName* (mod: Module; OUT name: Name); + VAR res: INTEGER; + BEGIN + Utf8ToString(mod.name, name, res); ASSERT(res = 0) + END GetModName; + + PROCEDURE GetObjName* (mod: Module; obj: Object; OUT name: Name); + VAR p: StrPtr; res: INTEGER; + BEGIN + p := S.VAL(StrPtr, S.ADR(mod.names[obj.id DIV 256])); + Utf8ToString(p^$, name, res); ASSERT(res = 0) + END GetObjName; + + PROCEDURE GetTypeName* (t: Type; OUT name: Name); + VAR p: StrPtr; res: INTEGER; + BEGIN + p := S.VAL(StrPtr, S.ADR(t.mod.names[t.id DIV 256])); + Utf8ToString(p^$, name, res); ASSERT(res = 0) + END GetTypeName; + + PROCEDURE RegisterMod* (mod: Module); + VAR i: INTEGER; epoch: time.time_t; tm: time.struct_tm; ptm: time.Pstruct_tm; + BEGIN + mod.next := modList; modList := mod; mod.refcnt := 0; INCL(mod.opts, dyn); i := 0; + WHILE i < mod.nofimps DO + IF mod.imports[i] # NIL THEN INC(mod.imports[i].refcnt) END; + INC(i) + END; + epoch := time.time(NIL); + ptm := time.localtime_r(epoch, tm); + IF ptm # NIL THEN + mod.loadTime[0] := SHORT(tm.tm_year + 1900); + mod.loadTime[1] := SHORT(tm.tm_mon + 1); + mod.loadTime[2] := SHORT(tm.tm_mday); + mod.loadTime[3] := SHORT(tm.tm_hour); + mod.loadTime[4] := SHORT(tm.tm_min); + mod.loadTime[5] := SHORT(tm.tm_sec) + ELSE + mod.loadTime[0] := 0; + mod.loadTime[1] := 0; + mod.loadTime[2] := 0; + mod.loadTime[3] := 0; + mod.loadTime[4] := 0; + mod.loadTime[5] := 0 + END; + IF ~(init IN mod.opts) THEN InitModule(mod) END + END RegisterMod; + + PROCEDURE^ Collect*; + + PROCEDURE UnloadMod* (mod: Module); + VAR i: INTEGER; t: Command; + BEGIN + IF mod.refcnt = 0 THEN + t := mod.term; mod.term := NIL; + IF t # NIL THEN t() END; (* terminate module *) + i := 0; + WHILE i < mod.nofptrs DO (* release global pointers *) + S.PUT(mod.varBase + mod.ptrs[i], 0); INC(i) + END; + Collect; (* call finalizers *) + i := 0; + WHILE i < mod.nofimps DO (* release imported modules *) + IF mod.imports[i] # NIL THEN DEC(mod.imports[i].refcnt) END; + INC(i) + END; + mod.refcnt := -1; + IF dyn IN mod.opts THEN (* release memory *) + InvalModMem(mod.data + mod.dsize - mod.refs, mod.refs) + END + END + END UnloadMod; + + (* -------------------- dynamic procedure call --------------------- *) + + PROCEDURE Call* (adr: INTEGER; sig: Signature; IN par: ARRAY OF INTEGER; n: INTEGER): LONGINT; + BEGIN + HALT(126); (* !!! *) + RETURN 0 + END Call; + + (* -------------------- reference information (portable) --------------------- *) + + PROCEDURE RefCh (VAR ref: INTEGER; OUT ch: SHORTCHAR); + BEGIN + S.GET(ref, ch); INC(ref) + END RefCh; + + PROCEDURE RefNum (VAR ref: INTEGER; OUT x: INTEGER); + VAR s, n: INTEGER; ch: SHORTCHAR; + BEGIN + s := 0; n := 0; RefCh(ref, ch); + WHILE ORD(ch) >= 128 DO INC(n, ASH(ORD(ch) - 128, s) ); INC(s, 7); RefCh(ref, ch) END; + x := n + ASH(ORD(ch) MOD 64 - ORD(ch) DIV 64 * 64, s) + END RefNum; + + PROCEDURE RefName (VAR ref: INTEGER; OUT n: Utf8Name); + VAR i: INTEGER; ch: SHORTCHAR; + BEGIN + i := 0; RefCh(ref, ch); + WHILE ch # 0X DO n[i] := ch; INC(i); RefCh(ref, ch) END; + n[i] := 0X + END RefName; + + PROCEDURE GetRefProc* (VAR ref: INTEGER; OUT adr: INTEGER; OUT name: Utf8Name); + VAR ch: SHORTCHAR; + BEGIN + S.GET(ref, ch); + WHILE ch >= 0FDX DO (* skip variables *) + INC(ref); RefCh(ref, ch); + IF ch = 10X THEN INC(ref, 4) END; + RefNum(ref, adr); RefName(ref, name); S.GET(ref, ch) + END; + WHILE (ch > 0X) & (ch < 0FCX) DO (* skip source refs *) + INC(ref); RefNum(ref, adr); S.GET(ref, ch) + END; + IF ch = 0FCX THEN INC(ref); RefNum(ref, adr); RefName(ref, name) + ELSE adr := 0 + END + END GetRefProc; + + PROCEDURE GetRefVar* (VAR ref: INTEGER; OUT mode, form: SHORTCHAR; OUT desc: Type; OUT adr: INTEGER; OUT name: Utf8Name); + BEGIN + S.GET(ref, mode); desc := NIL; + IF mode >= 0FDX THEN + mode := SHORT(CHR(ORD(mode) - 0FCH)); + INC(ref); RefCh(ref, form); + IF form = 10X THEN + S.GET(ref, desc); INC(ref, 4); form := SHORT(CHR(16 + desc.id MOD 4)) + END; + RefNum(ref, adr); RefName(ref, name) + ELSE + mode := 0X; form := 0X; adr := 0 + END + END GetRefVar; + + PROCEDURE SourcePos* (mod: Module; codePos: INTEGER): INTEGER; + VAR ref, pos, ad, d: INTEGER; ch: SHORTCHAR; name: Utf8Name; + BEGIN + IF mod # NIL THEN (* mf, 12.02.04 *) + ref := mod.refs; pos := 0; ad := 0; S.GET(ref, ch); + WHILE ch # 0X DO + WHILE (ch > 0X) & (ch < 0FCX) DO (* srcref: {dAdr,dPos} *) + INC(ad, ORD(ch)); INC(ref); RefNum(ref, d); + IF ad > codePos THEN RETURN pos END; + INC(pos, d); S.GET(ref, ch) + END; + IF ch = 0FCX THEN (* proc: 0FCX,Adr,Name *) + INC(ref); RefNum(ref, d); RefName(ref, name); S.GET(ref, ch); + IF (d > codePos) & (pos > 0) THEN RETURN pos END + END; + WHILE ch >= 0FDX DO (* skip variables: Mode, Form, adr, Name *) + INC(ref); RefCh(ref, ch); + IF ch = 10X THEN INC(ref, 4) END; + RefNum(ref, d); RefName(ref, name); S.GET(ref, ch) + END + END; + END; + RETURN -1 + END SourcePos; + + PROCEDURE LoadDll* (IN name: ARRAY OF CHAR; VAR ok: BOOLEAN); + VAR h: ADDRESS; file: Utf8Name; res: INTEGER; + BEGIN + StringToUtf8(name, file, res); + IF res = 0 THEN + h := dlfcn.dlopen(file, dlfcn.RTLD_LAZY + dlfcn.RTLD_GLOBAL); + ok := h # 0 + ELSE + ok := FALSE + END + END LoadDll; + + PROCEDURE ThisDllObj* (mode, fprint: INTEGER; IN dll, name: ARRAY OF CHAR): INTEGER; + VAR h, p: ADDRESS; file, sym: Utf8Name; res: INTEGER; err: dlfcn.int; + BEGIN + StringToUtf8(dll, file, res); + IF res = 0 THEN + h := dlfcn.dlopen(file, dlfcn.RTLD_LAZY + dlfcn.RTLD_GLOBAL); + IF h # 0 THEN + StringToUtf8(name, sym, res); + IF res = 0 THEN + p := dlfcn.dlsym(h, sym) + ELSE + p := 0 + END; + err := dlfcn.dlclose(h); + ASSERT(err = 0, 100) + ELSE + p := 0 + END + ELSE + p := 0 + END; + RETURN p + END ThisDllObj; + + (* -------------------- garbage collector (portable) --------------------- *) + + PROCEDURE Mark (this: Block); + VAR father, son: Block; tag: Type; flag, offset, actual: INTEGER; + BEGIN + IF ~ODD(S.VAL(INTEGER, this.tag)) THEN + father := NIL; + LOOP + INC(S.VAL(INTEGER, this.tag)); + flag := S.VAL(INTEGER, this.tag) MOD 4; + tag := S.VAL(Type, S.VAL(INTEGER, this.tag) - flag); + IF flag >= 2 THEN actual := this.first; this.actual := actual + ELSE actual := S.ADR(this.last) + END; + LOOP + offset := tag.ptroffs[0]; + IF offset < 0 THEN + INC(S.VAL(INTEGER, tag), offset + 4); (* restore tag *) + IF (flag >= 2) & (actual < this.last) & (offset < -4) THEN (* next array element *) + INC(actual, tag.size); this.actual := actual + ELSE (* up *) + this.tag := S.VAL(Type, S.VAL(INTEGER, tag) + flag); + IF father = NIL THEN RETURN END; + son := this; this := father; + flag := S.VAL(INTEGER, this.tag) MOD 4; + tag := S.VAL(Type, S.VAL(INTEGER, this.tag) - flag); + offset := tag.ptroffs[0]; + IF flag >= 2 THEN actual := this.actual ELSE actual := S.ADR(this.last) END; + S.GET(actual + offset, father); S.PUT(actual + offset, S.ADR(son.last)); + INC(S.VAL(INTEGER, tag), 4) + END + ELSE + S.GET(actual + offset, son); + IF son # NIL THEN + DEC(S.VAL(INTEGER, son), 4); + IF ~ODD(S.VAL(INTEGER, son.tag)) THEN (* down *) + this.tag := S.VAL(Type, S.VAL(INTEGER, tag) + flag); + S.PUT(actual + offset, father); father := this; this := son; + EXIT + END + END; + INC(S.VAL(INTEGER, tag), 4) + END + END + END + END + END Mark; + + PROCEDURE MarkGlobals; + VAR m: Module; i, p: INTEGER; + BEGIN + m := modList; + WHILE m # NIL DO + IF m.refcnt >= 0 THEN + i := 0; + WHILE i < m.nofptrs DO + S.GET(m.varBase + m.ptrs[i], p); INC(i); + IF p # 0 THEN Mark(S.VAL(Block, p - 4)) END + END + END; + m := m.next + END + END MarkGlobals; + + PROCEDURE Next (b: Block): Block; (* next block in same cluster *) + VAR size: INTEGER; + BEGIN + S.GET(S.VAL(INTEGER, b.tag) DIV 4 * 4, size); + IF ODD(S.VAL(INTEGER, b.tag) DIV 2) THEN INC(size, b.last - S.ADR(b.last)) END; + RETURN S.VAL(Block, S.VAL(INTEGER, b) + (size + 19) DIV 16 * 16) + END Next; + + PROCEDURE CheckCandidates; + (* pre: nofcand > 0 *) + VAR i, j, h, p, end: INTEGER; c: Cluster; blk, next: Block; + BEGIN + (* sort candidates (shellsort) *) + h := 1; REPEAT h := h*3 + 1 UNTIL h > nofcand; + REPEAT h := h DIV 3; i := h; + WHILE i < nofcand DO p := candidates[i]; j := i; + WHILE (j >= h) & (candidates[j-h] > p) DO + candidates[j] := candidates[j-h]; j := j-h + END; + candidates[j] := p; INC(i) + END + UNTIL h = 1; + (* sweep *) + c := root; i := 0; + WHILE c # NIL DO + blk := S.VAL(Block, S.VAL(INTEGER, c) + 12); + end := S.VAL(INTEGER, blk) + (c.size - 12) DIV 16 * 16; + WHILE candidates[i] < S.VAL(INTEGER, blk) DO + INC(i); + IF i = nofcand THEN RETURN END + END; + WHILE S.VAL(INTEGER, blk) < end DO + next := Next(blk); + IF candidates[i] < S.VAL(INTEGER, next) THEN + IF (S.VAL(INTEGER, blk.tag) # S.ADR(blk.last)) (* not a free block *) + & (~strictStackSweep OR (candidates[i] = S.ADR(blk.last))) THEN + Mark(blk) + END; + REPEAT + INC(i); + IF i = nofcand THEN RETURN END + UNTIL candidates[i] >= S.VAL(INTEGER, next) + END; + IF (S.VAL(INTEGER, blk.tag) MOD 4 = 0) & (S.VAL(INTEGER, blk.tag) # S.ADR(blk.last)) + & (blk.tag.base[0] = NIL) & (blk.actual > 0) THEN (* referenced interface record *) + Mark(blk) + END; + blk := next + END; + c := c.next + END + END CheckCandidates; + + PROCEDURE MarkLocals; + VAR sp, p, min, max: INTEGER; c: Cluster; + BEGIN + sp := S.ADR(sp); nofcand := 0; c := root; + WHILE c.next # NIL DO c := c.next END; + min := S.VAL(INTEGER, root); max := S.VAL(INTEGER, c) + c.size; + WHILE sp < baseStack DO + S.GET(sp, p); + IF (p > min) & (p < max) & (~strictStackSweep OR (p MOD 16 = 0)) THEN + candidates[nofcand] := p; INC(nofcand); + IF nofcand = LEN(candidates) - 1 THEN CheckCandidates; nofcand := 0 END + END; + INC(sp, 4) + END; + candidates[nofcand] := max; INC(nofcand); (* ensure complete scan for interface mark*) + IF nofcand > 0 THEN CheckCandidates END + END MarkLocals; + + PROCEDURE MarkFinObj; + VAR f: FList; + BEGIN + wouldFinalize := FALSE; + f := finalizers; + WHILE f # NIL DO + IF ~ODD(S.VAL(INTEGER, f.blk.tag)) THEN wouldFinalize := TRUE END; + Mark(f.blk); + f := f.next + END; + f := hotFinalizers; + WHILE f # NIL DO IF ~ODD(S.VAL(INTEGER, f.blk.tag)) THEN wouldFinalize := TRUE END; + Mark(f.blk); + f := f.next + END + END MarkFinObj; + + PROCEDURE CheckFinalizers; + VAR f, g, h, k: FList; + BEGIN + f := finalizers; g := NIL; + IF hotFinalizers = NIL THEN k := NIL + ELSE + k := hotFinalizers; + WHILE k.next # NIL DO k := k.next END + END; + WHILE f # NIL DO + h := f; f := f.next; + IF ~ODD(S.VAL(INTEGER, h.blk.tag)) THEN + IF g = NIL THEN finalizers := f ELSE g.next := f END; + IF k = NIL THEN hotFinalizers := h ELSE k.next := h END; + k := h; h.next := NIL + ELSE g := h + END + END; + h := hotFinalizers; + WHILE h # NIL DO Mark(h.blk); h := h.next END + END CheckFinalizers; + + PROCEDURE ExecFinalizer (a, b, c: INTEGER); + VAR f: FList; fin: PROCEDURE(this: ANYPTR); + BEGIN + f := S.VAL(FList, a); + S.GET(S.VAL(INTEGER, f.blk.tag) - 4, fin); (* method 0 *) + IF (fin # NIL) & (f.blk.tag.mod.refcnt >= 0) THEN fin(S.VAL(ANYPTR, S.ADR(f.blk.last))) END; + END ExecFinalizer; + + PROCEDURE^ Try* (h: TryHandler; a, b, c: INTEGER); (* COMPILER DEPENDENT *) + + PROCEDURE CallFinalizers; + VAR f: FList; + BEGIN + WHILE hotFinalizers # NIL DO + f := hotFinalizers; hotFinalizers := hotFinalizers.next; + Try(ExecFinalizer, S.VAL(INTEGER, f), 0, 0) + END; + wouldFinalize := FALSE + END CallFinalizers; + + PROCEDURE Insert (blk: FreeBlock; size: INTEGER); (* insert block in free list *) + VAR i: INTEGER; + BEGIN + blk.size := size - 4; blk.tag := S.VAL(Type, S.ADR(blk.size)); + i := MIN(N - 1, (blk.size DIV 16)); + blk.next := free[i]; free[i] := blk + END Insert; + + PROCEDURE Sweep (dealloc: BOOLEAN); + VAR cluster, last, c: Cluster; blk, next: Block; fblk, b, t: FreeBlock; end, i: INTEGER; + BEGIN + cluster := root; last := NIL; allocated := 0; + i := N; + REPEAT DEC(i); free[i] := sentinel UNTIL i = 0; + WHILE cluster # NIL DO + blk := S.VAL(Block, S.VAL(INTEGER, cluster) + 12); + end := S.VAL(INTEGER, blk) + (cluster.size - 12) DIV 16 * 16; + fblk := NIL; + WHILE S.VAL(INTEGER, blk) < end DO + next := Next(blk); + IF ODD(S.VAL(INTEGER, blk.tag)) THEN + IF fblk # NIL THEN + Insert(fblk, S.VAL(INTEGER, blk) - S.VAL(INTEGER, fblk)); + fblk := NIL + END; + DEC(S.VAL(INTEGER, blk.tag)); (* unmark *) + INC(allocated, S.VAL(INTEGER, next) - S.VAL(INTEGER, blk)) + ELSIF fblk = NIL THEN + fblk := S.VAL(FreeBlock, blk) + END; + blk := next + END; + IF dealloc & (S.VAL(INTEGER, fblk) = S.VAL(INTEGER, cluster) + 12) THEN (* deallocate cluster *) + c := cluster; cluster := cluster.next; + IF last = NIL THEN root := cluster ELSE last.next := cluster END; + FreeHeapMem(c) + ELSE + IF fblk # NIL THEN Insert(fblk, end - S.VAL(INTEGER, fblk)) END; + last := cluster; cluster := cluster.next + END + END; + (* reverse free list *) + i := N; + REPEAT + DEC(i); + b := free[i]; fblk := sentinel; + WHILE b # sentinel DO t := b; b := t.next; t.next := fblk; fblk := t END; + free[i] := fblk + UNTIL i = 0 + END Sweep; + + PROCEDURE Collect*; + BEGIN + IF root # NIL THEN + CallFinalizers; (* trap cleanup *) + MarkGlobals; + MarkLocals; + CheckFinalizers; + Sweep(TRUE); + CallFinalizers + END + END Collect; + + PROCEDURE FastCollect*; + BEGIN + IF root # NIL THEN + MarkGlobals; + MarkLocals; + MarkFinObj; + Sweep(FALSE) + END + END FastCollect; + + PROCEDURE WouldFinalize* (): BOOLEAN; + BEGIN + RETURN wouldFinalize + END WouldFinalize; + + (* --------------------- memory allocation (portable) -------------------- *) + + PROCEDURE OldBlock (size: INTEGER): FreeBlock; (* size MOD 16 = 0 *) + VAR b, l: FreeBlock; s, i: INTEGER; + BEGIN + s := size - 4; + i := MIN(N - 1, s DIV 16); + WHILE (i # N - 1) & (free[i] = sentinel) DO INC(i) END; + b := free[i]; l := NIL; + WHILE b.size < s DO l := b; b := b.next END; + IF b # sentinel THEN + IF l = NIL THEN free[i] := b.next ELSE l.next := b.next END + ELSE b := NIL + END; + RETURN b + END OldBlock; + + PROCEDURE LastBlock (limit: INTEGER): FreeBlock; (* size MOD 16 = 0 *) + VAR b, l: FreeBlock; s, i: INTEGER; + BEGIN + s := limit - 4; + i := 0; + REPEAT + b := free[i]; l := NIL; + WHILE (b # sentinel) & (S.VAL(INTEGER, b) + b.size # s) DO l := b; b := b.next END; + IF b # sentinel THEN + IF l = NIL THEN free[i] := b.next ELSE l.next := b.next END + ELSE b := NIL + END; + INC(i) + UNTIL (b # NIL) OR (i = N); + RETURN b + END LastBlock; + + PROCEDURE NewBlock (size: INTEGER): Block; + VAR tsize, a, s: INTEGER; b: FreeBlock; new, c: Cluster; r: Reducer; + BEGIN + ASSERT(size >= 0, 20); + IF size > MAX(INTEGER) - 19 THEN RETURN NIL END; + tsize := (size + 19) DIV 16 * 16; + b := OldBlock(tsize); (* 1) search for free block *) + IF b = NIL THEN + FastCollect; b := OldBlock(tsize); (* 2) collect *) + IF b = NIL THEN + Collect; b := OldBlock(tsize); (* 2a) fully collect *) + END; + IF b = NIL THEN + AllocHeapMem(tsize + 12, new); (* 3) allocate new cluster *) + IF new # NIL THEN + IF (root = NIL) OR (S.VAL(INTEGER, new) < S.VAL(INTEGER, root)) THEN + new.next := root; root := new + ELSE + c := root; + WHILE (c.next # NIL) & (S.VAL(INTEGER, new) > S.VAL(INTEGER, c.next)) DO c := c.next END; + new.next := c.next; c.next := new + END; + b := S.VAL(FreeBlock, S.VAL(INTEGER, new) + 12); + b.size := (new.size - 12) DIV 16 * 16 - 4 + ELSE + RETURN NIL (* 4) give up *) + END + END + END; + (* b # NIL *) + a := b.size + 4 - tsize; + IF a > 0 THEN Insert(S.VAL(FreeBlock, S.VAL(INTEGER, b) + tsize), a) END; + IF size > 0 THEN Erase(S.ADR(b.size), (size + 3) DIV 4) END; + INC(allocated, tsize); + RETURN S.VAL(Block, b) + END NewBlock; + + PROCEDURE Allocated* (): INTEGER; + BEGIN + RETURN allocated + END Allocated; + + PROCEDURE Used* (): INTEGER; + BEGIN + RETURN used + END Used; + + PROCEDURE Root* (): INTEGER; + BEGIN + RETURN S.VAL(INTEGER, root) + END Root; + + (* -------------------- Trap Handling --------------------- *) + + PROCEDURE [code] GetDLink (): DLink "(Kernel_DLink)SYSTEM_dlink"; + PROCEDURE [code] SetDLink (dl: DLink) "SYSTEM_dlink = (SYSTEM_DLINK*)dl"; + + PROCEDURE Start* (code: Command); + VAR res: setjmp.int; dl: DLink; + BEGIN + restart := code; + baseStack := S.ADR(code); (* XXX: expected that target uses one stack *) + startDLink := GetDLink(); + res := setjmp.sigsetjmp(startEnv, 1); + restart + END Start; + + PROCEDURE Quit* (exitCode: INTEGER); + VAR m: Module; term: Command; t: BOOLEAN; + BEGIN + trapViewer := NIL; trapChecker := NIL; restart := NIL; + t := terminating; terminating := TRUE; m := modList; + WHILE m # NIL DO (* call terminators *) + IF ~static OR ~t THEN + term := m.term; m.term := NIL; + IF term # NIL THEN term() END + END; + m := m.next + END; + CallFinalizers; + hotFinalizers := finalizers; finalizers := NIL; + CallFinalizers; + stdlib.exit(exitCode) + END Quit; + + PROCEDURE FatalError* (id: INTEGER; str: ARRAY OF CHAR); + VAR res: stdio.int; title: ARRAY 16 OF CHAR; text: ARRAY 256 OF SHORTCHAR; + BEGIN + title := "Error xy"; + title[6] := CHR(id DIV 10 + ORD("0")); + title[7] := CHR(id MOD 10 + ORD("0")); + res := unistd.write(2, S.ADR(title), 8); + stdlib.abort + END FatalError; + + PROCEDURE DefaultTrapViewer; + VAR out: ARRAY 256 OF SHORTCHAR; c, len: INTEGER; res: unistd.int; dl: DLink; + + PROCEDURE WriteString (IN s: ARRAY OF SHORTCHAR); + VAR i: INTEGER; + BEGIN + i := 0; + WHILE (len < LEN(out) - 1) & (s[i] # 0X) DO out[len] := s[i]; INC(i); INC(len) END + END WriteString; + + PROCEDURE WriteHex (x, n: INTEGER); + VAR i, y: INTEGER; + BEGIN + IF len + n < LEN(out) THEN + i := len + n - 1; + WHILE i >= len DO + y := x MOD 16; x := x DIV 16; + IF y > 9 THEN y := y + (ORD("A") - ORD("0") - 10) END; + out[i] := SHORT(CHR(y + ORD("0"))); DEC(i) + END; + INC(len, n) + END + END WriteHex; + + PROCEDURE WriteLn; + BEGIN + IF len < LEN(out) - 1 THEN out[len] := 0AX; INC(len) END + END WriteLn; + + BEGIN + len := 0; + WriteString("====== "); + IF err = 129 THEN WriteString("invalid with") + ELSIF err = 130 THEN WriteString("invalid case") + ELSIF err = 131 THEN WriteString("function without return") + ELSIF err = 132 THEN WriteString("type guard") + ELSIF err = 133 THEN WriteString("implied type guard") + ELSIF err = 134 THEN WriteString("value out of range") + ELSIF err = 135 THEN WriteString("index out of range") + ELSIF err = 136 THEN WriteString("string too long") + ELSIF err = 137 THEN WriteString("stack overflow") + ELSIF err = 138 THEN WriteString("integer overflow") + ELSIF err = 139 THEN WriteString("division by zero") + ELSIF err = 140 THEN WriteString("infinite real result") + ELSIF err = 141 THEN WriteString("real underflow") + ELSIF err = 142 THEN WriteString("real overflow") + ELSIF err = 143 THEN WriteString("undefined real result") + ELSIF err = 144 THEN WriteString("not a number") + ELSIF err = 200 THEN WriteString("keyboard interrupt") + ELSIF err = 201 THEN WriteString("NIL dereference") + ELSIF err = 202 THEN WriteString("illegal instruction: "); + WriteHex(val, 4) + ELSIF err = 203 THEN WriteString("illegal memory read [ad = "); + WriteHex(val, 8); WriteString("]") + ELSIF err = 204 THEN WriteString("illegal memory write [ad = "); + WriteHex(val, 8); WriteString("]") + ELSIF err = 205 THEN WriteString("illegal execution [ad = "); + WriteHex(val, 8); WriteString("]") + ELSIF err = 257 THEN WriteString("out of memory") + ELSIF err = 10001H THEN WriteString("bus error") + ELSIF err = 10002H THEN WriteString("address error") + ELSIF err = 10007H THEN WriteString("fpu error") + ELSIF err < 0 THEN WriteString("exception #"); WriteHex(-err, 2) + ELSE err := err DIV 100 * 256 + err DIV 10 MOD 10 * 16 + err MOD 10; + WriteString("trap #"); WriteHex(err, 3) + END; + WriteString(" ======"); + WriteLn; + dl := GetDLink(); + (* skip Kernel.DefaultTrapViewer & Kernel.Trap/Kernel.TrapHandler *) + c := 2; + WHILE (c > 0) & (dl # NIL) DO + dl := dl.next; + DEC(c) + END; + (* stack trace *) + c := 16; + WHILE (c > 0) & (dl # NIL) DO + WriteString("- "); WriteString(dl.name$); WriteLn; + dl := dl.next; + DEC(c) + END; + out[len] := 0X; + res := unistd.write(2, S.ADR(out), len) + END DefaultTrapViewer; + + PROCEDURE TrapCleanup; + VAR t: TrapCleaner; + BEGIN + WHILE trapStack # NIL DO + t := trapStack; trapStack := trapStack.next; t.Cleanup + END; + IF (trapChecker # NIL) & (err # 128) THEN trapChecker END + END TrapCleanup; + + PROCEDURE SetTrapGuard* (on: BOOLEAN); + BEGIN + guarded := on + END SetTrapGuard; + + PROCEDURE Try* (h: TryHandler; a, b, c: INTEGER); + VAR oldIsTry: BOOLEAN; oldTryEnv: setjmp.jmp_buf; oldTryDLink: DLink; res: setjmp.int; + BEGIN + oldIsTry := isTry; oldTryEnv := tryEnv; oldTryDLink := tryDLink; + isTry := TRUE; tryDLink := GetDLink(); + res := setjmp._setjmp(tryEnv); + IF res = 0 THEN h(a, b, c) END; + isTry := oldIsTry; tryEnv := oldTryEnv; tryDLink := oldTryDLink + END Try; + + PROCEDURE Trap* (n: INTEGER); + BEGIN + IF trapped THEN + DefaultTrapViewer; + IF ~secondTrap THEN trapped := FALSE; secondTrap := TRUE END + END; + IF n >= 0 THEN err := n + ELSE err := -n + 128 + END; + pc := 0; sp := 0; fp := 0; stack := 0; val := 0; + INC(trapCount); + (* !!! InitFPU *) + TrapCleanup; + IF isTry THEN + SetDLink(tryDLink); + setjmp._longjmp(tryEnv, 1) + END; + IF err = 128 THEN (* do nothing *) + ELSIF (trapViewer # NIL) & (restart # NIL) & ~trapped & ~guarded THEN + trapped := TRUE; trapViewer() + ELSE DefaultTrapViewer + END; + trapped := FALSE; secondTrap := FALSE; + IF restart # NIL THEN + SetDLink(startDLink); + setjmp.siglongjmp(startEnv, 1) + END; + stdlib.abort + END Trap; + + PROCEDURE [ccall] TrapHandler (signo: signal.int; IN _info: signal.siginfo_t; context: ADDRESS); + TYPE SigInfo = POINTER [untagged] TO signal._siginfo_t; + VAR res: signal.int; info: SigInfo; + BEGIN + info := S.VAL(SigInfo, S.ADR(_info)); (* !!! hack for CPfront *) + IF trapped THEN + DefaultTrapViewer; + IF ~secondTrap THEN trapped := FALSE; secondTrap := TRUE END + END; + err := -signo; pc := 0; sp := 0; fp := 0; stack := 0; val := 0; + CASE signo OF + | signal.SIGFPE: + pc := info.si_addr; + val := info.si_code; + CASE info.si_code OF + | signal.FPE_INTDIV: err := 139 (* division by zero *) + | signal.FPE_INTOVF: err := 138 (* integer overflow *) + | signal.FPE_FLTDIV: err := 140 (* fpu: division by zero *) + | signal.FPE_FLTOVF: err := 142 (* fpu: overflow *) + | signal.FPE_FLTUND: err := 141 (* fpu: underflow *) + (* !!! | signal.FPE_FLTRES: err := ??? (* fpu: *) *) + | signal.FPE_FLTINV: err := 143 (* val := opcode *) (* fpu: invalid op *) + (* !!! | signal.FPE_FLTSUB: err := ??? (* fpu: *) *) + ELSE (* unknown *) + END + | signal.SIGINT: + val := info.si_code; + err := 200 (* keyboard interrupt *) + | signal.SIGSEGV: + val := info.si_addr; + err := 203 (* illigal read *) + | signal.SIGBUS: + val := info.si_addr; + err := 10001H (* bus error *) + | signal.SIGILL: + pc := info.si_addr; + err := 202; (* illigal instruction *) + IF IsReadable(pc, pc + 4) THEN + S.GET(pc, val) + (* !!! err := halt code *) + END; + ELSE (* unknown *) + END; + INC(trapCount); + (* !!! InitFPU *) + TrapCleanup; + IF isTry THEN + SetDLink(tryDLink); + setjmp._longjmp(tryEnv, 1) + END; + IF err = 128 THEN (* do nothing *) + ELSIF (trapViewer # NIL) & (restart # NIL) & ~trapped & ~guarded THEN + trapped := TRUE; trapViewer() + ELSE DefaultTrapViewer + END; + trapped := FALSE; secondTrap := FALSE; + IF restart # NIL THEN + SetDLink(startDLink); + setjmp.siglongjmp(startEnv, 1) + END; + stdlib.abort + END TrapHandler; + + (* -------------------- Initialization --------------------- *) + + PROCEDURE InstallTrap (signo: signal.int); + VAR act: signal._struct_sigaction; (* !!! CPfront hack *) res: signal.int; + BEGIN + act.sa_handler := NIL; + res := signal.sigemptyset(act.sa_mask); + act.sa_flags := signal.SA_NODEFER + signal.SA_SIGINFO; + act.sa_sigaction := TrapHandler; + res := signal.sigaction(signo, S.VAL(signal.struct_sigaction, act), NIL); + END InstallTrap; + + PROCEDURE InstallTrapVectors; + BEGIN + InstallTrap(signal.SIGFPE); + InstallTrap(signal.SIGINT); + InstallTrap(signal.SIGSEGV); + InstallTrap(signal.SIGBUS); + InstallTrap(signal.SIGILL) + END InstallTrapVectors; + + PROCEDURE RemoveTrapVectors; + END RemoveTrapVectors; + + PROCEDURE Init; + VAR i: INTEGER; + BEGIN + baseStack := S.ADR(i); (* XXX *) + pagesize := unistd.sysconf(unistd._SC_PAGESIZE); + + (* init heap *) + allocated := 0; total := 0; used := 0; + sentinelBlock.size := MAX(INTEGER); + sentinel := S.ADR(sentinelBlock); + i := N; + REPEAT DEC(i); free[i] := sentinel UNTIL i = 0; + + IF ~inDll THEN + InstallTrapVectors + END; + + (* !!! InitFPU *) + IF ~static THEN + InitModule(modList); + IF ~inDll THEN Quit(1) END + END + END Init; + + PROCEDURE [code] SYSTEM_argCount (): INTEGER "SYSTEM_argCount"; + PROCEDURE [code] SYSTEM_argVector (): ArrStrPtr "(Kernel_ArrStrPtr)SYSTEM_argVector"; + PROCEDURE [code] SYSTEM_modlist (): Module "(Kernel_Module)SYSTEM_modlist"; + +BEGIN + IF modList = NIL THEN (* only once *) + argc := SYSTEM_argCount(); + argv := SYSTEM_argVector(); + modList := SYSTEM_modlist(); + static := init IN modList.opts; + inDll := dll IN modList.opts; + Init + END +CLOSE + IF ~terminating THEN + terminating := TRUE; + Quit(0) + END +END Kernel. diff --git a/src/cpfront/posix/System/Mod/Math.cp b/src/cpfront/posix/System/Mod/Math.cp new file mode 100644 index 0000000..494b12a --- /dev/null +++ b/src/cpfront/posix/System/Mod/Math.cp @@ -0,0 +1,231 @@ +MODULE Math; + + IMPORT SYSTEM; + + VAR + eps, e: REAL; + + PROCEDURE [code] IncludeMATH "#include "; + PROCEDURE [code] M_PI (): REAL "M_PI"; + PROCEDURE [code] sqrt (x: REAL): REAL "sqrt(x)"; + PROCEDURE [code] exp (x: REAL): REAL "exp(x)"; + PROCEDURE [code] log (x: REAL): REAL "log(x)"; + PROCEDURE [code] log10 (x: REAL): REAL "log10(x)"; + PROCEDURE [code] pow (x, y: REAL): REAL "pow(x, y)"; + PROCEDURE [code] sin (x: REAL): REAL "sin(x)"; + PROCEDURE [code] cos (x: REAL): REAL "cos(x)"; + PROCEDURE [code] tan (x: REAL): REAL "tan(x)"; + PROCEDURE [code] asin (x: REAL): REAL "asin(x)"; + PROCEDURE [code] acos (x: REAL): REAL "acos(x)"; + PROCEDURE [code] atan (x: REAL): REAL "atan(x)"; + PROCEDURE [code] atan2 (y, x: REAL): REAL "atan2(y, x)"; + PROCEDURE [code] sinh (x: REAL): REAL "sinh(x)"; + PROCEDURE [code] cosh (x: REAL): REAL "cosh(x)"; + PROCEDURE [code] tanh (x: REAL): REAL "tanh(x)"; + PROCEDURE [code] asinh (x: REAL): REAL "asinh(x)"; + PROCEDURE [code] acosh (x: REAL): REAL "acosh(x)"; + PROCEDURE [code] atanh (x: REAL): REAL "atanh(x)"; + PROCEDURE [code] floor (x: REAL): REAL "floor(x)"; + PROCEDURE [code] ceil (x: REAL): REAL "ceil(x)"; + PROCEDURE [code] round (x: REAL): REAL "round(x)"; + PROCEDURE [code] trunc (x: REAL): REAL "trunc(x)"; + PROCEDURE [code] copysign (x, y: REAL): REAL "copysign(x, y)"; + PROCEDURE [code] frexp (x: REAL; OUT exp: INTEGER): REAL "frexp(x, exp)"; + PROCEDURE [code] ldexp (x: REAL; exp: INTEGER): REAL "ldexp(x, exp)"; + + PROCEDURE Pi* (): REAL; + BEGIN + RETURN M_PI() + END Pi; + + PROCEDURE Eps* (): REAL; + BEGIN + RETURN eps + END Eps; + + PROCEDURE Sqrt* (x: REAL): REAL; + BEGIN + RETURN sqrt(x) + END Sqrt; + + PROCEDURE Exp* (x: REAL): REAL; + BEGIN + RETURN exp(x) + END Exp; + + PROCEDURE Ln* (x: REAL): REAL; + BEGIN + RETURN log(x) + END Ln; + + PROCEDURE Log* (x: REAL): REAL; + BEGIN + RETURN log10(x) + END Log; + + PROCEDURE Power* (x, y: REAL): REAL; + BEGIN + RETURN pow(x, y) + END Power; + + PROCEDURE IntPower* (x: REAL; n: INTEGER): REAL; + VAR y: REAL; + BEGIN + IF n = MIN(INTEGER) THEN RETURN IntPower(x, n + 1) / x END; + y := 1.0; + IF n < 0 THEN x := 1.0 / x; n := -n END; + WHILE n > 0 DO + IF ODD(n) THEN y := y * x; DEC(n) + ELSE x := x * x; n := n DIV 2 + END + END; + RETURN y + END IntPower; + + PROCEDURE Sin* (x: REAL): REAL; + BEGIN + RETURN sin(x) + END Sin; + + PROCEDURE Cos* (x: REAL): REAL; + BEGIN + RETURN cos(x) + END Cos; + + PROCEDURE Tan* (x: REAL): REAL; + BEGIN + RETURN tan(x) + END Tan; + + PROCEDURE SinCos* (x: REAL; OUT s, c: REAL); + BEGIN + s := sin(x); c := cos(x) + END SinCos; + + PROCEDURE ArcSin* (x: REAL): REAL; + BEGIN + RETURN asin(x) + END ArcSin; + + PROCEDURE ArcCos* (x: REAL): REAL; + BEGIN + RETURN acos(x) + END ArcCos; + + PROCEDURE ArcTan* (x: REAL): REAL; + BEGIN + RETURN atan(x) + END ArcTan; + + PROCEDURE ArcTan2* (y, x: REAL): REAL; + BEGIN + RETURN atan2(y, x) + END ArcTan2; + + PROCEDURE Sinh* (x: REAL): REAL; + BEGIN + RETURN sinh(x) + END Sinh; + + PROCEDURE Cosh* (x: REAL): REAL; + BEGIN + RETURN cosh(x) + END Cosh; + + PROCEDURE Tanh* (x: REAL): REAL; + BEGIN + RETURN tanh(x) + END Tanh; + + PROCEDURE ArcSinh* (x: REAL): REAL; + BEGIN + RETURN asinh(x) + END ArcSinh; + + PROCEDURE ArcCosh* (x: REAL): REAL; + BEGIN + RETURN acosh(x) + END ArcCosh; + + PROCEDURE ArcTanh* (x: REAL): REAL; + BEGIN + RETURN atanh(x) + END ArcTanh; + + PROCEDURE Floor* (x: REAL): REAL; + BEGIN + RETURN floor(x) + END Floor; + + PROCEDURE Ceiling* (x: REAL): REAL; + BEGIN + RETURN ceil(x) + END Ceiling; + + PROCEDURE Round* (x: REAL): REAL; + BEGIN + RETURN round(x) + END Round; + + PROCEDURE Trunc* (x: REAL): REAL; + BEGIN + RETURN trunc(x) + END Trunc; + + PROCEDURE Frac* (x: REAL): REAL; + BEGIN + IF x >= 0 THEN RETURN x - ENTIER(x) + ELSE RETURN x + ENTIER(-x) + END + END Frac; + + PROCEDURE Mod1* (x: REAL): REAL; + BEGIN + RETURN x - ENTIER(x) + END Mod1; + + PROCEDURE Sign* (x: REAL): REAL; + BEGIN + IF x > 0 THEN RETURN 1 + ELSIF x < 0 THEN RETURN -1 + ELSE RETURN x + END + END Sign; + + PROCEDURE SignBit* (x: REAL): BOOLEAN; + BEGIN + RETURN copysign(1.0, x) > 0 + END SignBit; + + PROCEDURE CopySign* (x, y: REAL): REAL; + BEGIN + RETURN copysign(x, y) + END CopySign; + + PROCEDURE Mantissa* (x: REAL): REAL; + VAR e: INTEGER; + BEGIN + RETURN frexp(x, e); + END Mantissa; + + PROCEDURE Exponent* (x: REAL): INTEGER; + VAR m: REAL; e: INTEGER; + BEGIN + m := frexp(x, e); + RETURN e + END Exponent; + + PROCEDURE Real* (m: REAL; e: INTEGER): REAL; + BEGIN + RETURN ldexp(m, e) + END Real; + +BEGIN + eps := 1.0E+0; + e := 2.0E+0; + WHILE e > 1.0E+0 DO + eps := eps/2.0E+0; + e := 1.0E+0 + eps + END; + eps := 2.0E+0 * eps +END Math. diff --git a/src/cpfront/posix/System/Mod/SMath.cp b/src/cpfront/posix/System/Mod/SMath.cp new file mode 100644 index 0000000..796ccc1 --- /dev/null +++ b/src/cpfront/posix/System/Mod/SMath.cp @@ -0,0 +1,231 @@ +MODULE SMath; + + IMPORT SYSTEM; + + VAR + eps, e: SHORTREAL; + + PROCEDURE [code] IncludeMATH "#include "; + PROCEDURE [code] M_PI (): SHORTREAL "M_PI"; + PROCEDURE [code] sqrtf (x: SHORTREAL): SHORTREAL "sqrtf(x)"; + PROCEDURE [code] expf (x: SHORTREAL): SHORTREAL "expf(x)"; + PROCEDURE [code] logf (x: SHORTREAL): SHORTREAL "logf(x)"; + PROCEDURE [code] log10f (x: SHORTREAL): SHORTREAL "log10f(x)"; + PROCEDURE [code] powf (x, y: SHORTREAL): SHORTREAL "powf(x, y)"; + PROCEDURE [code] sinf (x: SHORTREAL): SHORTREAL "sinf(x)"; + PROCEDURE [code] cosf (x: SHORTREAL): SHORTREAL "cosf(x)"; + PROCEDURE [code] tanf (x: SHORTREAL): SHORTREAL "tanf(x)"; + PROCEDURE [code] asinf (x: SHORTREAL): SHORTREAL "asinf(x)"; + PROCEDURE [code] acosf (x: SHORTREAL): SHORTREAL "acosf(x)"; + PROCEDURE [code] atanf (x: SHORTREAL): SHORTREAL "atanf(x)"; + PROCEDURE [code] atan2f (y, x: SHORTREAL): SHORTREAL "atan2f(y, x)"; + PROCEDURE [code] sinhf (x: SHORTREAL): SHORTREAL "sinhf(x)"; + PROCEDURE [code] coshf (x: SHORTREAL): SHORTREAL "coshf(x)"; + PROCEDURE [code] tanhf (x: SHORTREAL): SHORTREAL "tanhf(x)"; + PROCEDURE [code] asinhf (x: SHORTREAL): SHORTREAL "asinhf(x)"; + PROCEDURE [code] acoshf (x: SHORTREAL): SHORTREAL "acoshf(x)"; + PROCEDURE [code] atanhf (x: SHORTREAL): SHORTREAL "atanhf(x)"; + PROCEDURE [code] floorf (x: SHORTREAL): SHORTREAL "floorf(x)"; + PROCEDURE [code] ceilf (x: SHORTREAL): SHORTREAL "ceilf(x)"; + PROCEDURE [code] roundf (x: SHORTREAL): SHORTREAL "roundf(x)"; + PROCEDURE [code] truncf (x: SHORTREAL): SHORTREAL "truncf(x)"; + PROCEDURE [code] copysignf (x, y: SHORTREAL): SHORTREAL "copysignf(x, y)"; + PROCEDURE [code] frexpf (x: SHORTREAL; OUT exp: INTEGER): SHORTREAL "frexpf(x, exp)"; + PROCEDURE [code] ldexpf (x: SHORTREAL; exp: INTEGER): SHORTREAL "ldexpf(x, exp)"; + + PROCEDURE Pi* (): SHORTREAL; + BEGIN + RETURN M_PI() + END Pi; + + PROCEDURE Eps* (): SHORTREAL; + BEGIN + RETURN eps + END Eps; + + PROCEDURE Sqrt* (x: SHORTREAL): SHORTREAL; + BEGIN + RETURN sqrtf(x) + END Sqrt; + + PROCEDURE Exp* (x: SHORTREAL): SHORTREAL; + BEGIN + RETURN expf(x) + END Exp; + + PROCEDURE Ln* (x: SHORTREAL): SHORTREAL; + BEGIN + RETURN logf(x) + END Ln; + + PROCEDURE Log* (x: SHORTREAL): SHORTREAL; + BEGIN + RETURN log10f(x) + END Log; + + PROCEDURE Power* (x, y: SHORTREAL): SHORTREAL; + BEGIN + RETURN powf(x, y) + END Power; + + PROCEDURE IntPower* (x: SHORTREAL; n: INTEGER): SHORTREAL; + VAR y: SHORTREAL; + BEGIN + IF n = MIN(INTEGER) THEN RETURN IntPower(x, n + 1) / x END; + y := 1.0; + IF n < 0 THEN x := 1.0 / x; n := -n END; + WHILE n > 0 DO + IF ODD(n) THEN y := y * x; DEC(n) + ELSE x := x * x; n := n DIV 2 + END + END; + RETURN y + END IntPower; + + PROCEDURE Sin* (x: SHORTREAL): SHORTREAL; + BEGIN + RETURN sinf(x) + END Sin; + + PROCEDURE Cos* (x: SHORTREAL): SHORTREAL; + BEGIN + RETURN cosf(x) + END Cos; + + PROCEDURE Tan* (x: SHORTREAL): SHORTREAL; + BEGIN + RETURN tanf(x) + END Tan; + + PROCEDURE SinCos* (x: SHORTREAL; OUT s, c: SHORTREAL); + BEGIN + s := sinf(x); c := cosf(x) + END SinCos; + + PROCEDURE ArcSin* (x: SHORTREAL): SHORTREAL; + BEGIN + RETURN asinf(x) + END ArcSin; + + PROCEDURE ArcCos* (x: SHORTREAL): SHORTREAL; + BEGIN + RETURN acosf(x) + END ArcCos; + + PROCEDURE ArcTan* (x: SHORTREAL): SHORTREAL; + BEGIN + RETURN atanf(x) + END ArcTan; + + PROCEDURE ArcTan2* (y, x: SHORTREAL): SHORTREAL; + BEGIN + RETURN atan2f(y, x) + END ArcTan2; + + PROCEDURE Sinh* (x: SHORTREAL): SHORTREAL; + BEGIN + RETURN sinhf(x) + END Sinh; + + PROCEDURE Cosh* (x: SHORTREAL): SHORTREAL; + BEGIN + RETURN coshf(x) + END Cosh; + + PROCEDURE Tanh* (x: SHORTREAL): SHORTREAL; + BEGIN + RETURN tanhf(x) + END Tanh; + + PROCEDURE ArcSinh* (x: SHORTREAL): SHORTREAL; + BEGIN + RETURN asinhf(x) + END ArcSinh; + + PROCEDURE ArcCosh* (x: SHORTREAL): SHORTREAL; + BEGIN + RETURN acoshf(x) + END ArcCosh; + + PROCEDURE ArcTanh* (x: SHORTREAL): SHORTREAL; + BEGIN + RETURN atanhf(x) + END ArcTanh; + + PROCEDURE Floor* (x: SHORTREAL): SHORTREAL; + BEGIN + RETURN floorf(x) + END Floor; + + PROCEDURE Ceiling* (x: SHORTREAL): SHORTREAL; + BEGIN + RETURN ceilf(x) + END Ceiling; + + PROCEDURE Round* (x: SHORTREAL): SHORTREAL; + BEGIN + RETURN roundf(x) + END Round; + + PROCEDURE Trunc* (x: SHORTREAL): SHORTREAL; + BEGIN + RETURN truncf(x) + END Trunc; + + PROCEDURE Frac* (x: SHORTREAL): SHORTREAL; + BEGIN + IF x >= 0 THEN RETURN x - ENTIER(x) + ELSE RETURN x + ENTIER(-x) + END + END Frac; + + PROCEDURE Mod1* (x: SHORTREAL): SHORTREAL; + BEGIN + RETURN x - ENTIER(x) + END Mod1; + + PROCEDURE Sign* (x: SHORTREAL): SHORTREAL; + BEGIN + IF x > 0 THEN RETURN 1 + ELSIF x < 0 THEN RETURN -1 + ELSE RETURN x + END + END Sign; + + PROCEDURE SignBit* (x: SHORTREAL): BOOLEAN; + BEGIN + RETURN copysignf(1.0, x) > 0 + END SignBit; + + PROCEDURE CopySign* (x, y: SHORTREAL): SHORTREAL; + BEGIN + RETURN copysignf(x, y) + END CopySign; + + PROCEDURE Mantissa* (x: SHORTREAL): SHORTREAL; + VAR e: INTEGER; + BEGIN + RETURN frexpf(x, e); + END Mantissa; + + PROCEDURE Exponent* (x: SHORTREAL): INTEGER; + VAR m: SHORTREAL; e: INTEGER; + BEGIN + m := frexpf(x, e); + RETURN e + END Exponent; + + PROCEDURE Real* (m: SHORTREAL; e: INTEGER): SHORTREAL; + BEGIN + RETURN ldexpf(m, e) + END Real; + +BEGIN + eps := 1.0E+0; + e := 2.0E+0; + WHILE e > 1.0E+0 DO + eps := eps/2.0E+0; + e := 1.0E+0 + eps + END; + eps := 2.0E+0 * eps +END SMath. diff --git a/src/generic/CPfront/Mod/CPC.odc b/src/generic/CPfront/Mod/CPC.odc new file mode 100644 index 0000000000000000000000000000000000000000..e4fe990a14a21b7847e5a5bf1ef848be4a7ebfab GIT binary patch literal 79409 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 Nng8O~|D&0i{}*$i$Y%fm literal 0 HcmV?d00001 diff --git a/src/generic/CPfront/Mod/CPG.odc b/src/generic/CPfront/Mod/CPG.odc new file mode 100644 index 0000000000000000000000000000000000000000..fd732b9813a3455454f09a37996b49e3ed0c0cbc GIT binary patch literal 9887 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 O=j@N2KfnAt$N4Y*XJw55 literal 0 HcmV?d00001 diff --git a/src/generic/CPfront/Mod/CPV.odc b/src/generic/CPfront/Mod/CPV.odc new file mode 100644 index 0000000000000000000000000000000000000000..0fbf6c0fcabfc80fc9e2d5dc390011a0cf6cff9c GIT binary patch literal 51097 zcmdUYTWn=ndX_ysH8UqkLx2#$L_|C8VREX*<&<4DeW{vm#^rK#nW?gk?e6JGGgUg} zvu&U0<8wUc99LH{o>tT&o{&%;xJf)jN)Sj~B%Tm2j1WSQNJx3&1@VLg0v-_4yhITq zeBbx~>$3OR$K{%yL}1DGzO2iCU;p~oztvo)N<&&NNyGu%HtE(eqG((a@iZtj%h z{kiN__4(RxFzNILM9e_Rm@h2~P!A<{f75~8Rnkru5JK{WF z;LqIe;&;BytABuY=YNJ*pWyd1sqMePXZUfTeoZ%xK>b<1dI`Uu`2}8m5x?_4%`4Jl z{?FjgXLR*Td`1{PBS8LoxSikOv!BJEdDa#7R)np5<`q8r6MXSSu>Pe4;T=B1&n&XB z7bDvjSnM`_U((e|ydqIQn_7GixBQvaB8yv#zszDJzqRe)T{(pES zLQ=S1V!u*&dq#P%Xa9^>5|6*f_9P0wb16Kdc-!0G##_6(9G~&+C92pL5&>|hpIJO1 z{gZTFqWI4VJ5qRV0T5d+{|}UF;@5inHMDR^9QiMJHvgyj_BO9%*4X?d0y%faXM}$4zvK7Pb#y-W zJv427u$rMI+d%ZKdDc8R2p#L_ng!w+MJ}YYcV_wOe{w-cD;LqF@+#Ad-U_CE7|3h>>zrnYZJ9~>qbC=lY z+`quDseBg@*;PV@W6r$5Jw-V)JHG)Oj7RKp{y*Z++z;7@;QM`)Hkkhcp9!N?mXpE$ z54bX}5{3Eyggv3mXc8lSl*iwb9?RSgE&x*ge zRP2?Q!s(rUfi8L2>li)~%6+$!Mb;NkUK#oc}v7dLJdd(TdA@zq6xx6sa--@I|F*zn8cYqtt`5h%R8j26Pv>j9YYv*X9Ze(|K!KLs?yQ87Gm zpeDUzJR#i0xZfEc;Sx}Fdrxoyr~p1LZm`?VfR}*lq<_j90PDCn(B*5l*yfwX>$i&X zyM0`|!3u-&ySOB1{js`0AANgO!YAmCZo@$^EgJ~IE9FITXOLWpN zRZP9?4+n&G1>JNWv(gH>+3%2sE9hp}CDbeEW-y%K>N;pb{_K8hcW?cH_|oYTk`<7C zpX6Ra?~i*dyMpffMiO*CQvDTl4>Iztx(5kxeI1pLJ5PCq+LLD|2YQP7`B2ObjNx0z|l4eifJK376MbaEVS@t(~&d*B!9p^{Y4V26*k3#2R9?3rBQt z$X3X`&0gPR60(Kb+r!>qQU>Nx)ch@aTpJ#f@L(Vc5+?P(3_4hoc8hKSk9q|+U0?Q5 zbvW(;wQ&>vtD{lp8JY&Jcb*M!hif3aQ|=E(E~4Tq*i41nhb)hS;%z>Wwh~5Kl$KxRvb%9FAqQ6^sfp*p6dZy@~9A5F42) z5eBjdWv*Xyo*kSH_9s0Uu)*o^<8oxm6yOA0gYrX(HgN6@OzMGX(RB>~l3*F$^sN*~ zTs{pqfMb7n^32|#bFy5mCJG8(=zqHV*It zK^VR#rS%pq`r6imdS7PPVGnv;6~2L*-#sly2KS8sC`F>|N~8Oo!?6f;)EVC%b}7;% z&v>Ua{RY>@{ml}0lmk$!cWmPZ5b2HY^}1czJ{TX|zD?n@g6Oz6UV}6}?(EY{UXNgR z!nCqDVCO}f50+r`7G2YpVu{6qkS@`rcKS=>a)N)C4M)(1^HYKg%E8ixJCLs5I}Uf? z6b9sQ2Ou#k_B%+bt2#(cP^{ro#1Re;g#-vO7_RnB&Vf3}dN`of0`9t|MMCeV0}34# zPx1pTIq1M=0BE3sbX3g&mcj5~)H&8G>Fl7_zb&~(S0$ttHykopviy(@fQmg07;Jhx z0WE{!S$6oxrzfVB!bWBpVUR9tAiDto82bn4v&&(i)Tr|eb`{)ZF~gZg6CML>tXD(7 zsCMF(RTVJ+J}yy0EJ5K^my(io35h{n3>BbJAEm=<_3xv{9jmc1xTmr1`d8rNEZr+R zuzGi4F6ux-Hqki*EkKPy?ntGJ16mgeaBTCoq}bY|NME$Y#}xn29>~3QQV!r3Nxm1_ z3mQWD!*Lm(UDh)eyFCJDG+HgZp9*GAzpbaY`<(%mVWF@>!{g%)Zx`+Uj@$f&D|)>? znDjso7&Vr8^k{u^Z)1JO0NEI)=Nr4>*>?VL+n!1%wd`K`T|%TknO^ zklyTlYkPg`uCaD?srfO?j+uyS14`ANX^9Nh+ zt~>PQBt3q6eb1h5pJq?D-|?pyhXL^VQ;shn7o=8X{3b?^wIh-J(W7r}?A=?t_YLF5 zsO;$RV_q1^F^26XT#Pa#=ocg zM;|N#hTZ@+_HeQ2492~i#qF)F`|GQlZf%ZFQcJfuiGZcUa1!vLjt|Q51g5}d7p~nv zd@!ulbP@~?(9v-4?05)A9p&gOfl=le0Y16`H;aIs`h?4}e^g=+=^Yg7?``anbmJao zSu$LXX z0uw>plTy9ucG*56*=Av&#te%Bh^(xemfms&R& zNjL6N06=E~aXRQ8@NVzkIx&2(RE|dNufERN>iYd%EBbKB=P*~7RZbleeN=q7#3>3~ zwRle-Q81x06?n&FP8|@cSnxJb+IwbYTPUoTZx)*y_YE2&0E>gwM4XqV>0|}kHBUif zk-%N&)R|Onv#raR`-z6E#|Mtb)nfJbu1es6IU<*fI~(u9dAN2j^<*{Vbr4~)RcMjc z5r=+n@PR%3=DiJsGunLl3URnxd|7u7mlyy59WcE|H(P3}C0qd(ia%TeXqxnAkXtE{ zy#o9#69M*5%^(Ry1g_mU(pJ?t7w|*(<}#5BR)AJ*Zw1ncZHbI} z2})RTNC-_Me+Z2rX?&>W4Suw2QKJgP_oPt8SNyHBy0}WxUAugR+IHFT1IQSdV9qs} z)LklV;Cm4N>3r+%TyZsx2NgF<0*g#TDbO7c|2~aIAfX zfkF@__Mn=Hb3Kms8Lnjmj znWnus%s{K~P&Sb-5#WLU0sv$vrPkSF5SxIZ&dFqyJ%?J=XkcDo9F$xxfiM{+8lXfZ zKw^#ukRt7ZIYws>1LTb+Ibatgk9O5$@^Z1YQx(#LmIHLdD5YW5Mi-B#WZ)Rh0~@WB z?!Hpopg)Mv);`vV;l6cy#}Y!l&Bs6?5n6aXa7UE$AuI?&&W1!pnq_%b7(jWg_GD)k z-Q$8`yM~{8k__XD{^Cy%k*f2vMnzFjdd#L9{U73*ztB7&^PlMQkJ}KN+|ju#hZPT( zjt4_H5L;J{m4z;V|dGbTjCzQH+k4=F54b)Ry3XatxxVYD`Zwa$MMP zzdSG}PNSzlu>s$L@KMGvMD8u!MP!lccb6j!ky&D-;Gqc1KbUTZArl?zzTS1KrD~_g zlyQ|kjpa9l%F^WN1hHHn&^e+@3~9dB1qdM)`1?x(lQM|KlA9WN&_1Xe z`KRIY;Mpwr1fDE_TQk5#0>IyqZ4X-EzC*^&QSb0*QWb2MCkkW`3o!=(gBY1p>`#M9 zFd&2&k-b(3{dn&-4$_HsKq6rrED=k&oz`vqv?YIsI|n z-?I5jh0-4Z8Mvx&QT96=Zi7nI9)rYtJMXNET^o<*Hgw0xc5@+2}!mR=#Qqq-Jmf(xum5DVA4I=KlI-d;HJ_m|}DN zn{C8EdYDBluYm58hwAuCSR>)ZBq*Hv#)E}N3wZT@?<>pS=6l`JhXEm2{R2MKWOrwM zdwq4U7`*?13fcr_?cPqi{T-jWTt=S=^R*YQEnLPt#Zb0#-|=t(p0e=|E*I}0QhXmp zs;%Ey=Su;kUf7#e0cos?g}^|=fWfu*KvB{~ysff32*QtHkdb@Za8P(C?6CS1v*H zd?zDB+WHs(Fh%bojQT+tf}>xD-CHb{mX=(-3@~W4M>i@s*F9V5)q@faMf@-BzfleC%%uK0S+CBuV7d`z0M!ets{&@|^ ztR$cPqtL6>;cS4jc>p&YAT~Q>;5*HN4HfpOG!l5l&rV=$VU!JP^OrGo&V4z&T0$UX z^o)wa8}bbczfi+)wWc3@ln=Oy2N0JVFMK;|qa~BY~T>7aR&CNl@pALBuD2L&fPFu+!+W zv|6OH>WS*J=$uN(7Dh%e!-AuM-ak|mCV`rlxLjN2kY=VLv}?#RBOCim2TK@4)|ONV zi+c?BL=z2Wf`#6=PqyF@nJ6aLFd-%nC9fVB-~#AP$={Z9?raafjgt$V62;2Qg%gyY z&;%e?u>hbcNB}HKV9m5?*r%Zm)vC67wL4lJbm@d%fg3bD*{wUyWKNh)c;FpVCW=HT zt?;a^$iM}~;xLk9xbBU4t%z5ga!nYEG>F+FWG2;5b?X8az>L5=Tyhjc9jFleXPZ(V z^hSt`o^aK~jZ3t7^l%V=pcTeKmZdd}Tk8EHeVFGew8rql*$R76eMsRkqEDQ*_x3|S z<7`P=iFivJ2vj2a*1_7I;;G*~MR?+%huHzhqlV}U?K2|^utKgBZZh3=iN|Up=DlGN zow63HEWi3gc3N%Q`^uQ!Rr5^o%@I(F2g9cpf_qF`C zQu(kDdivO}IM2muDdv;OnZ2AYGsC*Jihz@9VX{M8zX^*o#*Bh_fcUGG9{g9rAO6#z z;U5zQZp!0m?X2&;v$KiW5^m30mJNut*Si=g-{xe{*N=U1*oMPc$09y{`vwMCOQ5-l!3KRZV6HC$Zp<44;s=98=E0H=gD193?Tw&9K-p+`*6Ok1WBfs0E(ZH< z7gr!OvTUd7h|*|6<10yyWXbcPQwDQt2W0d>2y$jB47pL^$Ln-X0)R?=zDOI_XSacz zX;5j{P0b{Zfj@ZtD|ib&l?c?G^pUaFWe)p+CsD@LH6YCl>(tC_j8-bpyq04mc3q^6 zDpe|NAZ;57F6DO@nXHXJ<#$tqj@zq&g2?+`gxF1&_-ZHtk726%a(FomT9BlNDu6Pv_}$``!px%|RaG#FShw7TIHOAk>%)dy?-> zsuZ#hv2hVB8$A0E$;Z;91fM4*S!G!x12}Ki`o&*Fr-DVRIEoMHSB;7`;xhC=HaQtp zCR4I!^c3Sl$U`mx0j?LW@Cb@~UL|DTbVsvdxcAFihgf||87Sb*e*fCjyt2g`5EBkr zDrTNyhzXf5nVGf#(%|8enQE*HS_ZZUlF%8VC|ZR@87{cQd4;E43{p)PGtF`bOR{5_ ztSg5VO<4o6KIH+LHJ}w&77L16{Ot8OAEjCU<_J0I_M(j}x81!Rgs6}K2$0CSHssRN z)$k-%Xs^Z0MVp49DDbh*3Oxwk;RCv zY!>j*62)y{GX)rwpaE_|)|AbU$&PR&D}1`$MF{X3BZ#qtE@F@z+5d>DA(e(YrFtN& zic~v|WI~1;nPhUah=DxkQXu}-w_s!5Crcw$H;_?df)^jP7rwm^V(yms5?`^j18S>S z0MGcSf}B=MhaN6rHVZo`IxTV$mkp{g5ki@YbtrZbe_4Ne0{gIxS}Vy&z~4!!gJB*S zv|%}_!(hcOjXTSfb%;5h;v%FYY0w{pI_4*x1rNzQ6nBko7H->68hBVsxFGvbL%vlk z1CWzyF%AV9y}pE$4$K%V5XC+%)4Vrern$9Oc_eb9X*p{0yS(dHhy-ECU85LtaDXJ3 zfL$r!GWuvrrbSJCg>7BY?TT(qAgNo`>a6S(s|jhZTdp4*Abn??k1&lQ zN{gFCl!HK3>ze&!n0RC8t}8G(9BafEdds>;t0XfQP^rJS;717?mW-ijf3%|E+?f8S*)tNmeORXKg7}g1e*QbS*g;+ncH=Z*c1> z=On%%AWbOcZ8n=o$je8zB?9uptS|_u2Gwjv2DfZHksF!6mHYN^Df(|%P4xP7Eb`gF zE1vLinJCOCgAMxH+RJVR@8chRym8XZf>FK zJ_`4|k0+ev$C*Lhh}GQ|0~CqAcCq}b*@QT)&FBh}wlgD`&G@25fc0NS%ArkKX9O~x z1x7ivPP*$spPV#m}1 zdyOPTu&%CdA|j{ltdihnV}#$L{UO*7AY^I7RN0ce3`fOND3I10%)NR;_W%+5ZL-XU z+Ot=rc-pupOGZY*mLn#RO9Y`IRByx>13FXDw=#NLjc6{~+?A@0stQdwS-bqa;#1u;M!?zVYRqV$H^g=_L-f;So-1 zglj?^Z4d(my}W?4&Vj<(f37~VI94wh$65*6RuEnAgR9nbWkuto_W7n@CMC>Y0Hhp8 z5e4B<2q6I5py)Yz7AycfHWmOz8;qj7BwxgBT`0kFxl%Q_a|>7BvLKKf36o?J;=Ic3 zg{4?4j3iuhZe)+ZOAHE;Oyt%{=nOF*1gCqo*EC>W5IhESFd`n8qer;P_*=}u%$rRy z(aNw}AykD#-iw*cFghA7W(C{2ok=H7SS}&EVYj&R{G$%y1iA_aHOmmLg#)=i*f<5iJaHNeV;@ zIuFx6MGU740?=*koN#OKz2OLlH6b(QsKg%opsB+CsnJJOWNFMveG04>i`Ot7HK`fm z;T&__dqM)ICyo@!d2&Z<0r^0RJuoudqkE|z2~*yayK3w&mPxwUY6(w=)eAtNA{+0* zX%$tF^aRFJNFV?i2{HYOBL*R;>s^KR0RqskC~tLnb%w-_oe~kjr$FT%PUg*+DQRE9Jggky=#d`t zWaa13nYijRQSALsQZmJHHSJk>O#5t7%14j(Pe&t;fLtjFgBLvj$I(WC_7(2c;BjL! z`);h8X`8gSeZ}`OB(MV!JzqX##Xtk%#_>8aF~QRr8>=u96)@`sMRh;9BbCg6iW5&8 z-qPF;e5IU-y$+f8lv|K`e{i-qL-dlQCsGC(OF}yh)UOx!s3O9dtnkqHspJ)ba6maz zwm?ETW>q;^oi|F=nG3mo!-~=k2QZoz%5_{?>E?kjiPO>6M$4bb{ zAq`gNisFDQ4s5fDTqa^J8Ga%~4p9RbZ4PX?tj_3Pl=^Wz4LcIdowa+b_xIY^8yR>C zN|PYy^IWUoHY@Wlpg7do>Rchv$i;d6FX7Ob(3AO+Rhq?SNxW=j)7x=z@+eYpU}J+K z^AtN{-#E?&ZRYM?@Xvx)T@TO zS>gcQ2@Cbv0LfTIQ=s9zxDXi{rueB9MhFQ>aI5lOsy(dYB*IRAyHg839e7A$OEC&b z4R@G;ElAVB@dnk1g%aCvCWI3An2R2IhZ~gzBbd<)e>euPurRrtg)b5!QBbmJH|?k= zlK286+%o_|!+Zeqh)bE;edZ@`GvLgY5AwukPW3N~Ri86c(Q z@r%xMeVPcJnauNI^wM;tifgz)0Hu%kJj^~T++s#C+6?#pE7LZJ)moDIACD$c&P0o zvFiqiToK#9;@al~q1~tVO%5D;> zi-d?jJXn3N9he>KS4+KxQX89DDMD*{9u=*76y{}@({Mg>-rKFKR~Xi$_WJB)4l`fC~W zJ*ZSAcGNc>@dSC-CUEBEV<{hDr6Au^`o88Xlo4yFuWWdQ72G%ty^4iI_1I|UWy|f8 zG|D{j5OH}`wK%FxR-IL8z1JScX}v`36&-aQ@)T*XBNWb{fP#`M5l`eItL z)Hur_jiBlxd%>U<8VMtc=`0VX*AHc14P6NOHy!#UxijGpz?%Q+Kvg=)V|6*QAu3uY z41=N+-GC6*8tIjjJyo1T*U3EPWTr%L_O-k5tLtr5%_mg-4Ra`Jwr8yK6Xifgo^^k#YexOFL`sx~zg z=1(AP@H8P#n4r-bt79ize9LX5(I$J$t-Y|Tk;ldz1FI^k?S;KiB1BbGFSqG@I< zP`kp3hnh5FQ}+arWwT%gT_Wwll5BH`;xUhyNnNeM!9Aa5+w3QAL~>4IYGldE@|h-~ zh>g@9Q*djK=rn9sJ7WVNc1>McE$kM;M4!T}6eSkZ!gW>sLgc~*JbF4l#lWc=z8}y> z9Nng=d>CyBB-Oa@#i%SeD9P`nrFhnmYq&c(-T_ z2Rf{IXj2qDM?=hG7q+!I4)qZTAA6An8V{bvpg{E7z#>fQXT}s%5+{#kMF9nVVh2?d zP5@K%O}Iwh+inHaMal#760U z2naiaOISt|94G!~Esh}5Y^2s1SW`J}v8!3^0v|Hh7I)Af<(`AHl#wZ6VudhAJ!@5V zwnlWEMi4GL%bl`gn-7}xrltqz;;e;jv=vPAOh@dR$eqoKD7j$U7KItHyGM_3H1b`X zd6Y!QXZ}GTvsUl{nd*?|*ny#Jg(;PZ$~I8eS^;b*e&rjwx$m2{tt+meiSzzSdT=)sl;I8r!7LZFcJpId!h#ZGx6ZgQj-P*w`qA zygewJWw(Q7KL2EP9LOWDAMCfId2iEI;^`*7@ETlxP<)C2>~MG>P%~>_vQW|JY~{na zen!vX0M1WHus*Mw7%L!6_S_J<_&{yAtni}EMA^%!gq7w*rCL8GaJACa#k~5;W|OUs z{c#tSaB8^3A%R(V)r|ig{HreLq1)ZeI+HWQ;D8j7}JH zR+e9L17Pnl0eJ2yApLR>M>Ph>fbNKa)dB2M*r1YDyGhYAi0?UPN`&J)8cvs(F$aNn z)=NO3hlqG`jS$mLqK#o`d=#NZ1rU@#E6EL5!;f;eb1Kz8p^KiYt(h3RmORG++`V_V2DVE{Z9gR(P86;6 z69y*w%s4V6r*Z?@4_0@-fd-;%*F5+}R^HygcaS2ba7@V`2`}$ooR=v2TwXSM)To$Y zRuzG>7EWBrsriQ_vpZXRHRjiBcM>ub{qgWb#dGk40jS|wk@|t+J5%Z!pVss<9JJYF zsPXlg8XQUqxsaBi?nSkPMQi<3v?M>eNM_~_3txO3qz1>u@kQN>;>)77ek%A@jWy)B zj_<6gDOV z^|1Q;<5O?-y-!6wRR0vzL+y)F4@GNOChB2CO##C&(~6FG7<=o?uZ7kiuk9EIrSGNF zvBH^HcEZX@#inO4XZkQT&WO$rF#|}UJt-flXv0btF!UK|)eVb1rBMh6L#;j7&U^@ZbL~;` z=EB0)sJ8G$J>ksCCQ|&uLD=?Zr?BReSnDpV7qv&21lAt)DVrY&v7q`7!!R zG(R#LiQ#0JUako+V_i3ccGkQ{ z$r1t9e8zLus+|mZZl_yVPmCQutaRKw$`-%EB#qRunGCJoSYXwbt6_e_GLe7nf|d%F zxjE@CYcJXHPZjmbT8x~OfX6WnQ`!7@$JB46$Coos)K9pKRBg1tF^pgl>6KT%n&hwQ zJDnp3XBS}y_Z%i%6RJ}yg%Mzwx^T+ql)f+@tkPa(@h}qRYQ57S5NECYRLlmFo@Gb@ z*icW3HLZn)4q_=>ZT6WBhbY(>NS7tt$UNAC_~lA{J*Z+FPzz;b{vf9IL2L~HT*0T= z%2I0rJ)0Ha(IXnvP>u0SrC%s3$H0j7GoLBNJy|m<5Q29^1pV`|B@`Jq(Ye7KLo4c1 zF#Fy^#EY=f5sR<;j$Dp`gk}#53P|w}1rjhZxrhte1_29^%m`#VnWJcUz>%+**}>K= zUCn}S%|o+>9kiKjr^D=5f2h-os>v_c)o9Z#hL#Q zatNDcvyl1Nu*qi&`2LOjMa#QFLHlBu?evXe7;F#TQ~yZEcJIL2Lt2J?ZQH&CfFkCA z#>#DdRo&f}+vVZyzI{81QU;i!iVePWYgGVwxBMaq zF{?HrO~?0u%u7NMPdUXh9}DXNuFWC>Fcf4k7+JO5Y^xbo0hT0~$ z3BResZ^jPc#`N%|8?|31)MAptWB5)i=5D`Ywbpvp-rIb z1`tIkFaR~$8lz-{IgJSeK)r*i6n+!Bx^~2mRb`x1OEz>uuQP}fkgoo2cAF?28U$nj zR$vh-v$z%GU95G+IA|F>tJvXL_S=l^76$d)6o^XhVi<7hD!5=BBs1w&H?xxHCf1r^8#PUVPudMEp_yAw4Ikg4iIhcSfnc|))@%bqWpBSX*(oQdqd{)d8V^P`4QTtu2l-9m zz&+^VNR2Q_KAnRPenr9ZNDn0O_Z8$icxUY=P~`JxW+Ix z6Fp1Y%|s^gF;TSFw{f=zR~5p-{%xk-P~Y%Cb)E>s>iU1hV1+)+Y?Xw}(8h$3PbyeW z`Mu$7+>ho~D{MQ%rU!>KH68eorRkVDc#1CpZ17h=7oflXR3BER=Ft?OtbgRoErG&* zY{5d9;UIc_zHw1|sSt|iZj76z1NwGIJe*m(KvsaYo!1-+U5`(A6tfEHJM3r0ZG2S9 zpXd`MX9XfT{y<+fvD1fRwb!gAX1MTtW;LbHtDgxf9uTc(+A=G!Vlmqeeii}=UU1nF z@EEQRffxE!j;K+58kKaj9`Ge;8=R*2LowC&2mDQxiNLs!XAS04oLzrhZYcmn(j@~* z$1=BFc=?umTh_k5?la7Sz(4l_G=qGabePQq6YG8jj|}4(Jrr-wH?z`|q3VdXU>h&( zNUr#uT@7kU8i_46BzJf{;vU<}%hZYDaTPqqmJ8a$s*S`a5b=Syy*uR?AD*wcr2G7~ zM~n+l*Mj@lWW_Vj2?u&jCir*-Xu$DRZQm*P`KiT8MCF)?ve!adS->^c$^^{0QDu>}dM=lMN+XX}cX!u!_Szzehg_guN*D{a zKYs_e02y>~T&vU$aa?|M%7!)&Bz|-vlOBbevOuuolna<2N11KGMO(l@JvVE4*i#b& z2sWa)vs*WHLW)D9VW+<`3#NGuIQvB6IViVgBja0aY0@YvpB5W4Voi9+XnGjG0h}Oa zC>Bg>V<{1zg*ZsiMkFz-iXW{%=i9YtY+dBE1(xZQne{l&;xUVJFvLemVdjVur70s? zoW}%pX*p|xy9-&hgP2ShpR;q1&BI;>A-0-P(D`2r;fjg+AMb4z;5v1^WdQ&}4;Sm!iq_@KVT zy%`mQTMgv{8A%cU)95*;urhM=-Q0+*%%xQZxx?HnX8{FhT?_U zeovop3N+MVNBJs-93QM=5Jz7_s?rWrP-V>m*shYGeShaB0w!fRv)VNt(OaAC+StP2 zfE?#rh^Cd|mkJ-?MQ0PuMu1&W9{!F;+oxV_W7{8dZ#G}Jh$;PilKU3{G zOd6{+(&Z)H-Uzge)YGYhg59IRjz`Msl6VAxl7Ljt5wj$Qu+a16kZoa0VhDjXC0x84 zKAw<)Ywg69G%W6U;H)yJ)=FW$t;H$3eI^}?0uz2bp6h^D<4T)P;EfECKR&j@2T~eY zjX5rk9J1pIWCp7be6<<9#`nBbMpE%Dd)I_pWo5_RxNC2+Ll@++MRwl zvhHGZ&p4N3t+{@K``?5N!A+9OB&zcQ-dip|jH>5=O33 zUh}*$AUNVv`lblHhnAyw#M2!bVaf><#6ssiKr|w3CIpT39jE7x(eBMh>~J9$ChH{7 zmV5MYTq?h~fPaasWDAp(7>YCh$>&@#LyI2M#$bP>!}?h)%sJIkn7V|n6NwE`_1kC1 z<_~^C1y;roT{e4b!Z95XaEv*7j%_53({*Z2?~Ygl zd4J-lRcL6T;v{Vs&nj&1XH?8gmEYAQPNQ$zaiqFJ+0<+z77b&{#geLP^Bw0RaswGjxVWaIU1>y$yitxd}ls)ABx`Udh30APPS~Cm;x1ei5 zCWbI0oy{;^P-TN=M#bc`IyU7B=KrdZx7-Zm=Eg#ld2XhR6gy&$I^-e}3DKky@g3O7 zCndL$g}fFfU&kywJm+_ovVz{!hey5s?6x98K}JE%O%w;K-{ZlciOb{2ZY$Cg-F|K*UpUBSN9U!bs89 zQFV2j{l-kbI(?dv>JRZ%c`u>xud+$NT+UDei}?(J1bYyY+pa1rhyMK(ps?6Q`_?V) z|9Wx!0~4T%S%C%|WOA*jElm1VfHW&3VaKsEFUM2W{OEMROV5FX!6onsEA0EoiwGWjvf(W_eiL$>C&&jU8a0T-uey~ z?NJI&2Bt-k&SBuxmKX1V9J$x&YXoW@bXbtX2v&7MPrRo3;y7Ic+ZpFpG7Q(%jsdi( zB*d(~cBEw;9hJr88D8XDVz{P+K@9(7M)9Avk56kWP1!1(bv0`ljtg$pB{-z5U`go; zS4j@jLL4P6{7%5XqRFGX_yjuxU#TXwg zOW)dvy=aBI(hXav_o7nh1&p9UX|R6C$$~v3G+|+vU94fPZ*Y2|OwO^TUzqejqR7;> z?Ss*9Fj?Dvcj@Jif3$~lP1kTc8ut4*Lv3ky(p{U3`gf4&H8=G#6}0!f2L!Cw^eVJj zd-us_=j`X_{C~^;`@eaEY6k*u0O=}0;+J?aAMT3ZvPRB+I6wCrLwgZke*DSH zp_u>wVz^h4D|4*HpI;AEboVpAH#f)M#lQRh+)w}B+}A(;(VgM`DL)!E#fMLRRyEQe kqNN`Z{b+wY_xdmV*4(fC@1N4|e?2&w`{%#-cjo5)FI~LRvH$=8 literal 0 HcmV?d00001 diff --git a/src/generic/Dev/Mod/CPB.odc b/src/generic/Dev/Mod/CPB.odc new file mode 100644 index 0000000000000000000000000000000000000000..ef983246097fbfbcf8f16ffee102234b9ded3e76 GIT binary patch literal 85461 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 literal 0 HcmV?d00001 diff --git a/src/generic/Dev/Mod/CPC486.odc b/src/generic/Dev/Mod/CPC486.odc new file mode 100644 index 0000000000000000000000000000000000000000..0898cd23de4300d617709a2acf9ad63b941e4e00 GIT binary patch literal 87900 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 vE&An+~3=0Rbo%@7SWT>XsuH_!HGFU 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 V|N2?||F5U#GynGQ{^88b{|2`hPFer} literal 0 HcmV?d00001 diff --git a/src/generic/Dev/Mod/CPH.odc b/src/generic/Dev/Mod/CPH.odc new file mode 100644 index 0000000000000000000000000000000000000000..014828b9f796db5c78802b23fcec952048869021 GIT binary patch literal 12814 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 cw4&0J55Hb|OV literal 0 HcmV?d00001 diff --git a/src/generic/Dev/Mod/CPL486.odc b/src/generic/Dev/Mod/CPL486.odc new file mode 100644 index 0000000000000000000000000000000000000000..eca6a68d9c4062b22157f06f88bfdc14f85fe7e0 GIT binary patch literal 36869 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 O|Mc@p^us@_RQ@mCb$BKK literal 0 HcmV?d00001 diff --git a/src/generic/Dev/Mod/CPM.cp b/src/generic/Dev/Mod/CPM.cp new file mode 100644 index 0000000..38cfe53 --- /dev/null +++ b/src/generic/Dev/Mod/CPM.cp @@ -0,0 +1,1194 @@ +MODULE DevCPM; + + IMPORT SYSTEM, Kernel, Files, Console, Strings; + + CONST + ProcSize* = 4; (* PROCEDURE type *) + PointerSize* = 4; (* POINTER type *) + DArrSizeA* = 8; (* dyn array descriptor *) + DArrSizeB* = 4; (* size = A + B * typ.n *) + + MaxSet* = 31; + MaxIndex* = 7FFFFFFFH; (* maximal index value for array declaration *) + + MinReal32Pat = 0FF7FFFFFH; (* most positive, 32-bit pattern *) + MinReal64PatL = 0FFFFFFFFH; (* most negative, lower 32-bit pattern *) + MinReal64PatH = 0FFEFFFFFH; (* most negative, higher 32-bit pattern *) + MaxReal32Pat = 07F7FFFFFH; (* most positive, 32-bit pattern *) + MaxReal64PatL = 0FFFFFFFFH; (* most positive, lower 32-bit pattern *) + MaxReal64PatH = 07FEFFFFFH; (* most positive, higher 32-bit pattern *) + InfRealPat = 07F800000H; (* real infinity pattern *) + + + (* inclusive range of parameter of standard procedure HALT *) + MinHaltNr* = 0; + MaxHaltNr* = 128; + + (* inclusive range of register number of procedures SYSTEM.GETREG and SYSTEM.PUTREG *) + MinRegNr* = 0; + MaxRegNr* = 31; + + (* maximal value of flag used to mark interface structures *) + MaxSysFlag* = 127; (* shortint *) + CProcFlag* = 1; (* code procedures *) + + (* maximal condition value of parameter of SYSTEM.CC *) + MaxCC* = 15; + + (* initialization of constant address, must be different from any valid constant address *) + ConstNotAlloc* = -1; + + (* whether hidden pointer fields have to be nevertheless exported *) + ExpHdPtrFld* = TRUE; + HdPtrName* = "@ptr"; + + (* whether hidden untagged pointer fields have to be nevertheless exported *) + ExpHdUtPtrFld* = TRUE; + HdUtPtrName* = "@utptr"; + + (* whether hidden procedure fields have to be nevertheless exported (may be used for System.Free) *) + ExpHdProcFld* = TRUE; + HdProcName* = "@proc"; + + (* whether hidden bound procedures have to be nevertheless exported *) + ExpHdTProc* = FALSE; + HdTProcName* = "@tproc"; + + (* maximal number of exported stuctures: *) + MaxStruct* = 16000; (* must be < MAX(INTEGER) DIV 2 in object model *) + + (* maximal number of record extensions: *) + MaxExts* = 15; (* defined by type descriptor layout *) + + (* whether field leaf of pointer variable p has to be set to FALSE, when NEW(p) or SYSTEM.NEW(p, n) is used *) + NEWusingAdr* = FALSE; + + (* special character (< " ") returned by procedure Get, if end of text reached *) + Eot* = 0X; + + (* warnings *) + longreal* = 0; largeint* = 1; realConst* = 2; copy* = 3; lchr* = 4; lentier* = 5; invar* = 6; outvar* = 7; + + (* language options *) + interface* = 1; + com* = 2; comAware* = 3; + som* = 4; somAware* = 5; + oberon* = 6; + java* = 7; javaAware* = 8; + noCode* = 9; + allSysVal* = 14; + sysImp* = 15; + trap* = 31; + sys386 = 10; sys68k = 20; (* processor type in options if system imported *) + + CONST + SFdir = "Sym"; + OFdir = "Code"; + SYSdir = "System"; + SFtag = 6F4F5346H; (* symbol file tag *) + OFtag = 6F4F4346H; (* object file tag *) + maxErrors = 64; + errFile = "Errors"; + + TYPE + Directory* = POINTER TO RECORD + path*: Files.Name; + legacy*: BOOLEAN; + next*: Directory + END; + + VAR + LEHost*: BOOLEAN; (* little or big endian host *) + MinReal32*, MaxReal32*, InfReal*, + MinReal64*, MaxReal64*: REAL; + noerr*: BOOLEAN; (* no error found until now *) + curpos*, startpos*, errpos*: INTEGER; (* character, start, and error position in source file *) + searchpos*: INTEGER; (* search position in source file *) + errors*: INTEGER; + breakpc*: INTEGER; (* set by OPV.Init *) + options*: SET; (* language options *) + file*: Files.File; (* used for sym file import *) + legacy*: BOOLEAN; (* use BlackBox subsystems *) + symList*: Directory; + codePath*: Files.Name; + symPath*: Files.Name; + codeDir*: ARRAY 16 OF CHAR; + symDir*: ARRAY 16 OF CHAR; + name*: Files.Name; (* source name *) + checksum*: INTEGER; (* symbol file checksum *) + verbose*: INTEGER; + + lastpos: INTEGER; + ObjFName: Files.Name; + + in: POINTER TO ARRAY OF CHAR; + oldSymFile, symFile, objFile: Files.File; + inSym: Files.Reader; + outSym, outObj: Files.Writer; + + errNo, errPos: ARRAY maxErrors OF INTEGER; + + crc32tab: ARRAY 256 OF INTEGER; + + + PROCEDURE^ err* (n: INTEGER); + + PROCEDURE Init* (source: POINTER TO ARRAY OF CHAR); + BEGIN + in := source; + noerr := TRUE; options := {}; + curpos := 0; errpos := curpos; lastpos := curpos - 11; errors := 0; + codePath := ""; symPath := ""; name := ""; + codeDir := OFdir; symDir := SFdir; + END Init; + + PROCEDURE Close*; + BEGIN + oldSymFile := NIL; inSym := NIL; + symFile := NIL; outSym := NIL; + objFile := NIL; outObj := NIL; + in := NIL + END Close; + + PROCEDURE Get* (VAR ch: CHAR); + BEGIN + ch := in[curpos]; INC(curpos) + END Get; + + PROCEDURE LineColOf (pos: INTEGER; OUT line, col, beg, end: INTEGER); + VAR i: INTEGER; + BEGIN + i := 0; line := 1; col := 1; beg := 0; end := 0; + WHILE i < pos DO + IF in[i] = 0DX THEN + INC(i); + IF in[i] = 0AX THEN + INC(i) + END; + INC(line); + beg := i; + col := 1 + ELSIF in[i] = 0AX THEN + INC(i); + INC(line); + beg := i; + col := 1 + ELSIF in[i] = 09X THEN + INC(i); INC(col, 2) + ELSE + INC(i); INC(col) + END; + END; + WHILE (in[i] # 0DX) & (in[i] # 0AX) & (in[i] # 0X) DO + INC(i) + END; + end := i - 1 + END LineColOf; + + PROCEDURE LineOf* (pos: INTEGER): INTEGER; + VAR line, col, beg, end: INTEGER; + BEGIN + LineColOf(pos, line, col, beg, end); + RETURN line + END LineOf; + + PROCEDURE LoWord (r: REAL): INTEGER; + VAR x: INTEGER; + BEGIN + x := SYSTEM.ADR(r); + IF ~LEHost THEN INC(x, 4) END; + SYSTEM.GET(x, x); + RETURN x + END LoWord; + + PROCEDURE HiWord (r: REAL): INTEGER; + VAR x: INTEGER; + BEGIN + x := SYSTEM.ADR(r); + IF LEHost THEN INC(x, 4) END; + SYSTEM.GET(x, x); + RETURN x + END HiWord; + + PROCEDURE Compound (lo, hi: INTEGER): REAL; + VAR r: REAL; + BEGIN + IF LEHost THEN + SYSTEM.PUT(SYSTEM.ADR(r), lo); SYSTEM.PUT(SYSTEM.ADR(r) + 4, hi) + ELSE + SYSTEM.PUT(SYSTEM.ADR(r) + 4, lo); SYSTEM.PUT(SYSTEM.ADR(r), hi) + END; + RETURN r + END Compound; + + + (* sysflag control *) + + PROCEDURE ValidGuid* (IN str: ARRAY OF SHORTCHAR): BOOLEAN; + VAR i: INTEGER; ch: SHORTCHAR; + BEGIN + IF (LEN(str$) # 38) OR (str[0] # "{") & (str[37] # "}") THEN RETURN FALSE END; + i := 1; + WHILE i < 37 DO + ch := str[i]; + IF (i = 9) OR (i = 14) OR (i = 19) OR (i = 24) THEN + IF ch # "-" THEN RETURN FALSE END + ELSE + IF (ch < "0") OR (ch > "9") & (CAP(ch) < "A") OR (CAP(ch) > "Z") THEN RETURN FALSE END + END; + INC(i) + END; + RETURN TRUE + END ValidGuid; + + PROCEDURE GetProcSysFlag* (IN id: ARRAY OF SHORTCHAR; num: SHORTINT; VAR flag: SHORTINT); + BEGIN + IF id # "" THEN + IF id = "code" THEN num := 1 + ELSIF id = "callback" THEN num := 2 + ELSIF id = "nostkchk" THEN num := 4 + ELSIF id = "ccall" THEN num := -10 + ELSIF id = "ccall16" THEN num := -12 + ELSIF id = "guarded" THEN num := 8 + ELSIF id = "noframe" THEN num := 16 + ELSIF id = "native" THEN num := -33 + ELSIF id = "bytecode" THEN num := -35 + END + END; + IF (options * {sysImp, sys386, sys68k} # {}) & ((num = 1) OR (num = 2)) THEN INC(flag, num) + ELSIF (sys68k IN options) & (num = 4) THEN INC(flag, num) + ELSIF (options * {sys386, interface} # {}) & (num = -10) & (flag = 0) THEN flag := -10 + ELSIF (options * {sys386, interface} # {}) & (num = -12) & (flag = 0) THEN flag := -12 + ELSIF (options * {sys386, com} # {}) & (num = 8) & (flag = 0) THEN flag := 8 + ELSIF (options * {sysImp, sys386} # {}) & (num = 16) & (flag = 0) THEN flag := 16 + ELSIF ({sysImp, java} - options = {}) & ((num= -33) OR (num = -35)) & (flag = 0) THEN flag := num + ELSE err(225); flag := 0 + END + END GetProcSysFlag; + + PROCEDURE GetVarParSysFlag* (IN id: ARRAY OF SHORTCHAR; num: SHORTINT; VAR flag: SHORTINT); + VAR old: SHORTINT; + BEGIN + old := flag; flag := 0; + IF (options * {sys386, sys68k, interface, com} # {}) THEN + IF (num = 1) OR (id = "nil") THEN + IF ~ODD(old) THEN flag := SHORT(old + 1) END + ELSIF ((num = 2) OR (id = "in")) & (oberon IN options) THEN + IF old <= 1 THEN flag := SHORT(old + 2) END + ELSIF ((num = 4) OR (id = "out")) & (oberon IN options) THEN + IF old <= 1 THEN flag := SHORT(old + 4) END + ELSIF ((num = 8) OR (id = "new")) & (options * {com, interface} # {}) THEN + IF old <= 1 THEN flag := SHORT(old + 8) END + ELSIF ((num = 16) OR (id = "iid")) & (com IN options) THEN + IF old <= 1 THEN flag := SHORT(old + 16) END + END + END; + IF flag = 0 THEN err(225) END + END GetVarParSysFlag; + + PROCEDURE GetRecordSysFlag* (IN id: ARRAY OF SHORTCHAR; num: SHORTINT; VAR flag: SHORTINT); + VAR old: SHORTINT; + BEGIN + old := flag; flag := 0; + IF (num = 1) OR (id = "untagged") THEN + IF (options * {sysImp, sys386, sys68k, interface, com, som} # {}) & (old = 0) THEN flag := 1 END + ELSIF (num = 3) OR (id = "noalign") THEN + IF (options * {sys386, sys68k, interface, com, som} # {}) & (old = 0) THEN flag := 3 END + ELSIF (num = 4) OR (id = "align2") THEN + IF (options * {sys386, interface, com} # {}) & (old = 0) THEN flag := 4 END + ELSIF (num = 5) OR (id = "align4") THEN + IF (options * {sys386, interface, com} # {}) & (old = 0) THEN flag := 5 END + ELSIF (num = 6) OR (id = "align8") THEN + IF (options * {sys386, interface, com} # {}) & (old = 0) THEN flag := 6 END + ELSIF (num = 7) OR (id = "union") THEN + IF (options * {sys386, sys68k, interface, com} # {}) & (old = 0) THEN flag := 7 END + ELSIF (num = 10) OR (id = "interface") OR ValidGuid(id) THEN + IF (com IN options) & (old = 0) THEN flag := 10 END + ELSIF (num = -11) OR (id = "jint") THEN + IF (java IN options) & (old = 0) THEN flag := -11 END + ELSIF (num = -13) OR (id = "jstr") THEN + IF (java IN options) & (old = 0) THEN flag := -13 END + ELSIF (num = 20) OR (id = "som") THEN + IF (som IN options) & (old = 0) THEN flag := 20 END + END; + IF flag = 0 THEN err(225) END + END GetRecordSysFlag; + + PROCEDURE GetArraySysFlag* (IN id: ARRAY OF SHORTCHAR; num: SHORTINT; VAR flag: SHORTINT); + VAR old: SHORTINT; + BEGIN + old := flag; flag := 0; + IF (num = 1) OR (id = "untagged") THEN + IF (options * {sysImp, sys386, sys68k, interface, com, som} # {}) & (old = 0) THEN flag := 1 END + ELSIF (num = -12) OR (id = "jarr") THEN + IF (java IN options) & (old = 0) THEN flag := -12 END + ELSIF (num = -13) OR (id = "jstr") THEN + IF (java IN options) & (old = 0) THEN flag := -13 END + END; + IF flag = 0 THEN err(225) END + END GetArraySysFlag; + + PROCEDURE GetPointerSysFlag* (IN id: ARRAY OF SHORTCHAR; num: SHORTINT; VAR flag: SHORTINT); + VAR old: SHORTINT; + BEGIN + old := flag; flag := 0; + IF (num = 1) OR (id = "untagged") THEN + IF (options * {sys386, sys68k, interface, com, som} # {}) & (old = 0) THEN flag := 1 END + ELSIF (num = 2) OR (id = "handle") THEN + IF (sys68k IN options) & (old = 0) THEN flag := 2 END + ELSIF (num = 10) OR (id = "interface") THEN + IF (com IN options) & (old = 0) THEN flag := 10 END + ELSIF (num = 20) OR (id = "som") THEN + IF (som IN options) & (old = 0) THEN flag := 20 END + END; + IF flag = 0 THEN err(225) END + END GetPointerSysFlag; + + PROCEDURE GetProcTypSysFlag* (IN id: ARRAY OF SHORTCHAR; num: SHORTINT; VAR flag: SHORTINT); + BEGIN + IF ((num = -10) OR (id = "ccall")) & (options * {sys386, interface} # {}) THEN flag := -10 + ELSIF ((num = -12) OR (id = "ccall16")) & (options * {sys386, interface} # {}) THEN flag := -12 + ELSE err(225); flag := 0 + END + END GetProcTypSysFlag; + + PROCEDURE PropagateRecordSysFlag* (baseFlag: SHORTINT; VAR flag: SHORTINT); + BEGIN + IF (baseFlag = 1) OR (baseFlag >= 3) & (baseFlag <= 7) THEN (* propagate untagged .. union *) + IF flag = 0 THEN flag := baseFlag + ELSIF (flag = 6) & (baseFlag < 6) THEN (* OK *) (* special case for 8 byte aligned records *) + ELSIF flag # baseFlag THEN err(225); flag := 0 + END + ELSIF (baseFlag # 10) & (flag = 10) THEN err(225) + END + END PropagateRecordSysFlag; + + PROCEDURE PropagateRecPtrSysFlag* (baseFlag: SHORTINT; VAR flag: SHORTINT); + BEGIN + IF (baseFlag = 1) OR (baseFlag >= 3) & (baseFlag <= 7) THEN (* pointer to untagged .. union is untagged *) + IF flag = 0 THEN flag := 1 + ELSIF (flag # 1) & (flag # 2) THEN err(225); flag := 0 + END + ELSIF baseFlag = 10 THEN (* pointer to interface is interface *) + IF flag = 0 THEN flag := 10 + ELSIF flag # 10 THEN err(225); flag := 0 + END + ELSIF baseFlag = -11 THEN (* pointer to java interface is java interface *) + IF flag # 0 THEN err(225) END; + flag := -11 + ELSIF baseFlag = -13 THEN (* pointer to java string is java string *) + IF flag # 0 THEN err(225) END; + flag := -13 + END + END PropagateRecPtrSysFlag; + + PROCEDURE PropagateArrPtrSysFlag* (baseFlag: SHORTINT; VAR flag: SHORTINT); + BEGIN + IF baseFlag = 1 THEN (* pointer to untagged or guid is untagged *) + IF flag = 0 THEN flag := 1 + ELSIF (flag # 1) & (flag # 2) THEN err(225); flag := 0 + END + ELSIF baseFlag = -12 THEN (* pointer to java array is java array *) + IF flag # 0 THEN err(225) END; + flag := -12 + ELSIF baseFlag = -13 THEN (* pointer to java string is java string *) + IF flag # 0 THEN err(225) END; + flag := -13 + END + END PropagateArrPtrSysFlag; + + + (* utf8 strings *) + + PROCEDURE PutUtf8* (VAR str: ARRAY OF SHORTCHAR; val: INTEGER; VAR idx: INTEGER); + BEGIN + ASSERT((val >= 0) & (val < 65536)); + IF val < 128 THEN + str[idx] := SHORT(CHR(val)); INC(idx) + ELSIF val < 2048 THEN + str[idx] := SHORT(CHR(val DIV 64 + 192)); INC(idx); + str[idx] := SHORT(CHR(val MOD 64 + 128)); INC(idx) + ELSE + str[idx] := SHORT(CHR(val DIV 4096 + 224)); INC(idx); + str[idx] := SHORT(CHR(val DIV 64 MOD 64 + 128)); INC(idx); + str[idx] := SHORT(CHR(val MOD 64 + 128)); INC(idx) + END + END PutUtf8; + + PROCEDURE GetUtf8* (IN str: ARRAY OF SHORTCHAR; VAR val, idx: INTEGER); + VAR ch: SHORTCHAR; + BEGIN + ch := str[idx]; INC(idx); + IF ch < 80X THEN + val := ORD(ch) + ELSIF ch < 0E0X THEN + val := ORD(ch) - 192; + ch := str[idx]; INC(idx); val := val * 64 + ORD(ch) - 128 + ELSE + val := ORD(ch) - 224; + ch := str[idx]; INC(idx); val := val * 64 + ORD(ch) - 128; + ch := str[idx]; INC(idx); val := val * 64 + ORD(ch) - 128 + END + END GetUtf8; + + + (* log output *) + + PROCEDURE LogW* (ch: CHAR); + BEGIN + Console.WriteChar(ch) + END LogW; + + PROCEDURE LogWStr* (IN s: ARRAY OF CHAR); + BEGIN + Console.WriteStr(s) + END LogWStr; + + PROCEDURE LogWPar* (IN key: ARRAY OF CHAR; IN p0, p1: ARRAY OF SHORTCHAR); + VAR s, s0, s1: ARRAY 256 OF CHAR; i, res: INTEGER; + BEGIN + Kernel.Utf8ToString(p0, s0, res); + Kernel.Utf8ToString(p1, s1, res); + IF key = "#Dev:NotImplementedIn" THEN s := "^0 not implemented in ^1" + ELSIF key = "#Dev:NotImplemented" THEN s := "^0 not implemented" + ELSIF key = "#Dev:InconsistentImport" THEN s := "^0.^1 is not consistently imported" + ELSIF key = "#Dev:ChangedLibFlag" THEN s := "changed library flag" + ELSIF key = "#Dev:IsNoLongerInSymFile" THEN s := "^0 is no longer in symbol file" + ELSIF key = "#Dev:IsRedefinedInternally" THEN s := "^0 is redefined internally" + ELSIF key = "#Dev:IsRedefined" THEN s := "^0 is redefined" + ELSIF key = "#Dev:IsNewInSymFile" THEN s := "^0 is new in symbol file" + ELSIF key = "#Dev:NewSymFile" THEN s := "new symbol file" + ELSE s := key$ + END; + i := 0; + WHILE s[i] # 0X DO + IF s[i] = "^" THEN + CASE s[i + 1] OF + | "0": Console.WriteStr(s0) + | "1": Console.WriteStr(s1) + | "2": (* skip *) + ELSE Console.WriteChar("^") + END; + INC(i, 2) + ELSE + Console.WriteChar(s[i]); + INC(i) + END + END + END LogWPar; + + PROCEDURE LogWNum* (i, len: INTEGER); + VAR s: ARRAY 32 OF CHAR; + BEGIN + Strings.IntToStringForm(i, 10, len, " ", FALSE, s); + Console.WriteStr(s) + END LogWNum; + + PROCEDURE LogWLn*; + BEGIN + Console.WriteLn + END LogWLn; + + PROCEDURE Mark* (n, pos: INTEGER); + BEGIN + IF (n >= 0) & ~((oberon IN options) & (n >= 181) & (n <= 190)) THEN + noerr := FALSE; + IF pos < 0 THEN pos := 0 END; + IF (pos < lastpos) OR (lastpos + 9 < pos) THEN + lastpos := pos; + IF errors < maxErrors THEN + errNo[errors] := n; errPos[errors] := pos + END; + INC(errors) + END; + IF trap IN options THEN HALT(100) END; + ELSIF (n <= -700) & (errors < maxErrors) THEN + errNo[errors] := -n; errPos[errors] := pos; INC(errors) + END + END Mark; + + PROCEDURE err* (n: INTEGER); + BEGIN + Mark(n, errpos) + END err; + + PROCEDURE GetErrorMsg (err: INTEGER; OUT msg: ARRAY OF CHAR); + BEGIN + CASE err OF + | 0: msg := 'undeclared identifier' + | 1: msg := 'multiply defined identifier' + | 2: msg := 'illegal character in number' + | 3: msg := 'illegal character in string' + | 4: msg := 'identifier does not match procedure name' + | 5: msg := 'comment not closed' + | 9: msg := '"=" expected' + | 12: msg := 'type definition starts with incorrect symbol' + | 13: msg := 'factor starts with incorrect symbol' + | 14: msg := 'statement starts with incorrect symbol' + | 15: msg := 'declaration followed by incorrect symbol' + | 16: msg := 'MODULE expected' + | 19: msg := '"." missing' + | 20: msg := '"," missing' + | 21: msg := '":" missing' + | 23: msg := '")" missing' + | 24: msg := '"]" missing' + | 25: msg := '"}" missing' + | 26: msg := 'OF missing' + | 27: msg := 'THEN missing' + | 28: msg := 'DO missing' + | 29: msg := 'TO missing' + | 35: msg := '"," or OF expected' + | 36: msg := 'CONST, TYPE, VAR, PROCEDURE, BEGIN, or END missing' + | 37: msg := 'PROCEDURE, BEGIN, or END missing' + | 38: msg := 'BEGIN or END missing' + | 40: msg := '"(" missing' + | 41: msg := 'illegally marked identifier' + | 42: msg := 'constant not an integer' + | 43: msg := 'UNTIL missing' + | 44: msg := '":=" missing' + | 46: msg := 'EXIT not within loop statement' + | 47: msg := 'string expected' + | 48: msg := 'identifier expected' + | 49: msg := '";" missing' + | 50: msg := 'expression should be constant' + | 51: msg := 'END missing' + | 52: msg := 'identifier does not denote a type' + | 53: msg := 'identifier does not denote a record type' + | 54: msg := 'result type of procedure is not a basic type' + | 55: msg := 'procedure call of a function' + | 56: msg := 'assignment to non-variable' + | 57: msg := 'pointer not bound to record or array type' + | 58: msg := 'recursive type definition' + | 59: msg := 'illegal open array parameter' + | 60: msg := 'wrong type of case label' + | 61: msg := 'inadmissible type of case label' + | 62: msg := 'case label defined more than once' + | 63: msg := 'illegal value of constant' + | 64: msg := 'more actual than formal parameters' + | 65: msg := 'fewer actual than formal parameters' + | 66: msg := 'element types of actual array and formal open array differ' + | 67: msg := 'actual parameter corresponding to open array is not an array' + | 68: msg := 'control variable must be integer' + | 69: msg := 'parameter must be an integer constant' + | 70: msg := 'pointer or VAR / IN record required as formal receiver' + | 71: msg := 'pointer expected as actual receiver' + | 72: msg := 'procedure must be bound to a record of the same scope' + | 73: msg := 'procedure must have level 0' + | 74: msg := 'procedure unknown in base type' + | 75: msg := 'invalid call of base procedure' + | 76: msg := 'this variable (field) is read only' + | 77: msg := 'object is not a record' + | 78: msg := 'dereferenced object is not a variable' + | 79: msg := 'indexed object is not a variable' + | 80: msg := 'index expression is not an integer' + | 81: msg := 'index out of specified bounds' + | 82: msg := 'indexed variable is not an array' + | 83: msg := 'undefined record field' + | 84: msg := 'dereferenced variable is not a pointer' + | 85: msg := 'guard or test type is not an extension of variable type' + | 86: msg := 'guard or testtype is not a pointer' + | 87: msg := 'guarded or tested variable is neither a pointer nor a VAR- or IN-parameter record' + | 88: msg := 'open array not allowed as variable, record field or array element' + | 89: msg := 'ANYRECORD may not be allocated' + | 90: msg := 'dereferenced variable is not a character array' + | 92: msg := 'operand of IN not an integer, or not a set' + | 93: msg := 'set element type is not an integer' + | 94: msg := 'operand of & is not of type BOOLEAN' + | 95: msg := 'operand of OR is not of type BOOLEAN' + | 96: msg := 'operand not applicable to (unary) +' + | 97: msg := 'operand not applicable to (unary) -' + | 98: msg := 'operand of ~ is not of type BOOLEAN' + | 99: msg := 'ASSERT fault' + | 100: msg := 'incompatible operands of dyadic operator' + | 101: msg := 'operand type inapplicable to *' + | 102: msg := 'operand type inapplicable to /' + | 103: msg := 'operand type inapplicable to DIV' + | 104: msg := 'operand type inapplicable to MOD' + | 105: msg := 'operand type inapplicable to +' + | 106: msg := 'operand type inapplicable to -' + | 107: msg := 'operand type inapplicable to = or #' + | 108: msg := 'operand type inapplicable to relation' + | 109: msg := 'overriding method must be exported' + | 110: msg := 'operand is not a type' + | 111: msg := 'operand inapplicable to (this) function' + | 112: msg := 'operand is not a variable' + | 113: msg := 'incompatible assignment' + | 114: msg := 'string too long to be assigned' + | 115: msg := 'parameter does not match' + | 116: msg := 'number of parameters does not match' + | 117: msg := 'result type does not match' + | 118: msg := 'export mark does not match with forward declaration' + | 119: msg := 'redefinition textually precedes procedure bound to base type' + | 120: msg := 'type of expression following IF, WHILE, UNTIL or ASSERT is not BOOLEAN' + | 121: msg := 'called object is not a procedure' + | 122: msg := 'actual VAR-, IN-, or OUT-parameter is not a variable' + | 123: msg := 'type is not identical with that of formal VAR-, IN-, or OUT-parameter' + | 124: msg := 'type of result expression differs from that of procedure' + | 125: msg := 'type of case expression is neither INTEGER nor CHAR' + | 126: msg := 'this expression cannot be a type or a procedure' + | 127: msg := 'illegal use of object' + | 128: msg := 'unsatisfied forward reference' + | 129: msg := 'unsatisfied forward procedure' + | 130: msg := 'WITH clause does not specify a variable' + | 131: msg := 'LEN not applied to array' + | 132: msg := 'dimension in LEN too large or negative' + | 133: msg := 'function without RETURN' + | 135: msg := 'SYSTEM not imported' + | 136: msg := 'LEN applied to untagged array' + | 137: msg := 'unknown array length' + | 138: msg := 'NEW not allowed for untagged structures' + | 139: msg := 'Test applied to untagged record' + | 140: msg := 'untagged receiver' + | 141: msg := 'SYSTEM.NEW not implemented' + | 142: msg := 'tagged structures not allowed for NIL compatible var parameters' + | 143: msg := 'tagged pointer not allowed in untagged structure' + | 144: msg := 'no pointers allowed in BYTES argument' + | 145: msg := 'untagged open array not allowed as value parameter' + | 150: msg := 'key inconsistency of imported module' + | 151: msg := 'incorrect symbol file' + | 152: msg := 'symbol file of imported module not found' + | 153: msg := 'object or symbol file not opened (disk full?)' + | 154: msg := 'recursive import not allowed' + | 155: msg := 'generation of new symbol file not allowed' + | 160: msg := 'interfaces must be extensions of IUnknown' + | 161: msg := 'interfaces must not have fields' + | 162: msg := 'interface procedures must be abstract' + | 163: msg := 'interface records must be abstract' + | 164: msg := 'pointer must be extension of queried interface type' + | 165: msg := 'illegal guid constant' + | 166: msg := 'AddRef & Release may not be used' + | 167: msg := 'illegal assignment to [new] parameter' + | 168: msg := 'wrong [iid] - [new] pair' + | 169: msg := 'must be an interface pointer' + | 177: msg := 'IN only allowed for records and arrays' + | 178: msg := 'illegal attribute' + | 179: msg := 'abstract methods of exported records must be exported' + | 180: msg := 'illegal receiver type' + | 181: msg := 'base type is not extensible' + | 182: msg := 'base procedure is not extensible' + | 183: msg := 'non-matching export' + | 184: msg := 'Attribute does not match with forward declaration' + | 185: msg := 'missing NEW attribute' + | 186: msg := 'illegal NEW attribute' + | 187: msg := 'new empty procedure in non extensible record' + | 188: msg := 'extensible procedure in non extensible record' + | 189: msg := 'illegal attribute change' + | 190: msg := 'record must be abstract' + | 191: msg := 'base type must be abstract' + | 192: msg := 'unimplemented abstract procedures in base types' + | 193: msg := 'abstract or limited records may not be allocated' + | 194: msg := 'no supercall allowed to abstract or empty procedures' + | 195: msg := 'empty procedures may not have out parameters or return a value' + | 196: msg := 'procedure is implement-only exported' + | 197: msg := 'extension of limited type must be limited' + | 198: msg := 'obsolete oberon type' + | 199: msg := 'obsolete oberon function' + | 200: msg := 'not yet implemented' + | 201: msg := 'lower bound of set range greater than higher bound' + | 202: msg := 'set element greater than MAX(SET) or less than 0' + | 203: msg := 'number too large' + | 204: msg := 'product too large' + | 205: msg := 'division by zero' + | 206: msg := 'sum too large' + | 207: msg := 'difference too large' + | 208: msg := 'overflow in arithmetic shift' + | 209: msg := 'case range too large' + | 210: msg := 'code too long' + | 211: msg := 'jump distance too large' + | 212: msg := 'illegal real operation' + | 213: msg := 'too many cases in case statement' + | 214: msg := 'structure too large' + | 215: msg := 'not enough registers: simplify expression' + | 216: msg := 'not enough floating-point registers: simplify expression' + | 217: msg := 'unimplemented SYSTEM function' + | 218: msg := 'illegal value of parameter (0 <= p < 128)' + | 219: msg := 'illegal value of parameter (0 <= p < 16)' + | 220: msg := 'illegal value of parameter' + | 221: msg := 'too many pointers in a record' + | 222: msg := 'too many global pointers' + | 223: msg := 'too many record types' + | 224: msg := 'too many pointer types' + | 225: msg := 'illegal sys flag' + | 226: msg := 'too many exported procedures' + | 227: msg := 'too many imported modules' + | 228: msg := 'too many exported structures' + | 229: msg := 'too many nested records for import' + | 230: msg := 'too many constants (strings) in module' + | 231: msg := 'too many link table entries (external procedures)' + | 232: msg := 'too many commands in module' + | 233: msg := 'record extension hierarchy too high' + | 235: msg := 'too many modifiers ' + | 240: msg := 'identifier too long' + | 241: msg := 'string too long' + | 242: msg := 'too many meta names' + | 243: msg := 'too many imported variables' + | 249: msg := 'inconsistent import' + | 250: msg := 'code proc must not be exported' + | 251: msg := 'too many nested function calls' + | 254: msg := 'debug position not found' + | 255: msg := 'debug position' + | 260: msg := 'illegal LONGINT operation' + | 261: msg := 'unsupported mode or size of second argument of SYSTEM.VAL' + | 265: msg := 'unsupported string operation' + | 270: msg := 'interface pointer reference counting restriction violated' + | 301: msg := 'implicit type cast' + | 302: msg := 'guarded variable can be side-effected' + | 303: msg := 'open array (or pointer to array) containing pointers' + | 900: msg := 'never used' + | 901: msg := 'never set' + | 902: msg := 'used before set' + | 903: msg := 'set but never used' + | 904: msg := 'used as varpar, possibly not set' + | 905: msg := 'also declared in outer scope' + | 906: msg := 'access/assignment to intermediate' + | 907: msg := 'redefinition' + | 908: msg := 'new definition' + | 909: msg := 'statement after RETURN/EXIT' + | 910: msg := 'for loop variable set' + | 911: msg := 'implied type guard' + | 912: msg := 'superfluous type guard' + | 913: msg := 'call might depend on evaluation sequence of params.' + | 930: msg := 'superfluous semicolon' + | 401: msg := 'bytecode restriction: no structured assignment' + | 402: msg := 'bytecode restriction: no procedure types' + | 403: msg := 'bytecode restriction: no nested procedures' + | 404: msg := 'bytecode restriction: illegal SYSTEM function' + | 410: msg := 'variable may not have been assigned' + | 411: msg := 'no proofable return' + | 412: msg := 'illegal constructor call' + | 413: msg := 'missing constructor call' + ELSE Strings.IntToString(err, msg) + END + END GetErrorMsg; + + PROCEDURE InsertMarks*; + VAR i, j, x, y, n, line, col, beg, end: INTEGER; s: ARRAY 128 OF CHAR; + BEGIN + n := errors; + IF n > maxErrors THEN n := maxErrors END; + (* sort *) + i := 1; + WHILE i < n DO + x := errPos[i]; y := errNo[i]; j := i-1; + WHILE (j >= 0) & (errPos[j] < x) DO + errPos[j+1] := errPos[j]; + errNo[j+1] := errNo[j]; + DEC(j) + END; + errPos[j+1] := x; errNo[j+1] := y; INC(i) + END; + (* insert *) + IF n > 0 THEN + WHILE n > 0 DO DEC(n); + LineColOf(errPos[n], line, col, beg, end); + IF name = "" THEN Console.WriteStr("???") + ELSE Console.WriteStr(name) + END; + Console.WriteChar(":"); + Strings.IntToString(line, s); Console.WriteStr(s); + Console.WriteChar(":"); + Strings.IntToString(col, s); Console.WriteStr(s); + Console.WriteChar(":"); + Strings.IntToString(errPos[n], s); Console.WriteStr(s); + Console.WriteStr(": "); + GetErrorMsg(errNo[n], s); + Console.WriteStr(s); + Console.WriteLn; + Console.WriteStr(" "); + FOR i := beg TO end DO + IF in[i] = 09X THEN Console.WriteStr(" ") + ELSE Console.WriteChar(in[i]) + END + END; + Console.WriteLn; + Console.WriteStr(" "); + FOR i := 1 TO col - 2 DO + Console.WriteChar(" ") + END; + Console.WriteChar("^"); + Console.WriteLn; + Console.WriteLn + END; + END + END InsertMarks; + + + (* fingerprinting *) + + PROCEDURE InitCrcTab; + (* CRC32, high bit first, pre & post inverted *) + CONST poly = {0, 1, 2, 4, 5, 7, 8, 10, 11, 12, 16, 22, 23, 26}; (* CRC32 polynom *) + VAR x, c, i: INTEGER; + BEGIN + x := 0; + WHILE x < 256 DO + c := x * 1000000H; i := 0; + WHILE i < 8 DO + IF c < 0 THEN c := ORD(BITS(c * 2) / poly) + ELSE c := c * 2 + END; + INC(i) + END; + crc32tab[ORD(BITS(x) / BITS(255))] := ORD(BITS(c) / BITS(255)); + INC(x) + END + END InitCrcTab; + + PROCEDURE FPrint* (VAR fp: INTEGER; val: INTEGER); + VAR c: INTEGER; + BEGIN +(* + fp := SYSTEM.ROT(ORD(BITS(fp) / BITS(val)), 1) (* bad collision detection *) +*) + (* CRC32, high bit first, pre & post inverted *) + c := ORD(BITS(fp * 256) / BITS(crc32tab[ORD(BITS(fp DIV 1000000H) / BITS(val DIV 1000000H)) MOD 256])); + c := ORD(BITS(c * 256) / BITS(crc32tab[ORD(BITS(c DIV 1000000H) / BITS(val DIV 10000H)) MOD 256])); + c := ORD(BITS(c * 256) / BITS(crc32tab[ORD(BITS(c DIV 1000000H) / BITS(val DIV 100H)) MOD 256])); + fp := ORD(BITS(c * 256) / BITS(crc32tab[ORD(BITS(c DIV 1000000H) / BITS(val)) MOD 256])); + END FPrint; + + PROCEDURE FPrintSet* (VAR fp: INTEGER; set: SET); + BEGIN FPrint(fp, ORD(set)) + END FPrintSet; + + PROCEDURE FPrintReal* (VAR fp: INTEGER; real: SHORTREAL); + BEGIN FPrint(fp, SYSTEM.VAL(INTEGER, real)) + END FPrintReal; + + PROCEDURE FPrintLReal* (VAR fp: INTEGER; lr: REAL); + BEGIN + FPrint(fp, LoWord(lr)); FPrint(fp, HiWord(lr)) + END FPrintLReal; + + PROCEDURE ChkSum (VAR fp: INTEGER; val: INTEGER); (* symbolfile checksum *) + BEGIN + (* same as FPrint, 8 bit only *) + fp := ORD(BITS(fp * 256) / BITS(crc32tab[ORD(BITS(fp DIV 1000000H) / BITS(val)) MOD 256])) + END ChkSum; + + + + (* compact format *) + + PROCEDURE WriteLInt (w: Files.Writer; i: INTEGER); + BEGIN + ChkSum(checksum, i); + w.WriteByte(SHORT(SHORT(i MOD 256))); i := i DIV 256; + ChkSum(checksum, i); + w.WriteByte(SHORT(SHORT(i MOD 256))); i := i DIV 256; + ChkSum(checksum, i); + w.WriteByte(SHORT(SHORT(i MOD 256))); i := i DIV 256; + ChkSum(checksum, i); + w.WriteByte(SHORT(SHORT(i MOD 256))) + END WriteLInt; + + PROCEDURE ReadLInt (r: Files.Reader; VAR i: INTEGER); + VAR b: BYTE; x: INTEGER; + BEGIN + r.ReadByte(b); x := b MOD 256; + ChkSum(checksum, b); + r.ReadByte(b); x := x + 100H * (b MOD 256); + ChkSum(checksum, b); + r.ReadByte(b); x := x + 10000H * (b MOD 256); + ChkSum(checksum, b); + r.ReadByte(b); i := x + 1000000H * b; + ChkSum(checksum, b) + END ReadLInt; + + PROCEDURE WriteNum (w: Files.Writer; i: INTEGER); + BEGIN (* old format of Oberon *) + WHILE (i < -64) OR (i > 63) DO ChkSum(checksum, i MOD 128 - 128); w.WriteByte(SHORT(SHORT(i MOD 128 - 128))); i := i DIV 128 END; + ChkSum(checksum, i MOD 128); + w.WriteByte(SHORT(SHORT(i MOD 128))) + END WriteNum; + + PROCEDURE ReadNum (r: Files.Reader; VAR i: INTEGER); + VAR b: BYTE; s, y: INTEGER; + BEGIN + s := 0; y := 0; r.ReadByte(b); + IF ~r.eof THEN ChkSum(checksum, b) END; + WHILE b < 0 DO INC(y, ASH(b + 128, s)); INC(s, 7); r.ReadByte(b); ChkSum(checksum, b) END; + i := ASH((b + 64) MOD 128 - 64, s) + y; + END ReadNum; + + PROCEDURE WriteNumSet (w: Files.Writer; x: SET); + BEGIN + WriteNum(w, ORD(x)) + END WriteNumSet; + + PROCEDURE ReadNumSet (r: Files.Reader; VAR x: SET); + VAR i: INTEGER; + BEGIN + ReadNum(r, i); x := BITS(i) + END ReadNumSet; + + PROCEDURE WriteReal (w: Files.Writer; x: SHORTREAL); + BEGIN + WriteLInt(w, SYSTEM.VAL(INTEGER, x)) + END WriteReal; + + PROCEDURE ReadReal (r: Files.Reader; VAR x: SHORTREAL); + VAR i: INTEGER; + BEGIN + ReadLInt(r, i); x := SYSTEM.VAL(SHORTREAL, i) + END ReadReal; + + PROCEDURE WriteLReal (w: Files.Writer; x: REAL); + BEGIN + WriteLInt(w, LoWord(x)); WriteLInt(w, HiWord(x)) + END WriteLReal; + + PROCEDURE ReadLReal (r: Files.Reader; VAR x: REAL); + VAR h, l: INTEGER; + BEGIN + ReadLInt(r, l); ReadLInt(r, h); x := Compound(l, h) + END ReadLReal; + + + (* read symbol file *) + + PROCEDURE SymRCh* (VAR ch: SHORTCHAR); + VAR b: BYTE; + BEGIN + inSym.ReadByte(b); ch := SHORT(CHR(b)); + ChkSum(checksum, b) + END SymRCh; + + PROCEDURE SymRInt* (): INTEGER; + VAR k: INTEGER; + BEGIN + ReadNum(inSym, k); RETURN k + END SymRInt; + + PROCEDURE SymRSet* (VAR s: SET); + BEGIN + ReadNumSet(inSym, s) + END SymRSet; + + PROCEDURE SymRReal* (VAR r: SHORTREAL); + BEGIN + ReadReal(inSym, r) + END SymRReal; + + PROCEDURE SymRLReal* (VAR lr: REAL); + BEGIN + ReadLReal(inSym, lr) + END SymRLReal; + + PROCEDURE eofSF* (): BOOLEAN; + BEGIN + RETURN inSym.eof + END eofSF; + + PROCEDURE OldSym* (IN modName: ARRAY OF SHORTCHAR; VAR done: BOOLEAN); + VAR tag: INTEGER; d: Directory; + + PROCEDURE Old (IN path: Files.Name; IN modName: ARRAY OF SHORTCHAR; legacy: BOOLEAN): Files.File; + VAR f: Files.File; res: INTEGER; loc: Files.Locator; dir, name: Files.Name; + BEGIN + Kernel.Utf8ToString(modName, name, res); + loc := Files.dir.This(path); + IF legacy THEN + Kernel.SplitName(name, dir, name); + Kernel.MakeFileName(name, Kernel.symType); + loc := loc.This(dir).This(symDir); + f := Files.dir.Old(loc, name, Files.shared); + IF (f = NIL) & (dir = "") THEN + loc := Files.dir.This(path).This(SYSdir).This(symDir); + f := Files.dir.Old(loc, name, Files.shared) + END + ELSE + Kernel.MakeFileName(name, Kernel.symType); + f := Files.dir.Old(loc, name, Files.shared) + END; + RETURN f + END Old; + + BEGIN + done := FALSE; + IF modName = "@file" THEN + oldSymFile := file + ELSE + oldSymFile := Old(symPath, modName, legacy); + d := symList; + WHILE (oldSymFile = NIL) & (d # NIL) DO + oldSymFile := Old(d.path, modName, d.legacy); + d := d.next + END + END; + IF oldSymFile # NIL THEN + inSym := oldSymFile.NewReader(inSym); + IF inSym # NIL THEN + ReadLInt(inSym, tag); + IF tag = SFtag THEN done := TRUE ELSE err(151) END + END + END + END OldSym; + + PROCEDURE CloseOldSym*; + BEGIN + IF oldSymFile # NIL THEN oldSymFile.Close; oldSymFile := NIL END + END CloseOldSym; + + + (* write symbol file *) + + PROCEDURE SymWCh* (ch: SHORTCHAR); + BEGIN + ChkSum(checksum, ORD(ch)); + outSym.WriteByte(SHORT(ORD(ch))) + END SymWCh; + + PROCEDURE SymWInt* (i: INTEGER); + BEGIN + WriteNum(outSym, i) + END SymWInt; + + PROCEDURE SymWSet* (s: SET); + BEGIN + WriteNumSet(outSym, s) + END SymWSet; + + PROCEDURE SymWReal* (r: SHORTREAL); + BEGIN + WriteReal(outSym, r) + END SymWReal; + + PROCEDURE SymWLReal* (r: REAL); + BEGIN + WriteLReal(outSym, r) + END SymWLReal; + + PROCEDURE SymReset*; + BEGIN + outSym.SetPos(4) + END SymReset; + + PROCEDURE NewSym* (IN modName: ARRAY OF SHORTCHAR); + VAR res: INTEGER; loc: Files.Locator; dir: Files.Name; + BEGIN + Kernel.Utf8ToString(modName, ObjFName, res); + loc := Files.dir.This(symPath); + IF legacy THEN + Kernel.SplitName(ObjFName, dir, ObjFName); + loc := loc.This(dir).This(symDir) + END; + symFile := Files.dir.New(loc, Files.ask); + IF symFile # NIL THEN + outSym := symFile.NewWriter(NIL); + WriteLInt(outSym, SFtag) + ELSE + err(153) + END + END NewSym; + + PROCEDURE RegisterNewSym*; + VAR res: INTEGER; name: Files.Name; + BEGIN + IF symFile # NIL THEN + name := ObjFName$; + Kernel.MakeFileName(name, Kernel.symType); + symFile.Register(name, Kernel.symType, Files.ask, res); + symFile := NIL + END + END RegisterNewSym; + + PROCEDURE DeleteNewSym*; + BEGIN + IF symFile # NIL THEN symFile.Close; symFile := NIL END + END DeleteNewSym; + + + (* write object file *) + + PROCEDURE ObjW* (ch: SHORTCHAR); + BEGIN + outObj.WriteByte(SHORT(ORD(ch))) + END ObjW; + + PROCEDURE ObjWNum* (i: INTEGER); + BEGIN + WriteNum(outObj, i) + END ObjWNum; + + PROCEDURE ObjWInt (i: SHORTINT); + BEGIN + outObj.WriteByte(SHORT(SHORT(i MOD 256))); + outObj.WriteByte(SHORT(SHORT(i DIV 256))) + END ObjWInt; + + PROCEDURE ObjWLInt* (i: INTEGER); + BEGIN + ObjWInt(SHORT(i MOD 65536)); + ObjWInt(SHORT(i DIV 65536)) + END ObjWLInt; + + PROCEDURE ObjWBytes* (IN bytes: ARRAY OF SHORTCHAR; n: INTEGER); + TYPE P = POINTER TO ARRAY [untagged] 100000H OF BYTE; + VAR p: P; + BEGIN + p := SYSTEM.VAL(P, SYSTEM.ADR(bytes)); + outObj.WriteBytes(p^, 0, n) + END ObjWBytes; + + PROCEDURE ObjLen* (): INTEGER; + BEGIN + RETURN outObj.Pos() + END ObjLen; + + PROCEDURE ObjSet* (pos: INTEGER); + BEGIN + outObj.SetPos(pos) + END ObjSet; + + PROCEDURE NewObj* (IN modName: ARRAY OF SHORTCHAR); + VAR res: INTEGER; loc: Files.Locator; dir: Files.Name; + BEGIN + errpos := 0; + Kernel.Utf8ToString(modName, ObjFName, res); + loc := Files.dir.This(codePath); + IF legacy THEN + Kernel.SplitName(ObjFName, dir, ObjFName); + loc := loc.This(dir).This(codeDir) + END; + objFile := Files.dir.New(loc, Files.ask); + IF objFile # NIL THEN + outObj := objFile.NewWriter(NIL); + WriteLInt(outObj, OFtag) + ELSE + err(153) + END + END NewObj; + + PROCEDURE RegisterObj*; + VAR res: INTEGER; name: Files.Name; + BEGIN + IF objFile # NIL THEN + name := ObjFName$; + Kernel.MakeFileName(name, Kernel.objType); + objFile.Register(name, Kernel.objType, Files.ask, res); + objFile := NIL; outObj := NIL + END + END RegisterObj; + + PROCEDURE DeleteObj*; + BEGIN + IF objFile # NIL THEN objFile.Close; objFile := NIL END + END DeleteObj; + + + PROCEDURE InitHost; + VAR test: SHORTINT; lo: SHORTCHAR; + BEGIN + test := 1; SYSTEM.GET(SYSTEM.ADR(test), lo); LEHost := lo = 1X; + InfReal := SYSTEM.VAL(SHORTREAL, InfRealPat); + MinReal32 := SYSTEM.VAL(SHORTREAL, MinReal32Pat); + MaxReal32 := SYSTEM.VAL(SHORTREAL, MaxReal32Pat); + MinReal64 := Compound(MinReal64PatL, MinReal64PatH); + MaxReal64 := Compound(MaxReal64PatL, MaxReal64PatH) + END InitHost; + +BEGIN + InitCrcTab; + InitHost +END DevCPM. diff --git a/src/generic/Dev/Mod/CPP.odc b/src/generic/Dev/Mod/CPP.odc new file mode 100644 index 0000000000000000000000000000000000000000..16801ddc99f6ad8706bc71cb64b318070811fee1 GIT binary patch literal 63647 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 literal 0 HcmV?d00001 diff --git a/src/generic/Dev/Mod/CPS.odc b/src/generic/Dev/Mod/CPS.odc new file mode 100644 index 0000000000000000000000000000000000000000..0254946eaebd3165806db33c989e8ab149395876 GIT binary patch literal 15376 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

  • 10U`0*fTa8Y=4?l=swv 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 U|Nde5fA|kRn#n%>J2Nx?7q7u)0RR91 literal 0 HcmV?d00001 diff --git a/src/generic/Dev/Mod/CPV486.odc b/src/generic/Dev/Mod/CPV486.odc new file mode 100644 index 0000000000000000000000000000000000000000..f9004c8121704526aed2b4943fb71a67ea4be879 GIT binary patch literal 68156 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 literal 0 HcmV?d00001 diff --git a/src/generic/Dev2/Mod/LnkBase.odc b/src/generic/Dev2/Mod/LnkBase.odc new file mode 100644 index 0000000000000000000000000000000000000000..08d481434485617cc7a383a5316245551bd22779 GIT binary patch literal 17733 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 literal 0 HcmV?d00001 diff --git a/src/generic/Dev2/Mod/LnkChmod.odc b/src/generic/Dev2/Mod/LnkChmod.odc new file mode 100644 index 0000000000000000000000000000000000000000..220b6b9499a60acb36f725e529fdc28d73b7d00f GIT binary patch literal 1949 zcmah~Pfrs;6rX}o7pWRUqT%ACno!ER0tXXHNQ8EQ#{MB~L839R!h~+x?vmYUfy9G> zs|SxJ9yH7*_nSALIhEI=yihRBS7mO;0y=!$T>nwPAY7kbI*R?;>^FelQHy!F)AlQVko4@ zhhIVFO;&Yd6Q;YdphsbGqt9>Jsa2JS~3;av|QVAz~tDz+t%syh100@7X@ZbQ+!youkPB*Qjjd%CFZ~$LU0ma;aBYsxE_LGxK!A{8XCtm=@kTFMi10*aZhnE!JVfD<(F zJOM?x8l{*;x_v2C4|W-S5>Ub-$a6OeR-NIoB9o+Gdf`+RPYfTQrASpK39bP2CC_$t zsxB&mc!Yt=G7r1bDO3}W32A`{WtkLJK?-gitI|ExExfz}L#KFM@Y+DSIKJf30!|zk zK@G%t8?pglv-8|W1G_17l??Y(7sRF#HHLCem+WT>FfZAXXX>Y#y5ZG6FPQGKK>mN&!5d2`JVbh$UonH`sn}w literal 0 HcmV?d00001 diff --git a/src/generic/Dev2/Mod/LnkLoad.odc b/src/generic/Dev2/Mod/LnkLoad.odc new file mode 100644 index 0000000000000000000000000000000000000000..4a2f790a4d04d19b19bd0c4f7111f85349778dd2 GIT binary patch literal 15077 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 br|*B9`>pT4EdT%FtG|=`?f?FxT<(7W2ec>; literal 0 HcmV?d00001 diff --git a/src/generic/Dev2/Mod/LnkWriteElfStatic.odc b/src/generic/Dev2/Mod/LnkWriteElfStatic.odc new file mode 100644 index 0000000000000000000000000000000000000000..3ca7d6da6cff2109cafd46fa14ddfa855bfac11f GIT binary patch literal 7370 zcmc&(U2h{-8TM{Jz|vYEL=h?o9jTx=iDevbnl3S^aO_E9;k6^%yG#2lsOpZ235^e7Y$ zp`beczJR~oZ_4n)l#2Vo&>Lw{Dfua=3}@vO#Hesa-dGr~UKXjj+#kM?%jGftEuQjw z`q{v{h_s1tGqE}W$FQs0hKUav`<9mSp~x^+KuF3EN?9=P>Qy7>>#yf>U&8pycuB0MA|Q{QIBSjt^saG(%oiLTMOh)=V(<-QLy@&r^N;uat zoS)=Am-##=%lwv94Ic@DHxqqeDIn>sQZ z+MYaqC-fuF86Ec{H}a2ag+ji#Qpo39CqW33)9BI-y~*Q16$jy2I9gUERjsUTl-Jfa zRokDOU8q%1H^+VyUaEdD3eXBB{^Q_0MYj`r-gdvK*4D}u5Z6cEg*zE~q3WOd;ic=P zX}eQzLfQ=>ZJoOlSTXTu8G(({aWE|8SC(OI>;8VXH&8$H!ihI3S+9hmq}tnRbIZcE z-I-TXJO0R<(alD;(;wtv&(J$2sy-Z|-^|pOx>s4hSE*F?NHutO-%%jKGQ)}hvc1g? zf^iK{{Ofy1ksnNe={b#VuL)3o=D+W4s#a&<>^eQtCnp6mZCv2w~ zfzjpke+op-)VUu4hKpHjY@y&F{h@tYw?uln; z-I0GXNxY#<0f{4tU}T+YqEkOb4r;%G~O){gPp>_A(h9XAW zzp~6cd86Y!&qZ+=@;9qBW(ohmF%5&0&>gE&p-_?g2!4nW)6=Mngm?^lMnsK5fpsP* za3k|>l{vM*MsOzCx@$=dmBq^xx{VAWufd{1{$afbIl)=Pn%vZtS>~AH0k$Anq9K8( zi}3O=TTJu~CJ#^|DoFu=N7xWcYUoC8Nu9ePLTqYP3n76TGW4N_&H zxbn>3av{Ip>o%O`gPx{;YY8HW5X z*tP!uvg^e?dU4KFEY`1yML!CQt&T#)pZPRk`6jwUKMJNOA3}{?cH~WgP=GKk_MEnDQyh( z?+3HuviiOP<)TRytDAa6B6L32!olKA>Ki*y&l?3tE5*zTPZ>n{mI{76&(h3jXnMzH zX=4k_>-Ng<=l2JP?QXrv{#sL*?C&*um~7P8Xu12?{lvTQj)17t)Ds>YG((7ficwXl zkJ--6z5vmQds=ysMUZJSB0s4LB?314&Y-3@kr;)=3xT$a}bD#wrbqU7_J(*fsLgJTjh%^mOJluT=uU*0x0Xs@8oCuQ+`Tuh=8- zRoUz%Fxo3vn>sNVw+tz?`=}J2df*jniiLxw@?2dd-L`hUh-sd!6uS=wV!l3U(=a`v z=^Uk2a#D))oya)uG|&dxB4Q_ru;R!ON5wc{jd_vo*l_xl` zC55c(-(t*CNOvS=1r4^ODp^K-TGZ<+RjX-M=1N#4Y4lZ}Ld$f~3|Zg0oy(eFD;J-c zQo~;se_^Pkm<%Sx3u$_;ibX?LNjBy9>Daph1lyZN-f8bN+Vy__Zk2o6K}`YBtPkqd zc7NMK9v(Ix^mbsii5arZzn z9K$=#fEQq3s#?32v(s}N!neMchIaRzjzCpqdrnThcONn~-~y@xdhZ|dz65^-vm{1>N`gUe zCHy=k8p$XHeGpsQkV+DKl`Wgs8eJ#`ru|5P){ASHApz%jVa1!c&VZ1w7nA;%VTqST z28y#Hb7WXKgIIl@NeLCZl1pZar&@$u$KDjvo>;hSw;2vXk#)(w0Se z=E^iHn#~@(a>yz_!o?e1S@(7x17eJB%!m<`u^EFCqqaYj?NHx`h9lF6E z5tf9FRtxA^{%~o>3D>4Cc+@?U1G{*HS9kFNqNc{1=EbIc=cuMJq!EnAc%g<+*dkrn z7^SZuIee!?=lPtKhkjV@cu$JSY;fvJjevA|7VW#y>9ToIT6SlTZ9!3j5k`Kg{E$6K zFF*{+eJ|og8C?ru6oOPEGLY-qPtpKQxoc(}FYCp#q~lKW0m{|m1xBtjCYAKF-1AOQ z!(Paxpxx}aV;uhDDL0yw(sccZ7 z4pPO?W$~lMw=AuY)I;AL z<^K5_O`rN81*$v$Hh+Jd=I(r__ICPn}*X69Oyb5+CA2P*^(|YQ&)>j%GZTGK*+PYD7RI3M6-S*M_0A$d=R= z$!5BnGb1}Tf^`l#juz8+R^*LAF}5%5I3HDlu5x=TofT0si?h7(GKpX7!F&qd ze?2JDEGANX$p}uz&+p^!m*17gp9fRCNXPL+qYCf`t@4;Rf)+DHXA(~Z@a^vk)=K5S zA6F_>JpU)Y<@3dFhVh$1lL$6F)xO!az5SX2;uneiJB{V%g2PY&Bmp7BvO?b5uNyqc zqe|ru@f_h>fBxnJd~2Ev*g;Wb$@!v)^D-w51MyAsT_I%Ue&w(KT^=gG&|lKH_{Q)* zzHZR=7Za)nWXhA4E6Fq+zV+?z7}WoUZ?gL@`dzc@@eGQaiB_b@!FAZyw}iEyKfuHH z&5P#KjK7Uf3;1n5c%Dr2^Iv^X`6t*bJ6z`<^W}@T8)l6CS|=&OXh}WbuwOi^RQ~sC zFM91yjytLyziJ-Ou0PF^B0i1xH#VxZ`y172_cG1UcU9a(SvQ3aTG`Mew@eIs}dlIo@dE4%5KyZhJboSNqL}FI-Mp3 zCR0k#1~>;rG`jXkn}!+(F8vz53=X+ip&v|=%NhM2W*~k+Px*u$k9LH6N7NW=OU5^M z$zl9v-cB<1icHvK1)nd@^P9Ygr-7cx-vLw?=Xvj!LM#!(T~)vGAW>nh8$QC%g|d0JOs0sm+5 zB;8YH#(mO>Uc*`m8HNvvY#5zSfD>cv%N{KoFUjmuIw=Ym*-117sabb6j^8Zdi4P~y zC72s@hFWf?{a&ln{-obgVv?;ZRU2KQ{|Jk$b#&0*#IR?b=iL*Hx*?;U-4t<6hSacr z0I<2axxqzXkpO6;x`eu^YMz>Rq1DLWD0mIkeDoOj_thJ&_&2KEeaR-n>k2`ukO5`1 zs};g_|Gx

    MVVA$UqoeOe?~G-PF1#3MN9+8uq&<&-c|No;f?B=IG{B;+oJRCL$J0 zC2e!er$=4*`}_yV57oES_GhZyQ?ShyebIn8NL1WCY1NWVW!$O8kf=W=0ju!aun7+k zFa{pzS-t(8M&n^xo2PzNhxVtZA#JB=UfaZU7`bjbLl^B_Fk+J0{daygOG56>lHxwa zBYt08z$ibP!->CVr^w=I`buWc7PGU9ES;X^uMsQgvG>(1 zF3wikcg#H6`En#k8c!yCLP%T8K^fihSvs5Cu#vWB-3kniQi0a2AFBmEt}byxtZvP~ zl4pcLFuuDWKvP6C-DlL3Fx@?*Rj2c!;m5!>)$piuLgOuiE)OM-F3=+iX>3>184=oAq!NQRw!mrejObcTI= z*L@Z%voc~eVbtXjBup^d0hm@g<8e*Mk@hX+NUN`)5RnT7YjAknTN37l%C$H^$iZs< zL7GE4Kwg4X&_mh@(&=NkDDe3HKIVB`P?7olTJMvgOrjHHlB}P|6rY?6C#!Znk}7tt zq0rf$m98BZN&}pf#@We;&r5TQb`Xvu%a-!5;#phiWP;4TJDrm_MyN@0zNbv$uM~Wv z4r({k^K@dI9U8l1pOyqt&^@GCq8V`U88l-p9w&Jr2z2OR-?!9B_ZUF~Q*-S>;aHkX z#LB)5LmTi}jTw6C>LViih|a>bf*QTjZJVb=DObz^@ffMQ{A)(69tKT)jmMB7yAkt~v<;qwPZs|8e%}AdBv%k5m z?yDNa$>zzVl`gPx*it((A=*;s8Una2^~6J2kTQ-&%)s7Su{c zuceK-DIp973b9AZdsY21q0#^9jG`+sMe|frywUiIHZh}@JYMW>44R?BG)-3W0f$D; z)eeFbk|Np3c|@|zv>61N=opEYlo3rviwX8)$I%UhW7XlMA8HYqmUavlQxz2l?%eO? zIw=r4TI1kDS0&GkUuzw_VPp*sk6R2*GkXgT?hhMla6o{mZr_r92-A`4D$g3ztqH7R%#3gO5A`o$|LEsUWRJ8^H^|S_oM_kg= z5&{$~AX&H=nU7|Pl-gvm-df-tWG?~hu`_Mkot3u-83k<8BB)9&4$}I^<)wG0>?B;g zQa~`t8md$@9N^Zwq0y{3qhUOKw6FL~jXqV6^~*xPeHR;xBp*c?H%m|ZkA z!{bBn{h9?vK67hg3xb@MP7v(}{r8RCRm zs(sy@#yg0Rs5QOJbj{y6oE49xdz>fIE1);0rA8CoNhc!}Xqbcd5rV#*=7VB!PMgr4 zjEf7!WV8Wlr-^zCR_Dj?WxIMgS-bI0;NFYx->W}n3B$UE-I~V&TLl8HySPwAs*0;v z;gBOoWtc#*`5CZdOHZdwSsfoOMiF10+01&Jh@0CwDFU?@Sj6gkBE$&59P5Jn8u2-$?G z@KgrCUhG0DGh&UBwT9k>km?TJ3?_OJiLl{Fp>cU6f}krplqNHdcqx4~_{&k!)7Y#% z0uo~wCW7_mafS#tyBtW#^QBQl?M3vXG^-8AK8HbQ)A-%}fO*gPdUS{~7 zdeqof57ej0Y@EK%v4`HqrYy7oLnkr>9uG>*S*GxU*G3^klw~BQZ=7hU$KY&T#iQ%N zVj5URv*v28;VLlz+|^%2Su`r*3`Lb>WP-hsyCy^q7R|w9Y1W`ypF6JU1-14h^p@T= zprDS6_Bf@_ks~wplu~5gZAjaB40IS{-An&fbTAu}BEtgux-Sl%ch1^foHGx5{m=K* z4|X2^Fp!P)k|_0>J)S-ql-x|C@5ugFNu2_a%uj^?2kN$%`fM=(?IJp7g#ld)>$U;< zbTWX2w9`d4ioaxH)QyZ1J8wp@M9MpjZpB%VTqMW>Ep|GRRmR+2Rv(lG#7WW7r+s&t zwawc5+Ic)52N_OD3S|1y*$qy=x0u){jR&JRUewSJdc-(dbZz znq4H9cNzW+MX|9my7sQZ*@s7L#@Nk)HK{Klr5#VA8;hHlT5w8*3r3L3mjJbn`>KyZ z9nQ>^Nu0iPyjj>|jnyJ9<;AulE|#xxmJj%(gW-wM0TI`xS3J~{KAu?TQc1)hl!WC3 zqH)evm~ovoD@H2ULw(X+xr8P_zLGnhPFRDwOU0REimS!!+9g*3vC?4*EG|arN~J3R zVYNfE^fKanqVqhR;2M)+l+*$=rByJ5+VVRJ)uxDe=Q6U061m3q;bEA1G$r?t&fS{k zVoPeuz>k9BeZ)6<(;rRe3PCB!u);L0wp1=_nZ;yV=W1$K?F!veom{FZ-&R9*DigJ= zD9cy~H8D-c{(Qh2jn1Ma`Oq6(YmorxEf{Z`omo)7ztI~Q4t#~XkT`|M@2ZwG| zO1rExsSbwAaE(jVl+i@&g22wto@LnDIK7TP*?`S6p*R+vLf6mwkW^j`(k*pYTs-ml z&Iv1C&f9|}W+pl}025e@DQ<&_i+&&9VV1ii$vP3e=D{noT3U!1XmSOHh40WDurEf< zQl?!Ra+qeXQQnI)WQNJCJVc9P%b$Ej^f2X_tiW%jXuao<+FwBIdpv?o{5$O7QVcb| zqlP`z#9<&MZ3I;4%Uh&h$+Ou#;X=o{gGFW5^4KXI}3&ZXKb}VyYFYm5!!0DCls+FUum>(AM$`aT4E|<72 zr1Y|Jf(neJe2}bN`=GmY^hR1Q7BjiniHI&NOqahc{@DSWuf_0WxzGUIf3j(FX zNKv^Q9U&RdZv9iqYaD=1~afQt)|uy{g~Fa=V-Oc6B<@toVLkn28#SDf64 zD1>gtpZQpBSRp zrBwv!!gNR%tjQdBI!ea<##PxMr3vEtXk#H>0!&r)P%pIz&=u*T)dkn@0AcR3;4ok7HYE=yUy3?8oBVFuiN zCMSKt`3^TBZVsm`I^p3By+CxlIw$gP;x1o!MURUYWn~NA0Y{Z!8GWBM0kagw_Y8GxWsLk)y`kYC5V7-`CiOay^>iI6O83jW({qkGCT98 z`ZLK*%zRgv5SK0~giUIbha*@1US`$Fi*r7~ilu8I(gz9}=cJGv`}{y&$!OTbUG3(=+qcBE2?V{gIFs0BR) zbCpY$r6twp(aD+(bZ?=rrgCMVI=IgCTg&Iavb*72R5!o#26lLjllXPbzYVVv*?hyX z<6g^YR9xX&i|&r{Yb|2*5e2^3K?EX=tcDghqA`dIUeblIARrlF$^le}yqo=yyEgStCs8*4gpO*0_P+_Nk)<2QryZLF`x-N@z zsn7lJ?2pW^koe=X;Pb)X@<&$omrJX^S^5(@R)!p8IG?Ee*Wc^$!7scp>ciifzki%p zKK#@DkHg>ZEfe((i`9JdM_KaukpKVsm#-@S{NrC${^Do9Cx8F?&A+Pr<^TLcrSgB5 CMIUhh literal 0 HcmV?d00001 diff --git a/src/generic/Dsw/Mod/Compiler486Main.cp b/src/generic/Dsw/Mod/Compiler486Main.cp new file mode 100644 index 0000000..77ded19 --- /dev/null +++ b/src/generic/Dsw/Mod/Compiler486Main.cp @@ -0,0 +1,320 @@ +MODULE DswCompiler486Main; + + IMPORT Kernel, HostFiles, Files, Console, Strings, DswDocuments, + DevCPM, DevCPT, DevCPB, DevCPP, DevCPE, DevCPV := DevCPV486, DevCPS, + DevCPH; + + CONST + (* compiler options: *) + checks = 0; allchecks = 1; assert = 2; obj = 3; ref = 4; allref = 5; + srcpos = 6; reallib = 7; signatures = 8; + hint = 29; oberon = 30; errorTrap = 31; + defopt = {checks, assert, obj, ref, allref, srcpos, signatures}; + + emulong = 0; + defopt2 = {}; + + TYPE + Elem = POINTER TO RECORD + dir, name, path: Files.Name; + outsym, outcode: Files.Name; (* dir *) + insym: DevCPM.Directory; + found: BOOLEAN; (* COM Aware *) + opts, opts2: SET; + next: Elem + END; + + VAR + u: Elem; + + PROCEDURE GetPath (IN path: ARRAY OF CHAR; OUT dir, name: Files.Name); + VAR i, j, len: INTEGER; + BEGIN + len := LEN(path$); + i := len - 1; + WHILE (i >= 0) & (path[i] # '/') DO DEC(i) END; + IF i >= 0 THEN + FOR i := 0 TO i - 1 DO + dir[i] := path[i] + END; + dir[i] := 0X + ELSE + dir := "" + END; + j := i + 1; i := 0; + WHILE path[j] # 0X DO + name[i] := path[j]; + INC(i); INC(j) + END; + name[i] := 0X + END GetPath; + + PROCEDURE InitOptions; + VAR + i: INTEGER; + found: BOOLEAN; + insym, sym: DevCPM.Directory; + outsym, outcode: Files.Name; + p: ARRAY 256 OF CHAR; + h, t: Elem; + opts, opts2: SET; + + PROCEDURE Check; + BEGIN + IF i >= Kernel.argc THEN + Console.WriteStr("required more parameters for "); + Console.WriteStr(p); Console.WriteLn; + Kernel.Quit(1) + END + END Check; + + BEGIN + outsym := ""; outcode := ""; + opts := defopt; opts2 := defopt2; found := FALSE; + h := NIL; t := NIL; insym := NIL; + i := 1; + WHILE i < Kernel.argc DO + IF Kernel.argv[i, 0] = "-" THEN + p := Kernel.argv[i]$; + INC(i); + IF p = "-legacy" THEN + DevCPM.legacy := TRUE + ELSIF p = "-outsym" THEN + Check; + outsym := Kernel.argv[i]$; + INC(i) + ELSIF p = "-outcode" THEN + Check; + outcode := Kernel.argv[i]$; + INC(i) + ELSIF p = "-symdir" THEN + Check; + sym := insym; + NEW(insym); + insym.path := Kernel.argv[i]$; + insym.legacy := FALSE; + insym.next := sym; + INC(i) + ELSIF p = "-legacysymdir" THEN + Check; + sym := insym; + NEW(insym); + insym.path := Kernel.argv[i]$; + insym.legacy := TRUE; + insym.next := sym; + INC(i) + ELSIF p = "-allchecks" THEN + INCL(opts, allchecks) + ELSIF p = "-no-allchecks" THEN + EXCL(opts, allchecks) + ELSIF p = "-srcpos" THEN + INCL(opts, srcpos) + ELSIF p = "-no-srcpos" THEN + EXCL(opts, srcpos) + ELSIF p = "-structref" THEN + INCL(opts, allref) + ELSIF p = "-no-structref" THEN + EXCL(opts, allref) + ELSIF p = "-ref" THEN + INCL(opts, ref) + ELSIF p = "-no-ref" THEN + EXCL(opts, ref) + ELSIF p = "-obj" THEN + INCL(opts, obj) + ELSIF p = "-no-obj" THEN + EXCL(opts, obj) + ELSIF p = "-assert" THEN + INCL(opts, assert) + ELSIF p = "-no-assert" THEN + EXCL(opts, assert) + ELSIF p = "-checks" THEN + INCL(opts, checks) + ELSIF p = "-no-checks" THEN + EXCL(opts, checks) + ELSIF p = "-hints" THEN + INCL(opts, hint) + ELSIF p = "-no-hints" THEN + EXCL(opts, hint) + ELSIF p = "-trap" THEN + INCL(opts, errorTrap) + ELSIF p = "-no-trap" THEN + EXCL(opts, errorTrap) + ELSIF p = "-oberon" THEN + INCL(opts, oberon) + ELSIF p = "-no-oberon" THEN + EXCL(opts, oberon) + ELSIF p = "-com-aware" THEN + found := TRUE + ELSIF p = "-no-com-aware" THEN + found := FALSE + ELSIF (p = "-v") OR (p = "-verbose") THEN + DevCPM.verbose := MIN(DevCPM.verbose + 1, 3); + ELSIF p = "-main" THEN + (* ignore *) + ELSIF p = "-no-main" THEN + (* ignore *) + ELSIF p = "-include0" THEN + (* ignore *) + ELSIF p = "-no-include0" THEN + (* ignore *) + ELSIF p = "-includedir" THEN + Check; + (* ignore *) + INC(i) + ELSIF p = "-long-calls" THEN + INCL(opts2, emulong) + ELSIF p = "-no-long-calls" THEN + EXCL(opts2, emulong) + ELSE + Console.WriteStr("unknown option "); + Console.WriteStr(p); Console.WriteLn; + Kernel.Quit(1) + END + ELSE + IF h = NIL THEN NEW(h); t := h + ELSE NEW(t.next); t := t.next + END; + t.path := Kernel.argv[i]$; + t.outcode := outcode; + t.outsym := outsym; + t.insym := insym; + t.found := found; + t.opts := opts; + t.opts2 := opts2; + GetPath(t.path, t.dir, t.name); + IF t.name = "" THEN + Console.WriteStr("specified path to directory"); Console.WriteLn; + Kernel.Quit(1) + END; + INC(i) + END + END; + u := h + END InitOptions; + + PROCEDURE Module (source: POINTER TO ARRAY OF CHAR; m: Elem; OUT error: BOOLEAN); + VAR ext, new: BOOLEAN; p: DevCPT.Node; + BEGIN + DevCPM.Init(source); + DevCPM.symList := m.insym; + DevCPM.codePath := m.outcode; + DevCPM.symPath := m.outsym; + DevCPM.name := m.path; + IF m.found THEN INCL(DevCPM.options, DevCPM.comAware) END; + IF errorTrap IN m.opts THEN INCL(DevCPM.options, DevCPM.trap) END; + IF oberon IN m.opts THEN INCL(DevCPM.options, DevCPM.oberon) END; + DevCPT.Init(m.opts); + DevCPB.typSize := DevCPV.TypeSize; + DevCPT.processor := DevCPV.processor; + DevCPP.Module(p); + IF DevCPM.noerr THEN + IF DevCPT.libName # "" THEN EXCL(m.opts, obj) END; + DevCPV.Init(m.opts); DevCPV.Allocate; DevCPT.Export(ext, new); + IF DevCPM.noerr & (obj IN m.opts) THEN + IF emulong IN m.opts2 THEN + DevCPH.UseCalls(p, {DevCPH.longMop, DevCPH.longDop}) + END; + DevCPV.Module(p) + END; + DevCPV.Close + END; + IF DevCPM.noerr & (new OR ext) THEN DevCPM.RegisterNewSym + ELSE DevCPM.DeleteNewSym + END; + DevCPT.Close; + error := ~DevCPM.noerr; + IF error THEN + DevCPM.InsertMarks; + IF DevCPM.verbose > 0 THEN DevCPM.LogWStr(" ") END; + IF DevCPM.errors = 1 THEN + DevCPM.LogWStr("one error detected") + ELSE + DevCPM.LogWNum(DevCPM.errors, 0); DevCPM.LogWStr(" errors detected") + END; + DevCPM.LogWLn + ELSE + IF hint IN m.opts THEN DevCPM.InsertMarks END + END; + DevCPM.Close; + p := NIL; + Kernel.FastCollect + END Module; + + PROCEDURE ReadText (s: Elem): POINTER TO ARRAY OF CHAR; + VAR + i, len, res: INTEGER; + text: DswDocuments.Text; + loc: Files.Locator; f: Files.File; r: Files.Reader; + ssrc: POINTER TO ARRAY OF SHORTCHAR; + src: POINTER TO ARRAY OF CHAR; + x: POINTER TO ARRAY OF BYTE; + num: ARRAY 32 OF CHAR; + BEGIN + src := NIL; + loc := Files.dir.This(s.dir); + DswDocuments.Import(loc, s.name, text, res); + Strings.IntToString(res, num); + IF res = 0 THEN + src := text.t + ELSIF res = 2 THEN + f := Files.dir.Old(loc, s.name, Files.shared); + IF f # NIL THEN + len := f.Length(); + r := f.NewReader(NIL); + NEW(x, len + 1); + r.ReadBytes(x, 0, len); + NEW(ssrc, len + 1); + FOR i := 0 TO len - 1 DO + ssrc[i] := SHORT(CHR(x[i])) + END; + ssrc[i] := 0X; + x := NIL; + NEW(src, len + 1); + Kernel.Utf8ToString(ssrc, src, res); + ssrc := NIL; + f.Close + END + ELSE + IF DevCPM.verbose > 0 THEN + Console.WriteStr("document error "); + Console.WriteStr(num); + Console.WriteLn + END + END; + IF src = NIL THEN + Console.WriteStr("unable to open file "); + Console.WriteStr(s.path); + Console.WriteLn; + Kernel.Quit(1) + END; + RETURN src + END ReadText; + + PROCEDURE CompileAll; + VAR loc: Files.Locator; m: Elem; error: BOOLEAN; src: POINTER TO ARRAY OF CHAR; + BEGIN + m := u; + WHILE m # NIL DO + IF DevCPM.verbose > 0 THEN + Console.WriteStr("compiling "); Console.WriteStr(m.path); Console.WriteLn + END; + src := ReadText(m); + Module(src, m, error); + IF error THEN Kernel.Quit(1) END; + m := m.next + END + END CompileAll; + + PROCEDURE Init; + BEGIN + IF Kernel.trapCount # 0 THEN Kernel.Quit(1) END; + HostFiles.SetRootDir("."); + InitOptions; + CompileAll; + Kernel.Quit(0) + END Init; + +BEGIN + Kernel.Start(Init) +END DswCompiler486Main. + diff --git a/src/generic/Dsw/Mod/CompilerCPfrontMain.cp b/src/generic/Dsw/Mod/CompilerCPfrontMain.cp new file mode 100644 index 0000000..672ca76 --- /dev/null +++ b/src/generic/Dsw/Mod/CompilerCPfrontMain.cp @@ -0,0 +1,338 @@ +MODULE DswCompilerCPfrontMain; + + IMPORT Kernel, HostFiles, Files, Console, Strings, DswDocuments, + DevCPM, DevCPT, DevCPB, DevCPP, DevCPE, DevCPH, DevCPV := CPfrontCPV, DevCPG := CPfrontCPG; + + CONST + (* compiler options: *) + checks = 0; allchecks = 1; assert = 2; obj = 3; ref = 4; allref = 5; + srcpos = 6; reallib = 7; signatures = 8; + mainprog = 20; include0 = 21; + hint = 29; oberon = 30; errorTrap = 31; + (* defopt = {checks, assert, obj, ref, allref, srcpos, signatures}; *) + defopt = {checks, assert, obj}; + + emulong = 0; + defopt2 = {}; + + TYPE + Elem = POINTER TO RECORD + dir, name, path: Files.Name; + outsym, outcode: Files.Name; (* dir *) + insym: DevCPM.Directory; + found: BOOLEAN; (* COM Aware *) + opts, opts2: SET; + next: Elem + END; + + VAR + u: Elem; + + PROCEDURE GetPath (IN path: ARRAY OF CHAR; OUT dir, name: Files.Name); + VAR i, j, len: INTEGER; + BEGIN + len := LEN(path$); + i := len - 1; + WHILE (i >= 0) & (path[i] # '/') DO DEC(i) END; + IF i >= 0 THEN + FOR i := 0 TO i - 1 DO + dir[i] := path[i] + END; + dir[i] := 0X + ELSE + dir := "" + END; + j := i + 1; i := 0; + WHILE path[j] # 0X DO + name[i] := path[j]; + INC(i); INC(j) + END; + name[i] := 0X + END GetPath; + + PROCEDURE InitOptions; + VAR + i: INTEGER; + found: BOOLEAN; + insym, sym: DevCPM.Directory; + outsym, outcode: Files.Name; + p: ARRAY 256 OF CHAR; + h, t: Elem; + opts, opts2: SET; + + PROCEDURE Check; + BEGIN + IF i >= Kernel.argc THEN + Console.WriteStr("required more parameters for "); + Console.WriteStr(p); Console.WriteLn; + Kernel.Quit(1) + END + END Check; + + BEGIN + outsym := ""; outcode := ""; + opts := defopt; opts2 := defopt2; found := FALSE; + h := NIL; t := NIL; insym := NIL; + i := 1; + WHILE i < Kernel.argc DO + IF Kernel.argv[i, 0] = "-" THEN + p := Kernel.argv[i]$; + INC(i); + IF p = "-legacy" THEN + DevCPM.legacy := TRUE + ELSIF p = "-outsym" THEN + Check; + outsym := Kernel.argv[i]$; + INC(i) + ELSIF p = "-outcode" THEN + Check; + outcode := Kernel.argv[i]$; + INC(i) + ELSIF p = "-symdir" THEN + Check; + sym := insym; + NEW(insym); + insym.path := Kernel.argv[i]$; + insym.legacy := FALSE; + insym.next := sym; + INC(i) + ELSIF p = "-legacysymdir" THEN + Check; + sym := insym; + NEW(insym); + insym.path := Kernel.argv[i]$; + insym.legacy := TRUE; + insym.next := sym; + INC(i) + ELSIF p = "-allchecks" THEN + INCL(opts, allchecks) + ELSIF p = "-no-allchecks" THEN + EXCL(opts, allchecks) + ELSIF p = "-srcpos" THEN + INCL(opts, srcpos) + ELSIF p = "-no-srcpos" THEN + EXCL(opts, srcpos) + ELSIF p = "-structref" THEN + INCL(opts, allref) + ELSIF p = "-no-structref" THEN + EXCL(opts, allref) + ELSIF p = "-ref" THEN + INCL(opts, ref) + ELSIF p = "-no-ref" THEN + EXCL(opts, ref) + ELSIF p = "-obj" THEN + INCL(opts, obj) + ELSIF p = "-no-obj" THEN + EXCL(opts, obj) + ELSIF p = "-assert" THEN + INCL(opts, assert) + ELSIF p = "-no-assert" THEN + EXCL(opts, assert) + ELSIF p = "-checks" THEN + INCL(opts, checks) + ELSIF p = "-no-checks" THEN + EXCL(opts, checks) + ELSIF p = "-hints" THEN + INCL(opts, hint) + ELSIF p = "-no-hints" THEN + EXCL(opts, hint) + ELSIF p = "-trap" THEN + INCL(opts, errorTrap) + ELSIF p = "-no-trap" THEN + EXCL(opts, errorTrap) + ELSIF p = "-oberon" THEN + INCL(opts, oberon) + ELSIF p = "-no-oberon" THEN + EXCL(opts, oberon) + ELSIF p = "-com-aware" THEN + found := TRUE + ELSIF p = "-no-com-aware" THEN + found := FALSE + ELSIF (p = "-v") OR (p = "-verbose") THEN + DevCPM.verbose := MIN(DevCPM.verbose + 1, 3) + ELSIF p = "-main" THEN + INCL(opts, mainprog) + ELSIF p = "-no-main" THEN + EXCL(opts, mainprog) + ELSIF p = "-include0" THEN + INCL(opts, include0) + ELSIF p = "-no-include0" THEN + EXCL(opts, include0) + ELSIF p = "-includedir" THEN + Check; + DevCPG.includePath := Kernel.argv[i]$; + INC(i) + ELSIF p = "-long-calls" THEN + INCL(opts2, emulong) + ELSIF p = "-no-long-calls" THEN + EXCL(opts2, emulong) + ELSE + Console.WriteStr("unknown option "); + Console.WriteStr(p); Console.WriteLn; + Kernel.Quit(1) + END + ELSE + IF h = NIL THEN NEW(h); t := h + ELSE NEW(t.next); t := t.next + END; + t.path := Kernel.argv[i]$; + t.outcode := outcode; + t.outsym := outsym; + t.insym := insym; + t.found := found; + t.opts := opts; + t.opts2 := opts2; + GetPath(t.path, t.dir, t.name); + IF t.name = "" THEN + Console.WriteStr("specified path to directory"); Console.WriteLn; + Kernel.Quit(1) + END; + INC(i) + END + END; + u := h + END InitOptions; + + PROCEDURE Module (source: POINTER TO ARRAY OF CHAR; m: Elem; OUT error: BOOLEAN); + VAR ext, new: BOOLEAN; p: DevCPT.Node; + BEGIN + DevCPG.opt := {}; (* !!! *) + DevCPM.Init(source); + DevCPM.symList := m.insym; + DevCPM.codePath := m.outcode; + DevCPM.symPath := m.outsym; + DevCPM.name := m.path; + INCL(DevCPM.options, 10); (* !!! allow [ccall] *) + INCL(DevCPM.options, DevCPM.allSysVal); (* !!! make nodes for all SYSTEM.VAL *) + INCL(DevCPG.opt, DevCPG.ansi); (* !!! *) + IF m.found THEN INCL(DevCPM.options, DevCPM.comAware) END; + IF errorTrap IN m.opts THEN INCL(DevCPM.options, DevCPM.trap) END; + IF oberon IN m.opts THEN INCL(DevCPM.options, DevCPM.oberon) END; + IF mainprog IN m.opts THEN INCL(DevCPG.opt, DevCPG.mainprog) END; + IF include0 IN m.opts THEN INCL(DevCPG.opt, DevCPG.include0) END; + DevCPT.Init(m.opts); + (* DevCPB.typSize := DevCPV.TypeSize; *) + DevCPB.typSize := DevCPV.TypSize; + DevCPT.processor := DevCPV.processor; + DevCPP.Module(p); + IF DevCPM.noerr THEN + IF DevCPT.libName # "" THEN EXCL(m.opts, obj) END; + DevCPV.Init(m.opts); DevCPV.AdrAndSize(DevCPT.topScope); DevCPT.Export(ext, new); + IF DevCPM.noerr & (obj IN m.opts) THEN + DevCPG.OpenFiles(DevCPT.SelfName); + IF emulong IN m.opts2 THEN + DevCPH.UseCalls(p, {DevCPH.longMop, DevCPH.longDop, DevCPH.longConv, DevCPH.longOdd}); + END; + DevCPV.Module(p) + END; + (* DevCPV.Close *) + END; + IF DevCPM.noerr & (DevCPG.mainprog IN DevCPG.opt) & (DevCPG.modName # "SYSTEM") THEN + DevCPM.DeleteNewSym; + IF DevCPM.verbose > 0 THEN + DevCPM.LogWStr(" main program"); DevCPM.LogWLn + END + ELSIF DevCPM.noerr & (new OR ext) THEN + DevCPM.RegisterNewSym + ELSE + DevCPM.DeleteNewSym + END; + IF obj IN m.opts THEN + DevCPG.CloseFiles + END; + DevCPT.Close; + error := ~DevCPM.noerr; + IF error THEN + DevCPM.InsertMarks; + IF DevCPM.verbose > 0 THEN DevCPM.LogWStr(" ") END; + IF DevCPM.errors = 1 THEN + DevCPM.LogWStr("one error detected"); + ELSE + DevCPM.LogWNum(DevCPM.errors, 0); DevCPM.LogWStr(" errors detected") + END; + DevCPM.LogWLn + ELSE + IF hint IN m.opts THEN DevCPM.InsertMarks END + END; + DevCPM.Close; + p := NIL; + Kernel.FastCollect + END Module; + + PROCEDURE ReadText (s: Elem): POINTER TO ARRAY OF CHAR; + VAR + i, len, res: INTEGER; + text: DswDocuments.Text; + loc: Files.Locator; f: Files.File; r: Files.Reader; + ssrc: POINTER TO ARRAY OF SHORTCHAR; + src: POINTER TO ARRAY OF CHAR; + x: POINTER TO ARRAY OF BYTE; + num: ARRAY 32 OF CHAR; + BEGIN + src := NIL; + loc := Files.dir.This(s.dir); + DswDocuments.Import(loc, s.name, text, res); + Strings.IntToString(res, num); + IF res = 0 THEN + src := text.t + ELSIF res = 2 THEN + f := Files.dir.Old(loc, s.name, Files.shared); + IF f # NIL THEN + len := f.Length(); + r := f.NewReader(NIL); + NEW(x, len + 1); + r.ReadBytes(x, 0, len); + NEW(ssrc, len + 1); + FOR i := 0 TO len - 1 DO + ssrc[i] := SHORT(CHR(x[i])) + END; + ssrc[i] := 0X; + x := NIL; + NEW(src, len + 1); + Kernel.Utf8ToString(ssrc, src, res); + ssrc := NIL; + f.Close + END + ELSE + IF DevCPM.verbose > 0 THEN + Console.WriteStr("document error "); + Console.WriteStr(num); + Console.WriteLn + END + END; + IF src = NIL THEN + Console.WriteStr("unable to open file "); + Console.WriteStr(s.path); + Console.WriteLn; + Kernel.Quit(1) + END; + RETURN src + END ReadText; + + PROCEDURE CompileAll; + VAR loc: Files.Locator; m: Elem; error: BOOLEAN; src: POINTER TO ARRAY OF CHAR; + BEGIN + m := u; + WHILE m # NIL DO + IF DevCPM.verbose > 0 THEN + Console.WriteStr("compiling "); Console.WriteStr(m.path); Console.WriteLn + END; + src := ReadText(m); + Module(src, m, error); + IF error THEN Kernel.Quit(1) END; + m := m.next + END + END CompileAll; + + PROCEDURE Init; + BEGIN + IF Kernel.trapCount # 0 THEN Kernel.Quit(1) END; + HostFiles.SetRootDir("."); + InitOptions; + CompileAll; + Kernel.Quit(0) + END Init; + +BEGIN + Kernel.Start(Init) +END DswCompilerCPfrontMain. diff --git a/src/generic/Dsw/Mod/Debug.odc b/src/generic/Dsw/Mod/Debug.odc new file mode 100644 index 0000000000000000000000000000000000000000..743e20508dd5f784ce6587f4cd69bfcbe015e111 GIT binary patch literal 18325 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 len THEN + NEW(t, len + Step); + FOR i := 0 TO len - 1 DO + t[i] := text.t[i] + END; + text.t := t + END; + text.t[chid] := ch; INC(chid); + text.t[chid] := 0X; + END AddChar; + + PROCEDURE ReadSChar (OUT x: SHORTCHAR); + VAR i: BYTE; + BEGIN + r.ReadByte(i); + x := SHORT(CHR(i MOD 256)) + END ReadSChar; + + PROCEDURE ReadInt (OUT x: INTEGER); + VAR i: ARRAY 4 OF BYTE; + BEGIN + r.ReadBytes(i, 0, 4); + x := i[0] MOD 256 + i[1] MOD 256 * 256 + i[2] MOD 256 * 65536 + i[3] MOD 256 * 16777216 + END ReadInt; + + PROCEDURE ReadBool (OUT x: BOOLEAN); + VAR i: SHORTCHAR; + BEGIN + ReadSChar(i); + x := i # 0X + END ReadBool; + + PROCEDURE ReadStore (OUT s: Store); + CONST + storeVersion = 0X; + newBase = 0F0X; newExt = 0F1X; oldType = 0F2X; + nil = 80X; link = 81X; store = 82X; elem = 83X; newlink = 84X; + elemTName = "Stores.ElemDesc"; modelTName = "Models.ModelDesc"; (* from pre-1.3 *) + VAR + tag, version, ch: SHORTCHAR; i, x: INTEGER; + BEGIN + ReadSChar(tag); s.isElem := tag = elem; + ASSERT((tag = store) OR (tag = elem), 100); + ReadSChar(tag); + WHILE tag = newExt DO + REPEAT ReadSChar(ch) UNTIL ch = 0X; + ReadSChar(tag) + END; + IF tag = newBase THEN (* !!! get base types *) + REPEAT ReadSChar(ch) UNTIL ch = 0X; + ELSIF tag = oldType THEN + ReadInt(x) (* !!! get from dictionary *) + ELSE + HALT(102) + END; + ReadInt(x); (* extension hook = 00000000 *) + ReadInt(s.next); s.next := s.next + r.Pos(); + ReadInt(s.down); s.down := s.down + r.Pos(); + ReadInt(s.len); s.pos := r.Pos(); s.end := s.pos + s.len; + ReadSChar(version); (* version *) + ASSERT(version = storeVersion, 103); + IF s.isElem THEN + ReadSChar(version); + ASSERT(version = storeVersion, 104) + END + END ReadStore; + + PROCEDURE ReadStdTextModel; + CONST + dictSize = 32; + noLCharStdModelVersion = 0; stdModelVersion = 1; + VAR + s: Store; + version, ano: BYTE; + org, len, dictlen, i, w, h: INTEGER; + R: Files.Reader; + x: ARRAY 2 OF BYTE; + ch: CHAR; + BEGIN + r.ReadByte(version); + IF version IN {noLCharStdModelVersion, stdModelVersion} THEN + ReadInt(org); org := org + r.Pos(); R := f.NewReader(NIL); R.SetPos(org); + r.ReadByte(ano); dictlen := 0; + WHILE ano # -1 DO + IF ano = dictlen THEN + ReadStore(s); r.SetPos(s.end); (* attr IS TextModels.AttributesDesc *) + IF dictlen < dictSize THEN (* dictattr[dictlen] := attr *) INC(dictlen) END + ELSE + (* attr := dictattr[ano] *) + END; + ReadInt(len); + IF len > 0 THEN (* pice *) + FOR i := 0 TO len - 1 DO + R.ReadByte(x[0]); ch := CHR(x[0] MOD 256); AddChar(ch) + END + ELSIF len < 0 THEN (* longchar pice *) + ASSERT(len MOD 2 = 0); + FOR i := 0 TO (-len) DIV 2 - 1 DO + R.ReadBytes(x, 0, 2); ch := CHR(x[0] MOD 256 + x[1] MOD 256 * 256); AddChar(ch) + END + ELSE (* len = 0 => embedded view *) + ReadInt(w); ReadInt(h); R.ReadByte(x[0]); (* viewcode!!! *) AddChar(02X); + ReadStore(s); r.SetPos(s.end) (* random view type *) + END; + r.ReadByte(ano) + END; + res := 0 (* ok *) + ELSE + res := 4 (* unsupported text model version *) + END + END ReadStdTextModel; + + PROCEDURE ReadTextModel; + CONST + modelVersion = 0; + conteinerVersion = 0; + textModelVersion = 0; + VAR + s: Store; + version: BYTE; + BEGIN + ReadStore(s); + IF TRUE (*s.type = "TextModels.StdModelDesc"*) THEN + r.ReadByte(version); + IF version = modelVersion THEN (* Models.Model *) + r.ReadByte(version); + IF version = conteinerVersion THEN (* Containers.Container *) + r.ReadByte(version); + IF version = textModelVersion THEN (* TextModels.Model *) + ReadStdTextModel + ELSE + res := 4 (* unsupported text model version *) + END + ELSE + res := 4 (* unsupported text model version *) + END + ELSE + res := 4 (* unsupported text model version *) + END + ELSE + res := 3 (* unsupported version *) + END + END ReadTextModel; + + PROCEDURE ReadDocument; + VAR s: Store; + BEGIN + ReadStore(s); + IF TRUE (*s.type = "Documents.StdDocumentDesc"*) THEN + r.SetPos(s.down); (* !!! *) + ReadStore(s); + IF TRUE (*s.type = "Documents.ModelDesc"*) THEN + r.SetPos(s.down); (* !!! *) + ReadStore(s); + IF TRUE (*s.type = "TextViews.StdViewDesc"*) THEN + r.SetPos(s.down); (* !!! *) + ReadTextModel + ELSE + res := 3 (* unsupported version *) + END + ELSE + res := 3 (* unsupported version *) + END + ELSE + res := 3 (* unsupported version *) + END + END ReadDocument; + + BEGIN + ASSERT(loc # NIL, 20); + ASSERT(name # "", 21); + text := NIL; + f := Files.dir.Old(loc, name, Files.shared); + IF f # NIL THEN + IF f.Length() > 8 THEN (* !!! calculate minimal document size *) + r := f.NewReader(NIL); + ReadInt(tag); + IF tag = docTag THEN + ReadInt(version); + IF version = docVersion THEN + ReadDocument; + f.Close + ELSE + f.Close; + res := 3 (* unsupported version *) + END + ELSE + f.Close; + res := 2 (* not document *) + END + ELSE + f.Close; + res := 2 (* not document *) + END + ELSE + res := 1 (* unable to open *) + END + END Import; + +END DswDocuments. diff --git a/src/generic/Dsw/Mod/EchoMain.cp b/src/generic/Dsw/Mod/EchoMain.cp new file mode 100644 index 0000000..ecfb334 --- /dev/null +++ b/src/generic/Dsw/Mod/EchoMain.cp @@ -0,0 +1,44 @@ +MODULE DswEchoMain; + + (* encoding converter test *) + + IMPORT Kernel, HostLang, Console, Strings; + + PROCEDURE Init; + CONST maxBuf = 256; + VAR i, j, res: INTEGER; p, x: ARRAY maxBuf OF CHAR; + BEGIN + IF Kernel.trapCount # 0 THEN Kernel.Quit(1) END; + i := 1; + WHILE i < Kernel.argc DO + HostLang.HostToString(Kernel.argv[i]$, p, TRUE, res); + Console.WriteStr(p); + IF res # 0 THEN + Console.WriteLn; + Console.WriteStr("Error: "); Console.WriteChar(CHR(ORD("0") + res MOD 10)); + Console.WriteLn; + Kernel.Quit(1) + END; + INC(i) + END; + IF i > 1 THEN Console.WriteLn END; + + i := 1; + WHILE i < Kernel.argc DO + HostLang.HostToString(Kernel.argv[i]$, p, TRUE, res); + j := 0; + WHILE p[j] # 0X DO + Strings.IntToStringForm(ORD(p[j]), 16, 4, "0", FALSE, x); + Console.WriteStr(x); + Console.WriteStr(" "); + INC(j) + END; + INC(i) + END; + IF i > 1 THEN Console.WriteLn END; + Kernel.Quit(0) + END Init; + +BEGIN + Kernel.Start(Init) +END DswEchoMain. diff --git a/src/generic/Dsw/Mod/Linker486Main.cp b/src/generic/Dsw/Mod/Linker486Main.cp new file mode 100644 index 0000000..27997e2 --- /dev/null +++ b/src/generic/Dsw/Mod/Linker486Main.cp @@ -0,0 +1,259 @@ +MODULE DswLinker486Main; + + IMPORT Kernel, HostFiles, Files, Console, Strings, + LB := Dev2LnkBase, Load := Dev2LnkLoad, WrPe := Dev2LnkWritePe, + WrElf := Dev2LnkWriteElf, WrElfS := Dev2LnkWriteElfStatic; + + CONST + tgtElfStatic = 0; tgtElfExe = 1; tgtElfDll = 2; tgtPeExe = 3; tgtPeDll = 4; + + TYPE + Elem = POINTER TO RECORD + name: ARRAY 256 OF CHAR; + next: Elem + END; + + VAR + u: Elem; + inobj: LB.Directory; + outdir, outname: Files.Name; + os, interp, main, kernel: ARRAY 256 OF CHAR; + static, dll, sinit: BOOLEAN; + + PROCEDURE GetPath (IN path: ARRAY OF CHAR; OUT dir, name: Files.Name); + VAR i, j, len: INTEGER; + BEGIN + len := LEN(path$); + i := len - 1; + WHILE (i >= 0) & (path[i] # '/') DO DEC(i) END; + IF i >= 0 THEN + FOR i := 0 TO i - 1 DO + dir[i] := path[i] + END; + dir[i] := 0X + ELSE + dir := "" + END; + j := i + 1; i := 0; + WHILE path[j] # 0X DO + name[i] := path[j]; + INC(i); INC(j) + END; + name[i] := 0X + END GetPath; + + PROCEDURE InitOptions; + VAR i: INTEGER; h, t: Elem; obj: LB.Directory; p: ARRAY 256 OF CHAR; + + PROCEDURE Check; + BEGIN + IF i >= Kernel.argc THEN + Console.WriteStr("required more parameters for "); + Console.WriteStr(p); Console.WriteLn; + Kernel.Quit(1) + END + END Check; + + BEGIN + i := 1; + WHILE i < Kernel.argc DO + IF Kernel.argv[i, 0] = "-" THEN + p := Kernel.argv[i]$; + INC(i); + IF p = "-os" THEN + Check; + Strings.ToLower(Kernel.argv[i]$, os); + INC(i) + ELSIF p = "-interp" THEN + Check; + interp := Kernel.argv[i]$; + INC(i) + ELSIF p = "-o" THEN + Check; + GetPath(Kernel.argv[i]$, outdir, outname); + INC(i) + ELSIF p = "-static" THEN + static := TRUE + ELSIF p = "-dll" THEN + dll := TRUE + ELSIF p = "-sinit" THEN + sinit := TRUE + ELSIF (p = "-m") OR (p = "-main") THEN + Check; + main := Kernel.argv[i]$; + INC(i) + ELSIF (p = "-k") OR (p = "-kernel") THEN + Check; + kernel := Kernel.argv[i]$; + INC(i) + ELSIF p = "-codedir" THEN + Check; + obj := inobj; + NEW(inobj); + inobj.path := Kernel.argv[i]$; + inobj.legacy := FALSE; + inobj.next := obj; + INC(i) + ELSIF p = "-legacycodedir" THEN + Check; + obj := inobj; + NEW(inobj); + inobj.path := Kernel.argv[i]$; + inobj.legacy := TRUE; + inobj.next := obj; + INC(i) + ELSIF p = "-trap" THEN + LB.trap := TRUE + ELSE + Console.WriteStr("unknown option "); + Console.WriteStr(p); Console.WriteLn; + Kernel.Quit(1) + END + ELSE + IF h = NIL THEN NEW(h); t := h + ELSE NEW(t.next); t := t.next + END; + t.name := Kernel.argv[i]$; + INC(i) + END + END; + u := h + END InitOptions; + + PROCEDURE CheckOptions; + BEGIN + IF (os = "linux") OR (os = "freebsd") OR (os = "openbsd") THEN + IF dll THEN LB.Init(tgtElfDll) + ELSIF static THEN LB.Init(tgtElfStatic) + ELSE LB.Init(tgtElfExe) + END; + LB.dynaInit := ~sinit; + IF os = "linux" THEN + LB.opt.OSABI := WrElf.ELFOSABI_NONE; + IF interp = "" THEN LB.opt.elfInterpreter := WrElf.linuxInterpreter + ELSE LB.opt.elfInterpreter := SHORT(interp$) + END + ELSIF os = "freebsd" THEN + LB.opt.OSABI := WrElf.ELFOSABI_FREEBSD; + IF interp = "" THEN LB.opt.elfInterpreter := WrElf.freeBSDInterpreter + ELSE LB.opt.elfInterpreter := SHORT(interp$) + END + ELSIF os = "openbsd" THEN + LB.opt.OSABI := WrElf.ELFOSABI_NONE; + IF interp = "" THEN LB.opt.elfInterpreter := WrElf.openBSDInterpreter + ELSE LB.opt.elfInterpreter := SHORT(interp$) + END + ELSE + HALT(100) + END; + IF outname = "" THEN + Files.dir.GetFileName("a", "out", outname) + END + ELSIF os = "win32" THEN + IF dll THEN LB.Init(tgtPeDll) + ELSE LB.Init(tgtPeExe) + END; + LB.dynaInit := ~sinit; + IF outname = "" THEN + Files.dir.GetFileName("a", "exe", outname) + END; + IF static THEN + Console.WriteStr("-static not supported for win32"); Console.WriteLn; + Kernel.Quit(1) + END; + IF interp # "" THEN + Console.WriteStr("-interp not supported for win32"); Console.WriteLn; + Kernel.Quit(1) + END + ELSIF os = "" THEN + Console.WriteStr("os not specified"); Console.WriteLn; + Kernel.Quit(1) + ELSE + Console.WriteStr("unknown os "); Console.WriteStr(os); Console.WriteLn; + Kernel.Quit(1) + END; + IF main = "" THEN + Console.WriteStr("main module not specified"); Console.WriteLn; + Kernel.Quit(1) + END; + IF outname = "" THEN + Console.WriteStr("required path to output file"); Console.WriteLn; + Kernel.Quit(1) + END; + IF inobj = NIL THEN + Console.WriteStr("required path to input objects"); Console.WriteLn; + Kernel.Quit(1) + END; + LB.objList := inobj; + LB.outputPath := outdir; + LB.outputName := SHORT(outname$); + LB.KernelName := SHORT(kernel$); + LB.mainName := SHORT(main$); + IF u = NIL THEN + Console.WriteStr("no input specified"); Console.WriteLn; + Kernel.Quit(1) + END; + END CheckOptions; + + PROCEDURE LinkAll; + VAR m: Elem; codeBase, dataBase, varsBase: INTEGER; + BEGIN + m := u; + WHILE m # NIL DO + CASE LB.target OF + | tgtElfStatic, tgtElfExe, tgtPeExe: Load.AddModule(m.name) + | tgtElfDll, tgtPeDll: Load.ExportModule(m.name) + END; + m := m.next + END; + CASE LB.target OF + | tgtElfStatic, tgtElfDll, tgtPeDll: (* ok *) + | tgtElfExe: + IF os = "freebsd" THEN + Load.ExportVariable(LB.KernelName$, "__progname"); + Load.ExportVariable(LB.KernelName$, "environ") + END; + Load.ExportAll + | tgtPeExe: + Load.ExportAll + END; + codeBase := 0; dataBase := 0; varsBase := 0; + LB.BeginLinking; + IF LB.outPe THEN + WrPe.Init; + WrPe.GetBases(codeBase, dataBase, varsBase); + LB.SetAddr(codeBase, dataBase, varsBase); + LB.DoFixups; + WrPe.WriteOut + ELSIF LB.outElf & LB.opt.elfStatic THEN + WrElfS.Init; + WrElfS.GetBases(codeBase, dataBase, varsBase); + LB.SetAddr(codeBase, dataBase, varsBase); + LB.DoFixups; + WrElfS.WriteOut + ELSIF LB.outElf THEN + WrElf.Init; + WrElf.GetBases(codeBase, dataBase, varsBase); + LB.SetAddr(codeBase, dataBase, varsBase); + LB.DoFixups; + WrElf.WriteOut + END; + IF LB.error THEN + Console.WriteStr("link failed"); Console.WriteLn; + Kernel.Quit(1) + END + END LinkAll; + + PROCEDURE Init; + BEGIN + IF Kernel.trapCount # 0 THEN Kernel.Quit(1) END; + HostFiles.SetRootDir("."); + InitOptions; + CheckOptions; + LinkAll; + Kernel.Quit(0) + END Init; + +BEGIN + Kernel.Start(Init) +END DswLinker486Main. diff --git a/src/generic/Dsw/Mod/ListMain.cp b/src/generic/Dsw/Mod/ListMain.cp new file mode 100644 index 0000000..d1daf15 --- /dev/null +++ b/src/generic/Dsw/Mod/ListMain.cp @@ -0,0 +1,48 @@ +MODULE DswListMain; + + (* file list test *) + + IMPORT Kernel, HostFiles, Files, Console, Strings; + + PROCEDURE Init; + VAR i, res: INTEGER; loc: Files.Locator; f: Files.FileInfo; d: Files.LocInfo; s: ARRAY 20 OF CHAR; + BEGIN + IF Kernel.trapCount > 0 THEN Kernel.Quit(1) END; + HostFiles.SetRootDir("."); + i := 1; res := 0; + WHILE i < Kernel.argc DO + loc := Files.dir.This(Kernel.argv[i]$); + d := Files.dir.LocList(loc); + IF loc.res = 0 THEN + WHILE d # NIL DO + Console.WriteStr(d.name + "/"); + Console.WriteLn; + d := d.next + END; + f := Files.dir.FileList(loc); + IF loc.res = 0 THEN + WHILE f # NIL DO + Console.WriteStr(f.name); + Console.WriteLn; + f := f.next + END + END + END; + IF loc.res # 0 THEN + Console.WriteStr(Kernel.argv[i] + ': error '); + Strings.IntToString(loc.res, s); + Console.WriteStr(s); + Console.WriteLn; + INC(res); + END; + INC(i) + END; + IF res = 0 THEN Kernel.Quit(0) + ELSIF res = 1 THEN Kernel.Quit(1) + ELSE Kernel.Quit(2) + END + END Init; + +BEGIN + Kernel.Start(Init) +END DswListMain. diff --git a/src/generic/Dsw/Mod/Log.odc b/src/generic/Dsw/Mod/Log.odc new file mode 100644 index 0000000000000000000000000000000000000000..1e08e846744e7dde17d66ed4a96d2cf0ea82c0c2 GIT binary patch literal 6480 zcmcIp&2KAL6`!OC7{KDAd=$#Z!SC@p4#sjqDPT7|9DDL&>e$iPd3hm9B`0r^SU8@@ zGx>ND3)F5|u-m1bBO(-v#_w&!Qz90&M|Z>mRJp#e{AVWBg2`i}5?6IidDF?mm-XViwOV%)bbx zDC|27wkR~diPkF6ow}>m7OBhj9v!3Mk1qy?7}5lKyIXF~wl{*{SF}o7oo2h| zderNX=hi!3gB*q{VYWbSyHRD(oPEFM@%O;@&z35**6Fm|TDxjHOXQFG2ScAQLrVpQ zIaGX1fL)FUkxx-TdRoC=a7a%D!~{i;&U^(Y*kgti*-ASgHkRdMx<@QEfOGbi*QvXW zZO^6k;dyw%{I9w9nr&vSxlW1_-J*80MZFCd!?qeMt@T6SDU<|@hgtRZv2!3L>s)VxA!F->#_yaLn_D2ElyIE4a0!4PyEJ{ldK2sdgis9i6u*J0rF z@vE7G7yoHi>2tKW0IDuvOwqJdWc z3~D@@8WtL{kSQ6Ne`8PR()ge<5cq?r#))QWpT`-Dezr>G2L-w#otIbX$LriP7BVK9 z)aHav;eWQ<>cYKkn}gyHrE`y8O+OWJOn=q7Qd`GEF{TEi1z*!v1o zU7|`ygDV*v(TuHKaiS$4(q?CQN3IB%a?N zl5F6eLOh{E^%IqliM^!yjXsM zkq1^C_Sr0hMb6~li+x#hH0jkD_sRq#D9%w2oIKVKg0f0yWB+gv4gyXB&`^>5tFxUM zI+~`CCmg~?B~#f-X(p4eX6VC6J4YeC{sGULKueO}Pao)9tpH}F{njXj&0%Wt@6D5I zYc%i7Dn*E#8p<_3qQ*fh^k*%;)gSkt?(%wtSq$Lzft-u@RKUzgIS?ir)yMD-R_6tm z9Hyv3+Qktp&jWcmMyc?$Z`ag^Wtuqvu(RVu`=ls;9k>})a-T4`TX&kjmOm!C%m zdGPUcH1YiY6stWZDZ#eh8epk$KE49t5dN;|BN%BaA|Lo(Jsv^YG z7~Tm{OtMek;+>kS)DYF=ErL2yU6inK(JBO%g@C=Y(d1hk#u{X?qzkM@hxfX=Gl)wi zxgJR1)uBRHHYQTcS5eo%1t5d+O%1JxGYQEp z@{tbzknxag1=Ac2a1;@b;9?1-k}8;Z(CjEuRdCkANv#@h5AlH9NyWWODIt;MILCo9 zDp*aqP?c*PKK)>wcvKY>ij$mP6ulhSR`+`)b!S`W`|oiu9O43;FM{jQSYKS@9ymRj zv~OH&Pn$9{C+6a7?Jx6nBpzICr=A7Hm3M9!l9pN#9O;Q<^cwf6c>csMZn)n<$FkH7 zcS5HdJsPUJd%60KC(P(IaLw~+Zv0YrG7QbS+BS%{(U5CwG|KNNB43IYtl#rr6qqoR zAO1dB-Ee~*p3i-t-k1NlXMOeq>*wh|JtlSi1%(p-LM(Yi>2JIeTJ*wO)^Gmv8F`=U MoLGNYdc(5*2bKVdK>z>% literal 0 HcmV?d00001 diff --git a/src/generic/Dsw/Mod/LoopMain.cp b/src/generic/Dsw/Mod/LoopMain.cp new file mode 100644 index 0000000..ad030df --- /dev/null +++ b/src/generic/Dsw/Mod/LoopMain.cp @@ -0,0 +1,45 @@ +MODULE DswLoopMain; + + (* file locking test *) + + IMPORT Kernel, Files, Console, Strings, Log; + + VAR + mode: BOOLEAN; + + PROCEDURE Init; + VAR i: INTEGER; s: ARRAY 16 OF CHAR; f: Files.File; loc: Files.Locator; + BEGIN + IF (Kernel.trapCount > 0) & (Kernel.err # 128) THEN + IF Kernel.err = 200 THEN Console.WriteStr("Keyboard Interrupt") + ELSE Console.WriteStr("Trap "); Strings.IntToString(Kernel.err, s); Console.WriteStr(s) + END; + Console.WriteLn; + Kernel.Quit(1) + END; + i := 1; + mode := Files.shared; + loc := Files.dir.This(""); + WHILE i < Kernel.argc DO + IF Kernel.argv[i]$ = "-" THEN mode := Files.shared + ELSIF Kernel.argv[i]$ = "+" THEN mode := Files.exclusive + ELSIF Kernel.argv[i]$ = "!" THEN + IF f # NIL THEN f.Close; f := NIL END + ELSE + f := Files.dir.Old(loc, Kernel.argv[i]$, mode); + Log.Int(i); Log.String(": "); + IF f = NIL THEN Log.String("~open") + ELSE Log.String("ok") + END; + Log.Int(loc.res); + Log.Ln + END; + INC(i) + END; + LOOP END; + Kernel.Quit(0) + END Init; + +BEGIN + Kernel.Start(Init) +END DswLoopMain. diff --git a/src/generic/System/Mod/Console.odc b/src/generic/System/Mod/Console.odc new file mode 100644 index 0000000000000000000000000000000000000000..27cfe44ee1942e39ab275622985f190ec80b517b GIT binary patch literal 1938 zcmbVNzi-n(6n-f`(>5vt1HW|=NF-5+PzQukRp8pDL`vhzc3YK-p(GZKl*W>M6?CiG zm4Ok7fuSQ48v_G>3KIW7o2dg*dGGEVUlLapoOHhL-rf7&chBc%({e(*sb*k|YgaG-@) z3fn-+a7&Fq zo=}Eg9|VApVz`O6+pIo3+UX879Uup7)33VDBh*)HVsRwoKtc!74y zY@RJU^`>vT%y*cv;Q6j$`pmUW$F-QZ8@*viFW`86@U%l$L!&V~&vyM{o84#4 zdZWT-AD3{IZXT=6v$mv`EXYi`Rd>5ukY7DjxG3y)sf1!FF?pm)A5{{4F~wu0F>5K| z99bI_#_RaGQ4`;zg!IfwRqjqANFW)J6sd*O+P|Qjzv4)r^r4)~8kzEVe77sBzbKxA zg~Zwy24g!y|U5~F}3Lv v*(;wnVCn>(>%Yy>TwjwegQuv6G!seRTZ`f8?L*l6GbuW3Y{B#7X8B literal 0 HcmV?d00001 diff --git a/src/generic/System/Mod/Dates.odc b/src/generic/System/Mod/Dates.odc new file mode 100644 index 0000000000000000000000000000000000000000..db6753b6db5da8fb63a8c4c58f3bc7397a538a1c GIT binary patch literal 7801 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 R{7wEn`p(dJ{`^;l@qb=cxVr!V literal 0 HcmV?d00001 diff --git a/src/generic/System/Mod/Files.odc b/src/generic/System/Mod/Files.odc new file mode 100644 index 0000000000000000000000000000000000000000..bb52b5cd2c814bcf660dd1184fc1f304f0e7ab96 GIT binary patch literal 6812 zcmb_h&5t8T74Pw|0mB+XAR>VSl}*Ta9Itn0k}T0!8|1I~AYOZ9_hhv}eDv5gc4yn& zqwb!a^(qR{?g1n&AaOwmIOK#tNL)Cfhzm+?$%(&#Bk_sb@_w(XKRn}^wU?CCu2=87 zURAw%-LBQ!oX-xO&^}Mkv)^R!LCVApuP+^?Dy2V#WiTkEFxo`Jks}tIe2%pm#^71Q$P)Zx z>bc$j)RcEa6xr(2^B9IECEq4-uZw5eP2 z!BR>JM^ATul_7^{R@>6*Pc7_ZS!?U+{&nstNG}>?dJbs#^S>cxFB*M~JJh%W_3$(? z$_8Vr=0{KHFm#R_SS1G-Qu_d5)r15a`}0pyj^+6iJ=E0lBzn5x*ijpg*DWSQ*a>8# zhV|Ij1GO%i|EzV11d9OFd_iFThAE(xc4N+Lya`T=a!78 z!X*{=rtRJiO88Y9Ac}gMxY0IMw}j|Zlxm}XP--7a*YrH6Zd;Bw$ggzAK`2L8I)UH2 zQrY*8!j+;}VL((Jt9QHV-CbEVGG}j;hipXcE;yhz%2x^EDaH;@zRrw>aY^@xU(}X( zmKdGp|A}V$3}>^bcYIc6d-p@_T}|~%W$M$huKM0_ApQIb(&3eA^>WkhNjH!Pa};0^ z;V95J^os;8cJ1PSjbvwRdJe5Mey4ZF2c-QXJ%6MpY7Zt~ia_dN{}=K28lYtDBmDVE z;tgVZn9E)k>sQxaSzBMfRunYlQ2OHe_4T6I_JVNJb|}xcKCpX)@!VXN!x2w!^0fBiCF(I3EG9MPdXGVjkk`%-e1}L79MBWB(?QsYNXBCY z0apnJp;Rh8<`j@0c?t$4TTXiutPYw(4|35h3@DFHbP#xigY`Xzuy$Y5P}IEuK&d6* ztn9-~7x0UTEYG(E!2Wl5ZSXbrMFN%~ZX^(vWtp=mHr+C3ETpSt&IW9YWlumX!8oWg zkS&(^;>I_Ikz_COphHxwuA9m+5+h80+E5Na*xP6pYa82>CHP*+tr-;B&;iP4J z3w-R$_W`j7_W-eGT&qg+^=XJ>%hp(81ZsjyWZCX(pt6m1KpeGK0Wlv_S<82U<9X~o zT7vo5KaT0mSfT|eSs8|Y6jKwsTfngg*oJE6@5WFA5PM$-gyl9^GfVu7Mh|ba>wC?H z;ABwF#d|dMOrSG|=-jL`$DlfSh z^85hwHq*q&?)hH8S6o0`cc@;Vlmdp#sf#beY7WP~Js7h2*({FA->lXOO2Eeg_5IM>d1jj_q$&db=#+?dj1$$S6FU8h3QDw z8c89PZ|n-$@Tsb6yUrL!uEOZh?)RmO;Tnc2tQf9iX!*UNcJpN>hrC$QX9cfdlIE@5 z2648?7{n@_PUV(ZfAyMZZ;IM>r2{c@e3&AxrD#ONPT6q}JV@`hcUoqnBh0qwG-~Zm zo#-`#?tZ& zMKPkt52^24WBMI>M~t*xD#K|UNZN=H(z->XRcCz`)#`-qHcWDfk<>T6-aNC>Y%?d5 z=mj~Y*rK&Q5vEGDYj!F%GZim-+e(~GYe1wQEsm&NPDRaj?Qla>+wEqf(n_oA@EgLT z6-w`b{F$LZ)d}Y-P{F1!#Cv@{{x>Tf(YO7}w0!h7OTb2QHZTcq|849G(8nVU^}QZL zLeD;%FNgz*nLtPafkU3l?snR>Mt!f-5P4@q&@y6CR)smVgM!HKw8Wtm4mb2U&}U#Z zW-N+U<7QDrtA+!VQh1qld|lPVyGgQ4*N{kqr^%Q$S*p*a1`~9Kt`V0%9M(t*4{G( z9lbbQa~iEVUVwF8gq^MutcyNU^Tnd8@1S!9bJ?l==tqmTDyo+9Qti-lO{S!FJsgTT zw@^y1D?=rE=*=6@lr%P4bxgTi+(&b;*{ZX$;YH5tpKAOgV?T2dfyAa_ZYI{$KDtC;H-C3w`~^ z13oyXi3zMeNMo%3_?ShCbe^Eae@jGPP5Esd@6f8zm;2~jkVP20XaC>dg2emkOEfIJ z)>9vep2L9J=?_5PRs{XKC0%*PI`J1n#DQ;jc#6OMfpPIW<=4}HAf24|Gm(()`MU;S h27Y}bFrInoedEu+zhG>Ca>4lbUq;3!Z~e|#`XAPy`D*|G literal 0 HcmV?d00001 diff --git a/src/generic/System/Mod/Int.odc b/src/generic/System/Mod/Int.odc new file mode 100644 index 0000000000000000000000000000000000000000..9adb645530a063bad03d9836082c569a1cc4b95c GIT binary patch literal 2497 zcmb_e%}*0i5PwypR&6xK1M%XJn6Qi8rafsW5TUz5BebS1nCPi3o7kk#WOvbWGvJYf zM{bgEGM>Eqhj=mZPmrECnCQ&BkKIxbG`{5Z&CbVfKHhX^OK!C%aBUyDz4qq1zY&GG zdbFk=Tt94!glL#w>TN{L&W0a^xz&#UMk*7Pc>Yn3dVx=%c(4Y!qjd%MY?{fPgp1|g zn%|XB3H$_?$uO7TC>LJWUuVO?B}Nru_o@)&;T@j5whtSAKawG0nsL-I+wcY#lo1^i zY)+!=Fouc(K@x!w%1C&F%L?Za5;u{~Ylaw4;iHU6naxE}&}nT(emI=Tgu=M1PC=Gp zQheWKLcHf=40);TK}IX7^E9I`oZ&^%+Q*%uB*izPIKulxvD7uZtf3wniei%%_lRPY zuZG9cV<>qejZwx84~SwE3jEh{)m>Tgpu7V<6H@lNyHM7u~f^wzd zEqFECP{m9-y*gKec9JviEtD%LXv5SDEFgpVUaI45km!Ck@b*-iijYY45 z$R(?dK5XzRE}5j8WIb13B-c*CW?oD4T3IOAsHK!^USp+Jfp&%%6!CBhZs&FW%oKtw zgePSYlFvdB0+S7f-h^q$%g8xSr&$D6bV8i~YPDi5j@)UDXeBC>$I5`~mAKY+kxLSo zdZ-kw031vmCLxr`Qf?#J;)V6Iuw~L2x-fk`7~mGnsx;J<^y7$?!)nd7ocVI2ZjmP| ze(c*ey0C4!hP1a-_dr>&9=Vs2ic9yjRA+a(YQ~-RuZ?4ThOzpbE_T4Fo*Z(; z9fsXNGz9mh}ul{6_Mc;cG3Ya($Z+~9nJyv}s_9yp*_zfDmH2DAk literal 0 HcmV?d00001 diff --git a/src/generic/System/Mod/Integers.odc b/src/generic/System/Mod/Integers.odc new file mode 100644 index 0000000000000000000000000000000000000000..bd9d450baa5df16eed5c4efa8fe19b4ea071f7c6 GIT binary patch literal 29326 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 literal 0 HcmV?d00001 diff --git a/src/generic/System/Mod/Log.odc b/src/generic/System/Mod/Log.odc new file mode 100644 index 0000000000000000000000000000000000000000..6844660b4441862cb3b973b657ebd3e46bc96c5d GIT binary patch literal 6537 zcmb_hO^hQ)6)t;cmsqU%4}||>fSn%4@h(B)XRKY~pPm^j9(!o_W;Gij(c`HZo9*eg zy4&-!3MksWAWk50L5OgO#07+uOHK%JLE@M@$4F6*i4Ta|^4_be{;|iK&XSVa_3G7o z-+T3{`aQecYWIBx?ZNwPe>goBUKG{_(SaVcML1-ssVu+cdyzBtL=e_q8jDjYj8tm; z-XQV=fuPWl1e(M4F?gHf3#Os6|^JYb*gdIBjpDz&OAz>&l03_uIqAa*KyFzM=MW1KvlR&%B z%hq`cdg+r=YeZ2n-k(My%&ufjX?#ibtbjy?z4CV=*srO(3cSLDSy>5vSM?Vup}bVW zU`de5^y$HGir^5eYFju5nT?%YQfLF!-=ZFZbdA;FIfUUa-^7?*V+V>iQM?ND=xJh< z48~UNe_c^wu%<3r1qXFn|j=g(f4L{`p&{6M$G`3CI6)^e`rPlF5SnE%OXZya}9y_joWULL&!$=%ox58j} zy|M34qqQnuBZ4Xb7g$~Gr@@b%GiLt}8&ygTwtE$KN=~kds z;%HI+r%LD}T+N5|?i1j`lGXe~dDoJCp$>gI*3G~_4MkwAVLH6tY(Cc=4}}*B46_a} z*E|R`zVu5>T^P97wKv{Qos3Q2g}uhl?8*2QpyP`_g-5rCvyW>MdbEEh9)Az1WbZZq z@ks(x-=lKrIlc#NXQ$n+a?h*sTCG+t(b8g9XHP4{XQ4;GaATm6)T>0|2y@gD#aCbo z6_4Q2ZE-;zJ;k1AL0A@OK~KH}%yqN`28okW*bF0$&4mZ^${r3NC(Tq4XoN4xkBGv3 z_^hII_bntOED*~w2?<@sPu#al$#%YgJZKkfC-VP>UNb6?F9K0m!y&%Lg&RnH2A-7! z4O!ThpQmyx1bLZzcK;O5Hj$!mzJL^2YsVB>BMq#nQujVm1oa17lH59h9j6C z!q+EHSFrx~QB*t&tPJl7^!V-r8v`SkcoC?18yq)#%gnE6 z3C9J^vkf>Djc#sx19(NeBT(%0co+q+1D4g;+`!jXU41jYEs<#qxio_K*# zuk%SDhGWbp(vK<^XOlaLCv&#p9ZPwZ+pz8I=RSvBFSqEf6F9kr@m+`TpTw_h-UE(` zDr&KEou5{DvSGOcfgT_4g!=ea`Q!#X-+|}(4?M`3Y%~xNrC9@Xq-kz-dMbnQ zjhlQ_Es>uhpNe*Bxf*XeS5+w9S}re!ftOGwShV#Wz72d0)yFf}KO z`ItmRN zSzct~WqRPd`g*k$1?rX^Z&%Zk2`z75ajb6nFPhSrb93<>yuKpD3zt-bYifO2;sE<2 zxh&zY-;FK&U?^`<@JBqh#XAkW8c5of@WhETcb~4Oul^Tqq~NLk{$+Oc+x1)Ne@o`q pt^aD!y7Z$R2SogKCuGk&`#Sr}YnR#fTbJ3pe?4Yz-TebA{0{}mwZi}a literal 0 HcmV?d00001 diff --git a/src/generic/System/Mod/Services.odc b/src/generic/System/Mod/Services.odc new file mode 100644 index 0000000000000000000000000000000000000000..9a36129cf772297910fa759ae2d4d6df3d4291f9 GIT binary patch literal 10737 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 literal 0 HcmV?d00001 diff --git a/src/generic/System/Mod/Strings.odc b/src/generic/System/Mod/Strings.odc new file mode 100644 index 0000000000000000000000000000000000000000..d4aafc8a3d1915c627487105da478bc90601ab2f GIT binary patch literal 27034 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 literal 0 HcmV?d00001 diff --git a/src/i486/generic/System/Mod/Long.odc b/src/i486/generic/System/Mod/Long.odc new file mode 100644 index 0000000000000000000000000000000000000000..f50db609a4a965e4bfa26e2b1ca781e01a328405 GIT binary patch literal 6568 zcmds6&2Jk;6yE>>0z@FhNBIy;rIgx{iPm;P(xg;4-gOhEws!4e zmkVmI2ysE`4WynB2gHFJ{{%;FNc;mdryh{ty*F=Wcb#>bR_%qA>>cmCdG9yB_c1%; zqE+h|aNW3L_1eP&r#lE1w+9{d!*YVQ5$TFQFZQ~FrrUM=VDYl+d?AIg75V-5_MqoG zs1$A_f#&df3O;9Eqvp+siAt~Icv4kFf8;4OgT=@bHeq|t0S!ESg0vb&aLO=dp?wwZ zblteqa7F_O5vCcU4j=1hhmY|fydl_^rIwqdgHeEz2oThA1m5A3tmo}l4C8rdzY2GG zeK`YniHV051_R%14F^sTpUGJs@jBlP9BC{Ve|}93<6F8F;MvTL!#O3y_i2NEqZvMq zQs2O5hFaf&CfWL3w|>>VVe3thmU2I9IcgF4e_=0@W_*NWiGl^K<+6VEmTqn7);qd| zvzA)^(5)Tao52=g4)uj&Lw(u!2txG+Jo~p&vv$h1DEGR%>vMCnTa`<-dP8h~y4|oV z_#m|)Jm{nJhSQP>Psa32CZ0;tdmjsdg` zHc?N180>+OmNK%OjXiIx=d0%kBab@hT_a?OPY*4^P+^uf@H<>)n3YH{Y>^4nqD8WDT5Kq2p@_ty zXb5vuSoZ|8rt~sLT(i?5 ze$l)pU&g$x!j2GzmS}vDotHR%y7Of8lTWomnTSQn;VStTwa%|1rhqbkHaXWio#TCK z!VJJKq#1pL-a*x7NMIO~B)hC-1kK@KfO2jQgB>^|) z)kDQy2=-#NZC!NN1QcESqFtXzCXOzybGpLFxQ-F z%CW-IdjyYCBFAzBaz38}g>8@JR>(hDSdY-;z9Z~Uwi?_gD|3CVl^)A5kwEs4E6|Ib%NMlBkJfdMuoirDyGHdOGn+FX<_%G7gIl)2Io&KYC2? z%QSiv97)dv5MBcTNa7l(-~bg!yP{%Bm5QbHQdo|b?p2N|Zuj`K&QDF%Hn=Pj{R*(T zLMwodY%k(hbH&E#n(WDa&k@C1<&umkm}$9Iu+&Ut+QsV$5}8y_c%CqjzcTvDPE-Sh07|PjDG8Lik$$07)iY#tYH@t|;eK)u!|_A#JHFd7_-t0a(sH zcu<=V2&55$TH7M>Fg2(L$YWb(y!gv^Zn-{8ECA{S6c&K;QV2AsfNsz_S)%Dqexp%L z@cDOX+c2qFRc6T5sOo%NwS2Y2%@hK>$G73f;=eKi=Ge zbAkx03n**VK+7xvgLi7$-K7!AEKR1+>7-!RS={Zjn!4TCsaFMT22(hIdVv>^009gY zAYg*oglfZQ4G|LK)40IXKqRVXf=mViA(uj{DQt{jw>VBCT4cr+EJOV;d@Osa7EWi9 zIpw9JCKVW^PMc)LvS1Y*36_&hOP6aQf~P>(_$%ft&19TNI9$7Th`Jd82bD=d>Z%}h zDDX}grYDcgBuY;djDR;IMvx_8IKm@Di!laK?aF|p31C3N91{YPeL*pa8Yv7gB$2lx zOg_?(M38_R!vu{-BlAdnkif$WO*GBsF)B&>38EAOR6?cVq$4$+FVjL5MgqaeHJ(B) z%ClfR_x5|9hX?C$z+4>od?1eJ%hArTedNGAsY~gc=+npLFTtTGUU+04xn?A)`cMI) zmb8e7xFdXeNQbhZ;V1auaqDfVO`e>GdbS5+PyQ!BN9wvmJw2qOS~=Eu8t$KQI|gXl zkvYp6^VonRYI&KzNF^^0W{mIQuMg}{ohLszm&ff&=W}-r13%|~ykb0i*Z3g%XUZhk jFQ`F$$7#_;q~H25FvQv0##jG5L!VQ%J>!RkTZZu;RQ9;3 literal 0 HcmV?d00001 diff --git a/src/i486/generic/System/Mod/Math.odc b/src/i486/generic/System/Mod/Math.odc new file mode 100644 index 0000000000000000000000000000000000000000..8adb3e1bc05ccb405959244450e708395a5fec1f GIT binary patch literal 21761 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 J{GX>%{|64W;Clc7 literal 0 HcmV?d00001 diff --git a/src/i486/generic/System/Mod/SMath.odc b/src/i486/generic/System/Mod/SMath.odc new file mode 100644 index 0000000000000000000000000000000000000000..719a3f35daa79fa89d53944905bcc04477cfd3fd GIT binary patch literal 16557 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 literal 0 HcmV?d00001 diff --git a/src/i486/linux/C99/Mod/dirent.cp b/src/i486/linux/C99/Mod/dirent.cp new file mode 100644 index 0000000..974ffd2 --- /dev/null +++ b/src/i486/linux/C99/Mod/dirent.cp @@ -0,0 +1,66 @@ +MODULE C99dirent ['libc.so.6']; + + (* generated by genposix.sh, do not modify *) + + IMPORT SYSTEM, C99types, C99sys_types; + + TYPE + char* = C99types.char; + signed_char* = C99types.signed_char; + unsigned_char* = C99types.unsigned_char; + short* = C99types.short; + short_int* = C99types.short_int; + signed_short* = C99types.signed_short; + signed_short_int* = C99types.signed_short_int; + unsigned_short* = C99types.unsigned_short; + unsigned_short_int* = C99types.unsigned_short_int; + int* = C99types.int; + signed* = C99types.signed; + signed_int* = C99types.signed_int; + unsigned* = C99types.unsigned; + unsigned_int* = C99types.unsigned_int; + long* = C99types.long; + long_int* = C99types.long_int; + signed_long* = C99types.signed_long; + signed_long_int* = C99types.signed_long_int; + unsigned_long* = C99types.unsigned_long; + unsigned_long_int* = C99types.unsigned_long_int; + long_long* = C99types.long_long; + long_long_int* = C99types.long_long_int; + signed_long_long* = C99types.signed_long_long; + signed_long_long_int* = C99types.signed_long_long_int; + unsigned_long_long* = C99types.unsigned_long_long; + unsigned_long_long_int* = C99types.unsigned_long_long_int; + float* = C99types.float; + double* = C99types.double; + long_double* = C99types.long_double; + + TYPE + PDIR* = POINTER TO DIR; + DIR = LIMITED RECORD [untagged] END; + + TYPE + Pstruct_dirent* = POINTER TO struct_dirent; + struct_dirent* = RECORD [noalign] (* 268 *) + d_ino*: ino_t; (* 0+4 *) + _____align0_____: ARRAY 7 OF BYTE; + d_name*: ARRAY [untagged] 256 OF SHORTCHAR; (* 11+256 *) + _____align1_____: ARRAY 1 OF BYTE; + END; + + TYPE + ino_t* = C99sys_types.ino_t; + + PROCEDURE [ccall] alphasort* (IN a, b: Pstruct_dirent): int; + PROCEDURE [ccall] closedir* (dirp: PDIR): int; + PROCEDURE [ccall] dirfd* (dirp: PDIR): int; + PROCEDURE [ccall] fdopendir* (fd: int): PDIR; + PROCEDURE [ccall] opendir* (IN name: ARRAY [untagged] OF SHORTCHAR): PDIR; + PROCEDURE [ccall] readdir* (dirp: PDIR): Pstruct_dirent; + PROCEDURE [ccall] readdir_r* (dirp: PDIR; entry: Pstruct_dirent; VAR result: Pstruct_dirent): int; + PROCEDURE [ccall] rewinddir* (dirp: PDIR); + PROCEDURE [ccall] scandir* (IN dirp: ARRAY [untagged] OF SHORTCHAR; filter: PROCEDURE [ccall] (IN d: struct_dirent): int; compar: PROCEDURE [ccall] (IN a, b: Pstruct_dirent): int): int; + PROCEDURE [ccall] seekdir* (dirp: PDIR; loc: long); + PROCEDURE [ccall] telldir* (dirp: PDIR): long; + +END C99dirent. diff --git a/src/i486/linux/C99/Mod/dlfcn.cp b/src/i486/linux/C99/Mod/dlfcn.cp new file mode 100644 index 0000000..e308262 --- /dev/null +++ b/src/i486/linux/C99/Mod/dlfcn.cp @@ -0,0 +1,49 @@ +MODULE C99dlfcn ['libdl.so.2']; + + (* generated by genposix.sh, do not modify *) + + IMPORT SYSTEM, C99types; + + TYPE + char* = C99types.char; + signed_char* = C99types.signed_char; + unsigned_char* = C99types.unsigned_char; + short* = C99types.short; + short_int* = C99types.short_int; + signed_short* = C99types.signed_short; + signed_short_int* = C99types.signed_short_int; + unsigned_short* = C99types.unsigned_short; + unsigned_short_int* = C99types.unsigned_short_int; + int* = C99types.int; + signed* = C99types.signed; + signed_int* = C99types.signed_int; + unsigned* = C99types.unsigned; + unsigned_int* = C99types.unsigned_int; + long* = C99types.long; + long_int* = C99types.long_int; + signed_long* = C99types.signed_long; + signed_long_int* = C99types.signed_long_int; + unsigned_long* = C99types.unsigned_long; + unsigned_long_int* = C99types.unsigned_long_int; + long_long* = C99types.long_long; + long_long_int* = C99types.long_long_int; + signed_long_long* = C99types.signed_long_long; + signed_long_long_int* = C99types.signed_long_long_int; + unsigned_long_long* = C99types.unsigned_long_long; + unsigned_long_long_int* = C99types.unsigned_long_long_int; + float* = C99types.float; + double* = C99types.double; + long_double* = C99types.long_double; + + CONST + RTLD_LAZY* = 1; + RTLD_NOW* = 2; + RTLD_GLOBAL* = 256; + RTLD_LOCAL* = 0; + + PROCEDURE [ccall] dlclose* (handle: C99types.Pvoid): int; + PROCEDURE [ccall] dlerror* (): POINTER TO ARRAY [untagged] OF SHORTCHAR; + PROCEDURE [ccall] dlopen* (IN [nil] filename: ARRAY [untagged] OF SHORTCHAR; flags: int): C99types.Pvoid; + PROCEDURE [ccall] dlsym* (handle: C99types.Pvoid; IN symbol: ARRAY [untagged] OF SHORTCHAR): C99types.Pvoid; + +END C99dlfcn. diff --git a/src/i486/linux/C99/Mod/errno.cp b/src/i486/linux/C99/Mod/errno.cp new file mode 100644 index 0000000..3646dff --- /dev/null +++ b/src/i486/linux/C99/Mod/errno.cp @@ -0,0 +1,123 @@ +MODULE C99errno ['libc.so.6']; + + (* generated by genposix.sh, do not modify *) + + IMPORT SYSTEM, C99types; + + TYPE + char* = C99types.char; + signed_char* = C99types.signed_char; + unsigned_char* = C99types.unsigned_char; + short* = C99types.short; + short_int* = C99types.short_int; + signed_short* = C99types.signed_short; + signed_short_int* = C99types.signed_short_int; + unsigned_short* = C99types.unsigned_short; + unsigned_short_int* = C99types.unsigned_short_int; + int* = C99types.int; + signed* = C99types.signed; + signed_int* = C99types.signed_int; + unsigned* = C99types.unsigned; + unsigned_int* = C99types.unsigned_int; + long* = C99types.long; + long_int* = C99types.long_int; + signed_long* = C99types.signed_long; + signed_long_int* = C99types.signed_long_int; + unsigned_long* = C99types.unsigned_long; + unsigned_long_int* = C99types.unsigned_long_int; + long_long* = C99types.long_long; + long_long_int* = C99types.long_long_int; + signed_long_long* = C99types.signed_long_long; + signed_long_long_int* = C99types.signed_long_long_int; + unsigned_long_long* = C99types.unsigned_long_long; + unsigned_long_long_int* = C99types.unsigned_long_long_int; + float* = C99types.float; + double* = C99types.double; + long_double* = C99types.long_double; + + CONST + E2BIG* = 7; + EACCES* = 13; + EADDRINUSE* = 98; + EADDRNOTAVAIL* = 99; + EAFNOSUPPORT* = 97; + EAGAIN* = 11; + EALREADY* = 114; + EBADF* = 9; + EBADMSG* = 74; + EBUSY* = 16; + ECANCELED* = 125; + ECHILD* = 10; + ECONNABORTED* = 103; + ECONNREFUSED* = 111; + ECONNRESET* = 104; + EDEADLK* = 35; + EDESTADDRREQ* = 89; + EDOM* = 33; + EDQUOT* = 122; + EEXIST* = 17; + EFAULT* = 14; + EFBIG* = 27; + EHOSTUNREACH* = 113; + EIDRM* = 43; + EILSEQ* = 84; + EINPROGRESS* = 115; + EINTR* = 4; + EINVAL* = 22; + EIO* = 5; + EISCONN* = 106; + EISDIR* = 21; + ELOOP* = 40; + EMFILE* = 24; + EMLINK* = 31; + EMSGSIZE* = 90; + EMULTIHOP* = 72; + ENAMETOOLONG* = 36; + ENETDOWN* = 100; + ENETRESET* = 102; + ENETUNREACH* = 101; + ENFILE* = 23; + ENOBUFS* = 105; + ENODATA* = 61; + ENODEV* = 19; + ENOENT* = 2; + ENOEXEC* = 8; + ENOLCK* = 37; + ENOLINK* = 67; + ENOMEM* = 12; + ENOMSG* = 42; + ENOPROTOOPT* = 92; + ENOSPC* = 28; + ENOSR* = 63; + ENOSTR* = 60; + ENOSYS* = 38; + ENOTCONN* = 107; + ENOTDIR* = 20; + ENOTEMPTY* = 39; + ENOTRECOVERABLE* = 131; + ENOTSOCK* = 88; + ENOTSUP* = 95; + ENOTTY* = 25; + ENXIO* = 6; + EOPNOTSUPP* = 95; + EOVERFLOW* = 75; + EOWNERDEAD* = 130; + EPERM* = 1; + EPIPE* = 32; + EPROTO* = 71; + EPROTONOSUPPORT* = 93; + EPROTOTYPE* = 91; + ERANGE* = 34; + EROFS* = 30; + ESPIPE* = 29; + ESRCH* = 3; + ESTALE* = 116; + ETIME* = 62; + ETIMEDOUT* = 110; + ETXTBSY* = 26; + EWOULDBLOCK* = 11; + EXDEV* = 18; + + PROCEDURE [ccall] __errno_location* (): POINTER TO ARRAY [untagged] 1 OF int; + +END C99errno. diff --git a/src/i486/linux/C99/Mod/fcntl.cp b/src/i486/linux/C99/Mod/fcntl.cp new file mode 100644 index 0000000..1402977 --- /dev/null +++ b/src/i486/linux/C99/Mod/fcntl.cp @@ -0,0 +1,119 @@ +MODULE C99fcntl ['libc.so.6']; + + (* generated by genposix.sh, do not modify *) + + IMPORT SYSTEM, C99types, C99sys_types; + + TYPE + char* = C99types.char; + signed_char* = C99types.signed_char; + unsigned_char* = C99types.unsigned_char; + short* = C99types.short; + short_int* = C99types.short_int; + signed_short* = C99types.signed_short; + signed_short_int* = C99types.signed_short_int; + unsigned_short* = C99types.unsigned_short; + unsigned_short_int* = C99types.unsigned_short_int; + int* = C99types.int; + signed* = C99types.signed; + signed_int* = C99types.signed_int; + unsigned* = C99types.unsigned; + unsigned_int* = C99types.unsigned_int; + long* = C99types.long; + long_int* = C99types.long_int; + signed_long* = C99types.signed_long; + signed_long_int* = C99types.signed_long_int; + unsigned_long* = C99types.unsigned_long; + unsigned_long_int* = C99types.unsigned_long_int; + long_long* = C99types.long_long; + long_long_int* = C99types.long_long_int; + signed_long_long* = C99types.signed_long_long; + signed_long_long_int* = C99types.signed_long_long_int; + unsigned_long_long* = C99types.unsigned_long_long; + unsigned_long_long_int* = C99types.unsigned_long_long_int; + float* = C99types.float; + double* = C99types.double; + long_double* = C99types.long_double; + + CONST + F_DUPFD* = 0; + F_DUPFD_CLOEXEC* = 1030; + F_GETFD* = 1; + F_SETFD* = 2; + F_GETFL* = 3; + F_SETFL* = 4; + F_GETLK* = 5; + F_SETLK* = 6; + F_SETLKW* = 7; + F_GETOWN* = 9; + F_SETOWN* = 8; + + CONST + FD_CLOEXEC* = 1; + + CONST + F_RDLCK* = 0; + F_UNLCK* = 2; + F_WRLCK* = 1; + + CONST + SEEK_SET* = 0; + SEEK_CUR* = 1; + SEEK_END* = 2; + + CONST + O_CLOEXEC* = 524288; + O_CREAT* = 64; + O_DIRECTORY* = 65536; + O_EXCL* = 128; + O_NOCTTY* = 256; + O_NOFOLLOW* = 131072; + O_TRUNC* = 512; + O_APPEND* = 1024; + O_DSYNC* = 4096; + O_NONBLOCK* = 2048; + O_RSYNC* = 1052672; + O_SYNC* = 1052672; + O_ACCMODE* = 3; + O_RDONLY* = 0; + O_RDWR* = 2; + O_WRONLY* = 1; + + CONST + AT_FDCWD* = -100; + AT_EACCESS* = 512; + AT_SYMLINK_NOFOLLOW* = 256; + AT_SYMLINK_FOLLOW* = 1024; + AT_REMOVEDIR* = 512; + + CONST + POSIX_FADV_DONTNEED* = 4; + POSIX_FADV_NOREUSE* = 5; + POSIX_FADV_NORMAL* = 0; + POSIX_FADV_RANDOM* = 1; + POSIX_FADV_SEQUENTIAL* = 2; + POSIX_FADV_WILLNEED* = 3; + + TYPE + Pstruct_flock* = POINTER TO struct_flock; + struct_flock* = RECORD [noalign] (* 16 *) + l_type*: short; (* 0+2 *) + l_whence*: short; (* 2+2 *) + l_start*: off_t; (* 4+4 *) + l_len*: off_t; (* 8+4 *) + l_pid*: pid_t; (* 12+4 *) + END; + + TYPE + mode_t* = C99sys_types.mode_t; + off_t* = C99sys_types.off_t; + pid_t* = C99sys_types.pid_t; + + PROCEDURE [ccall] creat* (IN pathname: ARRAY [untagged] OF SHORTCHAR; mode: mode_t): int; + PROCEDURE [ccall] fcntl* (fildes, cmd, arg: int): int; + PROCEDURE [ccall] open* (IN pathname: ARRAY [untagged] OF SHORTCHAR; flags: int; mode: mode_t): int; + PROCEDURE [ccall] openat* (fddir: int; IN pathname: ARRAY [untagged] OF SHORTCHAR; flags: int; mode: mode_t): int; + PROCEDURE [ccall] posix_fadvise* (fd: int; offset, len: off_t; advice: int): int; + PROCEDURE [ccall] posix_fallocate* (fd: int; offset, len: off_t): int; + +END C99fcntl. diff --git a/src/i486/linux/C99/Mod/iconv.cp b/src/i486/linux/C99/Mod/iconv.cp new file mode 100644 index 0000000..4726629 --- /dev/null +++ b/src/i486/linux/C99/Mod/iconv.cp @@ -0,0 +1,48 @@ +MODULE C99iconv ['libc.so.6']; + + (* generated by genposix.sh, do not modify *) + + IMPORT SYSTEM, C99types, C99sys_types; + + TYPE + char* = C99types.char; + signed_char* = C99types.signed_char; + unsigned_char* = C99types.unsigned_char; + short* = C99types.short; + short_int* = C99types.short_int; + signed_short* = C99types.signed_short; + signed_short_int* = C99types.signed_short_int; + unsigned_short* = C99types.unsigned_short; + unsigned_short_int* = C99types.unsigned_short_int; + int* = C99types.int; + signed* = C99types.signed; + signed_int* = C99types.signed_int; + unsigned* = C99types.unsigned; + unsigned_int* = C99types.unsigned_int; + long* = C99types.long; + long_int* = C99types.long_int; + signed_long* = C99types.signed_long; + signed_long_int* = C99types.signed_long_int; + unsigned_long* = C99types.unsigned_long; + unsigned_long_int* = C99types.unsigned_long_int; + long_long* = C99types.long_long; + long_long_int* = C99types.long_long_int; + signed_long_long* = C99types.signed_long_long; + signed_long_long_int* = C99types.signed_long_long_int; + unsigned_long_long* = C99types.unsigned_long_long; + unsigned_long_long_int* = C99types.unsigned_long_long_int; + float* = C99types.float; + double* = C99types.double; + long_double* = C99types.long_double; + + TYPE + iconv_t* = INTEGER; + + TYPE + size_t* = C99sys_types.size_t; + + PROCEDURE [ccall] iconv* (cd: iconv_t; VAR [nil] inbuf: C99types.Pvoid; VAR inbytesleft: size_t; VAR [nil] outbuf: C99types.Pvoid; VAR outbytesleft: size_t): size_t; + PROCEDURE [ccall] iconv_open* (IN tocode, fromcode: ARRAY [untagged] OF SHORTCHAR): iconv_t; + PROCEDURE [ccall] iconv_close* (cd: iconv_t): int; + +END C99iconv. diff --git a/src/i486/linux/C99/Mod/libgen.cp b/src/i486/linux/C99/Mod/libgen.cp new file mode 100644 index 0000000..32ab7c9 --- /dev/null +++ b/src/i486/linux/C99/Mod/libgen.cp @@ -0,0 +1,41 @@ +MODULE C99libgen ['libc.so.6']; + + (* generated by genposix.sh, do not modify *) + + IMPORT SYSTEM, C99types; + + TYPE + char* = C99types.char; + signed_char* = C99types.signed_char; + unsigned_char* = C99types.unsigned_char; + short* = C99types.short; + short_int* = C99types.short_int; + signed_short* = C99types.signed_short; + signed_short_int* = C99types.signed_short_int; + unsigned_short* = C99types.unsigned_short; + unsigned_short_int* = C99types.unsigned_short_int; + int* = C99types.int; + signed* = C99types.signed; + signed_int* = C99types.signed_int; + unsigned* = C99types.unsigned; + unsigned_int* = C99types.unsigned_int; + long* = C99types.long; + long_int* = C99types.long_int; + signed_long* = C99types.signed_long; + signed_long_int* = C99types.signed_long_int; + unsigned_long* = C99types.unsigned_long; + unsigned_long_int* = C99types.unsigned_long_int; + long_long* = C99types.long_long; + long_long_int* = C99types.long_long_int; + signed_long_long* = C99types.signed_long_long; + signed_long_long_int* = C99types.signed_long_long_int; + unsigned_long_long* = C99types.unsigned_long_long; + unsigned_long_long_int* = C99types.unsigned_long_long_int; + float* = C99types.float; + double* = C99types.double; + long_double* = C99types.long_double; + + PROCEDURE [ccall] basename* (path: POINTER TO ARRAY [untagged] OF SHORTCHAR): POINTER TO ARRAY [untagged] OF SHORTCHAR; + PROCEDURE [ccall] dirname* (path: POINTER TO ARRAY [untagged] OF SHORTCHAR): POINTER TO ARRAY [untagged] OF SHORTCHAR; + +END C99libgen. diff --git a/src/i486/linux/C99/Mod/locale.cp b/src/i486/linux/C99/Mod/locale.cp new file mode 100644 index 0000000..376d726 --- /dev/null +++ b/src/i486/linux/C99/Mod/locale.cp @@ -0,0 +1,75 @@ +MODULE C99locale ['libc.so.6']; + + (* generated by genposix.sh, do not modify *) + + IMPORT SYSTEM, C99types; + + TYPE + char* = C99types.char; + signed_char* = C99types.signed_char; + unsigned_char* = C99types.unsigned_char; + short* = C99types.short; + short_int* = C99types.short_int; + signed_short* = C99types.signed_short; + signed_short_int* = C99types.signed_short_int; + unsigned_short* = C99types.unsigned_short; + unsigned_short_int* = C99types.unsigned_short_int; + int* = C99types.int; + signed* = C99types.signed; + signed_int* = C99types.signed_int; + unsigned* = C99types.unsigned; + unsigned_int* = C99types.unsigned_int; + long* = C99types.long; + long_int* = C99types.long_int; + signed_long* = C99types.signed_long; + signed_long_int* = C99types.signed_long_int; + unsigned_long* = C99types.unsigned_long; + unsigned_long_int* = C99types.unsigned_long_int; + long_long* = C99types.long_long; + long_long_int* = C99types.long_long_int; + signed_long_long* = C99types.signed_long_long; + signed_long_long_int* = C99types.signed_long_long_int; + unsigned_long_long* = C99types.unsigned_long_long; + unsigned_long_long_int* = C99types.unsigned_long_long_int; + float* = C99types.float; + double* = C99types.double; + long_double* = C99types.long_double; + + TYPE + Pstruct_lconv* = POINTER TO struct_lconv; + struct_lconv = LIMITED RECORD [untagged] END; + + CONST + LC_ALL* = 6; + LC_COLLATE* = 3; + LC_CTYPE* = 0; + LC_MESSAGES* = 5; + LC_MONETARY* = 4; + LC_NUMERIC* = 1; + LC_TIME* = 2; + + CONST + LC_COLLATE_MASK* = 8; + LC_CTYPE_MASK* = 1; + LC_MESSAGES_MASK* = 32; + LC_MONETARY_MASK* = 16; + LC_NUMERIC_MASK* = 2; + LC_TIME_MASK* = 4; + + CONST + LC_ALL_MASK* = 8127; + + CONST + LC_GLOBAL_LOCALE* = -1; + + TYPE + locale_t* = INTEGER; + + PROCEDURE [ccall] duplocale* (locobj: locale_t): locale_t; + PROCEDURE [ccall] freelocale* (locobj: locale_t); + PROCEDURE [ccall] localeconv* (): Pstruct_lconv; + PROCEDURE [ccall] newlocale* (category_mask: int; IN locale: ARRAY [untagged] OF SHORTCHAR; base: locale_t): locale_t; + PROCEDURE [ccall] setlocale* (category: int; IN [nil] locale: ARRAY [untagged] OF SHORTCHAR): POINTER TO ARRAY [untagged] OF SHORTCHAR; + PROCEDURE [ccall] uselocale* (newloc: locale_t): locale_t; + +END C99locale. diff --git a/src/i486/linux/C99/Mod/macro.cp b/src/i486/linux/C99/Mod/macro.cp new file mode 100644 index 0000000..212fbb1 --- /dev/null +++ b/src/i486/linux/C99/Mod/macro.cp @@ -0,0 +1,15 @@ +MODULE C99macro; + + IMPORT SYSTEM, C99errno, C99sys_stat; + + PROCEDURE errno* (): C99errno.int; + BEGIN + RETURN C99errno.__errno_location()[0] + END errno; + + PROCEDURE stat* (IN path: ARRAY [untagged] OF SHORTCHAR; VAR buf: C99sys_stat.struct_stat): C99sys_stat.int; + BEGIN + RETURN C99sys_stat.__xstat(C99sys_stat._STAT_VER, path, buf) + END stat; + +END C99macro. diff --git a/src/i486/linux/C99/Mod/setjmp.cp b/src/i486/linux/C99/Mod/setjmp.cp new file mode 100644 index 0000000..0794ac4 --- /dev/null +++ b/src/i486/linux/C99/Mod/setjmp.cp @@ -0,0 +1,49 @@ +MODULE C99setjmp ['libc.so.6']; + + (* generated by genposix.sh, do not modify *) + + IMPORT SYSTEM, C99types; + + TYPE + char* = C99types.char; + signed_char* = C99types.signed_char; + unsigned_char* = C99types.unsigned_char; + short* = C99types.short; + short_int* = C99types.short_int; + signed_short* = C99types.signed_short; + signed_short_int* = C99types.signed_short_int; + unsigned_short* = C99types.unsigned_short; + unsigned_short_int* = C99types.unsigned_short_int; + int* = C99types.int; + signed* = C99types.signed; + signed_int* = C99types.signed_int; + unsigned* = C99types.unsigned; + unsigned_int* = C99types.unsigned_int; + long* = C99types.long; + long_int* = C99types.long_int; + signed_long* = C99types.signed_long; + signed_long_int* = C99types.signed_long_int; + unsigned_long* = C99types.unsigned_long; + unsigned_long_int* = C99types.unsigned_long_int; + long_long* = C99types.long_long; + long_long_int* = C99types.long_long_int; + signed_long_long* = C99types.signed_long_long; + signed_long_long_int* = C99types.signed_long_long_int; + unsigned_long_long* = C99types.unsigned_long_long; + unsigned_long_long_int* = C99types.unsigned_long_long_int; + float* = C99types.float; + double* = C99types.double; + long_double* = C99types.long_double; + + TYPE + jmp_buf* = ARRAY [untagged] 156 OF BYTE; + sigjmp_buf* = ARRAY [untagged] 156 OF BYTE; + + PROCEDURE [ccall] _longjmp* (IN env: jmp_buf; val: int); + PROCEDURE [ccall] longjmp* (IN env: jmp_buf; val: int); + PROCEDURE [ccall] siglongjmp* (IN env: sigjmp_buf; val: int); + PROCEDURE [ccall] _setjmp* (VAR env: jmp_buf): int; + PROCEDURE [ccall] setjmp* (VAR env: jmp_buf): int; + PROCEDURE [ccall] sigsetjmp* ['__sigsetjmp'] (VAR env: sigjmp_buf; savesigs: int): int; + +END C99setjmp. diff --git a/src/i486/linux/C99/Mod/signal.cp b/src/i486/linux/C99/Mod/signal.cp new file mode 100644 index 0000000..343afcb --- /dev/null +++ b/src/i486/linux/C99/Mod/signal.cp @@ -0,0 +1,316 @@ +MODULE C99signal ['libc.so.6']; + + (* generated by genposix.sh, do not modify *) + + IMPORT SYSTEM, C99types, C99sys_types, C99time; + + TYPE + char* = C99types.char; + signed_char* = C99types.signed_char; + unsigned_char* = C99types.unsigned_char; + short* = C99types.short; + short_int* = C99types.short_int; + signed_short* = C99types.signed_short; + signed_short_int* = C99types.signed_short_int; + unsigned_short* = C99types.unsigned_short; + unsigned_short_int* = C99types.unsigned_short_int; + int* = C99types.int; + signed* = C99types.signed; + signed_int* = C99types.signed_int; + unsigned* = C99types.unsigned; + unsigned_int* = C99types.unsigned_int; + long* = C99types.long; + long_int* = C99types.long_int; + signed_long* = C99types.signed_long; + signed_long_int* = C99types.signed_long_int; + unsigned_long* = C99types.unsigned_long; + unsigned_long_int* = C99types.unsigned_long_int; + long_long* = C99types.long_long; + long_long_int* = C99types.long_long_int; + signed_long_long* = C99types.signed_long_long; + signed_long_long_int* = C99types.signed_long_long_int; + unsigned_long_long* = C99types.unsigned_long_long; + unsigned_long_long_int* = C99types.unsigned_long_long_int; + float* = C99types.float; + double* = C99types.double; + long_double* = C99types.long_double; + + CONST + SIG_DFL* = 0; + SIG_ERR* = -1; + SIG_IGN* = 1; + + TYPE + pthread_t* = C99sys_types.pthread_t; + pthread_attr_t* = C99sys_types.pthread_attr_t; + size_t* = C99sys_types.size_t; + uid_t* = C99sys_types.uid_t; + pid_t* = C99sys_types.pid_t; + + TYPE + struct_timespec* = C99time.struct_timespec; + + TYPE + sig_atomic_t* = INTEGER; + sigset_t* = RECORD [noalign] _: ARRAY [untagged] 128 OF BYTE END; + + TYPE + Pstruct_sigevent* = POINTER TO struct_sigevent; + struct_sigevent* = RECORD [noalign] (* 64 *) + sigev_value*: union_sigval; (* 0+4 *) + sigev_signo*: int; (* 4+4 *) + sigev_notify*: int; (* 8+4 *) + sigev_notify_function*: PROCEDURE [ccall] (x: union_sigval); (* 12+4 *) + _____align0_____: ARRAY 48 OF BYTE; + END; + + CONST + SIGEV_NONE* = 1; + SIGEV_SIGNAL* = 0; + SIGEV_THREAD* = 2; + + TYPE + Punion_sigval* = POINTER TO union_sigval; + union_sigval* = RECORD [union] (* 4 *) + sival_int*: int; (* 0+4 *) + sival_ptr*: C99types.Pvoid; (* 0+4 *) + END; + + CONST + SIGRTMIN* = 34; + SIGRTMAX* = 64; + RTSIG_MAX* = 32; + + CONST + SIGABRT* = 6; + SIGALRM* = 14; + SIGBUS* = 7; + SIGCHLD* = 17; + SIGCONT* = 18; + SIGFPE* = 8; + SIGHUP* = 1; + SIGILL* = 4; + SIGINT* = 2; + SIGKILL* = 9; + SIGPIPE* = 13; + SIGQUIT* = 3; + SIGSEGV* = 11; + SIGSTOP* = 19; + SIGTERM* = 15; + SIGTSTP* = 20; + SIGTTIN* = 21; + SIGTTOU* = 22; + SIGUSR1* = 10; + SIGUSR2* = 12; + SIGPOLL* = 29; + SIGPROF* = 27; + SIGSYS* = 31; + SIGTRAP* = 5; + SIGURG* = 23; + SIGVTALRM* = 26; + SIGXCPU* = 24; + SIGXFSZ* = 25; + + TYPE + Pstruct_sigaction* = POINTER TO struct_sigaction; + struct_sigaction* = RECORD [noalign] (* 140 *) + handler*: RECORD [union] (* 4 *) + sa_handler*: PROCEDURE [ccall] (sig: int); (* 0+4 *) + sa_sigaction*: PROCEDURE [ccall] (sig: int; IN siginfo: siginfo_t; context: C99types.Pvoid); (* 0+4 *) + END; (* 0+4 *) + sa_mask*: sigset_t; (* 4+128 *) + sa_flags*: int; (* 132+4 *) + _____align0_____: ARRAY 4 OF BYTE; + END; + + CONST + SIG_BLOCK* = 0; + SIG_UNBLOCK* = 1; + SIG_SETMASK* = 2; + + CONST + SA_NOCLDSTOP* = 1; + SA_ONSTACK* = 134217728; + SA_RESETHAND* = -2147483648; + SA_RESTART* = 268435456; + SA_SIGINFO* = 4; + SA_NOCLDWAIT* = 2; + SA_NODEFER* = 1073741824; + SS_ONSTACK* = 1; + SS_DISABLE* = 2; + MINSIGSTKSZ* = 2048; + SIGSTKSZ* = 8192; + + CONST + __NGREG* = 19; + + TYPE + greg_t* = INTEGER; + + TYPE gregset_t* = ARRAY [untagged] __NGREG OF greg_t; + + TYPE + Pstruct__libc_fpreg* = POINTER TO struct__libc_fpreg; + struct__libc_fpreg* = RECORD [noalign] (* 10 *) + significand*: INTEGER; (* 0+8 *) + exponent*: unsigned_short_int; (* 8+2 *) + END; + + TYPE + Pstruct__libc_fpstate* = POINTER TO struct__libc_fpstate; + struct__libc_fpstate* = RECORD [noalign] (* 112 *) + cw*: unsigned_long_int; (* 0+4 *) + sw*: unsigned_long_int; (* 4+4 *) + tag*: unsigned_long_int; (* 8+4 *) + ipoff*: unsigned_long_int; (* 12+4 *) + cssel*: unsigned_long_int; (* 16+4 *) + dataoff*: unsigned_long_int; (* 20+4 *) + datasel*: unsigned_long_int; (* 24+4 *) + _st*: ARRAY [untagged] 8 OF struct__libc_fpreg; (* 28+80 *) + status*: unsigned_long_int; (* 108+4 *) + END; + + TYPE fpregset_t* = Pstruct__libc_fpstate; + + TYPE + Pmcontext_t* = POINTER TO mcontext_t; + mcontext_t* = RECORD [noalign] (* 88 *) + gregs*: gregset_t; (* 0+76 *) + fpregs*: fpregset_t; (* 76+4 *) + oldmask*: unsigned_long_int; (* 80+4 *) + cr2*: unsigned_long_int; (* 84+4 *) + END; + + TYPE + Pucontext_t* = POINTER TO ucontext_t; + ucontext_t* = RECORD [noalign] (* 348 *) + uc_flags*: unsigned_long_int; (* 0+4 *) + uc_link*: Pucontext_t; (* 4+4 *) + uc_stack*: stack_t; (* 8+12 *) + uc_mcontext*: mcontext_t; (* 20+88 *) + uc_sigmask*: sigset_t; (* 108+128 *) + __fpregs_mem*: struct__libc_fpstate; (* 236+112 *) + END; + + TYPE + Pstack_t* = POINTER TO stack_t; + stack_t* = RECORD [noalign] (* 12 *) + ss_sp*: C99types.Pvoid; (* 0+4 *) + ss_flags*: int; (* 4+4 *) + ss_size*: size_t; (* 8+4 *) + END; + + TYPE + Psiginfo_t* = POINTER TO siginfo_t; + siginfo_t* = RECORD [noalign] (* 128 *) + si_signo*: int; (* 0+4 *) + si_errno*: int; (* 4+4 *) + si_code*: int; (* 8+4 *) + info*: RECORD [union] (* 12 *) + sigill*: RECORD [noalign] (* 4 *) + si_addr*: C99types.Pvoid; (* 0+4 *) + END; (* 0+4 *) + sigfpe*: RECORD [noalign] (* 4 *) + si_addr*: C99types.Pvoid; (* 0+4 *) + END; (* 0+4 *) + sigsegv*: RECORD [noalign] (* 4 *) + si_addr*: C99types.Pvoid; (* 0+4 *) + END; (* 0+4 *) + sigbus*: RECORD [noalign] (* 4 *) + si_addr*: C99types.Pvoid; (* 0+4 *) + END; (* 0+4 *) + sigchld*: RECORD [noalign] (* 12 *) + si_pid*: pid_t; (* 0+4 *) + si_uid*: uid_t; (* 4+4 *) + si_status*: int; (* 8+4 *) + END; (* 0+12 *) + sigpoll*: RECORD [noalign] (* 4 *) + si_band*: long; (* 0+4 *) + END; (* 0+4 *) + other*: RECORD [noalign] (* 4 *) + si_value*: union_sigval; (* 0+4 *) + END; (* 8+4 *) + END; (* 12+12 *) + _____align0_____: ARRAY 104 OF BYTE; + END; + + CONST + ILL_ILLOPC* = 1; + ILL_ILLOPN* = 2; + ILL_ILLADR* = 3; + ILL_ILLTRP* = 4; + ILL_PRVOPC* = 5; + ILL_PRVREG* = 6; + ILL_COPROC* = 7; + ILL_BADSTK* = 8; + + CONST + FPE_INTDIV* = 1; + FPE_INTOVF* = 2; + FPE_FLTDIV* = 3; + FPE_FLTOVF* = 4; + FPE_FLTUND* = 5; + FPE_FLTRES* = 6; + FPE_FLTINV* = 7; + FPE_FLTSUB* = 8; + + CONST + SEGV_MAPERR* = 1; + SEGV_ACCERR* = 2; + + CONST + BUS_ADRALN* = 1; + BUS_ADRERR* = 2; + BUS_OBJERR* = 3; + + CONST + CLD_EXITED* = 1; + CLD_KILLED* = 2; + CLD_DUMPED* = 3; + CLD_TRAPPED* = 4; + CLD_STOPPED* = 5; + CLD_CONTINUED* = 6; + + CONST + POLL_IN* = 1; + POLL_OUT* = 2; + POLL_MSG* = 3; + POLL_ERR* = 4; + POLL_PRI* = 5; + POLL_HUP* = 6; + + CONST + SI_USER* = 0; + SI_QUEUE* = -1; + SI_TIMER* = -2; + SI_ASYNCIO* = -4; + SI_MESGQ* = -3; + + PROCEDURE [ccall] kill* (pid: pid_t; sig: int): int; + PROCEDURE [ccall] killpg* (pgrp, sig: int): int; + PROCEDURE [ccall] psiginfo* (IN pinfo: siginfo_t; IN [nil] s: ARRAY [untagged] OF SHORTCHAR); + PROCEDURE [ccall] psignal* (sig: int; IN [nil] s: ARRAY [untagged] OF SHORTCHAR); + PROCEDURE [ccall] pthread_kill* (thread: pthread_t; sig: int): int; + PROCEDURE [ccall] pthread_sigmask* (how: int; IN [nil] set: sigset_t; VAR [nil] oldset: sigset_t): int; + PROCEDURE [ccall] raise* (sig: int): int; + PROCEDURE [ccall] sigaction* (sig: int; IN [nil] act: struct_sigaction; VAR [nil] oact: struct_sigaction): int; + PROCEDURE [ccall] sigaddset* (VAR set: sigset_t; signum: int): int; + PROCEDURE [ccall] sigaltstack* (IN [nil] ss: stack_t; VAR [nil] oss: stack_t): int; + PROCEDURE [ccall] sigdelset* (VAR set: sigset_t; signum: int): int; + PROCEDURE [ccall] sigemptyset* (VAR set: sigset_t): int; + PROCEDURE [ccall] sigfillset* (VAR set: sigset_t): int; + PROCEDURE [ccall] sighold* (sig: int): int; + PROCEDURE [ccall] sigignore* (sig: int): int; + PROCEDURE [ccall] siginterrupt* (sig, flag: int): int; + PROCEDURE [ccall] sigismember* (IN set: sigset_t; signum: int): int; + PROCEDURE [ccall] sigpause* (sig: int): int; + PROCEDURE [ccall] sigpending* (VAR set: sigset_t): int; + PROCEDURE [ccall] sigprocmask* (how: int; IN [nil] set: sigset_t; VAR [nil] oset: sigset_t): int; + PROCEDURE [ccall] sigqueue* (pid: pid_t; sig: int; IN value: union_sigval): int; + PROCEDURE [ccall] sigrelse* (sig: int): int; + PROCEDURE [ccall] sigsuspend* (IN sigmask: sigset_t): int; + PROCEDURE [ccall] sigtimedwait* (IN set: sigset_t; VAR [nil] info: siginfo_t; IN timeout: struct_timespec): int; + PROCEDURE [ccall] sigwait* (IN set: sigset_t; VAR sig: int): int; + PROCEDURE [ccall] sigwaitinfo* (IN set: sigset_t; VAR [nil] info: siginfo_t): int; + +END C99signal. diff --git a/src/i486/linux/C99/Mod/stdio.cp b/src/i486/linux/C99/Mod/stdio.cp new file mode 100644 index 0000000..a39efb0 --- /dev/null +++ b/src/i486/linux/C99/Mod/stdio.cp @@ -0,0 +1,91 @@ +MODULE C99stdio ['libc.so.6']; + + (* generated by genposix.sh, do not modify *) + + IMPORT SYSTEM, C99types, C99sys_types; + + TYPE + char* = C99types.char; + signed_char* = C99types.signed_char; + unsigned_char* = C99types.unsigned_char; + short* = C99types.short; + short_int* = C99types.short_int; + signed_short* = C99types.signed_short; + signed_short_int* = C99types.signed_short_int; + unsigned_short* = C99types.unsigned_short; + unsigned_short_int* = C99types.unsigned_short_int; + int* = C99types.int; + signed* = C99types.signed; + signed_int* = C99types.signed_int; + unsigned* = C99types.unsigned; + unsigned_int* = C99types.unsigned_int; + long* = C99types.long; + long_int* = C99types.long_int; + signed_long* = C99types.signed_long; + signed_long_int* = C99types.signed_long_int; + unsigned_long* = C99types.unsigned_long; + unsigned_long_int* = C99types.unsigned_long_int; + long_long* = C99types.long_long; + long_long_int* = C99types.long_long_int; + signed_long_long* = C99types.signed_long_long; + signed_long_long_int* = C99types.signed_long_long_int; + unsigned_long_long* = C99types.unsigned_long_long; + unsigned_long_long_int* = C99types.unsigned_long_long_int; + float* = C99types.float; + double* = C99types.double; + long_double* = C99types.long_double; + + TYPE + PFILE* = POINTER TO FILE; + FILE = LIMITED RECORD [untagged] END; + + TYPE + fpos_t* = RECORD [noalign] _: ARRAY [untagged] 12 OF BYTE END; + + TYPE + off_t* = C99sys_types.off_t; + ssize_t* = C99sys_types.ssize_t; + + TYPE + size_t* = INTEGER; + + TYPE + va_list* = INTEGER; + + CONST + BUFSIZ* = 8192; + L_ctermid* = 9; + L_tmpnam* = 20; + + CONST + _IOFBF* = 0; + _IOLBF* = 1; + _IONBF* = 2; + + CONST + SEEK_CUR* = 1; + SEEK_END* = 2; + SEEK_SET* = 0; + + CONST + FILENAME_MAX* = 4096; + FOPEN_MAX* = 16; + TMP_MAX* = 238328; + + CONST + EOF* = -1; + + PROCEDURE [ccall] fclose* (stream: PFILE): int; + PROCEDURE [ccall] ferror* (stream: PFILE): int; + PROCEDURE [ccall] fflush* (stream: PFILE): int; + PROCEDURE [ccall] fopen* (IN pathname, mode: ARRAY [untagged] OF SHORTCHAR): PFILE; + PROCEDURE [ccall] fread* (ptr: C99types.Pvoid; size, n: size_t; stream: PFILE): size_t; + PROCEDURE [ccall] fseek* (stream: PFILE; offset: long; whence: int): int; + PROCEDURE [ccall] ftell* (stream: PFILE): long; + PROCEDURE [ccall] fwrite* (ptr: C99types.Pvoid; size, n: size_t; stream: PFILE): size_t; + PROCEDURE [ccall] feof* (stream: PFILE): int; + PROCEDURE [ccall] remove* (IN pathname: ARRAY [untagged] OF SHORTCHAR): int; + PROCEDURE [ccall] rename* (IN old, new: ARRAY [untagged] OF SHORTCHAR): int; + PROCEDURE [ccall] tmpfile* (): PFILE; + +END C99stdio. diff --git a/src/i486/linux/C99/Mod/stdlib.cp b/src/i486/linux/C99/Mod/stdlib.cp new file mode 100644 index 0000000..cde4dd2 --- /dev/null +++ b/src/i486/linux/C99/Mod/stdlib.cp @@ -0,0 +1,66 @@ +MODULE C99stdlib ['libc.so.6']; + + (* generated by genposix.sh, do not modify *) + + IMPORT SYSTEM, C99types; + + TYPE + char* = C99types.char; + signed_char* = C99types.signed_char; + unsigned_char* = C99types.unsigned_char; + short* = C99types.short; + short_int* = C99types.short_int; + signed_short* = C99types.signed_short; + signed_short_int* = C99types.signed_short_int; + unsigned_short* = C99types.unsigned_short; + unsigned_short_int* = C99types.unsigned_short_int; + int* = C99types.int; + signed* = C99types.signed; + signed_int* = C99types.signed_int; + unsigned* = C99types.unsigned; + unsigned_int* = C99types.unsigned_int; + long* = C99types.long; + long_int* = C99types.long_int; + signed_long* = C99types.signed_long; + signed_long_int* = C99types.signed_long_int; + unsigned_long* = C99types.unsigned_long; + unsigned_long_int* = C99types.unsigned_long_int; + long_long* = C99types.long_long; + long_long_int* = C99types.long_long_int; + signed_long_long* = C99types.signed_long_long; + signed_long_long_int* = C99types.signed_long_long_int; + unsigned_long_long* = C99types.unsigned_long_long; + unsigned_long_long_int* = C99types.unsigned_long_long_int; + float* = C99types.float; + double* = C99types.double; + long_double* = C99types.long_double; + + CONST + EXIT_FAILURE* = 1; + EXIT_SUCCESS* = 0; + RAND_MAX* = 2147483647; + + CONST + MB_CUR_MAX* = 1; + + TYPE + div_t* = RECORD [noalign] _: ARRAY [untagged] 8 OF BYTE END; + ldiv_t* = RECORD [noalign] _: ARRAY [untagged] 8 OF BYTE END; + lldiv_t* = RECORD [noalign] _: ARRAY [untagged] 16 OF BYTE END; + + TYPE + size_t* = INTEGER; + wchar_t* = INTEGER; + + PROCEDURE [ccall] _Exit* (status: int); + PROCEDURE [ccall] abort* ; + PROCEDURE [ccall] atexit* (function: PROCEDURE [ccall]): int; + PROCEDURE [ccall] exit* (status: int); + PROCEDURE [ccall] free* (ptr: C99types.Pvoid); + PROCEDURE [ccall] getenv* (IN name: ARRAY [untagged] OF SHORTCHAR): POINTER TO ARRAY [untagged] OF SHORTCHAR; + PROCEDURE [ccall] malloc* (size: size_t): C99types.Pvoid; + PROCEDURE [ccall] system* (IN command: ARRAY [untagged] OF SHORTCHAR): int; + PROCEDURE [ccall] mkstemp* (VAR template: ARRAY [untagged] OF SHORTCHAR): int; + PROCEDURE [ccall] realpath* (IN path: ARRAY [untagged] OF SHORTCHAR; VAR [nil] resolved_path: ARRAY [untagged] OF SHORTCHAR): POINTER TO ARRAY [untagged] OF SHORTCHAR; + +END C99stdlib. diff --git a/src/i486/linux/C99/Mod/sys_mman.cp b/src/i486/linux/C99/Mod/sys_mman.cp new file mode 100644 index 0000000..4e08026 --- /dev/null +++ b/src/i486/linux/C99/Mod/sys_mman.cp @@ -0,0 +1,86 @@ +MODULE C99sys_mman ['libc.so.6']; + + (* generated by genposix.sh, do not modify *) + + IMPORT SYSTEM, C99types, C99sys_types; + + TYPE + char* = C99types.char; + signed_char* = C99types.signed_char; + unsigned_char* = C99types.unsigned_char; + short* = C99types.short; + short_int* = C99types.short_int; + signed_short* = C99types.signed_short; + signed_short_int* = C99types.signed_short_int; + unsigned_short* = C99types.unsigned_short; + unsigned_short_int* = C99types.unsigned_short_int; + int* = C99types.int; + signed* = C99types.signed; + signed_int* = C99types.signed_int; + unsigned* = C99types.unsigned; + unsigned_int* = C99types.unsigned_int; + long* = C99types.long; + long_int* = C99types.long_int; + signed_long* = C99types.signed_long; + signed_long_int* = C99types.signed_long_int; + unsigned_long* = C99types.unsigned_long; + unsigned_long_int* = C99types.unsigned_long_int; + long_long* = C99types.long_long; + long_long_int* = C99types.long_long_int; + signed_long_long* = C99types.signed_long_long; + signed_long_long_int* = C99types.signed_long_long_int; + unsigned_long_long* = C99types.unsigned_long_long; + unsigned_long_long_int* = C99types.unsigned_long_long_int; + float* = C99types.float; + double* = C99types.double; + long_double* = C99types.long_double; + + CONST + PROT_EXEC* = 4; + PROT_NONE* = 0; + PROT_READ* = 1; + PROT_WRITE* = 2; + + CONST + MAP_FIXED* = 16; + MAP_PRIVATE* = 2; + MAP_SHARED* = 1; + + CONST + MS_ASYNC* = 1; + MS_INVALIDATE* = 2; + MS_SYNC* = 4; + + CONST + MCL_CURRENT* = 1; + MCL_FUTURE* = 2; + + CONST + MAP_FAILED* = -1; + + CONST + POSIX_MADV_DONTNEED* = 4; + POSIX_MADV_NORMAL* = 0; + POSIX_MADV_RANDOM* = 1; + POSIX_MADV_SEQUENTIAL* = 2; + POSIX_MADV_WILLNEED* = 3; + + TYPE + mode_t* = C99sys_types.mode_t; + off_t* = C99sys_types.off_t; + size_t* = C99sys_types.size_t; + + PROCEDURE [ccall] mlock* (addr: C99types.Pvoid; len: size_t): int; + PROCEDURE [ccall] mlockall* (flags: int): int; + PROCEDURE [ccall] mmap* (addr: C99types.Pvoid; len: size_t; prot, flags, fildes: int; off: off_t): C99types.Pvoid; + PROCEDURE [ccall] mprotect* (addr: C99types.Pvoid; len: size_t; prot: int): int; + PROCEDURE [ccall] msync* (addr: C99types.Pvoid; len: size_t; flags: int): int; + PROCEDURE [ccall] munlock* (addr: C99types.Pvoid; len: size_t): int; + PROCEDURE [ccall] munlockall* (): int; + PROCEDURE [ccall] munmap* (addr: C99types.Pvoid; len: size_t): int; + PROCEDURE [ccall] posix_madvise* (addr: C99types.Pvoid; len: size_t; advice: int): int; + PROCEDURE [ccall] posix_mem_offset* (addr: C99types.Pvoid; len: size_t; VAR off: off_t; VAR contng_len: size_t; VAR fildes: int): int; + PROCEDURE [ccall] shm_open* (IN name: ARRAY [untagged] OF SHORTCHAR; oflag, mode: int): int; + PROCEDURE [ccall] shm_unlink* (IN name: ARRAY [untagged] OF SHORTCHAR): int; + +END C99sys_mman. diff --git a/src/i486/linux/C99/Mod/sys_stat.cp b/src/i486/linux/C99/Mod/sys_stat.cp new file mode 100644 index 0000000..a0b745b --- /dev/null +++ b/src/i486/linux/C99/Mod/sys_stat.cp @@ -0,0 +1,125 @@ +MODULE C99sys_stat ['libc.so.6']; + + (* generated by genposix.sh, do not modify *) + + IMPORT SYSTEM, C99types, C99time, C99sys_types; + + TYPE + char* = C99types.char; + signed_char* = C99types.signed_char; + unsigned_char* = C99types.unsigned_char; + short* = C99types.short; + short_int* = C99types.short_int; + signed_short* = C99types.signed_short; + signed_short_int* = C99types.signed_short_int; + unsigned_short* = C99types.unsigned_short; + unsigned_short_int* = C99types.unsigned_short_int; + int* = C99types.int; + signed* = C99types.signed; + signed_int* = C99types.signed_int; + unsigned* = C99types.unsigned; + unsigned_int* = C99types.unsigned_int; + long* = C99types.long; + long_int* = C99types.long_int; + signed_long* = C99types.signed_long; + signed_long_int* = C99types.signed_long_int; + unsigned_long* = C99types.unsigned_long; + unsigned_long_int* = C99types.unsigned_long_int; + long_long* = C99types.long_long; + long_long_int* = C99types.long_long_int; + signed_long_long* = C99types.signed_long_long; + signed_long_long_int* = C99types.signed_long_long_int; + unsigned_long_long* = C99types.unsigned_long_long; + unsigned_long_long_int* = C99types.unsigned_long_long_int; + float* = C99types.float; + double* = C99types.double; + long_double* = C99types.long_double; + + CONST + S_IFMT* = 61440; + S_IFBLK* = 24576; + S_IFCHR* = 8192; + S_IFIFO* = 4096; + S_IFREG* = 32768; + S_IFDIR* = 16384; + S_IFLNK* = 40960; + S_IFSOCK* = 49152; + + CONST + S_IRWXU* = 448; + S_IRUSR* = 256; + S_IWUSR* = 128; + S_IXUSR* = 64; + S_IRWXG* = 56; + S_IRGRP* = 32; + S_IWGRP* = 16; + S_IXGRP* = 8; + S_IRWXO* = 7; + S_IROTH* = 4; + S_IWOTH* = 2; + S_IXOTH* = 1; + S_ISUID* = 2048; + S_ISGID* = 1024; + S_ISVTX* = 512; + + CONST + UTIME_NOW* = 1073741823; + UTIME_OMIT* = 1073741822; + + TYPE + blkcnt_t* = C99sys_types.blkcnt_t; + blksize_t* = C99sys_types.blksize_t; + dev_t* = C99sys_types.dev_t; + ino_t* = C99sys_types.ino_t; + mode_t* = C99sys_types.mode_t; + nlink_t* = C99sys_types.nlink_t; + uid_t* = C99sys_types.uid_t; + gid_t* = C99sys_types.gid_t; + off_t* = C99sys_types.off_t; + time_t* = C99sys_types.time_t; + + TYPE + struct_timespec* = C99time.struct_timespec; + + TYPE + Pstruct_stat* = POINTER TO struct_stat; + struct_stat* = RECORD [noalign] (* 88 *) + st_dev*: dev_t; (* 0+8 *) + _____align0_____: ARRAY 4 OF BYTE; + st_ino*: ino_t; (* 12+4 *) + st_mode*: mode_t; (* 16+4 *) + st_nlink*: nlink_t; (* 20+4 *) + st_uid*: uid_t; (* 24+4 *) + st_gid*: gid_t; (* 28+4 *) + st_rdev*: dev_t; (* 32+8 *) + _____align1_____: ARRAY 4 OF BYTE; + st_size*: off_t; (* 44+4 *) + st_blksize*: blksize_t; (* 48+4 *) + st_blocks*: blkcnt_t; (* 52+4 *) + st_atim*: struct_timespec; (* 56+8 *) + st_mtim*: struct_timespec; (* 64+8 *) + st_ctim*: struct_timespec; (* 72+8 *) + _____align2_____: ARRAY 8 OF BYTE; + END; + + CONST + _STAT_VER* = 3; + + PROCEDURE [ccall] chmod* (IN path: ARRAY [untagged] OF SHORTCHAR; mode: mode_t): int; + PROCEDURE [ccall] fchmod* (fd: int; IN path: ARRAY [untagged] OF SHORTCHAR; mode: mode_t): int; + PROCEDURE [ccall] fchmodat* (fd: int; IN path: ARRAY [untagged] OF SHORTCHAR; mode: mode_t; flag: int): int; + PROCEDURE [ccall] fstat* (fd: int; VAR buf: struct_stat): int; + PROCEDURE [ccall] fstatat* (fd: int; IN path: ARRAY [untagged] OF SHORTCHAR; VAR buf: struct_stat; flag: int): int; + PROCEDURE [ccall] futimens* (fd: int; IN times: ARRAY [untagged] 2 OF struct_timespec): int; + PROCEDURE [ccall] lstat* (IN path: ARRAY [untagged] OF SHORTCHAR; VAR buf: struct_stat): int; + PROCEDURE [ccall] mkdir* (IN path: ARRAY [untagged] OF SHORTCHAR; mode: mode_t): int; + PROCEDURE [ccall] mkdirat* (fd: int; IN path: ARRAY [untagged] OF SHORTCHAR; mode: mode_t): int; + PROCEDURE [ccall] mkfifo* (IN pathname: ARRAY [untagged] OF SHORTCHAR; mode: mode_t): int; + PROCEDURE [ccall] mkfifoat* (dirfd: int; IN pathname: ARRAY [untagged] OF SHORTCHAR; mode: mode_t): int; + PROCEDURE [ccall] mknod* (IN path: ARRAY [untagged] OF SHORTCHAR; mode: mode_t; dev: dev_t): int; + PROCEDURE [ccall] mknodat* (df: int; IN path: ARRAY [untagged] OF SHORTCHAR; mode: mode_t; dev: dev_t): int; + PROCEDURE [ccall] __xstat* (version: int; IN path: ARRAY [untagged] OF SHORTCHAR; VAR buf: struct_stat): int; + PROCEDURE [ccall] umask* (mode: mode_t): mode_t; + PROCEDURE [ccall] utimensat* (dirfd: int; IN pathname: ARRAY [untagged] OF SHORTCHAR; IN times: ARRAY [untagged] 2 OF struct_timespec; flags: int): int; + +END C99sys_stat. diff --git a/src/i486/linux/C99/Mod/sys_types.cp b/src/i486/linux/C99/Mod/sys_types.cp new file mode 100644 index 0000000..728a8ce --- /dev/null +++ b/src/i486/linux/C99/Mod/sys_types.cp @@ -0,0 +1,75 @@ +MODULE C99sys_types ['libc.so.6']; + + (* generated by genposix.sh, do not modify *) + + IMPORT SYSTEM, C99types; + + TYPE + char* = C99types.char; + signed_char* = C99types.signed_char; + unsigned_char* = C99types.unsigned_char; + short* = C99types.short; + short_int* = C99types.short_int; + signed_short* = C99types.signed_short; + signed_short_int* = C99types.signed_short_int; + unsigned_short* = C99types.unsigned_short; + unsigned_short_int* = C99types.unsigned_short_int; + int* = C99types.int; + signed* = C99types.signed; + signed_int* = C99types.signed_int; + unsigned* = C99types.unsigned; + unsigned_int* = C99types.unsigned_int; + long* = C99types.long; + long_int* = C99types.long_int; + signed_long* = C99types.signed_long; + signed_long_int* = C99types.signed_long_int; + unsigned_long* = C99types.unsigned_long; + unsigned_long_int* = C99types.unsigned_long_int; + long_long* = C99types.long_long; + long_long_int* = C99types.long_long_int; + signed_long_long* = C99types.signed_long_long; + signed_long_long_int* = C99types.signed_long_long_int; + unsigned_long_long* = C99types.unsigned_long_long; + unsigned_long_long_int* = C99types.unsigned_long_long_int; + float* = C99types.float; + double* = C99types.double; + long_double* = C99types.long_double; + + TYPE + blkcnt_t* = INTEGER; + blksize_t* = INTEGER; + clock_t* = INTEGER; + clockid_t* = INTEGER; + dev_t* = LONGINT; + fsblkcnt_t* = INTEGER; + fsfilcnt_t* = INTEGER; + gid_t* = INTEGER; + id_t* = INTEGER; + ino_t* = INTEGER; + key_t* = INTEGER; + mode_t* = INTEGER; + nlink_t* = INTEGER; + off_t* = INTEGER; + pid_t* = INTEGER; + pthread_attr_t* = RECORD [noalign] _: ARRAY [untagged] 36 OF BYTE END; + pthread_barrier_t* = RECORD [noalign] _: ARRAY [untagged] 20 OF BYTE END; + pthread_barrierattr_t* = INTEGER; + pthread_cond_t* = RECORD [noalign] _: ARRAY [untagged] 48 OF BYTE END; + pthread_condattr_t* = INTEGER; + pthread_key_t* = INTEGER; + pthread_mutex_t* = RECORD [noalign] _: ARRAY [untagged] 24 OF BYTE END; + pthread_mutexattr_t* = INTEGER; + pthread_once_t* = INTEGER; + pthread_rwlock_t* = RECORD [noalign] _: ARRAY [untagged] 32 OF BYTE END; + pthread_rwlockattr_t* = RECORD [noalign] _: ARRAY [untagged] 8 OF BYTE END; + pthread_spinlock_t* = INTEGER; + pthread_t* = INTEGER; + size_t* = INTEGER; + ssize_t* = INTEGER; + suseconds_t* = INTEGER; + time_t* = INTEGER; + timer_t* = INTEGER; + uid_t* = INTEGER; + + +END C99sys_types. diff --git a/src/i486/linux/C99/Mod/time.cp b/src/i486/linux/C99/Mod/time.cp new file mode 100644 index 0000000..5ff122e --- /dev/null +++ b/src/i486/linux/C99/Mod/time.cp @@ -0,0 +1,118 @@ +MODULE C99time ['librt.so.1']; + + (* generated by genposix.sh, do not modify *) + + IMPORT SYSTEM, C99types, C99sys_types, C99locale; + + TYPE + char* = C99types.char; + signed_char* = C99types.signed_char; + unsigned_char* = C99types.unsigned_char; + short* = C99types.short; + short_int* = C99types.short_int; + signed_short* = C99types.signed_short; + signed_short_int* = C99types.signed_short_int; + unsigned_short* = C99types.unsigned_short; + unsigned_short_int* = C99types.unsigned_short_int; + int* = C99types.int; + signed* = C99types.signed; + signed_int* = C99types.signed_int; + unsigned* = C99types.unsigned; + unsigned_int* = C99types.unsigned_int; + long* = C99types.long; + long_int* = C99types.long_int; + signed_long* = C99types.signed_long; + signed_long_int* = C99types.signed_long_int; + unsigned_long* = C99types.unsigned_long; + unsigned_long_int* = C99types.unsigned_long_int; + long_long* = C99types.long_long; + long_long_int* = C99types.long_long_int; + signed_long_long* = C99types.signed_long_long; + signed_long_long_int* = C99types.signed_long_long_int; + unsigned_long_long* = C99types.unsigned_long_long; + unsigned_long_long_int* = C99types.unsigned_long_long_int; + float* = C99types.float; + double* = C99types.double; + long_double* = C99types.long_double; + + TYPE + clock_t* = C99sys_types.clock_t; + size_t* = C99sys_types.size_t; + time_t* = C99sys_types.time_t; + clockid_t* = C99sys_types.clockid_t; + timer_t* = C99sys_types.timer_t; + pid_t* = C99sys_types.pid_t; + + TYPE + locale_t* = C99locale.locale_t; + + TYPE + Pstruct_tm* = POINTER TO struct_tm; + struct_tm* = RECORD [noalign] (* 44 *) + tm_sec*: int; (* 0+4 *) + tm_min*: int; (* 4+4 *) + tm_hour*: int; (* 8+4 *) + tm_mday*: int; (* 12+4 *) + tm_mon*: int; (* 16+4 *) + tm_year*: int; (* 20+4 *) + tm_wday*: int; (* 24+4 *) + tm_yday*: int; (* 28+4 *) + tm_isdst*: int; (* 32+4 *) + _____align0_____: ARRAY 8 OF BYTE; + END; + + TYPE + Pstruct_timespec* = POINTER TO struct_timespec; + struct_timespec* = RECORD [noalign] (* 8 *) + tv_sec*: time_t; (* 0+4 *) + tv_nsec*: long; (* 4+4 *) + END; + + TYPE + Pstruct_itimerspec* = POINTER TO struct_itimerspec; + struct_itimerspec* = RECORD [noalign] (* 16 *) + it_interval*: struct_timespec; (* 0+8 *) + it_value*: struct_timespec; (* 8+8 *) + END; + + CONST + CLOCKS_PER_SEC* = 1000000; + + CONST + CLOCK_MONOTONIC* = 1; + CLOCK_PROCESS_CPUTIME_ID* = 2; + CLOCK_REALTIME* = 0; + CLOCK_THREAD_CPUTIME_ID* = 3; + + CONST + TIMER_ABSTIME* = 1; + + PROCEDURE [ccall] asctime* (IN tm: struct_tm): POINTER TO ARRAY [untagged] OF SHORTCHAR; + PROCEDURE [ccall] asctime_r* (IN tm: struct_tm; buf: POINTER TO ARRAY [untagged] OF SHORTCHAR): POINTER TO ARRAY [untagged] OF SHORTCHAR; + PROCEDURE [ccall] clock* (): clock_t; + PROCEDURE [ccall] clock_getcpuclockid* (pid: pid_t; VAR clock_id: clockid_t): int; + PROCEDURE [ccall] clock_getres* (clk_id: clockid_t; VAR res: struct_timespec): int; + PROCEDURE [ccall] clock_gettime* (clk_id: clockid_t; VAR res: struct_timespec): int; + PROCEDURE [ccall] clock_nanosleep* (clock_id: clockid_t; falgs: int; IN [nil] rqtp: struct_timespec; VAR [nil] rmtp: struct_timespec): int; + PROCEDURE [ccall] clock_settime* (clk_id: clockid_t; IN res: struct_timespec): int; + PROCEDURE [ccall] ctime* (VAR timep: time_t): POINTER TO ARRAY [untagged] OF SHORTCHAR; + PROCEDURE [ccall] ctime_r* (VAR timep: time_t; buf: POINTER TO ARRAY [untagged] OF SHORTCHAR): POINTER TO ARRAY [untagged] OF SHORTCHAR; + PROCEDURE [ccall] difftime* (time0, time1: time_t): double; + PROCEDURE [ccall] getdate* (IN string: ARRAY [untagged] OF SHORTCHAR): Pstruct_tm; + PROCEDURE [ccall] gmtime* (VAR timep: time_t): Pstruct_tm; + PROCEDURE [ccall] gmtime_r* (VAR timep: time_t; VAR result: struct_tm): Pstruct_tm; + PROCEDURE [ccall] localtime* (VAR timep: time_t): Pstruct_tm; + PROCEDURE [ccall] localtime_r* (VAR timep: time_t; VAR result: struct_tm): Pstruct_tm; + PROCEDURE [ccall] mktime* (VAR tm: struct_tm): time_t; + PROCEDURE [ccall] nanosleep* (IN [nil] rqtp: struct_timespec; VAR [nil] rmtp: struct_timespec): int; + PROCEDURE [ccall] strftime* (VAR s: ARRAY [untagged] OF SHORTCHAR; max: size_t; IN format: ARRAY [untagged] OF SHORTCHAR; IN tm: struct_tm): size_t; + PROCEDURE [ccall] strftime_l* (VAR s: ARRAY [untagged] OF SHORTCHAR; max: size_t; IN format: ARRAY [untagged] OF SHORTCHAR; IN tm: struct_tm; locale: locale_t): size_t; + PROCEDURE [ccall] strptime* (IN s, format: ARRAY [untagged] OF SHORTCHAR; VAR tm: struct_tm): POINTER TO ARRAY [untagged] OF SHORTCHAR; + PROCEDURE [ccall] time* (VAR [nil] tloc: time_t): time_t; + PROCEDURE [ccall] timer_delete* (timerid: timer_t): int; + PROCEDURE [ccall] timer_getoverrun* (timerid: timer_t): int; + PROCEDURE [ccall] timer_gettime* (timerid: timer_t; VAR value: struct_itimerspec): int; + PROCEDURE [ccall] timer_settime* (timerid: timer_t; flags: int; IN value: struct_itimerspec; VAR [nil] ovalue: struct_itimerspec): int; + PROCEDURE [ccall] tzset* ; + +END C99time. diff --git a/src/i486/linux/C99/Mod/types.cp b/src/i486/linux/C99/Mod/types.cp new file mode 100644 index 0000000..8c86e26 --- /dev/null +++ b/src/i486/linux/C99/Mod/types.cp @@ -0,0 +1,40 @@ +MODULE C99types; + + (* generated by genposix.sh, do not modify *) + +IMPORT SYSTEM; + + TYPE + char* = BYTE; + signed_char* = BYTE; + unsigned_char* = BYTE; + short* = SHORTINT; + short_int* = SHORTINT; + signed_short* = SHORTINT; + signed_short_int* = SHORTINT; + unsigned_short* = SHORTINT; + unsigned_short_int* = SHORTINT; + int* = INTEGER; + signed* = INTEGER; + signed_int* = INTEGER; + unsigned* = INTEGER; + unsigned_int* = INTEGER; + long* = INTEGER; + long_int* = INTEGER; + signed_long* = INTEGER; + signed_long_int* = INTEGER; + unsigned_long* = INTEGER; + unsigned_long_int* = INTEGER; + long_long* = LONGINT; + long_long_int* = LONGINT; + signed_long_long* = LONGINT; + signed_long_long_int* = LONGINT; + unsigned_long_long* = LONGINT; + unsigned_long_long_int* = LONGINT; + float* = SHORTREAL; + double* = REAL; + long_double* = RECORD [noalign] _: ARRAY [untagged] 12 OF BYTE END; + Pvoid* = INTEGER; + + +END C99types. diff --git a/src/i486/linux/C99/Mod/unistd.cp b/src/i486/linux/C99/Mod/unistd.cp new file mode 100644 index 0000000..47ee6c4 --- /dev/null +++ b/src/i486/linux/C99/Mod/unistd.cp @@ -0,0 +1,430 @@ +MODULE C99unistd ['libc.so.6']; + + (* generated by genposix.sh, do not modify *) + + IMPORT SYSTEM, C99types, C99sys_types; + + TYPE + char* = C99types.char; + signed_char* = C99types.signed_char; + unsigned_char* = C99types.unsigned_char; + short* = C99types.short; + short_int* = C99types.short_int; + signed_short* = C99types.signed_short; + signed_short_int* = C99types.signed_short_int; + unsigned_short* = C99types.unsigned_short; + unsigned_short_int* = C99types.unsigned_short_int; + int* = C99types.int; + signed* = C99types.signed; + signed_int* = C99types.signed_int; + unsigned* = C99types.unsigned; + unsigned_int* = C99types.unsigned_int; + long* = C99types.long; + long_int* = C99types.long_int; + signed_long* = C99types.signed_long; + signed_long_int* = C99types.signed_long_int; + unsigned_long* = C99types.unsigned_long; + unsigned_long_int* = C99types.unsigned_long_int; + long_long* = C99types.long_long; + long_long_int* = C99types.long_long_int; + signed_long_long* = C99types.signed_long_long; + signed_long_long_int* = C99types.signed_long_long_int; + unsigned_long_long* = C99types.unsigned_long_long; + unsigned_long_long_int* = C99types.unsigned_long_long_int; + float* = C99types.float; + double* = C99types.double; + long_double* = C99types.long_double; + + CONST + _POSIX_VERSION* = 200809; + _POSIX2_VERSION* = 200809; + _XOPEN_VERSION* = 700; + + CONST + _POSIX_ADVISORY_INFO* = 200809; + _POSIX_ASYNCHRONOUS_IO* = 200809; + _POSIX_BARRIERS* = 200809; + _POSIX_CHOWN_RESTRICTED* = 0; + _POSIX_CLOCK_SELECTION* = 200809; + _POSIX_CPUTIME* = 0; + _POSIX_FSYNC* = 200809; + _POSIX_IPV6* = 200809; + _POSIX_JOB_CONTROL* = 1; + _POSIX_MAPPED_FILES* = 200809; + _POSIX_MEMLOCK* = 200809; + _POSIX_MEMLOCK_RANGE* = 200809; + _POSIX_MEMORY_PROTECTION* = 200809; + _POSIX_MESSAGE_PASSING* = 200809; + _POSIX_MONOTONIC_CLOCK* = 0; + _POSIX_NO_TRUNC* = 1; + _POSIX_PRIORITIZED_IO* = 200809; + _POSIX_PRIORITY_SCHEDULING* = 200809; + _POSIX_RAW_SOCKETS* = 200809; + _POSIX_READER_WRITER_LOCKS* = 200809; + _POSIX_REALTIME_SIGNALS* = 200809; + _POSIX_REGEXP* = 1; + _POSIX_SAVED_IDS* = 1; + _POSIX_SEMAPHORES* = 200809; + _POSIX_SHARED_MEMORY_OBJECTS* = 200809; + _POSIX_SHELL* = 1; + _POSIX_SPAWN* = 200809; + _POSIX_SPIN_LOCKS* = 200809; + _POSIX_SPORADIC_SERVER* = -1; + _POSIX_SYNCHRONIZED_IO* = 200809; + _POSIX_THREAD_ATTR_STACKADDR* = 200809; + _POSIX_THREAD_ATTR_STACKSIZE* = 200809; + _POSIX_THREAD_CPUTIME* = 0; + _POSIX_THREAD_PRIO_INHERIT* = 200809; + _POSIX_THREAD_PRIO_PROTECT* = 200809; + _POSIX_THREAD_PRIORITY_SCHEDULING* = 200809; + _POSIX_THREAD_PROCESS_SHARED* = 200809; + _POSIX_THREAD_ROBUST_PRIO_INHERIT* = 200809; + _POSIX_THREAD_ROBUST_PRIO_PROTECT* = -1; + _POSIX_THREAD_SAFE_FUNCTIONS* = 200809; + _POSIX_THREAD_SPORADIC_SERVER* = -1; + _POSIX_THREADS* = 200809; + _POSIX_TIMEOUTS* = 200809; + _POSIX_TIMERS* = 200809; + _POSIX_TRACE* = -1; + _POSIX_TRACE_EVENT_FILTER* = -1; + _POSIX_TRACE_INHERIT* = -1; + _POSIX_TRACE_LOG* = -1; + _POSIX_TYPED_MEMORY_OBJECTS* = -1; + _POSIX_V6_ILP32_OFF32* = 1; + _POSIX_V6_ILP32_OFFBIG* = 1; + _POSIX_V6_LP64_OFF64* = -1; + _POSIX_V6_LPBIG_OFFBIG* = -1; + _POSIX_V7_ILP32_OFF32* = 1; + _POSIX_V7_ILP32_OFFBIG* = 1; + _POSIX_V7_LP64_OFF64* = -1; + _POSIX_V7_LPBIG_OFFBIG* = -1; + _POSIX2_C_BIND* = 200809; + _POSIX2_C_DEV* = 200809; + _POSIX2_CHAR_TERM* = 200809; + _POSIX2_FORT_DEV* = -1; + _POSIX2_FORT_RUN* = -1; + _POSIX2_LOCALEDEF* = 200809; + _POSIX2_PBS* = -1; + _POSIX2_PBS_ACCOUNTING* = -1; + _POSIX2_PBS_CHECKPOINT* = -1; + _POSIX2_PBS_LOCATE* = -1; + _POSIX2_PBS_MESSAGE* = -1; + _POSIX2_PBS_TRACK* = -1; + _POSIX2_SW_DEV* = 200809; + _POSIX2_UPE* = -1; + _XOPEN_CRYPT* = 1; + _XOPEN_ENH_I18N* = 1; + _XOPEN_REALTIME* = 1; + _XOPEN_REALTIME_THREADS* = 1; + _XOPEN_SHM* = 1; + _XOPEN_STREAMS* = -1; + _XOPEN_UNIX* = 1; + _XOPEN_UUCP* = -1; + + CONST + _POSIX_ASYNC_IO* = 1; + _POSIX_PRIO_IO* = -1; + _POSIX_SYNC_IO* = -1; + _POSIX_TIMESTAMP_RESOLUTION* = -1; + _POSIX2_SYMLINKS* = -1; + + CONST + F_OK* = 0; + R_OK* = 4; + W_OK* = 2; + X_OK* = 1; + + CONST + _CS_PATH* = 0; + _CS_POSIX_V7_ILP32_OFF32_CFLAGS* = 1132; + _CS_POSIX_V7_ILP32_OFF32_LDFLAGS* = 1133; + _CS_POSIX_V7_ILP32_OFF32_LIBS* = 1134; + _CS_POSIX_V7_ILP32_OFFBIG_CFLAGS* = 1136; + _CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS* = 1137; + _CS_POSIX_V7_ILP32_OFFBIG_LIBS* = 1138; + _CS_POSIX_V7_LP64_OFF64_CFLAGS* = 1140; + _CS_POSIX_V7_LP64_OFF64_LDFLAGS* = 1141; + _CS_POSIX_V7_LP64_OFF64_LIBS* = 1142; + _CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS* = 1144; + _CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS* = 1145; + _CS_POSIX_V7_LPBIG_OFFBIG_LIBS* = 1146; + _CS_POSIX_V7_THREADS_CFLAGS* = -1; + _CS_POSIX_V7_THREADS_LDFLAGS* = -1; + _CS_POSIX_V7_WIDTH_RESTRICTED_ENVS* = 5; + _CS_V7_ENV* = 1149; + _CS_POSIX_V6_ILP32_OFF32_CFLAGS* = 1116; + _CS_POSIX_V6_ILP32_OFF32_LDFLAGS* = 1117; + _CS_POSIX_V6_ILP32_OFF32_LIBS* = 1118; + _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS* = 1120; + _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS* = 1121; + _CS_POSIX_V6_ILP32_OFFBIG_LIBS* = 1122; + _CS_POSIX_V6_LP64_OFF64_CFLAGS* = 1124; + _CS_POSIX_V6_LP64_OFF64_LDFLAGS* = 1125; + _CS_POSIX_V6_LP64_OFF64_LIBS* = 1126; + _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS* = 1128; + _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS* = 1129; + _CS_POSIX_V6_LPBIG_OFFBIG_LIBS* = 1130; + _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS* = 1; + _CS_V6_ENV* = 1148; + + CONST + SEEK_CUR* = 1; + SEEK_END* = 2; + SEEK_SET* = 0; + + CONST + F_LOCK* = 1; + F_TEST* = 3; + F_TLOCK* = 2; + F_ULOCK* = 0; + + CONST + _PC_2_SYMLINKS* = 20; + _PC_ALLOC_SIZE_MIN* = 18; + _PC_ASYNC_IO* = 10; + _PC_CHOWN_RESTRICTED* = 6; + _PC_FILESIZEBITS* = 13; + _PC_LINK_MAX* = 0; + _PC_MAX_CANON* = 1; + _PC_MAX_INPUT* = 2; + _PC_NAME_MAX* = 3; + _PC_NO_TRUNC* = 7; + _PC_PATH_MAX* = 4; + _PC_PIPE_BUF* = 5; + _PC_PRIO_IO* = 11; + _PC_REC_INCR_XFER_SIZE* = 14; + _PC_REC_MAX_XFER_SIZE* = 15; + _PC_REC_MIN_XFER_SIZE* = 16; + _PC_REC_XFER_ALIGN* = 17; + _PC_SYMLINK_MAX* = 19; + _PC_SYNC_IO* = 9; + _PC_TIMESTAMP_RESOLUTION* = -1; + _PC_VDISABLE* = 8; + + CONST + _SC_2_C_BIND* = 47; + _SC_2_C_DEV* = 48; + _SC_2_CHAR_TERM* = 95; + _SC_2_FORT_DEV* = 49; + _SC_2_FORT_RUN* = 50; + _SC_2_LOCALEDEF* = 52; + _SC_2_PBS* = 168; + _SC_2_PBS_ACCOUNTING* = 169; + _SC_2_PBS_CHECKPOINT* = 175; + _SC_2_PBS_LOCATE* = 170; + _SC_2_PBS_MESSAGE* = 171; + _SC_2_PBS_TRACK* = 172; + _SC_2_SW_DEV* = 51; + _SC_2_UPE* = 97; + _SC_2_VERSION* = 46; + _SC_ADVISORY_INFO* = 132; + _SC_AIO_LISTIO_MAX* = 23; + _SC_AIO_MAX* = 24; + _SC_AIO_PRIO_DELTA_MAX* = 25; + _SC_ARG_MAX* = 0; + _SC_ASYNCHRONOUS_IO* = 12; + _SC_ATEXIT_MAX* = 87; + _SC_BARRIERS* = 133; + _SC_BC_BASE_MAX* = 36; + _SC_BC_DIM_MAX* = 37; + _SC_BC_SCALE_MAX* = 38; + _SC_BC_STRING_MAX* = 39; + _SC_CHILD_MAX* = 1; + _SC_CLK_TCK* = 2; + _SC_CLOCK_SELECTION* = 137; + _SC_COLL_WEIGHTS_MAX* = 40; + _SC_CPUTIME* = 138; + _SC_DELAYTIMER_MAX* = 26; + _SC_EXPR_NEST_MAX* = 42; + _SC_FSYNC* = 15; + _SC_GETGR_R_SIZE_MAX* = 69; + _SC_GETPW_R_SIZE_MAX* = 70; + _SC_HOST_NAME_MAX* = 180; + _SC_IOV_MAX* = 60; + _SC_IPV6* = 235; + _SC_JOB_CONTROL* = 7; + _SC_LINE_MAX* = 43; + _SC_LOGIN_NAME_MAX* = 71; + _SC_MAPPED_FILES* = 16; + _SC_MEMLOCK* = 17; + _SC_MEMLOCK_RANGE* = 18; + _SC_MEMORY_PROTECTION* = 19; + _SC_MESSAGE_PASSING* = 20; + _SC_MONOTONIC_CLOCK* = 149; + _SC_MQ_OPEN_MAX* = 27; + _SC_MQ_PRIO_MAX* = 28; + _SC_NGROUPS_MAX* = 3; + _SC_OPEN_MAX* = 4; + _SC_PAGE_SIZE* = 30; + _SC_PAGESIZE* = 30; + _SC_PRIORITIZED_IO* = 13; + _SC_PRIORITY_SCHEDULING* = 10; + _SC_RAW_SOCKETS* = 236; + _SC_RE_DUP_MAX* = 44; + _SC_READER_WRITER_LOCKS* = 153; + _SC_REALTIME_SIGNALS* = 9; + _SC_REGEXP* = 155; + _SC_RTSIG_MAX* = 31; + _SC_SAVED_IDS* = 8; + _SC_SEM_NSEMS_MAX* = 32; + _SC_SEM_VALUE_MAX* = 33; + _SC_SEMAPHORES* = 21; + _SC_SHARED_MEMORY_OBJECTS* = 22; + _SC_SHELL* = 157; + _SC_SIGQUEUE_MAX* = 34; + _SC_SPAWN* = 159; + _SC_SPIN_LOCKS* = 154; + _SC_SPORADIC_SERVER* = 160; + _SC_SS_REPL_MAX* = 241; + _SC_STREAM_MAX* = 5; + _SC_SYMLOOP_MAX* = 173; + _SC_SYNCHRONIZED_IO* = 14; + _SC_THREAD_ATTR_STACKADDR* = 77; + _SC_THREAD_ATTR_STACKSIZE* = 78; + _SC_THREAD_CPUTIME* = 139; + _SC_THREAD_DESTRUCTOR_ITERATIONS* = 73; + _SC_THREAD_KEYS_MAX* = 74; + _SC_THREAD_PRIO_INHERIT* = 80; + _SC_THREAD_PRIO_PROTECT* = 81; + _SC_THREAD_PRIORITY_SCHEDULING* = 79; + _SC_THREAD_PROCESS_SHARED* = 82; + _SC_THREAD_ROBUST_PRIO_INHERIT* = 247; + _SC_THREAD_ROBUST_PRIO_PROTECT* = 248; + _SC_THREAD_SAFE_FUNCTIONS* = 68; + _SC_THREAD_SPORADIC_SERVER* = 161; + _SC_THREAD_STACK_MIN* = 75; + _SC_THREAD_THREADS_MAX* = 76; + _SC_THREADS* = 67; + _SC_TIMEOUTS* = 164; + _SC_TIMER_MAX* = 35; + _SC_TIMERS* = 11; + _SC_TRACE* = 181; + _SC_TRACE_EVENT_FILTER* = 182; + _SC_TRACE_EVENT_NAME_MAX* = 242; + _SC_TRACE_INHERIT* = 183; + _SC_TRACE_LOG* = 184; + _SC_TRACE_NAME_MAX* = 243; + _SC_TRACE_SYS_MAX* = 244; + _SC_TRACE_USER_EVENT_MAX* = 245; + _SC_TTY_NAME_MAX* = 72; + _SC_TYPED_MEMORY_OBJECTS* = 165; + _SC_TZNAME_MAX* = 6; + _SC_V7_ILP32_OFF32* = 237; + _SC_V7_ILP32_OFFBIG* = 238; + _SC_V7_LP64_OFF64* = 239; + _SC_V7_LPBIG_OFFBIG* = 240; + _SC_V6_ILP32_OFF32* = 176; + _SC_V6_ILP32_OFFBIG* = 177; + _SC_V6_LP64_OFF64* = 178; + _SC_V6_LPBIG_OFFBIG* = 179; + _SC_VERSION* = 29; + _SC_XOPEN_CRYPT* = 92; + _SC_XOPEN_ENH_I18N* = 93; + _SC_XOPEN_REALTIME* = 130; + _SC_XOPEN_REALTIME_THREADS* = 131; + _SC_XOPEN_SHM* = 94; + _SC_XOPEN_STREAMS* = 246; + _SC_XOPEN_UNIX* = 91; + _SC_XOPEN_UUCP* = -1; + _SC_XOPEN_VERSION* = 89; + + CONST + STDERR_FILENO* = 2; + STDIN_FILENO* = 0; + STDOUT_FILENO* = 1; + + CONST + _POSIX_VDISABLE* = 0; + + TYPE + size_t* = C99sys_types.size_t; + ssize_t* = C99sys_types.ssize_t; + uid_t* = C99sys_types.uid_t; + gid_t* = C99sys_types.gid_t; + off_t* = C99sys_types.off_t; + pid_t* = C99sys_types.pid_t; + + TYPE + intptr_t* = INTEGER; + + PROCEDURE [ccall] access* (IN path: ARRAY [untagged] OF SHORTCHAR; amode: int): int; + PROCEDURE [ccall] alarm* (seconds: unsigned): unsigned; + PROCEDURE [ccall] chdir* (IN path: ARRAY [untagged] OF SHORTCHAR): int; + PROCEDURE [ccall] chown* (IN path: ARRAY [untagged] OF SHORTCHAR; owner: uid_t; group: gid_t): int; + PROCEDURE [ccall] close* (fd: int): int; + PROCEDURE [ccall] confstr* (name: int; VAR buf: ARRAY [untagged] OF SHORTCHAR; len: size_t); + PROCEDURE [ccall] crypt* (IN key, salt: ARRAY [untagged] OF SHORTCHAR); + PROCEDURE [ccall] dup* (oldfd: int): int; + PROCEDURE [ccall] dup2* (oldfd, newfd: int): int; + PROCEDURE [ccall] _exit* (status: int); + PROCEDURE [ccall] encrypt* (VAR block: ARRAY [untagged] 64 OF SHORTCHAR; edflag: int); + PROCEDURE [ccall] execv* (IN path: ARRAY [untagged] OF SHORTCHAR; IN argv: ARRAY [untagged] OF POINTER TO ARRAY [untagged] OF SHORTCHAR): int; + PROCEDURE [ccall] execve* (IN path: ARRAY [untagged] OF SHORTCHAR; IN argv, envp: ARRAY [untagged] OF POINTER TO ARRAY [untagged] OF SHORTCHAR): int; + PROCEDURE [ccall] execvp* (IN file: ARRAY [untagged] OF SHORTCHAR; IN argv, envp: ARRAY [untagged] OF POINTER TO ARRAY [untagged] OF SHORTCHAR): int; + PROCEDURE [ccall] faccessat* (fd: int; IN path: ARRAY [untagged] OF SHORTCHAR; amode, flag: int): int; + PROCEDURE [ccall] fchdir* (fildes: int): int; + PROCEDURE [ccall] fchown* (fildes: int; owner: uid_t; group: gid_t): int; + PROCEDURE [ccall] fchownat* (fd: int; IN path: ARRAY [untagged] OF SHORTCHAR; owner: uid_t; group: gid_t; flag: int): int; + PROCEDURE [ccall] fdatasync* (fildes: int): int; + PROCEDURE [ccall] fexecve* (fd: int; IN argv, envp: ARRAY [untagged] OF POINTER TO ARRAY [untagged] OF SHORTCHAR): int; + PROCEDURE [ccall] fork* (): pid_t; + PROCEDURE [ccall] fpathconf* (fd, name: int): long; + PROCEDURE [ccall] fsync* (fildes: int): int; + PROCEDURE [ccall] ftruncate* (fildes: int; length: off_t): int; + PROCEDURE [ccall] getcwd* (VAR [nil] buf: ARRAY [untagged] OF SHORTCHAR; size: size_t): POINTER TO ARRAY [untagged] OF SHORTCHAR; + PROCEDURE [ccall] getegid* (): gid_t; + PROCEDURE [ccall] geteuid* (): uid_t; + PROCEDURE [ccall] getgid* (): gid_t; + PROCEDURE [ccall] getgroups* (gidsetsize: int; VAR grouplist: ARRAY [untagged] OF gid_t): int; + PROCEDURE [ccall] gethostid* (): long; + PROCEDURE [ccall] gethostname* (VAR name: ARRAY [untagged] OF SHORTCHAR; namelen: size_t): int; + PROCEDURE [ccall] getlogin* (): POINTER TO ARRAY [untagged] OF SHORTCHAR; + PROCEDURE [ccall] getlogin_r* (VAR buf: ARRAY [untagged] OF SHORTCHAR; bufsize: size_t): int; + PROCEDURE [ccall] getopt* (argc: int; IN argv: ARRAY [untagged] OF POINTER TO ARRAY [untagged] OF SHORTCHAR; IN optstring: ARRAY [untagged] OF SHORTCHAR): int; + PROCEDURE [ccall] getpgid* (pid: pid_t): pid_t; + PROCEDURE [ccall] getpgrp* (): pid_t; + PROCEDURE [ccall] getpid* (): pid_t; + PROCEDURE [ccall] getppid* (): pid_t; + PROCEDURE [ccall] getsid* (): pid_t; + PROCEDURE [ccall] getuid* (): uid_t; + PROCEDURE [ccall] isatty* (fd: int): int; + PROCEDURE [ccall] lchown* (IN path: ARRAY [untagged] OF SHORTCHAR; owner: uid_t; group: gid_t): int; + PROCEDURE [ccall] link* (IN path1, path2: ARRAY [untagged] OF SHORTCHAR): int; + PROCEDURE [ccall] linkat* (fd1: int; IN path1: ARRAY [untagged] OF SHORTCHAR; fd2: int; IN path2: ARRAY [untagged] OF SHORTCHAR; flag: int): int; + PROCEDURE [ccall] lockf* (fd, cmd: int; len: off_t): int; + PROCEDURE [ccall] lseek* (fildes: int; offset: off_t; whence: int): off_t; + PROCEDURE [ccall] nice* (incr: int): int; + PROCEDURE [ccall] pathconf* (IN path: ARRAY [untagged] OF SHORTCHAR; name: int): long; + PROCEDURE [ccall] pause* (): int; + PROCEDURE [ccall] pipe* (VAR fildes: ARRAY [untagged] 2 OF int): int; + PROCEDURE [ccall] pread* (fildes: int; buf: C99types.Pvoid; nbyte: size_t; offset: off_t): ssize_t; + PROCEDURE [ccall] pwrite* (fildes: int; buf: C99types.Pvoid; nbyte: size_t; offset: off_t): ssize_t; + PROCEDURE [ccall] read* (fildes: int; buf: C99types.Pvoid; nbyte: size_t): ssize_t; + PROCEDURE [ccall] readlink* (IN path: ARRAY [untagged] OF SHORTCHAR; VAR buf: ARRAY [untagged] OF SHORTCHAR; bufsize: size_t): ssize_t; + PROCEDURE [ccall] readlinkat* (fd: int; IN path: ARRAY [untagged] OF SHORTCHAR; VAR buf: ARRAY [untagged] OF SHORTCHAR; bufsize: size_t): ssize_t; + PROCEDURE [ccall] rmdir* (IN path: ARRAY [untagged] OF SHORTCHAR): int; + PROCEDURE [ccall] setegid* (gid: gid_t): int; + PROCEDURE [ccall] seteuid* (uid: uid_t): int; + PROCEDURE [ccall] setgid* (gid: gid_t): int; + PROCEDURE [ccall] setpgid* (pid, pgid: pid_t): int; + PROCEDURE [ccall] setpgrp* (): pid_t; + PROCEDURE [ccall] setregid* (rgid, egid: pid_t): int; + PROCEDURE [ccall] setreuid* (ruid, euid: uid_t): int; + PROCEDURE [ccall] setsid* (): pid_t; + PROCEDURE [ccall] setuid* (uid: uid_t): int; + PROCEDURE [ccall] sleep* (seconds: unsigned): unsigned; + PROCEDURE [ccall] swab* (from, to: C99types.Pvoid; n: ssize_t); + PROCEDURE [ccall] symlink* (IN path1, path2: ARRAY [untagged] OF SHORTCHAR): int; + PROCEDURE [ccall] symlinkat* (IN path1: ARRAY [untagged] OF SHORTCHAR; fd: int; IN path2: ARRAY [untagged] OF SHORTCHAR): int; + PROCEDURE [ccall] sync* ; + PROCEDURE [ccall] sysconf* (name: int): long; + PROCEDURE [ccall] tcgetpgrp* (fd: int): pid_t; + PROCEDURE [ccall] tcsetpgrp* (fd: int; pgrp: pid_t): int; + PROCEDURE [ccall] truncate* (IN path: ARRAY [untagged] OF SHORTCHAR; length: off_t): int; + PROCEDURE [ccall] ttyname* (fd: int): POINTER TO ARRAY [untagged] OF SHORTCHAR; + PROCEDURE [ccall] ttyname_r* (fd: int; VAR buf: ARRAY [untagged] OF SHORTCHAR; buflen: size_t): int; + PROCEDURE [ccall] unlink* (IN path: ARRAY [untagged] OF SHORTCHAR): int; + PROCEDURE [ccall] unlinkat* (fd: int; IN path: ARRAY [untagged] OF SHORTCHAR; flag: int): int; + PROCEDURE [ccall] write* (fildes: int; buf: C99types.Pvoid; nbyte: size_t): int; + +END C99unistd. diff --git a/src/i486/linux/C99/Mod/wctype.cp b/src/i486/linux/C99/Mod/wctype.cp new file mode 100644 index 0000000..4f290c6 --- /dev/null +++ b/src/i486/linux/C99/Mod/wctype.cp @@ -0,0 +1,58 @@ +MODULE C99wctype ['libc.so.6']; + + (* generated by genposix.sh, do not modify *) + + IMPORT SYSTEM, C99types, C99locale; + + TYPE + char* = C99types.char; + signed_char* = C99types.signed_char; + unsigned_char* = C99types.unsigned_char; + short* = C99types.short; + short_int* = C99types.short_int; + signed_short* = C99types.signed_short; + signed_short_int* = C99types.signed_short_int; + unsigned_short* = C99types.unsigned_short; + unsigned_short_int* = C99types.unsigned_short_int; + int* = C99types.int; + signed* = C99types.signed; + signed_int* = C99types.signed_int; + unsigned* = C99types.unsigned; + unsigned_int* = C99types.unsigned_int; + long* = C99types.long; + long_int* = C99types.long_int; + signed_long* = C99types.signed_long; + signed_long_int* = C99types.signed_long_int; + unsigned_long* = C99types.unsigned_long; + unsigned_long_int* = C99types.unsigned_long_int; + long_long* = C99types.long_long; + long_long_int* = C99types.long_long_int; + signed_long_long* = C99types.signed_long_long; + signed_long_long_int* = C99types.signed_long_long_int; + unsigned_long_long* = C99types.unsigned_long_long; + unsigned_long_long_int* = C99types.unsigned_long_long_int; + float* = C99types.float; + double* = C99types.double; + long_double* = C99types.long_double; + + TYPE + wint_t* = INTEGER; + wctype_t* = INTEGER; + + TYPE + wctrans_t* = INTEGER; + + TYPE + locale_t* = C99locale.locale_t; + + CONST + WEOF* = -1; + + PROCEDURE [ccall] iswalpha* (wc: wint_t): int; + PROCEDURE [ccall] iswdigit* (wc: wint_t): int; + PROCEDURE [ccall] iswlower* (wc: wint_t): int; + PROCEDURE [ccall] iswupper* (wc: wint_t): int; + PROCEDURE [ccall] towlower* (wc: wint_t): wint_t; + PROCEDURE [ccall] towupper* (wc: wint_t): wint_t; + +END C99wctype. diff --git a/src/i486/linux/System/Mod/Kernel.cp b/src/i486/linux/System/Mod/Kernel.cp new file mode 100644 index 0000000..a9b755a --- /dev/null +++ b/src/i486/linux/System/Mod/Kernel.cp @@ -0,0 +1,1708 @@ +MODULE Kernel; + + IMPORT S := SYSTEM, stdlib := C99stdlib, stdio := C99stdio, + time := C99time, wctype := C99wctype, sysmman := C99sys_mman, + dlfcn := C99dlfcn, types := C99types, fcntl := C99fcntl, + unistd := C99unistd, signal := C99signal, setjmp := C99setjmp; + + (* init fpu? *) + (* add signal blocking to avoid race conditions in Try/Trap/TrapHandler *) + (* add BeepHook for Beep *) + (* implement Call using libffi *) + + CONST + nameLen* = 256; + + littleEndian* = TRUE; + timeResolution* = 1000; (* ticks per second *) + + processor* = 1; (* generic c *) + + objType* = "ocf"; (* file types *) + symType* = "osf"; + docType* = "odc"; + + (* loader constants *) + done* = 0; + fileNotFound* = 1; + syntaxError* = 2; + objNotFound* = 3; + illegalFPrint* = 4; + cyclicImport* = 5; + noMem* = 6; + commNotFound* = 7; + commSyntaxError* = 8; + moduleNotFound* = 9; + + any = 1000000; + + CX = 1; + SP = 4; (* register number of stack pointer *) + FP = 5; (* register number of frame pointer *) + ML = 3; (* register which holds the module list at program start *) + + strictStackSweep = FALSE; + N = 128 DIV 16; (* free lists *) + + (* kernel flags in module desc *) + init = 16; dyn = 17; dll = 24; iptrs = 30; + + (* meta interface consts *) + mConst = 1; mTyp = 2; mVar = 3; mProc = 4; mField = 5; + + TYPE + Name* = ARRAY nameLen OF CHAR; + Utf8Name* = ARRAY nameLen OF SHORTCHAR; + Command* = PROCEDURE; + + Module* = POINTER TO RECORD [untagged] + next-: Module; + opts-: SET; (* 0..15: compiler opts, 16..31: kernel flags *) + refcnt-: INTEGER; (* <0: module invalidated *) + compTime-, loadTime-: ARRAY 6 OF SHORTINT; + ext-: INTEGER; (* currently not used *) + term-: Command; (* terminator *) + nofimps-, nofptrs-: INTEGER; + csize-, dsize-, rsize-: INTEGER; + code-, data-, refs-: INTEGER; + procBase-, varBase-: INTEGER; (* meta base addresses *) + names-: POINTER TO ARRAY [untagged] OF SHORTCHAR; (* names[0] = 0X *) + ptrs-: POINTER TO ARRAY [untagged] OF INTEGER; + imports-: POINTER TO ARRAY [untagged] OF Module; + export-: Directory; (* exported objects (name sorted) *) + name-: Utf8Name + END; + + Type* = POINTER TO RECORD [untagged] + (* record: ptr to method n at offset - 4 * (n+1) *) + size-: INTEGER; (* record: size, array: #elem, dyn array: 0, proc: sigfp *) + mod-: Module; + id-: INTEGER; (* name idx * 256 + lev * 16 + attr * 4 + form *) + base-: ARRAY 16 OF Type; (* signature if form = ProcTyp *) + fields-: Directory; (* new fields (declaration order) *) + ptroffs-: ARRAY any OF INTEGER (* array of any length *) + END; + + Object* = POINTER TO ObjDesc; + + ObjDesc* = RECORD [untagged] + fprint-: INTEGER; + offs-: INTEGER; (* pvfprint for record types *) + id-: INTEGER; (* name idx * 256 + vis * 16 + mode *) + struct-: Type (* id of basic type or pointer to typedesc/signature *) + END; + + Directory* = POINTER TO RECORD [untagged] + num-: INTEGER; (* number of entries *) + obj-: ARRAY any OF ObjDesc (* array of any length *) + END; + + Signature* = POINTER TO RECORD [untagged] + retStruct-: Type; (* id of basic type or pointer to typedesc or 0 *) + num-: INTEGER; (* number of parameters *) + par-: ARRAY any OF RECORD [untagged] (* parameters *) + id-: INTEGER; (* name idx * 256 + kind *) + struct-: Type (* id of basic type or pointer to typedesc *) + END + END; + + Handler* = PROCEDURE; + + Reducer* = POINTER TO ABSTRACT RECORD + next: Reducer + END; + + Identifier* = ABSTRACT RECORD + typ*: INTEGER; + obj-: ANYPTR + END; + + TrapCleaner* = POINTER TO ABSTRACT RECORD + next: TrapCleaner + END; + + TryHandler* = PROCEDURE (a, b, c: INTEGER); + + (* meta extension suport *) + + ItemExt* = POINTER TO ABSTRACT RECORD END; + + ItemAttr* = RECORD + obj*, vis*, typ*, adr*: INTEGER; + mod*: Module; + desc*: Type; + ptr*: S.PTR; + ext*: ItemExt + END; + + Hook* = POINTER TO ABSTRACT RECORD END; + + LoaderHook* = POINTER TO ABSTRACT RECORD (Hook) + res*: INTEGER; + importing*, imported*, object*: ARRAY 256 OF CHAR + END; + + Block = POINTER TO RECORD [untagged] + tag: Type; + last: INTEGER; (* arrays: last element *) + actual: INTEGER; (* arrays: used during mark phase *) + first: INTEGER (* arrays: first element *) + END; + + FreeBlock = POINTER TO FreeDesc; + + FreeDesc = RECORD [untagged] + tag: Type; (* f.tag = ADR(f.size) *) + size: INTEGER; + next: FreeBlock + END; + + Cluster = POINTER TO RECORD [untagged] + size: INTEGER; (* total size *) + next: Cluster; + max: INTEGER (* exe: reserved size, dll: original address *) + (* start of first block *) + END; + + FList = POINTER TO RECORD + next: FList; + blk: Block; + iptr, aiptr: BOOLEAN + END; + + CList = POINTER TO RECORD + next: CList; + do: Command; + trapped: BOOLEAN + END; + + + PtrType = RECORD v: S.PTR END; (* used for array of pointer *) + Char8Type = RECORD v: SHORTCHAR END; + Char16Type = RECORD v: CHAR END; + Int8Type = RECORD v: BYTE END; + Int16Type = RECORD v: SHORTINT END; + Int32Type = RECORD v: INTEGER END; + Int64Type = RECORD v: LONGINT END; + BoolType = RECORD v: BOOLEAN END; + SetType = RECORD v: SET END; + Real32Type = RECORD v: SHORTREAL END; + Real64Type = RECORD v: REAL END; + ProcType = RECORD v: PROCEDURE END; + UPtrType = RECORD v: INTEGER END; + StrPtr = POINTER TO ARRAY [untagged] OF SHORTCHAR; + + ArrStrPtr = POINTER TO ARRAY [untagged] OF StrPtr; + + ADDRESS* = types.Pvoid; + + VAR + baseStack: INTEGER; + root: Cluster; + modList-: Module; + trapCount-: INTEGER; + err-, pc-, sp-, fp-, stack-, val-: INTEGER; + + isTry, testRead: BOOLEAN; + startEnv: setjmp.sigjmp_buf; + tryEnv, readEnv: setjmp.jmp_buf; + + argc-: INTEGER; + argv-: ArrStrPtr; + pagesize: unistd.long; + + free: ARRAY N OF FreeBlock; (* free list *) + sentinelBlock: FreeDesc; + sentinel: FreeBlock; + candidates: ARRAY 1024 OF INTEGER; + nofcand: INTEGER; + allocated: INTEGER; (* bytes allocated on BlackBox heap *) + total: INTEGER; (* current total size of BlackBox heap *) + used: INTEGER; (* bytes allocated on system heap *) + finalizers: FList; + hotFinalizers: FList; + cleaners: CList; + reducers: Reducer; + trapStack: TrapCleaner; + actual: Module; (* valid during module initialization *) + + trapViewer, trapChecker: Handler; + trapped, guarded, secondTrap: BOOLEAN; + interrupted: BOOLEAN; + static, inDll, terminating: BOOLEAN; + restart: Command; + + loader: LoaderHook; + loadres: INTEGER; + + wouldFinalize: BOOLEAN; + + watcher*: PROCEDURE (event: INTEGER); (* for debugging *) + + PROCEDURE Erase (adr, words: INTEGER); + BEGIN + ASSERT(words >= 0, 20); + WHILE words > 0 DO + S.PUT(adr, 0); + INC(adr, 4); + DEC(words) + END + END Erase; + + + PROCEDURE (VAR id: Identifier) Identified* (): BOOLEAN, NEW, ABSTRACT; + PROCEDURE (r: Reducer) Reduce* (full: BOOLEAN), NEW, ABSTRACT; + PROCEDURE (c: TrapCleaner) Cleanup*, NEW, EMPTY; + + (* meta extension suport *) + + PROCEDURE (e: ItemExt) Lookup* (name: ARRAY OF CHAR; VAR i: ANYREC), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) Index* (index: INTEGER; VAR elem: ANYREC), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) Deref* (VAR ref: ANYREC), NEW, ABSTRACT; + + PROCEDURE (e: ItemExt) Valid* (): BOOLEAN, NEW, ABSTRACT; + PROCEDURE (e: ItemExt) Size* (): INTEGER, NEW, ABSTRACT; + PROCEDURE (e: ItemExt) BaseTyp* (): INTEGER, NEW, ABSTRACT; + PROCEDURE (e: ItemExt) Len* (): INTEGER, NEW, ABSTRACT; + + PROCEDURE (e: ItemExt) Call* (OUT ok: BOOLEAN), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) BoolVal* (): BOOLEAN, NEW, ABSTRACT; + PROCEDURE (e: ItemExt) PutBoolVal* (x: BOOLEAN), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) CharVal* (): CHAR, NEW, ABSTRACT; + PROCEDURE (e: ItemExt) PutCharVal* (x: CHAR), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) IntVal* (): INTEGER, NEW, ABSTRACT; + PROCEDURE (e: ItemExt) PutIntVal* (x: INTEGER), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) LongVal* (): LONGINT, NEW, ABSTRACT; + PROCEDURE (e: ItemExt) PutLongVal* (x: LONGINT), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) RealVal* (): REAL, NEW, ABSTRACT; + PROCEDURE (e: ItemExt) PutRealVal* (x: REAL), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) SetVal* (): SET, NEW, ABSTRACT; + PROCEDURE (e: ItemExt) PutSetVal* (x: SET), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) PtrVal* (): ANYPTR, NEW, ABSTRACT; + PROCEDURE (e: ItemExt) PutPtrVal* (x: ANYPTR), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) GetSStringVal* (OUT x: ARRAY OF SHORTCHAR; + OUT ok: BOOLEAN), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) PutSStringVal* (IN x: ARRAY OF SHORTCHAR; + OUT ok: BOOLEAN), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) GetStringVal* (OUT x: ARRAY OF CHAR; OUT ok: BOOLEAN), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) PutStringVal* (IN x: ARRAY OF CHAR; OUT ok: BOOLEAN), NEW, ABSTRACT; + + (* -------------------- miscellaneous tools -------------------- *) + + PROCEDURE IsUpper* (ch: CHAR): BOOLEAN; + BEGIN + RETURN wctype.iswupper(ORD(ch)) # 0 + END IsUpper; + + PROCEDURE Upper* (ch: CHAR): CHAR; + BEGIN + RETURN CHR(wctype.towupper(ORD(ch))) + END Upper; + + PROCEDURE IsLower* (ch: CHAR): BOOLEAN; + BEGIN + RETURN wctype.iswlower(ORD(ch)) # 0 + END IsLower; + + PROCEDURE Lower* (ch: CHAR): CHAR; + BEGIN + RETURN CHR(wctype.towlower(ORD(ch))) + END Lower; + + PROCEDURE IsAlpha* (ch: CHAR): BOOLEAN; + BEGIN + RETURN wctype.iswalpha(ORD(ch)) # 0 + END IsAlpha; + + PROCEDURE Utf8ToString* (IN in: ARRAY OF SHORTCHAR; OUT out: ARRAY OF CHAR; OUT res: INTEGER); + VAR i, j, val, max: INTEGER; ch: SHORTCHAR; + + PROCEDURE FormatError(); + BEGIN out := in$; res := 2 (*format error*) + END FormatError; + + BEGIN + ch := in[0]; i := 1; j := 0; max := LEN(out) - 1; + WHILE (ch # 0X) & (j < max) DO + IF ch < 80X THEN + out[j] := ch; INC(j) + ELSIF ch < 0E0X THEN + val := ORD(ch) - 192; + IF val < 0 THEN FormatError; RETURN END ; + ch := in[i]; INC(i); val := val * 64 + ORD(ch) - 128; + IF (ch < 80X) OR (ch >= 0E0X) THEN FormatError; RETURN END ; + out[j] := CHR(val); INC(j) + ELSIF ch < 0F0X THEN + val := ORD(ch) - 224; + ch := in[i]; INC(i); val := val * 64 + ORD(ch) - 128; + IF (ch < 80X) OR (ch >= 0E0X) THEN FormatError; RETURN END ; + ch := in[i]; INC(i); val := val * 64 + ORD(ch) - 128; + IF (ch < 80X) OR (ch >= 0E0X) THEN FormatError; RETURN END ; + out[j] := CHR(val); INC(j) + ELSE + FormatError; RETURN + END ; + ch := in[i]; INC(i) + END; + out[j] := 0X; + IF ch = 0X THEN res := 0 (*ok*) ELSE res := 1 (*truncated*) END + END Utf8ToString; + + PROCEDURE StringToUtf8* (IN in: ARRAY OF CHAR; OUT out: ARRAY OF SHORTCHAR; OUT res: INTEGER); + VAR i, j, val, max: INTEGER; + BEGIN + i := 0; j := 0; max := LEN(out) - 3; + WHILE (in[i] # 0X) & (j < max) DO + val := ORD(in[i]); INC(i); + IF val < 128 THEN + out[j] := SHORT(CHR(val)); INC(j) + ELSIF val < 2048 THEN + out[j] := SHORT(CHR(val DIV 64 + 192)); INC(j); + out[j] := SHORT(CHR(val MOD 64 + 128)); INC(j) + ELSE + out[j] := SHORT(CHR(val DIV 4096 + 224)); INC(j); + out[j] := SHORT(CHR(val DIV 64 MOD 64 + 128)); INC(j); + out[j] := SHORT(CHR(val MOD 64 + 128)); INC(j) + END; + END; + out[j] := 0X; + IF in[i] = 0X THEN res := 0 (*ok*) ELSE res := 1 (*truncated*) END + END StringToUtf8; + + PROCEDURE SplitName* (name: ARRAY OF CHAR; VAR head, tail: ARRAY OF CHAR); + (* portable *) + VAR i, j: INTEGER; ch, lch: CHAR; + BEGIN + i := 0; ch := name[0]; + IF ch # 0X THEN + REPEAT + head[i] := ch; lch := ch; INC(i); ch := name[i] + UNTIL (ch = 0X) OR (ch = ".") OR IsUpper(ch) & ~IsUpper(lch); + IF ch = "." THEN i := 0; ch := name[0] END; + head[i] := 0X; j := 0; + WHILE ch # 0X DO tail[j] := ch; INC(i); INC(j); ch := name[i] END; + tail[j] := 0X; + IF tail = "" THEN tail := head$; head := "" END + ELSE head := ""; tail := "" + END + END SplitName; + + PROCEDURE MakeFileName* (VAR name: ARRAY OF CHAR; type: ARRAY OF CHAR); + VAR i, j: INTEGER; ext: ARRAY 8 OF CHAR; ch: CHAR; + BEGIN + i := 0; + WHILE (name[i] # 0X) & (name[i] # ".") DO INC(i) END; + IF name[i] = "." THEN + IF name[i + 1] = 0X THEN name[i] := 0X END + ELSE + IF type = "" THEN ext := docType ELSE ext := type$ END; + IF i < LEN(name) - LEN(ext$) - 1 THEN + name[i] := "."; INC(i); j := 0; ch := ext[0]; + WHILE ch # 0X DO + name[i] := Lower(ch); INC(i); INC(j); ch := ext[j] + END; + name[i] := 0X + END + END + END MakeFileName; + + PROCEDURE Time* (): LONGINT; + VAR res: time.int; tp: time.struct_timespec; + BEGIN + ASSERT(timeResolution >= 1); + ASSERT(timeResolution <= 1000000000); + res := time.clock_gettime(time.CLOCK_MONOTONIC, tp); + ASSERT(res = 0, 100); + RETURN tp.tv_sec * LONG(timeResolution) + tp.tv_nsec DIV LONG(1000000000 DIV timeResolution) + END Time; + + PROCEDURE Beep*; + (* !!! *) + END Beep; + + PROCEDURE SearchProcVar* (var: INTEGER; VAR m: Module; VAR adr: INTEGER); + BEGIN + adr := var; m := NIL; + IF var # 0 THEN + m := modList; + WHILE (m # NIL) & ((var < m.code) OR (var >= m.code + m.csize)) DO m := m.next END; + IF m # NIL THEN DEC(adr, m.code) END + END + END SearchProcVar; + + (* -------------------- system memory management --------------------- *) + + PROCEDURE AllocMem (size: sysmman.size_t; VAR max: sysmman.size_t): ADDRESS; + VAR fd, flags, res: fcntl.int; ptr: ADDRESS; + BEGIN + max := (size + pagesize - 1) DIV pagesize * pagesize; + fd := fcntl.open("/dev/zero", fcntl.O_RDWR, 0); + IF fd # -1 THEN + flags := sysmman.PROT_READ + sysmman.PROT_WRITE; + ptr := sysmman.mmap(0, max, flags, sysmman.MAP_PRIVATE, fd, 0); + IF ptr = sysmman.MAP_FAILED THEN ptr := 0 END; + res := unistd.close(fd); + ASSERT(res = 0, 100) + ELSE + ptr := 0 + END; + RETURN ptr + END AllocMem; + + PROCEDURE FreeMem (adr: ADDRESS; size: sysmman.size_t); + VAR res: types.int; + BEGIN + size := (size + pagesize - 1) DIV pagesize * pagesize; + res := sysmman.munmap(adr, size); + ASSERT(res = 0, 100) + END FreeMem; + + PROCEDURE AllocHeapMem (size: INTEGER; VAR c: Cluster); + CONST N = 65536; (* cluster size for dll *) + VAR adr, allocated: INTEGER; + BEGIN + INC(size, 16); + ASSERT(size > 0, 100); adr := 0; + IF size < N THEN adr := stdlib.malloc(N) END; + IF adr = 0 THEN adr := stdlib.malloc(size); allocated := size ELSE allocated := N END; + IF adr = 0 THEN c := NIL + ELSE + c := S.VAL(Cluster, (adr + 15) DIV 16 * 16); c.max := adr; + c.size := allocated - (S.VAL(INTEGER, c) - adr); + INC(used, c.size); INC(total, c.size) + END; + ASSERT((adr = 0) OR (adr MOD 16 = 0) & (c.size >= size), 101); + (* post: (c = NIL) OR (c MOD 16 = 0) & (c.size >= size) *) + END AllocHeapMem; + + PROCEDURE FreeHeapMem (c: Cluster); + BEGIN + DEC(used, c.size); DEC(total, c.size); + stdlib.free(S.VAL(ADDRESS, c.max)) + END FreeHeapMem; + + PROCEDURE HeapFull (size: INTEGER): BOOLEAN; + BEGIN + RETURN TRUE + END HeapFull; + + PROCEDURE AllocModMem* (descSize, modSize: INTEGER; VAR descAdr, modAdr: INTEGER); + BEGIN + descAdr := 0; modAdr := 0; + descAdr := AllocMem(descSize, descSize); + IF descAdr # 0 THEN + modAdr := AllocMem(modSize, modSize); + IF modAdr = 0 THEN + FreeMem(descAdr, descSize) + ELSE + INC(used, descSize + modSize) + END + END + END AllocModMem; + + PROCEDURE DeallocModMem* (descSize, modSize, descAdr, modAdr: INTEGER); + BEGIN + FreeMem(descAdr, descSize); + FreeMem(modAdr, modSize); + DEC(used, descSize + modSize) + END DeallocModMem; + + PROCEDURE InvalModMem (modSize, modAdr: INTEGER); + BEGIN + FreeMem(modAdr, modSize) + END InvalModMem; + + PROCEDURE IsReadable* (from, to: INTEGER): BOOLEAN; + VAR i: INTEGER; x: BYTE; res: setjmp.int; + BEGIN + testRead := TRUE; + res := setjmp.setjmp(readEnv); + IF res = 0 THEN + IF from <= to THEN + FOR i := from TO to - 1 DO + S.GET(i, x) + END + ELSE + FOR i := to - 1 TO from BY -1 DO + S.GET(i, x) + END + END; + END; + testRead := FALSE; + RETURN res = 0 + END IsReadable; + + (* --------------------- NEW implementation (portable) -------------------- *) + + PROCEDURE^ NewBlock (size: INTEGER): Block; + + PROCEDURE NewRec* (typ: INTEGER): INTEGER; (* implementation of NEW(ptr) *) + VAR size, adr: INTEGER; b: Block; tag: Type; l: FList; + BEGIN + IF ~ODD(typ) THEN + tag := S.VAL(Type, typ); + b := NewBlock(tag.size); + IF b # NIL THEN + b.tag := tag; + S.GET(typ - 4, size); + IF size # 0 THEN (* record uses a finalizer *) + l := S.VAL(FList, S.ADR(b.last)); (* anchor new object! *) + l := S.VAL(FList, NewRec(S.TYP(FList))); (* NEW(l) *) + l.blk := b; l.next := finalizers; finalizers := l + END; + adr := S.ADR(b.last) + ELSE + adr := 0 + END + ELSE + HALT(100) (* COM interface pointers not supported *) + END; + RETURN adr + END NewRec; + + PROCEDURE NewArr* (eltyp, nofelem, nofdim: INTEGER): INTEGER; (* impl. of NEW(ptr, dim0, dim1, ...) *) + VAR b: Block; size, headSize: INTEGER; t: Type; + BEGIN + CASE eltyp OF + | -1: HALT(100) (* COM interface pointers not supported *) + | 0: eltyp := S.ADR(PtrType) + | 1: eltyp := S.ADR(Char8Type) + | 2: eltyp := S.ADR(Int16Type) + | 3: eltyp := S.ADR(Int8Type) + | 4: eltyp := S.ADR(Int32Type) + | 5: eltyp := S.ADR(BoolType) + | 6: eltyp := S.ADR(SetType) + | 7: eltyp := S.ADR(Real32Type) + | 8: eltyp := S.ADR(Real64Type) + | 9: eltyp := S.ADR(Char16Type) + | 10: eltyp := S.ADR(Int64Type) + | 11: eltyp := S.ADR(ProcType) + | 12: HALT(101) (* COM interface pointers not supported *) + ELSE + ASSERT(~ODD(eltyp), 102) (* COM interface pointers not supported *) + END; + t := S.VAL(Type, eltyp); + headSize := 4 * nofdim + 12; + size := headSize + nofelem * t.size; + b := NewBlock(size); + IF b # NIL THEN + b.tag := S.VAL(Type, eltyp + 2); (* tag + array mark *) + b.last := S.ADR(b.last) + size - t.size; (* pointer to last elem *) + b.first := S.ADR(b.last) + headSize; (* pointer to first elem *) + RETURN S.ADR(b.last) + ELSE + RETURN 0 + END; + END NewArr; + + (* -------------------- handler installation (portable) --------------------- *) + + PROCEDURE ThisFinObj* (VAR id: Identifier): ANYPTR; + VAR l: FList; + BEGIN + ASSERT(id.typ # 0, 100); + l := finalizers; + WHILE l # NIL DO + IF S.VAL(INTEGER, l.blk.tag) = id.typ THEN + id.obj := S.VAL(ANYPTR, S.ADR(l.blk.last)); + IF id.Identified() THEN RETURN id.obj END + END; + l := l.next + END; + RETURN NIL + END ThisFinObj; + + PROCEDURE InstallReducer* (r: Reducer); + BEGIN + r.next := reducers; reducers := r + END InstallReducer; + + PROCEDURE InstallTrapViewer* (h: Handler); + BEGIN + trapViewer := h + END InstallTrapViewer; + + PROCEDURE InstallTrapChecker* (h: Handler); + BEGIN + trapChecker := h + END InstallTrapChecker; + + PROCEDURE PushTrapCleaner* (c: TrapCleaner); + VAR t: TrapCleaner; + BEGIN + t := trapStack; WHILE (t # NIL) & (t # c) DO t := t.next END; + ASSERT(t = NIL, 20); + c.next := trapStack; trapStack := c + END PushTrapCleaner; + + PROCEDURE PopTrapCleaner* (c: TrapCleaner); + VAR t: TrapCleaner; + BEGIN + t := NIL; + WHILE (trapStack # NIL) & (t # c) DO + t := trapStack; trapStack := trapStack.next + END + END PopTrapCleaner; + + PROCEDURE InstallCleaner* (p: Command); + VAR c: CList; + BEGIN + c := S.VAL(CList, NewRec(S.TYP(CList))); (* NEW(c) *) + c.do := p; c.trapped := FALSE; c.next := cleaners; cleaners := c + END InstallCleaner; + + PROCEDURE RemoveCleaner* (p: Command); + VAR c0, c: CList; + BEGIN + c := cleaners; c0 := NIL; + WHILE (c # NIL) & (c.do # p) DO c0 := c; c := c.next END; + IF c # NIL THEN + IF c0 = NIL THEN cleaners := cleaners.next ELSE c0.next := c.next END + END + END RemoveCleaner; + + PROCEDURE Cleanup*; + VAR c, c0: CList; + BEGIN + c := cleaners; c0 := NIL; + WHILE c # NIL DO + IF ~c.trapped THEN + c.trapped := TRUE; c.do; c.trapped := FALSE; c0 := c + ELSE + IF c0 = NIL THEN cleaners := cleaners.next + ELSE c0.next := c.next + END + END; + c := c.next + END + END Cleanup; + + (* -------------------- meta information (portable) --------------------- *) + + PROCEDURE (h: LoaderHook) ThisMod* (IN name: ARRAY OF CHAR): Module, NEW, ABSTRACT; + + PROCEDURE SetLoaderHook*(h: LoaderHook); + BEGIN + loader := h + END SetLoaderHook; + + PROCEDURE InitModule (mod: Module); (* initialize linked modules *) + VAR body: Command; + BEGIN + IF ~(dyn IN mod.opts) & (mod.next # NIL) & ~(init IN mod.next.opts) THEN InitModule(mod.next) END; + IF ~(init IN mod.opts) THEN + body := S.VAL(Command, mod.code); + INCL(mod.opts, init); + actual := mod; + body(); actual := NIL + END + END InitModule; + + PROCEDURE ThisLoadedMod* (IN name: ARRAY OF CHAR): Module; (* loaded modules only *) + VAR m: Module; res: INTEGER; n: Utf8Name; + BEGIN + StringToUtf8(name, n, res); ASSERT(res = 0); + loadres := done; + m := modList; + WHILE (m # NIL) & ((m.name # n) OR (m.refcnt < 0)) DO m := m.next END; + IF (m # NIL) & ~(init IN m.opts) THEN InitModule(m) END; + IF m = NIL THEN loadres := moduleNotFound END; + RETURN m + END ThisLoadedMod; + + PROCEDURE ThisMod* (IN name: ARRAY OF CHAR): Module; + BEGIN + IF loader # NIL THEN + loader.res := done; + RETURN loader.ThisMod(name) + ELSE + RETURN ThisLoadedMod(name) + END + END ThisMod; + + PROCEDURE LoadMod* (IN name: ARRAY OF CHAR); + VAR m: Module; + BEGIN + m := ThisMod(name) + END LoadMod; + + PROCEDURE GetLoaderResult* (OUT res: INTEGER; OUT importing, imported, object: ARRAY OF CHAR); + BEGIN + IF loader # NIL THEN + res := loader.res; + importing := loader.importing$; + imported := loader.imported$; + object := loader.object$ + ELSE + res := loadres; + importing := ""; + imported := ""; + object := "" + END + END GetLoaderResult; + + PROCEDURE ThisObject* (mod: Module; IN name: ARRAY OF CHAR): Object; + VAR l, r, m, res: INTEGER; p: StrPtr; n: Utf8Name; + BEGIN + StringToUtf8(name, n, res); ASSERT(res = 0); + l := 0; r := mod.export.num; + WHILE l < r DO (* binary search *) + m := (l + r) DIV 2; + p := S.VAL(StrPtr, S.ADR(mod.names[mod.export.obj[m].id DIV 256])); + IF p^ = n THEN RETURN S.VAL(Object, S.ADR(mod.export.obj[m])) END; + IF p^ < n THEN l := m + 1 ELSE r := m END + END; + RETURN NIL + END ThisObject; + + PROCEDURE ThisDesc* (mod: Module; fprint: INTEGER): Object; + VAR i, n: INTEGER; + BEGIN + i := 0; n := mod.export.num; + WHILE (i < n) & (mod.export.obj[i].id DIV 256 = 0) DO + IF mod.export.obj[i].offs = fprint THEN RETURN S.VAL(Object, S.ADR(mod.export.obj[i])) END; + INC(i) + END; + RETURN NIL + END ThisDesc; + + PROCEDURE ThisField* (rec: Type; IN name: ARRAY OF CHAR): Object; + VAR n, res: INTEGER; p: StrPtr; obj: Object; m: Module; nn: Utf8Name; + BEGIN + StringToUtf8(name, nn, res); ASSERT(res = 0); + m := rec.mod; + obj := S.VAL(Object, S.ADR(rec.fields.obj[0])); n := rec.fields.num; + WHILE n > 0 DO + p := S.VAL(StrPtr, S.ADR(m.names[obj.id DIV 256])); + IF p^ = nn THEN RETURN obj END; + DEC(n); INC(S.VAL(INTEGER, obj), 16) + END; + RETURN NIL + END ThisField; + + PROCEDURE ThisCommand* (mod: Module; IN name: ARRAY OF CHAR): Command; + VAR x: Object; sig: Signature; + BEGIN + x := ThisObject(mod, name); + IF (x # NIL) & (x.id MOD 16 = mProc) THEN + sig := S.VAL(Signature, x.struct); + IF (sig.retStruct = NIL) & (sig.num = 0) THEN RETURN S.VAL(Command, mod.procBase + x.offs) END + END; + RETURN NIL + END ThisCommand; + + PROCEDURE ThisType* (mod: Module; IN name: ARRAY OF CHAR): Type; + VAR x: Object; + BEGIN + x := ThisObject(mod, name); + IF (x # NIL) & (x.id MOD 16 = mTyp) & (S.VAL(INTEGER, x.struct) DIV 256 # 0) THEN + RETURN x.struct + ELSE + RETURN NIL + END + END ThisType; + + PROCEDURE TypeOf* (IN rec: ANYREC): Type; + BEGIN + RETURN S.VAL(Type, S.TYP(rec)) + END TypeOf; + + PROCEDURE LevelOf* (t: Type): SHORTINT; + BEGIN + RETURN SHORT(t.id DIV 16 MOD 16) + END LevelOf; + + PROCEDURE NewObj* (VAR o: S.PTR; t: Type); + VAR i: INTEGER; + BEGIN + IF t.size = -1 THEN o := NIL + ELSE + i := 0; WHILE t.ptroffs[i] >= 0 DO INC(i) END; + IF t.ptroffs[i+1] >= 0 THEN INC(S.VAL(INTEGER, t)) END; (* with interface pointers *) + o := S.VAL(S.PTR, NewRec(S.VAL(INTEGER, t))) (* generic NEW *) + END + END NewObj; + + PROCEDURE GetModName* (mod: Module; OUT name: Name); + VAR res: INTEGER; + BEGIN + Utf8ToString(mod.name, name, res); ASSERT(res = 0) + END GetModName; + + PROCEDURE GetObjName* (mod: Module; obj: Object; OUT name: Name); + VAR p: StrPtr; res: INTEGER; + BEGIN + p := S.VAL(StrPtr, S.ADR(mod.names[obj.id DIV 256])); + Utf8ToString(p^$, name, res); ASSERT(res = 0) + END GetObjName; + + PROCEDURE GetTypeName* (t: Type; OUT name: Name); + VAR p: StrPtr; res: INTEGER; + BEGIN + p := S.VAL(StrPtr, S.ADR(t.mod.names[t.id DIV 256])); + Utf8ToString(p^$, name, res); ASSERT(res = 0) + END GetTypeName; + + PROCEDURE RegisterMod* (mod: Module); + VAR i: INTEGER; epoch: time.time_t; tm: time.struct_tm; ptm: time.Pstruct_tm; + BEGIN + mod.next := modList; modList := mod; mod.refcnt := 0; INCL(mod.opts, dyn); i := 0; + WHILE i < mod.nofimps DO + IF mod.imports[i] # NIL THEN INC(mod.imports[i].refcnt) END; + INC(i) + END; + epoch := time.time(NIL); + ptm := time.localtime_r(epoch, tm); + IF ptm # NIL THEN + mod.loadTime[0] := SHORT(tm.tm_year + 1900); + mod.loadTime[1] := SHORT(tm.tm_mon + 1); + mod.loadTime[2] := SHORT(tm.tm_mday); + mod.loadTime[3] := SHORT(tm.tm_hour); + mod.loadTime[4] := SHORT(tm.tm_min); + mod.loadTime[5] := SHORT(tm.tm_sec) + ELSE + mod.loadTime[0] := 0; + mod.loadTime[1] := 0; + mod.loadTime[2] := 0; + mod.loadTime[3] := 0; + mod.loadTime[4] := 0; + mod.loadTime[5] := 0 + END; + IF ~(init IN mod.opts) THEN InitModule(mod) END + END RegisterMod; + + PROCEDURE^ Collect*; + + PROCEDURE UnloadMod* (mod: Module); + VAR i: INTEGER; t: Command; + BEGIN + IF mod.refcnt = 0 THEN + t := mod.term; mod.term := NIL; + IF t # NIL THEN t() END; (* terminate module *) + i := 0; + WHILE i < mod.nofptrs DO (* release global pointers *) + S.PUT(mod.varBase + mod.ptrs[i], 0); INC(i) + END; + Collect; (* call finalizers *) + i := 0; + WHILE i < mod.nofimps DO (* release imported modules *) + IF mod.imports[i] # NIL THEN DEC(mod.imports[i].refcnt) END; + INC(i) + END; + mod.refcnt := -1; + IF dyn IN mod.opts THEN (* release memory *) + InvalModMem(mod.data + mod.dsize - mod.refs, mod.refs) + END + END + END UnloadMod; + + (* -------------------- dynamic procedure call --------------------- *) + + PROCEDURE Call* (adr: INTEGER; sig: Signature; IN par: ARRAY OF INTEGER; n: INTEGER): LONGINT; + BEGIN + HALT(126); (* !!! *) + RETURN 0 + END Call; + + (* -------------------- reference information (portable) --------------------- *) + + PROCEDURE RefCh (VAR ref: INTEGER; OUT ch: SHORTCHAR); + BEGIN + S.GET(ref, ch); INC(ref) + END RefCh; + + PROCEDURE RefNum (VAR ref: INTEGER; OUT x: INTEGER); + VAR s, n: INTEGER; ch: SHORTCHAR; + BEGIN + s := 0; n := 0; RefCh(ref, ch); + WHILE ORD(ch) >= 128 DO INC(n, ASH(ORD(ch) - 128, s) ); INC(s, 7); RefCh(ref, ch) END; + x := n + ASH(ORD(ch) MOD 64 - ORD(ch) DIV 64 * 64, s) + END RefNum; + + PROCEDURE RefName (VAR ref: INTEGER; OUT n: Utf8Name); + VAR i: INTEGER; ch: SHORTCHAR; + BEGIN + i := 0; RefCh(ref, ch); + WHILE ch # 0X DO n[i] := ch; INC(i); RefCh(ref, ch) END; + n[i] := 0X + END RefName; + + PROCEDURE GetRefProc* (VAR ref: INTEGER; OUT adr: INTEGER; OUT name: Utf8Name); + VAR ch: SHORTCHAR; + BEGIN + S.GET(ref, ch); + WHILE ch >= 0FDX DO (* skip variables *) + INC(ref); RefCh(ref, ch); + IF ch = 10X THEN INC(ref, 4) END; + RefNum(ref, adr); RefName(ref, name); S.GET(ref, ch) + END; + WHILE (ch > 0X) & (ch < 0FCX) DO (* skip source refs *) + INC(ref); RefNum(ref, adr); S.GET(ref, ch) + END; + IF ch = 0FCX THEN INC(ref); RefNum(ref, adr); RefName(ref, name) + ELSE adr := 0 + END + END GetRefProc; + + PROCEDURE GetRefVar* (VAR ref: INTEGER; OUT mode, form: SHORTCHAR; OUT desc: Type; OUT adr: INTEGER; OUT name: Utf8Name); + BEGIN + S.GET(ref, mode); desc := NIL; + IF mode >= 0FDX THEN + mode := SHORT(CHR(ORD(mode) - 0FCH)); + INC(ref); RefCh(ref, form); + IF form = 10X THEN + S.GET(ref, desc); INC(ref, 4); form := SHORT(CHR(16 + desc.id MOD 4)) + END; + RefNum(ref, adr); RefName(ref, name) + ELSE + mode := 0X; form := 0X; adr := 0 + END + END GetRefVar; + + PROCEDURE SourcePos* (mod: Module; codePos: INTEGER): INTEGER; + VAR ref, pos, ad, d: INTEGER; ch: SHORTCHAR; name: Utf8Name; + BEGIN + IF mod # NIL THEN (* mf, 12.02.04 *) + ref := mod.refs; pos := 0; ad := 0; S.GET(ref, ch); + WHILE ch # 0X DO + WHILE (ch > 0X) & (ch < 0FCX) DO (* srcref: {dAdr,dPos} *) + INC(ad, ORD(ch)); INC(ref); RefNum(ref, d); + IF ad > codePos THEN RETURN pos END; + INC(pos, d); S.GET(ref, ch) + END; + IF ch = 0FCX THEN (* proc: 0FCX,Adr,Name *) + INC(ref); RefNum(ref, d); RefName(ref, name); S.GET(ref, ch); + IF (d > codePos) & (pos > 0) THEN RETURN pos END + END; + WHILE ch >= 0FDX DO (* skip variables: Mode, Form, adr, Name *) + INC(ref); RefCh(ref, ch); + IF ch = 10X THEN INC(ref, 4) END; + RefNum(ref, d); RefName(ref, name); S.GET(ref, ch) + END + END; + END; + RETURN -1 + END SourcePos; + + PROCEDURE LoadDll* (IN name: ARRAY OF CHAR; VAR ok: BOOLEAN); + VAR h: ADDRESS; file: Utf8Name; res: INTEGER; + BEGIN + StringToUtf8(name, file, res); + IF res = 0 THEN + h := dlfcn.dlopen(file, dlfcn.RTLD_LAZY + dlfcn.RTLD_GLOBAL); + ok := h # 0 + ELSE + ok := FALSE + END + END LoadDll; + + PROCEDURE ThisDllObj* (mode, fprint: INTEGER; IN dll, name: ARRAY OF CHAR): INTEGER; + VAR h, p: ADDRESS; file, sym: Utf8Name; res: INTEGER; err: dlfcn.int; + BEGIN + StringToUtf8(dll, file, res); + IF res = 0 THEN + h := dlfcn.dlopen(file, dlfcn.RTLD_LAZY + dlfcn.RTLD_GLOBAL); + IF h # 0 THEN + StringToUtf8(name, sym, res); + IF res = 0 THEN + p := dlfcn.dlsym(h, sym) + ELSE + p := 0 + END; + err := dlfcn.dlclose(h); + ASSERT(err = 0, 100) + ELSE + p := 0 + END + ELSE + p := 0 + END; + RETURN p + END ThisDllObj; + + (* -------------------- garbage collector (portable) --------------------- *) + + PROCEDURE Mark (this: Block); + VAR father, son: Block; tag: Type; flag, offset, actual: INTEGER; + BEGIN + IF ~ODD(S.VAL(INTEGER, this.tag)) THEN + father := NIL; + LOOP + INC(S.VAL(INTEGER, this.tag)); + flag := S.VAL(INTEGER, this.tag) MOD 4; + tag := S.VAL(Type, S.VAL(INTEGER, this.tag) - flag); + IF flag >= 2 THEN actual := this.first; this.actual := actual + ELSE actual := S.ADR(this.last) + END; + LOOP + offset := tag.ptroffs[0]; + IF offset < 0 THEN + INC(S.VAL(INTEGER, tag), offset + 4); (* restore tag *) + IF (flag >= 2) & (actual < this.last) & (offset < -4) THEN (* next array element *) + INC(actual, tag.size); this.actual := actual + ELSE (* up *) + this.tag := S.VAL(Type, S.VAL(INTEGER, tag) + flag); + IF father = NIL THEN RETURN END; + son := this; this := father; + flag := S.VAL(INTEGER, this.tag) MOD 4; + tag := S.VAL(Type, S.VAL(INTEGER, this.tag) - flag); + offset := tag.ptroffs[0]; + IF flag >= 2 THEN actual := this.actual ELSE actual := S.ADR(this.last) END; + S.GET(actual + offset, father); S.PUT(actual + offset, S.ADR(son.last)); + INC(S.VAL(INTEGER, tag), 4) + END + ELSE + S.GET(actual + offset, son); + IF son # NIL THEN + DEC(S.VAL(INTEGER, son), 4); + IF ~ODD(S.VAL(INTEGER, son.tag)) THEN (* down *) + this.tag := S.VAL(Type, S.VAL(INTEGER, tag) + flag); + S.PUT(actual + offset, father); father := this; this := son; + EXIT + END + END; + INC(S.VAL(INTEGER, tag), 4) + END + END + END + END + END Mark; + + PROCEDURE MarkGlobals; + VAR m: Module; i, p: INTEGER; + BEGIN + m := modList; + WHILE m # NIL DO + IF m.refcnt >= 0 THEN + i := 0; + WHILE i < m.nofptrs DO + S.GET(m.varBase + m.ptrs[i], p); INC(i); + IF p # 0 THEN Mark(S.VAL(Block, p - 4)) END + END + END; + m := m.next + END + END MarkGlobals; + + PROCEDURE Next (b: Block): Block; (* next block in same cluster *) + VAR size: INTEGER; + BEGIN + S.GET(S.VAL(INTEGER, b.tag) DIV 4 * 4, size); + IF ODD(S.VAL(INTEGER, b.tag) DIV 2) THEN INC(size, b.last - S.ADR(b.last)) END; + RETURN S.VAL(Block, S.VAL(INTEGER, b) + (size + 19) DIV 16 * 16) + END Next; + + PROCEDURE CheckCandidates; + (* pre: nofcand > 0 *) + VAR i, j, h, p, end: INTEGER; c: Cluster; blk, next: Block; + BEGIN + (* sort candidates (shellsort) *) + h := 1; REPEAT h := h*3 + 1 UNTIL h > nofcand; + REPEAT h := h DIV 3; i := h; + WHILE i < nofcand DO p := candidates[i]; j := i; + WHILE (j >= h) & (candidates[j-h] > p) DO + candidates[j] := candidates[j-h]; j := j-h + END; + candidates[j] := p; INC(i) + END + UNTIL h = 1; + (* sweep *) + c := root; i := 0; + WHILE c # NIL DO + blk := S.VAL(Block, S.VAL(INTEGER, c) + 12); + end := S.VAL(INTEGER, blk) + (c.size - 12) DIV 16 * 16; + WHILE candidates[i] < S.VAL(INTEGER, blk) DO + INC(i); + IF i = nofcand THEN RETURN END + END; + WHILE S.VAL(INTEGER, blk) < end DO + next := Next(blk); + IF candidates[i] < S.VAL(INTEGER, next) THEN + IF (S.VAL(INTEGER, blk.tag) # S.ADR(blk.last)) (* not a free block *) + & (~strictStackSweep OR (candidates[i] = S.ADR(blk.last))) THEN + Mark(blk) + END; + REPEAT + INC(i); + IF i = nofcand THEN RETURN END + UNTIL candidates[i] >= S.VAL(INTEGER, next) + END; + IF (S.VAL(INTEGER, blk.tag) MOD 4 = 0) & (S.VAL(INTEGER, blk.tag) # S.ADR(blk.last)) + & (blk.tag.base[0] = NIL) & (blk.actual > 0) THEN (* referenced interface record *) + Mark(blk) + END; + blk := next + END; + c := c.next + END + END CheckCandidates; + + PROCEDURE MarkLocals; + VAR sp, p, min, max: INTEGER; c: Cluster; + BEGIN + sp := S.ADR(sp); nofcand := 0; c := root; + WHILE c.next # NIL DO c := c.next END; + min := S.VAL(INTEGER, root); max := S.VAL(INTEGER, c) + c.size; + WHILE sp < baseStack DO + S.GET(sp, p); + IF (p > min) & (p < max) & (~strictStackSweep OR (p MOD 16 = 0)) THEN + candidates[nofcand] := p; INC(nofcand); + IF nofcand = LEN(candidates) - 1 THEN CheckCandidates; nofcand := 0 END + END; + INC(sp, 4) + END; + candidates[nofcand] := max; INC(nofcand); (* ensure complete scan for interface mark*) + IF nofcand > 0 THEN CheckCandidates END + END MarkLocals; + + PROCEDURE MarkFinObj; + VAR f: FList; + BEGIN + wouldFinalize := FALSE; + f := finalizers; + WHILE f # NIL DO + IF ~ODD(S.VAL(INTEGER, f.blk.tag)) THEN wouldFinalize := TRUE END; + Mark(f.blk); + f := f.next + END; + f := hotFinalizers; + WHILE f # NIL DO IF ~ODD(S.VAL(INTEGER, f.blk.tag)) THEN wouldFinalize := TRUE END; + Mark(f.blk); + f := f.next + END + END MarkFinObj; + + PROCEDURE CheckFinalizers; + VAR f, g, h, k: FList; + BEGIN + f := finalizers; g := NIL; + IF hotFinalizers = NIL THEN k := NIL + ELSE + k := hotFinalizers; + WHILE k.next # NIL DO k := k.next END + END; + WHILE f # NIL DO + h := f; f := f.next; + IF ~ODD(S.VAL(INTEGER, h.blk.tag)) THEN + IF g = NIL THEN finalizers := f ELSE g.next := f END; + IF k = NIL THEN hotFinalizers := h ELSE k.next := h END; + k := h; h.next := NIL + ELSE g := h + END + END; + h := hotFinalizers; + WHILE h # NIL DO Mark(h.blk); h := h.next END + END CheckFinalizers; + + PROCEDURE ExecFinalizer (a, b, c: INTEGER); + VAR f: FList; fin: PROCEDURE(this: ANYPTR); + BEGIN + f := S.VAL(FList, a); + S.GET(S.VAL(INTEGER, f.blk.tag) - 4, fin); (* method 0 *) + IF (fin # NIL) & (f.blk.tag.mod.refcnt >= 0) THEN fin(S.VAL(ANYPTR, S.ADR(f.blk.last))) END; + END ExecFinalizer; + + PROCEDURE^ Try* (h: TryHandler; a, b, c: INTEGER); (* COMPILER DEPENDENT *) + + PROCEDURE CallFinalizers; + VAR f: FList; + BEGIN + WHILE hotFinalizers # NIL DO + f := hotFinalizers; hotFinalizers := hotFinalizers.next; + Try(ExecFinalizer, S.VAL(INTEGER, f), 0, 0) + END; + wouldFinalize := FALSE + END CallFinalizers; + + PROCEDURE Insert (blk: FreeBlock; size: INTEGER); (* insert block in free list *) + VAR i: INTEGER; + BEGIN + blk.size := size - 4; blk.tag := S.VAL(Type, S.ADR(blk.size)); + i := MIN(N - 1, (blk.size DIV 16)); + blk.next := free[i]; free[i] := blk + END Insert; + + PROCEDURE Sweep (dealloc: BOOLEAN); + VAR cluster, last, c: Cluster; blk, next: Block; fblk, b, t: FreeBlock; end, i: INTEGER; + BEGIN + cluster := root; last := NIL; allocated := 0; + i := N; + REPEAT DEC(i); free[i] := sentinel UNTIL i = 0; + WHILE cluster # NIL DO + blk := S.VAL(Block, S.VAL(INTEGER, cluster) + 12); + end := S.VAL(INTEGER, blk) + (cluster.size - 12) DIV 16 * 16; + fblk := NIL; + WHILE S.VAL(INTEGER, blk) < end DO + next := Next(blk); + IF ODD(S.VAL(INTEGER, blk.tag)) THEN + IF fblk # NIL THEN + Insert(fblk, S.VAL(INTEGER, blk) - S.VAL(INTEGER, fblk)); + fblk := NIL + END; + DEC(S.VAL(INTEGER, blk.tag)); (* unmark *) + INC(allocated, S.VAL(INTEGER, next) - S.VAL(INTEGER, blk)) + ELSIF fblk = NIL THEN + fblk := S.VAL(FreeBlock, blk) + END; + blk := next + END; + IF dealloc & (S.VAL(INTEGER, fblk) = S.VAL(INTEGER, cluster) + 12) THEN (* deallocate cluster *) + c := cluster; cluster := cluster.next; + IF last = NIL THEN root := cluster ELSE last.next := cluster END; + FreeHeapMem(c) + ELSE + IF fblk # NIL THEN Insert(fblk, end - S.VAL(INTEGER, fblk)) END; + last := cluster; cluster := cluster.next + END + END; + (* reverse free list *) + i := N; + REPEAT + DEC(i); + b := free[i]; fblk := sentinel; + WHILE b # sentinel DO t := b; b := t.next; t.next := fblk; fblk := t END; + free[i] := fblk + UNTIL i = 0 + END Sweep; + + PROCEDURE Collect*; + BEGIN + IF root # NIL THEN + CallFinalizers; (* trap cleanup *) + MarkGlobals; + MarkLocals; + CheckFinalizers; + Sweep(TRUE); + CallFinalizers + END + END Collect; + + PROCEDURE FastCollect*; + BEGIN + IF root # NIL THEN + MarkGlobals; + MarkLocals; + MarkFinObj; + Sweep(FALSE) + END + END FastCollect; + + PROCEDURE WouldFinalize* (): BOOLEAN; + BEGIN + RETURN wouldFinalize + END WouldFinalize; + + (* --------------------- memory allocation (portable) -------------------- *) + + PROCEDURE OldBlock (size: INTEGER): FreeBlock; (* size MOD 16 = 0 *) + VAR b, l: FreeBlock; s, i: INTEGER; + BEGIN + s := size - 4; + i := MIN(N - 1, s DIV 16); + WHILE (i # N - 1) & (free[i] = sentinel) DO INC(i) END; + b := free[i]; l := NIL; + WHILE b.size < s DO l := b; b := b.next END; + IF b # sentinel THEN + IF l = NIL THEN free[i] := b.next ELSE l.next := b.next END + ELSE b := NIL + END; + RETURN b + END OldBlock; + + PROCEDURE LastBlock (limit: INTEGER): FreeBlock; (* size MOD 16 = 0 *) + VAR b, l: FreeBlock; s, i: INTEGER; + BEGIN + s := limit - 4; + i := 0; + REPEAT + b := free[i]; l := NIL; + WHILE (b # sentinel) & (S.VAL(INTEGER, b) + b.size # s) DO l := b; b := b.next END; + IF b # sentinel THEN + IF l = NIL THEN free[i] := b.next ELSE l.next := b.next END + ELSE b := NIL + END; + INC(i) + UNTIL (b # NIL) OR (i = N); + RETURN b + END LastBlock; + + PROCEDURE NewBlock (size: INTEGER): Block; + VAR tsize, a, s: INTEGER; b: FreeBlock; new, c: Cluster; r: Reducer; + BEGIN + ASSERT(size >= 0, 20); + IF size > MAX(INTEGER) - 19 THEN RETURN NIL END; + tsize := (size + 19) DIV 16 * 16; + b := OldBlock(tsize); (* 1) search for free block *) + IF b = NIL THEN + FastCollect; b := OldBlock(tsize); (* 2) collect *) + IF b = NIL THEN + Collect; b := OldBlock(tsize); (* 2a) fully collect *) + END; + IF b = NIL THEN + AllocHeapMem(tsize + 12, new); (* 3) allocate new cluster *) + IF new # NIL THEN + IF (root = NIL) OR (S.VAL(INTEGER, new) < S.VAL(INTEGER, root)) THEN + new.next := root; root := new + ELSE + c := root; + WHILE (c.next # NIL) & (S.VAL(INTEGER, new) > S.VAL(INTEGER, c.next)) DO c := c.next END; + new.next := c.next; c.next := new + END; + b := S.VAL(FreeBlock, S.VAL(INTEGER, new) + 12); + b.size := (new.size - 12) DIV 16 * 16 - 4 + ELSE + RETURN NIL (* 4) give up *) + END + END + END; + (* b # NIL *) + a := b.size + 4 - tsize; + IF a > 0 THEN Insert(S.VAL(FreeBlock, S.VAL(INTEGER, b) + tsize), a) END; + IF size > 0 THEN Erase(S.ADR(b.size), (size + 3) DIV 4) END; + INC(allocated, tsize); + RETURN S.VAL(Block, b) + END NewBlock; + + PROCEDURE Allocated* (): INTEGER; + BEGIN + RETURN allocated + END Allocated; + + PROCEDURE Used* (): INTEGER; + BEGIN + RETURN used + END Used; + + PROCEDURE Root* (): INTEGER; + BEGIN + RETURN S.VAL(INTEGER, root) + END Root; + + (* -------------------- Trap Handling --------------------- *) + + PROCEDURE Start* (code: Command); + VAR res: setjmp.int; + BEGIN + restart := code; + S.GETREG(SP, baseStack); + res := setjmp.sigsetjmp(startEnv, 1); + restart + END Start; + + PROCEDURE Quit* (exitCode: INTEGER); + VAR m: Module; term: Command; t: BOOLEAN; + BEGIN + trapViewer := NIL; trapChecker := NIL; restart := NIL; + t := terminating; terminating := TRUE; m := modList; + WHILE m # NIL DO (* call terminators *) + IF ~static OR ~t THEN + term := m.term; m.term := NIL; + IF term # NIL THEN term() END + END; + m := m.next + END; + CallFinalizers; + hotFinalizers := finalizers; finalizers := NIL; + CallFinalizers; + stdlib.exit(exitCode) + END Quit; + + PROCEDURE FatalError* (id: INTEGER; str: ARRAY OF CHAR); + VAR res: stdio.int; title: ARRAY 16 OF CHAR; text: ARRAY 256 OF SHORTCHAR; + BEGIN + title := "Error xy"; + title[6] := CHR(id DIV 10 + ORD("0")); + title[7] := CHR(id MOD 10 + ORD("0")); + res := unistd.write(2, S.ADR(title), 8); + stdlib.abort + END FatalError; + + PROCEDURE DefaultTrapViewer; + VAR out: ARRAY 2048 OF SHORTCHAR; a, b, c, len, ref, end: INTEGER; mod: Module; + modName, name: Name; n: Utf8Name; res: unistd.int; + + PROCEDURE WriteString (IN s: ARRAY OF SHORTCHAR); + VAR i: INTEGER; + BEGIN + i := 0; + WHILE (len < LEN(out) - 1) & (s[i] # 0X) DO out[len] := s[i]; INC(i); INC(len) END + END WriteString; + + PROCEDURE WriteHex (x, n: INTEGER); + VAR i, y: INTEGER; + BEGIN + IF len + n < LEN(out) THEN + i := len + n - 1; + WHILE i >= len DO + y := x MOD 16; x := x DIV 16; + IF y > 9 THEN y := y + (ORD("A") - ORD("0") - 10) END; + out[i] := SHORT(CHR(y + ORD("0"))); DEC(i) + END; + INC(len, n) + END + END WriteHex; + + PROCEDURE WriteLn; + BEGIN + IF len < LEN(out) - 1 THEN out[len] := 0AX; INC(len) END + END WriteLn; + + BEGIN + len := 0; + WriteString("====== "); + IF err = 129 THEN WriteString("invalid with") + ELSIF err = 130 THEN WriteString("invalid case") + ELSIF err = 131 THEN WriteString("function without return") + ELSIF err = 132 THEN WriteString("type guard") + ELSIF err = 133 THEN WriteString("implied type guard") + ELSIF err = 134 THEN WriteString("value out of range") + ELSIF err = 135 THEN WriteString("index out of range") + ELSIF err = 136 THEN WriteString("string too long") + ELSIF err = 137 THEN WriteString("stack overflow") + ELSIF err = 138 THEN WriteString("integer overflow") + ELSIF err = 139 THEN WriteString("division by zero") + ELSIF err = 140 THEN WriteString("infinite real result") + ELSIF err = 141 THEN WriteString("real underflow") + ELSIF err = 142 THEN WriteString("real overflow") + ELSIF err = 143 THEN WriteString("undefined real result") + ELSIF err = 144 THEN WriteString("not a number") + ELSIF err = 200 THEN WriteString("keyboard interrupt") + ELSIF err = 201 THEN WriteString("NIL dereference") + ELSIF err = 202 THEN WriteString("illegal instruction: "); + WriteHex(val, 4) + ELSIF err = 203 THEN WriteString("illegal memory read [ad = "); + WriteHex(val, 8); WriteString("]") + ELSIF err = 204 THEN WriteString("illegal memory write [ad = "); + WriteHex(val, 8); WriteString("]") + ELSIF err = 205 THEN WriteString("illegal execution [ad = "); + WriteHex(val, 8); WriteString("]") + ELSIF err = 257 THEN WriteString("out of memory") + ELSIF err = 10001H THEN WriteString("bus error") + ELSIF err = 10002H THEN WriteString("address error") + ELSIF err = 10007H THEN WriteString("fpu error") + ELSIF err < 0 THEN WriteString("exception #"); WriteHex(-err, 2) + ELSE err := err DIV 100 * 256 + err DIV 10 MOD 10 * 16 + err MOD 10; + WriteString("trap #"); WriteHex(err, 3) + END; + WriteString(" ======"); + a := pc; b := fp; c := 12; + REPEAT + WriteLn; WriteString("- "); + mod := modList; + WHILE (mod # NIL) & ((a < mod.code) OR (a >= mod.code + mod.csize)) DO mod := mod.next END; + IF mod # NIL THEN + DEC(a, mod.code); + IF mod.refcnt >= 0 THEN + GetModName(mod, modName); WriteString(SHORT(modName)); ref := mod.refs; + REPEAT GetRefProc(ref, end, n) UNTIL (end = 0) OR (a < end); + IF a < end THEN + Utf8ToString(n, name, res); WriteString("."); WriteString(SHORT(name)) + END + ELSE + GetModName(mod, modName); WriteString("("); WriteString(SHORT(modName)); WriteString(")") + END; + WriteString(" ") + END; + WriteString("(pc="); WriteHex(a, 8); + WriteString(", fp="); WriteHex(b, 8); WriteString(")"); + IF (b >= sp) & (b < stack) THEN + S.GET(b+4, a); (* stacked pc *) + S.GET(b, b); (* dynamic link *) + DEC(c) + ELSE c := 0 + END + UNTIL c = 0; + out[len] := 0X; + res := unistd.write(2, S.ADR(out), len) + END DefaultTrapViewer; + + PROCEDURE TrapCleanup; + VAR t: TrapCleaner; + BEGIN + WHILE trapStack # NIL DO + t := trapStack; trapStack := trapStack.next; t.Cleanup + END; + IF (trapChecker # NIL) & (err # 128) THEN trapChecker END + END TrapCleanup; + + PROCEDURE SetTrapGuard* (on: BOOLEAN); + BEGIN + guarded := on + END SetTrapGuard; + + PROCEDURE Try* (h: TryHandler; a, b, c: INTEGER); + VAR oldIsTry: BOOLEAN; oldTryEnv: setjmp.jmp_buf; res: setjmp.int; + BEGIN + oldIsTry := isTry; oldTryEnv := tryEnv; + isTry := TRUE; + res := setjmp._setjmp(tryEnv); + IF res = 0 THEN h(a, b, c) END; + isTry := oldIsTry; tryEnv := oldTryEnv + END Try; + + PROCEDURE Trap* (n: INTEGER); + BEGIN + IF trapped THEN + DefaultTrapViewer; + IF ~secondTrap THEN trapped := FALSE; secondTrap := TRUE END + END; + IF n >= 0 THEN err := n + ELSE err := -n + 128 + END; + pc := 0; sp := 0; fp := 0; stack := 0; val := 0; + S.GETREG(SP, sp); S.GETREG(FP, fp); + INC(trapCount); + (* !!! InitFPU *) + TrapCleanup; + IF isTry THEN + setjmp._longjmp(tryEnv, 1) + END; + IF err = 128 THEN (* do nothing *) + ELSIF (trapViewer # NIL) & (restart # NIL) & ~trapped & ~guarded THEN + trapped := TRUE; trapViewer() + ELSE DefaultTrapViewer + END; + trapped := FALSE; secondTrap := FALSE; + IF restart # NIL THEN + setjmp.siglongjmp(startEnv, 1) + END; + stdlib.abort + END Trap; + + PROCEDURE [ccall] TrapHandler (signo: signal.int; IN info: signal.siginfo_t; context: ADDRESS); + VAR res: signal.int; uc: signal.Pucontext_t; + BEGIN + IF testRead THEN + setjmp.longjmp(readEnv, 1) + END; + IF trapped THEN + DefaultTrapViewer; + IF ~secondTrap THEN trapped := FALSE; secondTrap := TRUE END + END; + err := -signo; + uc := S.VAL(signal.Pucontext_t, context); + pc := uc.uc_mcontext.gregs[14]; (* %eip *) + sp := uc.uc_mcontext.gregs[7]; (* %esp *) + fp := uc.uc_mcontext.gregs[6]; (* %ebp *) + stack := baseStack; + val := info.info.sigsegv.si_addr; + CASE signo OF + | signal.SIGFPE: + val := info.si_code; + pc := info.info.sigfpe.si_addr; + CASE info.si_code OF + | signal.FPE_INTDIV: err := 139 (* division by zero *) + | signal.FPE_INTOVF: err := 138 (* integer overflow *) + | signal.FPE_FLTDIV: err := 140 (* fpu: division by zero *) + | signal.FPE_FLTOVF: err := 142 (* fpu: overflow *) + | signal.FPE_FLTUND: err := 141 (* fpu: underflow *) + (* !!! | signal.FPE_FLTRES: err := ??? (* fpu: *) *) + | signal.FPE_FLTINV: err := 143 (* val := opcode *) (* fpu: invalid op *) + (* !!! | signal.FPE_FLTSUB: err := ??? (* fpu: *) *) + ELSE (* unknown *) + END + | signal.SIGINT: + val := info.si_code; + err := 200 (* keyboard interrupt *) + | signal.SIGSEGV: + val := info.info.sigsegv.si_addr; + err := 203 (* illigal read *) + | signal.SIGBUS: + val := info.info.sigbus.si_addr; + err := 10001H (* bus error *) + | signal.SIGILL: + pc := info.info.sigill.si_addr; + err := 202; (* illigal instruction *) + IF IsReadable(pc, pc + 4) THEN + S.GET(pc, val); + IF val MOD 100H = 8DH THEN (* lea reg,reg *) + IF val DIV 100H MOD 100H = 0F0H THEN + err := val DIV 10000H MOD 100H (* trap *) + ELSIF val DIV 1000H MOD 10H = 0EH THEN + err := 128 + val DIV 100H MOD 10H (* run time error *) + END + END + END + ELSE (* unknown *) + END; + INC(trapCount); + (* !!! InitFPU *) + TrapCleanup; + IF isTry THEN + setjmp._longjmp(tryEnv, 1) + END; + IF err = 128 THEN (* do nothing *) + ELSIF (trapViewer # NIL) & (restart # NIL) & ~trapped & ~guarded THEN + trapped := TRUE; trapViewer() + ELSE DefaultTrapViewer + END; + trapped := FALSE; secondTrap := FALSE; + IF restart # NIL THEN + setjmp.siglongjmp(startEnv, 1) + END; + stdlib.abort + END TrapHandler; + + (* -------------------- Initialization --------------------- *) + + PROCEDURE InstallTrap (signo: signal.int); + VAR act: signal.struct_sigaction; res: signal.int; + BEGIN + act.handler.sa_handler := NIL; + res := signal.sigemptyset(act.sa_mask); + act.sa_flags := signal.SA_NODEFER + signal.SA_SIGINFO; + act.handler.sa_sigaction := TrapHandler; + res := signal.sigaction(signo, act, NIL); + END InstallTrap; + + PROCEDURE InstallTrapVectors; + BEGIN + InstallTrap(signal.SIGFPE); + InstallTrap(signal.SIGINT); + InstallTrap(signal.SIGSEGV); + InstallTrap(signal.SIGBUS); + InstallTrap(signal.SIGILL) + END InstallTrapVectors; + + PROCEDURE RemoveTrapVectors; + END RemoveTrapVectors; + + PROCEDURE Init; + VAR i: INTEGER; + BEGIN + pagesize := unistd.sysconf(unistd._SC_PAGESIZE); + + (* init heap *) + allocated := 0; total := 0; used := 0; + sentinelBlock.size := MAX(INTEGER); + sentinel := S.ADR(sentinelBlock); + i := N; + REPEAT DEC(i); free[i] := sentinel UNTIL i = 0; + + IF ~inDll THEN + InstallTrapVectors + END; + + (* !!! InitFPU *) + IF ~static THEN + InitModule(modList); + IF ~inDll THEN Quit(1) END + END + END Init; + +BEGIN + IF modList = NIL THEN (* only once *) + S.GETREG(SP, baseStack); + S.GET(baseStack + 16, argc); + argv := S.VAL(ArrStrPtr, baseStack + 20); + S.GETREG(ML, modList); (* linker loads module list to BX *) + static := init IN modList.opts; + inDll := dll IN modList.opts; + Init + END +CLOSE + IF ~terminating THEN + terminating := TRUE; + Quit(0) + END +END Kernel. diff --git a/src/i486/posix/System/Mod/Kernel.cp b/src/i486/posix/System/Mod/Kernel.cp new file mode 100644 index 0000000..083c997 --- /dev/null +++ b/src/i486/posix/System/Mod/Kernel.cp @@ -0,0 +1,1696 @@ +MODULE Kernel; + + IMPORT S := SYSTEM, stdlib := C99stdlib, stdio := C99stdio, + time := C99time, wctype := C99wctype, sysmman := C99sys_mman, + dlfcn := C99dlfcn, types := C99types, fcntl := C99fcntl, + unistd := C99unistd, signal := C99signal, setjmp := C99setjmp; + + (* init fpu? *) + (* add signal blocking to avoid race conditions in Try/Trap/TrapHandler *) + (* add BeepHook for Beep *) + (* implement Call using libffi *) + + CONST + nameLen* = 256; + + littleEndian* = TRUE; + timeResolution* = 1000; (* ticks per second *) + + processor* = 1; (* generic c *) + + objType* = "ocf"; (* file types *) + symType* = "osf"; + docType* = "odc"; + + (* loader constants *) + done* = 0; + fileNotFound* = 1; + syntaxError* = 2; + objNotFound* = 3; + illegalFPrint* = 4; + cyclicImport* = 5; + noMem* = 6; + commNotFound* = 7; + commSyntaxError* = 8; + moduleNotFound* = 9; + + any = 1000000; + + CX = 1; + SP = 4; (* register number of stack pointer *) + FP = 5; (* register number of frame pointer *) + ML = 3; (* register which holds the module list at program start *) + + strictStackSweep = FALSE; + N = 128 DIV 16; (* free lists *) + + (* kernel flags in module desc *) + init = 16; dyn = 17; dll = 24; iptrs = 30; + + (* meta interface consts *) + mConst = 1; mTyp = 2; mVar = 3; mProc = 4; mField = 5; + + TYPE + Name* = ARRAY nameLen OF CHAR; + Utf8Name* = ARRAY nameLen OF SHORTCHAR; + Command* = PROCEDURE; + + Module* = POINTER TO RECORD [untagged] + next-: Module; + opts-: SET; (* 0..15: compiler opts, 16..31: kernel flags *) + refcnt-: INTEGER; (* <0: module invalidated *) + compTime-, loadTime-: ARRAY 6 OF SHORTINT; + ext-: INTEGER; (* currently not used *) + term-: Command; (* terminator *) + nofimps-, nofptrs-: INTEGER; + csize-, dsize-, rsize-: INTEGER; + code-, data-, refs-: INTEGER; + procBase-, varBase-: INTEGER; (* meta base addresses *) + names-: POINTER TO ARRAY [untagged] OF SHORTCHAR; (* names[0] = 0X *) + ptrs-: POINTER TO ARRAY [untagged] OF INTEGER; + imports-: POINTER TO ARRAY [untagged] OF Module; + export-: Directory; (* exported objects (name sorted) *) + name-: Utf8Name + END; + + Type* = POINTER TO RECORD [untagged] + (* record: ptr to method n at offset - 4 * (n+1) *) + size-: INTEGER; (* record: size, array: #elem, dyn array: 0, proc: sigfp *) + mod-: Module; + id-: INTEGER; (* name idx * 256 + lev * 16 + attr * 4 + form *) + base-: ARRAY 16 OF Type; (* signature if form = ProcTyp *) + fields-: Directory; (* new fields (declaration order) *) + ptroffs-: ARRAY any OF INTEGER (* array of any length *) + END; + + Object* = POINTER TO ObjDesc; + + ObjDesc* = RECORD [untagged] + fprint-: INTEGER; + offs-: INTEGER; (* pvfprint for record types *) + id-: INTEGER; (* name idx * 256 + vis * 16 + mode *) + struct-: Type (* id of basic type or pointer to typedesc/signature *) + END; + + Directory* = POINTER TO RECORD [untagged] + num-: INTEGER; (* number of entries *) + obj-: ARRAY any OF ObjDesc (* array of any length *) + END; + + Signature* = POINTER TO RECORD [untagged] + retStruct-: Type; (* id of basic type or pointer to typedesc or 0 *) + num-: INTEGER; (* number of parameters *) + par-: ARRAY any OF RECORD [untagged] (* parameters *) + id-: INTEGER; (* name idx * 256 + kind *) + struct-: Type (* id of basic type or pointer to typedesc *) + END + END; + + Handler* = PROCEDURE; + + Reducer* = POINTER TO ABSTRACT RECORD + next: Reducer + END; + + Identifier* = ABSTRACT RECORD + typ*: INTEGER; + obj-: ANYPTR + END; + + TrapCleaner* = POINTER TO ABSTRACT RECORD + next: TrapCleaner + END; + + TryHandler* = PROCEDURE (a, b, c: INTEGER); + + (* meta extension suport *) + + ItemExt* = POINTER TO ABSTRACT RECORD END; + + ItemAttr* = RECORD + obj*, vis*, typ*, adr*: INTEGER; + mod*: Module; + desc*: Type; + ptr*: S.PTR; + ext*: ItemExt + END; + + Hook* = POINTER TO ABSTRACT RECORD END; + + LoaderHook* = POINTER TO ABSTRACT RECORD (Hook) + res*: INTEGER; + importing*, imported*, object*: ARRAY 256 OF CHAR + END; + + Block = POINTER TO RECORD [untagged] + tag: Type; + last: INTEGER; (* arrays: last element *) + actual: INTEGER; (* arrays: used during mark phase *) + first: INTEGER (* arrays: first element *) + END; + + FreeBlock = POINTER TO FreeDesc; + + FreeDesc = RECORD [untagged] + tag: Type; (* f.tag = ADR(f.size) *) + size: INTEGER; + next: FreeBlock + END; + + Cluster = POINTER TO RECORD [untagged] + size: INTEGER; (* total size *) + next: Cluster; + max: INTEGER (* exe: reserved size, dll: original address *) + (* start of first block *) + END; + + FList = POINTER TO RECORD + next: FList; + blk: Block; + iptr, aiptr: BOOLEAN + END; + + CList = POINTER TO RECORD + next: CList; + do: Command; + trapped: BOOLEAN + END; + + + PtrType = RECORD v: S.PTR END; (* used for array of pointer *) + Char8Type = RECORD v: SHORTCHAR END; + Char16Type = RECORD v: CHAR END; + Int8Type = RECORD v: BYTE END; + Int16Type = RECORD v: SHORTINT END; + Int32Type = RECORD v: INTEGER END; + Int64Type = RECORD v: LONGINT END; + BoolType = RECORD v: BOOLEAN END; + SetType = RECORD v: SET END; + Real32Type = RECORD v: SHORTREAL END; + Real64Type = RECORD v: REAL END; + ProcType = RECORD v: PROCEDURE END; + UPtrType = RECORD v: INTEGER END; + StrPtr = POINTER TO ARRAY [untagged] OF SHORTCHAR; + + ArrStrPtr = POINTER TO ARRAY [untagged] OF StrPtr; + + ADDRESS* = types.Pvoid; + + VAR + baseStack: INTEGER; + root: Cluster; + modList-: Module; + trapCount-: INTEGER; + err-, pc-, sp-, fp-, stack-, val-: INTEGER; + + isTry: BOOLEAN; + startEnv: setjmp.sigjmp_buf; + tryEnv: setjmp.jmp_buf; + + argc-: INTEGER; + argv-: ArrStrPtr; + pagesize: unistd.long; + + free: ARRAY N OF FreeBlock; (* free list *) + sentinelBlock: FreeDesc; + sentinel: FreeBlock; + candidates: ARRAY 1024 OF INTEGER; + nofcand: INTEGER; + allocated: INTEGER; (* bytes allocated on BlackBox heap *) + total: INTEGER; (* current total size of BlackBox heap *) + used: INTEGER; (* bytes allocated on system heap *) + finalizers: FList; + hotFinalizers: FList; + cleaners: CList; + reducers: Reducer; + trapStack: TrapCleaner; + actual: Module; (* valid during module initialization *) + + trapViewer, trapChecker: Handler; + trapped, guarded, secondTrap: BOOLEAN; + interrupted: BOOLEAN; + static, inDll, terminating: BOOLEAN; + restart: Command; + + loader: LoaderHook; + loadres: INTEGER; + + wouldFinalize: BOOLEAN; + + watcher*: PROCEDURE (event: INTEGER); (* for debugging *) + + PROCEDURE Erase (adr, words: INTEGER); + BEGIN + ASSERT(words >= 0, 20); + WHILE words > 0 DO + S.PUT(adr, 0); + INC(adr, 4); + DEC(words) + END + END Erase; + + + PROCEDURE (VAR id: Identifier) Identified* (): BOOLEAN, NEW, ABSTRACT; + PROCEDURE (r: Reducer) Reduce* (full: BOOLEAN), NEW, ABSTRACT; + PROCEDURE (c: TrapCleaner) Cleanup*, NEW, EMPTY; + + (* meta extension suport *) + + PROCEDURE (e: ItemExt) Lookup* (name: ARRAY OF CHAR; VAR i: ANYREC), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) Index* (index: INTEGER; VAR elem: ANYREC), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) Deref* (VAR ref: ANYREC), NEW, ABSTRACT; + + PROCEDURE (e: ItemExt) Valid* (): BOOLEAN, NEW, ABSTRACT; + PROCEDURE (e: ItemExt) Size* (): INTEGER, NEW, ABSTRACT; + PROCEDURE (e: ItemExt) BaseTyp* (): INTEGER, NEW, ABSTRACT; + PROCEDURE (e: ItemExt) Len* (): INTEGER, NEW, ABSTRACT; + + PROCEDURE (e: ItemExt) Call* (OUT ok: BOOLEAN), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) BoolVal* (): BOOLEAN, NEW, ABSTRACT; + PROCEDURE (e: ItemExt) PutBoolVal* (x: BOOLEAN), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) CharVal* (): CHAR, NEW, ABSTRACT; + PROCEDURE (e: ItemExt) PutCharVal* (x: CHAR), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) IntVal* (): INTEGER, NEW, ABSTRACT; + PROCEDURE (e: ItemExt) PutIntVal* (x: INTEGER), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) LongVal* (): LONGINT, NEW, ABSTRACT; + PROCEDURE (e: ItemExt) PutLongVal* (x: LONGINT), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) RealVal* (): REAL, NEW, ABSTRACT; + PROCEDURE (e: ItemExt) PutRealVal* (x: REAL), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) SetVal* (): SET, NEW, ABSTRACT; + PROCEDURE (e: ItemExt) PutSetVal* (x: SET), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) PtrVal* (): ANYPTR, NEW, ABSTRACT; + PROCEDURE (e: ItemExt) PutPtrVal* (x: ANYPTR), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) GetSStringVal* (OUT x: ARRAY OF SHORTCHAR; + OUT ok: BOOLEAN), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) PutSStringVal* (IN x: ARRAY OF SHORTCHAR; + OUT ok: BOOLEAN), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) GetStringVal* (OUT x: ARRAY OF CHAR; OUT ok: BOOLEAN), NEW, ABSTRACT; + PROCEDURE (e: ItemExt) PutStringVal* (IN x: ARRAY OF CHAR; OUT ok: BOOLEAN), NEW, ABSTRACT; + + (* -------------------- miscellaneous tools -------------------- *) + + PROCEDURE IsUpper* (ch: CHAR): BOOLEAN; + BEGIN + RETURN wctype.iswupper(ORD(ch)) # 0 + END IsUpper; + + PROCEDURE Upper* (ch: CHAR): CHAR; + BEGIN + RETURN CHR(wctype.towupper(ORD(ch))) + END Upper; + + PROCEDURE IsLower* (ch: CHAR): BOOLEAN; + BEGIN + RETURN wctype.iswlower(ORD(ch)) # 0 + END IsLower; + + PROCEDURE Lower* (ch: CHAR): CHAR; + BEGIN + RETURN CHR(wctype.towlower(ORD(ch))) + END Lower; + + PROCEDURE IsAlpha* (ch: CHAR): BOOLEAN; + BEGIN + RETURN wctype.iswalpha(ORD(ch)) # 0 + END IsAlpha; + + PROCEDURE Utf8ToString* (IN in: ARRAY OF SHORTCHAR; OUT out: ARRAY OF CHAR; OUT res: INTEGER); + VAR i, j, val, max: INTEGER; ch: SHORTCHAR; + + PROCEDURE FormatError(); + BEGIN out := in$; res := 2 (*format error*) + END FormatError; + + BEGIN + ch := in[0]; i := 1; j := 0; max := LEN(out) - 1; + WHILE (ch # 0X) & (j < max) DO + IF ch < 80X THEN + out[j] := ch; INC(j) + ELSIF ch < 0E0X THEN + val := ORD(ch) - 192; + IF val < 0 THEN FormatError; RETURN END ; + ch := in[i]; INC(i); val := val * 64 + ORD(ch) - 128; + IF (ch < 80X) OR (ch >= 0E0X) THEN FormatError; RETURN END ; + out[j] := CHR(val); INC(j) + ELSIF ch < 0F0X THEN + val := ORD(ch) - 224; + ch := in[i]; INC(i); val := val * 64 + ORD(ch) - 128; + IF (ch < 80X) OR (ch >= 0E0X) THEN FormatError; RETURN END ; + ch := in[i]; INC(i); val := val * 64 + ORD(ch) - 128; + IF (ch < 80X) OR (ch >= 0E0X) THEN FormatError; RETURN END ; + out[j] := CHR(val); INC(j) + ELSE + FormatError; RETURN + END ; + ch := in[i]; INC(i) + END; + out[j] := 0X; + IF ch = 0X THEN res := 0 (*ok*) ELSE res := 1 (*truncated*) END + END Utf8ToString; + + PROCEDURE StringToUtf8* (IN in: ARRAY OF CHAR; OUT out: ARRAY OF SHORTCHAR; OUT res: INTEGER); + VAR i, j, val, max: INTEGER; + BEGIN + i := 0; j := 0; max := LEN(out) - 3; + WHILE (in[i] # 0X) & (j < max) DO + val := ORD(in[i]); INC(i); + IF val < 128 THEN + out[j] := SHORT(CHR(val)); INC(j) + ELSIF val < 2048 THEN + out[j] := SHORT(CHR(val DIV 64 + 192)); INC(j); + out[j] := SHORT(CHR(val MOD 64 + 128)); INC(j) + ELSE + out[j] := SHORT(CHR(val DIV 4096 + 224)); INC(j); + out[j] := SHORT(CHR(val DIV 64 MOD 64 + 128)); INC(j); + out[j] := SHORT(CHR(val MOD 64 + 128)); INC(j) + END; + END; + out[j] := 0X; + IF in[i] = 0X THEN res := 0 (*ok*) ELSE res := 1 (*truncated*) END + END StringToUtf8; + + PROCEDURE SplitName* (name: ARRAY OF CHAR; VAR head, tail: ARRAY OF CHAR); + (* portable *) + VAR i, j: INTEGER; ch, lch: CHAR; + BEGIN + i := 0; ch := name[0]; + IF ch # 0X THEN + REPEAT + head[i] := ch; lch := ch; INC(i); ch := name[i] + UNTIL (ch = 0X) OR (ch = ".") OR IsUpper(ch) & ~IsUpper(lch); + IF ch = "." THEN i := 0; ch := name[0] END; + head[i] := 0X; j := 0; + WHILE ch # 0X DO tail[j] := ch; INC(i); INC(j); ch := name[i] END; + tail[j] := 0X; + IF tail = "" THEN tail := head$; head := "" END + ELSE head := ""; tail := "" + END + END SplitName; + + PROCEDURE MakeFileName* (VAR name: ARRAY OF CHAR; type: ARRAY OF CHAR); + VAR i, j: INTEGER; ext: ARRAY 8 OF CHAR; ch: CHAR; + BEGIN + i := 0; + WHILE (name[i] # 0X) & (name[i] # ".") DO INC(i) END; + IF name[i] = "." THEN + IF name[i + 1] = 0X THEN name[i] := 0X END + ELSE + IF type = "" THEN ext := docType ELSE ext := type$ END; + IF i < LEN(name) - LEN(ext$) - 1 THEN + name[i] := "."; INC(i); j := 0; ch := ext[0]; + WHILE ch # 0X DO + name[i] := Lower(ch); INC(i); INC(j); ch := ext[j] + END; + name[i] := 0X + END + END + END MakeFileName; + + PROCEDURE Time* (): LONGINT; + VAR res: time.int; tp: time.struct_timespec; + BEGIN + ASSERT(timeResolution >= 1); + ASSERT(timeResolution <= 1000000000); + res := time.clock_gettime(time.CLOCK_MONOTONIC, tp); + ASSERT(res = 0, 100); + RETURN tp.tv_sec * LONG(timeResolution) + tp.tv_nsec DIV LONG(1000000000 DIV timeResolution) + END Time; + + PROCEDURE Beep*; + (* !!! *) + END Beep; + + PROCEDURE SearchProcVar* (var: INTEGER; VAR m: Module; VAR adr: INTEGER); + BEGIN + adr := var; m := NIL; + IF var # 0 THEN + m := modList; + WHILE (m # NIL) & ((var < m.code) OR (var >= m.code + m.csize)) DO m := m.next END; + IF m # NIL THEN DEC(adr, m.code) END + END + END SearchProcVar; + + (* -------------------- system memory management --------------------- *) + + PROCEDURE AllocMem (size: sysmman.size_t; VAR max: sysmman.size_t): ADDRESS; + VAR fd, flags, res: fcntl.int; ptr: ADDRESS; + BEGIN + max := (size + pagesize - 1) DIV pagesize * pagesize; + fd := fcntl.open("/dev/zero", fcntl.O_RDWR, 0); + IF fd # -1 THEN + flags := sysmman.PROT_READ + sysmman.PROT_WRITE; + ptr := sysmman.mmap(0, max, flags, sysmman.MAP_PRIVATE, fd, 0); + IF ptr = sysmman.MAP_FAILED THEN ptr := 0 END; + res := unistd.close(fd); + ASSERT(res = 0, 100) + ELSE + ptr := 0 + END; + RETURN ptr + END AllocMem; + + PROCEDURE FreeMem (adr: ADDRESS; size: sysmman.size_t); + VAR res: types.int; + BEGIN + size := (size + pagesize - 1) DIV pagesize * pagesize; + res := sysmman.munmap(adr, size); + ASSERT(res = 0, 100) + END FreeMem; + + PROCEDURE AllocHeapMem (size: INTEGER; VAR c: Cluster); + CONST N = 65536; (* cluster size for dll *) + VAR adr, allocated: INTEGER; + BEGIN + INC(size, 16); + ASSERT(size > 0, 100); adr := 0; + IF size < N THEN adr := stdlib.malloc(N) END; + IF adr = 0 THEN adr := stdlib.malloc(size); allocated := size ELSE allocated := N END; + IF adr = 0 THEN c := NIL + ELSE + c := S.VAL(Cluster, (adr + 15) DIV 16 * 16); c.max := adr; + c.size := allocated - (S.VAL(INTEGER, c) - adr); + INC(used, c.size); INC(total, c.size) + END; + ASSERT((adr = 0) OR (adr MOD 16 = 0) & (c.size >= size), 101); + (* post: (c = NIL) OR (c MOD 16 = 0) & (c.size >= size) *) + END AllocHeapMem; + + PROCEDURE FreeHeapMem (c: Cluster); + BEGIN + DEC(used, c.size); DEC(total, c.size); + stdlib.free(S.VAL(ADDRESS, c.max)) + END FreeHeapMem; + + PROCEDURE HeapFull (size: INTEGER): BOOLEAN; + BEGIN + RETURN TRUE + END HeapFull; + + PROCEDURE AllocModMem* (descSize, modSize: INTEGER; VAR descAdr, modAdr: INTEGER); + BEGIN + descAdr := 0; modAdr := 0; + descAdr := AllocMem(descSize, descSize); + IF descAdr # 0 THEN + modAdr := AllocMem(modSize, modSize); + IF modAdr = 0 THEN + FreeMem(descAdr, descSize) + ELSE + INC(used, descSize + modSize) + END + END + END AllocModMem; + + PROCEDURE DeallocModMem* (descSize, modSize, descAdr, modAdr: INTEGER); + BEGIN + FreeMem(descAdr, descSize); + FreeMem(modAdr, modSize); + DEC(used, descSize + modSize) + END DeallocModMem; + + PROCEDURE InvalModMem (modSize, modAdr: INTEGER); + BEGIN + FreeMem(modAdr, modSize) + END InvalModMem; + + PROCEDURE TryRead (from, to, c: INTEGER); + VAR i: INTEGER; x: BYTE; + BEGIN + IF from <= to THEN + FOR i := from TO to DO + S.GET(i, x) + END + ELSE + FOR i := to TO from BY -1 DO + S.GET(i, x) + END + END; + END TryRead; + + PROCEDURE^ Try* (h: TryHandler; a, b, c: INTEGER); + + PROCEDURE IsReadable* (from, to: INTEGER): BOOLEAN; + VAR i: INTEGER; + BEGIN + i := trapCount; + Try(TryRead, from, to, 0); + RETURN trapCount = i + END IsReadable; + + (* --------------------- NEW implementation (portable) -------------------- *) + + PROCEDURE^ NewBlock (size: INTEGER): Block; + + PROCEDURE NewRec* (typ: INTEGER): INTEGER; (* implementation of NEW(ptr) *) + VAR size, adr: INTEGER; b: Block; tag: Type; l: FList; + BEGIN + IF ~ODD(typ) THEN + tag := S.VAL(Type, typ); + b := NewBlock(tag.size); + IF b # NIL THEN + b.tag := tag; + S.GET(typ - 4, size); + IF size # 0 THEN (* record uses a finalizer *) + l := S.VAL(FList, S.ADR(b.last)); (* anchor new object! *) + l := S.VAL(FList, NewRec(S.TYP(FList))); (* NEW(l) *) + l.blk := b; l.next := finalizers; finalizers := l + END; + adr := S.ADR(b.last) + ELSE + adr := 0 + END + ELSE + HALT(100) (* COM interface pointers not supported *) + END; + RETURN adr + END NewRec; + + PROCEDURE NewArr* (eltyp, nofelem, nofdim: INTEGER): INTEGER; (* impl. of NEW(ptr, dim0, dim1, ...) *) + VAR b: Block; size, headSize: INTEGER; t: Type; + BEGIN + CASE eltyp OF + | -1: HALT(100) (* COM interface pointers not supported *) + | 0: eltyp := S.ADR(PtrType) + | 1: eltyp := S.ADR(Char8Type) + | 2: eltyp := S.ADR(Int16Type) + | 3: eltyp := S.ADR(Int8Type) + | 4: eltyp := S.ADR(Int32Type) + | 5: eltyp := S.ADR(BoolType) + | 6: eltyp := S.ADR(SetType) + | 7: eltyp := S.ADR(Real32Type) + | 8: eltyp := S.ADR(Real64Type) + | 9: eltyp := S.ADR(Char16Type) + | 10: eltyp := S.ADR(Int64Type) + | 11: eltyp := S.ADR(ProcType) + | 12: HALT(101) (* COM interface pointers not supported *) + ELSE + ASSERT(~ODD(eltyp), 102) (* COM interface pointers not supported *) + END; + t := S.VAL(Type, eltyp); + headSize := 4 * nofdim + 12; + size := headSize + nofelem * t.size; + b := NewBlock(size); + IF b # NIL THEN + b.tag := S.VAL(Type, eltyp + 2); (* tag + array mark *) + b.last := S.ADR(b.last) + size - t.size; (* pointer to last elem *) + b.first := S.ADR(b.last) + headSize; (* pointer to first elem *) + RETURN S.ADR(b.last) + ELSE + RETURN 0 + END; + END NewArr; + + (* -------------------- handler installation (portable) --------------------- *) + + PROCEDURE ThisFinObj* (VAR id: Identifier): ANYPTR; + VAR l: FList; + BEGIN + ASSERT(id.typ # 0, 100); + l := finalizers; + WHILE l # NIL DO + IF S.VAL(INTEGER, l.blk.tag) = id.typ THEN + id.obj := S.VAL(ANYPTR, S.ADR(l.blk.last)); + IF id.Identified() THEN RETURN id.obj END + END; + l := l.next + END; + RETURN NIL + END ThisFinObj; + + PROCEDURE InstallReducer* (r: Reducer); + BEGIN + r.next := reducers; reducers := r + END InstallReducer; + + PROCEDURE InstallTrapViewer* (h: Handler); + BEGIN + trapViewer := h + END InstallTrapViewer; + + PROCEDURE InstallTrapChecker* (h: Handler); + BEGIN + trapChecker := h + END InstallTrapChecker; + + PROCEDURE PushTrapCleaner* (c: TrapCleaner); + VAR t: TrapCleaner; + BEGIN + t := trapStack; WHILE (t # NIL) & (t # c) DO t := t.next END; + ASSERT(t = NIL, 20); + c.next := trapStack; trapStack := c + END PushTrapCleaner; + + PROCEDURE PopTrapCleaner* (c: TrapCleaner); + VAR t: TrapCleaner; + BEGIN + t := NIL; + WHILE (trapStack # NIL) & (t # c) DO + t := trapStack; trapStack := trapStack.next + END + END PopTrapCleaner; + + PROCEDURE InstallCleaner* (p: Command); + VAR c: CList; + BEGIN + c := S.VAL(CList, NewRec(S.TYP(CList))); (* NEW(c) *) + c.do := p; c.trapped := FALSE; c.next := cleaners; cleaners := c + END InstallCleaner; + + PROCEDURE RemoveCleaner* (p: Command); + VAR c0, c: CList; + BEGIN + c := cleaners; c0 := NIL; + WHILE (c # NIL) & (c.do # p) DO c0 := c; c := c.next END; + IF c # NIL THEN + IF c0 = NIL THEN cleaners := cleaners.next ELSE c0.next := c.next END + END + END RemoveCleaner; + + PROCEDURE Cleanup*; + VAR c, c0: CList; + BEGIN + c := cleaners; c0 := NIL; + WHILE c # NIL DO + IF ~c.trapped THEN + c.trapped := TRUE; c.do; c.trapped := FALSE; c0 := c + ELSE + IF c0 = NIL THEN cleaners := cleaners.next + ELSE c0.next := c.next + END + END; + c := c.next + END + END Cleanup; + + (* -------------------- meta information (portable) --------------------- *) + + PROCEDURE (h: LoaderHook) ThisMod* (IN name: ARRAY OF CHAR): Module, NEW, ABSTRACT; + + PROCEDURE SetLoaderHook*(h: LoaderHook); + BEGIN + loader := h + END SetLoaderHook; + + PROCEDURE InitModule (mod: Module); (* initialize linked modules *) + VAR body: Command; + BEGIN + IF ~(dyn IN mod.opts) & (mod.next # NIL) & ~(init IN mod.next.opts) THEN InitModule(mod.next) END; + IF ~(init IN mod.opts) THEN + body := S.VAL(Command, mod.code); + INCL(mod.opts, init); + actual := mod; + body(); actual := NIL + END + END InitModule; + + PROCEDURE ThisLoadedMod* (IN name: ARRAY OF CHAR): Module; (* loaded modules only *) + VAR m: Module; res: INTEGER; n: Utf8Name; + BEGIN + StringToUtf8(name, n, res); ASSERT(res = 0); + loadres := done; + m := modList; + WHILE (m # NIL) & ((m.name # n) OR (m.refcnt < 0)) DO m := m.next END; + IF (m # NIL) & ~(init IN m.opts) THEN InitModule(m) END; + IF m = NIL THEN loadres := moduleNotFound END; + RETURN m + END ThisLoadedMod; + + PROCEDURE ThisMod* (IN name: ARRAY OF CHAR): Module; + BEGIN + IF loader # NIL THEN + loader.res := done; + RETURN loader.ThisMod(name) + ELSE + RETURN ThisLoadedMod(name) + END + END ThisMod; + + PROCEDURE LoadMod* (IN name: ARRAY OF CHAR); + VAR m: Module; + BEGIN + m := ThisMod(name) + END LoadMod; + + PROCEDURE GetLoaderResult* (OUT res: INTEGER; OUT importing, imported, object: ARRAY OF CHAR); + BEGIN + IF loader # NIL THEN + res := loader.res; + importing := loader.importing$; + imported := loader.imported$; + object := loader.object$ + ELSE + res := loadres; + importing := ""; + imported := ""; + object := "" + END + END GetLoaderResult; + + PROCEDURE ThisObject* (mod: Module; IN name: ARRAY OF CHAR): Object; + VAR l, r, m, res: INTEGER; p: StrPtr; n: Utf8Name; + BEGIN + StringToUtf8(name, n, res); ASSERT(res = 0); + l := 0; r := mod.export.num; + WHILE l < r DO (* binary search *) + m := (l + r) DIV 2; + p := S.VAL(StrPtr, S.ADR(mod.names[mod.export.obj[m].id DIV 256])); + IF p^ = n THEN RETURN S.VAL(Object, S.ADR(mod.export.obj[m])) END; + IF p^ < n THEN l := m + 1 ELSE r := m END + END; + RETURN NIL + END ThisObject; + + PROCEDURE ThisDesc* (mod: Module; fprint: INTEGER): Object; + VAR i, n: INTEGER; + BEGIN + i := 0; n := mod.export.num; + WHILE (i < n) & (mod.export.obj[i].id DIV 256 = 0) DO + IF mod.export.obj[i].offs = fprint THEN RETURN S.VAL(Object, S.ADR(mod.export.obj[i])) END; + INC(i) + END; + RETURN NIL + END ThisDesc; + + PROCEDURE ThisField* (rec: Type; IN name: ARRAY OF CHAR): Object; + VAR n, res: INTEGER; p: StrPtr; obj: Object; m: Module; nn: Utf8Name; + BEGIN + StringToUtf8(name, nn, res); ASSERT(res = 0); + m := rec.mod; + obj := S.VAL(Object, S.ADR(rec.fields.obj[0])); n := rec.fields.num; + WHILE n > 0 DO + p := S.VAL(StrPtr, S.ADR(m.names[obj.id DIV 256])); + IF p^ = nn THEN RETURN obj END; + DEC(n); INC(S.VAL(INTEGER, obj), 16) + END; + RETURN NIL + END ThisField; + + PROCEDURE ThisCommand* (mod: Module; IN name: ARRAY OF CHAR): Command; + VAR x: Object; sig: Signature; + BEGIN + x := ThisObject(mod, name); + IF (x # NIL) & (x.id MOD 16 = mProc) THEN + sig := S.VAL(Signature, x.struct); + IF (sig.retStruct = NIL) & (sig.num = 0) THEN RETURN S.VAL(Command, mod.procBase + x.offs) END + END; + RETURN NIL + END ThisCommand; + + PROCEDURE ThisType* (mod: Module; IN name: ARRAY OF CHAR): Type; + VAR x: Object; + BEGIN + x := ThisObject(mod, name); + IF (x # NIL) & (x.id MOD 16 = mTyp) & (S.VAL(INTEGER, x.struct) DIV 256 # 0) THEN + RETURN x.struct + ELSE + RETURN NIL + END + END ThisType; + + PROCEDURE TypeOf* (IN rec: ANYREC): Type; + BEGIN + RETURN S.VAL(Type, S.TYP(rec)) + END TypeOf; + + PROCEDURE LevelOf* (t: Type): SHORTINT; + BEGIN + RETURN SHORT(t.id DIV 16 MOD 16) + END LevelOf; + + PROCEDURE NewObj* (VAR o: S.PTR; t: Type); + VAR i: INTEGER; + BEGIN + IF t.size = -1 THEN o := NIL + ELSE + i := 0; WHILE t.ptroffs[i] >= 0 DO INC(i) END; + IF t.ptroffs[i+1] >= 0 THEN INC(S.VAL(INTEGER, t)) END; (* with interface pointers *) + o := S.VAL(S.PTR, NewRec(S.VAL(INTEGER, t))) (* generic NEW *) + END + END NewObj; + + PROCEDURE GetModName* (mod: Module; OUT name: Name); + VAR res: INTEGER; + BEGIN + Utf8ToString(mod.name, name, res); ASSERT(res = 0) + END GetModName; + + PROCEDURE GetObjName* (mod: Module; obj: Object; OUT name: Name); + VAR p: StrPtr; res: INTEGER; + BEGIN + p := S.VAL(StrPtr, S.ADR(mod.names[obj.id DIV 256])); + Utf8ToString(p^$, name, res); ASSERT(res = 0) + END GetObjName; + + PROCEDURE GetTypeName* (t: Type; OUT name: Name); + VAR p: StrPtr; res: INTEGER; + BEGIN + p := S.VAL(StrPtr, S.ADR(t.mod.names[t.id DIV 256])); + Utf8ToString(p^$, name, res); ASSERT(res = 0) + END GetTypeName; + + PROCEDURE RegisterMod* (mod: Module); + VAR i: INTEGER; epoch: time.time_t; tm: time.struct_tm; ptm: time.Pstruct_tm; + BEGIN + mod.next := modList; modList := mod; mod.refcnt := 0; INCL(mod.opts, dyn); i := 0; + WHILE i < mod.nofimps DO + IF mod.imports[i] # NIL THEN INC(mod.imports[i].refcnt) END; + INC(i) + END; + epoch := time.time(NIL); + ptm := time.localtime_r(epoch, tm); + IF ptm # NIL THEN + mod.loadTime[0] := SHORT(tm.tm_year + 1900); + mod.loadTime[1] := SHORT(tm.tm_mon + 1); + mod.loadTime[2] := SHORT(tm.tm_mday); + mod.loadTime[3] := SHORT(tm.tm_hour); + mod.loadTime[4] := SHORT(tm.tm_min); + mod.loadTime[5] := SHORT(tm.tm_sec) + ELSE + mod.loadTime[0] := 0; + mod.loadTime[1] := 0; + mod.loadTime[2] := 0; + mod.loadTime[3] := 0; + mod.loadTime[4] := 0; + mod.loadTime[5] := 0 + END; + IF ~(init IN mod.opts) THEN InitModule(mod) END + END RegisterMod; + + PROCEDURE^ Collect*; + + PROCEDURE UnloadMod* (mod: Module); + VAR i: INTEGER; t: Command; + BEGIN + IF mod.refcnt = 0 THEN + t := mod.term; mod.term := NIL; + IF t # NIL THEN t() END; (* terminate module *) + i := 0; + WHILE i < mod.nofptrs DO (* release global pointers *) + S.PUT(mod.varBase + mod.ptrs[i], 0); INC(i) + END; + Collect; (* call finalizers *) + i := 0; + WHILE i < mod.nofimps DO (* release imported modules *) + IF mod.imports[i] # NIL THEN DEC(mod.imports[i].refcnt) END; + INC(i) + END; + mod.refcnt := -1; + IF dyn IN mod.opts THEN (* release memory *) + InvalModMem(mod.data + mod.dsize - mod.refs, mod.refs) + END + END + END UnloadMod; + + (* -------------------- dynamic procedure call --------------------- *) + + PROCEDURE Call* (adr: INTEGER; sig: Signature; IN par: ARRAY OF INTEGER; n: INTEGER): LONGINT; + BEGIN + HALT(126); (* !!! *) + RETURN 0 + END Call; + + (* -------------------- reference information (portable) --------------------- *) + + PROCEDURE RefCh (VAR ref: INTEGER; OUT ch: SHORTCHAR); + BEGIN + S.GET(ref, ch); INC(ref) + END RefCh; + + PROCEDURE RefNum (VAR ref: INTEGER; OUT x: INTEGER); + VAR s, n: INTEGER; ch: SHORTCHAR; + BEGIN + s := 0; n := 0; RefCh(ref, ch); + WHILE ORD(ch) >= 128 DO INC(n, ASH(ORD(ch) - 128, s) ); INC(s, 7); RefCh(ref, ch) END; + x := n + ASH(ORD(ch) MOD 64 - ORD(ch) DIV 64 * 64, s) + END RefNum; + + PROCEDURE RefName (VAR ref: INTEGER; OUT n: Utf8Name); + VAR i: INTEGER; ch: SHORTCHAR; + BEGIN + i := 0; RefCh(ref, ch); + WHILE ch # 0X DO n[i] := ch; INC(i); RefCh(ref, ch) END; + n[i] := 0X + END RefName; + + PROCEDURE GetRefProc* (VAR ref: INTEGER; OUT adr: INTEGER; OUT name: Utf8Name); + VAR ch: SHORTCHAR; + BEGIN + S.GET(ref, ch); + WHILE ch >= 0FDX DO (* skip variables *) + INC(ref); RefCh(ref, ch); + IF ch = 10X THEN INC(ref, 4) END; + RefNum(ref, adr); RefName(ref, name); S.GET(ref, ch) + END; + WHILE (ch > 0X) & (ch < 0FCX) DO (* skip source refs *) + INC(ref); RefNum(ref, adr); S.GET(ref, ch) + END; + IF ch = 0FCX THEN INC(ref); RefNum(ref, adr); RefName(ref, name) + ELSE adr := 0 + END + END GetRefProc; + + PROCEDURE GetRefVar* (VAR ref: INTEGER; OUT mode, form: SHORTCHAR; OUT desc: Type; OUT adr: INTEGER; OUT name: Utf8Name); + BEGIN + S.GET(ref, mode); desc := NIL; + IF mode >= 0FDX THEN + mode := SHORT(CHR(ORD(mode) - 0FCH)); + INC(ref); RefCh(ref, form); + IF form = 10X THEN + S.GET(ref, desc); INC(ref, 4); form := SHORT(CHR(16 + desc.id MOD 4)) + END; + RefNum(ref, adr); RefName(ref, name) + ELSE + mode := 0X; form := 0X; adr := 0 + END + END GetRefVar; + + PROCEDURE SourcePos* (mod: Module; codePos: INTEGER): INTEGER; + VAR ref, pos, ad, d: INTEGER; ch: SHORTCHAR; name: Utf8Name; + BEGIN + IF mod # NIL THEN (* mf, 12.02.04 *) + ref := mod.refs; pos := 0; ad := 0; S.GET(ref, ch); + WHILE ch # 0X DO + WHILE (ch > 0X) & (ch < 0FCX) DO (* srcref: {dAdr,dPos} *) + INC(ad, ORD(ch)); INC(ref); RefNum(ref, d); + IF ad > codePos THEN RETURN pos END; + INC(pos, d); S.GET(ref, ch) + END; + IF ch = 0FCX THEN (* proc: 0FCX,Adr,Name *) + INC(ref); RefNum(ref, d); RefName(ref, name); S.GET(ref, ch); + IF (d > codePos) & (pos > 0) THEN RETURN pos END + END; + WHILE ch >= 0FDX DO (* skip variables: Mode, Form, adr, Name *) + INC(ref); RefCh(ref, ch); + IF ch = 10X THEN INC(ref, 4) END; + RefNum(ref, d); RefName(ref, name); S.GET(ref, ch) + END + END; + END; + RETURN -1 + END SourcePos; + + PROCEDURE LoadDll* (IN name: ARRAY OF CHAR; VAR ok: BOOLEAN); + VAR h: ADDRESS; file: Utf8Name; res: INTEGER; + BEGIN + StringToUtf8(name, file, res); + IF res = 0 THEN + h := dlfcn.dlopen(file, dlfcn.RTLD_LAZY + dlfcn.RTLD_GLOBAL); + ok := h # 0 + ELSE + ok := FALSE + END + END LoadDll; + + PROCEDURE ThisDllObj* (mode, fprint: INTEGER; IN dll, name: ARRAY OF CHAR): INTEGER; + VAR h, p: ADDRESS; file, sym: Utf8Name; res: INTEGER; err: dlfcn.int; + BEGIN + StringToUtf8(dll, file, res); + IF res = 0 THEN + h := dlfcn.dlopen(file, dlfcn.RTLD_LAZY + dlfcn.RTLD_GLOBAL); + IF h # 0 THEN + StringToUtf8(name, sym, res); + IF res = 0 THEN + p := dlfcn.dlsym(h, sym) + ELSE + p := 0 + END; + err := dlfcn.dlclose(h); + ASSERT(err = 0, 100) + ELSE + p := 0 + END + ELSE + p := 0 + END; + RETURN p + END ThisDllObj; + + (* -------------------- garbage collector (portable) --------------------- *) + + PROCEDURE Mark (this: Block); + VAR father, son: Block; tag: Type; flag, offset, actual: INTEGER; + BEGIN + IF ~ODD(S.VAL(INTEGER, this.tag)) THEN + father := NIL; + LOOP + INC(S.VAL(INTEGER, this.tag)); + flag := S.VAL(INTEGER, this.tag) MOD 4; + tag := S.VAL(Type, S.VAL(INTEGER, this.tag) - flag); + IF flag >= 2 THEN actual := this.first; this.actual := actual + ELSE actual := S.ADR(this.last) + END; + LOOP + offset := tag.ptroffs[0]; + IF offset < 0 THEN + INC(S.VAL(INTEGER, tag), offset + 4); (* restore tag *) + IF (flag >= 2) & (actual < this.last) & (offset < -4) THEN (* next array element *) + INC(actual, tag.size); this.actual := actual + ELSE (* up *) + this.tag := S.VAL(Type, S.VAL(INTEGER, tag) + flag); + IF father = NIL THEN RETURN END; + son := this; this := father; + flag := S.VAL(INTEGER, this.tag) MOD 4; + tag := S.VAL(Type, S.VAL(INTEGER, this.tag) - flag); + offset := tag.ptroffs[0]; + IF flag >= 2 THEN actual := this.actual ELSE actual := S.ADR(this.last) END; + S.GET(actual + offset, father); S.PUT(actual + offset, S.ADR(son.last)); + INC(S.VAL(INTEGER, tag), 4) + END + ELSE + S.GET(actual + offset, son); + IF son # NIL THEN + DEC(S.VAL(INTEGER, son), 4); + IF ~ODD(S.VAL(INTEGER, son.tag)) THEN (* down *) + this.tag := S.VAL(Type, S.VAL(INTEGER, tag) + flag); + S.PUT(actual + offset, father); father := this; this := son; + EXIT + END + END; + INC(S.VAL(INTEGER, tag), 4) + END + END + END + END + END Mark; + + PROCEDURE MarkGlobals; + VAR m: Module; i, p: INTEGER; + BEGIN + m := modList; + WHILE m # NIL DO + IF m.refcnt >= 0 THEN + i := 0; + WHILE i < m.nofptrs DO + S.GET(m.varBase + m.ptrs[i], p); INC(i); + IF p # 0 THEN Mark(S.VAL(Block, p - 4)) END + END + END; + m := m.next + END + END MarkGlobals; + + PROCEDURE Next (b: Block): Block; (* next block in same cluster *) + VAR size: INTEGER; + BEGIN + S.GET(S.VAL(INTEGER, b.tag) DIV 4 * 4, size); + IF ODD(S.VAL(INTEGER, b.tag) DIV 2) THEN INC(size, b.last - S.ADR(b.last)) END; + RETURN S.VAL(Block, S.VAL(INTEGER, b) + (size + 19) DIV 16 * 16) + END Next; + + PROCEDURE CheckCandidates; + (* pre: nofcand > 0 *) + VAR i, j, h, p, end: INTEGER; c: Cluster; blk, next: Block; + BEGIN + (* sort candidates (shellsort) *) + h := 1; REPEAT h := h*3 + 1 UNTIL h > nofcand; + REPEAT h := h DIV 3; i := h; + WHILE i < nofcand DO p := candidates[i]; j := i; + WHILE (j >= h) & (candidates[j-h] > p) DO + candidates[j] := candidates[j-h]; j := j-h + END; + candidates[j] := p; INC(i) + END + UNTIL h = 1; + (* sweep *) + c := root; i := 0; + WHILE c # NIL DO + blk := S.VAL(Block, S.VAL(INTEGER, c) + 12); + end := S.VAL(INTEGER, blk) + (c.size - 12) DIV 16 * 16; + WHILE candidates[i] < S.VAL(INTEGER, blk) DO + INC(i); + IF i = nofcand THEN RETURN END + END; + WHILE S.VAL(INTEGER, blk) < end DO + next := Next(blk); + IF candidates[i] < S.VAL(INTEGER, next) THEN + IF (S.VAL(INTEGER, blk.tag) # S.ADR(blk.last)) (* not a free block *) + & (~strictStackSweep OR (candidates[i] = S.ADR(blk.last))) THEN + Mark(blk) + END; + REPEAT + INC(i); + IF i = nofcand THEN RETURN END + UNTIL candidates[i] >= S.VAL(INTEGER, next) + END; + IF (S.VAL(INTEGER, blk.tag) MOD 4 = 0) & (S.VAL(INTEGER, blk.tag) # S.ADR(blk.last)) + & (blk.tag.base[0] = NIL) & (blk.actual > 0) THEN (* referenced interface record *) + Mark(blk) + END; + blk := next + END; + c := c.next + END + END CheckCandidates; + + PROCEDURE MarkLocals; + VAR sp, p, min, max: INTEGER; c: Cluster; + BEGIN + sp := S.ADR(sp); nofcand := 0; c := root; + WHILE c.next # NIL DO c := c.next END; + min := S.VAL(INTEGER, root); max := S.VAL(INTEGER, c) + c.size; + WHILE sp < baseStack DO + S.GET(sp, p); + IF (p > min) & (p < max) & (~strictStackSweep OR (p MOD 16 = 0)) THEN + candidates[nofcand] := p; INC(nofcand); + IF nofcand = LEN(candidates) - 1 THEN CheckCandidates; nofcand := 0 END + END; + INC(sp, 4) + END; + candidates[nofcand] := max; INC(nofcand); (* ensure complete scan for interface mark*) + IF nofcand > 0 THEN CheckCandidates END + END MarkLocals; + + PROCEDURE MarkFinObj; + VAR f: FList; + BEGIN + wouldFinalize := FALSE; + f := finalizers; + WHILE f # NIL DO + IF ~ODD(S.VAL(INTEGER, f.blk.tag)) THEN wouldFinalize := TRUE END; + Mark(f.blk); + f := f.next + END; + f := hotFinalizers; + WHILE f # NIL DO IF ~ODD(S.VAL(INTEGER, f.blk.tag)) THEN wouldFinalize := TRUE END; + Mark(f.blk); + f := f.next + END + END MarkFinObj; + + PROCEDURE CheckFinalizers; + VAR f, g, h, k: FList; + BEGIN + f := finalizers; g := NIL; + IF hotFinalizers = NIL THEN k := NIL + ELSE + k := hotFinalizers; + WHILE k.next # NIL DO k := k.next END + END; + WHILE f # NIL DO + h := f; f := f.next; + IF ~ODD(S.VAL(INTEGER, h.blk.tag)) THEN + IF g = NIL THEN finalizers := f ELSE g.next := f END; + IF k = NIL THEN hotFinalizers := h ELSE k.next := h END; + k := h; h.next := NIL + ELSE g := h + END + END; + h := hotFinalizers; + WHILE h # NIL DO Mark(h.blk); h := h.next END + END CheckFinalizers; + + PROCEDURE ExecFinalizer (a, b, c: INTEGER); + VAR f: FList; fin: PROCEDURE(this: ANYPTR); + BEGIN + f := S.VAL(FList, a); + S.GET(S.VAL(INTEGER, f.blk.tag) - 4, fin); (* method 0 *) + IF (fin # NIL) & (f.blk.tag.mod.refcnt >= 0) THEN fin(S.VAL(ANYPTR, S.ADR(f.blk.last))) END; + END ExecFinalizer; + + PROCEDURE^ Try* (h: TryHandler; a, b, c: INTEGER); (* COMPILER DEPENDENT *) + + PROCEDURE CallFinalizers; + VAR f: FList; + BEGIN + WHILE hotFinalizers # NIL DO + f := hotFinalizers; hotFinalizers := hotFinalizers.next; + Try(ExecFinalizer, S.VAL(INTEGER, f), 0, 0) + END; + wouldFinalize := FALSE + END CallFinalizers; + + PROCEDURE Insert (blk: FreeBlock; size: INTEGER); (* insert block in free list *) + VAR i: INTEGER; + BEGIN + blk.size := size - 4; blk.tag := S.VAL(Type, S.ADR(blk.size)); + i := MIN(N - 1, (blk.size DIV 16)); + blk.next := free[i]; free[i] := blk + END Insert; + + PROCEDURE Sweep (dealloc: BOOLEAN); + VAR cluster, last, c: Cluster; blk, next: Block; fblk, b, t: FreeBlock; end, i: INTEGER; + BEGIN + cluster := root; last := NIL; allocated := 0; + i := N; + REPEAT DEC(i); free[i] := sentinel UNTIL i = 0; + WHILE cluster # NIL DO + blk := S.VAL(Block, S.VAL(INTEGER, cluster) + 12); + end := S.VAL(INTEGER, blk) + (cluster.size - 12) DIV 16 * 16; + fblk := NIL; + WHILE S.VAL(INTEGER, blk) < end DO + next := Next(blk); + IF ODD(S.VAL(INTEGER, blk.tag)) THEN + IF fblk # NIL THEN + Insert(fblk, S.VAL(INTEGER, blk) - S.VAL(INTEGER, fblk)); + fblk := NIL + END; + DEC(S.VAL(INTEGER, blk.tag)); (* unmark *) + INC(allocated, S.VAL(INTEGER, next) - S.VAL(INTEGER, blk)) + ELSIF fblk = NIL THEN + fblk := S.VAL(FreeBlock, blk) + END; + blk := next + END; + IF dealloc & (S.VAL(INTEGER, fblk) = S.VAL(INTEGER, cluster) + 12) THEN (* deallocate cluster *) + c := cluster; cluster := cluster.next; + IF last = NIL THEN root := cluster ELSE last.next := cluster END; + FreeHeapMem(c) + ELSE + IF fblk # NIL THEN Insert(fblk, end - S.VAL(INTEGER, fblk)) END; + last := cluster; cluster := cluster.next + END + END; + (* reverse free list *) + i := N; + REPEAT + DEC(i); + b := free[i]; fblk := sentinel; + WHILE b # sentinel DO t := b; b := t.next; t.next := fblk; fblk := t END; + free[i] := fblk + UNTIL i = 0 + END Sweep; + + PROCEDURE Collect*; + BEGIN + IF root # NIL THEN + CallFinalizers; (* trap cleanup *) + MarkGlobals; + MarkLocals; + CheckFinalizers; + Sweep(TRUE); + CallFinalizers + END + END Collect; + + PROCEDURE FastCollect*; + BEGIN + IF root # NIL THEN + MarkGlobals; + MarkLocals; + MarkFinObj; + Sweep(FALSE) + END + END FastCollect; + + PROCEDURE WouldFinalize* (): BOOLEAN; + BEGIN + RETURN wouldFinalize + END WouldFinalize; + + (* --------------------- memory allocation (portable) -------------------- *) + + PROCEDURE OldBlock (size: INTEGER): FreeBlock; (* size MOD 16 = 0 *) + VAR b, l: FreeBlock; s, i: INTEGER; + BEGIN + s := size - 4; + i := MIN(N - 1, s DIV 16); + WHILE (i # N - 1) & (free[i] = sentinel) DO INC(i) END; + b := free[i]; l := NIL; + WHILE b.size < s DO l := b; b := b.next END; + IF b # sentinel THEN + IF l = NIL THEN free[i] := b.next ELSE l.next := b.next END + ELSE b := NIL + END; + RETURN b + END OldBlock; + + PROCEDURE LastBlock (limit: INTEGER): FreeBlock; (* size MOD 16 = 0 *) + VAR b, l: FreeBlock; s, i: INTEGER; + BEGIN + s := limit - 4; + i := 0; + REPEAT + b := free[i]; l := NIL; + WHILE (b # sentinel) & (S.VAL(INTEGER, b) + b.size # s) DO l := b; b := b.next END; + IF b # sentinel THEN + IF l = NIL THEN free[i] := b.next ELSE l.next := b.next END + ELSE b := NIL + END; + INC(i) + UNTIL (b # NIL) OR (i = N); + RETURN b + END LastBlock; + + PROCEDURE NewBlock (size: INTEGER): Block; + VAR tsize, a, s: INTEGER; b: FreeBlock; new, c: Cluster; r: Reducer; + BEGIN + ASSERT(size >= 0, 20); + IF size > MAX(INTEGER) - 19 THEN RETURN NIL END; + tsize := (size + 19) DIV 16 * 16; + b := OldBlock(tsize); (* 1) search for free block *) + IF b = NIL THEN + FastCollect; b := OldBlock(tsize); (* 2) collect *) + IF b = NIL THEN + Collect; b := OldBlock(tsize); (* 2a) fully collect *) + END; + IF b = NIL THEN + AllocHeapMem(tsize + 12, new); (* 3) allocate new cluster *) + IF new # NIL THEN + IF (root = NIL) OR (S.VAL(INTEGER, new) < S.VAL(INTEGER, root)) THEN + new.next := root; root := new + ELSE + c := root; + WHILE (c.next # NIL) & (S.VAL(INTEGER, new) > S.VAL(INTEGER, c.next)) DO c := c.next END; + new.next := c.next; c.next := new + END; + b := S.VAL(FreeBlock, S.VAL(INTEGER, new) + 12); + b.size := (new.size - 12) DIV 16 * 16 - 4 + ELSE + RETURN NIL (* 4) give up *) + END + END + END; + (* b # NIL *) + a := b.size + 4 - tsize; + IF a > 0 THEN Insert(S.VAL(FreeBlock, S.VAL(INTEGER, b) + tsize), a) END; + IF size > 0 THEN Erase(S.ADR(b.size), (size + 3) DIV 4) END; + INC(allocated, tsize); + RETURN S.VAL(Block, b) + END NewBlock; + + PROCEDURE Allocated* (): INTEGER; + BEGIN + RETURN allocated + END Allocated; + + PROCEDURE Used* (): INTEGER; + BEGIN + RETURN used + END Used; + + PROCEDURE Root* (): INTEGER; + BEGIN + RETURN S.VAL(INTEGER, root) + END Root; + + (* -------------------- Trap Handling --------------------- *) + + PROCEDURE Start* (code: Command); + VAR res: setjmp.int; + BEGIN + restart := code; + S.GETREG(SP, baseStack); + res := setjmp.sigsetjmp(startEnv, 1); + restart + END Start; + + PROCEDURE Quit* (exitCode: INTEGER); + VAR m: Module; term: Command; t: BOOLEAN; + BEGIN + trapViewer := NIL; trapChecker := NIL; restart := NIL; + t := terminating; terminating := TRUE; m := modList; + WHILE m # NIL DO (* call terminators *) + IF ~static OR ~t THEN + term := m.term; m.term := NIL; + IF term # NIL THEN term() END + END; + m := m.next + END; + CallFinalizers; + hotFinalizers := finalizers; finalizers := NIL; + CallFinalizers; + stdlib.exit(exitCode) + END Quit; + + PROCEDURE FatalError* (id: INTEGER; str: ARRAY OF CHAR); + VAR res: stdio.int; title: ARRAY 16 OF CHAR; text: ARRAY 256 OF SHORTCHAR; + BEGIN + title := "Error xy"; + title[6] := CHR(id DIV 10 + ORD("0")); + title[7] := CHR(id MOD 10 + ORD("0")); + res := unistd.write(2, S.ADR(title), 8); + stdlib.abort + END FatalError; + + PROCEDURE DefaultTrapViewer; + VAR out: ARRAY 2048 OF SHORTCHAR; a, b, c, len, ref, end: INTEGER; mod: Module; + modName, name: Name; n: Utf8Name; res: unistd.int; + + PROCEDURE WriteString (IN s: ARRAY OF SHORTCHAR); + VAR i: INTEGER; + BEGIN + i := 0; + WHILE (len < LEN(out) - 1) & (s[i] # 0X) DO out[len] := s[i]; INC(i); INC(len) END + END WriteString; + + PROCEDURE WriteHex (x, n: INTEGER); + VAR i, y: INTEGER; + BEGIN + IF len + n < LEN(out) THEN + i := len + n - 1; + WHILE i >= len DO + y := x MOD 16; x := x DIV 16; + IF y > 9 THEN y := y + (ORD("A") - ORD("0") - 10) END; + out[i] := SHORT(CHR(y + ORD("0"))); DEC(i) + END; + INC(len, n) + END + END WriteHex; + + PROCEDURE WriteLn; + BEGIN + IF len < LEN(out) - 1 THEN out[len] := 0AX; INC(len) END + END WriteLn; + + BEGIN + len := 0; + WriteString("====== "); + IF err = 129 THEN WriteString("invalid with") + ELSIF err = 130 THEN WriteString("invalid case") + ELSIF err = 131 THEN WriteString("function without return") + ELSIF err = 132 THEN WriteString("type guard") + ELSIF err = 133 THEN WriteString("implied type guard") + ELSIF err = 134 THEN WriteString("value out of range") + ELSIF err = 135 THEN WriteString("index out of range") + ELSIF err = 136 THEN WriteString("string too long") + ELSIF err = 137 THEN WriteString("stack overflow") + ELSIF err = 138 THEN WriteString("integer overflow") + ELSIF err = 139 THEN WriteString("division by zero") + ELSIF err = 140 THEN WriteString("infinite real result") + ELSIF err = 141 THEN WriteString("real underflow") + ELSIF err = 142 THEN WriteString("real overflow") + ELSIF err = 143 THEN WriteString("undefined real result") + ELSIF err = 144 THEN WriteString("not a number") + ELSIF err = 200 THEN WriteString("keyboard interrupt") + ELSIF err = 201 THEN WriteString("NIL dereference") + ELSIF err = 202 THEN WriteString("illegal instruction: "); + WriteHex(val, 4) + ELSIF err = 203 THEN WriteString("illegal memory read [ad = "); + WriteHex(val, 8); WriteString("]") + ELSIF err = 204 THEN WriteString("illegal memory write [ad = "); + WriteHex(val, 8); WriteString("]") + ELSIF err = 205 THEN WriteString("illegal execution [ad = "); + WriteHex(val, 8); WriteString("]") + ELSIF err = 257 THEN WriteString("out of memory") + ELSIF err = 10001H THEN WriteString("bus error") + ELSIF err = 10002H THEN WriteString("address error") + ELSIF err = 10007H THEN WriteString("fpu error") + ELSIF err < 0 THEN WriteString("exception #"); WriteHex(-err, 2) + ELSE err := err DIV 100 * 256 + err DIV 10 MOD 10 * 16 + err MOD 10; + WriteString("trap #"); WriteHex(err, 3) + END; + WriteString(" ======"); + a := pc; b := fp; c := 12; + REPEAT + WriteLn; WriteString("- "); + mod := modList; + WHILE (mod # NIL) & ((a < mod.code) OR (a >= mod.code + mod.csize)) DO mod := mod.next END; + IF mod # NIL THEN + DEC(a, mod.code); + IF mod.refcnt >= 0 THEN + GetModName(mod, modName); WriteString(SHORT(modName)); ref := mod.refs; + REPEAT GetRefProc(ref, end, n) UNTIL (end = 0) OR (a < end); + IF a < end THEN + Utf8ToString(n, name, res); WriteString("."); WriteString(SHORT(name)) + END + ELSE + GetModName(mod, modName); WriteString("("); WriteString(SHORT(modName)); WriteString(")") + END; + WriteString(" ") + END; + WriteString("(pc="); WriteHex(a, 8); + WriteString(", fp="); WriteHex(b, 8); WriteString(")"); + IF (b >= sp) & (b < stack) THEN + S.GET(b+4, a); (* stacked pc *) + S.GET(b, b); (* dynamic link *) + DEC(c) + ELSE c := 0 + END + UNTIL c = 0; + out[len] := 0X; + res := unistd.write(2, S.ADR(out), len) + END DefaultTrapViewer; + + PROCEDURE TrapCleanup; + VAR t: TrapCleaner; + BEGIN + WHILE trapStack # NIL DO + t := trapStack; trapStack := trapStack.next; t.Cleanup + END; + IF (trapChecker # NIL) & (err # 128) THEN trapChecker END + END TrapCleanup; + + PROCEDURE SetTrapGuard* (on: BOOLEAN); + BEGIN + guarded := on + END SetTrapGuard; + + PROCEDURE Try* (h: TryHandler; a, b, c: INTEGER); + VAR oldIsTry: BOOLEAN; oldTryEnv: setjmp.jmp_buf; res: setjmp.int; + BEGIN + oldIsTry := isTry; oldTryEnv := tryEnv; + isTry := TRUE; + res := setjmp._setjmp(tryEnv); + IF res = 0 THEN h(a, b, c) END; + isTry := oldIsTry; tryEnv := oldTryEnv + END Try; + + PROCEDURE Trap* (n: INTEGER); + BEGIN + IF trapped THEN + DefaultTrapViewer; + IF ~secondTrap THEN trapped := FALSE; secondTrap := TRUE END + END; + IF n >= 0 THEN err := n + ELSE err := -n + 128 + END; + pc := 0; sp := 0; fp := 0; stack := 0; val := 0; + INC(trapCount); + (* !!! InitFPU *) + TrapCleanup; + IF isTry THEN + setjmp._longjmp(tryEnv, 1) + END; + IF err = 128 THEN (* do nothing *) + ELSIF (trapViewer # NIL) & (restart # NIL) & ~trapped & ~guarded THEN + trapped := TRUE; trapViewer() + ELSE DefaultTrapViewer + END; + trapped := FALSE; secondTrap := FALSE; + IF restart # NIL THEN + setjmp.siglongjmp(startEnv, 1) + END; + stdlib.abort + END Trap; + + PROCEDURE [ccall] TrapHandler (signo: signal.int; IN info: signal.siginfo_t; context: ADDRESS); + VAR res: signal.int; + BEGIN + IF trapped THEN + DefaultTrapViewer; + IF ~secondTrap THEN trapped := FALSE; secondTrap := TRUE END + END; + err := -signo; pc := 0; sp := 0; fp := 0; stack := baseStack; val := 0; + CASE signo OF + | signal.SIGFPE: + val := info.si_code; + pc := info.info.sigfpe.si_addr; + CASE info.si_code OF + | signal.FPE_INTDIV: err := 139 (* division by zero *) + | signal.FPE_INTOVF: err := 138 (* integer overflow *) + | signal.FPE_FLTDIV: err := 140 (* fpu: division by zero *) + | signal.FPE_FLTOVF: err := 142 (* fpu: overflow *) + | signal.FPE_FLTUND: err := 141 (* fpu: underflow *) + (* !!! | signal.FPE_FLTRES: err := ??? (* fpu: *) *) + | signal.FPE_FLTINV: err := 143 (* val := opcode *) (* fpu: invalid op *) + (* !!! | signal.FPE_FLTSUB: err := ??? (* fpu: *) *) + ELSE (* unknown *) + END + | signal.SIGINT: + val := info.si_code; + err := 200 (* keyboard interrupt *) + | signal.SIGSEGV: + val := info.info.sigsegv.si_addr; + err := 203 (* illigal read *) + | signal.SIGBUS: + val := info.info.sigbus.si_addr; + err := 10001H (* bus error *) + | signal.SIGILL: + pc := info.info.sigill.si_addr; + err := 202; (* illigal instruction *) + IF IsReadable(pc, pc + 4) THEN + S.GET(pc, val) + (* !!! err := halt code *) + END; + ELSE (* unknown *) + END; + INC(trapCount); + (* !!! InitFPU *) + TrapCleanup; + IF isTry THEN + setjmp._longjmp(tryEnv, 1) + END; + IF err = 128 THEN (* do nothing *) + ELSIF (trapViewer # NIL) & (restart # NIL) & ~trapped & ~guarded THEN + trapped := TRUE; trapViewer() + ELSE DefaultTrapViewer + END; + trapped := FALSE; secondTrap := FALSE; + IF restart # NIL THEN + setjmp.siglongjmp(startEnv, 1) + END; + stdlib.abort + END TrapHandler; + + (* -------------------- Initialization --------------------- *) + + PROCEDURE InstallTrap (signo: signal.int); + VAR act: signal.struct_sigaction; res: signal.int; + BEGIN + act.handler.sa_handler := NIL; + res := signal.sigemptyset(act.sa_mask); + act.sa_flags := signal.SA_NODEFER + signal.SA_SIGINFO; + act.handler.sa_sigaction := TrapHandler; + res := signal.sigaction(signo, act, NIL); + END InstallTrap; + + PROCEDURE InstallTrapVectors; + BEGIN + InstallTrap(signal.SIGFPE); + InstallTrap(signal.SIGINT); + InstallTrap(signal.SIGSEGV); + InstallTrap(signal.SIGBUS); + InstallTrap(signal.SIGILL) + END InstallTrapVectors; + + PROCEDURE RemoveTrapVectors; + END RemoveTrapVectors; + + PROCEDURE Init; + VAR i: INTEGER; + BEGIN + pagesize := unistd.sysconf(unistd._SC_PAGESIZE); + + (* init heap *) + allocated := 0; total := 0; used := 0; + sentinelBlock.size := MAX(INTEGER); + sentinel := S.ADR(sentinelBlock); + i := N; + REPEAT DEC(i); free[i] := sentinel UNTIL i = 0; + + IF ~inDll THEN + InstallTrapVectors + END; + + (* !!! InitFPU *) + IF ~static THEN + InitModule(modList); + IF ~inDll THEN Quit(1) END + END + END Init; + +BEGIN + IF modList = NIL THEN (* only once *) + S.GETREG(SP, baseStack); + S.GET(baseStack + 16, argc); + argv := S.VAL(ArrStrPtr, baseStack + 20); + S.GETREG(ML, modList); (* linker loads module list to BX *) + static := init IN modList.opts; + inDll := dll IN modList.opts; + Init + END +CLOSE + IF ~terminating THEN + terminating := TRUE; + Quit(0) + END +END Kernel. diff --git a/src/posix/Host/Mod/Console.cp b/src/posix/Host/Mod/Console.cp new file mode 100644 index 0000000..d29048e --- /dev/null +++ b/src/posix/Host/Mod/Console.cp @@ -0,0 +1,41 @@ +MODULE HostConsole; + + IMPORT S := SYSTEM, Console, HostLang, unistd := C99unistd; + + TYPE + Directory = POINTER TO RECORD (Console.Directory) END; + + PROCEDURE (d: Directory) WriteChar (ch: CHAR); + VAR res: INTEGER; s: ARRAY 2 OF CHAR; ss: ARRAY 12 OF SHORTCHAR; + BEGIN + s[0] := ch; s[1] := 0X; + HostLang.StringToHost(s, ss, TRUE, res); + ASSERT(res = 0, 100); + res := unistd.write(1, S.ADR(ss[0]), LEN(ss$)); + res := unistd.fsync(1) + END WriteChar; + + PROCEDURE (d: Directory) WriteString (IN s: ARRAY OF CHAR); + VAR ss: POINTER TO ARRAY OF SHORTCHAR; res: INTEGER; + BEGIN + NEW(ss, LEN(s$) * 4 + 1); + HostLang.StringToHost(s, ss, TRUE, res); + ASSERT(res = 0, 100); + res := unistd.write(1, S.ADR(ss[0]), LEN(ss$)); + res := unistd.fsync(1) + END WriteString; + + PROCEDURE (d: Directory) WriteLn; + BEGIN + d.WriteChar(0AX) + END WriteLn; + + PROCEDURE Init; + VAR d: Directory; + BEGIN + NEW(d); Console.SetDir(d) + END Init; + +BEGIN + Init +END HostConsole. diff --git a/src/posix/Host/Mod/Dates.cp b/src/posix/Host/Mod/Dates.cp new file mode 100644 index 0000000..3d7acab --- /dev/null +++ b/src/posix/Host/Mod/Dates.cp @@ -0,0 +1,142 @@ +MODULE HostDates; + + IMPORT Dates, Strings, time := C99time; + + (* add localization? *) + + TYPE + Hook = POINTER TO RECORD (Dates.Hook) END; + + VAR + day: ARRAY 7, 10 OF CHAR; + month: ARRAY 12, 10 OF CHAR; + + PROCEDURE (h: Hook) GetTime (OUT d: Dates.Date; OUT t: Dates.Time); + VAR epoch: time.time_t; tm: time.struct_tm; ptm: time.Pstruct_tm; + BEGIN + epoch := time.time(NIL); + ptm := time.localtime_r(epoch, tm); + IF ptm # NIL THEN + d.year := tm.tm_year + 1900; + d.month := tm.tm_mon + 1; + d.day := tm.tm_mday; + t.hour := tm.tm_hour; + t.minute := tm.tm_min; + t.second := tm.tm_sec + ELSE + d.year := 0; + d.month := 0; + d.day := 0; + t.hour := 0; + t.minute := 0; + t.second := 0 + END + END GetTime; + + PROCEDURE (h: Hook) GetUTCTime (OUT d: Dates.Date; OUT t: Dates.Time); + VAR epoch: time.time_t; tm: time.struct_tm; ptm: time.Pstruct_tm; + BEGIN + epoch := time.time(NIL); + ptm := time.gmtime_r(epoch, tm); + IF ptm # NIL THEN + d.year := tm.tm_year + 1900; + d.month := tm.tm_mon + 1; + d.day := tm.tm_mday; + t.hour := tm.tm_hour; + t.minute := tm.tm_min; + t.second := tm.tm_sec + ELSE + d.year := 0; + d.month := 0; + d.day := 0; + t.hour := 0; + t.minute := 0; + t.second := 0 + END + END GetUTCTime; + + PROCEDURE (h: Hook) GetUTCBias (OUT bias: INTEGER); + BEGIN + time.tzset; + (* !!! fix Dev2 *) + (* bias := time.timezone DIV 60 *) + bias := 0; + END GetUTCBias; + + PROCEDURE (h: Hook) DateToString (d: Dates.Date; format: INTEGER; OUT str: ARRAY OF CHAR); + VAR s: ARRAY 20 OF CHAR; + + PROCEDURE Copy (IN s: ARRAY OF CHAR; n: INTEGER; OUT str: ARRAY OF CHAR); + VAR i: INTEGER; + BEGIN + FOR i := 0 TO n - 1 DO + str[i] := s[i] + END; + str[i] := 0X + END Copy; + + BEGIN + CASE format OF + | Dates.short: + str[0] := CHR(d.day DIV 10 MOD 10 + ORD("0")); + str[1] := CHR(d.day MOD 10 + ORD("0")); + str[2] := "/"; + str[3] := CHR(d.month DIV 10 MOD 10 + ORD("0")); + str[4] := CHR(d.month MOD 10 + ORD("0")); + str[5] := "/"; + str[6] := CHR(d.year DIV 10 MOD 10 + ORD("0")); + str[7] := CHR(d.year MOD 10 + ORD("0")); + str[8] := 0X + | Dates.abbreviated: + Copy(day[d.day - 1], 3, str); + Copy(month[d.month - 1], 3, s); str := str + ", " + s; + Strings.IntToString(d.year, s); str := str + ", " + s + | Dates.long: + str := day[d.day - 1] + ", " + month[d.month - 1]; + Strings.IntToString(d.year, s); str := str + ", " + s + | Dates.plainAbbreviated: + Copy(month[d.month - 1], 3, str); + Strings.IntToString(d.day, s); str := str + " " + s; + Strings.IntToString(d.year, s); str := str + ", " + s + | Dates.plainLong: + Strings.IntToString(d.day, s); str := month[d.month - 1] + " " + s; + Strings.IntToString(d.year, s); str := str + ", " + s + END + END DateToString; + + PROCEDURE (h: Hook) TimeToString (t: Dates.Time; OUT str: ARRAY OF CHAR); + VAR s: ARRAY 12 OF CHAR; + BEGIN + Strings.IntToString(t.hour, str); + Strings.IntToString(t.minute, s); str := str + ":" + s; + Strings.IntToString(t.second, s); str := str + ":" + s; + END TimeToString; + + PROCEDURE Init; + VAR h: Hook; + BEGIN + day[0] := "Monday"; + day[1] := "Tuesday"; + day[2] := "Wednesday"; + day[3] := "Thursday"; + day[4] := "Friday"; + day[5] := "Saturday"; + day[6] := "Sunday"; + month[0] := "January"; + month[1] := "February"; + month[2] := "March"; + month[3] := "April"; + month[4] := "May"; + month[5] := "June"; + month[6] := "July"; + month[7] := "August"; + month[8] := "September"; + month[9] := "October"; + month[10] := "November"; + month[11] := "December"; + NEW(h); Dates.SetHook(h) + END Init; + +BEGIN + Init +END HostDates. diff --git a/src/posix/Host/Mod/Files.cp b/src/posix/Host/Mod/Files.cp new file mode 100644 index 0000000..19517f2 --- /dev/null +++ b/src/posix/Host/Mod/Files.cp @@ -0,0 +1,757 @@ +MODULE HostFiles; + + IMPORT S := SYSTEM, Kernel, HostLang, Files, Log, stdlib := C99stdlib, + unistd := C99unistd, dirent := C99dirent, fcntl := C99fcntl, + sysstat := C99sys_stat, stdio := C99stdio, errno := C99errno, + macro := C99macro, libgen := C99libgen, time := C99time; + + (* !!! add buffer cache *) + + CONST + closed = 0; new = 1; temp = 2; shared = 3; exclusive = 4; + + TYPE + FullName* = Files.Name; + NativeName* = ARRAY 1024 OF SHORTCHAR; + + Locator = POINTER TO RECORD (Files.Locator) + path-: FullName (* pathname # "" *) + END; + + Directory = POINTER TO RECORD (Files.Directory) END; + + File = POINTER TO RECORD (Files.File) + state: INTEGER; + len: INTEGER; + fd: unistd.int; + ino: sysstat.ino_t; + pathname: FullName + END; + + Reader = POINTER TO RECORD (Files.Reader) + f: File; + pos: INTEGER + END; + + Writer = POINTER TO RECORD (Files.Writer) + f: File; + pos: INTEGER + END; + + InodeIdentifier = RECORD (Kernel.Identifier) + ino: sysstat.ino_t + END; + + VAR + ignoreAsk-: BOOLEAN; + root: Locator; + + PROCEDURE (VAR id: InodeIdentifier) Identified (): BOOLEAN; + VAR f: File; + BEGIN + f := id.obj(File); + RETURN (f.state # closed) & (f.ino = id.ino) + END Identified; + + PROCEDURE GetFileByInode (ino: sysstat.ino_t): File; + VAR id: InodeIdentifier; obj: ANYPTR; f: File; + BEGIN + ASSERT(ino # 0, 20); + id.typ := S.TYP(File); + id.ino := ino; + obj := Kernel.ThisFinObj(id); + IF obj # NIL THEN f := obj(File) + ELSE f := NIL + END; + RETURN f + END GetFileByInode; + + PROCEDURE GetError (OUT res: INTEGER); + VAR err: INTEGER; + BEGIN + err := macro.errno(); + CASE err OF + | errno.ENAMETOOLONG, errno.ENOTDIR: res := 1 (* invalid name/location *) + | errno.ENOENT: res := 2 (* file/dir not found *) + | errno.EEXIST: res := 3 (* file/dir already exists *) + | errno.EROFS: res := 4 (* write-protection *) + | errno.EIO: res := 5 (* io error *) + | errno.EACCES, errno.EPERM: res := 6 (* access denied *) + | errno.ENOMEM: res := 80 (* not enough memory *) + | errno.ENFILE, errno.ENOBUFS, errno.ENOSPC: res := 81 (* not enough system resources *) + ELSE res := -err + END + END GetError; + + (* Locator *) + + PROCEDURE NewLocator* (IN path: ARRAY OF CHAR): Locator; + VAR l: Locator; ch: SHORTCHAR; + BEGIN + NEW(l); + IF path = "" THEN l.path := "." + ELSE l.path := path$ + END; + RETURN l + END NewLocator; + + PROCEDURE (l: Locator) This (IN path: ARRAY OF CHAR): Locator; + VAR loc: Locator; + BEGIN + IF path = "" THEN NEW(loc); loc^ := l^ + ELSIF path[0] = "/" THEN loc := NewLocator(path) + ELSE loc := NewLocator(l.path + "/" + path) + END; + RETURN loc + END This; + + (* File *) + + PROCEDURE (f: File) Length (): INTEGER; + BEGIN + RETURN f.len + END Length; + + PROCEDURE (f: File) NewReader (old: Files.Reader): Reader; + VAR r: Reader; + BEGIN + ASSERT(f.state # closed, 20); + IF (old # NIL) & (old.Base() = f) THEN + r := old(Reader); + IF r.pos > f.len THEN r.pos := 0 END; + r.eof := FALSE + ELSE NEW(r); r.f := f; r.pos := 0 + END; + RETURN r + END NewReader; + + PROCEDURE (f: File) NewWriter (old: Files.Writer): Writer; + VAR w: Writer; + BEGIN + ASSERT(f.state # closed, 20); + ASSERT(f.state # shared, 21); + IF (old # NIL) & (old.Base() = f) THEN + w := old(Writer); + IF w.pos > f.len THEN w.pos := 0 END + ELSE NEW(w); w.f := f; w.pos := 0 + END; + RETURN w + END NewWriter; + + PROCEDURE (f: File) Flush; + VAR res: unistd.int; + BEGIN + IF f.state # closed THEN + res := unistd.fsync(f.fd); + ASSERT(res = 0, 100) + END + END Flush; + + PROCEDURE IsName (IN name: Files.Name): BOOLEAN; + VAR i: INTEGER; + BEGIN + i := 0; + WHILE (name[i] # "/") & (name[i] # 0X) DO INC(i) END; + RETURN name[i] = 0X + END IsName; + + PROCEDURE DirName (VAR path: ARRAY OF CHAR); + VAR i, j, k: INTEGER; + BEGIN + IF path[0] = "/" THEN i := 1; j := 1; k := 1 + ELSE i := 0; j := 0; k := 0 + END; + WHILE path[i] # 0X DO + IF path[i] = "/" THEN + k := j; j := i; INC(i); + WHILE (path[i] # 0X) & (path[i] = "/") DO INC(i) END; + IF path[i] = 0X THEN j := k END + ELSE + INC(i) + END + END; + path[j] := 0X + END DirName; + + PROCEDURE (f: File) Register (name: Files.Name; type: Files.Type; ask: BOOLEAN; OUT res: INTEGER); + VAR i, err: INTEGER; dir: FullName; p0, p1: NativeName; s: sysstat.struct_stat; x: unistd.int; + BEGIN + ASSERT(f.state = new, 20); + ASSERT(name # "", 21); + ASSERT(IsName(name), 22); + HostLang.StringToHost(f.pathname, p0, FALSE, err); + IF err = 0 THEN + dir := f.pathname$; + DirName(dir); + HostLang.StringToHost(dir + "/" + name, p1, FALSE, err); + IF err = 0 THEN + x := stdio.rename(p0, p1); + IF x = 0 THEN res := 0 (* no error *) + ELSE GetError(res) + END; + f.state := exclusive; + f.Close + ELSE + res := 1 (* invalid name (too long?) *) + END + ELSE + res := 1 (* invalid name (too long?) *) + END + END Register; + + PROCEDURE (f: File) Close; + VAR res: unistd.int; path: NativeName; err: INTEGER; + BEGIN + IF f.state # closed THEN + f.Flush; + IF f.state = new THEN + HostLang.StringToHost(f.pathname, path, FALSE, err); + ASSERT(err = 0, 100); + res := unistd.unlink(path); + ASSERT(res = 0, 101); + f.state := temp + END; + res := unistd.close(f.fd); + ASSERT(res = 0, 102); + f.state := closed + END + END Close; + + PROCEDURE (f: File) Closed (): BOOLEAN; + BEGIN + RETURN f.state = closed + END Closed; + + PROCEDURE (f: File) Shared (): BOOLEAN; + BEGIN + RETURN f.state = shared + END Shared; + + PROCEDURE (f: File) FINALIZE; + BEGIN + f.Close + END FINALIZE; + + (* Reader *) + + PROCEDURE (r: Reader) Base (): File; + BEGIN + RETURN r.f + END Base; + + PROCEDURE (r: Reader) Pos (): INTEGER; + BEGIN + RETURN r.pos + END Pos; + + PROCEDURE (r: Reader) SetPos (pos: INTEGER); + BEGIN + ASSERT(pos >= 0, 20); + ASSERT(pos <= r.f.len, 21); + r.pos := pos; + r.eof := FALSE + END SetPos; + + PROCEDURE (r: Reader) ReadByte (OUT x: BYTE); + VAR res: unistd.int; offset: unistd.off_t; + BEGIN + ASSERT(r.f.state # closed, 20); + offset := unistd.lseek(r.f.fd, r.pos, unistd.SEEK_SET); + ASSERT(offset = r.pos, 100); + res := unistd.read(r.f.fd, S.ADR(x), 1); + ASSERT(res # -1, 101); + IF res = 0 THEN x := 0 END; + r.pos := r.pos + res; + r.eof := res = 0 + END ReadByte; + + PROCEDURE (r: Reader) ReadBytes (VAR x: ARRAY OF BYTE; beg, len: INTEGER); + VAR res: unistd.int; offset: unistd.off_t; + BEGIN + ASSERT(beg >= 0, 20); + ASSERT(len >= 0, 2); + ASSERT(beg + len <= LEN(x), 22); + ASSERT(r.f.state # closed, 23); + offset := unistd.lseek(r.f.fd, r.pos, unistd.SEEK_SET); + ASSERT(offset = r.pos, 100); + res := unistd.read(r.f.fd, S.ADR(x[beg]), len); + ASSERT(res # -1, 101); + r.pos := r.pos + res; + r.eof := res = 0 + END ReadBytes; + + (* Writer *) + + PROCEDURE (w: Writer) Base (): File; + BEGIN + RETURN w.f + END Base; + + PROCEDURE (w: Writer) Pos (): INTEGER; + BEGIN + RETURN w.pos + END Pos; + + PROCEDURE (w: Writer) SetPos (pos: INTEGER); + BEGIN + ASSERT(pos >= 0, 20); + ASSERT(pos <= w.f.len, 21); + w.pos := pos + END SetPos; + + PROCEDURE (w: Writer) WriteByte (x: BYTE); + VAR res: unistd.int; offset: unistd.off_t; + BEGIN + ASSERT(w.f.state # closed, 20); + offset := unistd.lseek(w.f.fd, w.pos, unistd.SEEK_SET); + ASSERT(offset = w.pos, 100); + res := unistd.write(w.f.fd, S.ADR(x), 1); + ASSERT(res # -1, 101); + w.pos := w.pos + res; + w.f.len := MAX(w.f.len, w.pos); + ASSERT(res = 1, 60) + END WriteByte; + + PROCEDURE (w: Writer) WriteBytes (IN x: ARRAY OF BYTE; beg, len: INTEGER); + VAR res: unistd.int; offset: unistd.off_t; + BEGIN + ASSERT(beg >= 0, 20); + ASSERT(len >= 0, 21); + ASSERT(beg + len <= LEN(x), 22); + ASSERT(w.f.state # closed, 23); + offset := unistd.lseek(w.f.fd, w.pos, unistd.SEEK_SET); + ASSERT(offset = w.pos, 100); + res := unistd.write(w.f.fd, S.ADR(x[beg]), len); + ASSERT(res # -1, 101); + w.pos := w.pos + res; + w.f.len := MAX(w.f.len, w.pos); + ASSERT(res = len, 60) + END WriteBytes; + + (* Directory *) + + PROCEDURE (d: Directory) This (IN path: ARRAY OF CHAR): Locator; + BEGIN + RETURN root.This(path) + END This; + + PROCEDURE MakeDir (path: ARRAY OF SHORTCHAR; OUT res: unistd.int); + VAR i: INTEGER; sep: BOOLEAN; err: unistd.int; s: sysstat.struct_stat; mode: sysstat.mode_t; + BEGIN + i := 0; err := 0; + mode := ORD(BITS(511(*a=rwx*)) - BITS(sysstat.umask(0))); + WHILE (err = 0) & (path[i] # 0X) DO + WHILE (path[i] # "/") & (path[i] # 0X) DO INC(i) END; + sep := path[i] = "/"; + IF sep THEN path[i] := 0X END; + err := sysstat.mkdir(path, mode); + IF err = -1 THEN + GetError(err); + IF err = 3 THEN + (* already exists, continue make dirs *) + err := 0 + END + END; + IF sep THEN path[i] := "/" END; + INC(i) + END; + res := err + END MakeDir; + + PROCEDURE (d: Directory) New (loc: Files.Locator; ask: BOOLEAN): File; + VAR err: INTEGER; f: File; s: sysstat.struct_stat; fd, res: unistd.int; pathname: NativeName; + BEGIN + ASSERT(loc # NIL, 20); + WITH loc: Locator DO + HostLang.StringToHost(loc.path, pathname, FALSE, err); + IF err = 0 THEN + MakeDir(pathname, res); + IF res = 0 THEN + (* use fcntl.open() with O_TMPFILE for Linux 3.11+? *) + pathname := pathname + "/" + ".newXXXXXX"; + fd := stdlib.mkstemp(pathname); + IF fd # -1 THEN + NEW(f); HostLang.HostToString(pathname, f.pathname, FALSE, err); + IF err = 0 THEN + (* !!! get valid inode? *) + f.fd := fd; f.len := 0; f.state := new; f.ino := 0; + loc.res := 0 (* no errors *) + ELSE + f := NIL; + res := unistd.close(fd); + ASSERT(res = 0, 100); + res := unistd.unlink(pathname); + ASSERT(res = 0, 101); + loc.res := 1 (* invalid name *) + END + ELSE + GetError(loc.res) + END + ELSE + loc.res := res + END + ELSE + loc.res := 1 (* invalid name *) + END + ELSE + loc.res := 1 (* invalid locator *) + END; + RETURN f + END New; + + PROCEDURE IsRegFile (IN s: sysstat.struct_stat): BOOLEAN; + BEGIN + RETURN BITS(s.st_mode) * BITS(sysstat.S_IFMT) = BITS(sysstat.S_IFREG) + END IsRegFile; + + PROCEDURE (d: Directory) Old (loc: Files.Locator; name: Files.Name; isShared: BOOLEAN): File; + CONST rwrwrw = 438; + VAR err: INTEGER; f, if: File; s: sysstat.struct_stat; fd, flags, res: unistd.int; + pathname: NativeName; mode: sysstat.mode_t; lock: fcntl.struct_flock; + + PROCEDURE Cleanup; + BEGIN + f := NIL; + res := unistd.close(fd); + ASSERT(res = 0, 100) + END Cleanup; + + BEGIN + ASSERT(loc # NIL, 20); + ASSERT(name # "", 21); + WITH loc: Locator DO + IF IsName(name) THEN + HostLang.StringToHost(loc.path + "/" + name, pathname, FALSE, err); + IF err = 0 THEN + res := macro.stat(pathname, s); + IF res = 0 THEN + IF IsRegFile(s) THEN + if := GetFileByInode(s.st_ino); + IF (if = NIL) OR isShared & (if.state = shared) THEN + mode := ORD(BITS(rwrwrw) - BITS(sysstat.umask(0))); + IF isShared THEN flags := fcntl.O_RDONLY + ELSE flags := fcntl.O_RDWR + END; + fd := fcntl.open(pathname, flags, mode); + IF fd # -1 THEN + IF isShared THEN lock.l_type := fcntl.F_RDLCK + ELSE lock.l_type := fcntl.F_WRLCK + END; + lock.l_whence := unistd.SEEK_SET; + lock.l_start := 0; + lock.l_len := 0; + lock.l_pid := 0; + res := fcntl.fcntl(fd, fcntl.F_SETLK, S.ADR(lock)); + IF res # -1 THEN + NEW(f); HostLang.HostToString(pathname, f.pathname, FALSE, err); + IF err = 0 THEN + f.fd := fd; f.len := s.st_size; f.ino := s.st_ino; + IF isShared THEN f.state := shared + ELSE f.state := exclusive + END; + loc.res := 0 (* no errors *) + ELSE + loc.res := 1; (* invalid name *) + Cleanup + END + ELSE + GetError(loc.res); (* already locked *) + Cleanup + END + ELSE + GetError(loc.res) (* failed to open *) + END + ELSE + loc.res := 6 (* already opened / locked *) + END + ELSE + loc.res := 6 (* access denied (not a regular file) *) + END + ELSE + loc.res := 2 (* file not found *) + END + ELSE + loc.res := 1 (* invalid name *) + END + ELSE + loc.res := 1 (* invalid name *) + END + ELSE + loc.res := 1 (* invalid locator *) + END; + RETURN f + END Old; + + PROCEDURE (d: Directory) Temp (): File; + VAR f: File; fd: unistd.int; name: ARRAY 12 OF SHORTCHAR; + BEGIN + (* use fcntl.open() with O_TMPFILE for Linux 3.11+? *) + name := ".tmpXXXXXX"; + fd := stdlib.mkstemp(name); + ASSERT(fd # -1, 100); + (* !!! get pathname and unlink it here *) + NEW(f); f.fd := fd; f.pathname := ""; f.len := 0; f.ino := 0; f.state := temp; + RETURN f + END Temp; + + PROCEDURE (d: Directory) Delete (loc: Files.Locator; name: Files.Name); + VAR pathname: NativeName; err: INTEGER; res: unistd.int; + BEGIN + ASSERT(loc # NIL, 20); + ASSERT(IsName(name), 21); + WITH loc: Locator DO + IF IsName(name) THEN + HostLang.StringToHost(loc.path + "/" + name, pathname, FALSE, err); + IF err = 0 THEN + res := unistd.unlink(pathname); + IF res = 0 THEN loc.res := 0 (* no error *) + ELSE GetError(loc.res) + END + ELSE + loc.res := 1 (* invalid name *) + END + ELSE + loc.res := 1 (* invalid name *) + END + ELSE + loc.res := 1 (* invalid locator *) + END + END Delete; + + PROCEDURE (d: Directory) Rename (loc: Files.Locator; old, new: Files.Name; ask: BOOLEAN); + VAR p0, p1: NativeName; res: stdio.int; err: INTEGER; + BEGIN + ASSERT(loc # NIL, 20); + ASSERT(old # "", 21); + ASSERT(new # "", 22); + WITH loc: Locator DO + IF IsName(old) & IsName(new) THEN + HostLang.StringToHost(loc.path + "/" + old, p0, FALSE, err); + IF err = 0 THEN + HostLang.StringToHost(loc.path + "/" + new, p1, FALSE, err); + IF err = 0 THEN + res := stdio.rename(p0, p1); + IF res = 0 THEN loc.res := 0 (* no error *) + ELSE GetError(loc.res) + END + ELSE + loc.res := 1 (* invalid name *) + END + ELSE + loc.res := 1 (* invalid name *) + END + ELSE + loc.res := 1 (* invalid name *) + END + ELSE + loc.res := 1 (* invalid locator *) + END + END Rename; + + PROCEDURE (d: Directory) SameFile (loc0: Files.Locator; name0: Files.Name; loc1: Files.Locator; name1: Files.Name): BOOLEAN; + VAR ok: BOOLEAN; a0, a1: NativeName; s0, s1: sysstat.struct_stat; err: INTEGER; + BEGIN + ASSERT(loc0 # NIL, 20); + ASSERT(name0 # "", 21); + ASSERT(loc1 # NIL, 22); + ASSERT(name1 # "", 23); + ok := FALSE; + WITH loc0: Locator DO + WITH loc1: Locator DO + IF IsName(name0) & IsName(name1) THEN + HostLang.StringToHost(loc0.path + "/" + name0, a0, FALSE, err); + IF err = 0 THEN + err := macro.stat(a0, s0); + IF err = 0 THEN + HostLang.StringToHost(loc1.path + "/" + name1, a1, FALSE, err); + IF err = 0 THEN + err := macro.stat(a1, s1); + IF err = 0 THEN + ok := s0.st_ino = s1.st_ino + END + END + END + END + END + ELSE (* don't trap *) + END + ELSE (* don't trap *) + END; + RETURN ok + END SameFile; + + PROCEDURE IsDir (IN s: sysstat.struct_stat): BOOLEAN; + BEGIN + RETURN BITS(s.st_mode) * BITS(sysstat.S_IFMT) = BITS(sysstat.S_IFDIR) + END IsDir; + + PROCEDURE GetAttr (IN path: NativeName; IN name: FullName; s: sysstat.struct_stat): SET; + VAR attr: SET; + BEGIN + attr := {}; + IF name[0] = "." THEN INCL(attr, Files.hidden) END; + IF BITS(s.st_mode) * BITS(sysstat.S_IXOTH) # {} THEN INCL(attr, 16) END; + IF BITS(s.st_mode) * BITS(sysstat.S_IWOTH) # {} THEN INCL(attr, 17) END; + IF BITS(s.st_mode) * BITS(sysstat.S_IROTH) # {} THEN INCL(attr, 18) END; + IF BITS(s.st_mode) * BITS(sysstat.S_IXGRP) # {} THEN INCL(attr, 19) END; + IF BITS(s.st_mode) * BITS(sysstat.S_IWGRP) # {} THEN INCL(attr, 20) END; + IF BITS(s.st_mode) * BITS(sysstat.S_IRGRP) # {} THEN INCL(attr, 21) END; + IF BITS(s.st_mode) * BITS(sysstat.S_IXUSR) # {} THEN INCL(attr, 22) END; + IF BITS(s.st_mode) * BITS(sysstat.S_IWUSR) # {} THEN INCL(attr, 23) END; + IF BITS(s.st_mode) * BITS(sysstat.S_IRUSR) # {} THEN INCL(attr, 24) END; + IF BITS(s.st_mode) * BITS(sysstat.S_ISVTX) # {} THEN INCL(attr, 25) END; + IF BITS(s.st_mode) * BITS(sysstat.S_ISGID) # {} THEN INCL(attr, 26) END; + IF BITS(s.st_mode) * BITS(sysstat.S_ISUID) # {} THEN INCL(attr, 27) END; + (* !!! better to check real access? *) + IF BITS(s.st_mode) * BITS(sysstat.S_IRUSR) # {} THEN INCL(attr, Files.readOnly) END; + RETURN attr + END GetAttr; + + PROCEDURE (d: Directory) FileList (loc: Files.Locator): Files.FileInfo; + VAR + pathname: NativeName; + name: FullName; + err: INTEGER; + p: dirent.PDIR; + ent: dirent.Pstruct_dirent; + s: sysstat.struct_stat; + res: sysstat.int; + tm: time.Pstruct_tm; + h, t: Files.FileInfo; + BEGIN + ASSERT(loc # NIL, 20); + WITH loc: Locator DO + HostLang.StringToHost(loc.path, pathname, FALSE, err); + IF err = 0 THEN + p := dirent.opendir(pathname); + IF p # NIL THEN + ent := dirent.readdir(p); + WHILE ent # NIL DO + HostLang.HostToString(ent.d_name, name, FALSE, err); + IF err = 0 THEN + HostLang.StringToHost(loc.path + "/" + name, pathname, FALSE, err); + IF err = 0 THEN + res := macro.stat(pathname, s); + IF (res = 0) & ~IsDir(s) THEN + IF h = NIL THEN NEW(h); t := h + ELSE NEW(t.next); t := t.next + END; + t.name := name$; + t.type := ""; (* ??? *) + t.length := s.st_size; + tm := time.localtime(s.st_mtim.tv_sec); + IF tm # NIL THEN + t.modified.year := tm.tm_year + 1900; + t.modified.month := tm.tm_mon + 1; + t.modified.day := tm.tm_mday; + t.modified.hour := tm.tm_hour; + t.modified.minute := tm.tm_min; + t.modified.second := tm.tm_sec + END; + t.attr := GetAttr(pathname, name, s) + END + END + END; + ent := dirent.readdir(p) + END; + res := dirent.closedir(p); + ASSERT(res = 0, 100); + loc.res := 0 (* no error *) + ELSE + GetError(loc.res) + END + ELSE + loc.res := 1 (* invalid name *) + END + ELSE + loc.res := 1 (* invalid locator *) + END; + RETURN h + END FileList; + + PROCEDURE (d: Directory) LocList (loc: Files.Locator): Files.LocInfo; + VAR + pathname: NativeName; + name: FullName; + err: INTEGER; + p: dirent.PDIR; + ent: dirent.Pstruct_dirent; + s: sysstat.struct_stat; + res: sysstat.int; + tm: time.Pstruct_tm; + h, t: Files.LocInfo; + BEGIN + ASSERT(loc # NIL, 20); + WITH loc: Locator DO + HostLang.StringToHost(loc.path, pathname, FALSE, err); + IF err = 0 THEN + p := dirent.opendir(pathname); + IF p # NIL THEN + ent := dirent.readdir(p); + WHILE ent # NIL DO + HostLang.HostToString(ent.d_name, name, FALSE, err); + IF err = 0 THEN + HostLang.StringToHost(loc.path + "/" + name, pathname, FALSE, err); + IF err = 0 THEN + res := macro.stat(pathname, s); + IF (res = 0) & IsDir(s) & (name # ".") & (name # "..") THEN + IF h = NIL THEN NEW(h); t := h + ELSE NEW(t.next); t := t.next + END; + t.name := name$; + t.attr := GetAttr(pathname, name, s) + END + END + END; + ent := dirent.readdir(p) + END; + res := dirent.closedir(p); + ASSERT(res = 0, 100); + loc.res := 0 (* no error *) + ELSE + GetError(loc.res) + END + ELSE + loc.res := 1 (* invlid name *) + END + ELSE + loc.res := 1 (* invalid locator *) + END; + RETURN h + END LocList; + + PROCEDURE (d: Directory) GetFileName (name: Files.Name; type: Files.Type; OUT filename: Files.Name); + BEGIN + filename := name + "." + type + END GetFileName; + + (* Misc *) + + (* !!! implement NofFiles *) + (* !!! implement GetModDate & GetName *) + + PROCEDURE SetRootDir* (x: ARRAY OF CHAR); + BEGIN + root := NewLocator(x) + END SetRootDir; + + PROCEDURE UseAsk*; + BEGIN + ignoreAsk := FALSE + END UseAsk; + + PROCEDURE IgnoreAsk*; + BEGIN + ignoreAsk := TRUE + END IgnoreAsk; + + PROCEDURE Init; + VAR d: Directory; + BEGIN + SetRootDir("."); + NEW(d); Files.SetDir(d) + END Init; + +BEGIN + Init +END HostFiles. diff --git a/src/posix/Host/Mod/Lang.cp b/src/posix/Host/Mod/Lang.cp new file mode 100644 index 0000000..836888e --- /dev/null +++ b/src/posix/Host/Mod/Lang.cp @@ -0,0 +1,167 @@ +MODULE HostLang; + + IMPORT S := SYSTEM, Kernel, stdlib := C99stdlib, locale := C99locale, + iconv := C99iconv, errno := C99errno, macro := C99macro; + + CONST + maxLen = 32; + + VAR + lang-, country-, encoding-: ARRAY maxLen OF CHAR; + c2sc, sc2c, invalid: iconv.iconv_t; + + (* PEP 383 *) + + PROCEDURE StringToHost* (IN in: ARRAY OF CHAR; OUT out: ARRAY OF SHORTCHAR; low: BOOLEAN; OUT res: INTEGER); + VAR i, j, err: INTEGER; maxlen, len, count: iconv.size_t; inadr, outadr: Kernel.ADDRESS; ch: SHORTCHAR; + BEGIN + ASSERT(c2sc # invalid, 100); + i := 0; err := 0; + outadr := S.ADR(out[0]); + maxlen := LEN(out) - 1; + WHILE (err = 0) & (in[i] # 0X) DO + j := i; + WHILE (in[i] # 0X) & ((in[i] < 0D800X) OR (in[i] > 0D8FFX)) DO INC(i) END; + len := (i - j) * 2; + WHILE (err = 0) & (len > 0) & (maxlen > 0) DO + inadr := S.ADR(in[j]); + count := iconv.iconv(c2sc, inadr, len, outadr, maxlen); + IF count # 0 THEN + CASE macro.errno() OF + | errno.EILSEQ: + (* !!! HALT(101)*) (* invalid input char *) + IF maxlen < 1 THEN + err := 1 + ELSE + ch := "?"; + S.PUT(outadr, ch); INC(outadr); DEC(maxlen); + INC(j); DEC(len, 2) + END + | errno.E2BIG: err := 1 (* unexpected end of out *) + | errno.EINVAL: HALT(102) (* unexpected end of input *) + | errno.EBADF: HALT(103) (* invalid iconv descriptor *) + ELSE HALT(104) (* unknown error *) + END + END + END; + WHILE (err = 0) & (in[i] >= 0D800X) & (in[i] <= 0D8FFX) DO + IF maxlen < 1 THEN + err := 1 + ELSE + ch := SHORT(CHR(ORD(in[i]) MOD 256)); + IF low OR (ch > 7FX) THEN + S.PUT(outadr, ch); INC(outadr); DEC(maxlen); + INC(i) + ELSE + err := 3 (* invalid char *) + END + END + END + END; + ch := 0X; + S.PUT(outadr, ch); + res := err + END StringToHost; + + PROCEDURE HostToString* (IN in: ARRAY OF SHORTCHAR; OUT out: ARRAY OF CHAR; low: BOOLEAN; OUT res: INTEGER); + VAR err: INTEGER; maxin, maxout, count: iconv.size_t; inadr, outadr: Kernel.ADDRESS; sch: SHORTCHAR; ch: CHAR; + BEGIN + ASSERT(sc2c # invalid, 100); + err := 0; + inadr := S.ADR(in[0]); + outadr := S.ADR(out[0]); + maxin := LEN(in$); maxout := LEN(out) * 2 - 2; + WHILE (err = 0) & (maxout > 1) & (maxin > 0) DO + count := iconv.iconv(sc2c, inadr, maxin, outadr, maxout); + IF count # 0 THEN + CASE macro.errno() OF + | errno.EILSEQ, errno.EINVAL, errno.E2BIG: + IF maxout < 2 THEN + err := 1 (* unexpected end of output buffer *) + ELSIF maxin < 1 THEN + err := 2 (* unexpected end of input buffer *) + ELSE + S.GET(inadr, sch); INC(inadr); DEC(maxin); + ch := CHR(0D800H + ORD(sch)); + IF low OR (ch > 7FX) THEN + S.PUT(outadr, ch); INC(outadr, 2); DEC(maxout, 2) + ELSE + err := 3 (* invalid char *) + END + END + | errno.EBADF: HALT(101) + ELSE HALT(102) + END + END + END; + ch := 0X; + S.PUT(outadr, ch); + res := err + END HostToString; + + PROCEDURE Init; + VAR p: POINTER TO ARRAY [untagged] OF SHORTCHAR; i, j: INTEGER; enc: ARRAY 32 OF SHORTCHAR; + BEGIN + invalid := S.VAL(iconv.iconv_t, -1); + p := locale.setlocale(locale.LC_ALL, ""); + IF p = NIL THEN + p := stdlib.getenv("LANG"); + IF p = NIL THEN + p := "" + END + END; + i := 0; j := 0; + WHILE (p[i] # 0X) & (p[i] # "_") & (p[i] # ".") DO + lang[j] := p[i]; + INC(i); INC(j) + END; + lang[j] := 0X; + IF p[i] = "_" THEN + INC(i); j := 0; + WHILE (p[i] # 0X) & (p[i] # ".") DO + country[j] := p[i]; + INC(i); INC(j) + END; + country[j] := 0X + END; + enc := "ASCII"; + IF p[i] = "." THEN + INC(i); j := 0; + WHILE p[i] # 0X DO + enc[j] := p[i]; + INC(i); INC(j) + END; + enc[j] := 0X + END; + IF (lang = "C") OR (lang = "POSIX") THEN + lang := "" + END; + sc2c := invalid; c2sc := invalid; + IF Kernel.littleEndian THEN sc2c := iconv.iconv_open("UCS-2LE", enc) + ELSE sc2c := iconv.iconv_open("UCS-2BE", enc) + END; + IF sc2c = invalid THEN enc := "ASCII"; + IF Kernel.littleEndian THEN sc2c := iconv.iconv_open("UCS-2LE", enc) + ELSE sc2c := iconv.iconv_open("UCS-2BE", enc) + END; + ASSERT(c2sc # invalid, 100) (* ascii to ucs2 not supported? *) + END; + IF Kernel.littleEndian THEN c2sc := iconv.iconv_open(enc, "UCS-2LE") + ELSE c2sc := iconv.iconv_open(enc, "UCS-2BE"); + END; + ASSERT(c2sc # invalid, 101); (* ucs2 to ascii not supported? *) + encoding := enc$ + END Init; + + PROCEDURE Fin; + VAR res: iconv.int; + BEGIN + res := iconv.iconv_close(sc2c); sc2c := invalid; + res := iconv.iconv_close(c2sc); c2sc := invalid + END Fin; + +BEGIN + Init +CLOSE + Fin +END HostLang. -- 2.29.2