ref: ddd49d6806fbc3f2c9128c38d6b703e9cd6b7225
parent: 17c3518fa9ddc3695dd21e35e360ba78a289374a
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Tue Jan 7 21:07:02 EST 2025
crude initial MacOS 9.x (PowerPC) port
--- a/3rd/fn.c
+++ b/3rd/fn.c
@@ -118,7 +118,7 @@
Tbl *
Tsetl(Tbl *tbl, const char *key, size_t len, void *val)
{
- assert(!Tindex_branch((Tindex)val) && len <= Tmaxlen);
+ assert(!Tindex_branch((Tindex)(uintptr_t)val) && len <= Tmaxlen);
if(val == nil)
return Tdell(tbl, key, len);
// First leaf in an empty tbl?
--- a/3rd/fn.h
+++ b/3rd/fn.h
@@ -49,16 +49,16 @@
} \
struct dummy
-Tset_field((void *), ptr, Trie *, twigs);
-Tset_field((Tindex), index, Tindex, index);
-Tset_field((void *)(uint64_t), ptr, const char *, key);
-Tset_field((Tindex), index, void *, val);
+Tset_field((void *), ptr, Trie *, twigs);
+Tset_field((Tindex), index, Tindex, index);
+Tset_field((void *)(uintptr_t), ptr, const char *, key);
+Tset_field((Tindex)(uintptr_t), index, void *, val);
static inline bool Tindex_branch(Tindex i);
static inline bool isbranch(Trie *t)
{
- return(Tindex_branch(t->index));
+ return Tindex_branch(t->index);
}
#define Tbranch(t) assert(isbranch(t))
@@ -75,7 +75,7 @@
Tcheck_get(Trie *, Tbranch, twigs, t->ptr);
Tcheck_get(const char *, Tleaf, key, t->ptr);
-Tcheck_get(void *, Tleaf, val, (void*)t->index);
+Tcheck_get(void *, Tleaf, val, (void*)(uintptr_t)t->index);
// index word layout
--- /dev/null
+++ b/3rd/mp/mp.h
@@ -1,0 +1,178 @@
+#pragma once
+
+#ifdef BITS64
+typedef uint64_t mpdigit;
+#else
+typedef uint32_t mpdigit;
+#endif
+
+typedef union FPdbleword FPdbleword;
+union FPdbleword
+{
+ double x;
+ struct {
+#if BYTE_ORDER == LITTLE_ENDIAN
+ uint32_t lo;
+ uint32_t hi;
+#else
+ uint32_t hi;
+ uint32_t lo;
+#endif
+ };
+};
+
+#define mpdighi (((mpdigit)1)<<(Dbits-1))
+#define DIGITS(x) ((int)(x) >= -(Dbits-1) ? ((Dbits - 1 + (x))/Dbits) : 0)
+
+extern int dec16(uint8_t*, int, char*, int);
+extern int enc16(char*, int, uint8_t*, int);
+extern mpdigit dec16chr(int);
+extern int enc16chr(int);
+
+/*
+ * the code assumes mpdigit to be at least an int
+ * mpdigit must be an atomic type. mpdigit is defined
+ * in the architecture specific u.h
+ */
+typedef struct mpint mpint;
+
+struct mpint
+{
+ mpdigit *p;
+ uint32_t size; /* allocated digits */
+ uint32_t top; /* significant digits */
+ int sign; /* +1 or -1 */
+ int flags;
+};
+
+enum
+{
+ MPstatic= 0x01, /* static constant */
+ MPnorm= 0x02, /* normalization status */
+ MPtimesafe= 0x04, /* request time invariant computation */
+
+ Dbytes= sizeof(mpdigit), /* bytes per digit */
+ Dbits= Dbytes*8 /* bits per digit */
+};
+
+/* allocation */
+void mpsetminbits(int n); /* newly created mpint's get at least n bits */
+mpint* mpnew(int n); /* create a new mpint with at least n bits */
+void mpfree(mpint *b);
+void mpbits(mpint *b, int n); /* ensure that b has at least n bits */
+mpint* mpnorm(mpint *b); /* dump leading zeros */
+mpint* mpcopy(mpint *b);
+void mpassign(mpint *old, mpint *new);
+
+/* random bits */
+mpint* mprand(int bits, void (*gen)(uint8_t*, int), mpint *b);
+/* return uniform random [0..n-1] */
+mpint* mpnrand(mpint *n, void (*gen)(uint8_t*, int), mpint *b);
+
+/* conversion */
+mpint* strtomp(const char*, char**, int, mpint*); /* ascii */
+char* mptoa(mpint*, int, char*, int);
+mpint* letomp(uint8_t*, uint32_t, mpint*); /* byte array, little-endian */
+int mptole(mpint*, uint8_t*, uint32_t, uint8_t**);
+void mptolel(mpint *b, uint8_t *p, int n);
+mpint* betomp(uint8_t*, uint32_t, mpint*); /* byte array, big-endian */
+int mptobe(mpint*, uint8_t*, uint32_t, uint8_t**);
+void mptober(mpint *b, uint8_t *p, int n);
+uint32_t mptoui(mpint*); /* unsigned int */
+mpint* uitomp(uint32_t, mpint*);
+int mptoi(mpint*); /* int */
+mpint* itomp(int, mpint*);
+uint64_t mptouv(mpint*); /* unsigned int64_t */
+mpint* uvtomp(uint64_t, mpint*);
+int64_t mptov(mpint*); /* int64_t */
+mpint* vtomp(int64_t, mpint*);
+double mptod(mpint*); /* double */
+mpint* dtomp(double, mpint*);
+
+/* divide the 2 digit dividend by the one digit divisor and stick in quotient */
+/* we assume that the result is one digit - overflow is all 1's */
+void mpdigdiv(mpdigit *dividend, mpdigit divisor, mpdigit *quotient);
+
+/* in the following, the result mpint may be */
+/* the same as one of the inputs. */
+void mpadd(mpint *b1, mpint *b2, mpint *sum); /* sum = b1+b2 */
+void mpsub(mpint *b1, mpint *b2, mpint *diff); /* diff = b1-b2 */
+void mpleft(mpint *b, int shift, mpint *res); /* res = b<<shift */
+void mpright(mpint *b, int shift, mpint *res); /* res = b>>shift */
+void mpmul(mpint *b1, mpint *b2, mpint *prod); /* prod = b1*b2 */
+void mpexp(mpint *b, mpint *e, mpint *m, mpint *res); /* res = b**e mod m */
+void mpmod(mpint *b, mpint *m, mpint *remainder); /* remainder = b mod m */
+
+/* logical operations */
+void mpand(mpint *b1, mpint *b2, mpint *res);
+void mpbic(mpint *b1, mpint *b2, mpint *res);
+void mpor(mpint *b1, mpint *b2, mpint *res);
+void mpnot(mpint *b, mpint *res);
+void mpxor(mpint *b1, mpint *b2, mpint *res);
+void mpasr(mpint *b, int shift, mpint *res);
+
+/* modular arithmetic, time invariant when 0≤b1≤m-1 and 0≤b2≤m-1 */
+void mpmodadd(mpint *b1, mpint *b2, mpint *m, mpint *sum); /* sum = b1+b2 % m */
+void mpmodsub(mpint *b1, mpint *b2, mpint *m, mpint *diff); /* diff = b1-b2 % m */
+void mpmodmul(mpint *b1, mpint *b2, mpint *m, mpint *prod); /* prod = b1*b2 % m */
+
+/* quotient = dividend/divisor, remainder = dividend % divisor */
+void mpdiv(mpint *dividend, mpint *divisor, mpint *quotient, mpint *remainder);
+
+/* return neg, 0, pos as b1-b2 is neg, 0, pos */
+int mpcmp(mpint *b1, mpint *b2);
+
+/* res = s != 0 ? b1 : b2 */
+void mpsel(int s, mpint *b1, mpint *b2, mpint *res);
+
+/* extended gcd return d, x, and y, s.t. d = gcd(a,b) and ax+by = d */
+void mpextendedgcd(mpint *a, mpint *b, mpint *d, mpint *x, mpint *y);
+
+/* res = b**-1 mod m */
+void mpinvert(mpint *b, mpint *m, mpint *res);
+
+/* bit counting */
+uint32_t mpsignif(mpint*); /* number of sigificant bits in mantissa */
+uint32_t mplowbits0(mpint*); /* k, where n = 2**k * q for odd q */
+
+/* well known constants */
+extern mpint *mpzero, *mpone, *mptwo;
+
+/* sum[0:alen] = a[0:alen-1] + b[0:blen-1] */
+/* prereq: alen >= blen, sum has room for alen+1 digits */
+void mpvecadd(mpdigit *a, int alen, mpdigit *b, int blen, mpdigit *sum);
+
+/* diff[0:alen-1] = a[0:alen-1] - b[0:blen-1] */
+/* prereq: alen >= blen, diff has room for alen digits */
+void mpvecsub(mpdigit *a, int alen, mpdigit *b, int blen, mpdigit *diff);
+
+/* p[0:n] += m * b[0:n-1] */
+/* prereq: p has room for n+1 digits */
+void mpvecdigmuladd(mpdigit *b, int n, mpdigit m, mpdigit *p);
+
+/* p[0:n] -= m * b[0:n-1] */
+/* prereq: p has room for n+1 digits */
+int mpvecdigmulsub(mpdigit *b, int n, mpdigit m, mpdigit *p);
+
+/* p[0:alen+blen-1] = a[0:alen-1] * b[0:blen-1] */
+/* prereq: alen >= blen, p has room for m*n digits */
+void mpvecmul(mpdigit *a, int alen, mpdigit *b, int blen, mpdigit *p);
+void mpvectsmul(mpdigit *a, int alen, mpdigit *b, int blen, mpdigit *p);
+
+/* sign of a - b or zero if the same */
+int mpveccmp(mpdigit *a, int alen, mpdigit *b, int blen);
+int mpvectscmp(mpdigit *a, int alen, mpdigit *b, int blen);
+
+/* playing with magnitudes */
+int mpmagcmp(mpint *b1, mpint *b2);
+void mpmagadd(mpint *b1, mpint *b2, mpint *sum); /* sum = b1+b2 */
+void mpmagsub(mpint *b1, mpint *b2, mpint *sum); /* sum = b1+b2 */
+
+/* fast field arithmetic */
+typedef struct Mfield Mfield;
+
+struct Mfield
+{
+ mpint m;
+ int (*reduce)(Mfield*, mpint*, mpint*);
+};
--- a/3rd/mp/mpadd.c
+++ b/3rd/mp/mpadd.c
@@ -1,4 +1,5 @@
#include "platform.h"
+#include "mp.h"
// sum = abs(b1) + abs(b2), i.e., add the magnitudes
void
--- a/3rd/mp/mpaux.c
+++ b/3rd/mp/mpaux.c
@@ -1,4 +1,5 @@
#include "platform.h"
+#include "mp.h"
static mpdigit _mptwodata[1] = { 2 };
static mpint _mptwo =
--- a/3rd/mp/mpcmp.c
+++ b/3rd/mp/mpcmp.c
@@ -1,4 +1,5 @@
#include "platform.h"
+#include "mp.h"
// return neg, 0, pos as abs(b1)-abs(b2) is neg, 0, pos
int
--- a/3rd/mp/mpdigdiv.c
+++ b/3rd/mp/mpdigdiv.c
@@ -1,4 +1,5 @@
#include "platform.h"
+#include "mp.h"
//
// divide two digits by one and return quotient
--- a/3rd/mp/mpdiv.c
+++ b/3rd/mp/mpdiv.c
@@ -1,4 +1,5 @@
#include "platform.h"
+#include "mp.h"
// division ala knuth, seminumerical algorithms, pp 237-238
// the numbers are stored backwards to what knuth expects so j
--- a/3rd/mp/mpfmt.c
+++ b/3rd/mp/mpfmt.c
@@ -1,4 +1,5 @@
#include "platform.h"
+#include "mp.h"
static int
topow2(mpint *b, char *buf, int len, int s)
--- a/3rd/mp/mpleft.c
+++ b/3rd/mp/mpleft.c
@@ -1,4 +1,5 @@
#include "platform.h"
+#include "mp.h"
// res = b << shift
void
--- a/3rd/mp/mplogic.c
+++ b/3rd/mp/mplogic.c
@@ -1,4 +1,5 @@
#include "platform.h"
+#include "mp.h"
/*
mplogic calculates b1|b2 subject to the
--- a/3rd/mp/mpmul.c
+++ b/3rd/mp/mpmul.c
@@ -1,4 +1,5 @@
#include "platform.h"
+#include "mp.h"
//
// from knuth's 1969 seminumberical algorithms, pp 233-235 and pp 258-260
--- a/3rd/mp/mpright.c
+++ b/3rd/mp/mpright.c
@@ -1,4 +1,5 @@
#include "platform.h"
+#include "mp.h"
// res = b >> shift
void
--- a/3rd/mp/mpsub.c
+++ b/3rd/mp/mpsub.c
@@ -1,4 +1,5 @@
#include "platform.h"
+#include "mp.h"
// diff = abs(b1) - abs(b2), i.e., subtract the magnitudes
void
--- a/3rd/mp/mptobe.c
+++ b/3rd/mp/mptobe.c
@@ -1,4 +1,5 @@
#include "platform.h"
+#include "mp.h"
// convert an mpint into a big endian byte array (most significant byte first; left adjusted)
// return number of bytes converted
--- a/3rd/mp/mptober.c
+++ b/3rd/mp/mptober.c
@@ -1,4 +1,5 @@
#include "platform.h"
+#include "mp.h"
void
mptober(mpint *b, uint8_t *p, int n)
--- a/3rd/mp/mptod.c
+++ b/3rd/mp/mptod.c
@@ -1,4 +1,5 @@
#include "platform.h"
+#include "mp.h"
extern double D_PINF, D_NINF;
--- a/3rd/mp/mptoi.c
+++ b/3rd/mp/mptoi.c
@@ -1,4 +1,5 @@
#include "platform.h"
+#include "mp.h"
/*
* this code assumes that mpdigit is at least as
--- a/3rd/mp/mptoui.c
+++ b/3rd/mp/mptoui.c
@@ -1,4 +1,5 @@
#include "platform.h"
+#include "mp.h"
/*
* this code assumes that mpdigit is at least as
--- a/3rd/mp/mptouv.c
+++ b/3rd/mp/mptouv.c
@@ -1,4 +1,5 @@
#include "platform.h"
+#include "mp.h"
#define VLDIGITS (int)(sizeof(int64_t)/Dbytes)
--- a/3rd/mp/mptov.c
+++ b/3rd/mp/mptov.c
@@ -1,4 +1,5 @@
#include "platform.h"
+#include "mp.h"
#define VLDIGITS (int)(sizeof(int64_t)/Dbytes)
--- a/3rd/mp/mpvecadd.c
+++ b/3rd/mp/mpvecadd.c
@@ -1,4 +1,5 @@
#include "platform.h"
+#include "mp.h"
// prereq: alen >= blen, sum has at least blen+1 digits
void
--- a/3rd/mp/mpveccmp.c
+++ b/3rd/mp/mpveccmp.c
@@ -1,4 +1,5 @@
#include "platform.h"
+#include "mp.h"
int
mpveccmp(mpdigit *a, int alen, mpdigit *b, int blen)
--- a/3rd/mp/mpvecdigmuladd.c
+++ b/3rd/mp/mpvecdigmuladd.c
@@ -1,4 +1,5 @@
#include "platform.h"
+#include "mp.h"
#define LO(x) ((x) & ((((mpdigit)1)<<(Dbits/2))-1))
#define HI(x) ((x) >> (Dbits/2))
--- a/3rd/mp/mpvecsub.c
+++ b/3rd/mp/mpvecsub.c
@@ -1,4 +1,5 @@
#include "platform.h"
+#include "mp.h"
// prereq: a >= b, alen >= blen, diff has at least alen digits
void
--- a/3rd/mp/mpvectscmp.c
+++ b/3rd/mp/mpvectscmp.c
@@ -1,4 +1,5 @@
#include "platform.h"
+#include "mp.h"
int
mpvectscmp(mpdigit *a, int alen, mpdigit *b, int blen)
--- a/3rd/mp/strtomp.c
+++ b/3rd/mp/strtomp.c
@@ -1,4 +1,5 @@
#include "platform.h"
+#include "mp.h"
static const char *
frompow2(const char *a, mpint *b, int s)
--- a/3rd/mp/u16.c
+++ b/3rd/mp/u16.c
@@ -1,4 +1,5 @@
#include "platform.h"
+#include "mp.h"
#define between(x,min,max) (((min-1-x) & (x-max-1))>>8)
--- a/3rd/utf/rune.c
+++ b/3rd/utf/rune.c
@@ -1,4 +1,5 @@
#include "platform.h"
+#include "utf.h"
enum
{
--- a/3rd/utf/runeistype.c
+++ b/3rd/utf/runeistype.c
@@ -1,4 +1,5 @@
#include "platform.h"
+#include "utf.h"
#include "runeistypedata"
int
--- a/3rd/utf/runetotype.c
+++ b/3rd/utf/runetotype.c
@@ -1,4 +1,5 @@
#include "platform.h"
+#include "utf.h"
#include "runetotypedata"
Rune
--- /dev/null
+++ b/3rd/utf/utf.h
@@ -1,0 +1,27 @@
+#pragma once
+
+enum {
+ Runeself = 0x80,
+ Runeerror = 0xfffd,
+ Runemax = 0x10ffff,
+ UTFmax = 4,
+};
+
+typedef uint32_t Rune;
+
+int chartorune(Rune *rune, const char *str);
+int runetochar(char *str, const Rune *rune);
+int runenlen(const Rune *r, int nrune);
+int fullrune(const char *str, int n);
+int runelen(Rune c);
+Rune tolowerrune(Rune c);
+Rune toupperrune(Rune c);
+Rune totitlerune(Rune c);
+int islowerrune(Rune c);
+int isupperrune(Rune c);
+int isalpharune(Rune c);
+int istitlerune(Rune c);
+int isspacerune(Rune c);
+int isdigitrune(Rune c);
+
+int utfnlen(const char *s, long m);
--- a/3rd/utf/utfnlen.c
+++ b/3rd/utf/utfnlen.c
@@ -1,4 +1,5 @@
#include "platform.h"
+#include "utf.h"
int
utfnlen(const char *s, long m)
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
This is a reanimation of
https://github.com/lambdaconservatory/femtolisp with bigger plans.
-Supported OS: [9front](http://9front.org), Unix-like operating systems (OpenBSD, NetBSD, Linux, etc).
+Supported OS: [9front](http://9front.org), Unix-like operating systems (OpenBSD, NetBSD, Linux, etc), MacOS 9.x.
Supported CPUs: any decent 32 or 64-bit, little or big endian.
@@ -42,6 +42,19 @@
### Plan 9
mk all test
+
+### MacOS 9.x (PowerPC)
+
+Install and build [Retro68](https://github.com/autc04/Retro68).
+
+ ln -s path-to-Retro68-build/toolchain cross/macos-toolchain
+ meson setup build . -Dbuildtype=minsize --cross-file cross/powerpc-apple.txt -Dstrip=true
+ ninja -C build
+
+`build/flisp.bin` can be then copied to your MacOS, it contains the executable.
+
+NOTE: this isn't a full-fledged port and has a rather low priority at the moment. Some things
+are not working.
## Characteristics
--- /dev/null
+++ b/cross/powerpc-apple.txt
@@ -1,0 +1,40 @@
+[constants]
+toolchain = '@DIRNAME@/macos-toolchain/'
+path = toolchain + 'bin/'
+prefix = path + 'powerpc-apple-macos-'
+ add_project_arguments(
+ '-fdata-sections',
+ '-ffunction-sections',
+ '-D__macos__',
+ language: 'c',
+ )
+ add_project_link_arguments(
+ '-Wl,-gc-sections',
+ language: 'cpp',
+ )
+
+[built-in options]
+c_args = ['-fdata-sections', '-ffunction-sections', '-D__macos__']
+cpp_link_args = ['-Wl,-gc-sections']
+
+[properties]
+rincludes = toolchain + 'RIncludes'
+makepef = path + 'MakePEF'
+rez = path + 'Rez'
+
+[binaries]
+c = prefix + 'gcc'
+as = prefix + 'as'
+ar = prefix + 'ar'
+cpp = prefix + 'g++'
+pkg-config = prefix + 'pkg-config'
+strip = prefix + 'strip'
+
+[host_machine]
+system = 'macos'
+cpu_family = 'ppc'
+cpu = 'ppc'
+endian = 'big'
+
+[project options]
+build-tests = 'disabled'
--- a/flisp.boot
+++ b/flisp.boot
@@ -17,7 +17,7 @@
0)
*properties* #table(*funvars* #table(>= ((a . rest)) void? ((x)) length= ((lst n)) help ((term)) lz-unpack ((data
:to destination)
- (data :size decompressed-bytes)) = ((a . rest)) <= ((a . rest)) car ((lst)) /= ((a . rest)) void (rest) *prompt* (nil) nan? ((x)) lz-pack ((data
+ (data :size decompressed-bytes)) = ((a . rest)) <= ((a . rest)) car ((lst)) /= ((a . rest)) void (rest) *prompt* (#f) nan? ((x)) lz-pack ((data
(level 0))) cons? ((value)) vm-stats (nil) * ((number…)) cdr ((lst)) > ((a . rest)) + ((number…))) *doc* #table(+ "Return sum of the numbers or 0 with no arguments." >= "Return #t if the arguments are in non-increasing order (previous\none is greater than or equal to the next one)." void? "Return #t if x is #<void> and #f otherwise." length= "Bounded length test.\nUse this instead of (= (length lst) n), since it avoids unnecessary\nwork and always terminates." help "Display documentation for the specified term, if available." lz-unpack "Return decompressed data previously compressed using lz-pack.\nEither destination for the decompressed data or the expected size of\nthe decompressed data must be specified. In the latter case a new\narray is allocated." = "Return #t if the arguments are equal." <= "Return #t if the arguments are in non-decreasing order (previous\none is less than or equal to the next one)." *builtins* "VM instructions as closures." car "Returns the first element of a list or nil if not available." /= "Return #t if not all arguments are equal. Shorthand for (not (= …))." void "Return the constant #<void> while ignoring any arguments.\n#<void> is mainly used when a function has side effects but does not\nproduce any meaningful value to return, so even though #t or nil could\nbe returned instead, in case of #<void> alone, REPL will not print\nit." arg-counts "VM instructions mapped to their expected arguments count." *prompt* "Function called by REPL to signal the user input is required.\nDefault function prints \"#;> \"." nan? "Return #t if the argument is NaN, regardless of the sign." Instructions "VM instructions mapped to their encoded byte representation." lz-pack "Return data compressed using Lempel-Ziv.\nThe data must be an array, returned value will have the same type.\nThe optional level is between 0 and 10. With level 0 a simple LZSS\nusing hashing will be performed. Levels between 1 and 9 offer a\ntrade-off between time/space and ratio. Level 10 is optimal but very\nslow." vm-stats "Print various VM-related information, such as the number of GC calls\nso far, heap and stack size, etc." cons? "Returns #t if the value is a cons cell." * "Return product of the numbers or 1 with no arguments." > "Return #t if the arguments are in strictly decreasing order (previous\none is greater than the next one)." cdr "Returns the tail of a list or nil if not available." *properties* "All properties of symbols recorded with putprop are recorded in this table."))
*runestring-type* (array rune) *string-type* (array byte)
*syntax-environment* #table(bcode:nconst #fn("7000n1200r2e3:" #(aref)) with-input-from #fn("<000z12021e1220e2e1e12315163:" #(#fn(nconc)
@@ -56,13 +56,13 @@
> #fn(";000z1\x8d\x8a6862086>1_486<^10162:" #(#fn("7000n21V;IE041<0L2;3;04A<1<1=62:" #())) >)
>= #fn(";000z1\x8d\x8a6862086>1_486<^10162:" #(#fn("7000n21V;IL0401<L2;I5040\x8e340O:A<1<1=62:" #())) >=)
Instructions #table(call.l 81 trycatch 75 largc 79 loadg.l 68 aref2 23 box 90 cadr 36 argc 62 setg 71 load0 21 nan? 94 vector? 45 fixnum? 41 loadc0 17 loada0 0 div0 59 keyargs 89 call 5 loada.l 69 brt.l 50 sub2 78 add2 29 loadc.l 70 loadc 9 builtin? 43 set-car! 47 brt 25 ret 10 loadi8 66 tapply 77 loadvoid 93 loada1 1 shift 46 boolean? 39 atom? 24 cdr 13 brne.l 83 / 58 loadf 31 equal? 52 apply 54 dup 11 loadt 20 jmp.l 48 null? 38 not 35 = 60 set-cdr! 30 eq? 33 * 57 load1 27 bound? 42 brf 3 function? 44 box.l 91 < 28 brnn.l 84 jmp 16 loadv 2 for 76 lvargc 80 dummy_eof 95 + 55 brne 19 compare 61 neg 37 loadv.l 67 number? 40 vargc 74 brn 85 brbound 88 vector 63 loadc1 22 setg.l 72 cons? 18 brf.l 49 aref 92 symbol? 34 aset! 64 car 12 cons 32 tcall.l 82 - 56 brn.l 86 optargs 87 closure 14 pop 4 eqv? 51 list 53 seta 15 seta.l 73 brnn 26 loadnil 65 loadg 7 loada 8 tcall 6)
- __init_globals #fn("5000n020w1422w3424w5476w7478w947:w;:" #(#fn("6000n0702161:" #(princ
- "#;> ")) *prompt* "/" *directory-separator* "\n" *linefeed* *stdout* *output-stream* *stdin*
- *input-stream* *stderr*
- *error-stream*) __init_globals)
- __rcscript #fn("<000n0708421c360O@A08422c37023@4024^125845185;3=042685772853863B02986513907:8661:O:" #(*os-name*
- "unknown" "plan9" "home" "HOME" #fn(os-getenv) #fn(string)
- *directory-separator* ".flisprc" #fn(path-exists?) load) __rcscript)
+ __init_globals #fn("7000n07021l237022@402384w4^1425w6427w8479w:47;w<47=w>:" #(*os-name*
+ "macos" #fn("6000n0702161:" #(princ "\e[0m\e[1m#;> \e[0m"))
+ #fn("6000n0702161:" #(princ "#;> ")) *prompt* "/" *directory-separator* "\n" *linefeed* *stdout*
+ *output-stream* *stdin* *input-stream* *stderr* *error-stream*) __init_globals)
+ __rcscript #fn("=000n0708421c360O@T08422c37023@G08424c3=07526514O@4027^184;390428845185;3=0429857:2;53863B02<86513907=8661:O:" #(*os-name*
+ "unknown" "plan9" "home" "macos" princ "\e]0;femtolisp v0.999\a" "HOME" #fn(os-getenv)
+ #fn(string) *directory-separator* ".flisprc" #fn(path-exists?) load) __rcscript)
__script #fn("6000n1200>121{:" #(#fn("6000n070A61:" #(load))
#fn("6000n170051421K61:" #(top-level-exception-handler
#fn(exit)))) __script)
binary files a/flisp.boot.builtin b/flisp.boot.builtin differ
--- a/flisp.c
+++ b/flisp.c
@@ -45,7 +45,7 @@
builtin_t fptr;
}builtinspec_t;
-#ifdef NDEBUG
+#if defined(NDEBUG)
__thread
#endif
Fl *fl;
@@ -1163,7 +1163,7 @@
if(__unlikely(nargs < 2))
lerrorf(FL_ArgError, "too few arguments");
intptr_t argSP = args-FL(stack);
- assert(argSP >= 0 && argSP < FL(nstack));
+ assert(argSP >= 0 && argSP < (intptr_t)FL(nstack));
while(FL(sp)+2+1+nargs >= FL(nstack))
grow_stack();
uint32_t k = FL(sp);
@@ -1198,7 +1198,7 @@
if(__unlikely(nargs < 2))
lerrorf(FL_ArgError, "too few arguments");
intptr_t argSP = args-FL(stack);
- assert(argSP >= 0 && argSP < FL(nstack));
+ assert(argSP >= 0 && argSP < (intptr_t)FL(nstack));
if(FL(sp)+1+2*nargs >= FL(nstack))
grow_stack();
for(size_t n = 0;; n++){
@@ -1284,25 +1284,39 @@
// initialization -------------------------------------------------------------
-void
+int
fl_init(size_t initial_heapsize)
{
int i;
- fl = MEM_CALLOC(1, sizeof(*fl));
+ if((fl = MEM_CALLOC(1, sizeof(*fl))) == nil)
+ return -1;
FL(scr_width) = 100;
FL(heapsize) = initial_heapsize;
- FL(fromspace) = MEM_ALLOC(FL(heapsize));
- FL(tospace) = MEM_ALLOC(FL(heapsize));
+ if((FL(fromspace) = MEM_ALLOC(FL(heapsize))) == nil){
+failed:
+ MEM_FREE(FL(fromspace));
+ MEM_FREE(FL(tospace));
+ MEM_FREE(FL(consflags));
+ MEM_FREE(FL(stack));
+ htable_free(&FL(printconses));
+ MEM_FREE(fl);
+ return -1;
+ }
+ if((FL(tospace) = MEM_ALLOC(FL(heapsize))) == nil)
+ goto failed;
+ if((FL(consflags) = bitvector_new(FL(heapsize)/sizeof(cons_t), 1)) == nil)
+ goto failed;
+ if((htable_new(&FL(printconses), 32)) == nil)
+ goto failed;
FL(curheap) = FL(fromspace);
FL(lim) = FL(curheap)+FL(heapsize)-sizeof(cons_t);
- FL(consflags) = bitvector_new(FL(heapsize)/sizeof(cons_t), 1);
- htable_new(&FL(printconses), 32);
- comparehash_init();
FL(nstack) = 4096;
- FL(stack) = MEM_ALLOC(FL(nstack)*sizeof(value_t));
+ if((FL(stack) = MEM_ALLOC(FL(nstack)*sizeof(value_t))) == nil)
+ goto failed;
+ comparehash_init();
FL_lambda = symbol("λ", false);
FL_function = symbol("function", false);
@@ -1383,6 +1397,7 @@
table_init();
iostream_init();
compress_init();
+ return 0;
}
// top level ------------------------------------------------------------------
--- a/flisp.h
+++ b/flisp.h
@@ -1,6 +1,10 @@
#pragma once
#include "platform.h"
+#ifndef __plan9__
+#include "mp.h"
+#include "utf.h"
+#endif
#include "utf8.h"
#include "ios.h"
#include "tbl.h"
@@ -43,11 +47,13 @@
#define FIXNUM_BITS 62
#define TOP_BIT (1ULL<<63)
#define T_FIXNUM T_INT64
+#define PRIdFIXNUM PRId64
#else
typedef int32_t fixnum_t;
#define FIXNUM_BITS 30
#define TOP_BIT (1U<<31)
#define T_FIXNUM T_INT32
+#define PRIdFIXNUM PRId32
#endif
#define ALIGNED(x, sz) (((x) + (sz-1)) & (-sz))
@@ -170,7 +176,7 @@
#define POP() (FL(stack)[--FL(sp)])
bool isbuiltin(value_t x);
-void fl_init(size_t initial_heapsize);
+int fl_init(size_t initial_heapsize);
int fl_load_system_image(value_t ios);
_Noreturn void fl_exit(int status);
@@ -393,8 +399,6 @@
bool exiting;
bool grew;
- fltype_t *fsotype;
-
uint32_t *consflags;
size_t gccalls;
@@ -415,7 +419,7 @@
};
extern
-#ifdef NDEBUG
+#if defined(NDEBUG)
__thread
#endif
Fl *fl;
--- a/flmain.c
+++ b/flmain.c
@@ -39,7 +39,15 @@
ios_init_stdstreams();
mpsetminbits(sizeof(fixnum_t)*8);
- fl_init(2*1024*1024);
+#if defined(__macos__)
+ if(fl_init(INITIAL_HEAP_SIZE) != 0){
+ fprintf(stderr, "fl_init failed\n");
+ getchar();
+#else
+ if(fl_init(2*1024*1024) != 0){
+#endif
+ exit(1);
+ }
value_t f = cvalue(FL(iostreamtype), (int)sizeof(ios_t));
ios_t *s = value2c(ios_t*, f);
--- a/htable.c
+++ b/htable.c
@@ -16,9 +16,9 @@
size = nextipow2(size);
size *= 2; // 2 pointers per key/value pair
size *= 2; // aim for 50% occupancy
- h->table = MEM_ALLOC(size * sizeof(*h->table));
+ if((h->table = MEM_ALLOC(size * sizeof(*h->table))) == nil)
+ return nil;
}
- assert(h->table != nil);
h->size = size;
h->i = 0;
for(size_t i = 0; i < size; i++)
--- a/ios.c
+++ b/ios.c
@@ -22,7 +22,7 @@
return nil;
}
-#if !defined(__plan9__)
+#if !defined(__plan9__) && !defined(__macos__)
static int
_enonfatal(int err)
{
@@ -39,7 +39,7 @@
ssize_t r;
while(1){
-#if !defined(__plan9__)
+#if !defined(__plan9__) && !defined(__macos__)
errno = 0;
#endif
r = read(fd, buf, n);
@@ -47,7 +47,7 @@
*nread = (size_t)r;
break;
}
-#if defined(__plan9__)
+#if defined(__plan9__) || defined(__macos__)
return r;
#else
if(!_enonfatal(errno)){
@@ -84,7 +84,7 @@
ssize_t r;
while(1){
-#if !defined(__plan9__)
+#if !defined(__plan9__) && !defined(__macos__)
errno = 0;
#endif
r = write(fd, buf, n);
@@ -92,7 +92,7 @@
*nwritten = (size_t)r;
break;
}
-#if defined(__plan9__)
+#if defined(__plan9__) || defined(__macos__)
return r;
#else
if(!_enonfatal(errno)){
@@ -112,6 +112,7 @@
*nwritten = 0;
while(n > 0){
+ wrote = 0;
int err = _os_write(fd, buf, n, &wrote);
n -= wrote;
*nwritten += wrote;
@@ -240,6 +241,7 @@
s->state = bst_rd;
s->fpos = -1;
+ got = 0;
if(n > MOST_OF(s->maxsize)){
// doesn't fit comfortably in buffer; go direct
if(all)
@@ -906,7 +908,7 @@
return 1;
if(s->_eof)
return IOS_EOF;
-#if defined(__plan9__)
+#if defined(__plan9__) || defined(__macos__)
USED(ws);
return 1; // FIXME(sigrid): wait for input, but not too much
#else
--- /dev/null
+++ b/macos/platform.h
@@ -1,0 +1,57 @@
+#define _XOPEN_SOURCE 700
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <float.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <locale.h>
+#include <math.h>
+#include <setjmp.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+#include <wctype.h>
+#include <wchar.h>
+
+#define __os_name__ "macos"
+
+#define MEM_CALLOC(n, sz) calloc((size_t)(n), (size_t)(sz))
+#define MEM_ALLOC(n) malloc((size_t)(n))
+#define MEM_REALLOC(p, n) realloc((p), (size_t)(n))
+#define MEM_FREE(x) free(x)
+#define MEM_STRDUP(s) strdup(s)
+
+#define sadd_overflow __builtin_add_overflow
+#define sadd_overflow_64 __builtin_add_overflow
+#define smul_overflow_64 __builtin_mul_overflow
+
+#define nil NULL
+#define USED(x) ((void)(x))
+#define nelem(x) (int)(sizeof(x)/sizeof((x)[0]))
+
+#ifdef __GNUC__
+#define __unlikely(x) __builtin_expect(!!(x), 0)
+#define __likely(x) __builtin_expect(!!(x), 1)
+#define __printfmt(x, y) __attribute__((format(printf, x, y)))
+#endif
+
+#define PATHSEP '/'
+#define PATHSEPSTRING "/"
+#define PATHLISTSEP ':'
+#define PATHLISTSEPSTRING ":"
+#define ISPATHSEP(c) ((c) == '/')
+
+#ifndef BYTE_ORDER
+#error unknown byte order
+#endif
--- a/meson.build
+++ b/meson.build
@@ -42,6 +42,29 @@
language: 'c',
)
+platform = 'posix'
+
+if host_machine.system() == 'macos'
+ platform = 'macos'
+ add_languages(
+ 'cpp',
+ native: false,
+ required: true,
+ )
+ cpp = meson.get_compiler('cpp')
+ add_project_arguments(
+ '-DINITIAL_HEAP_SIZE=64*1024',
+ language: 'c',
+ )
+ extras = [cpp.find_library('RetroConsole', required: true)]
+else
+ add_project_arguments(
+ '-DINITIAL_HEAP_SIZE=2*1024*1024',
+ language: 'c',
+ )
+ extras = []
+endif
+
src = [
'3rd/fn.c',
'3rd/mt19937-64.c',
@@ -66,7 +89,7 @@
'random.c',
'read.c',
'string.c',
- 'sys_posix.c',
+ 'sys_' + platform + '.c',
'table.c',
'types.c',
'utf8.c',
@@ -128,7 +151,7 @@
],
include_directories: include_directories(
'3rd/brieflz',
- 'posix',
+ platform,
),
)
@@ -169,7 +192,7 @@
],
include_directories: include_directories(
'3rd/mp',
- 'posix',
+ platform,
),
)
@@ -183,7 +206,7 @@
],
include_directories: include_directories(
'3rd/utf',
- 'posix',
+ platform,
),
)
@@ -196,13 +219,13 @@
],
dependencies: [
math,
- ],
+ ] + extras,
include_directories: include_directories(
'3rd',
'3rd/brieflz',
'3rd/mp',
'3rd/utf',
- 'posix',
+ platform,
),
link_with: [
brieflz,
@@ -211,37 +234,78 @@
],
)
-mptest = executable(
- 'mptest',
- sources: [
- '3rd/mp/test.c',
- ],
- include_directories: include_directories(
- 'posix',
- ),
- link_with: [
- mp,
- ],
-)
-test('mp', mptest)
+if platform == 'macos'
+ flisp_pef = custom_target(
+ 'flisp.pef',
+ input: [
+ flisp
+ ],
+ output: [
+ 'flisp.pef',
+ ],
+ command: [
+ meson.get_external_property('makepef'), '@INPUT@', '-o', '@OUTPUT@',
+ ],
+ )
+ flisp_bin = custom_target(
+ 'flisp.bin',
+ input: [
+ flisp_pef,
+ ],
+ output: [
+ 'flisp.bin',
+ ],
+ command: [
+ meson.get_external_property('rez'),
+ '-I' + meson.get_external_property('rincludes'),
+ meson.get_external_property('rincludes') + '/RetroPPCAPPL.r',
+ '-DCFRAG_NAME="flisp"',
+ '-o', '@OUTPUT@',
+ #'--cc', 'flisp.dsk',
+ #'--cc', 'flisp.APPL',
+ #'--cc', '%flisp.ad',
+ '-t', 'APPL',
+ '-c', 'SGRD',
+ '--data', '@INPUT@',
+ ],
+ build_by_default: true,
+ )
+endif
-mptest2 = executable(
- 'mptest2',
- sources: [
- '3rd/mp/test/convtest.c',
- '3rd/mp/test/gen.tab.c',
- '3rd/mp/test/ld.c',
- '3rd/mp/test/main.c',
- ],
- include_directories: include_directories(
- '3rd/mp/test',
- 'posix',
- ),
- link_with: [
- mp,
- ],
-)
-test('mp2', mptest2, timeout: -1)
+build_tests = get_option('build-tests')
+if build_tests.enabled()
+ mptest = executable(
+ 'mptest',
+ sources: [
+ '3rd/mp/test.c',
+ ],
+ include_directories: include_directories(
+ platform,
+ ),
+ link_with: [
+ mp,
+ ],
+ )
+ test('mp', mptest)
+ mptest2 = executable(
+ 'mptest2',
+ sources: [
+ '3rd/mp/test/convtest.c',
+ '3rd/mp/test/gen.tab.c',
+ '3rd/mp/test/ld.c',
+ '3rd/mp/test/main.c',
+ ],
+ include_directories: include_directories(
+ '3rd/mp',
+ '3rd/mp/test',
+ platform,
+ ),
+ link_with: [
+ mp,
+ ],
+ )
+ test('mp2', mptest2, timeout: -1)
+endif
tests_dir = join_paths(meson.current_source_dir(), 'test')
--- a/meson.options
+++ b/meson.options
@@ -1,0 +1,1 @@
+option('build-tests', type: 'feature', value: 'enabled')
--- a/plan9/platform.h
+++ b/plan9/platform.h
@@ -82,8 +82,10 @@
#define isfinite(d) (((*(uint64_t*)&(d))&0x7ff0000000000000ULL) != 0x7ff0000000000000ULL)
#define PRIu32 "ud"
+#define PRIx32 "x"
#define PRId64 "lld"
#define PRIu64 "llud"
+#define PRIx64 "llx"
#define INT32_MAX 0x7fffffff
#define UINT32_MAX 0xffffffffU
--- a/posix/mp.h
+++ /dev/null
@@ -1,178 +1,0 @@
-#pragma once
-
-#ifdef BITS64
-typedef uint64_t mpdigit;
-#else
-typedef uint32_t mpdigit;
-#endif
-
-typedef union FPdbleword FPdbleword;
-union FPdbleword
-{
- double x;
- struct {
-#if BYTE_ORDER == LITTLE_ENDIAN
- uint32_t lo;
- uint32_t hi;
-#else
- uint32_t hi;
- uint32_t lo;
-#endif
- };
-};
-
-#define mpdighi (((mpdigit)1)<<(Dbits-1))
-#define DIGITS(x) ((int)(x) >= -(Dbits-1) ? ((Dbits - 1 + (x))/Dbits) : 0)
-
-extern int dec16(uint8_t*, int, char*, int);
-extern int enc16(char*, int, uint8_t*, int);
-extern mpdigit dec16chr(int);
-extern int enc16chr(int);
-
-/*
- * the code assumes mpdigit to be at least an int
- * mpdigit must be an atomic type. mpdigit is defined
- * in the architecture specific u.h
- */
-typedef struct mpint mpint;
-
-struct mpint
-{
- mpdigit *p;
- uint32_t size; /* allocated digits */
- uint32_t top; /* significant digits */
- int sign; /* +1 or -1 */
- int flags;
-};
-
-enum
-{
- MPstatic= 0x01, /* static constant */
- MPnorm= 0x02, /* normalization status */
- MPtimesafe= 0x04, /* request time invariant computation */
-
- Dbytes= sizeof(mpdigit), /* bytes per digit */
- Dbits= Dbytes*8 /* bits per digit */
-};
-
-/* allocation */
-void mpsetminbits(int n); /* newly created mpint's get at least n bits */
-mpint* mpnew(int n); /* create a new mpint with at least n bits */
-void mpfree(mpint *b);
-void mpbits(mpint *b, int n); /* ensure that b has at least n bits */
-mpint* mpnorm(mpint *b); /* dump leading zeros */
-mpint* mpcopy(mpint *b);
-void mpassign(mpint *old, mpint *new);
-
-/* random bits */
-mpint* mprand(int bits, void (*gen)(uint8_t*, int), mpint *b);
-/* return uniform random [0..n-1] */
-mpint* mpnrand(mpint *n, void (*gen)(uint8_t*, int), mpint *b);
-
-/* conversion */
-mpint* strtomp(const char*, char**, int, mpint*); /* ascii */
-char* mptoa(mpint*, int, char*, int);
-mpint* letomp(uint8_t*, uint32_t, mpint*); /* byte array, little-endian */
-int mptole(mpint*, uint8_t*, uint32_t, uint8_t**);
-void mptolel(mpint *b, uint8_t *p, int n);
-mpint* betomp(uint8_t*, uint32_t, mpint*); /* byte array, big-endian */
-int mptobe(mpint*, uint8_t*, uint32_t, uint8_t**);
-void mptober(mpint *b, uint8_t *p, int n);
-uint32_t mptoui(mpint*); /* unsigned int */
-mpint* uitomp(uint32_t, mpint*);
-int mptoi(mpint*); /* int */
-mpint* itomp(int, mpint*);
-uint64_t mptouv(mpint*); /* unsigned int64_t */
-mpint* uvtomp(uint64_t, mpint*);
-int64_t mptov(mpint*); /* int64_t */
-mpint* vtomp(int64_t, mpint*);
-double mptod(mpint*); /* double */
-mpint* dtomp(double, mpint*);
-
-/* divide the 2 digit dividend by the one digit divisor and stick in quotient */
-/* we assume that the result is one digit - overflow is all 1's */
-void mpdigdiv(mpdigit *dividend, mpdigit divisor, mpdigit *quotient);
-
-/* in the following, the result mpint may be */
-/* the same as one of the inputs. */
-void mpadd(mpint *b1, mpint *b2, mpint *sum); /* sum = b1+b2 */
-void mpsub(mpint *b1, mpint *b2, mpint *diff); /* diff = b1-b2 */
-void mpleft(mpint *b, int shift, mpint *res); /* res = b<<shift */
-void mpright(mpint *b, int shift, mpint *res); /* res = b>>shift */
-void mpmul(mpint *b1, mpint *b2, mpint *prod); /* prod = b1*b2 */
-void mpexp(mpint *b, mpint *e, mpint *m, mpint *res); /* res = b**e mod m */
-void mpmod(mpint *b, mpint *m, mpint *remainder); /* remainder = b mod m */
-
-/* logical operations */
-void mpand(mpint *b1, mpint *b2, mpint *res);
-void mpbic(mpint *b1, mpint *b2, mpint *res);
-void mpor(mpint *b1, mpint *b2, mpint *res);
-void mpnot(mpint *b, mpint *res);
-void mpxor(mpint *b1, mpint *b2, mpint *res);
-void mpasr(mpint *b, int shift, mpint *res);
-
-/* modular arithmetic, time invariant when 0≤b1≤m-1 and 0≤b2≤m-1 */
-void mpmodadd(mpint *b1, mpint *b2, mpint *m, mpint *sum); /* sum = b1+b2 % m */
-void mpmodsub(mpint *b1, mpint *b2, mpint *m, mpint *diff); /* diff = b1-b2 % m */
-void mpmodmul(mpint *b1, mpint *b2, mpint *m, mpint *prod); /* prod = b1*b2 % m */
-
-/* quotient = dividend/divisor, remainder = dividend % divisor */
-void mpdiv(mpint *dividend, mpint *divisor, mpint *quotient, mpint *remainder);
-
-/* return neg, 0, pos as b1-b2 is neg, 0, pos */
-int mpcmp(mpint *b1, mpint *b2);
-
-/* res = s != 0 ? b1 : b2 */
-void mpsel(int s, mpint *b1, mpint *b2, mpint *res);
-
-/* extended gcd return d, x, and y, s.t. d = gcd(a,b) and ax+by = d */
-void mpextendedgcd(mpint *a, mpint *b, mpint *d, mpint *x, mpint *y);
-
-/* res = b**-1 mod m */
-void mpinvert(mpint *b, mpint *m, mpint *res);
-
-/* bit counting */
-uint32_t mpsignif(mpint*); /* number of sigificant bits in mantissa */
-uint32_t mplowbits0(mpint*); /* k, where n = 2**k * q for odd q */
-
-/* well known constants */
-extern mpint *mpzero, *mpone, *mptwo;
-
-/* sum[0:alen] = a[0:alen-1] + b[0:blen-1] */
-/* prereq: alen >= blen, sum has room for alen+1 digits */
-void mpvecadd(mpdigit *a, int alen, mpdigit *b, int blen, mpdigit *sum);
-
-/* diff[0:alen-1] = a[0:alen-1] - b[0:blen-1] */
-/* prereq: alen >= blen, diff has room for alen digits */
-void mpvecsub(mpdigit *a, int alen, mpdigit *b, int blen, mpdigit *diff);
-
-/* p[0:n] += m * b[0:n-1] */
-/* prereq: p has room for n+1 digits */
-void mpvecdigmuladd(mpdigit *b, int n, mpdigit m, mpdigit *p);
-
-/* p[0:n] -= m * b[0:n-1] */
-/* prereq: p has room for n+1 digits */
-int mpvecdigmulsub(mpdigit *b, int n, mpdigit m, mpdigit *p);
-
-/* p[0:alen+blen-1] = a[0:alen-1] * b[0:blen-1] */
-/* prereq: alen >= blen, p has room for m*n digits */
-void mpvecmul(mpdigit *a, int alen, mpdigit *b, int blen, mpdigit *p);
-void mpvectsmul(mpdigit *a, int alen, mpdigit *b, int blen, mpdigit *p);
-
-/* sign of a - b or zero if the same */
-int mpveccmp(mpdigit *a, int alen, mpdigit *b, int blen);
-int mpvectscmp(mpdigit *a, int alen, mpdigit *b, int blen);
-
-/* playing with magnitudes */
-int mpmagcmp(mpint *b1, mpint *b2);
-void mpmagadd(mpint *b1, mpint *b2, mpint *sum); /* sum = b1+b2 */
-void mpmagsub(mpint *b1, mpint *b2, mpint *sum); /* sum = b1+b2 */
-
-/* fast field arithmetic */
-typedef struct Mfield Mfield;
-
-struct Mfield
-{
- mpint m;
- int (*reduce)(Mfield*, mpint*, mpint*);
-};
--- a/posix/platform.h
+++ b/posix/platform.h
@@ -76,6 +76,3 @@
#define BIG_ENDIAN __BIG_ENDIAN
#define BYTE_ORDER __BYTE_ORDER
#endif
-
-#include "mp.h"
-#include "utf.h"
--- a/posix/utf.h
+++ /dev/null
@@ -1,27 +1,0 @@
-#pragma once
-
-enum {
- Runeself = 0x80,
- Runeerror = 0xfffd,
- Runemax = 0x10ffff,
- UTFmax = 4,
-};
-
-typedef uint32_t Rune;
-
-int chartorune(Rune *rune, const char *str);
-int runetochar(char *str, const Rune *rune);
-int runenlen(const Rune *r, int nrune);
-int fullrune(const char *str, int n);
-int runelen(Rune c);
-Rune tolowerrune(Rune c);
-Rune toupperrune(Rune c);
-Rune totitlerune(Rune c);
-int islowerrune(Rune c);
-int isupperrune(Rune c);
-int isalpharune(Rune c);
-int istitlerune(Rune c);
-int isspacerune(Rune c);
-int isdigitrune(Rune c);
-
-int utfnlen(const char *s, long m);
--- a/print.c
+++ b/print.c
@@ -399,7 +399,7 @@
switch(tag(v)){
case TAG_NUM: case TAG_NUM1:
- FL(hpos) += ios_printf(f, "%"PRId64, (int64_t)numval(v));
+ FL(hpos) += ios_printf(f, "%"PRIdFIXNUM, numval(v));
break;
case TAG_SYM:
name = symbol_name(v);
@@ -667,7 +667,7 @@
if(u8_iswprint(r))
outs(f, seq);
else
- FL(hpos) += ios_printf(f, "x%04x", r);
+ FL(hpos) += ios_printf(f, "x%04"PRIx32, r);
break;
}
}
--- /dev/null
+++ b/sys_macos.c
@@ -1,0 +1,81 @@
+#include "flisp.h"
+#include "timefuncs.h"
+
+double
+sec_realtime(void)
+{
+ struct timeval now;
+
+ if(gettimeofday(&now, nil) != 0)
+ return 0.0;
+ return (double)now.tv_sec + (double)now.tv_usec/1.0e6;
+}
+
+/*
+ * nsec() is wallclock and can be adjusted by timesync
+ * so need to use cycles() instead, but fall back to
+ * nsec() in case we can't
+ */
+uint64_t
+nanosec_monotonic(void)
+{
+ return 0;
+}
+
+void
+timestring(double s, char *buf, int sz)
+{
+ USED(s); USED(sz);
+ buf[0] = 0;
+}
+
+double
+parsetime(const char *s)
+{
+ USED(s);
+ return 0.0;
+}
+
+void
+sleep_ms(int ms)
+{
+ USED(ms);
+}
+
+int
+ftruncate(int f, off_t sz)
+{
+ USED(f); USED(sz);
+ return -1;
+}
+
+char *
+getcwd(char *buf, size_t len)
+{
+ USED(buf); USED(len);
+ return nil;
+}
+
+int
+chdir(const char *path)
+{
+ USED(path);
+ return -1;
+}
+
+int
+access(const char *path, int amode)
+{
+ USED(path); USED(amode);
+ return -1;
+}
+
+static const uint8_t boot[] = {
+#include "flisp.boot.h"
+};
+
+int
+main(int argc, char **argv)
+{
+ flmain(boot, sizeof(boot), argc, argv);
+}
--- a/system.lsp
+++ b/system.lsp
@@ -1114,9 +1114,12 @@
; initialize globals that need to be set at load time
(define (__init_globals)
- (set! *prompt*
- "Function called by REPL to signal the user input is required.
-Default function prints \"#;> \"." (λ () (princ "#;> ")))
+ (let ((defprompt (if (= *os-name* "macos")
+ (λ () (princ "\x1b[0m\x1b[1m#;> \x1b[0m"))
+ (λ () (princ "#;> ")))))
+ (set! *prompt*
+ "Function called by REPL to signal the user input is required.
+Default function prints \"#;> \"." defprompt))
(set! *directory-separator* "/")
(set! *linefeed* "\n")
(set! *output-stream* *stdout*)
@@ -1132,8 +1135,9 @@
(let* ((homevar (case *os-name*
(("unknown") #f)
(("plan9") "home")
+ (("macos") (princ "\x1b]0;femtolisp v0.999\007") #f)
(else "HOME")))
- (home (os-getenv homevar))
+ (home (and homevar (os-getenv homevar)))
(fname (and home (string home *directory-separator* ".flisprc"))))
(when (and fname (path-exists? fname)) (load fname))))
--- a/utf8.c
+++ b/utf8.c
@@ -129,7 +129,7 @@
int
u8_escape_rune(char *buf, size_t sz, Rune ch)
{
- assert(sz > 2);
+ assert(sz > 12);
if(ch >= 0x20 && ch < 0x7f){
buf[0] = ch;
buf[1] = '\0';
@@ -136,9 +136,9 @@
return 1;
}
if(ch > 0xffff)
- return snprintf(buf, sz, "\\U%.8x", ch);
+ return snprintf(buf, sz, "\\U%.8"PRIx32, ch);
if(ch >= Runeself)
- return snprintf(buf, sz, "\\u%04x", ch);
+ return snprintf(buf, sz, "\\u%04"PRIx32, ch);
switch(ch){
case '\n': return buf_put2c(buf, "\\n");
case '\t': return buf_put2c(buf, "\\t");
@@ -150,7 +150,7 @@
case '\r': return buf_put2c(buf, "\\r");
case '\v': return buf_put2c(buf, "\\v");
}
- return snprintf(buf, sz, "\\x%02x", ch);
+ return snprintf(buf, sz, "\\x%02"PRIx32, ch);
}
size_t