shithub: sl

ref: a70379d7e4b822f532fb0a8ccdd1624a90b64a68
dir: /src/slmain.c/

View raw version
#include "sl.h"
#include "cvalues.h"
#include "print.h"
#include "io.h"
#include "random.h"
#include "brieflz.h"
#include "nan.h"

#if !defined(ARGBEGIN)
/* straight from 9front */
static char *argv0 = nil;
#define	ARGBEGIN \
	for((argv0 ? 0 : (argv0=*argv)), argv++, argc--; argv[0] && argv[0][0]=='-' && argv[0][1]; argc--, argv++){ \
		const char *_args, *_argt; \
		Rune _argc; \
		_args = &argv[0][1]; \
		if(_args[0]=='-' && _args[1]==0){ \
			argc--; \
			argv++; \
			break; \
		}\
		_argc = 0; \
		while(*_args && (_args += chartorune(&_argc, _args))) \
			switch(_argc)
#define	ARGEND USED(_argt); USED(_argc); USED(_args);}USED(argv); USED(argc);
#define	ARGF() (_argt=_args, _args="", (*_argt? _argt: argv[1]? (argc--, *++argv): 0))
#define	ARGC() _argc
#define	EARGF(x) (_argt=_args, _args="", (*_argt? _argt: argv[1]? (argc--, *++argv): (x, (char*)0)))
#endif

static sl_v
argv_list(int argc, char **argv)
{
	int i;
	sl_v lst = sl_nil, temp;
	sl_gc_handle(&lst);
	sl_gc_handle(&temp);
	for(i = argc-1; i >= 0; i--){
		temp = cvalue_static_cstr(argv[i]);
		lst = mk_cons(temp, lst);
	}
	lst = mk_cons(cvalue_static_cstr(argv0), lst);
	sl_free_gc_handles(2);
	return lst;
}

static void
sizesuffix(usize *sz, char su)
{
	switch(tolower(su)){
	case 'k':
		*sz *= 1024;
		break;
	case 'm':
		*sz *= 1024*1024;
		break;
	case 0:
		break;
	default:
		sysfatal("invalid size suffix '%c'", su);
	}
}

_Noreturn static void
usage(void)
{
	ios_printf(ios_stderr, "%s: [-i] [-H heapsize] [-S stacksize] ...\n", argv0);
	exits("usage");
}

_Noreturn void
slmain(const u8int *boot, int bootsz, int argc, char **argv)
{
	usize heapsize = HEAP_SIZE0, stacksize = STACK_SIZE0;
	sl_v interactive;
	char *e;

	nan_init();
	randomize();
	ios_init_std();
	mpsetminbits(sizeof(sl_fx)*8);

	interactive = sl_nil;
	ARGBEGIN{
	case 'H':
		heapsize = strtoull(EARGF(usage()), &e, 0);
		sizesuffix(&heapsize, *e);
		break;
	case 'S':
		stacksize = strtoull(EARGF(usage()), &e, 0);
		sizesuffix(&stacksize, *e);
		break;
	case 'i':
		interactive = sl_t;
		break;
	case 'h':
		usage();
	default:
		break;
	}ARGEND

	if(sl_init(heapsize, stacksize) != 0)
		sysfatal("init failed");

	u8int *unpacked = nil;
	if(boot[0] == 0){
		u32int unpackedsz =
			boot[1]<<0 |
			boot[2]<<8 |
			boot[3]<<16|
			boot[4]<<24;
		unpacked = MEM_ALLOC(unpackedsz);
		unsigned long n = blz_depack_safe(boot+5, bootsz-5, unpacked, unpackedsz);
		if(n == BLZ_ERROR)
			sysfatal("failed to unpack boot image");
		boot = unpacked;
		bootsz = n;
	}
	static sl_ios s;
	ios_static_buffer(&s, boot, bootsz);

	const char *status = nil;
	sl_v args = argv_list(argc, argv);
	sl_gc_handle(&args);
	SL_TRY_EXTERN{
		sl_v f = cvalue_from_ref(sl_iotype, &s, sizeof(sl_ios));
		if(sl_load_system_image(f) == 0){
			MEM_FREE(unpacked);
			ios_close(&s);
			ios_free(&s);
			sl_free_gc_handles(1);
			sl_applyn(2, sym_value(mk_sym("__start", false)), args, interactive);
		}
	}
	SL_CATCH_EXTERN_NO_RESTORE{
		ios_puts(ios_stderr, "fatal error:\n");
		sl_print(ios_stderr, sl.lasterror);
		ios_putc(ios_stderr, '\n');
		status = "error";
		break;
	}
	sl_exit(status);
}