From 6c03383cd1f6f5e5aba954314f52773a0bccdc9a Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Tue, 6 Nov 2018 05:39:14 +0000 Subject: [PATCH 01/21] Cast argument to unsigned char before feeding to ctype.h functions The behavior of the `` functions is undefined for negative arguments (other than `EOF`). In such a situation, the argument should be cast to `unsiged char` for safety. References: - C Programming: A Modern Approach, 2nd Edition: page 612, chapter 23.5 --- mpc.c | 1016 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 508 insertions(+), 508 deletions(-) diff --git a/mpc.c b/mpc.c index 6f9bac4..0ed0a37 100644 --- a/mpc.c +++ b/mpc.c @@ -27,24 +27,24 @@ static mpc_state_t mpc_state_new(void) { */ /* -** In mpc the input type has three modes of +** In mpc the input type has three modes of ** operation: String, File and Pipe. ** -** String is easy. The whole contents are +** String is easy. The whole contents are ** loaded into a buffer and scanned through. -** The cursor can jump around at will making +** The cursor can jump around at will making ** backtracking easy. ** ** The second is a File which is also somewhat -** easy. The contents are never loaded into +** easy. The contents are never loaded into ** memory but backtracking can still be achieved ** by seeking in the file at different positions. ** ** The final mode is Pipe. This is the difficult -** one. As we assume pipes cannot be seeked - and -** only support a single character lookahead at -** any point, when the input is marked for a -** potential backtracking we start buffering any +** one. As we assume pipes cannot be seeked - and +** only support a single character lookahead at +** any point, when the input is marked for a +** potential backtracking we start buffering any ** input. ** ** This means that if we are requested to seek @@ -78,43 +78,43 @@ typedef struct { typedef struct { int type; - char *filename; + char *filename; mpc_state_t state; - + char *string; char *buffer; FILE *file; - + int suppress; int backtrack; int marks_slots; int marks_num; mpc_state_t *marks; - + char *lasts; char last; - + size_t mem_index; char mem_full[MPC_INPUT_MEM_NUM]; mpc_mem_t mem[MPC_INPUT_MEM_NUM]; - + } mpc_input_t; static mpc_input_t *mpc_input_new_string(const char *filename, const char *string) { mpc_input_t *i = malloc(sizeof(mpc_input_t)); - + i->filename = malloc(strlen(filename) + 1); strcpy(i->filename, filename); i->type = MPC_INPUT_STRING; - + i->state = mpc_state_new(); - + i->string = malloc(strlen(string) + 1); strcpy(i->string, string); i->buffer = NULL; i->file = NULL; - + i->suppress = 0; i->backtrack = 1; i->marks_num = 0; @@ -122,29 +122,29 @@ static mpc_input_t *mpc_input_new_string(const char *filename, const char *strin i->marks = malloc(sizeof(mpc_state_t) * i->marks_slots); i->lasts = malloc(sizeof(char) * i->marks_slots); i->last = '\0'; - + i->mem_index = 0; memset(i->mem_full, 0, sizeof(char) * MPC_INPUT_MEM_NUM); - + return i; } static mpc_input_t *mpc_input_new_nstring(const char *filename, const char *string, size_t length) { mpc_input_t *i = malloc(sizeof(mpc_input_t)); - + i->filename = malloc(strlen(filename) + 1); strcpy(i->filename, filename); i->type = MPC_INPUT_STRING; - + i->state = mpc_state_new(); - + i->string = malloc(length + 1); strncpy(i->string, string, length); i->string[length] = '\0'; i->buffer = NULL; i->file = NULL; - + i->suppress = 0; i->backtrack = 1; i->marks_num = 0; @@ -152,10 +152,10 @@ static mpc_input_t *mpc_input_new_nstring(const char *filename, const char *stri i->marks = malloc(sizeof(mpc_state_t) * i->marks_slots); i->lasts = malloc(sizeof(char) * i->marks_slots); i->last = '\0'; - + i->mem_index = 0; memset(i->mem_full, 0, sizeof(char) * MPC_INPUT_MEM_NUM); - + return i; } @@ -163,17 +163,17 @@ static mpc_input_t *mpc_input_new_nstring(const char *filename, const char *stri static mpc_input_t *mpc_input_new_pipe(const char *filename, FILE *pipe) { mpc_input_t *i = malloc(sizeof(mpc_input_t)); - + i->filename = malloc(strlen(filename) + 1); strcpy(i->filename, filename); - + i->type = MPC_INPUT_PIPE; i->state = mpc_state_new(); - + i->string = NULL; i->buffer = NULL; i->file = pipe; - + i->suppress = 0; i->backtrack = 1; i->marks_num = 0; @@ -181,27 +181,27 @@ static mpc_input_t *mpc_input_new_pipe(const char *filename, FILE *pipe) { i->marks = malloc(sizeof(mpc_state_t) * i->marks_slots); i->lasts = malloc(sizeof(char) * i->marks_slots); i->last = '\0'; - + i->mem_index = 0; memset(i->mem_full, 0, sizeof(char) * MPC_INPUT_MEM_NUM); - + return i; - + } static mpc_input_t *mpc_input_new_file(const char *filename, FILE *file) { - + mpc_input_t *i = malloc(sizeof(mpc_input_t)); - + i->filename = malloc(strlen(filename) + 1); strcpy(i->filename, filename); i->type = MPC_INPUT_FILE; i->state = mpc_state_new(); - + i->string = NULL; i->buffer = NULL; i->file = file; - + i->suppress = 0; i->backtrack = 1; i->marks_num = 0; @@ -209,20 +209,20 @@ static mpc_input_t *mpc_input_new_file(const char *filename, FILE *file) { i->marks = malloc(sizeof(mpc_state_t) * i->marks_slots); i->lasts = malloc(sizeof(char) * i->marks_slots); i->last = '\0'; - + i->mem_index = 0; memset(i->mem_full, 0, sizeof(char) * MPC_INPUT_MEM_NUM); - + return i; } static void mpc_input_delete(mpc_input_t *i) { - + free(i->filename); - + if (i->type == MPC_INPUT_STRING) { free(i->string); } if (i->type == MPC_INPUT_PIPE) { free(i->buffer); } - + free(i->marks); free(i->lasts); free(i); @@ -237,9 +237,9 @@ static int mpc_mem_ptr(mpc_input_t *i, void *p) { static void *mpc_malloc(mpc_input_t *i, size_t n) { size_t j; char *p; - + if (n > sizeof(mpc_mem_t)) { return malloc(n); } - + j = i->mem_index; do { if (!i->mem_full[i->mem_index]) { @@ -250,7 +250,7 @@ static void *mpc_malloc(mpc_input_t *i, size_t n) { } i->mem_index = (i->mem_index+1) % MPC_INPUT_MEM_NUM; } while (j != i->mem_index); - + return malloc(n); } @@ -268,18 +268,18 @@ static void mpc_free(mpc_input_t *i, void *p) { } static void *mpc_realloc(mpc_input_t *i, void *p, size_t n) { - + char *q = NULL; - + if (!mpc_mem_ptr(i, p)) { return realloc(p, n); } - + if (n > sizeof(mpc_mem_t)) { q = malloc(n); memcpy(q, p, sizeof(mpc_mem_t)); mpc_free(i, p); return q; } - + return p; } @@ -289,7 +289,7 @@ static void *mpc_export(mpc_input_t *i, void *p) { q = malloc(sizeof(mpc_mem_t)); memcpy(q, p, sizeof(mpc_mem_t)); mpc_free(i, p); - return q; + return q; } static void mpc_input_backtrack_disable(mpc_input_t *i) { i->backtrack--; } @@ -299,11 +299,11 @@ static void mpc_input_suppress_disable(mpc_input_t *i) { i->suppress--; } static void mpc_input_suppress_enable(mpc_input_t *i) { i->suppress++; } static void mpc_input_mark(mpc_input_t *i) { - + if (i->backtrack < 1) { return; } - + i->marks_num++; - + if (i->marks_num > i->marks_slots) { i->marks_slots = i->marks_num + i->marks_num / 2; i->marks = realloc(i->marks, sizeof(mpc_state_t) * i->marks_slots); @@ -312,46 +312,46 @@ static void mpc_input_mark(mpc_input_t *i) { i->marks[i->marks_num-1] = i->state; i->lasts[i->marks_num-1] = i->last; - + if (i->type == MPC_INPUT_PIPE && i->marks_num == 1) { i->buffer = calloc(1, 1); } - + } static void mpc_input_unmark(mpc_input_t *i) { - + if (i->backtrack < 1) { return; } - + i->marks_num--; - + if (i->marks_slots > i->marks_num + i->marks_num / 2 && i->marks_slots > MPC_INPUT_MARKS_MIN) { - i->marks_slots = + i->marks_slots = i->marks_num > MPC_INPUT_MARKS_MIN ? i->marks_num : MPC_INPUT_MARKS_MIN; i->marks = realloc(i->marks, sizeof(mpc_state_t) * i->marks_slots); - i->lasts = realloc(i->lasts, sizeof(char) * i->marks_slots); + i->lasts = realloc(i->lasts, sizeof(char) * i->marks_slots); } - + if (i->type == MPC_INPUT_PIPE && i->marks_num == 0) { free(i->buffer); i->buffer = NULL; } - + } static void mpc_input_rewind(mpc_input_t *i) { - + if (i->backtrack < 1) { return; } - + i->state = i->marks[i->marks_num-1]; i->last = i->lasts[i->marks_num-1]; - + if (i->type == MPC_INPUT_FILE) { fseek(i->file, i->state.pos, SEEK_SET); } - + mpc_input_unmark(i); } @@ -371,17 +371,17 @@ static int mpc_input_terminated(mpc_input_t *i) { } static char mpc_input_getc(mpc_input_t *i) { - + char c = '\0'; - + switch (i->type) { - + case MPC_INPUT_STRING: return i->string[i->state.pos]; case MPC_INPUT_FILE: c = fgetc(i->file); return c; case MPC_INPUT_PIPE: - + if (!i->buffer) { c = getc(i->file); return c; } - + if (i->buffer && mpc_input_buffer_in_range(i)) { c = mpc_input_buffer_get(i); return c; @@ -389,34 +389,34 @@ static char mpc_input_getc(mpc_input_t *i) { c = getc(i->file); return c; } - + default: return c; } } static char mpc_input_peekc(mpc_input_t *i) { - + char c = '\0'; - + switch (i->type) { case MPC_INPUT_STRING: return i->string[i->state.pos]; - case MPC_INPUT_FILE: - + case MPC_INPUT_FILE: + c = fgetc(i->file); if (feof(i->file)) { return '\0'; } - + fseek(i->file, -1, SEEK_CUR); return c; - + case MPC_INPUT_PIPE: - + if (!i->buffer) { c = getc(i->file); if (feof(i->file)) { return '\0'; } ungetc(c, i->file); return c; } - + if (i->buffer && mpc_input_buffer_in_range(i)) { return mpc_input_buffer_get(i); } else { @@ -425,10 +425,10 @@ static char mpc_input_peekc(mpc_input_t *i) { ungetc(c, i->file); return c; } - + default: return c; } - + } static int mpc_input_failure(mpc_input_t *i, char c) { @@ -437,13 +437,13 @@ static int mpc_input_failure(mpc_input_t *i, char c) { case MPC_INPUT_STRING: { break; } case MPC_INPUT_FILE: fseek(i->file, -1, SEEK_CUR); { break; } case MPC_INPUT_PIPE: { - + if (!i->buffer) { ungetc(c, i->file); break; } - + if (i->buffer && mpc_input_buffer_in_range(i)) { break; } else { - ungetc(c, i->file); + ungetc(c, i->file); } } default: { break; } @@ -452,29 +452,29 @@ static int mpc_input_failure(mpc_input_t *i, char c) { } static int mpc_input_success(mpc_input_t *i, char c, char **o) { - + if (i->type == MPC_INPUT_PIPE && i->buffer && !mpc_input_buffer_in_range(i)) { i->buffer = realloc(i->buffer, strlen(i->buffer) + 2); i->buffer[strlen(i->buffer) + 1] = '\0'; i->buffer[strlen(i->buffer) + 0] = c; } - + i->last = c; i->state.pos++; i->state.col++; - + if (c == '\n') { i->state.col = 0; i->state.row++; } - + if (o) { (*o) = mpc_malloc(i, 2); (*o)[0] = c; (*o)[1] = '\0'; } - + return 1; } @@ -493,29 +493,29 @@ static int mpc_input_char(mpc_input_t *i, char c, char **o) { static int mpc_input_range(mpc_input_t *i, char c, char d, char **o) { char x = mpc_input_getc(i); if (mpc_input_terminated(i)) { return 0; } - return x >= c && x <= d ? mpc_input_success(i, x, o) : mpc_input_failure(i, x); + return x >= c && x <= d ? mpc_input_success(i, x, o) : mpc_input_failure(i, x); } static int mpc_input_oneof(mpc_input_t *i, const char *c, char **o) { char x = mpc_input_getc(i); if (mpc_input_terminated(i)) { return 0; } - return strchr(c, x) != 0 ? mpc_input_success(i, x, o) : mpc_input_failure(i, x); + return strchr(c, x) != 0 ? mpc_input_success(i, x, o) : mpc_input_failure(i, x); } static int mpc_input_noneof(mpc_input_t *i, const char *c, char **o) { char x = mpc_input_getc(i); if (mpc_input_terminated(i)) { return 0; } - return strchr(c, x) == 0 ? mpc_input_success(i, x, o) : mpc_input_failure(i, x); + return strchr(c, x) == 0 ? mpc_input_success(i, x, o) : mpc_input_failure(i, x); } static int mpc_input_satisfy(mpc_input_t *i, int(*cond)(char), char **o) { char x = mpc_input_getc(i); if (mpc_input_terminated(i)) { return 0; } - return cond(x) ? mpc_input_success(i, x, o) : mpc_input_failure(i, x); + return cond(x) ? mpc_input_success(i, x, o) : mpc_input_failure(i, x); } static int mpc_input_string(mpc_input_t *i, const char *c, char **o) { - + const char *x = c; mpc_input_mark(i); @@ -527,7 +527,7 @@ static int mpc_input_string(mpc_input_t *i, const char *c, char **o) { x++; } mpc_input_unmark(i); - + *o = mpc_malloc(i, strlen(c) + 1); strcpy(*o, c); return 1; @@ -597,12 +597,12 @@ static void mpc_err_string_cat(char *buffer, int *pos, int *max, char const *fmt static char char_unescape_buffer[4]; static const char *mpc_err_char_unescape(char c) { - + char_unescape_buffer[0] = '\''; char_unescape_buffer[1] = ' '; char_unescape_buffer[2] = '\''; char_unescape_buffer[3] = '\0'; - + switch (c) { case '\a': return "bell"; case '\b': return "backspace"; @@ -617,42 +617,42 @@ static const char *mpc_err_char_unescape(char c) { char_unescape_buffer[1] = c; return char_unescape_buffer; } - + } char *mpc_err_string(mpc_err_t *x) { - int i; - int pos = 0; + int i; + int pos = 0; int max = 1023; char *buffer = calloc(1, 1024); - + if (x->failure) { mpc_err_string_cat(buffer, &pos, &max, "%s: error: %s\n", x->filename, x->failure); return buffer; } - - mpc_err_string_cat(buffer, &pos, &max, + + mpc_err_string_cat(buffer, &pos, &max, "%s:%i:%i: error: expected ", x->filename, x->state.row+1, x->state.col+1); - + if (x->expected_num == 0) { mpc_err_string_cat(buffer, &pos, &max, "ERROR: NOTHING EXPECTED"); } if (x->expected_num == 1) { mpc_err_string_cat(buffer, &pos, &max, "%s", x->expected[0]); } if (x->expected_num >= 2) { - + for (i = 0; i < x->expected_num-2; i++) { mpc_err_string_cat(buffer, &pos, &max, "%s, ", x->expected[i]); - } - - mpc_err_string_cat(buffer, &pos, &max, "%s or %s", - x->expected[x->expected_num-2], + } + + mpc_err_string_cat(buffer, &pos, &max, "%s or %s", + x->expected[x->expected_num-2], x->expected[x->expected_num-1]); } - + mpc_err_string_cat(buffer, &pos, &max, " at "); mpc_err_string_cat(buffer, &pos, &max, mpc_err_char_unescape(x->recieved)); mpc_err_string_cat(buffer, &pos, &max, "\n"); - + return realloc(buffer, strlen(buffer) + 1); } @@ -740,17 +740,17 @@ static void mpc_err_add_expected(mpc_input_t *i, mpc_err_t *x, char *expected) { } static mpc_err_t *mpc_err_or(mpc_input_t *i, mpc_err_t** x, int n) { - + int j, k, fst; mpc_err_t *e; - + fst = -1; for (j = 0; j < n; j++) { if (x[j] != NULL) { fst = j; } } - + if (fst == -1) { return NULL; } - + e = mpc_malloc(i, sizeof(mpc_err_t)); e->state = mpc_state_invalid(); e->expected_num = 0; @@ -758,36 +758,36 @@ static mpc_err_t *mpc_err_or(mpc_input_t *i, mpc_err_t** x, int n) { e->failure = NULL; e->filename = mpc_malloc(i, strlen(x[fst]->filename)+1); strcpy(e->filename, x[fst]->filename); - + for (j = 0; j < n; j++) { if (x[j] == NULL) { continue; } if (x[j]->state.pos > e->state.pos) { e->state = x[j]->state; } } - + for (j = 0; j < n; j++) { if (x[j] == NULL) { continue; } if (x[j]->state.pos < e->state.pos) { continue; } - + if (x[j]->failure) { e->failure = mpc_malloc(i, strlen(x[j]->failure)+1); strcpy(e->failure, x[j]->failure); break; } - + e->recieved = x[j]->recieved; - + for (k = 0; k < x[j]->expected_num; k++) { if (!mpc_err_contains_expected(i, e, x[j]->expected[k])) { mpc_err_add_expected(i, e, x[j]->expected[k]); } } } - + for (j = 0; j < n; j++) { if (x[j] == NULL) { continue; } mpc_err_delete_internal(i, x[j]); } - + return e; } @@ -796,9 +796,9 @@ static mpc_err_t *mpc_err_repeat(mpc_input_t *i, mpc_err_t *x, const char *prefi int j = 0; size_t l = 0; char *expect = NULL; - + if (x == NULL) { return NULL; } - + if (x->expected_num == 0) { expect = mpc_calloc(i, 1, 1); x->expected_num = 1; @@ -806,7 +806,7 @@ static mpc_err_t *mpc_err_repeat(mpc_input_t *i, mpc_err_t *x, const char *prefi x->expected[0] = expect; return x; } - + else if (x->expected_num == 1) { expect = mpc_malloc(i, strlen(prefix) + strlen(x->expected[0]) + 1); strcpy(expect, prefix); @@ -815,9 +815,9 @@ static mpc_err_t *mpc_err_repeat(mpc_input_t *i, mpc_err_t *x, const char *prefi x->expected[0] = expect; return x; } - + else if (x->expected_num > 1) { - + l += strlen(prefix); for (j = 0; j < x->expected_num-2; j++) { l += strlen(x->expected[j]) + strlen(", "); @@ -825,9 +825,9 @@ static mpc_err_t *mpc_err_repeat(mpc_input_t *i, mpc_err_t *x, const char *prefi l += strlen(x->expected[x->expected_num-2]); l += strlen(" or "); l += strlen(x->expected[x->expected_num-1]); - + expect = mpc_malloc(i, l + 1); - + strcpy(expect, prefix); for (j = 0; j < x->expected_num-2; j++) { strcat(expect, x->expected[j]); strcat(expect, ", "); @@ -837,13 +837,13 @@ static mpc_err_t *mpc_err_repeat(mpc_input_t *i, mpc_err_t *x, const char *prefi strcat(expect, x->expected[x->expected_num-1]); for (j = 0; j < x->expected_num; j++) { mpc_free(i, x->expected[j]); } - + x->expected_num = 1; x->expected = mpc_realloc(i, x->expected, sizeof(char*) * x->expected_num); x->expected[0] = expect; return x; } - + return NULL; } @@ -905,7 +905,7 @@ enum { MPC_TYPE_CHECK = 25, MPC_TYPE_CHECK_WITH = 26, - + MPC_TYPE_SOI = 27, MPC_TYPE_EOI = 28 }; @@ -960,7 +960,7 @@ static mpc_val_t *mpcf_input_nth_free(mpc_input_t *i, int n, mpc_val_t **xs, int for (j = 0; j < n; j++) { if (j != x) { mpc_free(i, xs[j]); } } return xs[x]; } - + static mpc_val_t *mpcf_input_fst_free(mpc_input_t *i, int n, mpc_val_t **xs) { return mpcf_input_nth_free(i, n, xs, 0); } static mpc_val_t *mpcf_input_snd_free(mpc_input_t *i, int n, mpc_val_t **xs) { return mpcf_input_nth_free(i, n, xs, 1); } static mpc_val_t *mpcf_input_trd_free(mpc_input_t *i, int n, mpc_val_t **xs) { return mpcf_input_nth_free(i, n, xs, 2); } @@ -1036,14 +1036,14 @@ enum { else { MPC_FAILURE(NULL); } static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_err_t **e) { - + int j = 0, k = 0; mpc_result_t results_stk[MPC_PARSE_STACK_MIN]; mpc_result_t *results; int results_slots = MPC_PARSE_STACK_MIN; - + switch (p->type) { - + /* Basic Parsers */ case MPC_TYPE_ANY: MPC_PRIMITIVE(mpc_input_any(i, (char**)&r->output)); @@ -1056,25 +1056,25 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e case MPC_TYPE_ANCHOR: MPC_PRIMITIVE(mpc_input_anchor(i, p->data.anchor.f, (char**)&r->output)); case MPC_TYPE_SOI: MPC_PRIMITIVE(mpc_input_soi(i, (char**)&r->output)); case MPC_TYPE_EOI: MPC_PRIMITIVE(mpc_input_eoi(i, (char**)&r->output)); - + /* Other parsers */ - + case MPC_TYPE_UNDEFINED: MPC_FAILURE(mpc_err_fail(i, "Parser Undefined!")); case MPC_TYPE_PASS: MPC_SUCCESS(NULL); case MPC_TYPE_FAIL: MPC_FAILURE(mpc_err_fail(i, p->data.fail.m)); case MPC_TYPE_LIFT: MPC_SUCCESS(p->data.lift.lf()); case MPC_TYPE_LIFT_VAL: MPC_SUCCESS(p->data.lift.x); case MPC_TYPE_STATE: MPC_SUCCESS(mpc_input_state_copy(i)); - + /* Application Parsers */ - + case MPC_TYPE_APPLY: if (mpc_parse_run(i, p->data.apply.x, r, e)) { MPC_SUCCESS(mpc_parse_apply(i, p->data.apply.f, r->output)); } else { MPC_FAILURE(r->output); } - + case MPC_TYPE_APPLY_TO: if (mpc_parse_run(i, p->data.apply_to.x, r, e)) { MPC_SUCCESS(mpc_parse_apply_to(i, p->data.apply_to.f, r->output, p->data.apply_to.d)); @@ -1113,21 +1113,21 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e mpc_input_suppress_disable(i); MPC_FAILURE(mpc_err_new(i, p->data.expect.m)); } - + case MPC_TYPE_PREDICT: mpc_input_backtrack_disable(i); - if (mpc_parse_run(i, p->data.predict.x, r, e)) { + if (mpc_parse_run(i, p->data.predict.x, r, e)) { mpc_input_backtrack_enable(i); MPC_SUCCESS(r->output); } else { mpc_input_backtrack_enable(i); MPC_FAILURE(r->error); } - + /* Optional Parsers */ - + /* TODO: Update Not Error Message */ - + case MPC_TYPE_NOT: mpc_input_mark(i); mpc_input_suppress_enable(i); @@ -1141,7 +1141,7 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e mpc_input_suppress_disable(i); MPC_SUCCESS(p->data.not.lf()); } - + case MPC_TYPE_MAYBE: if (mpc_parse_run(i, p->data.not.x, r, e)) { MPC_SUCCESS(r->output); @@ -1149,13 +1149,13 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e *e = mpc_err_merge(i, *e, r->error); MPC_SUCCESS(p->data.not.lf()); } - + /* Repeat Parsers */ - + case MPC_TYPE_MANY: - + results = results_stk; - + while (mpc_parse_run(i, p->data.repeat.x, &results[j], e)) { j++; if (j == MPC_PARSE_STACK_MIN) { @@ -1167,17 +1167,17 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e results = mpc_realloc(i, results, sizeof(mpc_result_t) * results_slots); } } - + *e = mpc_err_merge(i, *e, results[j].error); - + MPC_SUCCESS( mpc_parse_fold(i, p->data.repeat.f, j, (mpc_val_t**)results); if (j >= MPC_PARSE_STACK_MIN) { mpc_free(i, results); }); - + case MPC_TYPE_MANY1: - + results = results_stk; - + while (mpc_parse_run(i, p->data.repeat.x, &results[j], e)) { j++; if (j == MPC_PARSE_STACK_MIN) { @@ -1189,31 +1189,31 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e results = mpc_realloc(i, results, sizeof(mpc_result_t) * results_slots); } } - + if (j == 0) { MPC_FAILURE( mpc_err_many1(i, results[j].error); if (j >= MPC_PARSE_STACK_MIN) { mpc_free(i, results); }); } else { - + *e = mpc_err_merge(i, *e, results[j].error); - + MPC_SUCCESS( mpc_parse_fold(i, p->data.repeat.f, j, (mpc_val_t**)results); if (j >= MPC_PARSE_STACK_MIN) { mpc_free(i, results); }); } - + case MPC_TYPE_COUNT: - + results = p->data.repeat.n > MPC_PARSE_STACK_MIN ? mpc_malloc(i, sizeof(mpc_result_t) * p->data.repeat.n) : results_stk; - + while (mpc_parse_run(i, p->data.repeat.x, &results[j], e)) { j++; if (j == p->data.repeat.n) { break; } } - + if (j == p->data.repeat.n) { MPC_SUCCESS( mpc_parse_fold(i, p->data.repeat.f, j, (mpc_val_t**)results); @@ -1224,39 +1224,39 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e } MPC_FAILURE( mpc_err_count(i, results[j].error, p->data.repeat.n); - if (p->data.repeat.n > MPC_PARSE_STACK_MIN) { mpc_free(i, results); }); + if (p->data.repeat.n > MPC_PARSE_STACK_MIN) { mpc_free(i, results); }); } - + /* Combinatory Parsers */ - + case MPC_TYPE_OR: - + if (p->data.or.n == 0) { MPC_SUCCESS(NULL); } - + results = p->data.or.n > MPC_PARSE_STACK_MIN ? mpc_malloc(i, sizeof(mpc_result_t) * p->data.or.n) : results_stk; - + for (j = 0; j < p->data.or.n; j++) { if (mpc_parse_run(i, p->data.or.xs[j], &results[j], e)) { MPC_SUCCESS(results[j].output; if (p->data.or.n > MPC_PARSE_STACK_MIN) { mpc_free(i, results); }); } else { *e = mpc_err_merge(i, *e, results[j].error); - } + } } - + MPC_FAILURE(NULL; if (p->data.or.n > MPC_PARSE_STACK_MIN) { mpc_free(i, results); }); - + case MPC_TYPE_AND: - + if (p->data.and.n == 0) { MPC_SUCCESS(NULL); } - + results = p->data.or.n > MPC_PARSE_STACK_MIN ? mpc_malloc(i, sizeof(mpc_result_t) * p->data.or.n) : results_stk; - + mpc_input_mark(i); for (j = 0; j < p->data.and.n; j++) { if (!mpc_parse_run(i, p->data.and.xs[j], &results[j], e)) { @@ -1268,20 +1268,20 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e if (p->data.or.n > MPC_PARSE_STACK_MIN) { mpc_free(i, results); }); } } - mpc_input_unmark(i); + mpc_input_unmark(i); MPC_SUCCESS( mpc_parse_fold(i, p->data.and.f, j, (mpc_val_t**)results); if (p->data.or.n > MPC_PARSE_STACK_MIN) { mpc_free(i, results); }); - + /* End */ - + default: - + MPC_FAILURE(mpc_err_fail(i, "Unknown Parser Type Id!")); } - + return 0; - + } #undef MPC_SUCCESS @@ -1335,16 +1335,16 @@ int mpc_parse_pipe(const char *filename, FILE *pipe, mpc_parser_t *p, mpc_result } int mpc_parse_contents(const char *filename, mpc_parser_t *p, mpc_result_t *r) { - + FILE *f = fopen(filename, "rb"); int res; - + if (f == NULL) { r->output = NULL; r->error = mpc_err_file(filename, "Unable to open file!"); return 0; } - + res = mpc_parse_file(filename, f, p, r); fclose(f); return res; @@ -1357,63 +1357,63 @@ int mpc_parse_contents(const char *filename, mpc_parser_t *p, mpc_result_t *r) { static void mpc_undefine_unretained(mpc_parser_t *p, int force); static void mpc_undefine_or(mpc_parser_t *p) { - + int i; for (i = 0; i < p->data.or.n; i++) { mpc_undefine_unretained(p->data.or.xs[i], 0); } free(p->data.or.xs); - + } static void mpc_undefine_and(mpc_parser_t *p) { - + int i; for (i = 0; i < p->data.and.n; i++) { mpc_undefine_unretained(p->data.and.xs[i], 0); } free(p->data.and.xs); free(p->data.and.dxs); - + } static void mpc_undefine_unretained(mpc_parser_t *p, int force) { - + if (p->retained && !force) { return; } - + switch (p->type) { - + case MPC_TYPE_FAIL: free(p->data.fail.m); break; - - case MPC_TYPE_ONEOF: + + case MPC_TYPE_ONEOF: case MPC_TYPE_NONEOF: case MPC_TYPE_STRING: - free(p->data.string.x); + free(p->data.string.x); break; - + case MPC_TYPE_APPLY: mpc_undefine_unretained(p->data.apply.x, 0); break; case MPC_TYPE_APPLY_TO: mpc_undefine_unretained(p->data.apply_to.x, 0); break; case MPC_TYPE_PREDICT: mpc_undefine_unretained(p->data.predict.x, 0); break; - + case MPC_TYPE_MAYBE: case MPC_TYPE_NOT: mpc_undefine_unretained(p->data.not.x, 0); break; - + case MPC_TYPE_EXPECT: mpc_undefine_unretained(p->data.expect.x, 0); free(p->data.expect.m); break; - + case MPC_TYPE_MANY: case MPC_TYPE_MANY1: case MPC_TYPE_COUNT: mpc_undefine_unretained(p->data.repeat.x, 0); break; - + case MPC_TYPE_OR: mpc_undefine_or(p); break; case MPC_TYPE_AND: mpc_undefine_and(p); break; - + case MPC_TYPE_CHECK: mpc_undefine_unretained(p->data.check.x, 0); free(p->data.check.e); @@ -1426,12 +1426,12 @@ static void mpc_undefine_unretained(mpc_parser_t *p, int force) { default: break; } - + if (!force) { free(p->name); free(p); } - + } void mpc_delete(mpc_parser_t *p) { @@ -1439,13 +1439,13 @@ void mpc_delete(mpc_parser_t *p) { if (p->type != MPC_TYPE_UNDEFINED) { mpc_undefine_unretained(p, 0); - } - + } + free(p->name); free(p); - + } else { - mpc_undefine_unretained(p, 0); + mpc_undefine_unretained(p, 0); } } @@ -1472,54 +1472,54 @@ mpc_parser_t *mpc_new(const char *name) { mpc_parser_t *mpc_copy(mpc_parser_t *a) { int i = 0; mpc_parser_t *p; - + if (a->retained) { return a; } - + p = mpc_undefined(); p->retained = a->retained; p->type = a->type; p->data = a->data; - + if (a->name) { p->name = malloc(strlen(a->name)+1); strcpy(p->name, a->name); } - + switch (a->type) { - + case MPC_TYPE_FAIL: p->data.fail.m = malloc(strlen(a->data.fail.m)+1); strcpy(p->data.fail.m, a->data.fail.m); break; - - case MPC_TYPE_ONEOF: + + case MPC_TYPE_ONEOF: case MPC_TYPE_NONEOF: case MPC_TYPE_STRING: p->data.string.x = malloc(strlen(a->data.string.x)+1); strcpy(p->data.string.x, a->data.string.x); break; - + case MPC_TYPE_APPLY: p->data.apply.x = mpc_copy(a->data.apply.x); break; case MPC_TYPE_APPLY_TO: p->data.apply_to.x = mpc_copy(a->data.apply_to.x); break; case MPC_TYPE_PREDICT: p->data.predict.x = mpc_copy(a->data.predict.x); break; - + case MPC_TYPE_MAYBE: case MPC_TYPE_NOT: p->data.not.x = mpc_copy(a->data.not.x); break; - + case MPC_TYPE_EXPECT: p->data.expect.x = mpc_copy(a->data.expect.x); p->data.expect.m = malloc(strlen(a->data.expect.m)+1); strcpy(p->data.expect.m, a->data.expect.m); break; - + case MPC_TYPE_MANY: case MPC_TYPE_MANY1: case MPC_TYPE_COUNT: p->data.repeat.x = mpc_copy(a->data.repeat.x); break; - + case MPC_TYPE_OR: p->data.or.xs = malloc(a->data.or.n * sizeof(mpc_parser_t*)); for (i = 0; i < a->data.or.n; i++) { @@ -1536,7 +1536,7 @@ mpc_parser_t *mpc_copy(mpc_parser_t *a) { p->data.and.dxs[i] = a->data.and.dxs[i]; } break; - + case MPC_TYPE_CHECK: p->data.check.x = mpc_copy(a->data.check.x); p->data.check.e = malloc(strlen(a->data.check.e)+1); @@ -1551,7 +1551,7 @@ mpc_parser_t *mpc_copy(mpc_parser_t *a) { default: break; } - + return p; } @@ -1562,7 +1562,7 @@ mpc_parser_t *mpc_undefine(mpc_parser_t *p) { } mpc_parser_t *mpc_define(mpc_parser_t *p, mpc_parser_t *a) { - + if (p->retained) { p->type = a->type; p->data = a->data; @@ -1572,21 +1572,21 @@ mpc_parser_t *mpc_define(mpc_parser_t *p, mpc_parser_t *a) { p->data = a2->data; free(a2); } - + free(a); - return p; + return p; } void mpc_cleanup(int n, ...) { int i; mpc_parser_t **list = malloc(sizeof(mpc_parser_t*) * n); - + va_list va; va_start(va, n); for (i = 0; i < n; i++) { list[i] = va_arg(va, mpc_parser_t*); } for (i = 0; i < n; i++) { mpc_undefine(list[i]); } - for (i = 0; i < n; i++) { mpc_delete(list[i]); } - va_end(va); + for (i = 0; i < n; i++) { mpc_delete(list[i]); } + va_end(va); free(list); } @@ -1606,7 +1606,7 @@ mpc_parser_t *mpc_fail(const char *m) { } /* -** As `snprintf` is not ANSI standard this +** As `snprintf` is not ANSI standard this ** function `mpc_failf` should be considered ** unsafe. ** @@ -1617,7 +1617,7 @@ mpc_parser_t *mpc_fail(const char *m) { ** the buffer length using precision specifiers ** such as `%.512s`. ** -** - Patch this function in your code base to +** - Patch this function in your code base to ** use `snprintf` or whatever variant your ** system supports. ** @@ -1626,18 +1626,18 @@ mpc_parser_t *mpc_fail(const char *m) { */ mpc_parser_t *mpc_failf(const char *fmt, ...) { - + va_list va; char *buffer; mpc_parser_t *p = mpc_undefined(); p->type = MPC_TYPE_FAIL; - + va_start(va, fmt); buffer = malloc(2048); vsprintf(buffer, fmt, va); va_end(va); - + buffer = realloc(buffer, strlen(buffer) + 1); p->data.fail.m = buffer; return p; @@ -1681,7 +1681,7 @@ mpc_parser_t *mpc_expect(mpc_parser_t *a, const char *expected) { } /* -** As `snprintf` is not ANSI standard this +** As `snprintf` is not ANSI standard this ** function `mpc_expectf` should be considered ** unsafe. ** @@ -1692,7 +1692,7 @@ mpc_parser_t *mpc_expect(mpc_parser_t *a, const char *expected) { ** the buffer length using precision specifiers ** such as `%.512s`. ** -** - Patch this function in your code base to +** - Patch this function in your code base to ** use `snprintf` or whatever variant your ** system supports. ** @@ -1706,12 +1706,12 @@ mpc_parser_t *mpc_expectf(mpc_parser_t *a, const char *fmt, ...) { mpc_parser_t *p = mpc_undefined(); p->type = MPC_TYPE_EXPECT; - + va_start(va, fmt); buffer = malloc(2048); vsprintf(buffer, fmt, va); va_end(va); - + buffer = realloc(buffer, strlen(buffer) + 1); p->data.expect.x = a; p->data.expect.m = buffer; @@ -1913,17 +1913,17 @@ mpc_parser_t *mpc_or(int n, ...) { va_list va; mpc_parser_t *p = mpc_undefined(); - + p->type = MPC_TYPE_OR; p->data.or.n = n; p->data.or.xs = malloc(sizeof(mpc_parser_t*) * n); - - va_start(va, n); + + va_start(va, n); for (i = 0; i < n; i++) { p->data.or.xs[i] = va_arg(va, mpc_parser_t*); } va_end(va); - + return p; } @@ -1933,22 +1933,22 @@ mpc_parser_t *mpc_and(int n, mpc_fold_t f, ...) { va_list va; mpc_parser_t *p = mpc_undefined(); - + p->type = MPC_TYPE_AND; p->data.and.n = n; p->data.and.f = f; p->data.and.xs = malloc(sizeof(mpc_parser_t*) * n); p->data.and.dxs = malloc(sizeof(mpc_dtor_t) * (n-1)); - va_start(va, f); + va_start(va, f); for (i = 0; i < n; i++) { p->data.and.xs[i] = va_arg(va, mpc_parser_t*); } for (i = 0; i < (n-1); i++) { p->data.and.dxs[i] = va_arg(va, mpc_dtor_t); - } + } va_end(va); - + return p; } @@ -1981,7 +1981,7 @@ static int mpc_boundary_anchor(char prev, char next) { static int mpc_boundary_newline_anchor(char prev, char next) { (void)next; - return prev == '\n'; + return prev == '\n'; } mpc_parser_t *mpc_boundary(void) { return mpc_expect(mpc_anchor(mpc_boundary_anchor), "word boundary"); } @@ -2016,9 +2016,9 @@ mpc_parser_t *mpc_number(void) { return mpc_expect(mpc_or(3, mpc_int(), mpc_hex( mpc_parser_t *mpc_real(void) { /* [+-]?\d+(\.\d+)?([eE][+-]?[0-9]+)? */ - + mpc_parser_t *p0, *p1, *p2, *p30, *p31, *p32, *p3; - + p0 = mpc_maybe_lift(mpc_oneof("+-"), mpcf_ctor_str); p1 = mpc_digits(); p2 = mpc_maybe_lift(mpc_and(2, mpcf_strfold, mpc_char('.'), mpc_digits(), free), mpcf_ctor_str); @@ -2026,7 +2026,7 @@ mpc_parser_t *mpc_real(void) { p31 = mpc_maybe_lift(mpc_oneof("+-"), mpcf_ctor_str); p32 = mpc_digits(); p3 = mpc_maybe_lift(mpc_and(3, mpcf_strfold, p30, p31, p32, free, free), mpcf_ctor_str); - + return mpc_expect(mpc_and(4, mpcf_strfold, p0, p1, p2, p3, free, free, free), "real"); } @@ -2044,15 +2044,15 @@ mpc_parser_t *mpc_string_lit(void) { return mpc_expect(mpc_between(mpc_many(mpcf_strfold, strchar), free, "\"", "\""), "string"); } -mpc_parser_t *mpc_regex_lit(void) { +mpc_parser_t *mpc_regex_lit(void) { mpc_parser_t *regexchar = mpc_or(2, mpc_escape(), mpc_noneof("/")); return mpc_expect(mpc_between(mpc_many(mpcf_strfold, regexchar), free, "/", "/"), "regex"); } mpc_parser_t *mpc_ident(void) { - mpc_parser_t *p0, *p1; + mpc_parser_t *p0, *p1; p0 = mpc_or(2, mpc_alpha(), mpc_underscore()); - p1 = mpc_many(mpcf_strfold, mpc_alphanum()); + p1 = mpc_many(mpcf_strfold, mpc_alphanum()); return mpc_and(2, mpcf_strfold, p0, p1, free); } @@ -2113,7 +2113,7 @@ mpc_parser_t *mpc_tok_squares(mpc_parser_t *a, mpc_dtor_t ad) { return mpc_tok_ ** a parser directly - as we are parsing. ** ** This is certainly something that -** would be less elegant/interesting +** would be less elegant/interesting ** in a two-phase parser which first ** builds an AST and then traverses it ** to generate the object. @@ -2129,7 +2129,7 @@ mpc_parser_t *mpc_tok_squares(mpc_parser_t *a, mpc_dtor_t ad) { return mpc_tok_ ** ### Regular Expression Grammar ** ** : | ( "|" ) -** +** ** : * ** ** : @@ -2137,7 +2137,7 @@ mpc_parser_t *mpc_tok_squares(mpc_parser_t *a, mpc_dtor_t ad) { return mpc_tok_ ** | "+" ** | "?" ** | "{" "}" -** +** ** : ** | "\" ** | "(" ")" @@ -2172,7 +2172,7 @@ static mpc_val_t *mpcf_re_repeat(int n, mpc_val_t **xs) { num = *(int*)xs[1]; free(xs[1]); } - + return mpc_count(num, mpcf_strfold, xs[0], free); } @@ -2199,21 +2199,21 @@ static mpc_parser_t *mpc_re_escape_char(char c) { } static mpc_val_t *mpcf_re_escape(mpc_val_t *x, void* data) { - + int mode = *((int*)data); char *s = x; mpc_parser_t *p; - + /* Any Character */ if (s[0] == '.') { free(s); if (mode & MPC_RE_DOTALL) { - return mpc_any(); + return mpc_any(); } else { return mpc_expect(mpc_noneof("\n"), "any character except a newline"); } } - + /* Start of Input */ if (s[0] == '^') { free(s); @@ -2223,21 +2223,21 @@ static mpc_val_t *mpcf_re_escape(mpc_val_t *x, void* data) { return mpc_and(2, mpcf_snd, mpc_soi(), mpc_lift(mpcf_ctor_str), free); } } - + /* End of Input */ if (s[0] == '$') { - free(s); + free(s); if (mode & MPC_RE_MULTILINE) { - return mpc_or(2, - mpc_newline(), - mpc_and(2, mpcf_snd, mpc_eoi(), mpc_lift(mpcf_ctor_str), free)); + return mpc_or(2, + mpc_newline(), + mpc_and(2, mpcf_snd, mpc_eoi(), mpc_lift(mpcf_ctor_str), free)); } else { - return mpc_or(2, - mpc_and(2, mpcf_fst, mpc_newline(), mpc_eoi(), free), - mpc_and(2, mpcf_snd, mpc_eoi(), mpc_lift(mpcf_ctor_str), free)); + return mpc_or(2, + mpc_and(2, mpcf_fst, mpc_newline(), mpc_eoi(), free), + mpc_and(2, mpcf_snd, mpc_eoi(), mpc_lift(mpcf_ctor_str), free)); } } - + /* Regex Escape */ if (s[0] == '\\') { p = mpc_re_escape_char(s[1]); @@ -2245,7 +2245,7 @@ static mpc_val_t *mpcf_re_escape(mpc_val_t *x, void* data) { free(s); return p; } - + /* Regex Standard */ p = mpc_char(s[0]); free(s); @@ -2270,7 +2270,7 @@ static const char *mpc_re_range_escape_char(char c) { } static mpc_val_t *mpcf_re_range(mpc_val_t *x) { - + mpc_parser_t *out; size_t i, j; size_t start, end; @@ -2278,13 +2278,13 @@ static mpc_val_t *mpcf_re_range(mpc_val_t *x) { const char *s = x; int comp = s[0] == '^' ? 1 : 0; char *range = calloc(1,1); - - if (s[0] == '\0') { free(range); free(x); return mpc_fail("Invalid Regex Range Expression"); } - if (s[0] == '^' && + + if (s[0] == '\0') { free(range); free(x); return mpc_fail("Invalid Regex Range Expression"); } + if (s[0] == '^' && s[1] == '\0') { free(range); free(x); return mpc_fail("Invalid Regex Range Expression"); } - + for (i = comp; i < strlen(s); i++){ - + /* Regex Range Escape */ if (s[i] == '\\') { tmp = mpc_re_range_escape_char(s[i+1]); @@ -2294,11 +2294,11 @@ static mpc_val_t *mpcf_re_range(mpc_val_t *x) { } else { range = realloc(range, strlen(range) + 1 + 1); range[strlen(range) + 1] = '\0'; - range[strlen(range) + 0] = s[i+1]; + range[strlen(range) + 0] = s[i+1]; } i++; } - + /* Regex Range...Range */ else if (s[i] == '-') { if (s[i+1] == '\0' || i == 0) { @@ -2311,24 +2311,24 @@ static mpc_val_t *mpcf_re_range(mpc_val_t *x) { range = realloc(range, strlen(range) + 1 + 1 + 1); range[strlen(range) + 1] = '\0'; range[strlen(range) + 0] = (char)j; - } + } } } - + /* Regex Range Normal */ else { range = realloc(range, strlen(range) + 1 + 1); range[strlen(range) + 1] = '\0'; range[strlen(range) + 0] = s[i]; } - + } - + out = comp == 1 ? mpc_noneof(range) : mpc_oneof(range); - + free(x); free(range); - + return out; } @@ -2337,26 +2337,26 @@ mpc_parser_t *mpc_re(const char *re) { } mpc_parser_t *mpc_re_mode(const char *re, int mode) { - + char *err_msg; mpc_parser_t *err_out; mpc_result_t r; - mpc_parser_t *Regex, *Term, *Factor, *Base, *Range, *RegexEnclose; - + mpc_parser_t *Regex, *Term, *Factor, *Base, *Range, *RegexEnclose; + Regex = mpc_new("regex"); Term = mpc_new("term"); Factor = mpc_new("factor"); Base = mpc_new("base"); Range = mpc_new("range"); - + mpc_define(Regex, mpc_and(2, mpcf_re_or, - Term, + Term, mpc_maybe(mpc_and(2, mpcf_snd_free, mpc_char('|'), Regex, free)), (mpc_dtor_t)mpc_delete )); - + mpc_define(Term, mpc_many(mpcf_re_and, Factor)); - + mpc_define(Factor, mpc_and(2, mpcf_re_repeat, Base, mpc_or(5, @@ -2365,42 +2365,42 @@ mpc_parser_t *mpc_re_mode(const char *re, int mode) { mpc_pass()), (mpc_dtor_t)mpc_delete )); - + mpc_define(Base, mpc_or(4, mpc_parens(Regex, (mpc_dtor_t)mpc_delete), mpc_squares(Range, (mpc_dtor_t)mpc_delete), mpc_apply_to(mpc_escape(), mpcf_re_escape, &mode), mpc_apply_to(mpc_noneof(")|"), mpcf_re_escape, &mode) )); - + mpc_define(Range, mpc_apply( mpc_many(mpcf_strfold, mpc_or(2, mpc_escape(), mpc_noneof("]"))), mpcf_re_range )); - + RegexEnclose = mpc_whole(mpc_predictive(Regex), (mpc_dtor_t)mpc_delete); - + mpc_optimise(RegexEnclose); mpc_optimise(Regex); mpc_optimise(Term); mpc_optimise(Factor); mpc_optimise(Base); mpc_optimise(Range); - + if(!mpc_parse("", re, RegexEnclose, &r)) { err_msg = mpc_err_string(r.error); err_out = mpc_failf("Invalid Regex: %s", err_msg); - mpc_err_delete(r.error); + mpc_err_delete(r.error); free(err_msg); r.output = err_out; } - + mpc_cleanup(6, RegexEnclose, Regex, Term, Factor, Base, Range); - + mpc_optimise(r.output); - + return r.output; - + } /* @@ -2443,7 +2443,7 @@ mpc_val_t *mpcf_float(mpc_val_t *x) { mpc_val_t *mpcf_strtriml(mpc_val_t *x) { char *s = x; - while (isspace(*s)) { + while (isspace((unsigned char)*s)) { memmove(s, s+1, strlen(s)); } return s; @@ -2452,7 +2452,7 @@ mpc_val_t *mpcf_strtriml(mpc_val_t *x) { mpc_val_t *mpcf_strtrimr(mpc_val_t *x) { char *s = x; size_t l = strlen(s); - while (isspace(s[l-1])) { + while (isspace((unsigned char)s[l-1])) { s[l-1] = '\0'; l--; } return s; @@ -2465,9 +2465,9 @@ mpc_val_t *mpcf_strtrim(mpc_val_t *x) { static const char mpc_escape_input_c[] = { '\a', '\b', '\f', '\n', '\r', '\t', '\v', '\\', '\'', '\"', '\0'}; - + static const char *mpc_escape_output_c[] = { - "\\a", "\\b", "\\f", "\\n", "\\r", "\\t", + "\\a", "\\b", "\\f", "\\n", "\\r", "\\t", "\\v", "\\\\", "\\'", "\\\"", "\\0", NULL}; static const char mpc_escape_input_raw_re[] = { '/' }; @@ -2480,15 +2480,15 @@ static const char mpc_escape_input_raw_cchar[] = { '\'' }; static const char *mpc_escape_output_raw_cchar[] = { "\\'", NULL }; static mpc_val_t *mpcf_escape_new(mpc_val_t *x, const char *input, const char **output) { - + int i; int found; char buff[2]; char *s = x; char *y = calloc(1, 1); - + while (*s) { - + i = 0; found = 0; @@ -2501,33 +2501,33 @@ static mpc_val_t *mpcf_escape_new(mpc_val_t *x, const char *input, const char ** } i++; } - + if (!found) { y = realloc(y, strlen(y) + 2); buff[0] = *s; buff[1] = '\0'; strcat(y, buff); } - + s++; } - - + + return y; } static mpc_val_t *mpcf_unescape_new(mpc_val_t *x, const char *input, const char **output) { - + int i; int found = 0; char buff[2]; char *s = x; char *y = calloc(1, 1); - + while (*s) { - + i = 0; found = 0; - + while (output[i]) { if ((*(s+0)) == output[i][0] && (*(s+1)) == output[i][1]) { @@ -2540,19 +2540,19 @@ static mpc_val_t *mpcf_unescape_new(mpc_val_t *x, const char *input, const char } i++; } - + if (!found) { y = realloc(y, strlen(y) + 1 + 1); buff[0] = *s; buff[1] = '\0'; strcat(y, buff); } - + if (*s == '\0') { break; } else { s++; } } - + return y; - + } mpc_val_t *mpcf_escape(mpc_val_t *x) { @@ -2570,13 +2570,13 @@ mpc_val_t *mpcf_unescape(mpc_val_t *x) { mpc_val_t *mpcf_escape_regex(mpc_val_t *x) { mpc_val_t *y = mpcf_escape_new(x, mpc_escape_input_raw_re, mpc_escape_output_raw_re); free(x); - return y; + return y; } mpc_val_t *mpcf_unescape_regex(mpc_val_t *x) { mpc_val_t *y = mpcf_unescape_new(x, mpc_escape_input_raw_re, mpc_escape_output_raw_re); free(x); - return y; + return y; } mpc_val_t *mpcf_escape_string_raw(mpc_val_t *x) { @@ -2615,7 +2615,7 @@ static mpc_val_t *mpcf_nth_free(int n, mpc_val_t **xs, int x) { } return xs[x]; } - + mpc_val_t *mpcf_fst_free(int n, mpc_val_t **xs) { return mpcf_nth_free(n, xs, 0); } mpc_val_t *mpcf_snd_free(int n, mpc_val_t **xs) { return mpcf_nth_free(n, xs, 1); } mpc_val_t *mpcf_trd_free(int n, mpc_val_t **xs) { return mpcf_nth_free(n, xs, 2); } @@ -2631,24 +2631,24 @@ mpc_val_t *mpcf_freefold(int n, mpc_val_t **xs) { mpc_val_t *mpcf_strfold(int n, mpc_val_t **xs) { int i; size_t l = 0; - + if (n == 0) { return calloc(1, 1); } - + for (i = 0; i < n; i++) { l += strlen(xs[i]); } - + xs[0] = realloc(xs[0], l + 1); - + for (i = 1; i < n; i++) { strcat(xs[0], xs[i]); free(xs[i]); } - + return xs[0]; } mpc_val_t *mpcf_maths(int n, mpc_val_t **xs) { int **vs = (int**)xs; (void) n; - + switch(((char*)xs[1])[0]) { case '*': { *vs[0] *= *vs[2]; }; break; @@ -2658,9 +2658,9 @@ mpc_val_t *mpcf_maths(int n, mpc_val_t **xs) { case '-': { *vs[0] -= *vs[2]; }; break; default: break; } - + free(xs[1]); free(xs[2]); - + return xs[0]; } @@ -2669,19 +2669,19 @@ mpc_val_t *mpcf_maths(int n, mpc_val_t **xs) { */ static void mpc_print_unretained(mpc_parser_t *p, int force) { - + /* TODO: Print Everything Escaped */ - + int i; char *s, *e; char buff[2]; - + if (p->retained && !force) {; if (p->name) { printf("<%s>", p->name); } else { printf(""); } return; } - + if (p->type == MPC_TYPE_UNDEFINED) { printf(""); } if (p->type == MPC_TYPE_PASS) { printf("<:>"); } if (p->type == MPC_TYPE_FAIL) { printf(""); } @@ -2692,7 +2692,7 @@ static void mpc_print_unretained(mpc_parser_t *p, int force) { printf("%s", p->data.expect.m); /*mpc_print_unretained(p->data.expect.x, 0);*/ } - + if (p->type == MPC_TYPE_ANY) { printf("<.>"); } if (p->type == MPC_TYPE_SATISFY) { printf(""); } @@ -2705,7 +2705,7 @@ static void mpc_print_unretained(mpc_parser_t *p, int force) { printf("'%s'", s); free(s); } - + if (p->type == MPC_TYPE_RANGE) { buff[0] = p->data.range.x; buff[1] = '\0'; s = mpcf_escape_new( @@ -2721,7 +2721,7 @@ static void mpc_print_unretained(mpc_parser_t *p, int force) { free(s); free(e); } - + if (p->type == MPC_TYPE_ONEOF) { s = mpcf_escape_new( p->data.string.x, @@ -2730,7 +2730,7 @@ static void mpc_print_unretained(mpc_parser_t *p, int force) { printf("[%s]", s); free(s); } - + if (p->type == MPC_TYPE_NONEOF) { s = mpcf_escape_new( p->data.string.x, @@ -2739,7 +2739,7 @@ static void mpc_print_unretained(mpc_parser_t *p, int force) { printf("[^%s]", s); free(s); } - + if (p->type == MPC_TYPE_STRING) { s = mpcf_escape_new( p->data.string.x, @@ -2748,7 +2748,7 @@ static void mpc_print_unretained(mpc_parser_t *p, int force) { printf("\"%s\"", s); free(s); } - + if (p->type == MPC_TYPE_APPLY) { mpc_print_unretained(p->data.apply.x, 0); } if (p->type == MPC_TYPE_APPLY_TO) { mpc_print_unretained(p->data.apply_to.x, 0); } if (p->type == MPC_TYPE_PREDICT) { mpc_print_unretained(p->data.predict.x, 0); } @@ -2759,7 +2759,7 @@ static void mpc_print_unretained(mpc_parser_t *p, int force) { if (p->type == MPC_TYPE_MANY) { mpc_print_unretained(p->data.repeat.x, 0); printf("*"); } if (p->type == MPC_TYPE_MANY1) { mpc_print_unretained(p->data.repeat.x, 0); printf("+"); } if (p->type == MPC_TYPE_COUNT) { mpc_print_unretained(p->data.repeat.x, 0); printf("{%i}", p->data.repeat.n); } - + if (p->type == MPC_TYPE_OR) { printf("("); for(i = 0; i < p->data.or.n-1; i++) { @@ -2769,7 +2769,7 @@ static void mpc_print_unretained(mpc_parser_t *p, int force) { mpc_print_unretained(p->data.or.xs[p->data.or.n-1], 0); printf(")"); } - + if (p->type == MPC_TYPE_AND) { printf("("); for(i = 0; i < p->data.and.n-1; i++) { @@ -2826,22 +2826,22 @@ int mpc_test_fail(mpc_parser_t *p, const char *s, const void *d, destructor(r.output); return 1; } - + } else { mpc_err_delete(r.error); return 1; } - + } int mpc_test_pass(mpc_parser_t *p, const char *s, const void *d, - int(*tester)(const void*, const void*), - mpc_dtor_t destructor, + int(*tester)(const void*, const void*), + mpc_dtor_t destructor, void(*printer)(const void*)) { - mpc_result_t r; + mpc_result_t r; if (mpc_parse("", s, p, &r)) { - + if (tester(r.output, d)) { destructor(r.output); return 1; @@ -2851,14 +2851,14 @@ int mpc_test_pass(mpc_parser_t *p, const char *s, const void *d, destructor(r.output); return 0; } - - } else { + + } else { mpc_err_print(r.error); mpc_err_delete(r.error); return 0; - + } - + } @@ -2867,20 +2867,20 @@ int mpc_test_pass(mpc_parser_t *p, const char *s, const void *d, */ void mpc_ast_delete(mpc_ast_t *a) { - + int i; - + if (a == NULL) { return; } - + for (i = 0; i < a->children_num; i++) { mpc_ast_delete(a->children[i]); } - + free(a->children); free(a->tag); free(a->contents); free(a); - + } static void mpc_ast_delete_no_children(mpc_ast_t *a) { @@ -2891,39 +2891,39 @@ static void mpc_ast_delete_no_children(mpc_ast_t *a) { } mpc_ast_t *mpc_ast_new(const char *tag, const char *contents) { - + mpc_ast_t *a = malloc(sizeof(mpc_ast_t)); - + a->tag = malloc(strlen(tag) + 1); strcpy(a->tag, tag); - + a->contents = malloc(strlen(contents) + 1); strcpy(a->contents, contents); - + a->state = mpc_state_new(); - + a->children_num = 0; a->children = NULL; return a; - + } mpc_ast_t *mpc_ast_build(int n, const char *tag, ...) { - + mpc_ast_t *a = mpc_ast_new(tag, ""); - + int i; va_list va; va_start(va, tag); - + for (i = 0; i < n; i++) { mpc_ast_add_child(a, va_arg(va, mpc_ast_t*)); } - + va_end(va); - + return a; - + } mpc_ast_t *mpc_ast_add_root(mpc_ast_t *a) { @@ -2940,17 +2940,17 @@ mpc_ast_t *mpc_ast_add_root(mpc_ast_t *a) { } int mpc_ast_eq(mpc_ast_t *a, mpc_ast_t *b) { - + int i; if (strcmp(a->tag, b->tag) != 0) { return 0; } if (strcmp(a->contents, b->contents) != 0) { return 0; } if (a->children_num != b->children_num) { return 0; } - + for (i = 0; i < a->children_num; i++) { if (!mpc_ast_eq(a->children[i], b->children[i])) { return 0; } } - + return 1; } @@ -2991,29 +2991,29 @@ mpc_ast_t *mpc_ast_state(mpc_ast_t *a, mpc_state_t s) { } static void mpc_ast_print_depth(mpc_ast_t *a, int d, FILE *fp) { - + int i; - + if (a == NULL) { fprintf(fp, "NULL\n"); return; } - + for (i = 0; i < d; i++) { fprintf(fp, " "); } - + if (strlen(a->contents)) { - fprintf(fp, "%s:%lu:%lu '%s'\n", a->tag, + fprintf(fp, "%s:%lu:%lu '%s'\n", a->tag, (long unsigned int)(a->state.row+1), (long unsigned int)(a->state.col+1), a->contents); } else { fprintf(fp, "%s \n", a->tag); } - + for (i = 0; i < a->children_num; i++) { mpc_ast_print_depth(a->children[i], d+1, fp); } - + } void mpc_ast_print(mpc_ast_t *a) { @@ -3193,22 +3193,22 @@ void mpc_ast_traverse_free(mpc_ast_trav_t **trav) { } mpc_val_t *mpcf_fold_ast(int n, mpc_val_t **xs) { - + int i, j; mpc_ast_t** as = (mpc_ast_t**)xs; mpc_ast_t *r; - + if (n == 0) { return NULL; } if (n == 1) { return xs[0]; } if (n == 2 && xs[1] == NULL) { return xs[0]; } if (n == 2 && xs[0] == NULL) { return xs[1]; } - + r = mpc_ast_new(">", ""); - + for (i = 0; i < n; i++) { - + if (as[i] == NULL) { continue; } - + if (as[i] && as[i]->children_num == 0) { mpc_ast_add_child(r, as[i]); } else if (as[i] && as[i]->children_num == 1) { @@ -3220,13 +3220,13 @@ mpc_val_t *mpcf_fold_ast(int n, mpc_val_t **xs) { } mpc_ast_delete_no_children(as[i]); } - + } - + if (r->children_num) { r->state = r->children[0]->state; } - + return r; } @@ -3273,44 +3273,44 @@ mpc_parser_t *mpca_or(int n, ...) { va_list va; mpc_parser_t *p = mpc_undefined(); - + p->type = MPC_TYPE_OR; p->data.or.n = n; p->data.or.xs = malloc(sizeof(mpc_parser_t*) * n); - - va_start(va, n); + + va_start(va, n); for (i = 0; i < n; i++) { p->data.or.xs[i] = va_arg(va, mpc_parser_t*); } va_end(va); - + return p; - + } mpc_parser_t *mpca_and(int n, ...) { - + int i; va_list va; - + mpc_parser_t *p = mpc_undefined(); - + p->type = MPC_TYPE_AND; p->data.and.n = n; p->data.and.f = mpcf_fold_ast; p->data.and.xs = malloc(sizeof(mpc_parser_t*) * n); p->data.and.dxs = malloc(sizeof(mpc_dtor_t) * (n-1)); - + va_start(va, n); for (i = 0; i < n; i++) { p->data.and.xs[i] = va_arg(va, mpc_parser_t*); } for (i = 0; i < (n-1); i++) { p->data.and.dxs[i] = (mpc_dtor_t)mpc_ast_delete; - } + } va_end(va); - - return p; + + return p; } mpc_parser_t *mpca_total(mpc_parser_t *a) { return mpc_total(a, (mpc_dtor_t)mpc_ast_delete); } @@ -3343,7 +3343,7 @@ mpc_parser_t *mpca_total(mpc_parser_t *a) { return mpc_total(a, (mpc_dtor_t)mpc_ ** ### Grammar Grammar ** ** : ( "|" ) | -** +** ** : * ** ** : @@ -3351,7 +3351,7 @@ mpc_parser_t *mpca_total(mpc_parser_t *a) { return mpc_total(a, (mpc_dtor_t)mpc_ ** | "+" ** | "?" ** | "{" "}" -** +** ** : "<" ( | ) ">" ** | ** | @@ -3374,14 +3374,14 @@ static mpc_val_t *mpcaf_grammar_or(int n, mpc_val_t **xs) { static mpc_val_t *mpcaf_grammar_and(int n, mpc_val_t **xs) { int i; - mpc_parser_t *p = mpc_pass(); + mpc_parser_t *p = mpc_pass(); for (i = 0; i < n; i++) { if (xs[i] != NULL) { p = mpca_and(2, p, xs[i]); } } return p; } -static mpc_val_t *mpcaf_grammar_repeat(int n, mpc_val_t **xs) { +static mpc_val_t *mpcaf_grammar_repeat(int n, mpc_val_t **xs) { int num; (void) n; if (xs[1] == NULL) { return xs[0]; } @@ -3420,7 +3420,7 @@ static mpc_val_t *mpcaf_fold_regex(int n, mpc_val_t **xs) { mpca_grammar_st_t *st = xs[2]; mpc_parser_t *p; int mode = MPC_RE_DEFAULT; - + (void)n; if (strchr(m, 'm')) { mode |= MPC_RE_MULTILINE; } if (strchr(m, 's')) { mode |= MPC_RE_DOTALL; } @@ -3428,7 +3428,7 @@ static mpc_val_t *mpcaf_fold_regex(int n, mpc_val_t **xs) { p = (st->flags & MPCA_LANG_WHITESPACE_SENSITIVE) ? mpc_re_mode(y, mode) : mpc_tok(mpc_re_mode(y, mode)); free(y); free(m); - + return mpca_state(mpca_tag(mpc_apply(p, mpcf_str_ast), "regex")); } @@ -3440,15 +3440,15 @@ static int is_number(const char* s) { } static mpc_parser_t *mpca_grammar_find_parser(char *x, mpca_grammar_st_t *st) { - + int i; mpc_parser_t *p; - + /* Case of Number */ if (is_number(x)) { i = strtol(x, NULL, 10); - + while (st->parsers_num <= i) { st->parsers_num++; st->parsers = realloc(st->parsers, sizeof(mpc_parser_t*) * st->parsers_num); @@ -3457,39 +3457,39 @@ static mpc_parser_t *mpca_grammar_find_parser(char *x, mpca_grammar_st_t *st) { return mpc_failf("No Parser in position %i! Only supplied %i Parsers!", i, st->parsers_num); } } - + return st->parsers[st->parsers_num-1]; - + /* Case of Identifier */ } else { - + /* Search Existing Parsers */ for (i = 0; i < st->parsers_num; i++) { mpc_parser_t *q = st->parsers[i]; if (q == NULL) { return mpc_failf("Unknown Parser '%s'!", x); } if (q->name && strcmp(q->name, x) == 0) { return q; } } - + /* Search New Parsers */ while (1) { - + p = va_arg(*st->va, mpc_parser_t*); - + st->parsers_num++; st->parsers = realloc(st->parsers, sizeof(mpc_parser_t*) * st->parsers_num); st->parsers[st->parsers_num-1] = p; - + if (p == NULL || p->name == NULL) { return mpc_failf("Unknown Parser '%s'!", x); } if (p->name && strcmp(p->name, x) == 0) { return p; } - + } - - } - + + } + } static mpc_val_t *mpcaf_grammar_id(mpc_val_t *x, void *s) { - + mpca_grammar_st_t *st = s; mpc_parser_t *p = mpca_grammar_find_parser(x, st); free(x); @@ -3502,30 +3502,30 @@ static mpc_val_t *mpcaf_grammar_id(mpc_val_t *x, void *s) { } mpc_parser_t *mpca_grammar_st(const char *grammar, mpca_grammar_st_t *st) { - + char *err_msg; mpc_parser_t *err_out; mpc_result_t r; mpc_parser_t *GrammarTotal, *Grammar, *Term, *Factor, *Base; - + GrammarTotal = mpc_new("grammar_total"); Grammar = mpc_new("grammar"); Term = mpc_new("term"); Factor = mpc_new("factor"); Base = mpc_new("base"); - + mpc_define(GrammarTotal, mpc_predictive(mpc_total(Grammar, mpc_soft_delete)) ); - + mpc_define(Grammar, mpc_and(2, mpcaf_grammar_or, Term, mpc_maybe(mpc_and(2, mpcf_snd_free, mpc_sym("|"), Grammar, free)), mpc_soft_delete )); - + mpc_define(Term, mpc_many1(mpcaf_grammar_and, Factor)); - + mpc_define(Factor, mpc_and(2, mpcaf_grammar_repeat, Base, mpc_or(6, @@ -3537,7 +3537,7 @@ mpc_parser_t *mpca_grammar_st(const char *grammar, mpca_grammar_st_t *st) { mpc_pass()), mpc_soft_delete )); - + mpc_define(Base, mpc_or(5, mpc_apply_to(mpc_tok(mpc_string_lit()), mpcaf_grammar_string, st), mpc_apply_to(mpc_tok(mpc_char_lit()), mpcaf_grammar_char, st), @@ -3545,13 +3545,13 @@ mpc_parser_t *mpca_grammar_st(const char *grammar, mpca_grammar_st_t *st) { mpc_apply_to(mpc_tok_braces(mpc_or(2, mpc_digits(), mpc_ident()), free), mpcaf_grammar_id, st), mpc_tok_parens(Grammar, mpc_soft_delete) )); - + mpc_optimise(GrammarTotal); mpc_optimise(Grammar); mpc_optimise(Factor); mpc_optimise(Term); mpc_optimise(Base); - + if(!mpc_parse("", grammar, GrammarTotal, &r)) { err_msg = mpc_err_string(r.error); err_out = mpc_failf("Invalid Grammar: %s", err_msg); @@ -3559,13 +3559,13 @@ mpc_parser_t *mpca_grammar_st(const char *grammar, mpca_grammar_st_t *st) { free(err_msg); r.output = err_out; } - + mpc_cleanup(5, GrammarTotal, Grammar, Term, Factor, Base); - + mpc_optimise(r.output); - + return (st->flags & MPCA_LANG_PREDICTIVE) ? mpc_predictive(r.output) : r.output; - + } mpc_parser_t *mpca_grammar(int flags, const char *grammar, ...) { @@ -3573,13 +3573,13 @@ mpc_parser_t *mpca_grammar(int flags, const char *grammar, ...) { mpc_parser_t *res; va_list va; va_start(va, grammar); - + st.va = &va; st.parsers_num = 0; st.parsers = NULL; st.flags = flags; - - res = mpca_grammar_st(grammar, &st); + + res = mpca_grammar_st(grammar, &st); free(st.parsers); va_end(va); return res; @@ -3599,20 +3599,20 @@ static mpc_val_t *mpca_stmt_afold(int n, mpc_val_t **xs) { (void) n; free(((char**)xs)[2]); free(((char**)xs)[4]); - + return stmt; } static mpc_val_t *mpca_stmt_fold(int n, mpc_val_t **xs) { - + int i; mpca_stmt_t **stmts = malloc(sizeof(mpca_stmt_t*) * (n+1)); - + for (i = 0; i < n; i++) { stmts[i] = xs[i]; } - stmts[n] = NULL; - + stmts[n] = NULL; + return stmts; } @@ -3621,11 +3621,11 @@ static void mpca_stmt_list_delete(mpc_val_t *x) { mpca_stmt_t **stmts = x; while(*stmts) { - mpca_stmt_t *stmt = *stmts; + mpca_stmt_t *stmt = *stmts; free(stmt->ident); free(stmt->name); mpc_soft_delete(stmt->grammar); - free(stmt); + free(stmt); stmts++; } free(x); @@ -3651,43 +3651,43 @@ static mpc_val_t *mpca_stmt_list_apply_to(mpc_val_t *x, void *s) { free(stmt); stmts++; } - + free(x); - + return NULL; } static mpc_err_t *mpca_lang_st(mpc_input_t *i, mpca_grammar_st_t *st) { - + mpc_result_t r; mpc_err_t *e; - mpc_parser_t *Lang, *Stmt, *Grammar, *Term, *Factor, *Base; - + mpc_parser_t *Lang, *Stmt, *Grammar, *Term, *Factor, *Base; + Lang = mpc_new("lang"); Stmt = mpc_new("stmt"); Grammar = mpc_new("grammar"); Term = mpc_new("term"); Factor = mpc_new("factor"); Base = mpc_new("base"); - + mpc_define(Lang, mpc_apply_to( mpc_total(mpc_predictive(mpc_many(mpca_stmt_fold, Stmt)), mpca_stmt_list_delete), mpca_stmt_list_apply_to, st )); - + mpc_define(Stmt, mpc_and(5, mpca_stmt_afold, mpc_tok(mpc_ident()), mpc_maybe(mpc_tok(mpc_string_lit())), mpc_sym(":"), Grammar, mpc_sym(";"), free, free, free, mpc_soft_delete )); - + mpc_define(Grammar, mpc_and(2, mpcaf_grammar_or, Term, mpc_maybe(mpc_and(2, mpcf_snd_free, mpc_sym("|"), Grammar, free)), mpc_soft_delete )); - + mpc_define(Term, mpc_many1(mpcaf_grammar_and, Factor)); - + mpc_define(Factor, mpc_and(2, mpcaf_grammar_repeat, Base, mpc_or(6, @@ -3699,7 +3699,7 @@ static mpc_err_t *mpca_lang_st(mpc_input_t *i, mpca_grammar_st_t *st) { mpc_pass()), mpc_soft_delete )); - + mpc_define(Base, mpc_or(5, mpc_apply_to(mpc_tok(mpc_string_lit()), mpcaf_grammar_string, st), mpc_apply_to(mpc_tok(mpc_char_lit()), mpcaf_grammar_char, st), @@ -3707,22 +3707,22 @@ static mpc_err_t *mpca_lang_st(mpc_input_t *i, mpca_grammar_st_t *st) { mpc_apply_to(mpc_tok_braces(mpc_or(2, mpc_digits(), mpc_ident()), free), mpcaf_grammar_id, st), mpc_tok_parens(Grammar, mpc_soft_delete) )); - + mpc_optimise(Lang); mpc_optimise(Stmt); mpc_optimise(Grammar); mpc_optimise(Term); mpc_optimise(Factor); mpc_optimise(Base); - + if (!mpc_parse_input(i, Lang, &r)) { e = r.error; } else { e = NULL; } - + mpc_cleanup(6, Lang, Stmt, Grammar, Term, Factor, Base); - + return e; } @@ -3731,18 +3731,18 @@ mpc_err_t *mpca_lang_file(int flags, FILE *f, ...) { mpc_input_t *i; mpc_err_t *err; - va_list va; + va_list va; va_start(va, f); - + st.va = &va; st.parsers_num = 0; st.parsers = NULL; st.flags = flags; - + i = mpc_input_new_file("", f); err = mpca_lang_st(i, &st); mpc_input_delete(i); - + free(st.parsers); va_end(va); return err; @@ -3753,77 +3753,77 @@ mpc_err_t *mpca_lang_pipe(int flags, FILE *p, ...) { mpc_input_t *i; mpc_err_t *err; - va_list va; + va_list va; va_start(va, p); - + st.va = &va; st.parsers_num = 0; st.parsers = NULL; st.flags = flags; - + i = mpc_input_new_pipe("", p); err = mpca_lang_st(i, &st); mpc_input_delete(i); - + free(st.parsers); va_end(va); return err; } mpc_err_t *mpca_lang(int flags, const char *language, ...) { - + mpca_grammar_st_t st; mpc_input_t *i; mpc_err_t *err; - - va_list va; + + va_list va; va_start(va, language); - + st.va = &va; st.parsers_num = 0; st.parsers = NULL; st.flags = flags; - + i = mpc_input_new_string("", language); err = mpca_lang_st(i, &st); mpc_input_delete(i); - + free(st.parsers); va_end(va); return err; } mpc_err_t *mpca_lang_contents(int flags, const char *filename, ...) { - + mpca_grammar_st_t st; mpc_input_t *i; mpc_err_t *err; - + va_list va; FILE *f = fopen(filename, "rb"); - + if (f == NULL) { err = mpc_err_file(filename, "Unable to open file!"); return err; } - + va_start(va, filename); - + st.va = &va; st.parsers_num = 0; st.parsers = NULL; st.flags = flags; - + i = mpc_input_new_file(filename, f); err = mpca_lang_st(i, &st); mpc_input_delete(i); - + free(st.parsers); - va_end(va); - + va_end(va); + fclose(f); - + return err; } @@ -3849,14 +3849,14 @@ static int mpc_nodecount_unretained(mpc_parser_t* p, int force) { if (p->type == MPC_TYPE_MANY1) { return 1 + mpc_nodecount_unretained(p->data.repeat.x, 0); } if (p->type == MPC_TYPE_COUNT) { return 1 + mpc_nodecount_unretained(p->data.repeat.x, 0); } - if (p->type == MPC_TYPE_OR) { + if (p->type == MPC_TYPE_OR) { total = 1; for(i = 0; i < p->data.or.n; i++) { total += mpc_nodecount_unretained(p->data.or.xs[i], 0); } return total; } - + if (p->type == MPC_TYPE_AND) { total = 1; for(i = 0; i < p->data.and.n; i++) { @@ -3866,7 +3866,7 @@ static int mpc_nodecount_unretained(mpc_parser_t* p, int force) { } return 1; - + } void mpc_stats(mpc_parser_t* p) { @@ -3876,14 +3876,14 @@ void mpc_stats(mpc_parser_t* p) { } static void mpc_optimise_unretained(mpc_parser_t *p, int force) { - + int i, n, m; mpc_parser_t *t; - + if (p->retained && !force) { return; } - + /* Optimise Subexpressions */ - + if (p->type == MPC_TYPE_EXPECT) { mpc_optimise_unretained(p->data.expect.x, 0); } if (p->type == MPC_TYPE_APPLY) { mpc_optimise_unretained(p->data.apply.x, 0); } if (p->type == MPC_TYPE_APPLY_TO) { mpc_optimise_unretained(p->data.apply_to.x, 0); } @@ -3895,23 +3895,23 @@ static void mpc_optimise_unretained(mpc_parser_t *p, int force) { if (p->type == MPC_TYPE_MANY) { mpc_optimise_unretained(p->data.repeat.x, 0); } if (p->type == MPC_TYPE_MANY1) { mpc_optimise_unretained(p->data.repeat.x, 0); } if (p->type == MPC_TYPE_COUNT) { mpc_optimise_unretained(p->data.repeat.x, 0); } - - if (p->type == MPC_TYPE_OR) { + + if (p->type == MPC_TYPE_OR) { for(i = 0; i < p->data.or.n; i++) { mpc_optimise_unretained(p->data.or.xs[i], 0); } } - + if (p->type == MPC_TYPE_AND) { for(i = 0; i < p->data.and.n; i++) { mpc_optimise_unretained(p->data.and.xs[i], 0); } - } - + } + /* Perform optimisations */ - + while (1) { - + /* Merge rhs `or` */ if (p->type == MPC_TYPE_OR && p->data.or.xs[p->data.or.n-1]->type == MPC_TYPE_OR @@ -3938,7 +3938,7 @@ static void mpc_optimise_unretained(mpc_parser_t *p, int force) { free(t->data.or.xs); free(t->name); free(t); continue; } - + /* Remove ast `pass` */ if (p->type == MPC_TYPE_AND && p->data.and.n == 2 @@ -3952,7 +3952,7 @@ static void mpc_optimise_unretained(mpc_parser_t *p, int force) { free(t); continue; } - + /* Merge ast lhs `and` */ if (p->type == MPC_TYPE_AND && p->data.and.f == mpcf_fold_ast @@ -3967,10 +3967,10 @@ static void mpc_optimise_unretained(mpc_parser_t *p, int force) { memmove(p->data.and.xs + m, p->data.and.xs + 1, (n - 1) * sizeof(mpc_parser_t*)); memmove(p->data.and.xs, t->data.and.xs, m * sizeof(mpc_parser_t*)); for (i = 0; i < p->data.and.n-1; i++) { p->data.and.dxs[i] = (mpc_dtor_t)mpc_ast_delete; } - free(t->data.and.xs); free(t->data.and.dxs); free(t->name); free(t); + free(t->data.and.xs); free(t->data.and.dxs); free(t->name); free(t); continue; } - + /* Merge ast rhs `and` */ if (p->type == MPC_TYPE_AND && p->data.and.f == mpcf_fold_ast @@ -3984,7 +3984,7 @@ static void mpc_optimise_unretained(mpc_parser_t *p, int force) { p->data.and.dxs = realloc(p->data.and.dxs, sizeof(mpc_dtor_t) * (n + m - 1 - 1)); memmove(p->data.and.xs + n - 1, t->data.and.xs, m * sizeof(mpc_parser_t*)); for (i = 0; i < p->data.and.n-1; i++) { p->data.and.dxs[i] = (mpc_dtor_t)mpc_ast_delete; } - free(t->data.and.xs); free(t->data.and.dxs); free(t->name); free(t); + free(t->data.and.xs); free(t->data.and.dxs); free(t->name); free(t); continue; } @@ -4017,10 +4017,10 @@ static void mpc_optimise_unretained(mpc_parser_t *p, int force) { memmove(p->data.and.xs + m, p->data.and.xs + 1, (n - 1) * sizeof(mpc_parser_t*)); memmove(p->data.and.xs, t->data.and.xs, m * sizeof(mpc_parser_t*)); for (i = 0; i < p->data.and.n-1; i++) { p->data.and.dxs[i] = free; } - free(t->data.and.xs); free(t->data.and.dxs); free(t->name); free(t); + free(t->data.and.xs); free(t->data.and.dxs); free(t->name); free(t); continue; } - + /* Merge re rhs `and` */ if (p->type == MPC_TYPE_AND && p->data.and.f == mpcf_strfold @@ -4034,14 +4034,14 @@ static void mpc_optimise_unretained(mpc_parser_t *p, int force) { p->data.and.dxs = realloc(p->data.and.dxs, sizeof(mpc_dtor_t) * (n + m - 1 - 1)); memmove(p->data.and.xs + n - 1, t->data.and.xs, m * sizeof(mpc_parser_t*)); for (i = 0; i < p->data.and.n-1; i++) { p->data.and.dxs[i] = free; } - free(t->data.and.xs); free(t->data.and.dxs); free(t->name); free(t); + free(t->data.and.xs); free(t->data.and.dxs); free(t->name); free(t); continue; } - + return; - + } - + } void mpc_optimise(mpc_parser_t *p) { From a17815f36c78c20a7b8782f65d38bd947894d679 Mon Sep 17 00:00:00 2001 From: halosghost Date: Fri, 9 Nov 2018 11:19:49 -0600 Subject: [PATCH 02/21] Dramatically update Makefile - Out-of-Tree builds (defaults to ./build, configurable via DIST) - Install and uninstall rules (which respect DESTDIR and PREFIX) - Production of static and dynamic libraries - Testing of all three methods of inclusion - direct file inclusion - static library - dynamic library (using LD_LIBRARY_PATH) - Better declaration of PHONY targets - Expose ability to override CC and CFLAGS --- Makefile | 61 +++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index 9a45c77..c6be65f 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,9 @@ - -CC = gcc -STND=-ansi -CFLAGS = $(STND) -pedantic -O3 -g -Wall -Werror -Wextra -Wformat=2 -Wshadow \ +PROJ = mpc +CC ?= gcc +STND = -ansi +DIST = build +PREFIX ?= /usr/local +CFLAGS ?= $(STND) -pedantic -O3 -g -Wall -Werror -Wextra -Wformat=2 -Wshadow \ -Wno-long-long -Wno-overlength-strings -Wno-format-nonliteral -Wcast-align \ -Wwrite-strings -Wstrict-prototypes -Wold-style-definition -Wredundant-decls \ -Wnested-externs -Wmissing-include-dirs -Wswitch-default @@ -10,15 +12,50 @@ TESTS = $(wildcard tests/*.c) EXAMPLES = $(wildcard examples/*.c) EXAMPLESEXE = $(EXAMPLES:.c=) -all: $(EXAMPLESEXE) check +.PHONY: all check clean libs -check: $(TESTS) mpc.c - $(CC) $(filter-out -Werror, $(CFLAGS)) $^ -lm -o test - ./test +all: $(EXAMPLESEXE) check -examples/%: examples/%.c mpc.c - $(CC) $(CFLAGS) $^ -lm -o $@ +$(DIST): + mkdir -p $(DIST)/examples + +check: test-file test-static test-dynamic + ./$(DIST)/test-file + ./$(DIST)/test-static + LD_LIBRARY_PATH=$(DIST) ./$(DIST)/test-dynamic + +test-file: $(DIST) $(TESTS) $(PROJ).c + $(CC) $(filter-out -Werror, $(CFLAGS)) $(TESTS) $(PROJ).c -lm -o $(DIST)/test-file + +test-dynamic: $(DIST) $(TESTS) lib$(PROJ).so + $(CC) $(filter-out -Werror, $(CFLAGS)) $(TESTS) -lm -L$(DIST) -l$(PROJ) -o $(DIST)/test-dynamic + +test-static: $(DIST) $(TESTS) lib$(PROJ).a + $(CC) $(filter-out -Werror, $(CFLAGS)) $(TESTS) -lm -L$(DIST) -l$(PROJ) -static -o $(DIST)/test-static + +examples/%: $(DIST) examples/%.c $(PROJ).c + $(CC) $(CFLAGS) $(filter-out $(DIST), $^) -lm -o $(DIST)/$@ + +lib$(PROJ).so: $(DIST) $(PROJ).c + $(CC) $(CFLAGS) -fPIC -shared $(PROJ).c -o $(DIST)/lib$(PROJ).so + +lib$(PROJ).a: $(DIST) $(PROJ).c + $(CC) $(CFLAGS) -c $(PROJ).c -o $(DIST)/$(PROJ).o + ar rcs $(DIST)/lib$(PROJ).a $(DIST)/$(PROJ).o + +libs: lib$(PROJ).so lib$(PROJ).a clean: - rm -rf test examples/doge examples/lispy examples/maths examples/smallc \ - examples/foobar examples/tree_traversal + rm -rf -- $(DIST) + +install: all + install -d -m644 $(DESTDIR)$(PREFIX)/{include,lib,share/$(PROJ)} + install -m755 -t $(DESTDIR)$(PREFIX)/lib $(DIST)/lib* + install -m644 -t $(DESTDIR)$(PREFIX)/share/$(PROJ) $(PROJ).{c,h} + install -m644 $(PROJ).h $(DESTDIR)$(PREFIX)/include/$(PROJ).h + +uninstall: + rm -rf -- \ + $(DESTDIR)$(PREFIX)/include/$(PROJ).h \ + $(DESTDIR)$(PREFIX)/share/$(PROJ)/$(PROJ).{c,h} \ + $(DESTDIR)$(PREFIX)/lib/lib$(PROJ).{so,a} From 462d5c8f9dd222ac53bade2160d8cd37b38e4d91 Mon Sep 17 00:00:00 2001 From: Ivan Veselov Date: Sun, 2 Dec 2018 12:34:09 +0000 Subject: [PATCH 03/21] Add documentation for ? and {d} in language approach. Fix EOL issues --- README.md | 68 +++++++++++++++++++++++++++---------------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 7075c78..3c1acd8 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,7 @@ Basic Parsers All the following functions construct new basic parsers of the type `mpc_parser_t *`. All of those parsers return a newly allocated `char *` with the character(s) they manage to match. If unsuccessful they will return an error. They have the following functionality. -* * * +* * * ```c mpc_parser_t *mpc_any(void); @@ -124,7 +124,7 @@ mpc_parser_t *mpc_any(void); Matches any individual character -* * * +* * * ```c mpc_parser_t *mpc_char(char c); @@ -283,7 +283,7 @@ Run a parser on the contents of some file. Combinators ----------- -Combinators are functions that take one or more parsers and return a new parser of some given functionality. +Combinators are functions that take one or more parsers and return a new parser of some given functionality. These combinators work independently of exactly what data type the parser(s) supplied as input return. In languages such as Haskell ensuring you don't input one type of data into a parser requiring a different type is done by the compiler. But in C we don't have that luxury. So it is at the discretion of the programmer to ensure that he or she deals correctly with the outputs of different parser types. @@ -556,9 +556,9 @@ To ease the task of undefining and then deleting parsers `mpc_cleanup` can be us mpc_parser_t *mpc_copy(mpc_parser_t *a); ``` -This function makes a copy of a parser `a`. This can be useful when you want to -use a parser as input for some other parsers multiple times without retaining -it. +This function makes a copy of a parser `a`. This can be useful when you want to +use a parser as input for some other parsers multiple times without retaining +it. * * * @@ -567,11 +567,11 @@ mpc_parser_t *mpc_re(const char *re); mpc_parser_t *mpc_re_mode(const char *re, int mode); ``` -This function takes as input the regular expression `re` and builds a parser -for it. With the `mpc_re_mode` function optional mode flags can also be given. -Available flags are `MPC_RE_MULTILINE` / `MPC_RE_M` where the start of input -character `^` also matches the beginning of new lines and the end of input `$` -character also matches new lines, and `MPC_RE_DOTALL` / `MPC_RE_S` where the +This function takes as input the regular expression `re` and builds a parser +for it. With the `mpc_re_mode` function optional mode flags can also be given. +Available flags are `MPC_RE_MULTILINE` / `MPC_RE_M` where the start of input +character `^` also matches the beginning of new lines and the end of input `$` +character also matches new lines, and `MPC_RE_DOTALL` / `MPC_RE_S` where the any character token `.` also matches newlines (by default it doesn't). @@ -626,7 +626,7 @@ Useful Parsers mpc_startswith(mpc_parser_t *a);Matches the start of input followed by a mpc_endswith(mpc_parser_t *a, mpc_dtor_t da);Matches a followed by the end of input - mpc_whole(mpc_parser_t *a, mpc_dtor_t da);Matches the start of input, a, and the end of input + mpc_whole(mpc_parser_t *a, mpc_dtor_t da);Matches the start of input, a, and the end of input mpc_stripl(mpc_parser_t *a);Matches a first consuming any whitespace to the left mpc_stripr(mpc_parser_t *a);Matches a then consumes any whitespace to the right mpc_strip(mpc_parser_t *a);Matches a consuming any surrounding whitespace @@ -707,17 +707,17 @@ We start with a fold function that will fold two `int *` into a new `int *` base ```c mpc_val_t *fold_maths(int n, mpc_val_t **xs) { - + int **vs = (int**)xs; - + if (strcmp(xs[1], "*") == 0) { *vs[0] *= *vs[2]; } if (strcmp(xs[1], "/") == 0) { *vs[0] /= *vs[2]; } if (strcmp(xs[1], "%") == 0) { *vs[0] %= *vs[2]; } if (strcmp(xs[1], "+") == 0) { *vs[0] += *vs[2]; } if (strcmp(xs[1], "-") == 0) { *vs[0] -= *vs[2]; } - + free(xs[1]); free(xs[2]); - + return xs[0]; } ``` @@ -730,14 +730,14 @@ mpc_parser_t *Factor = mpc_new("factor"); mpc_parser_t *Term = mpc_new("term"); mpc_parser_t *Maths = mpc_new("maths"); -mpc_define(Expr, mpc_or(2, +mpc_define(Expr, mpc_or(2, mpc_and(3, fold_maths, Factor, mpc_oneof("+-"), Factor, free, free), Factor )); -mpc_define(Factor, mpc_or(2, +mpc_define(Factor, mpc_or(2, mpc_and(3, fold_maths, Term, mpc_oneof("*/"), Term, free, free), @@ -781,6 +781,8 @@ The syntax for this is defined as follows. 'a' | 'b'Either 'a' is required, or 'b' is required. 'a'*Zero or more 'a' are required. 'a'+One or more 'a' are required. + 'a'?Zero or one 'a' is required. + 'a'{x}Exactly x (integer) copies of 'a' are required. <abba>The rule called abba is required. @@ -825,17 +827,17 @@ This opens and reads in the contents of the file given by `filename` and passes Case Study - Tokenizer ====================== -Another common task we might be interested in doing is tokenizing some block of +Another common task we might be interested in doing is tokenizing some block of text (splitting the text into individual elements) and performing some function on each one of these elements as it is read. We can do this with `mpc` too. -First, we can build a regular expression which parses an individual token. For -example if our tokens are identifiers, integers, commas, periods and colons we -could build something like this `mpc_re("\\s*([a-zA-Z_]+|[0-9]+|,|\\.|:)")`. -Next we can strip any whitespace, and add a callback function using `mpc_apply` -which gets called every time this regex is parsed successfully -`mpc_apply(mpc_strip(mpc_re("\\s*([a-zA-Z_]+|[0-9]+|,|\\.|:)")), print_token)`. -Finally we can surround all of this in `mpc_many` to parse it zero or more +First, we can build a regular expression which parses an individual token. For +example if our tokens are identifiers, integers, commas, periods and colons we +could build something like this `mpc_re("\\s*([a-zA-Z_]+|[0-9]+|,|\\.|:)")`. +Next we can strip any whitespace, and add a callback function using `mpc_apply` +which gets called every time this regex is parsed successfully +`mpc_apply(mpc_strip(mpc_re("\\s*([a-zA-Z_]+|[0-9]+|,|\\.|:)")), print_token)`. +Finally we can surround all of this in `mpc_many` to parse it zero or more times. The final code might look something like this: ```c @@ -847,16 +849,16 @@ static mpc_val_t *print_token(mpc_val_t *x) { int main(int argc, char **argv) { const char *input = " hello 4352 , \n foo.bar \n\n test:ing "; - + mpc_parser_t* Tokens = mpc_many( - mpcf_all_free, + mpcf_all_free, mpc_apply(mpc_strip(mpc_re("\\s*([a-zA-Z_]+|[0-9]+|,|\\.|:)")), print_token)); - + mpc_result_t r; mpc_parse("input", input, Tokens, &r); - + mpc_delete(Tokens); - + return 0; } ``` @@ -875,7 +877,7 @@ Token: ':' Token: 'ing' ``` -By extending the regex we can easily extend this to parse many more types of +By extending the regex we can easily extend this to parse many more types of tokens and quickly and easily build a tokenizer for whatever language we are interested in. @@ -991,5 +993,3 @@ When parsing from a grammar, the abstract syntax tree is tagged with different t If you have a rule in your grammar called `string`, `char` or `regex`, you may encounter some confusion. This is because nodes will be tagged with (for example) `string` _either_ if they are a string primitive, _or_ if they were parsed via your `string` rule. If you are detecting node type using something like `strstr`, in this situation it might break. One solution to this is to always check that `string` is the innermost tag to test for string primitives, or to rename your rule called `string` to something that doesn't conflict. Yes it is annoying but its probably not going to change! - - From b31e02e427f55d4ce69c33ed9936a1b396628440 Mon Sep 17 00:00:00 2001 From: Daniel Holden Date: Sun, 16 Dec 2018 09:53:56 -0500 Subject: [PATCH 04/21] version number --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3c1acd8..2e044a4 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Micro Parser Combinators ======================== -Version 0.8.8 +Version 0.9.0 About From 41f3a6de7cf1f7346d2fc872179a65860c5d71b8 Mon Sep 17 00:00:00 2001 From: halosghost Date: Thu, 23 May 2019 21:23:05 -0500 Subject: [PATCH 05/21] leverage $(AR) and allow mkdir-invocation to be configurable --- Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index c6be65f..aa890bb 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,7 @@ PROJ = mpc CC ?= gcc STND = -ansi DIST = build +MKDIR ?= mkdir -p PREFIX ?= /usr/local CFLAGS ?= $(STND) -pedantic -O3 -g -Wall -Werror -Wextra -Wformat=2 -Wshadow \ -Wno-long-long -Wno-overlength-strings -Wno-format-nonliteral -Wcast-align \ @@ -17,7 +18,7 @@ EXAMPLESEXE = $(EXAMPLES:.c=) all: $(EXAMPLESEXE) check $(DIST): - mkdir -p $(DIST)/examples + $(MKDIR) $(DIST)/examples check: test-file test-static test-dynamic ./$(DIST)/test-file @@ -41,7 +42,7 @@ lib$(PROJ).so: $(DIST) $(PROJ).c lib$(PROJ).a: $(DIST) $(PROJ).c $(CC) $(CFLAGS) -c $(PROJ).c -o $(DIST)/$(PROJ).o - ar rcs $(DIST)/lib$(PROJ).a $(DIST)/$(PROJ).o + $(AR) rcs $(DIST)/lib$(PROJ).a $(DIST)/$(PROJ).o libs: lib$(PROJ).so lib$(PROJ).a From 147545a488dbc353be3c5f9a4484c967e167bbdf Mon Sep 17 00:00:00 2001 From: halosghost Date: Wed, 29 May 2019 19:39:33 -0500 Subject: [PATCH 06/21] preliminarily detect windows platforms and call -fPIC accordingly --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index aa890bb..fd3460b 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,11 @@ examples/%: $(DIST) examples/%.c $(PROJ).c $(CC) $(CFLAGS) $(filter-out $(DIST), $^) -lm -o $(DIST)/$@ lib$(PROJ).so: $(DIST) $(PROJ).c +ifneq ($(OS),Windows_NT) $(CC) $(CFLAGS) -fPIC -shared $(PROJ).c -o $(DIST)/lib$(PROJ).so +else + $(CC) $(CFLAGS) -shared $(PROJ).c -o $(DIST)/lib$(PROJ).so +endif lib$(PROJ).a: $(DIST) $(PROJ).c $(CC) $(CFLAGS) -c $(PROJ).c -o $(DIST)/$(PROJ).o From dbe7308b9c3672357554fdab140dac28bdffb158 Mon Sep 17 00:00:00 2001 From: Daniel Holden Date: Sat, 15 Jun 2019 14:30:41 -0400 Subject: [PATCH 07/21] Added destructor to check combinators --- .gitignore | 1 + README.md | 10 +++++----- mpc.c | 48 ++++++++++++++++++++++++--------------------- mpc.h | 8 ++++---- tests/combinators.c | 8 ++++---- 5 files changed, 40 insertions(+), 35 deletions(-) diff --git a/.gitignore b/.gitignore index a82e7ec..788a748 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ examples/maths examples/smallc examples/foobar examples/tree_traversal +build/* \ No newline at end of file diff --git a/README.md b/README.md index 2e044a4..98ea680 100644 --- a/README.md +++ b/README.md @@ -312,13 +312,13 @@ Returns a parser that applies function `f` (optionality taking extra input `x`) * * * ```c -mpc_parser_t *mpc_check(mpc_parser_t *a, mpc_check_t f, const char *e); -mpc_parser_t *mpc_check_with(mpc_parser_t *a, mpc_check_with_t f, void *x, const char *e); -mpc_parser_t *mpc_checkf(mpc_parser_t *a, mpc_check_t f, const char *fmt, ...); -mpc_parser_t *mpc_check_withf(mpc_parser_t *a, mpc_check_with_t f, void *x, const char *fmt, ...); +mpc_parser_t *mpc_check(mpc_parser_t *a, mpc_dtor_t da, mpc_check_t f, const char *e); +mpc_parser_t *mpc_check_with(mpc_parser_t *a, mpc_dtor_t da, mpc_check_with_t f, void *x, const char *e); +mpc_parser_t *mpc_checkf(mpc_parser_t *a, mpc_dtor_t da, mpc_check_t f, const char *fmt, ...); +mpc_parser_t *mpc_check_withf(mpc_parser_t *a, mpc_dtor_t da, mpc_check_with_t f, void *x, const char *fmt, ...); ``` -Returns a parser that applies function `f` (optionally taking extra input `x`) to the result of parser `a`. If `f` returns non-zero, then the parser succeeds and returns the value of `a` (possibly modified by `f`). If `f` returns zero, then the parser fails with message `e`. +Returns a parser that applies function `f` (optionally taking extra input `x`) to the result of parser `a`. If `f` returns non-zero, then the parser succeeds and returns the value of `a` (possibly modified by `f`). If `f` returns zero, then the parser fails with message `e`, and the result of `a` is destroyed with the destructor `da`. * * * diff --git a/mpc.c b/mpc.c index 8e8e83e..9856efa 100644 --- a/mpc.c +++ b/mpc.c @@ -923,8 +923,8 @@ typedef struct { int(*f)(char); } mpc_pdata_satisfy_t; typedef struct { char *x; } mpc_pdata_string_t; typedef struct { mpc_parser_t *x; mpc_apply_t f; } mpc_pdata_apply_t; typedef struct { mpc_parser_t *x; mpc_apply_to_t f; void *d; } mpc_pdata_apply_to_t; -typedef struct { mpc_parser_t *x; mpc_check_t f; char *e; } mpc_pdata_check_t; -typedef struct { mpc_parser_t *x; mpc_check_with_t f; void *d; char *e; } mpc_pdata_check_with_t; +typedef struct { mpc_parser_t *x; mpc_dtor_t dx; mpc_check_t f; char *e; } mpc_pdata_check_t; +typedef struct { mpc_parser_t *x; mpc_dtor_t dx; mpc_check_with_t f; void *d; char *e; } mpc_pdata_check_with_t; typedef struct { mpc_parser_t *x; } mpc_pdata_predict_t; typedef struct { mpc_parser_t *x; mpc_dtor_t dx; mpc_ctor_t lf; } mpc_pdata_not_t; typedef struct { int n; mpc_fold_t f; mpc_parser_t *x; mpc_dtor_t dx; } mpc_pdata_repeat_t; @@ -1090,6 +1090,7 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e if (p->data.check.f(&r->output)) { MPC_SUCCESS(r->output); } else { + mpc_parse_dtor(i, p->data.check.dx, r->output); MPC_FAILURE(mpc_err_fail(i, p->data.check.e)); } } else { @@ -1101,6 +1102,7 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e if (p->data.check_with.f(&r->output, p->data.check_with.d)) { MPC_SUCCESS(r->output); } else { + mpc_parse_dtor(i, p->data.check.dx, r->output); MPC_FAILURE(mpc_err_fail(i, p->data.check_with.e)); } } else { @@ -1799,20 +1801,22 @@ mpc_parser_t *mpc_apply_to(mpc_parser_t *a, mpc_apply_to_t f, void *x) { return p; } -mpc_parser_t *mpc_check(mpc_parser_t *a, mpc_check_t f, const char *e) { +mpc_parser_t *mpc_check(mpc_parser_t *a, mpc_dtor_t da, mpc_check_t f, const char *e) { mpc_parser_t *p = mpc_undefined(); - p->type = MPC_TYPE_CHECK; - p->data.check.x = a; - p->data.check.f = f; - p->data.check.e = malloc(strlen(e) + 1); + p->type = MPC_TYPE_CHECK; + p->data.check.x = a; + p->data.check.dx = da; + p->data.check.f = f; + p->data.check.e = malloc(strlen(e) + 1); strcpy(p->data.check.e, e); return p; } -mpc_parser_t *mpc_check_with(mpc_parser_t *a, mpc_check_with_t f, void *x, const char *e) { - mpc_parser_t *p = mpc_undefined(); - p->type = MPC_TYPE_CHECK_WITH; +mpc_parser_t *mpc_check_with(mpc_parser_t *a, mpc_dtor_t da, mpc_check_with_t f, void *x, const char *e) { + mpc_parser_t *p = mpc_undefined(); + p->type = MPC_TYPE_CHECK_WITH; p->data.check_with.x = a; + p->data.check_with.dx = da; p->data.check_with.f = f; p->data.check_with.d = x; p->data.check_with.e = malloc(strlen(e) + 1); @@ -1820,34 +1824,34 @@ mpc_parser_t *mpc_check_with(mpc_parser_t *a, mpc_check_with_t f, void *x, const return p; } -mpc_parser_t *mpc_checkf(mpc_parser_t *a, mpc_check_t f, const char *fmt, ...) { - va_list va; - char *buffer; - mpc_parser_t *p; +mpc_parser_t *mpc_checkf(mpc_parser_t *a, mpc_dtor_t da, mpc_check_t f, const char *fmt, ...) { + va_list va; + char *buffer; + mpc_parser_t *p; va_start(va, fmt); buffer = malloc(2048); vsprintf(buffer, fmt, va); va_end(va); - p = mpc_check (a, f, buffer); - free (buffer); + p = mpc_check(a, da, f, buffer); + free(buffer); return p; } -mpc_parser_t *mpc_check_withf(mpc_parser_t *a, mpc_check_with_t f, void *x, const char *fmt, ...) { - va_list va; - char *buffer; - mpc_parser_t *p; +mpc_parser_t *mpc_check_withf(mpc_parser_t *a, mpc_dtor_t da, mpc_check_with_t f, void *x, const char *fmt, ...) { + va_list va; + char *buffer; + mpc_parser_t *p; va_start(va, fmt); buffer = malloc(2048); vsprintf(buffer, fmt, va); va_end(va); - p = mpc_check_with (a, f, x, buffer); - free (buffer); + p = mpc_check_with(a, da, f, x, buffer); + free(buffer); return p; } diff --git a/mpc.h b/mpc.h index 7ea12e3..b3c51a2 100644 --- a/mpc.h +++ b/mpc.h @@ -129,10 +129,10 @@ mpc_parser_t *mpc_expect(mpc_parser_t *a, const char *e); mpc_parser_t *mpc_expectf(mpc_parser_t *a, const char *fmt, ...); mpc_parser_t *mpc_apply(mpc_parser_t *a, mpc_apply_t f); mpc_parser_t *mpc_apply_to(mpc_parser_t *a, mpc_apply_to_t f, void *x); -mpc_parser_t *mpc_check(mpc_parser_t *a, mpc_check_t f, const char *e); -mpc_parser_t *mpc_check_with(mpc_parser_t *a, mpc_check_with_t f, void *x, const char *e); -mpc_parser_t *mpc_checkf(mpc_parser_t *a, mpc_check_t f, const char *fmt, ...); -mpc_parser_t *mpc_check_withf(mpc_parser_t *a, mpc_check_with_t f, void *x, const char *fmt, ...); +mpc_parser_t *mpc_check(mpc_parser_t *a, mpc_dtor_t da, mpc_check_t f, const char *e); +mpc_parser_t *mpc_check_with(mpc_parser_t *a, mpc_dtor_t da, mpc_check_with_t f, void *x, const char *e); +mpc_parser_t *mpc_checkf(mpc_parser_t *a, mpc_dtor_t da, mpc_check_t f, const char *fmt, ...); +mpc_parser_t *mpc_check_withf(mpc_parser_t *a, mpc_dtor_t da, mpc_check_with_t f, void *x, const char *fmt, ...); mpc_parser_t *mpc_not(mpc_parser_t *a, mpc_dtor_t da); mpc_parser_t *mpc_not_lift(mpc_parser_t *a, mpc_dtor_t da, mpc_ctor_t lf); diff --git a/tests/combinators.c b/tests/combinators.c index d9fe203..0bd0ae9 100644 --- a/tests/combinators.c +++ b/tests/combinators.c @@ -12,7 +12,7 @@ static int check_is(mpc_val_t** x, void* t) { void test_check(void) { int success; mpc_result_t r; - mpc_parser_t* p = mpc_check(mpc_or(2, mpc_char('a'), mpc_char('b')), check_is_a, "Expected 'a'"); + mpc_parser_t* p = mpc_check(mpc_or(2, mpc_char('a'), mpc_char('b')), free, check_is_a, "Expected 'a'"); success = mpc_parse("test", "a", p, &r); PT_ASSERT(success); @@ -30,7 +30,7 @@ void test_check(void) { void test_check_with(void) { int success; mpc_result_t r; - mpc_parser_t* p = mpc_check_with(mpc_or(2, mpc_char('a'), mpc_char('b')), check_is, (void*)"a", "Expected 'a'"); + mpc_parser_t* p = mpc_check_with(mpc_or(2, mpc_char('a'), mpc_char('b')), free, check_is, (void*)"a", "Expected 'a'"); success = mpc_parse("test", "a", p, &r); PT_ASSERT(success); @@ -48,7 +48,7 @@ void test_check_with(void) { void test_checkf(void) { int success; mpc_result_t r; - mpc_parser_t* p = mpc_checkf(mpc_or(2, mpc_char('a'), mpc_char('b')), check_is_a, "Expected '%s'", "a"); + mpc_parser_t* p = mpc_checkf(mpc_or(2, mpc_char('a'), mpc_char('b')), free, check_is_a, "Expected '%s'", "a"); success = mpc_parse("test", "a", p, &r); PT_ASSERT(success); @@ -66,7 +66,7 @@ void test_checkf(void) { void test_check_withf(void) { int success; mpc_result_t r; - mpc_parser_t* p = mpc_check_withf(mpc_or(2, mpc_char('a'), mpc_char('b')), check_is, (void*)"a", "Expected '%s'", "a"); + mpc_parser_t* p = mpc_check_withf(mpc_or(2, mpc_char('a'), mpc_char('b')), free, check_is, (void*)"a", "Expected '%s'", "a"); success = mpc_parse("test", "a", p, &r); PT_ASSERT(success); From 6f5e8f0f398e624b51bec54541833b27c1c139ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren=20Tempel?= Date: Tue, 4 Jun 2019 19:50:23 +0200 Subject: [PATCH 08/21] Fix backtracing bug with mpc_parse_pipe Before we free our buffer we need to reset the underlying stream to its original state by pushing the buffer contents back onto the input stream. Fixes #109 --- mpc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mpc.c b/mpc.c index 9856efa..87aac4c 100644 --- a/mpc.c +++ b/mpc.c @@ -320,6 +320,7 @@ static void mpc_input_mark(mpc_input_t *i) { } static void mpc_input_unmark(mpc_input_t *i) { + int j; if (i->backtrack < 1) { return; } @@ -335,6 +336,9 @@ static void mpc_input_unmark(mpc_input_t *i) { } if (i->type == MPC_INPUT_PIPE && i->marks_num == 0) { + for (j = strlen(i->buffer) - 1; j >= 0; j--) + ungetc(i->buffer[j], i->file); + free(i->buffer); i->buffer = NULL; } From f323a89923435d154bc607f72431af0d39ce917b Mon Sep 17 00:00:00 2001 From: Fotis Georgatos Date: Mon, 24 Jun 2019 22:44:58 +0200 Subject: [PATCH 09/21] typo: recieved -> received --- mpc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mpc.c b/mpc.c index 9856efa..cd675f7 100644 --- a/mpc.c +++ b/mpc.c @@ -653,7 +653,7 @@ char *mpc_err_string(mpc_err_t *x) { } mpc_err_string_cat(buffer, &pos, &max, " at "); - mpc_err_string_cat(buffer, &pos, &max, mpc_err_char_unescape(x->recieved)); + mpc_err_string_cat(buffer, &pos, &max, mpc_err_char_unescape(x->received)); mpc_err_string_cat(buffer, &pos, &max, "\n"); return realloc(buffer, strlen(buffer) + 1); @@ -671,7 +671,7 @@ static mpc_err_t *mpc_err_new(mpc_input_t *i, const char *expected) { x->expected[0] = mpc_malloc(i, strlen(expected) + 1); strcpy(x->expected[0], expected); x->failure = NULL; - x->recieved = mpc_input_peekc(i); + x->received = mpc_input_peekc(i); return x; } @@ -686,7 +686,7 @@ static mpc_err_t *mpc_err_fail(mpc_input_t *i, const char *failure) { x->expected = NULL; x->failure = mpc_malloc(i, strlen(failure) + 1); strcpy(x->failure, failure); - x->recieved = ' '; + x->received = ' '; return x; } @@ -700,7 +700,7 @@ static mpc_err_t *mpc_err_file(const char *filename, const char *failure) { x->expected = NULL; x->failure = malloc(strlen(failure) + 1); strcpy(x->failure, failure); - x->recieved = ' '; + x->received = ' '; return x; } @@ -777,7 +777,7 @@ static mpc_err_t *mpc_err_or(mpc_input_t *i, mpc_err_t** x, int n) { break; } - e->recieved = x[j]->recieved; + e->received = x[j]->received; for (k = 0; k < x[j]->expected_num; k++) { if (!mpc_err_contains_expected(i, e, x[j]->expected[k])) { From 83393d4f4cd6fee67095115b53f039921f4158ca Mon Sep 17 00:00:00 2001 From: Fotis Georgatos Date: Mon, 24 Jun 2019 22:46:12 +0200 Subject: [PATCH 10/21] typo: recieved -> received [ok] --- mpc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mpc.h b/mpc.h index b3c51a2..a5ed16d 100644 --- a/mpc.h +++ b/mpc.h @@ -43,7 +43,7 @@ typedef struct { char *filename; char *failure; char **expected; - char recieved; + char received; } mpc_err_t; void mpc_err_delete(mpc_err_t *e); From 8cf2c1d2d7914be388abf9d799fc23ea13e605c8 Mon Sep 17 00:00:00 2001 From: Vemake Date: Tue, 23 Jul 2019 12:14:11 +0800 Subject: [PATCH 11/21] Fix 12 dependency issues in Makefile --- Makefile | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index fd3460b..60bb361 100644 --- a/Makefile +++ b/Makefile @@ -25,28 +25,28 @@ check: test-file test-static test-dynamic ./$(DIST)/test-static LD_LIBRARY_PATH=$(DIST) ./$(DIST)/test-dynamic -test-file: $(DIST) $(TESTS) $(PROJ).c - $(CC) $(filter-out -Werror, $(CFLAGS)) $(TESTS) $(PROJ).c -lm -o $(DIST)/test-file +test-file: $(DIST) $(TESTS) $(PROJ).c mpc.h tests/ptest.h + $(CC) $(filter-out -Werror, $(CFLAGS)) $(TESTS) $(PROJ).c -lm -o $(DIST)/test-file -test-dynamic: $(DIST) $(TESTS) lib$(PROJ).so - $(CC) $(filter-out -Werror, $(CFLAGS)) $(TESTS) -lm -L$(DIST) -l$(PROJ) -o $(DIST)/test-dynamic +test-dynamic: $(DIST) $(TESTS) lib$(PROJ).so mpc.h tests/ptest.h + $(CC) $(filter-out -Werror, $(CFLAGS)) $(TESTS) -lm -L$(DIST) -l$(PROJ) -o $(DIST)/test-dynamic -test-static: $(DIST) $(TESTS) lib$(PROJ).a - $(CC) $(filter-out -Werror, $(CFLAGS)) $(TESTS) -lm -L$(DIST) -l$(PROJ) -static -o $(DIST)/test-static +test-static: $(DIST) $(TESTS) lib$(PROJ).a mpc.h tests/ptest.h + $(CC) $(filter-out -Werror, $(CFLAGS)) $(TESTS) -lm -L$(DIST) -l$(PROJ) -static -o $(DIST)/test-static -examples/%: $(DIST) examples/%.c $(PROJ).c - $(CC) $(CFLAGS) $(filter-out $(DIST), $^) -lm -o $(DIST)/$@ +examples/%: $(DIST) examples/%.c $(PROJ).c mpc.h + $(CC) $(CFLAGS) $(filter-out $(DIST), $^) -lm -o $(DIST)/$@ -lib$(PROJ).so: $(DIST) $(PROJ).c +lib$(PROJ).so: $(DIST) $(PROJ).c mpc.h ifneq ($(OS),Windows_NT) - $(CC) $(CFLAGS) -fPIC -shared $(PROJ).c -o $(DIST)/lib$(PROJ).so + $(CC) $(CFLAGS) -fPIC -shared $(PROJ).c -o $(DIST)/lib$(PROJ).so else - $(CC) $(CFLAGS) -shared $(PROJ).c -o $(DIST)/lib$(PROJ).so + $(CC) $(CFLAGS) -shared $(PROJ).c -o $(DIST)/lib$(PROJ).so endif -lib$(PROJ).a: $(DIST) $(PROJ).c - $(CC) $(CFLAGS) -c $(PROJ).c -o $(DIST)/$(PROJ).o - $(AR) rcs $(DIST)/lib$(PROJ).a $(DIST)/$(PROJ).o +lib$(PROJ).a: $(DIST) $(PROJ).c mpc.h + $(CC) $(CFLAGS) -c $(PROJ).c -o $(DIST)/$(PROJ).o + $(AR) rcs $(DIST)/lib$(PROJ).a $(DIST)/$(PROJ).o libs: lib$(PROJ).so lib$(PROJ).a From 217a551a0a3dac094a83014bf29680f749ca99f3 Mon Sep 17 00:00:00 2001 From: Vemake Date: Wed, 7 Aug 2019 17:55:12 +0800 Subject: [PATCH 12/21] Use tabs instead of spaces in Makefile. --- Makefile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 60bb361..a0972c5 100644 --- a/Makefile +++ b/Makefile @@ -26,27 +26,27 @@ check: test-file test-static test-dynamic LD_LIBRARY_PATH=$(DIST) ./$(DIST)/test-dynamic test-file: $(DIST) $(TESTS) $(PROJ).c mpc.h tests/ptest.h - $(CC) $(filter-out -Werror, $(CFLAGS)) $(TESTS) $(PROJ).c -lm -o $(DIST)/test-file + $(CC) $(filter-out -Werror, $(CFLAGS)) $(TESTS) $(PROJ).c -lm -o $(DIST)/test-file test-dynamic: $(DIST) $(TESTS) lib$(PROJ).so mpc.h tests/ptest.h - $(CC) $(filter-out -Werror, $(CFLAGS)) $(TESTS) -lm -L$(DIST) -l$(PROJ) -o $(DIST)/test-dynamic + $(CC) $(filter-out -Werror, $(CFLAGS)) $(TESTS) -lm -L$(DIST) -l$(PROJ) -o $(DIST)/test-dynamic test-static: $(DIST) $(TESTS) lib$(PROJ).a mpc.h tests/ptest.h - $(CC) $(filter-out -Werror, $(CFLAGS)) $(TESTS) -lm -L$(DIST) -l$(PROJ) -static -o $(DIST)/test-static + $(CC) $(filter-out -Werror, $(CFLAGS)) $(TESTS) -lm -L$(DIST) -l$(PROJ) -static -o $(DIST)/test-static examples/%: $(DIST) examples/%.c $(PROJ).c mpc.h - $(CC) $(CFLAGS) $(filter-out $(DIST), $^) -lm -o $(DIST)/$@ + $(CC) $(CFLAGS) $(filter-out $(DIST), $^) -lm -o $(DIST)/$@ lib$(PROJ).so: $(DIST) $(PROJ).c mpc.h ifneq ($(OS),Windows_NT) - $(CC) $(CFLAGS) -fPIC -shared $(PROJ).c -o $(DIST)/lib$(PROJ).so + $(CC) $(CFLAGS) -fPIC -shared $(PROJ).c -o $(DIST)/lib$(PROJ).so else - $(CC) $(CFLAGS) -shared $(PROJ).c -o $(DIST)/lib$(PROJ).so + $(CC) $(CFLAGS) -shared $(PROJ).c -o $(DIST)/lib$(PROJ).so endif lib$(PROJ).a: $(DIST) $(PROJ).c mpc.h - $(CC) $(CFLAGS) -c $(PROJ).c -o $(DIST)/$(PROJ).o - $(AR) rcs $(DIST)/lib$(PROJ).a $(DIST)/$(PROJ).o + $(CC) $(CFLAGS) -c $(PROJ).c -o $(DIST)/$(PROJ).o + $(AR) rcs $(DIST)/lib$(PROJ).a $(DIST)/$(PROJ).o libs: lib$(PROJ).so lib$(PROJ).a From 7812a337741acd01e436f59eef4c52b5b93abd34 Mon Sep 17 00:00:00 2001 From: vemakereporter Date: Wed, 7 Aug 2019 10:15:39 +0000 Subject: [PATCH 13/21] Fix dependency issues reported by Vemake --- Makefile | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index a0972c5..f60b65c 100644 --- a/Makefile +++ b/Makefile @@ -20,35 +20,35 @@ all: $(EXAMPLESEXE) check $(DIST): $(MKDIR) $(DIST)/examples -check: test-file test-static test-dynamic +check: $(DIST)/test-file $(DIST)/test-static $(DIST)/test-dynamic ./$(DIST)/test-file ./$(DIST)/test-static LD_LIBRARY_PATH=$(DIST) ./$(DIST)/test-dynamic -test-file: $(DIST) $(TESTS) $(PROJ).c mpc.h tests/ptest.h +$(DIST)/test-file: $(TESTS) $(PROJ).c mpc.h tests/ptest.h $(CC) $(filter-out -Werror, $(CFLAGS)) $(TESTS) $(PROJ).c -lm -o $(DIST)/test-file -test-dynamic: $(DIST) $(TESTS) lib$(PROJ).so mpc.h tests/ptest.h +$(DIST)/test-dynamic: $(TESTS) $(DIST)/lib$(PROJ).so mpc.h tests/ptest.h $(CC) $(filter-out -Werror, $(CFLAGS)) $(TESTS) -lm -L$(DIST) -l$(PROJ) -o $(DIST)/test-dynamic -test-static: $(DIST) $(TESTS) lib$(PROJ).a mpc.h tests/ptest.h +$(DIST)/test-static: $(TESTS) $(DIST)/lib$(PROJ).a mpc.h tests/ptest.h $(CC) $(filter-out -Werror, $(CFLAGS)) $(TESTS) -lm -L$(DIST) -l$(PROJ) -static -o $(DIST)/test-static examples/%: $(DIST) examples/%.c $(PROJ).c mpc.h $(CC) $(CFLAGS) $(filter-out $(DIST), $^) -lm -o $(DIST)/$@ -lib$(PROJ).so: $(DIST) $(PROJ).c mpc.h +$(DIST)/lib$(PROJ).so: $(PROJ).c mpc.h ifneq ($(OS),Windows_NT) $(CC) $(CFLAGS) -fPIC -shared $(PROJ).c -o $(DIST)/lib$(PROJ).so else $(CC) $(CFLAGS) -shared $(PROJ).c -o $(DIST)/lib$(PROJ).so endif -lib$(PROJ).a: $(DIST) $(PROJ).c mpc.h +$(DIST)/lib$(PROJ).a: $(PROJ).c mpc.h $(CC) $(CFLAGS) -c $(PROJ).c -o $(DIST)/$(PROJ).o $(AR) rcs $(DIST)/lib$(PROJ).a $(DIST)/$(PROJ).o -libs: lib$(PROJ).so lib$(PROJ).a +libs: $(DIST)/lib$(PROJ).so $(DIST)/lib$(PROJ).a clean: rm -rf -- $(DIST) From ea778d1b8dabace291453b650808a9773a21d382 Mon Sep 17 00:00:00 2001 From: Daniel Holden Date: Sun, 1 Sep 2019 13:32:36 -0400 Subject: [PATCH 14/21] added maximum recursion depth --- mpc.c | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/mpc.c b/mpc.c index cd675f7..0be7b5d 100644 --- a/mpc.c +++ b/mpc.c @@ -1038,13 +1038,20 @@ enum { if (x) { MPC_SUCCESS(r->output); } \ else { MPC_FAILURE(NULL); } -static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_err_t **e) { +#define MPC_MAX_RECURSION_DEPTH 1000 + +static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_err_t **e, int depth) { int j = 0, k = 0; mpc_result_t results_stk[MPC_PARSE_STACK_MIN]; mpc_result_t *results; int results_slots = MPC_PARSE_STACK_MIN; + if (depth == MPC_MAX_RECURSION_DEPTH) + { + MPC_FAILURE(mpc_err_fail(i, "Maximum recursion depth exceeded!")); + } + switch (p->type) { /* Basic Parsers */ @@ -1072,21 +1079,21 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e /* Application Parsers */ case MPC_TYPE_APPLY: - if (mpc_parse_run(i, p->data.apply.x, r, e)) { + if (mpc_parse_run(i, p->data.apply.x, r, e, depth+1)) { MPC_SUCCESS(mpc_parse_apply(i, p->data.apply.f, r->output)); } else { MPC_FAILURE(r->output); } case MPC_TYPE_APPLY_TO: - if (mpc_parse_run(i, p->data.apply_to.x, r, e)) { + if (mpc_parse_run(i, p->data.apply_to.x, r, e, depth+1)) { MPC_SUCCESS(mpc_parse_apply_to(i, p->data.apply_to.f, r->output, p->data.apply_to.d)); } else { MPC_FAILURE(r->error); } case MPC_TYPE_CHECK: - if (mpc_parse_run(i, p->data.check.x, r, e)) { + if (mpc_parse_run(i, p->data.check.x, r, e, depth+1)) { if (p->data.check.f(&r->output)) { MPC_SUCCESS(r->output); } else { @@ -1098,7 +1105,7 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e } case MPC_TYPE_CHECK_WITH: - if (mpc_parse_run(i, p->data.check_with.x, r, e)) { + if (mpc_parse_run(i, p->data.check_with.x, r, e, depth+1)) { if (p->data.check_with.f(&r->output, p->data.check_with.d)) { MPC_SUCCESS(r->output); } else { @@ -1111,7 +1118,7 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e case MPC_TYPE_EXPECT: mpc_input_suppress_enable(i); - if (mpc_parse_run(i, p->data.expect.x, r, e)) { + if (mpc_parse_run(i, p->data.expect.x, r, e, depth+1)) { mpc_input_suppress_disable(i); MPC_SUCCESS(r->output); } else { @@ -1121,7 +1128,7 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e case MPC_TYPE_PREDICT: mpc_input_backtrack_disable(i); - if (mpc_parse_run(i, p->data.predict.x, r, e)) { + if (mpc_parse_run(i, p->data.predict.x, r, e, depth+1)) { mpc_input_backtrack_enable(i); MPC_SUCCESS(r->output); } else { @@ -1136,7 +1143,7 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e case MPC_TYPE_NOT: mpc_input_mark(i); mpc_input_suppress_enable(i); - if (mpc_parse_run(i, p->data.not.x, r, e)) { + if (mpc_parse_run(i, p->data.not.x, r, e, depth+1)) { mpc_input_rewind(i); mpc_input_suppress_disable(i); mpc_parse_dtor(i, p->data.not.dx, r->output); @@ -1148,7 +1155,7 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e } case MPC_TYPE_MAYBE: - if (mpc_parse_run(i, p->data.not.x, r, e)) { + if (mpc_parse_run(i, p->data.not.x, r, e, depth+1)) { MPC_SUCCESS(r->output); } else { *e = mpc_err_merge(i, *e, r->error); @@ -1161,7 +1168,7 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e results = results_stk; - while (mpc_parse_run(i, p->data.repeat.x, &results[j], e)) { + while (mpc_parse_run(i, p->data.repeat.x, &results[j], e, depth+1)) { j++; if (j == MPC_PARSE_STACK_MIN) { results_slots = j + j / 2; @@ -1183,7 +1190,7 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e results = results_stk; - while (mpc_parse_run(i, p->data.repeat.x, &results[j], e)) { + while (mpc_parse_run(i, p->data.repeat.x, &results[j], e, depth+1)) { j++; if (j == MPC_PARSE_STACK_MIN) { results_slots = j + j / 2; @@ -1214,7 +1221,7 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e ? mpc_malloc(i, sizeof(mpc_result_t) * p->data.repeat.n) : results_stk; - while (mpc_parse_run(i, p->data.repeat.x, &results[j], e)) { + while (mpc_parse_run(i, p->data.repeat.x, &results[j], e, depth+1)) { j++; if (j == p->data.repeat.n) { break; } } @@ -1243,7 +1250,7 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e : results_stk; for (j = 0; j < p->data.or.n; j++) { - if (mpc_parse_run(i, p->data.or.xs[j], &results[j], e)) { + if (mpc_parse_run(i, p->data.or.xs[j], &results[j], e, depth+1)) { MPC_SUCCESS(results[j].output; if (p->data.or.n > MPC_PARSE_STACK_MIN) { mpc_free(i, results); }); } else { @@ -1264,7 +1271,7 @@ static int mpc_parse_run(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r, mpc_e mpc_input_mark(i); for (j = 0; j < p->data.and.n; j++) { - if (!mpc_parse_run(i, p->data.and.xs[j], &results[j], e)) { + if (!mpc_parse_run(i, p->data.and.xs[j], &results[j], e, depth+1)) { mpc_input_rewind(i); for (k = 0; k < j; k++) { mpc_parse_dtor(i, p->data.and.dxs[k], results[k].output); @@ -1297,7 +1304,7 @@ int mpc_parse_input(mpc_input_t *i, mpc_parser_t *p, mpc_result_t *r) { int x; mpc_err_t *e = mpc_err_fail(i, "Unknown Error"); e->state = mpc_state_invalid(); - x = mpc_parse_run(i, p, r, &e); + x = mpc_parse_run(i, p, r, &e, 0); if (x) { mpc_err_delete_internal(i, e); r->output = mpc_export(i, r->output); From 5120609e6e81974acd3a2e9704e74e32b770ef6f Mon Sep 17 00:00:00 2001 From: Daniel Holden Date: Sun, 1 Sep 2019 16:21:11 -0400 Subject: [PATCH 15/21] fixed bug with trimming string with all space characters --- mpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mpc.c b/mpc.c index befd1b5..9aa5a13 100644 --- a/mpc.c +++ b/mpc.c @@ -2470,7 +2470,7 @@ mpc_val_t *mpcf_strtriml(mpc_val_t *x) { mpc_val_t *mpcf_strtrimr(mpc_val_t *x) { char *s = x; size_t l = strlen(s); - while (isspace((unsigned char)s[l-1])) { + while (l > 0 && isspace((unsigned char)s[l-1])) { s[l-1] = '\0'; l--; } return s; From 0edd06ec442442e09e9fce14c7121d96171e3f98 Mon Sep 17 00:00:00 2001 From: Joshua Crowgey Date: Wed, 8 Jan 2020 22:07:32 -0800 Subject: [PATCH 16/21] Removed trailing whitespace --- Makefile | 2 +- mpc.c | 8 ++-- mpc.h | 8 ++-- tests/core.c | 108 +++++++++++++++++++++---------------------- tests/ptest.c | 126 +++++++++++++++++++++++++------------------------- tests/regex.c | 48 +++++++++---------- 6 files changed, 150 insertions(+), 150 deletions(-) diff --git a/Makefile b/Makefile index f60b65c..50b1ba3 100644 --- a/Makefile +++ b/Makefile @@ -49,7 +49,7 @@ $(DIST)/lib$(PROJ).a: $(PROJ).c mpc.h $(AR) rcs $(DIST)/lib$(PROJ).a $(DIST)/$(PROJ).o libs: $(DIST)/lib$(PROJ).so $(DIST)/lib$(PROJ).a - + clean: rm -rf -- $(DIST) diff --git a/mpc.c b/mpc.c index 9aa5a13..662ac53 100644 --- a/mpc.c +++ b/mpc.c @@ -497,28 +497,28 @@ static int mpc_input_range(mpc_input_t *i, char c, char d, char **o) { char x; if (mpc_input_terminated(i)) { return 0; } x = mpc_input_getc(i); - return x >= c && x <= d ? mpc_input_success(i, x, o) : mpc_input_failure(i, x); + return x >= c && x <= d ? mpc_input_success(i, x, o) : mpc_input_failure(i, x); } static int mpc_input_oneof(mpc_input_t *i, const char *c, char **o) { char x; if (mpc_input_terminated(i)) { return 0; } x = mpc_input_getc(i); - return strchr(c, x) != 0 ? mpc_input_success(i, x, o) : mpc_input_failure(i, x); + return strchr(c, x) != 0 ? mpc_input_success(i, x, o) : mpc_input_failure(i, x); } static int mpc_input_noneof(mpc_input_t *i, const char *c, char **o) { char x; if (mpc_input_terminated(i)) { return 0; } x = mpc_input_getc(i); - return strchr(c, x) == 0 ? mpc_input_success(i, x, o) : mpc_input_failure(i, x); + return strchr(c, x) == 0 ? mpc_input_success(i, x, o) : mpc_input_failure(i, x); } static int mpc_input_satisfy(mpc_input_t *i, int(*cond)(char), char **o) { char x; if (mpc_input_terminated(i)) { return 0; } x = mpc_input_getc(i); - return cond(x) ? mpc_input_success(i, x, o) : mpc_input_failure(i, x); + return cond(x) ? mpc_input_success(i, x, o) : mpc_input_failure(i, x); } static int mpc_input_string(mpc_input_t *i, const char *c, char **o) { diff --git a/mpc.h b/mpc.h index a5ed16d..b738cfd 100644 --- a/mpc.h +++ b/mpc.h @@ -204,7 +204,7 @@ mpc_parser_t *mpc_whole(mpc_parser_t *a, mpc_dtor_t da); mpc_parser_t *mpc_stripl(mpc_parser_t *a); mpc_parser_t *mpc_stripr(mpc_parser_t *a); mpc_parser_t *mpc_strip(mpc_parser_t *a); -mpc_parser_t *mpc_tok(mpc_parser_t *a); +mpc_parser_t *mpc_tok(mpc_parser_t *a); mpc_parser_t *mpc_sym(const char *s); mpc_parser_t *mpc_total(mpc_parser_t *a, mpc_dtor_t da); @@ -275,7 +275,7 @@ enum { mpc_parser_t *mpc_re(const char *re); mpc_parser_t *mpc_re_mode(const char *re, int mode); - + /* ** AST */ @@ -373,8 +373,8 @@ void mpc_optimise(mpc_parser_t *p); void mpc_stats(mpc_parser_t *p); int mpc_test_pass(mpc_parser_t *p, const char *s, const void *d, - int(*tester)(const void*, const void*), - mpc_dtor_t destructor, + int(*tester)(const void*, const void*), + mpc_dtor_t destructor, void(*printer)(const void*)); int mpc_test_fail(mpc_parser_t *p, const char *s, const void *d, diff --git a/tests/core.c b/tests/core.c index 81cb83b..0dae040 100644 --- a/tests/core.c +++ b/tests/core.c @@ -12,7 +12,7 @@ static void strprint(const void* x) { printf("'%s'", (char*)x); } void test_ident(void) { /* ^[a-zA-Z_][a-zA-Z0-9_]*$ */ - + mpc_parser_t* Ident = mpc_whole( mpc_and(2, mpcf_strfold, mpc_or(2, mpc_alpha(), mpc_underscore()), @@ -20,7 +20,7 @@ void test_ident(void) { free), free ); - + PT_ASSERT(mpc_test_pass(Ident, "test", "test", streq, free, strprint)); PT_ASSERT(mpc_test_fail(Ident, " blah", "", streq, free, strprint)); PT_ASSERT(mpc_test_pass(Ident, "anoth21er", "anoth21er", streq, free, strprint)); @@ -28,99 +28,99 @@ void test_ident(void) { PT_ASSERT(mpc_test_fail(Ident, "some spaces", "", streq, free, strprint)); PT_ASSERT(mpc_test_fail(Ident, "", "", streq, free, strprint)); PT_ASSERT(mpc_test_fail(Ident, "18nums", "", streq, free, strprint)); - + mpc_delete(Ident); } void test_maths(void) { - - mpc_parser_t *Expr, *Factor, *Term, *Maths; + + mpc_parser_t *Expr, *Factor, *Term, *Maths; int r0 = 1, r1 = 5, r2 = 13, r3 = 0, r4 = 2; - + Expr = mpc_new("expr"); Factor = mpc_new("factor"); Term = mpc_new("term"); Maths = mpc_new("maths"); - mpc_define(Expr, mpc_or(2, + mpc_define(Expr, mpc_or(2, mpc_and(3, mpcf_maths, Factor, mpc_oneof("*/"), Factor, free, free), Factor )); - - mpc_define(Factor, mpc_or(2, + + mpc_define(Factor, mpc_or(2, mpc_and(3, mpcf_maths, Term, mpc_oneof("+-"), Term, free, free), Term )); - - mpc_define(Term, mpc_or(2, + + mpc_define(Term, mpc_or(2, mpc_int(), mpc_parens(Expr, free) )); - + mpc_define(Maths, mpc_whole(Expr, free)); - + PT_ASSERT(mpc_test_pass(Maths, "1", &r0, int_eq, free, int_print)); PT_ASSERT(mpc_test_pass(Maths, "(5)", &r1, int_eq, free, int_print)); PT_ASSERT(mpc_test_pass(Maths, "(4*2)+5", &r2, int_eq, free, int_print)); PT_ASSERT(mpc_test_fail(Maths, "a", &r3, int_eq, free, int_print)); PT_ASSERT(mpc_test_fail(Maths, "2b+4", &r4, int_eq, free, int_print)); - + mpc_cleanup(4, Expr, Factor, Term, Maths); } void test_strip(void) { - + mpc_parser_t *Stripperl = mpc_apply(mpc_many(mpcf_strfold, mpc_any()), mpcf_strtriml); mpc_parser_t *Stripperr = mpc_apply(mpc_many(mpcf_strfold, mpc_any()), mpcf_strtrimr); mpc_parser_t *Stripper = mpc_apply(mpc_many(mpcf_strfold, mpc_any()), mpcf_strtrim); - + PT_ASSERT(mpc_test_pass(Stripperl, " asdmlm dasd ", "asdmlm dasd ", streq, free, strprint)); PT_ASSERT(mpc_test_pass(Stripperr, " asdmlm dasd ", " asdmlm dasd", streq, free, strprint)); PT_ASSERT(mpc_test_pass(Stripper, " asdmlm dasd ", "asdmlm dasd", streq, free, strprint)); - + mpc_delete(Stripperl); mpc_delete(Stripperr); mpc_delete(Stripper); - + } void test_repeat(void) { - + int success; mpc_result_t r; mpc_parser_t *p = mpc_count(3, mpcf_strfold, mpc_digit(), free); - + success = mpc_parse("test", "046", p, &r); PT_ASSERT(success); PT_ASSERT_STR_EQ(r.output, "046"); free(r.output); - + success = mpc_parse("test", "046aa", p, &r); PT_ASSERT(success); PT_ASSERT_STR_EQ(r.output, "046"); free(r.output); - + success = mpc_parse("test", "04632", p, &r); PT_ASSERT(success); PT_ASSERT_STR_EQ(r.output, "046"); free(r.output); - + success = mpc_parse("test", "04", p, &r); PT_ASSERT(!success); mpc_err_delete(r.error); - + mpc_delete(p); - + } void test_copy(void) { - + int success; mpc_result_t r; mpc_parser_t* p = mpc_or(2, mpc_char('a'), mpc_char('b')); mpc_parser_t* q = mpc_and(2, mpcf_strfold, p, mpc_copy(p), free); - + success = mpc_parse("test", "aa", q, &r); PT_ASSERT(success); PT_ASSERT_STR_EQ(r.output, "aa"); @@ -130,26 +130,26 @@ void test_copy(void) { PT_ASSERT(success); PT_ASSERT_STR_EQ(r.output, "bb"); free(r.output); - + success = mpc_parse("test", "ab", q, &r); PT_ASSERT(success); PT_ASSERT_STR_EQ(r.output, "ab"); free(r.output); - + success = mpc_parse("test", "ba", q, &r); PT_ASSERT(success); PT_ASSERT_STR_EQ(r.output, "ba"); free(r.output); - + success = mpc_parse("test", "c", p, &r); PT_ASSERT(!success); mpc_err_delete(r.error); - + mpc_delete(mpc_copy(p)); mpc_delete(mpc_copy(q)); - + mpc_delete(q); - + } static int line_count = 0; @@ -162,23 +162,23 @@ static mpc_val_t* read_line(mpc_val_t* line) { void test_reader(void) { mpc_parser_t* Line = mpc_many( - mpcf_strfold, + mpcf_strfold, mpc_apply(mpc_re("[^\\n]*(\\n|$)"), read_line)); - + line_count = 0; - PT_ASSERT(mpc_test_pass(Line, - "hello\nworld\n\nthis\nis\ndan", + PT_ASSERT(mpc_test_pass(Line, + "hello\nworld\n\nthis\nis\ndan", "hello\nworld\n\nthis\nis\ndan", streq, free, strprint)); - + PT_ASSERT(line_count == 6); - + line_count = 0; - - PT_ASSERT(mpc_test_pass(Line, - "abcHVwufvyuevuy3y436782\n\n\nrehre\nrew\n-ql.;qa\neg", + + PT_ASSERT(mpc_test_pass(Line, + "abcHVwufvyuevuy3y436782\n\n\nrehre\nrew\n-ql.;qa\neg", "abcHVwufvyuevuy3y436782\n\n\nrehre\nrew\n-ql.;qa\neg", streq, free, strprint)); - + PT_ASSERT(line_count == 7); mpc_delete(Line); @@ -194,32 +194,32 @@ static mpc_val_t *print_token(mpc_val_t *x) { } void test_tokens(void) { - + mpc_parser_t* Tokens = mpc_many( - mpcf_strfold, + mpcf_strfold, mpc_apply(mpc_strip(mpc_re("\\s*([a-zA-Z_]+|[0-9]+|,|\\.|:)")), print_token)); - + token_count = 0; - PT_ASSERT(mpc_test_pass(Tokens, - " hello 4352 , \n foo.bar \n\n test:ing ", + PT_ASSERT(mpc_test_pass(Tokens, + " hello 4352 , \n foo.bar \n\n test:ing ", "hello4352,foo.bartest:ing", streq, free, strprint)); - + PT_ASSERT(token_count == 9); mpc_delete(Tokens); - + } void test_eoi(void) { - + mpc_parser_t* Line = mpc_re("[^\\n]*$"); - + PT_ASSERT(mpc_test_pass(Line, "blah", "blah", streq, free, strprint)); PT_ASSERT(mpc_test_pass(Line, "blah\n", "blah\n", streq, free, strprint)); - + mpc_delete(Line); - + } void suite_core(void) { diff --git a/tests/ptest.c b/tests/ptest.c index f5ffc8d..f8e36a4 100644 --- a/tests/ptest.c +++ b/tests/ptest.c @@ -35,7 +35,7 @@ enum { YELLOW = 6, WHITE = 7, GRAY = 8, - + LIGHT_BLUE = 9, LIGHT_GREEN = 10, LIGHT_AQUA = 11, @@ -43,7 +43,7 @@ enum { LIGHT_PURPLE = 13, LIGHT_YELLOW = 14, LIGHT_WHITE = 15, - + DEFAULT = 16 }; @@ -55,16 +55,16 @@ static WORD defaults; static int defaults_loaded = 0; static void pt_color(int color) { - + HANDLE cnsl = GetStdHandle(STD_OUTPUT_HANDLE); - + if (!defaults_loaded) { CONSOLE_SCREEN_BUFFER_INFO info; GetConsoleScreenBufferInfo(cnsl, &info); defaults = info.wAttributes; defaults_loaded = 1; } - + SetConsoleTextAttribute(cnsl, color == DEFAULT ? defaults : color); } @@ -90,7 +90,7 @@ static const char* colors[] = { "\x1B[39m", }; -static void pt_color(int color) { +static void pt_color(int color) { printf("%s", colors[color]); } @@ -107,27 +107,27 @@ static char assert_err_buff[MAX_ERROR]; static int assert_err_num = 0; void pt_assert_run(int result, const char* expr, const char* file, int line) { - + num_asserts++; test_passing = test_passing && result; - + if (result) { num_assert_passes++; } else { - sprintf(assert_err_buff, - " %i. Assert [ %s ] (%s:%i)\n", + sprintf(assert_err_buff, + " %i. Assert [ %s ] (%s:%i)\n", assert_err_num+1, expr, file, line ); strcat(assert_err, assert_err_buff); assert_err_num++; num_assert_fails++; } - + } static void ptest_signal(int sig) { test_passing = 0; - + switch( sig ) { case SIGFPE: sprintf(assert_err_buff, " %i. Division by Zero\n", assert_err_num+1); @@ -140,18 +140,18 @@ static void ptest_signal(int sig) { break; default: break; } - + assert_err_num++; strcat(assert_err, assert_err_buff); - - pt_color(RED); + + pt_color(RED); printf("Failed! \n\n%s\n", assert_err); pt_color(DEFAULT); - + puts(" | Stopping Execution."); fflush(stdout); exit(0); - + } /* Tests */ @@ -160,27 +160,27 @@ static void pt_title_case(char* output, const char* input) { int space = 1; unsigned int i; - + strcpy(output, input); - + for(i = 0; i < strlen(output); i++) { if (output[i] == '_' || output[i] == ' ') { space = 1; output[i] = ' '; continue; - } - + } + if (space && output[i] >= 'a' && output[i] <= 'z') { space = 0; output[i] = output[i] - 32; continue; } - + space = 0; - + } - + } typedef struct { @@ -200,24 +200,24 @@ void pt_add_test(void (*func)(void), const char* name, const char* suite) { test_t test; if (num_tests == MAX_TESTS) { - printf("ERROR: Exceeded maximum test count of %i!\n", + printf("ERROR: Exceeded maximum test count of %i!\n", MAX_TESTS); abort(); } - + if (strlen(name) >= MAX_NAME) { - printf("ERROR: Test name '%s' too long (Maximum is %i characters)\n", + printf("ERROR: Test name '%s' too long (Maximum is %i characters)\n", name, MAX_NAME); abort(); } - + if (strlen(suite) >= MAX_NAME) { - printf("ERROR: Test suite '%s' too long (Maximum is %i characters)\n", + printf("ERROR: Test suite '%s' too long (Maximum is %i characters)\n", suite, MAX_NAME); abort(); } - + test.func = func; pt_title_case(test.name, name); pt_title_case(test.suite, suite); - + tests[num_tests] = test; num_tests++; } @@ -239,7 +239,7 @@ static clock_t start, end; static char current_suite[MAX_NAME]; int pt_run(void) { - + int i; double total; test_t test; @@ -252,18 +252,18 @@ int pt_run(void) { puts(" | |"); puts(" | Daniel Holden (contact@theorangeduck.com) |"); puts(" +-------------------------------------------+"); - + signal(SIGFPE, ptest_signal); signal(SIGILL, ptest_signal); signal(SIGSEGV, ptest_signal); - + start = clock(); strcpy(current_suite, ""); - + for(i = 0; i < num_tests; i++) { test = tests[i]; - + /* Check for transition to a new suite */ if (strcmp(test.suite, current_suite)) { @@ -275,25 +275,25 @@ int pt_run(void) { num_suites_fails++; } } - + suite_passing = 1; strcpy(current_suite, test.suite); printf("\n\n ===== %s =====\n\n", current_suite); } - + /* Run Test */ - + test_passing = 1; strcpy(assert_err, ""); strcpy(assert_err_buff, ""); assert_err_num = 0; printf(" | %s ... ", test.name); fflush(stdout); - + test.func(); - + suite_passing = suite_passing && test_passing; - + if (test_passing) { num_tests_passes++; pt_color(GREEN); @@ -301,56 +301,56 @@ int pt_run(void) { pt_color(DEFAULT); } else { num_tests_fails++; - pt_color(RED); + pt_color(RED); printf("Failed! \n\n%s\n", assert_err); pt_color(DEFAULT); } - + } - + if (suite_passing) { num_suites_passes++; } else { num_suites_fails++; } - + end = clock(); - + puts(""); puts(" +---------------------------------------------------+"); puts(" | Summary |"); puts(" +---------++------------+-------------+-------------+"); - + printf(" | Suites ||"); - pt_color(YELLOW); printf(" Total %4d ", num_suites); + pt_color(YELLOW); printf(" Total %4d ", num_suites); pt_color(DEFAULT); putchar('|'); - pt_color(GREEN); printf(" Passed %4d ", num_suites_passes); + pt_color(GREEN); printf(" Passed %4d ", num_suites_passes); pt_color(DEFAULT); putchar('|'); - pt_color(RED); printf(" Failed %4d ", num_suites_fails); + pt_color(RED); printf(" Failed %4d ", num_suites_fails); pt_color(DEFAULT); puts("|"); - + printf(" | Tests ||"); - pt_color(YELLOW); printf(" Total %4d ", num_tests); + pt_color(YELLOW); printf(" Total %4d ", num_tests); pt_color(DEFAULT); putchar('|'); - pt_color(GREEN); printf(" Passed %4d ", num_tests_passes); + pt_color(GREEN); printf(" Passed %4d ", num_tests_passes); pt_color(DEFAULT); putchar('|'); - pt_color(RED); printf(" Failed %4d ", num_tests_fails); + pt_color(RED); printf(" Failed %4d ", num_tests_fails); pt_color(DEFAULT); puts("|"); - + printf(" | Asserts ||"); - pt_color(YELLOW); printf(" Total %4d ", num_asserts); + pt_color(YELLOW); printf(" Total %4d ", num_asserts); pt_color(DEFAULT); putchar('|'); - pt_color(GREEN); printf(" Passed %4d ", num_assert_passes); + pt_color(GREEN); printf(" Passed %4d ", num_assert_passes); pt_color(DEFAULT); putchar('|'); - pt_color(RED); printf(" Failed %4d ", num_assert_fails); + pt_color(RED); printf(" Failed %4d ", num_assert_fails); pt_color(DEFAULT); puts("|"); - + puts(" +---------++------------+-------------+-------------+"); puts(""); - + total = (double)(end - start) / CLOCKS_PER_SEC; - + printf(" Total Running Time: %0.3fs\n\n", total); - + if (num_suites_fails > 0) { return 1; } else { return 0; } } diff --git a/tests/regex.c b/tests/regex.c index f72dc5a..38f9519 100644 --- a/tests/regex.c +++ b/tests/regex.c @@ -25,7 +25,7 @@ void test_regex_basic(void) { re3 = mpc_re("abc(abdd)?"); re4 = mpc_re("ab|c(abdd)?"); re5 = mpc_re("abc(ab|dd)+g$"); - + PT_ASSERT(regex_test_pass(re0, "abc", "abc")); PT_ASSERT(regex_test_pass(re0, "bcd", "bcd")); PT_ASSERT(regex_test_fail(re0, "bc", "bc")); @@ -35,7 +35,7 @@ void test_regex_basic(void) { PT_ASSERT(regex_test_pass(re2, "abcabab", "abcabab")); PT_ASSERT(regex_test_pass(re2, "abcababd", "abcabab")); PT_ASSERT(regex_test_pass(re5, "abcddg", "abcddg")); - + mpc_delete(re0); mpc_delete(re1); mpc_delete(re2); @@ -57,47 +57,47 @@ void test_regex_boundary(void) { PT_ASSERT(regex_test_pass(re0, "foo.", "foo")); PT_ASSERT(regex_test_pass(re0, "foo)", "foo")); PT_ASSERT(regex_test_pass(re0, "foo baz", "foo")); - + PT_ASSERT(regex_test_fail(re0, "foobar", "foo")); PT_ASSERT(regex_test_fail(re0, "foo3", "foo")); - + PT_ASSERT(regex_test_pass(re1, "foo", "foo")); PT_ASSERT(regex_test_pass(re1, " foo", " foo")); PT_ASSERT(regex_test_fail(re1, "wfoo", "foo")); - + PT_ASSERT(regex_test_pass(re2, "python", "python")); PT_ASSERT(regex_test_pass(re2, "py3", "py3")); PT_ASSERT(regex_test_pass(re2, "py2", "py2")); PT_ASSERT(regex_test_fail(re2, "py", "py")); PT_ASSERT(regex_test_fail(re2, "py.", "py.")); PT_ASSERT(regex_test_fail(re2, "py!", "py!")); - + mpc_delete(re0); mpc_delete(re1); mpc_delete(re2); - + } void test_regex_range(void) { mpc_parser_t *re0, *re1, *re2, *re3; - + re0 = mpc_re("abg[abcdef]"); re1 = mpc_re("y*[a-z]"); re2 = mpc_re("zz(p+)?[A-Z_0\\]123]*"); re3 = mpc_re("^[^56hy].*$"); - + /* TODO: Testing */ - + mpc_delete(re0); mpc_delete(re1); mpc_delete(re2); mpc_delete(re3); - + } void test_regex_string(void) { - + mpc_parser_t *re0 = mpc_re("\"(\\\\.|[^\"])*\""); PT_ASSERT(regex_test_pass(re0, "\"there\"", "\"there\"")); @@ -110,26 +110,26 @@ void test_regex_string(void) { } void test_regex_lisp_comment(void) { - + mpc_parser_t *re0 = mpc_re(";[^\\n\\r]*"); PT_ASSERT(regex_test_pass(re0, ";comment", ";comment")); PT_ASSERT(regex_test_pass(re0, ";i am the\nman", ";i am the")); - + mpc_delete(re0); - + } void test_regex_newline(void) { - + mpc_parser_t *re0 = mpc_re("[a-z]*"); PT_ASSERT(regex_test_pass(re0, "hi", "hi")); PT_ASSERT(regex_test_pass(re0, "hi\nk", "hi")); PT_ASSERT(regex_test_fail(re0, "hi\nk", "hi\nk")); - + mpc_delete(re0); - + } void test_regex_multiline(void) { @@ -142,13 +142,13 @@ void test_regex_multiline(void) { PT_ASSERT(regex_test_fail(re0, "45234", "45234")); PT_ASSERT(regex_test_fail(re0, "\n45234", "\n45234")); PT_ASSERT(regex_test_pass(re0, "\n45234", "\n")); - + mpc_delete(re0); - + } void test_regex_dotall(void) { - + mpc_parser_t *re0 = mpc_re_mode("^.*$", MPC_RE_DEFAULT); mpc_parser_t *re1 = mpc_re_mode("^.*$", MPC_RE_DOTALL); @@ -157,16 +157,16 @@ void test_regex_dotall(void) { PT_ASSERT(regex_test_fail(re0, "he\nllo\n", "he")); PT_ASSERT(regex_test_pass(re0, "34njaksdklmasd", "34njaksdklmasd")); PT_ASSERT(regex_test_fail(re0, "34njaksd\nklmasd", "34njaksd")); - + PT_ASSERT(regex_test_pass(re1, "hello", "hello")); PT_ASSERT(regex_test_pass(re1, "hello\n", "hello\n")); PT_ASSERT(regex_test_pass(re1, "he\nllo\n", "he\nllo\n")); PT_ASSERT(regex_test_pass(re1, "34njaksdklmasd", "34njaksdklmasd")); PT_ASSERT(regex_test_pass(re1, "34njaksd\nklmasd", "34njaksd\nklmasd")); - + mpc_delete(re0); mpc_delete(re1); - + } void suite_regex(void) { From e1f5bea9820a9d24a981d8886387f12456c6f560 Mon Sep 17 00:00:00 2001 From: halosghost Date: Mon, 3 Feb 2020 23:32:25 -0600 Subject: [PATCH 17/21] (#122) Support building with tcc - replace ``mpc.h`` with ``$(PROJ).h`` - ``filter-out`` ``$(PROJ).h`` when building examples - expose ``$(STD)`` --- Makefile | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 50b1ba3..435f0f2 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,10 @@ PROJ = mpc CC ?= gcc -STND = -ansi +STD ?= -ansi DIST = build MKDIR ?= mkdir -p PREFIX ?= /usr/local -CFLAGS ?= $(STND) -pedantic -O3 -g -Wall -Werror -Wextra -Wformat=2 -Wshadow \ +CFLAGS ?= $(STD) -pedantic -O3 -g -Wall -Werror -Wextra -Wformat=2 -Wshadow \ -Wno-long-long -Wno-overlength-strings -Wno-format-nonliteral -Wcast-align \ -Wwrite-strings -Wstrict-prototypes -Wold-style-definition -Wredundant-decls \ -Wnested-externs -Wmissing-include-dirs -Wswitch-default @@ -25,26 +25,26 @@ check: $(DIST)/test-file $(DIST)/test-static $(DIST)/test-dynamic ./$(DIST)/test-static LD_LIBRARY_PATH=$(DIST) ./$(DIST)/test-dynamic -$(DIST)/test-file: $(TESTS) $(PROJ).c mpc.h tests/ptest.h +$(DIST)/test-file: $(TESTS) $(PROJ).c $(PROJ).h tests/ptest.h $(CC) $(filter-out -Werror, $(CFLAGS)) $(TESTS) $(PROJ).c -lm -o $(DIST)/test-file -$(DIST)/test-dynamic: $(TESTS) $(DIST)/lib$(PROJ).so mpc.h tests/ptest.h +$(DIST)/test-dynamic: $(TESTS) $(DIST)/lib$(PROJ).so $(PROJ).h tests/ptest.h $(CC) $(filter-out -Werror, $(CFLAGS)) $(TESTS) -lm -L$(DIST) -l$(PROJ) -o $(DIST)/test-dynamic -$(DIST)/test-static: $(TESTS) $(DIST)/lib$(PROJ).a mpc.h tests/ptest.h +$(DIST)/test-static: $(TESTS) $(DIST)/lib$(PROJ).a $(PROJ).h tests/ptest.h $(CC) $(filter-out -Werror, $(CFLAGS)) $(TESTS) -lm -L$(DIST) -l$(PROJ) -static -o $(DIST)/test-static -examples/%: $(DIST) examples/%.c $(PROJ).c mpc.h - $(CC) $(CFLAGS) $(filter-out $(DIST), $^) -lm -o $(DIST)/$@ +examples/%: $(DIST) examples/%.c $(PROJ).c $(PROJ).h + $(CC) $(CFLAGS) $(filter-out $(DIST) $(PROJ).h, $^) -lm -o $(DIST)/$@ -$(DIST)/lib$(PROJ).so: $(PROJ).c mpc.h +$(DIST)/lib$(PROJ).so: $(PROJ).c $(PROJ).h ifneq ($(OS),Windows_NT) $(CC) $(CFLAGS) -fPIC -shared $(PROJ).c -o $(DIST)/lib$(PROJ).so else $(CC) $(CFLAGS) -shared $(PROJ).c -o $(DIST)/lib$(PROJ).so endif -$(DIST)/lib$(PROJ).a: $(PROJ).c mpc.h +$(DIST)/lib$(PROJ).a: $(PROJ).c $(PROJ).h $(CC) $(CFLAGS) -c $(PROJ).c -o $(DIST)/$(PROJ).o $(AR) rcs $(DIST)/lib$(PROJ).a $(DIST)/$(PROJ).o From 7869e2087ec25f808dca74d451af5c0e45c8b618 Mon Sep 17 00:00:00 2001 From: halosghost Date: Mon, 3 Feb 2020 23:39:35 -0600 Subject: [PATCH 18/21] (closes #122) add ^M to end of line_reader example --- examples/line_reader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/line_reader.c b/examples/line_reader.c index 1354d42..48d01be 100644 --- a/examples/line_reader.c +++ b/examples/line_reader.c @@ -31,4 +31,4 @@ int main(int argc, char **argv) { mpc_delete(Line); return 0; -} \ No newline at end of file +} From 7bc1bb0a9b1b75f115a0affe54e4a3559d01c73c Mon Sep 17 00:00:00 2001 From: halosghost Date: Sun, 9 Feb 2020 22:04:09 -0600 Subject: [PATCH 19/21] (#124) preliminary pkg-config file setup and install --- Makefile | 9 +++++++-- mpc.pc | 8 ++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 mpc.pc diff --git a/Makefile b/Makefile index 50b1ba3..e7b1b5a 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ TESTS = $(wildcard tests/*.c) EXAMPLES = $(wildcard examples/*.c) EXAMPLESEXE = $(EXAMPLES:.c=) -.PHONY: all check clean libs +.PHONY: all check clean libs $(DIST)/$(PROJ).pc all: $(EXAMPLESEXE) check @@ -50,14 +50,19 @@ $(DIST)/lib$(PROJ).a: $(PROJ).c mpc.h libs: $(DIST)/lib$(PROJ).so $(DIST)/lib$(PROJ).a +$(DIST)/$(PROJ).pc: $(DIST) $(PROJ).pc + cp $(PROJ).pc $(DIST)/$(PROJ).pc + sed -i '1i\prefix=$(PREFIX)/' $(DIST)/$(PROJ).pc + clean: rm -rf -- $(DIST) install: all - install -d -m644 $(DESTDIR)$(PREFIX)/{include,lib,share/$(PROJ)} + install -d -m644 $(DESTDIR)$(PREFIX)/{include,lib/pkgconfig,share/$(PROJ)} install -m755 -t $(DESTDIR)$(PREFIX)/lib $(DIST)/lib* install -m644 -t $(DESTDIR)$(PREFIX)/share/$(PROJ) $(PROJ).{c,h} install -m644 $(PROJ).h $(DESTDIR)$(PREFIX)/include/$(PROJ).h + install -m644 $(DIST)/$(PROJ).pc $(DESTDIR)$(PREFIX)/lib/pkgconfig/$(PROJ).pc uninstall: rm -rf -- \ diff --git a/mpc.pc b/mpc.pc new file mode 100644 index 0000000..858f0c7 --- /dev/null +++ b/mpc.pc @@ -0,0 +1,8 @@ +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: mpc +Description: Library for creating parser combinators +Version: 0.9.0 +Libs: -L${libdir} -lmpc +Cflags: -I${includedir} From 248540274d6f0f5202c92e606367680cfdc71d0d Mon Sep 17 00:00:00 2001 From: Liumeo Date: Tue, 7 Apr 2020 22:30:34 -0400 Subject: [PATCH 20/21] Fix long format --- mpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mpc.c b/mpc.c index 662ac53..b9e077c 100644 --- a/mpc.c +++ b/mpc.c @@ -641,7 +641,7 @@ char *mpc_err_string(mpc_err_t *x) { } mpc_err_string_cat(buffer, &pos, &max, - "%s:%i:%i: error: expected ", x->filename, x->state.row+1, x->state.col+1); + "%s:%li:%li: error: expected ", x->filename, x->state.row+1, x->state.col+1); if (x->expected_num == 0) { mpc_err_string_cat(buffer, &pos, &max, "ERROR: NOTHING EXPECTED"); } if (x->expected_num == 1) { mpc_err_string_cat(buffer, &pos, &max, "%s", x->expected[0]); } From e8631817639de4c976e22934ccc007051ef06a18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren=20Tempel?= Date: Sun, 3 May 2020 17:31:36 +0200 Subject: [PATCH 21/21] mpc.h: Add prototype for mpcf_freefold The mpcf_freefold is documented in the README but currently not declared in the header file. As such, adding the latter was probably just forgotten at some point. This change adds the required function prototype. --- mpc.h | 1 + 1 file changed, 1 insertion(+) diff --git a/mpc.h b/mpc.h index b738cfd..1622ada 100644 --- a/mpc.h +++ b/mpc.h @@ -258,6 +258,7 @@ mpc_val_t *mpcf_snd_free(int n, mpc_val_t** xs); mpc_val_t *mpcf_trd_free(int n, mpc_val_t** xs); mpc_val_t *mpcf_all_free(int n, mpc_val_t** xs); +mpc_val_t *mpcf_freefold(int n, mpc_val_t** xs); mpc_val_t *mpcf_strfold(int n, mpc_val_t** xs); mpc_val_t *mpcf_maths(int n, mpc_val_t** xs);