From fc4f0bef28689b07af3aea862f06376e281796f1 Mon Sep 17 00:00:00 2001 From: Sage Vaillancourt Date: Tue, 5 Apr 2022 20:05:58 -0400 Subject: [PATCH] Move main() etc. into main.c --- src/Makefile | 2 +- src/examples/pebblisp.pbl | 14 +-- src/main.c | 234 ++++++++++++++++++++++++++++++++++++++ src/main.h | 4 + src/pebblisp.c | 197 ++------------------------------ src/pebblisp.h | 2 + 6 files changed, 256 insertions(+), 197 deletions(-) create mode 100644 src/main.c create mode 100644 src/main.h diff --git a/src/Makefile b/src/Makefile index eb4a050..a56ab83 100644 --- a/src/Makefile +++ b/src/Makefile @@ -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 diff --git a/src/examples/pebblisp.pbl b/src/examples/pebblisp.pbl index a6a4793..063e3b4 100644 --- a/src/examples/pebblisp.pbl +++ b/src/examples/pebblisp.pbl @@ -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 () ( diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..96684d7 --- /dev/null +++ b/src/main.c @@ -0,0 +1,234 @@ +#define _GNU_SOURCE + +#include "pebblisp.h" + +#include +#include +#include + +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("\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 +#include + +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()); +} \ No newline at end of file diff --git a/src/main.h b/src/main.h new file mode 100644 index 0000000..6b296b9 --- /dev/null +++ b/src/main.h @@ -0,0 +1,4 @@ +#ifndef PEBBLISP_MAIN_H +#define PEBBLISP_MAIN_H + +#endif // PEBBLISP_MAIN_H diff --git a/src/pebblisp.c b/src/pebblisp.c index 49b08b4..7309eaf 100644 --- a/src/pebblisp.c +++ b/src/pebblisp.c @@ -1,20 +1,11 @@ -#ifdef STANDALONE -#define _GNU_SOURCE - -#endif - -#include "pebblisp.h" - #include #include #include "tokens.h" +#include "pebblisp.h" #ifdef STANDALONE -#include -#include - #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("\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 -#include - -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 diff --git a/src/pebblisp.h b/src/pebblisp.h index 534d1e2..af3d3ac 100644 --- a/src/pebblisp.h +++ b/src/pebblisp.h @@ -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",