63 lines
2.0 KiB
C
63 lines
2.0 KiB
C
|
|
/**
|
||
|
|
* @file main.c
|
||
|
|
* @brief The standalone driver.
|
||
|
|
*
|
||
|
|
* Everything that belongs to a program rather than to a library lives here: argv
|
||
|
|
* handling, sink selection, the unbounded run loop, and the one FINISH_NORETURN
|
||
|
|
* in the tree. The interpreter library itself never terminates the process.
|
||
|
|
*
|
||
|
|
* The runtime is static rather than automatic because it carries every pool the
|
||
|
|
* interpreter owns -- several megabytes -- and that will not fit on a default
|
||
|
|
* stack. An embedding game would place it in its own state for the same reason.
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include <stdio.h>
|
||
|
|
#include <stdlib.h>
|
||
|
|
|
||
|
|
#include <akerror.h>
|
||
|
|
#include <akstdlib.h>
|
||
|
|
|
||
|
|
#include <akbasic/error.h>
|
||
|
|
#include <akbasic/runtime.h>
|
||
|
|
#include <akbasic/sink.h>
|
||
|
|
|
||
|
|
static akbasic_Runtime RUNTIME;
|
||
|
|
static akbasic_TextSink SINK;
|
||
|
|
static akbasic_StdioSink SINKSTATE;
|
||
|
|
|
||
|
|
int main(int argc, char **argv)
|
||
|
|
{
|
||
|
|
PREPARE_ERROR(errctx);
|
||
|
|
FILE *program = NULL;
|
||
|
|
int rc = EXIT_SUCCESS;
|
||
|
|
|
||
|
|
ATTEMPT {
|
||
|
|
if ( argc > 1 ) {
|
||
|
|
/*
|
||
|
|
* A file argument: read the program from it in RUNSTREAM mode, which
|
||
|
|
* files each line under its line number and then switches to RUN.
|
||
|
|
*/
|
||
|
|
CATCH(errctx, aksl_fopen(argv[1], "r", &program));
|
||
|
|
CATCH(errctx, akbasic_sink_init_stdio(&SINK, &SINKSTATE, stdout, program));
|
||
|
|
CATCH(errctx, akbasic_runtime_init(&RUNTIME, &SINK));
|
||
|
|
CATCH(errctx, akbasic_runtime_start(&RUNTIME, AKBASIC_MODE_RUNSTREAM));
|
||
|
|
} else {
|
||
|
|
CATCH(errctx, akbasic_sink_init_stdio(&SINK, &SINKSTATE, stdout, stdin));
|
||
|
|
CATCH(errctx, akbasic_runtime_init(&RUNTIME, &SINK));
|
||
|
|
CATCH(errctx, akbasic_runtime_start(&RUNTIME, AKBASIC_MODE_REPL));
|
||
|
|
}
|
||
|
|
/* Unbounded: this is the driver, and it has nothing else to do. */
|
||
|
|
CATCH(errctx, akbasic_runtime_run(&RUNTIME, 0));
|
||
|
|
} CLEANUP {
|
||
|
|
if ( program != NULL ) {
|
||
|
|
IGNORE(aksl_fclose(program));
|
||
|
|
}
|
||
|
|
} PROCESS(errctx) {
|
||
|
|
} HANDLE_DEFAULT(errctx) {
|
||
|
|
LOG_ERROR_WITH_MESSAGE(errctx, "akbasic terminated on an unhandled error");
|
||
|
|
rc = EXIT_FAILURE;
|
||
|
|
} FINISH_NORETURN(errctx);
|
||
|
|
|
||
|
|
return rc;
|
||
|
|
}
|