ussval_t* builtin_load(ussenv_t* e, ussval_t* a) { UASSERT_NUM("load", a, 1); UASSERT_TYPE("load", a, 0, UVAL_STR); /* Parse File given by string name */ mpc_result_t r; parser_t *parser = parser_toplevel(); if (mpc_parse_contents(a->cell[0]->str, parser->uss, &r)) { fprintf(stderr, "DEBUG: loading: %s\n", a->cell[0]->str); ussenv_put(e, ussval_new_sym("file-path"), a->cell[0]); ussenv_put(e, ussval_new_sym("file-dir"), ussval_new_str(dirname(a->cell[0]->str))); /* Read contents */ ussval_t *expr = ussval_read(r.output); mpc_ast_delete(r.output); /* Evaluate each Expression */ while (expr->count) { ussval_t *x = ussval_eval(e, ussval_pop(expr, 0)); /* If Evaluation leads to error print it */ if (x->type == UVAL_ERR) { ussval_println(x); } ussval_del(x); } /* Delete expressions and arguments */ ussval_del(expr); ussval_del(a); parser_cleanup(parser); //lenv_put(e, lval_sym("file-path"), LVAL_NIL); //lenv_put(e, lval_sym("file-dir"), LVAL_NIL); /* Return empty list */ return ussval_new_sexpr(); } else { /* Get Parse Error as String */ char *err_msg = mpc_err_string(r.error); mpc_err_delete(r.error); /* Create new error message using it */ ussval_t *err = ussval_new_err("Could not load Library %s", err_msg); free(err_msg); ussval_del(a); parser_cleanup(parser); /* Cleanup and return error */ return err; } }
int main(int argc, char** argv) { GC_INIT(); ussenv_t *e = ussenv_new(); ussenv_common_builtins(e); char *prelude_path = join_path(STDLIB_PATH, true, "prelude.uss"); ussval_t *prelude = ussval_eval_from_file(e, prelude_path); /* If the result is an error be sure to print it */ if (prelude->type == UVAL_ERR) { ussval_println(prelude); } ussval_del(prelude); fprintf(stderr, "argv[0]=%s argv[1]=%s\n", argv[0], argv[1]); if (argc >= 2) { /* loop over each supplied filename (starting from 1) */ for (int i = 1; i < argc; i++) { ussval_t *x = ussval_eval_from_file(e, argv[i]); /* If the result is an error be sure to print it */ if (x->type == UVAL_ERR) { ussval_println(x); } ussval_del(x); } } else { char buf[4096]; parser_t *parser = parser_toplevel(); mpc_result_t r; ussval_t *x = UVAL_NIL; while(fgets(buf, sizeof(buf), stdin)) { if (mpc_parse("<stdin>", buf, parser->uss, &r)) { // mpc_ast_print(r.output); x = ussval_eval(e, ussval_read(r.output)); mpc_ast_delete(r.output); } else { mpc_err_print(r.error); mpc_err_delete(r.error); } } ussval_println(x); parser_cleanup(parser); } ussenv_del(e); return 0; }
int main(int argc, char** argv) { // Initialization parser_init(); lenv* env = lenv_new(); builtins_init(env); if (argc >= 2) { // Loop over file names for (int i = 1; i < argc; i++) { lval* args = lval_add(lval_sexpr(), lval_str(argv[i])); lval* result = builtin_load(env, args); if (result->type == LVAL_ERR) { lval_println(env, result); } lval_del(result); } } else { // Welcome message puts("MLisp Version 0.1dev"); puts("Enter 'quit' to exit\n"); while (1) { char* input = read_input(); add_history(input); if (input == NULL || strstr(input, "exit") || strstr(input, "quit")) { puts("Bye!"); if (input != NULL) { xfree(input); } break; } lval* result = NULL; mpc_err_t* parser_error = NULL; if (parse("<stdin>", input, env, &result, &parser_error)) { if (!(result->type == LVAL_SEXPR && result->count == 0)) { char* repr = lval_repr(env, result); printf("%s\n", repr); xfree(repr); } lval_del(result); } else { mpc_err_print(parser_error); mpc_err_delete(parser_error); } xfree(input); } } lenv_del(env); // Undefine and delete our parsers parser_cleanup(); return 0; }
void parser_free(parser_t *self) { // opposite of parser_init parser_cleanup(self); free(self); }
int parser_init(parser_t *self) { int sz; /* Initialize data buffers */ self->stream = NULL; self->words = NULL; self->word_starts = NULL; self->line_start = NULL; self->line_fields = NULL; // token stream self->stream = (char*) malloc(STREAM_INIT_SIZE * sizeof(char)); if (self->stream == NULL) { return PARSER_OUT_OF_MEMORY; } self->stream_cap = STREAM_INIT_SIZE; self->stream_len = 0; // word pointers and metadata sz = STREAM_INIT_SIZE / 10; sz = sz? sz : 1; self->words = (char**) malloc(sz * sizeof(char*)); self->word_starts = (int*) malloc(sz * sizeof(int)); self->words_cap = sz; self->words_len = 0; // line pointers and metadata self->line_start = (int*) malloc(sz * sizeof(int)); self->line_fields = (int*) malloc(sz * sizeof(int)); self->lines_cap = sz; self->lines = 0; self->file_lines = 0; if (self->stream == NULL || self->words == NULL || self->word_starts == NULL || self->line_start == NULL || self->line_fields == NULL) { parser_cleanup(self); return PARSER_OUT_OF_MEMORY; } /* amount of bytes buffered */ self->datalen = 0; self->datapos = 0; self->line_start[0] = 0; self->line_fields[0] = 0; self->pword_start = self->stream; self->word_start = 0; self->state = START_RECORD; self->error_msg = NULL; self->warn_msg = NULL; self->commentchar = '\0'; return 0; }
/** * mnt_table_parse_stream: * @tb: tab pointer * @f: file stream * @filename: filename used for debug and error messages * * Returns: 0 on success, negative number in case of error. */ int mnt_table_parse_stream(struct libmnt_table *tb, FILE *f, const char *filename) { int rc = -1; int flags = 0; pid_t tid = -1; struct libmnt_fs *fs = NULL; struct libmnt_parser pa = { .line = 0 }; assert(tb); assert(f); assert(filename); DBG(TAB, ul_debugobj(tb, "%s: start parsing [entries=%d, filter=%s]", filename, mnt_table_get_nents(tb), tb->fltrcb ? "yes" : "not")); pa.filename = filename; pa.f = f; /* necessary for /proc/mounts only, the /proc/self/mountinfo * parser sets the flag properly */ if (filename && strcmp(filename, _PATH_PROC_MOUNTS) == 0) flags = MNT_FS_KERNEL; while (!feof(f)) { if (!fs) { fs = mnt_new_fs(); if (!fs) goto err; } rc = mnt_table_parse_next(&pa, tb, fs); if (!rc && tb->fltrcb && tb->fltrcb(fs, tb->fltrcb_data)) rc = 1; /* filtered out by callback... */ if (!rc) { rc = mnt_table_add_fs(tb, fs); fs->flags |= flags; if (rc == 0 && tb->fmt == MNT_FMT_MOUNTINFO) { rc = kernel_fs_postparse(tb, fs, &tid, filename); if (rc) mnt_table_remove_fs(tb, fs); } } if (rc) { if (rc > 0) { mnt_reset_fs(fs); assert(fs->refcount == 1); continue; /* recoverable error, reuse fs*/ } mnt_unref_fs(fs); if (feof(f)) break; goto err; /* fatal error */ } mnt_unref_fs(fs); fs = NULL; } DBG(TAB, ul_debugobj(tb, "%s: stop parsing (%d entries)", filename, mnt_table_get_nents(tb))); parser_cleanup(&pa); return 0; err: DBG(TAB, ul_debugobj(tb, "%s: parse error (rc=%d)", filename, rc)); parser_cleanup(&pa); return rc; } /** * mnt_table_parse_file: * @tb: tab pointer * @filename: file * * Parses the whole table (e.g. /etc/fstab) and appends new records to the @tab. * * The libmount parser ignores broken (syntax error) lines, these lines are * reported to the caller by the errcb() function (see mnt_table_set_parser_errcb()). * * Returns: 0 on success, negative number in case of error. */ int mnt_table_parse_file(struct libmnt_table *tb, const char *filename) { FILE *f; int rc; if (!filename || !tb) return -EINVAL; f = fopen(filename, "r" UL_CLOEXECSTR); if (f) { rc = mnt_table_parse_stream(tb, f, filename); fclose(f); } else rc = -errno; DBG(TAB, ul_debugobj(tb, "parsing done [filename=%s, rc=%d]", filename, rc)); return rc; }