Move main() etc. into main.c
This commit is contained in:
parent
5ca9fdb042
commit
fc4f0bef28
|
@ -1,4 +1,4 @@
|
|||
files = pebblisp.c tokens.c object.c env.c web.c plfunc.c hash.c
|
||||
files = main.c pebblisp.c tokens.c object.c env.c web.c plfunc.c hash.c
|
||||
libs = -lreadline -lmicrohttpd
|
||||
exe = pl
|
||||
|
||||
|
|
|
@ -25,13 +25,6 @@
|
|||
|
||||
(def reloadConfig (fn () (loadfile config)))
|
||||
|
||||
(def hour (fn (ti) (
|
||||
(def h (% ti.hour 12))
|
||||
(if (= 0 h) 12 h)
|
||||
)))
|
||||
|
||||
(def zero (fn (num) (cat (if (< num 10) "0" "") num)))
|
||||
|
||||
(def string (fn (a) (cat "" a)))
|
||||
|
||||
(struct Alias (name value))
|
||||
|
@ -52,6 +45,13 @@
|
|||
(if (iserr match) text match.value)
|
||||
)))
|
||||
|
||||
(def hour (fn (ti) (
|
||||
(def h (% ti.hour 12))
|
||||
(if (= 0 h) 12 h)
|
||||
)))
|
||||
|
||||
(def zero (fn (num) (cat (if (< num 10) "0" "") num)))
|
||||
|
||||
(def clock (fn (ti) (cat (hour ti) ":" (zero ti.minute) ":" (zero ti.sec))))
|
||||
|
||||
(def cleanDir (fn () (
|
||||
|
|
|
@ -0,0 +1,234 @@
|
|||
#define _GNU_SOURCE
|
||||
|
||||
#include "pebblisp.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
|
||||
char* getPrompt(struct Environment* env)
|
||||
{
|
||||
Object prompt = fetchFromEnvironment("prompt", env);
|
||||
prompt = cloneObject(prompt);
|
||||
if (prompt.type == TYPE_STRING) {
|
||||
char* ret = readline(prompt.string);
|
||||
cleanObject(&prompt);
|
||||
return ret;
|
||||
}
|
||||
Object param = stringFromSlice("", 1);
|
||||
Object e = listEvalLambda(&prompt, ¶m, 2, env);
|
||||
cleanObject(&prompt);
|
||||
cleanObject(¶m);
|
||||
char* ret = readline(e.string);
|
||||
cleanObject(&e);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char* preprocess(char* buf, struct Environment* env)
|
||||
{
|
||||
Object lambda = fetchFromEnvironment("preprocess", env);
|
||||
Object buffer = nullTerminated(buf);
|
||||
Object s = listEvalLambda(&lambda, &buffer, 2, env);
|
||||
size_t length;
|
||||
return stringObj(&s, &length);
|
||||
}
|
||||
|
||||
void repl(struct Environment* env)
|
||||
{
|
||||
char* buf;
|
||||
using_history();
|
||||
|
||||
while ((buf = getPrompt(env)) != NULL) {
|
||||
if (strcmp("q", buf) == 0) {
|
||||
free(buf);
|
||||
break;
|
||||
}
|
||||
buf = preprocess(buf, env);
|
||||
if (buf[0] == '\0') {
|
||||
free(buf);
|
||||
continue;
|
||||
}
|
||||
add_history(buf);
|
||||
if ((buf[0] == 'c' && buf[1] == 'd')) {
|
||||
char* oldBuf = buf;
|
||||
buf = malloc(sizeof(char) * strlen(buf + 6));
|
||||
sprintf(buf, "(cd \"%s\")", oldBuf + 3);
|
||||
free(oldBuf);
|
||||
}
|
||||
if ((buf[0] == '?' && (buf[1] == ' ' || buf[1] == '\0'))) {
|
||||
char* oldBuf = buf;
|
||||
buf = malloc(sizeof(char) * strlen(buf + 3));
|
||||
sprintf(buf, "(%s)", oldBuf);
|
||||
free(oldBuf);
|
||||
}
|
||||
Object o = parseEval(buf, env);
|
||||
if (isFuncy(o) || isError(o, DID_NOT_FIND_SYMBOL)) {
|
||||
cleanObject(&o);
|
||||
system(buf);
|
||||
free(buf);
|
||||
continue;
|
||||
}
|
||||
free(buf);
|
||||
|
||||
size_t length;
|
||||
char* output = stringObj(&o, &length);
|
||||
cleanObject(&o);
|
||||
printColored(output);
|
||||
free(output);
|
||||
printf("[0m\n");
|
||||
}
|
||||
}
|
||||
|
||||
void loadArgsIntoEnv(int argc, const char* argv[], struct Environment* env)
|
||||
{
|
||||
Object args = listObject();
|
||||
for (int i = 0; i < argc; i++) {
|
||||
nf_addToList(&args, nullTerminated(argv[i]));
|
||||
}
|
||||
addToEnv(env, "args", args);
|
||||
}
|
||||
|
||||
#ifdef __x86_64__
|
||||
|
||||
#include <signal.h>
|
||||
#include <ucontext.h>
|
||||
|
||||
int nestedSegfault = 0;
|
||||
|
||||
void handler(int nSignum, siginfo_t* si, void* vcontext)
|
||||
{
|
||||
if (nestedSegfault) {
|
||||
printf("Nested segfault!!!\n");
|
||||
exit(139);
|
||||
}
|
||||
nestedSegfault = 1;
|
||||
|
||||
printf("Segfaulted!\n");
|
||||
struct Slice* lastOpen = getLastOpen();
|
||||
if (lastOpen) {
|
||||
printf("line: %d\n%s\n", lastOpen->lineNumber, lastOpen->text);
|
||||
} else {
|
||||
printf("Happened before token processing.\n");
|
||||
}
|
||||
ucontext_t* context = vcontext;
|
||||
context->uc_mcontext.gregs[REG_RIP]++;
|
||||
exit(139);
|
||||
}
|
||||
|
||||
void setupSegfaultHandler()
|
||||
{
|
||||
struct sigaction action;
|
||||
memset(&action, 0, sizeof(struct sigaction));
|
||||
action.sa_flags = SA_SIGINFO;
|
||||
action.sa_sigaction = handler;
|
||||
sigaction(SIGSEGV, &action, NULL);
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
void setupSegfaultHandler()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
struct Settings {
|
||||
int runTests;
|
||||
int ignoreConfig;
|
||||
int ignoreLib;
|
||||
int moreToDo;
|
||||
const char* configFile;
|
||||
} settings;
|
||||
|
||||
#define RUN_TESTS_ARG "--run-tests"
|
||||
#define RUN_DETAILED_TESTS "=detailed"
|
||||
#define IGNORE_CONFIG_ARG "--ignore-config"
|
||||
#define IGNORE_LIB_ARG "--ignore-lib"
|
||||
#define CONFIG_FILE_ARG "--config="
|
||||
|
||||
void getSettings(int argc, const char* argv[])
|
||||
{
|
||||
settings.runTests = 0;
|
||||
settings.ignoreConfig = 0;
|
||||
settings.ignoreLib = 0;
|
||||
settings.moreToDo = 0;
|
||||
settings.configFile = NULL;
|
||||
|
||||
size_t runTestsLen = strlen(RUN_TESTS_ARG);
|
||||
size_t configFileLen = strlen(CONFIG_FILE_ARG);
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (strncmp(argv[i], RUN_TESTS_ARG, runTestsLen) == 0) {
|
||||
int isDetailed = strcmp(argv[i] + runTestsLen, RUN_DETAILED_TESTS) == 0;
|
||||
settings.runTests = isDetailed ? 2 : 1;
|
||||
} else if (strncmp(argv[i], CONFIG_FILE_ARG, configFileLen) == 0) {
|
||||
settings.configFile = argv[i] + configFileLen;
|
||||
} else if (strcmp(argv[i], IGNORE_CONFIG_ARG) == 0) {
|
||||
settings.ignoreConfig = 1;
|
||||
} else if (strcmp(argv[i], IGNORE_LIB_ARG) == 0) {
|
||||
settings.ignoreLib = 1;
|
||||
} else if (argv[i][0] == '-') {
|
||||
fprintf(stderr, "Unrecognized argument: '%s'\n", argv[i]);
|
||||
} else if (i == (argc - 1)) {
|
||||
settings.moreToDo = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
setupSegfaultHandler();
|
||||
getSettings(argc, argv);
|
||||
|
||||
struct Environment env = defaultEnv();
|
||||
setGlobal(&env);
|
||||
|
||||
if (settings.runTests) {
|
||||
int ret = runTests(settings.runTests == 2);
|
||||
shredDictionary();
|
||||
deleteEnv(global());
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!settings.ignoreLib) {
|
||||
readFile(SCRIPTDIR "/lib.pbl", &env);
|
||||
}
|
||||
|
||||
Object o = parseEval("(def prompt \"pebblisp::> \")", &env);
|
||||
cleanObject(&o);
|
||||
o = parseEval("(def preprocess (fn (text) (text)))", &env);
|
||||
cleanObject(&o);
|
||||
|
||||
if (!settings.ignoreConfig) {
|
||||
char config[128];
|
||||
if (settings.configFile) {
|
||||
sprintf(config, "%s", settings.configFile);
|
||||
} else {
|
||||
const char* const home = getenv("HOME");
|
||||
sprintf(config, "%s/.pebblisp.pbl", home);
|
||||
}
|
||||
if (readFile(config, &env) == 1 && settings.configFile) {
|
||||
fprintf(stderr, "Config file not found at %s\n", config);
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.moreToDo) {
|
||||
FILE* file = fopen(argv[argc - 1], "r");
|
||||
if (file) {
|
||||
// Execute a file
|
||||
loadArgsIntoEnv(argc, argv, &env);
|
||||
_readFile(file, &env);
|
||||
} else {
|
||||
// Run arguments directly as pl code
|
||||
Object r = parseEval(argv[argc - 1], &env);
|
||||
printAndClean(&r);
|
||||
}
|
||||
} else {
|
||||
// Run a repl
|
||||
loadArgsIntoEnv(argc, argv, &env);
|
||||
repl(&env);
|
||||
}
|
||||
deleteEnv(&env);
|
||||
shredDictionary();
|
||||
// eprintf("totalSearchDepth: %d of %d searches\n", getTotalSearchDepth(), getTotalSearches());
|
||||
// eprintf("\nHEAP-ALLOCATED OBJECTS: %d\n", getAllocations());
|
||||
// eprintf("TOTAL OBJECT.C ALLOC: %zu\n", getBytes());
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
#ifndef PEBBLISP_MAIN_H
|
||||
#define PEBBLISP_MAIN_H
|
||||
|
||||
#endif // PEBBLISP_MAIN_H
|
197
src/pebblisp.c
197
src/pebblisp.c
|
@ -1,20 +1,11 @@
|
|||
#ifdef STANDALONE
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#endif
|
||||
|
||||
#include "pebblisp.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tokens.h"
|
||||
#include "pebblisp.h"
|
||||
|
||||
#ifdef STANDALONE
|
||||
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
|
||||
#include "web.h"
|
||||
|
||||
#endif
|
||||
|
@ -466,6 +457,11 @@ Result parseAtom(struct Slice* s)
|
|||
|
||||
struct Slice* lastOpen = NULL;
|
||||
|
||||
struct Slice* getLastOpen()
|
||||
{
|
||||
return lastOpen;
|
||||
}
|
||||
|
||||
Object parseEval(const char* input, struct Environment* env)
|
||||
{
|
||||
struct Error err = noError();
|
||||
|
@ -540,6 +536,7 @@ Object typeCheck(const char* funcName, Object* params, int length,
|
|||
|
||||
#ifdef STANDALONE
|
||||
|
||||
/// Returns 1 if the file could not be opened. Otherwise, 0
|
||||
int readFile(const char* filename, struct Environment* env)
|
||||
{
|
||||
FILE* input = fopen(filename, "r");
|
||||
|
@ -592,182 +589,4 @@ int _readFile(FILE* input, struct Environment* env)
|
|||
return 0;
|
||||
}
|
||||
|
||||
char* getPrompt(struct Environment* env)
|
||||
{
|
||||
Object prompt = fetchFromEnvironment("prompt", env);
|
||||
prompt = cloneObject(prompt);
|
||||
if (prompt.type == TYPE_STRING) {
|
||||
char* ret = readline(prompt.string);
|
||||
cleanObject(&prompt);
|
||||
return ret;
|
||||
}
|
||||
Object param = stringFromSlice("", 1);
|
||||
Object e = listEvalLambda(&prompt, ¶m, 2, env);
|
||||
cleanObject(&prompt);
|
||||
cleanObject(¶m);
|
||||
char* ret = readline(e.string);
|
||||
cleanObject(&e);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char* preprocess(char* buf, struct Environment* env)
|
||||
{
|
||||
Object lambda = fetchFromEnvironment("preprocess", env);
|
||||
Object buffer = nullTerminated(buf);
|
||||
Object s = listEvalLambda(&lambda, &buffer, 2, env);
|
||||
size_t length;
|
||||
return stringObj(&s, &length);
|
||||
}
|
||||
|
||||
void repl(struct Environment* env)
|
||||
{
|
||||
char* buf;
|
||||
using_history();
|
||||
|
||||
while ((buf = getPrompt(env)) != NULL) {
|
||||
if (strcmp("q", buf) == 0) {
|
||||
free(buf);
|
||||
break;
|
||||
}
|
||||
buf = preprocess(buf, env);
|
||||
if (buf[0] == '\0') {
|
||||
free(buf);
|
||||
continue;
|
||||
}
|
||||
add_history(buf);
|
||||
if ((buf[0] == 'c' && buf[1] == 'd')) {
|
||||
char* oldBuf = buf;
|
||||
buf = malloc(sizeof(char) * strlen(buf + 6));
|
||||
sprintf(buf, "(cd \"%s\")", oldBuf + 3);
|
||||
free(oldBuf);
|
||||
}
|
||||
if ((buf[0] == '?' && (buf[1] == ' ' || buf[1] == '\0'))) {
|
||||
char* oldBuf = buf;
|
||||
buf = malloc(sizeof(char) * strlen(buf + 3));
|
||||
sprintf(buf, "(%s)", oldBuf);
|
||||
free(oldBuf);
|
||||
}
|
||||
Object o = parseEval(buf, env);
|
||||
if (isFuncy(o) || isError(o, DID_NOT_FIND_SYMBOL)) {
|
||||
cleanObject(&o);
|
||||
system(buf);
|
||||
free(buf);
|
||||
continue;
|
||||
}
|
||||
free(buf);
|
||||
|
||||
size_t length;
|
||||
char* output = stringObj(&o, &length);
|
||||
cleanObject(&o);
|
||||
printColored(output);
|
||||
free(output);
|
||||
printf("[0m\n");
|
||||
}
|
||||
}
|
||||
|
||||
void loadArgsIntoEnv(int argc, const char* argv[], struct Environment* env)
|
||||
{
|
||||
Object args = listObject();
|
||||
for (int i = 0; i < argc; i++) {
|
||||
nf_addToList(&args, nullTerminated(argv[i]));
|
||||
}
|
||||
addToEnv(env, "args", args);
|
||||
}
|
||||
|
||||
#ifdef __x86_64__
|
||||
#include <signal.h>
|
||||
#include <ucontext.h>
|
||||
|
||||
int nestedSegfault = 0;
|
||||
|
||||
void handler(int nSignum, siginfo_t* si, void* vcontext)
|
||||
{
|
||||
if (nestedSegfault) {
|
||||
printf("Nested segfault!!!\n");
|
||||
exit(139);
|
||||
}
|
||||
nestedSegfault = 1;
|
||||
|
||||
printf("Segfaulted!\n");
|
||||
if (lastOpen) {
|
||||
printf("line: %d\n%s\n", lastOpen->lineNumber, lastOpen->text);
|
||||
} else {
|
||||
printf("Happened before token processing.\n");
|
||||
}
|
||||
ucontext_t* context = vcontext;
|
||||
context->uc_mcontext.gregs[REG_RIP]++;
|
||||
exit(139);
|
||||
}
|
||||
void setupSegfaultHandler()
|
||||
{
|
||||
struct sigaction action;
|
||||
memset(&action, 0, sizeof(struct sigaction));
|
||||
action.sa_flags = SA_SIGINFO;
|
||||
action.sa_sigaction = handler;
|
||||
sigaction(SIGSEGV, &action, NULL);
|
||||
|
||||
}
|
||||
#else
|
||||
void setupSegfaultHandler()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO: add --no-lib and --no-config and/or --config=
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
setupSegfaultHandler();
|
||||
|
||||
const char* const home = getenv("HOME");
|
||||
char config[strlen(home) + 15];
|
||||
|
||||
struct Environment env = defaultEnv();
|
||||
setGlobal(&env);
|
||||
|
||||
if (argc == 2) {
|
||||
const char* runTestsArg = "--run-tests";
|
||||
if (strncmp(argv[1], runTestsArg, strlen(runTestsArg)) == 0) {
|
||||
int ret = runTests(strcmp(argv[1] + strlen(runTestsArg), "=detailed") == 0);
|
||||
shredDictionary();
|
||||
deleteEnv(global());
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
readFile(SCRIPTDIR "/lib.pbl", &env);
|
||||
|
||||
Object o = parseEval("(def prompt \"pebblisp::> \")", &env);
|
||||
cleanObject(&o);
|
||||
o = parseEval("(def preprocess (fn (text) (text)))", &env);
|
||||
cleanObject(&o);
|
||||
|
||||
sprintf(config, "%s/.pebblisp.pbl", home);
|
||||
readFile(config, &env);
|
||||
|
||||
if (argc >= 2) {
|
||||
FILE* file = fopen(argv[1], "r");
|
||||
if (file) {
|
||||
// Execute a file
|
||||
loadArgsIntoEnv(argc, argv, &env);
|
||||
_readFile(file, &env);
|
||||
} else {
|
||||
// Run arguments directly as pl code
|
||||
Object r = numberObject(0);
|
||||
for (int i = 1; i < argc; i++) {
|
||||
r = parseEval(argv[i], &env);
|
||||
printAndClean(&r);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Run a repl
|
||||
loadArgsIntoEnv(argc, argv, &env);
|
||||
repl(&env);
|
||||
}
|
||||
deleteEnv(&env);
|
||||
shredDictionary();
|
||||
// eprintf("totalSearchDepth: %d of %d searches\n", getTotalSearchDepth(), getTotalSearches());
|
||||
// eprintf("\nHEAP-ALLOCATED OBJECTS: %d\n", getAllocations());
|
||||
// eprintf("TOTAL OBJECT.C ALLOC: %zu\n", getBytes());
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // STANDALONE
|
||||
|
|
|
@ -97,6 +97,8 @@ int _readFile(FILE* input, struct Environment* env);
|
|||
|
||||
int readFile(const char* filename, struct Environment* env);
|
||||
|
||||
struct Slice* getLastOpen();
|
||||
|
||||
#endif /* STANDALONE */
|
||||
|
||||
fn(mapO, "map",
|
||||
|
|
Loading…
Reference in New Issue