ref: 4ca4045c4d9956882813aba344b0b9430063e3e8
parent: 97d0c80fcc6e076d3a856f3ec2230194ce0e7b3f
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Mon Oct 28 22:13:16 EDT 2024
make → meson; fix a whole bunch of warnings; reorganize some of the platform-specific logic
--- a/.gitignore
+++ b/.gitignore
@@ -1,11 +1,7 @@
-*.[05678qvt]
-*.o
+*.[05678qvtoa]
*.out
-*.a
-/flisp
-/flisp.boot.bak
-/flisp.boot.new
-boot.h
+flisp
+flisp.boot.*
instructions.lsp
builtins.lsp
builtin_fns.h
--- a/3rd/lookup3.c
+++ b/3rd/lookup3.c
@@ -135,99 +135,6 @@
}
/*
---------------------------------------------------------------------
- This works on all machines. To be useful, it requires
- -- that the key be an array of uint32_t's, and
- -- that the length be the number of uint32_t's in the key
-
- The function hashword() is identical to hashlittle() on little-endian
- machines, and identical to hashbig() on big-endian machines,
- except that the length has to be measured in uint32_ts rather than in
- bytes. hashlittle() is more complicated than hashword() only because
- hashlittle() has to dance around fitting the key bytes into registers.
---------------------------------------------------------------------
-*/
-uint32_t hashword(
-const uint32_t *k, /* the key, an array of uint32_t values */
-size_t length, /* the length of the key, in uint32_ts */
-uint32_t initval) /* the previous hash, or an arbitrary value */
-{
- uint32_t a,b,c;
-
- /* Set up the internal state */
- a = b = c = 0xdeadbeef + (((uint32_t)length)<<2) + initval;
-
- /*------------------------------------------------- handle most of the key */
- while (length > 3)
- {
- a += k[0];
- b += k[1];
- c += k[2];
- mix(a,b,c);
- length -= 3;
- k += 3;
- }
-
- /*------------------------------------------- handle the last 3 uint32_t's */
- switch(length) /* all the case statements fall through */
- {
- case 3 : c+=k[2]; // fallthrough
- case 2 : b+=k[1]; // fallthrough
- case 1 : a+=k[0]; // fallthrough
- final(a,b,c);
- case 0: /* case 0: nothing left to add */
- break;
- }
- /*------------------------------------------------------ report the result */
- return c;
-}
-
-/*
---------------------------------------------------------------------
-hashword2() -- same as hashword(), but take two seeds and return two
-32-bit values. pc and pb must both be nonnull, and *pc and *pb must
-both be initialized with seeds. If you pass in (*pb)==0, the output
-(*pc) will be the same as the return value from hashword().
---------------------------------------------------------------------
-*/
-void hashword2 (
-const uint32_t *k, /* the key, an array of uint32_t values */
-size_t length, /* the length of the key, in uint32_ts */
-uint32_t *pc, /* IN: seed OUT: primary hash value */
-uint32_t *pb) /* IN: more seed OUT: secondary hash value */
-{
- uint32_t a,b,c;
-
- /* Set up the internal state */
- a = b = c = 0xdeadbeef + ((uint32_t)(length<<2)) + *pc;
- c += *pb;
-
- /*------------------------------------------------- handle most of the key */
- while (length > 3)
- {
- a += k[0];
- b += k[1];
- c += k[2];
- mix(a,b,c);
- length -= 3;
- k += 3;
- }
-
- /*------------------------------------------- handle the last 3 uint32_t's */
- switch(length) /* all the case statements fall through */
- {
- case 3 : c+=k[2]; // fallthrough
- case 2 : b+=k[1]; // fallthrough
- case 1 : a+=k[0]; // fallthrough
- final(a,b,c);
- case 0: /* case 0: nothing left to add */
- break;
- }
- /*------------------------------------------------------ report the result */
- *pc=c; *pb=b;
-}
-
-/*
* hashlittle2: return 2 32-bit hash values
*
* This is identical to hashlittle(), except it returns two 32-bit hash
@@ -237,7 +144,7 @@
* the key. *pc is better mixed than *pb, so use *pc first. If you want
* a 64-bit value do something like "*pc + (((uint64_t)*pb)<<32)".
*/
-void hashlittle2(
+static void hashlittle2(
const void *key, /* the key to hash */
size_t length, /* length of the key */
uint32_t *pc, /* IN: primary initval, OUT: primary hash */
--- a/Makefile
+++ /dev/null
@@ -1,107 +1,0 @@
-DESTDIR?=
-PREFIX?=/usr/local
-BIN=${DESTDIR}${PREFIX}/bin
-
-TARG=flisp
-CFLAGS?=-O2 -g
-CFLAGS+=-Wall -Wextra -Wno-parentheses -std=c99 -I3rd -Iposix
-LDFLAGS?=
-
-OBJS=\
- 3rd/mp/mpadd.o\
- 3rd/mp/mpaux.o\
- 3rd/mp/mpcmp.o\
- 3rd/mp/mpdigdiv.o\
- 3rd/mp/mpdiv.o\
- 3rd/mp/mpfmt.o\
- 3rd/mp/mpleft.o\
- 3rd/mp/mplogic.o\
- 3rd/mp/mpmul.o\
- 3rd/mp/mpright.o\
- 3rd/mp/mpsub.o\
- 3rd/mp/mptobe.o\
- 3rd/mp/mptober.o\
- 3rd/mp/mptod.o\
- 3rd/mp/mptoi.o\
- 3rd/mp/mptoui.o\
- 3rd/mp/mptouv.o\
- 3rd/mp/mptov.o\
- 3rd/mp/mpvecadd.o\
- 3rd/mp/mpveccmp.o\
- 3rd/mp/mpvecdigmuladd.o\
- 3rd/mp/mpvecsub.o\
- 3rd/mp/mpvectscmp.o\
- 3rd/mp/strtomp.o\
- 3rd/mp/u16.o\
- 3rd/mp/u32.o\
- 3rd/mp/u64.o\
- 3rd/mt19937-64.o\
- 3rd/utf/rune.o\
- 3rd/utf/runeistype.o\
- 3rd/utf/runetotype.o\
- 3rd/utf/utfnlen.o\
- bitvector-ops.o\
- bitvector.o\
- builtins.o\
- cvalues.o\
- dump.o\
- equal.o\
- equalhash.o\
- flisp.o\
- flmain.o\
- hashing.o\
- htable.o\
- ios.o\
- iostream.o\
- llt.o\
- main_posix.o\
- operators.o\
- print.o\
- ptrhash.o\
- random.o\
- read.o\
- string.o\
- table.o\
- timefuncs.o\
- types.o\
- utf8.o\
-
-.PHONY: all default test bootstrap clean
-
-all: default
-
-default: ${TARG}
-
-test: ${TARG}
- cd test && ../$(TARG) unittest.lsp
-
-${TARG}: ${OBJS}
- ${CC} -o $@ ${OBJS} ${LDFLAGS} -lm
-
-.SUFFIXES: .c .o
-.c.o:
- ${CC} -o $@ -c $< ${CFLAGS}
-
-flisp.o: flisp.c flisp.h operators.h cvalues.h maxstack.inc opcodes.h builtin_fns.h
-flmain.o: flmain.c boot.h flisp.h cvalues.h
-main_posix.o: main_posix.c builtin_fns.h
-3rd/utf/runeistype.o: 3rd/utf/runeistypedata
-3rd/utf/runetotype.o: 3rd/utf/runetotypedata
-
-boot.h: flisp.boot
- sed 's,\\,\\\\,g;s,",\\",g;s,^,",g;s,$$,\\n",g' flisp.boot >$@
-
-builtin_fns.h: *.c
- sed -nE 's/^BUILTIN[_]?(\(".*)/BUILTIN_FN\1/gp' *.c >$@
-
-bootstrap: ${TARG} builtin_fns.h mkboot0.lsp mkboot1.lsp
- cp flisp.boot flisp.boot.bak
- ./${TARG} gen.lsp
- ./${TARG} mkboot0.lsp instructions.lsp builtins.lsp system.lsp compiler.lsp >flisp.boot
- ${MAKE} clean
- ${MAKE} ${TARG}
- ./${TARG} mkboot1.lsp
- ${MAKE} test
-
-clean:
- rm -f ${OBJS} ${TARG}
--- a/README.md
+++ b/README.md
@@ -22,6 +22,17 @@
* fixed bootstrap (makes it work properly when opcodes change)
* bigints
+## Building
+
+### POSIX
+
+ meson setup build -Dbuildtype=release
+ ninja -C build
+
+### Plan 9
+
+ mk
+
## Characteristics
* lexical scope, lisp-1
--- /dev/null
+++ b/boot2h.sh
@@ -1,0 +1,3 @@
+#!/bin/sh
+set -e
+sed 's#\\#\\\\#g;s#"#\\"#g;s#^#"#g;s#$#\\n"#g' $*
--- /dev/null
+++ b/bootstrap.sh
@@ -1,0 +1,9 @@
+#!/bin/sh
+test -e
+F=./build/flisp
+test -x $F || { CC=clang meson setup -Dbuildtype=debug build . && ninja -C build || exit 1; }
+test -x $F || { echo no $F found; exit 1; }
+$F gen.lsp && \
+$F mkboot0.lsp system.lsp compiler.lsp > flisp.boot && \
+$F mkboot1.lsp && \
+ninja -C build || exit 1
--- a/builtins.c
+++ b/builtins.c
@@ -294,7 +294,7 @@
{
argcount(nargs, 0);
USED(args);
- return mk_double(clock_now());
+ return mk_double(sec_realtime());
}
static double
--- /dev/null
+++ b/builtins2h.sh
@@ -1,0 +1,3 @@
+#!/bin/sh
+set -e
+sed -nE 's/^BUILTIN[_]?(\(".*)/BUILTIN_FN\1/gp' $* | sort
--- a/cvalues.c
+++ b/cvalues.c
@@ -274,6 +274,7 @@
num_init(double, double, T_DOUBLE)
#define num_ctor_init(typenam, ctype, tag) \
+ static \
BUILTIN(#typenam, typenam) \
{ \
if(nargs == 0){ \
@@ -298,20 +299,20 @@
num_ctor_init(typenam, ctype, tag) \
num_ctor_ctor(typenam, ctype, tag)
-num_ctor(int8, int8_t, T_INT8)
-num_ctor(uint8, uint8_t, T_UINT8)
-num_ctor(int16, int16_t, T_INT16)
-num_ctor(uint16, uint16_t, T_UINT16)
+num_ctor_init(int8, int8_t, T_INT8)
+num_ctor_init(uint8, uint8_t, T_UINT8)
+num_ctor_init(int16, int16_t, T_INT16)
+num_ctor_init(uint16, uint16_t, T_UINT16)
num_ctor(int32, int32_t, T_INT32)
num_ctor(uint32, uint32_t, T_UINT32)
num_ctor(int64, int64_t, T_INT64)
num_ctor(uint64, uint64_t, T_UINT64)
-num_ctor(byte, uint8_t, T_UINT8)
+num_ctor_init(byte, uint8_t, T_UINT8)
#if defined(ULONG64)
-num_ctor(long, int64_t, T_INT64)
+num_ctor_init(long, int64_t, T_INT64)
num_ctor(ulong, uint64_t, T_UINT64)
#else
-num_ctor(long, int32_t, T_INT32)
+num_ctor_init(long, int32_t, T_INT32)
num_ctor(ulong, uint32_t, T_UINT32)
#endif
num_ctor(float, float, T_FLOAT)
@@ -907,7 +908,7 @@
cv->type = builtintype;
cv->data = &cv->_space[0];
cv->len = sizeof(value_t);
- *(void**)cv->data = f;
+ *(builtin_t*)cv->data = f;
value_t sym = symbol(name);
((symbol_t*)ptr(sym))->dlcache = cv;
--- a/cvalues.h
+++ b/cvalues.h
@@ -1,5 +1,4 @@
-#ifndef CVALUES_H
-#define CVALUES_H
+#pragma once
#ifdef BITS64
#define NWORDS(sz) (((sz)+7)>>3)
@@ -77,9 +76,11 @@
value_t mk_int64(int64_t n);
value_t mk_uint64(uint64_t n);
value_t mk_rune(Rune n);
+#if defined(ULONG64)
+value_t mk_ulong(uint64_t n);
+#else
+value_t mk_ulong(uint32_t n);
+#endif
/* builtins.c */
size_t llength(value_t v);
-
-#endif
-
--- a/equal.h
+++ b/equal.h
@@ -1,5 +1,4 @@
-#ifndef EQUAL_H
-#define EQUAL_H
+#pragma once
// comparable with ==
#define eq_comparable(a, b) (!(((a)|(b))&1))
@@ -10,6 +9,4 @@
int equal_lispvalue(value_t a, value_t b);
uintptr_t hash_lispvalue(value_t a);
value_t compare_(value_t a, value_t b, int eq);
-
-#endif
-
+void comparehash_init(void);
--- a/flisp.c
+++ b/flisp.c
@@ -15,6 +15,8 @@
#include "read.h"
#include "equal.h"
#include "hashing.h"
+#include "table.h"
+#include "iostream.h"
typedef struct {
char *name;
@@ -195,7 +197,7 @@
SAFECAST_OP(cons, cons_t*, ptr)
SAFECAST_OP(symbol, symbol_t*, ptr)
SAFECAST_OP(fixnum, fixnum_t, numval)
-SAFECAST_OP(cvalue, cvalue_t*, ptr)
+//SAFECAST_OP(cvalue, cvalue_t*, ptr)
SAFECAST_OP(string, char*, cvalue_data)
#undef isstring
@@ -1035,7 +1037,7 @@
}else if(iscbuiltin(func)){
s = SP;
curr_fname = cvalue_name(func);
- v = ((builtin_t)(((void**)ptr(func))[3]))(&Stack[SP-n], n);
+ v = (((builtin_t*)ptr(func))[3])(&Stack[SP-n], n);
SP = s-n;
Stack[SP-1] = v;
NEXT_OP;
@@ -2054,10 +2056,6 @@
};
// initialization -------------------------------------------------------------
-
-extern void comparehash_init(void);
-extern void table_init(void);
-extern void iostream_init(void);
static void
lisp_init(size_t initial_heapsize)
--- a/flisp.h
+++ b/flisp.h
@@ -1,5 +1,4 @@
-#ifndef FLISP_H
-#define FLISP_H
+#pragma once
enum {
TAG_NUM,
@@ -351,6 +350,3 @@
#define BUILTIN_FN(l, c) extern BUILTIN(l, c);
#include "builtin_fns.h"
#undef BUILTIN_FN
-
-#endif
-
--- a/flmain.c
+++ b/flmain.c
@@ -21,11 +21,8 @@
extern fltype_t *iostreamtype;
int
-flmain(int argc, char **argv)
+flmain(const char *boot, int bootsz, int argc, char **argv)
{
- static const char bootraw[] = {
-#include "boot.h"
- };
value_t f;
ios_t *s;
int r;
@@ -34,7 +31,7 @@
f = cvalue(iostreamtype, sizeof(ios_t));
s = value2c(ios_t*, f);
- ios_static_buffer(s, bootraw, sizeof(bootraw));
+ ios_static_buffer(s, boot, bootsz);
r = 1;
FL_TRY_EXTERN{
--- a/hashing.c
+++ b/hashing.c
@@ -1,4 +1,5 @@
#include "llt.h"
+#include "hashing.h"
lltuint_t
nextipow2(lltuint_t i)
--- a/hashing.h
+++ b/hashing.h
@@ -1,5 +1,4 @@
-#ifndef HASHING_H_
-#define HASHING_H_
+#pragma once
lltuint_t nextipow2(lltuint_t i);
uint32_t int32hash(uint32_t a);
@@ -7,5 +6,3 @@
uint32_t int64to32hash(uint64_t key);
uint64_t memhash(const char* buf, size_t n);
uint32_t memhash32(const char* buf, size_t n);
-
-#endif
--- a/htable.h
+++ b/htable.h
@@ -1,5 +1,4 @@
-#ifndef __HTABLE_H_
-#define __HTABLE_H_
+#pragma once
#define HT_N_INLINE 32
@@ -18,5 +17,3 @@
// clear and (possibly) change size
void htable_reset(htable_t *h, size_t sz);
-
-#endif
--- a/ieee754.h
+++ b/ieee754.h
@@ -1,5 +1,4 @@
-#ifndef __IEEE754_H_
-#define __IEEE754_H_
+#pragma once
union ieee754_float {
float f;
@@ -62,5 +61,3 @@
};
#define IEEE854_LONG_DOUBLE_BIAS 0x3fff
-
-#endif
--- a/ios.h
+++ b/ios.h
@@ -60,6 +60,8 @@
char local[IOS_INLSIZE];
}ios_t;
+void *llt_memrchr(const void *s, int c, size_t n);
+
/* low-level interface functions */
size_t ios_read(ios_t *s, char *dest, size_t n);
size_t ios_write(ios_t *s, const char *data, size_t n);
--- a/iostream.c
+++ b/iostream.c
@@ -4,12 +4,13 @@
#include "types.h"
#include "print.h"
#include "read.h"
+#include "iostream.h"
static value_t iostreamsym, rdsym, wrsym, apsym, crsym, truncsym;
static value_t instrsym, outstrsym;
fltype_t *iostreamtype;
-void
+static void
print_iostream(value_t v, ios_t *f)
{
USED(v);
@@ -16,7 +17,7 @@
fl_print_str("#<io stream>", f);
}
-void
+static void
free_iostream(value_t self)
{
ios_t *s = value2c(ios_t*, self);
@@ -23,7 +24,7 @@
ios_close(s);
}
-void
+static void
relocate_iostream(value_t oldv, value_t newv)
{
ios_t *olds = value2c(ios_t*, oldv);
@@ -39,8 +40,8 @@
nil
};
-int
-fl_isiostream(value_t v)
+static int
+isiostream(value_t v)
{
return iscvalue(v) && cv_class(ptr(v)) == iostreamtype;
}
@@ -48,7 +49,7 @@
BUILTIN("iostream?", iostreamp)
{
argcount(nargs, 1);
- return fl_isiostream(args[0]) ? FL_T : FL_F;
+ return isiostream(args[0]) ? FL_T : FL_F;
}
BUILTIN("eof-object", eof_object)
@@ -64,10 +65,10 @@
return args[0] == FL_EOF ? FL_T : FL_F;
}
-ios_t *
-fl_toiostream(value_t v)
+static ios_t *
+toiostream(value_t v)
{
- if(!fl_isiostream(v))
+ if(!isiostream(v))
type_error("iostream", v);
return value2c(ios_t*, v);
}
@@ -121,7 +122,7 @@
arg = symbol_value(instrsym);
else
arg = args[0];
- ios_t *s = fl_toiostream(arg);
+ ios_t *s = toiostream(arg);
fl_gc_handle(&arg);
value_t v = fl_read_sexpr(arg);
fl_free_gc_handles(1);
@@ -133,7 +134,7 @@
BUILTIN("io-getc", io_getc)
{
argcount(nargs, 1);
- ios_t *s = fl_toiostream(args[0]);
+ ios_t *s = toiostream(args[0]);
Rune r;
int res;
if((res = ios_getutf8(s, &r)) == IOS_EOF)
@@ -147,7 +148,7 @@
BUILTIN("io-putc", io_putc)
{
argcount(nargs, 2);
- ios_t *s = fl_toiostream(args[0]);
+ ios_t *s = toiostream(args[0]);
if(!iscprim(args[1]) || ((cprim_t*)ptr(args[1]))->type != runetype)
type_error("rune", args[1]);
Rune r = *(Rune*)cp_data((cprim_t*)ptr(args[1]));
@@ -157,7 +158,7 @@
BUILTIN("io-skip", io_skip)
{
argcount(nargs, 2);
- ios_t *s = fl_toiostream(args[0]);
+ ios_t *s = toiostream(args[0]);
off_t off = tooffset(args[1]);
off_t res = ios_skip(s, off);
if(res < 0)
@@ -168,13 +169,13 @@
BUILTIN("io-flush", io_flush)
{
argcount(nargs, 1);
- return ios_flush(fl_toiostream(args[0])) == 0 ? FL_T : FL_F;
+ return ios_flush(toiostream(args[0])) == 0 ? FL_T : FL_F;
}
BUILTIN("io-close", io_close)
{
argcount(nargs, 1);
- ios_close(fl_toiostream(args[0]));
+ ios_close(toiostream(args[0]));
return FL_T;
}
@@ -181,7 +182,7 @@
BUILTIN("io-discardbuffer", io_discardbuffer)
{
argcount(nargs, 1);
- ios_purge(fl_toiostream(args[0]));
+ ios_purge(toiostream(args[0]));
return FL_T;
}
@@ -188,13 +189,13 @@
BUILTIN("io-eof?", io_eofp)
{
argcount(nargs, 1);
- return ios_eof(fl_toiostream(args[0])) ? FL_T : FL_F;
+ return ios_eof(toiostream(args[0])) ? FL_T : FL_F;
}
BUILTIN("io-seek", io_seek)
{
argcount(nargs, 2);
- ios_t *s = fl_toiostream(args[0]);
+ ios_t *s = toiostream(args[0]);
size_t pos = toulong(args[1]);
off_t res = ios_seek(s, (off_t)pos);
if(res == -1)
@@ -205,7 +206,7 @@
BUILTIN("io-pos", io_pos)
{
argcount(nargs, 1);
- ios_t *s = fl_toiostream(args[0]);
+ ios_t *s = toiostream(args[0]);
off_t res = ios_pos(s);
if(res == -1)
return FL_F;
@@ -217,7 +218,7 @@
if(nargs < 1 || nargs > 2)
argcount(nargs, 1);
ios_t *s;
- s = nargs == 2 ? fl_toiostream(args[1]) : fl_toiostream(symbol_value(outstrsym));
+ s = nargs == 2 ? toiostream(args[1]) : toiostream(symbol_value(outstrsym));
fl_print(s, args[0]);
return args[0];
}
@@ -226,7 +227,7 @@
{
if(nargs != 3)
argcount(nargs, 2);
- ios_t *s = fl_toiostream(args[0]);
+ ios_t *s = toiostream(args[0]);
size_t n;
fltype_t *ft;
if(nargs == 3){
@@ -267,7 +268,7 @@
{
if(nargs < 2 || nargs > 4)
argcount(nargs, 2);
- ios_t *s = fl_toiostream(args[0]);
+ ios_t *s = toiostream(args[0]);
if(iscprim(args[1]) && ((cprim_t*)ptr(args[1]))->type == runetype){
if(nargs > 2)
lerrorf(ArgError, "offset argument not supported for characters");
@@ -289,7 +290,7 @@
{
if(nargs < 1 || nargs > 3)
argcount(nargs, 1);
- ios_t *s = fl_toiostream(symbol_value(outstrsym));
+ ios_t *s = toiostream(symbol_value(outstrsym));
char *data;
size_t sz, offs = 0;
to_sized_ptr(args[0], &data, &sz);
@@ -324,7 +325,7 @@
ios_mem(&dest, 0);
ios_setbuf(&dest, data, 80, 0);
char delim = get_delim_arg(args[1]);
- ios_t *src = fl_toiostream(args[0]);
+ ios_t *src = toiostream(args[0]);
size_t n = ios_copyuntil(&dest, src, delim);
cv->len = n;
if(dest.buf != data){
@@ -345,8 +346,8 @@
BUILTIN("io-copyuntil", io_copyuntil)
{
argcount(nargs, 3);
- ios_t *dest = fl_toiostream(args[0]);
- ios_t *src = fl_toiostream(args[1]);
+ ios_t *dest = toiostream(args[0]);
+ ios_t *src = toiostream(args[1]);
char delim = get_delim_arg(args[2]);
return size_wrap(ios_copyuntil(dest, src, delim));
}
@@ -355,8 +356,8 @@
{
if(nargs < 2 || nargs > 3)
argcount(nargs, 2);
- ios_t *dest = fl_toiostream(args[0]);
- ios_t *src = fl_toiostream(args[1]);
+ ios_t *dest = toiostream(args[0]);
+ ios_t *src = toiostream(args[1]);
if(nargs == 3)
return size_wrap(ios_copy(dest, src, toulong(args[2])));
return size_wrap(ios_copyall(dest, src));
@@ -387,7 +388,7 @@
BUILTIN("io-tostring!", io_tostring)
{
argcount(nargs, 1);
- ios_t *src = fl_toiostream(args[0]);
+ ios_t *src = toiostream(args[0]);
if(src->bm != bm_mem)
lerrorf(ArgError, "requires memory stream");
return stream_to_string(&args[0]);
--- /dev/null
+++ b/iostream.h
@@ -1,0 +1,2 @@
+value_t stream_to_string(value_t *ps);
+void iostream_init(void);
--- a/llt.h
+++ b/llt.h
@@ -1,5 +1,4 @@
-#ifndef __LLT_H_
-#define __LLT_H_
+#pragma once
#include "platform.h"
#include "utf8.h"
@@ -69,4 +68,4 @@
int isdigit_base(char c, int base);
void llt_init(void);
-#endif
+int flmain(const char *boot, int bootsz, int argc, char **argv);
--- a/main_plan9.c
+++ b/main_plan9.c
@@ -1,6 +1,8 @@
-#include "platform.h"
+#include "llt.h"
-int flmain(int argc, char **argv);
+static const char boot[] = {
+#include "flisp.boot.h"
+};
void
main(int argc, char **argv)
@@ -8,5 +10,5 @@
argv0 = argv[0];
setfcr(FPPDBL|FPRNR|FPOVFL);
tmfmtinstall();
- exit(flmain(argc, argv));
+ exit(flmain(boot, sizeof(boot), argc, argv));
}
--- a/main_posix.c
+++ b/main_posix.c
@@ -1,9 +1,11 @@
-#include "platform.h"
+#include "llt.h"
-int flmain(int argc, char **argv);
+static const char boot[] =
+#include "flisp.boot.h"
+;
int
main(int argc, char **argv)
{
- return flmain(argc, argv);
+ return flmain(boot, sizeof(boot), argc, argv);
}
--- /dev/null
+++ b/meson.build
@@ -1,0 +1,145 @@
+project(
+ 'femtolisp',
+ 'c',
+ version: '0.999',
+ default_options: [
+ 'c_std=c2x',
+ 'warning_level=3',
+ 'buildtype=debugoptimized',
+ #'b_coverage=true',
+ ],
+)
+
+add_project_arguments(
+ #'-Wconversion',
+ #'-Wsign-conversion',
+ '-Wmissing-prototypes',
+ '-Werror=odr',
+ '-Werror=strict-aliasing',
+ '-Wno-parentheses',
+ '-Wno-overlength-strings',
+ '-D_DEFAULT_SOURCE',
+ language: 'c',
+)
+
+src = [
+ '3rd/mt19937-64.c',
+ '3rd/mp/mpadd.c',
+ '3rd/mp/mpaux.c',
+ '3rd/mp/mpcmp.c',
+ '3rd/mp/mpdigdiv.c',
+ '3rd/mp/mpdiv.c',
+ '3rd/mp/mpfmt.c',
+ '3rd/mp/mpleft.c',
+ '3rd/mp/mplogic.c',
+ '3rd/mp/mpmul.c',
+ '3rd/mp/mpright.c',
+ '3rd/mp/mpsub.c',
+ '3rd/mp/mptobe.c',
+ '3rd/mp/mptober.c',
+ '3rd/mp/mptod.c',
+ '3rd/mp/mptoi.c',
+ '3rd/mp/mptoui.c',
+ '3rd/mp/mptouv.c',
+ '3rd/mp/mptov.c',
+ '3rd/mp/mpvecadd.c',
+ '3rd/mp/mpveccmp.c',
+ '3rd/mp/mpvecdigmuladd.c',
+ '3rd/mp/mpvecsub.c',
+ '3rd/mp/mpvectscmp.c',
+ '3rd/mp/strtomp.c',
+ '3rd/mp/u16.c',
+ '3rd/mp/u32.c',
+ '3rd/mp/u64.c',
+ '3rd/utf/rune.c',
+ '3rd/utf/runeistype.c',
+ '3rd/utf/runetotype.c',
+ '3rd/utf/utfnlen.c',
+ 'bitvector-ops.c',
+ 'bitvector.c',
+ 'builtins.c',
+ 'cvalues.c',
+ 'dump.c',
+ 'equal.c',
+ 'equalhash.c',
+ 'flisp.c',
+ 'flmain.c',
+ 'hashing.c',
+ 'htable.c',
+ 'ios.c',
+ 'iostream.c',
+ 'llt.c',
+ 'main_posix.c',
+ 'operators.c',
+ 'print.c',
+ 'ptrhash.c',
+ 'random.c',
+ 'read.c',
+ 'string.c',
+ 'table.c',
+ 'time_posix.c',
+ 'types.c',
+ 'utf8.c',
+]
+
+cc = meson.get_compiler('c')
+
+if cc.get_id() == 'clang'
+ add_project_arguments(
+ '-D__wchar_t=__please_no_wchar_t_thank_you',
+ language: 'c',
+ )
+else
+ add_project_arguments(
+ '-Werror=lto-type-mismatch',
+ language: 'c',
+ )
+endif
+
+math = cc.find_library('m', required: false)
+
+boot = custom_target(
+ 'boot',
+ capture: true,
+ input: [
+ 'flisp.boot',
+ ],
+ output: [
+ 'flisp.boot.h',
+ ],
+ command: [
+ 'boot2h.sh', '@INPUT@',
+ ],
+)
+
+builtins = custom_target(
+ 'builtins',
+ capture: true,
+ input: [
+ src,
+ ],
+ output: [
+ 'builtin_fns.h',
+ ],
+ command: [
+ 'builtins2h.sh', '@INPUT@',
+ ],
+)
+
+executable(
+ 'flisp',
+ sources: [
+ src,
+ boot,
+ builtins,
+ ],
+ dependencies: [
+ math,
+ ],
+ include_directories: include_directories(
+ '3rd',
+ '3rd/mp',
+ '3rd/utf',
+ 'posix',
+ ),
+)
--- a/mkfile
+++ b/mkfile
@@ -3,7 +3,7 @@
BIN=/$objtype/bin
TARG=flisp
CFLAGS=$CFLAGS -p -D__plan9__ -D__${objtype}__ -I3rd -Iplan9
-CLEANFILES=boot.h builtin_fns.h
+CLEANFILES=plan9/flisp.boot.h plan9/builtin_fns.h
HFILES=\
equalhash.h\
@@ -34,7 +34,7 @@
read.$O\
string.$O\
table.$O\
- timefuncs.$O\
+ time_plan9.$O\
types.$O\
utf8.$O\
@@ -42,16 +42,15 @@
</sys/src/cmd/mkone
-boot.h: flisp.boot
+plan9/flisp.boot.h: flisp.boot
sed 's,\\,\\\\,g;s,",\\",g;s,^,",g;s,$,\\n",g' $prereq >$target
-builtin_fns.h:
- sed -n 's/^BUILTIN[_]?(\(".*)/BUILTIN_FN\1/gp' *.c >$target
+plan9/builtin_fns.h:
+ sed -n 's/^BUILTIN[_]?(\(".*)/BUILTIN_FN\1/gp' *.c | sort >$target
-main_plan9.$O: boot.h builtin_fns.h
-flisp.$O: maxstack.inc opcodes.h builtin_fns.h
-flmain.$O: boot.h
-builtins.$O: builtin_fns.h
+main_plan9.$O: plan9/flisp.boot.h plan9/builtin_fns.h
+flisp.$O: maxstack.inc opcodes.h plan9/builtin_fns.h
+builtins.$O: plan9/builtin_fns.h
%.$O: %.c
$CC $CFLAGS -o $target $stem.c
--- a/operators.h
+++ b/operators.h
@@ -1,5 +1,4 @@
-#ifndef OPERATORS_H
-#define OPERATORS_H
+#pragma once
mpint * conv_to_mpint(void *data, numerictype_t tag);
double conv_to_double(void *data, numerictype_t tag);
@@ -23,6 +22,3 @@
#define conv_to_long conv_to_int32
#define conv_to_ulong conv_to_uint32
#endif
-
-#endif
-
--- a/posix/mp.h
+++ b/posix/mp.h
@@ -1,5 +1,4 @@
-#ifndef _MPINT_H_
-#define _MPINT_H_
+#pragma once
typedef uint32_t mpdigit;
typedef uint8_t uchar;
@@ -232,5 +231,3 @@
Mfield *gmfield(mpint*);
Mfield *cnfield(mpint*);
-
-#endif
--- a/posix/platform.h
+++ b/posix/platform.h
@@ -10,6 +10,7 @@
#include <locale.h>
#include <math.h>
#include <setjmp.h>
+#include <stdbool.h>
#include <stdarg.h>
#include <stdio.h>
#include <stddef.h>
--- a/print.c
+++ b/print.c
@@ -545,7 +545,7 @@
outc('"', f);
}
-int
+static int
double_exponent(double d)
{
union ieee754_double dl;
@@ -554,7 +554,7 @@
return dl.ieee.exponent - IEEE754_DOUBLE_BIAS;
}
-void
+static void
snprint_real(char *s, size_t cnt, double r,
int width, // printf field width, or 0
int dec, // # decimal digits desired, recommend 16
--- a/print.h
+++ b/print.h
@@ -1,5 +1,4 @@
-#ifndef PRINT_H
-#define PRINT_H
+#pragma once
extern htable_t printconses;
extern int SCR_WIDTH;
@@ -9,6 +8,3 @@
void fl_print_chr(char c, ios_t *f);
void fl_print_str(char *s, ios_t *f);
void fl_print_child(ios_t *f, value_t v);
-
-#endif
-
--- a/random.c
+++ b/random.c
@@ -1,9 +1,7 @@
-/*
- random numbers
-*/
#include "llt.h"
#include "mt19937-64.h"
#include "timefuncs.h"
+#include "random.h"
static mt19937_64 ctx;
@@ -34,6 +32,6 @@
void
randomize(void)
{
- unsigned long long tm = i64time();
+ unsigned long long tm = nanosec_monotonic();
init_by_array64(&ctx, &tm, 1);
}
--- a/random.h
+++ b/random.h
@@ -1,5 +1,4 @@
-#ifndef RANDOM_H_
-#define RANDOM_H_
+#pragma once
void randomize(void);
double genrand_double(void);
@@ -6,5 +5,3 @@
uint64_t genrand_uint64(void);
uint32_t genrand_uint32(void);
int64_t genrand_int63(void);
-
-#endif
--- a/read.h
+++ b/read.h
@@ -1,5 +1,4 @@
-#ifndef READ_H
-#define READ_H
+#pragma once
value_t fl_read_sexpr(value_t f);
int isnumtok_base(char *tok, value_t *pval, int base);
@@ -10,5 +9,3 @@
// unless it's the only character in the symbol, and '#', which is
// an ordinary symbol character unless it's the first character.
#define symchar(c) (!strchr("()[]{}'\";`,\\| \a\b\f\n\r\t\v", (c)))
-
-#endif
--- a/string.c
+++ b/string.c
@@ -8,6 +8,7 @@
#include "print.h"
#include "read.h"
#include "equal.h"
+#include "iostream.h"
BUILTIN("string?", stringp)
{
@@ -111,7 +112,6 @@
}
extern BUILTIN("buffer", buffer);
-extern value_t stream_to_string(value_t *ps);
BUILTIN("string", string)
{
--- a/table.c
+++ b/table.c
@@ -4,11 +4,12 @@
#include "cvalues.h"
#include "types.h"
#include "print.h"
+#include "table.h"
static value_t tablesym;
static fltype_t *tabletype;
-void
+static void
print_htable(value_t v, ios_t *f)
{
htable_t *h = (htable_t*)cv_data(ptr(v));
@@ -28,7 +29,7 @@
fl_print_chr(')', f);
}
-void
+static void
print_traverse_htable(value_t self)
{
htable_t *h = (htable_t*)cv_data(ptr(self));
@@ -41,7 +42,7 @@
}
}
-void
+static void
free_htable(value_t self)
{
htable_t *h = (htable_t*)cv_data((cvalue_t*)ptr(self));
@@ -48,7 +49,7 @@
htable_free(h);
}
-void
+static void
relocate_htable(value_t oldv, value_t newv)
{
htable_t *oldh = (htable_t*)cv_data(ptr(oldv));
@@ -69,7 +70,7 @@
print_traverse_htable,
};
-int
+static int
ishashtable(value_t v)
{
return iscvalue(v) && cv_class((cvalue_t*)ptr(v)) == tabletype;
--- /dev/null
+++ b/table.h
@@ -1,0 +1,1 @@
+void table_init(void);
--- /dev/null
+++ b/time_plan9.c
@@ -1,0 +1,68 @@
+#include "llt.h"
+#include "timefuncs.h"
+#include <tos.h>
+
+double
+sec_realtime(void)
+{
+ vlong t = nsec();
+ vlong ns = t % 1000000000LL;
+ vlong s = (t - ns) / 1000000000LL;
+ return (double)s + (double)ns/1.0e9;
+}
+
+/*
+ * 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)
+{
+ static uint64_t fasthz, xstart;
+ uint64_t x, div;
+
+ if(fasthz == ~0ULL)
+ return nsec() - xstart;
+
+ if(fasthz == 0){
+ if(_tos->cyclefreq){
+ fasthz = _tos->cyclefreq;
+ cycles(&xstart);
+ } else {
+ fasthz = ~0ULL;
+ xstart = nsec();
+ }
+ return 0;
+ }
+ cycles(&x);
+ x -= xstart;
+
+ /* this is ugly */
+ for(div = 1000000000ULL; x < 0x1999999999999999ULL && div > 1 ; div /= 10ULL, x *= 10ULL);
+
+ return x / (fasthz / div);
+}
+
+void
+timestring(double s, char *buf, int sz)
+{
+ Tm tm;
+ snprint(buf, sz, "%τ", tmfmt(tmtime(&tm, s, tzload("local")), nil));
+}
+
+double
+parsetime(const char *s)
+{
+ Tm tm;
+ if(tmparse(&tm, "?WWW, ?MM ?DD hh:mm:ss ?Z YYYY", s, tzload("local"), nil) == nil)
+ return -1;
+ return tmnorm(&tm);
+}
+
+void
+sleep_ms(int ms)
+{
+ if(ms != 0)
+ sleep(ms);
+}
--- /dev/null
+++ b/time_posix.c
@@ -1,0 +1,70 @@
+#include "llt.h"
+#include "timefuncs.h"
+
+double
+sec_realtime(void)
+{
+ struct timespec now;
+ if(clock_gettime(CLOCK_REALTIME, &now) != 0)
+ return 0;
+ return (double)now.tv_sec + (double)now.tv_nsec/1.0e9;
+}
+
+uint64_t
+nanosec_monotonic(void)
+{
+ static int64_t z;
+ struct timespec now;
+
+ if(clock_gettime(CLOCK_MONOTONIC, &now) != 0)
+ return 0;
+ if(z == 0){
+ z = now.tv_sec*1000000000LL + now.tv_nsec;
+ return 0;
+ }
+ return now.tv_sec*1000000000LL + now.tv_nsec - z;
+}
+
+void
+timestring(double s, char *buf, int sz)
+{
+ time_t tme = (time_t)s;
+ char *fmt = "%c"; /* needed to suppress GCC warning */
+ struct tm tm;
+
+ localtime_r(&tme, &tm);
+ strftime(buf, sz, fmt, &tm);
+}
+
+double
+parsetime(const char *s)
+{
+ char *fmt = "%c"; /* needed to suppress GCC warning */
+ char *res;
+ time_t t;
+ struct tm tm;
+
+ res = strptime(s, fmt, &tm);
+ if(res != nil){
+ /* Not set by strptime(); tells mktime() to determine
+ * whether daylight saving time is in effect
+ */
+ tm.tm_isdst = -1;
+ t = mktime(&tm);
+ if(t == (time_t)-1)
+ return -1;
+ return (double)t;
+ }
+ return -1;
+}
+
+void
+sleep_ms(int ms)
+{
+ if(ms != 0){
+ struct timeval timeout;
+ timeout.tv_sec = ms/1000;
+ timeout.tv_usec = (ms % 1000) * 1000;
+ select(0, nil, nil, nil, &timeout);
+ }
+}
--- a/timefuncs.c
+++ /dev/null
@@ -1,116 +1,0 @@
-#include "platform.h"
-
-#if defined(__plan9__)
-double
-floattime(void)
-{
- return (double)nsec() / 1.0e9;
-}
-#else
-double
-tv2float(struct timeval *tv)
-{
- return (double)tv->tv_sec + (double)tv->tv_usec/1.0e6;
-}
-
-double
-diff_time(struct timeval *tv1, struct timeval *tv2)
-{
- return tv2float(tv1) - tv2float(tv2);
-}
-#endif
-
-// return as many bits of system randomness as we can get our hands on
-uint64_t
-i64time(void)
-{
- uint64_t a;
-#if defined(__plan9__)
- a = nsec();
-#else
- struct timeval now;
- gettimeofday(&now, nil);
- a = (((uint64_t)now.tv_sec)<<32) + (uint64_t)now.tv_usec;
-#endif
-
- return a;
-}
-
-double
-clock_now(void)
-{
-#if defined(__plan9__)
- return floattime();
-#else
- struct timeval now;
- gettimeofday(&now, nil);
- return tv2float(&now);
-#endif
-}
-
-void
-timestring(double seconds, char *buffer, size_t len)
-{
-#if defined(__plan9__)
- Tm tm;
- snprint(buffer, len, "%τ", tmfmt(tmtime(&tm, seconds, tzload("local")), nil));
-#else
- time_t tme = (time_t)seconds;
-
- char *fmt = "%c"; /* needed to suppress GCC warning */
- struct tm tm;
-
- localtime_r(&tme, &tm);
- strftime(buffer, len, fmt, &tm);
-#endif
-}
-
-#if defined(__plan9__)
-double
-parsetime(const char *str)
-{
- Tm tm;
- if(tmparse(&tm, "?WWW, ?MM ?DD hh:mm:ss ?Z YYYY", str, tzload("local"), nil) == nil)
- return -1;
- return tmnorm(&tm);
-}
-#else
-double
-parsetime(const char *str)
-{
- char *fmt = "%c"; /* needed to suppress GCC warning */
- char *res;
- time_t t;
- struct tm tm;
-
- res = strptime(str, fmt, &tm);
- if(res != nil){
- /* Not set by strptime(); tells mktime() to determine
- * whether daylight saving time is in effect
- */
- tm.tm_isdst = -1;
- t = mktime(&tm);
- if(t == (time_t)-1)
- return -1;
- return (double)t;
- }
- return -1;
-}
-#endif
-
-void
-sleep_ms(int ms)
-{
- if(ms == 0)
- return;
-
-#if defined(__plan9__)
- sleep(ms);
-#else
- struct timeval timeout;
-
- timeout.tv_sec = ms/1000;
- timeout.tv_usec = (ms % 1000) * 1000;
- select(0, nil, nil, nil, &timeout);
-#endif
-}
--- a/timefuncs.h
+++ b/timefuncs.h
@@ -1,10 +1,7 @@
-#ifndef TIMEFUNCS_H_
-#define TIMEFUNCS_H_
+#pragma once
-uint64_t i64time(void);
-double clock_now(void);
-void timestring(double seconds, char *buffer, size_t len);
-double parsetime(const char *str);
+double sec_realtime(void);
+uint64_t nanosec_monotonic(void);
+void timestring(double s, char *buf, int sz);
+double parsetime(const char *s);
void sleep_ms(int ms);
-
-#endif
--- a/types.c
+++ b/types.c
@@ -2,6 +2,7 @@
#include "flisp.h"
#include "cvalues.h"
#include "equalhash.h"
+#include "types.h"
fltype_t *
get_type(value_t t)
--- a/types.h
+++ b/types.h
@@ -1,10 +1,6 @@
-#ifndef TYPES_H
-#define TYPES_H
+#pragma once
fltype_t *get_type(value_t t);
fltype_t *get_array_type(value_t eltype);
fltype_t *define_opaque_type(value_t sym, size_t sz, cvtable_t *vtab, cvinitfunc_t init);
void relocate_typetable(void);
-
-#endif
-
--- a/utf8.c
+++ b/utf8.c
@@ -111,7 +111,7 @@
case 't': return '\t';
case 'a': return '\a';
case 'b': return '\b';
- case 'e': return '\e';
+ case 'e': return 0x1b;
case 'f': return '\f';
case 'r': return '\r';
case 'v': return '\v';
@@ -147,7 +147,7 @@
case '\\': return buf_put2c(buf, "\\\\");
case '\a': return buf_put2c(buf, "\\a");
case '\b': return buf_put2c(buf, "\\b");
- case '\e': return buf_put2c(buf, "\\e");
+ case 0x1b: return buf_put2c(buf, "\\e");
case '\f': return buf_put2c(buf, "\\f");
case '\r': return buf_put2c(buf, "\\r");
case '\v': return buf_put2c(buf, "\\v");
--- a/utf8.h
+++ b/utf8.h
@@ -1,5 +1,4 @@
-#ifndef __UTF8_H_
-#define __UTF8_H_
+#pragma once
/* is c the start of a utf8 sequence? */
#define isutf(c) (((c)&0xC0) != 0x80)
@@ -57,5 +56,3 @@
/* reverse a UTF-8 string. len is length in bytes. dest and src must both
be allocated to at least len+1 bytes. returns 1 for error, 0 otherwise */
int u8_reverse(char *dest, char *src, size_t len);
-
-#endif