merge
This commit is contained in:
		| @@ -587,7 +587,7 @@ Useful Parsers | |||||||
|     <tr><td><code>mpc_strip(mpc_parser_t *a);</code></td><td>Matches <code>a</code> consuming any surrounding whitespace</td></tr> |     <tr><td><code>mpc_strip(mpc_parser_t *a);</code></td><td>Matches <code>a</code> consuming any surrounding whitespace</td></tr> | ||||||
|     <tr><td><code>mpc_tok(mpc_parser_t *a);</code></td><td>Matches <code>a</code> and consumes any trailing whitespace</td></tr> |     <tr><td><code>mpc_tok(mpc_parser_t *a);</code></td><td>Matches <code>a</code> and consumes any trailing whitespace</td></tr> | ||||||
|     <tr><td><code>mpc_sym(const char *s);</code></td><td>Matches string <code>s</code> and consumes any trailing whitespace</td></tr> |     <tr><td><code>mpc_sym(const char *s);</code></td><td>Matches string <code>s</code> and consumes any trailing whitespace</td></tr> | ||||||
|     <tr><td><code>mpc_total(mpc_parser_t *a, mpc_dtor_t da);</code></td><td>Matches the whitespace consumed <code>a</code>, enclosed in the start and end of input</td></tr> |     <tr><td><code>mpc_total(mpc_parser_t *a, mpc_dtor_t da);</code></td><td>Matches the whitespace consumed <code>a</code>, enclosed in the start and end of input</td></tr> | ||||||
|     <tr><td><code>mpc_between(mpc_parser_t *a, mpc_dtor_t ad, <br /> const char *o, const char *c);</code></td><td> Matches <code>a</code> between strings <code>o</code> and <code>c</code></td></tr> |     <tr><td><code>mpc_between(mpc_parser_t *a, mpc_dtor_t ad, <br /> const char *o, const char *c);</code></td><td> Matches <code>a</code> between strings <code>o</code> and <code>c</code></td></tr> | ||||||
|     <tr><td><code>mpc_parens(mpc_parser_t *a, mpc_dtor_t ad);</code></td><td>Matches <code>a</code> between <code>"("</code> and <code>")"</code></td></tr> |     <tr><td><code>mpc_parens(mpc_parser_t *a, mpc_dtor_t ad);</code></td><td>Matches <code>a</code> between <code>"("</code> and <code>")"</code></td></tr> | ||||||
|     <tr><td><code>mpc_braces(mpc_parser_t *a, mpc_dtor_t ad);</code></td><td>Matches <code>a</code> between <code>"<"</code> and <code>">"</code></td></tr> |     <tr><td><code>mpc_braces(mpc_parser_t *a, mpc_dtor_t ad);</code></td><td>Matches <code>a</code> between <code>"<"</code> and <code>">"</code></td></tr> | ||||||
| @@ -597,7 +597,7 @@ Useful Parsers | |||||||
|     <tr><td><code>mpc_tok_parens(mpc_parser_t *a, mpc_dtor_t ad);</code></td><td>Matches <code>a</code> between trailing whitespace consumed <code>"("</code> and <code>")"</code></td></tr> |     <tr><td><code>mpc_tok_parens(mpc_parser_t *a, mpc_dtor_t ad);</code></td><td>Matches <code>a</code> between trailing whitespace consumed <code>"("</code> and <code>")"</code></td></tr> | ||||||
|     <tr><td><code>mpc_tok_braces(mpc_parser_t *a, mpc_dtor_t ad);</code></td><td>Matches <code>a</code> between trailing whitespace consumed <code>"<"</code> and <code>">"</code></td></tr> |     <tr><td><code>mpc_tok_braces(mpc_parser_t *a, mpc_dtor_t ad);</code></td><td>Matches <code>a</code> between trailing whitespace consumed <code>"<"</code> and <code>">"</code></td></tr> | ||||||
|     <tr><td><code>mpc_tok_brackets(mpc_parser_t *a, mpc_dtor_t ad);</code></td><td>Matches <code>a</code> between trailing whitespace consumed <code>"{"</code> and <code>"}"</code></td></tr> |     <tr><td><code>mpc_tok_brackets(mpc_parser_t *a, mpc_dtor_t ad);</code></td><td>Matches <code>a</code> between trailing whitespace consumed <code>"{"</code> and <code>"}"</code></td></tr> | ||||||
|     <tr><td><code>mpc_tok_squares(mpc_parser_t *a, mpc_dtor_t ad);</code></td><td>Matches <code>a</code> between trailing whitespace consumed <code>"["</code> and <code>"]"</code></td></tr> |     <tr><td><code>mpc_tok_squares(mpc_parser_t *a, mpc_dtor_t ad);</code></td><td>Matches <code>a</code> between trailing whitespace consumed <code>"["</code> and <code>"]"</code></td></tr> | ||||||
|  |  | ||||||
| </table> | </table> | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										28
									
								
								examples/foobar.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								examples/foobar.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | |||||||
|  | #include "../mpc.h" | ||||||
|  |  | ||||||
|  | int main(int argc, char** argv) { | ||||||
|  |  | ||||||
|  |     mpc_result_t r; | ||||||
|  |     mpc_parser_t* Foobar; | ||||||
|  |  | ||||||
|  |     if (argc != 2) { | ||||||
|  |       printf("Usage: ./foobar <foo/bar>\n"); | ||||||
|  |       exit(0); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     Foobar = mpc_new("foobar"); | ||||||
|  |     mpca_lang(MPCA_LANG_DEFAULT, "foobar : \"foo\" | \"bar\";", Foobar); | ||||||
|  |      | ||||||
|  |     if (mpc_parse("<stdin>", argv[1], Foobar, &r)) { | ||||||
|  |         mpc_ast_print(r.output); | ||||||
|  |         mpc_ast_delete(r.output); | ||||||
|  |     } else { | ||||||
|  |         mpc_err_print(r.error); | ||||||
|  |         mpc_err_delete(r.error); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     mpc_cleanup(1, Foobar); | ||||||
|  |      | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										61
									
								
								mpc.c
									
									
									
									
									
								
							
							
						
						
									
										61
									
								
								mpc.c
									
									
									
									
									
								
							| @@ -122,13 +122,14 @@ void mpc_err_string_cat(char *buffer, int *pos, int *max, char const *fmt, ...) | |||||||
|   va_end(va); |   va_end(va); | ||||||
| } | } | ||||||
|  |  | ||||||
| static char char_unescape_buffer[3]; | static char char_unescape_buffer[4]; | ||||||
|  |  | ||||||
| static const char *mpc_err_char_unescape(char c) { | static const char *mpc_err_char_unescape(char c) { | ||||||
|    |    | ||||||
|   char_unescape_buffer[0] = '\''; |   char_unescape_buffer[0] = '\''; | ||||||
|   char_unescape_buffer[1] = ' '; |   char_unescape_buffer[1] = ' '; | ||||||
|   char_unescape_buffer[2] = '\''; |   char_unescape_buffer[2] = '\''; | ||||||
|  |   char_unescape_buffer[3] = '\0'; | ||||||
|    |    | ||||||
|   switch (c) { |   switch (c) { | ||||||
|      |      | ||||||
| @@ -149,11 +150,11 @@ static const char *mpc_err_char_unescape(char c) { | |||||||
| } | } | ||||||
|  |  | ||||||
| char *mpc_err_string(mpc_err_t *x) { | char *mpc_err_string(mpc_err_t *x) { | ||||||
|    |  | ||||||
|   char *buffer = calloc(1, 1024); |   int i;   | ||||||
|   int max = 1023; |  | ||||||
|   int pos = 0;  |   int pos = 0;  | ||||||
|   int i; |   int max = 1023; | ||||||
|  |   char *buffer = calloc(1, 1024); | ||||||
|    |    | ||||||
|   if (x->failure) { |   if (x->failure) { | ||||||
|     mpc_err_string_cat(buffer, &pos, &max, |     mpc_err_string_cat(buffer, &pos, &max, | ||||||
| @@ -959,7 +960,7 @@ static mpc_err_t *mpc_stack_merger_err(mpc_stack_t *s, int n) { | |||||||
| #define MPC_CONTINUE(st, x) mpc_stack_set_state(stk, st); mpc_stack_pushp(stk, x); continue | #define MPC_CONTINUE(st, x) mpc_stack_set_state(stk, st); mpc_stack_pushp(stk, x); continue | ||||||
| #define MPC_SUCCESS(x) mpc_stack_popp(stk, &p, &st); mpc_stack_pushr(stk, mpc_result_out(x), 1); continue | #define MPC_SUCCESS(x) mpc_stack_popp(stk, &p, &st); mpc_stack_pushr(stk, mpc_result_out(x), 1); continue | ||||||
| #define MPC_FAILURE(x) mpc_stack_popp(stk, &p, &st); mpc_stack_pushr(stk, mpc_result_err(x), 0); continue | #define MPC_FAILURE(x) mpc_stack_popp(stk, &p, &st); mpc_stack_pushr(stk, mpc_result_err(x), 0); continue | ||||||
| #define MPC_PRIMATIVE(x, f) if (f) { MPC_SUCCESS(x); } else { MPC_FAILURE(mpc_err_fail(i->filename, i->state, "Incorrect Input")); } | #define MPC_PRIMITIVE(x, f) if (f) { MPC_SUCCESS(x); } else { MPC_FAILURE(mpc_err_fail(i->filename, i->state, "Incorrect Input")); } | ||||||
|  |  | ||||||
| int mpc_parse_input(mpc_input_t *i, mpc_parser_t *init, mpc_result_t *final) { | int mpc_parse_input(mpc_input_t *i, mpc_parser_t *init, mpc_result_t *final) { | ||||||
|    |    | ||||||
| @@ -983,13 +984,13 @@ int mpc_parse_input(mpc_input_t *i, mpc_parser_t *init, mpc_result_t *final) { | |||||||
|        |        | ||||||
|       /* Basic Parsers */ |       /* Basic Parsers */ | ||||||
|  |  | ||||||
|       case MPC_TYPE_ANY:       MPC_PRIMATIVE(s, mpc_input_any(i, &s)); |       case MPC_TYPE_ANY:       MPC_PRIMITIVE(s, mpc_input_any(i, &s)); | ||||||
|       case MPC_TYPE_SINGLE:    MPC_PRIMATIVE(s, mpc_input_char(i, p->data.single.x, &s)); |       case MPC_TYPE_SINGLE:    MPC_PRIMITIVE(s, mpc_input_char(i, p->data.single.x, &s)); | ||||||
|       case MPC_TYPE_RANGE:     MPC_PRIMATIVE(s, mpc_input_range(i, p->data.range.x, p->data.range.y, &s)); |       case MPC_TYPE_RANGE:     MPC_PRIMITIVE(s, mpc_input_range(i, p->data.range.x, p->data.range.y, &s)); | ||||||
|       case MPC_TYPE_ONEOF:     MPC_PRIMATIVE(s, mpc_input_oneof(i, p->data.string.x, &s)); |       case MPC_TYPE_ONEOF:     MPC_PRIMITIVE(s, mpc_input_oneof(i, p->data.string.x, &s)); | ||||||
|       case MPC_TYPE_NONEOF:    MPC_PRIMATIVE(s, mpc_input_noneof(i, p->data.string.x, &s)); |       case MPC_TYPE_NONEOF:    MPC_PRIMITIVE(s, mpc_input_noneof(i, p->data.string.x, &s)); | ||||||
|       case MPC_TYPE_SATISFY:   MPC_PRIMATIVE(s, mpc_input_satisfy(i, p->data.satisfy.f, &s)); |       case MPC_TYPE_SATISFY:   MPC_PRIMITIVE(s, mpc_input_satisfy(i, p->data.satisfy.f, &s)); | ||||||
|       case MPC_TYPE_STRING:    MPC_PRIMATIVE(s, mpc_input_string(i, p->data.string.x, &s)); |       case MPC_TYPE_STRING:    MPC_PRIMITIVE(s, mpc_input_string(i, p->data.string.x, &s)); | ||||||
|        |        | ||||||
|       /* Other parsers */ |       /* Other parsers */ | ||||||
|        |        | ||||||
| @@ -1147,7 +1148,7 @@ int mpc_parse_input(mpc_input_t *i, mpc_parser_t *init, mpc_result_t *final) { | |||||||
|        |        | ||||||
|       case MPC_TYPE_AND: |       case MPC_TYPE_AND: | ||||||
|          |          | ||||||
|         if (p->data.or.n == 0) { MPC_SUCCESS(p->data.and.f(0, NULL)); } |         if (p->data.and.n == 0) { MPC_SUCCESS(p->data.and.f(0, NULL)); } | ||||||
|          |          | ||||||
|         if (st == 0) { mpc_input_mark(i); MPC_CONTINUE(st+1, p->data.and.xs[st]); } |         if (st == 0) { mpc_input_mark(i); MPC_CONTINUE(st+1, p->data.and.xs[st]); } | ||||||
|         if (st <= p->data.and.n) { |         if (st <= p->data.and.n) { | ||||||
| @@ -1176,7 +1177,7 @@ int mpc_parse_input(mpc_input_t *i, mpc_parser_t *init, mpc_result_t *final) { | |||||||
| #undef MPC_CONTINUE | #undef MPC_CONTINUE | ||||||
| #undef MPC_SUCCESS | #undef MPC_SUCCESS | ||||||
| #undef MPC_FAILURE | #undef MPC_FAILURE | ||||||
| #undef MPC_PRIMATIVE | #undef MPC_PRIMITIVE | ||||||
|  |  | ||||||
| int mpc_parse(const char *filename, const char *string, mpc_parser_t *p, mpc_result_t *r) { | int mpc_parse(const char *filename, const char *string, mpc_parser_t *p, mpc_result_t *r) { | ||||||
|   int x; |   int x; | ||||||
| @@ -1945,12 +1946,12 @@ static const char *mpc_re_range_escape_char(char c) { | |||||||
| static mpc_val_t *mpcf_re_range(mpc_val_t *x) { | static mpc_val_t *mpcf_re_range(mpc_val_t *x) { | ||||||
|    |    | ||||||
|   mpc_parser_t *out; |   mpc_parser_t *out; | ||||||
|   char *range = calloc(1,1); |   size_t i, j; | ||||||
|  |   size_t start, end; | ||||||
|   const char *tmp = NULL; |   const char *tmp = NULL; | ||||||
|   const char *s = x; |   const char *s = x; | ||||||
|   int comp = s[0] == '^' ? 1 : 0; |   int comp = s[0] == '^' ? 1 : 0; | ||||||
|   size_t start, end; |   char *range = calloc(1,1); | ||||||
|   size_t i, j; |  | ||||||
|    |    | ||||||
|   if (s[0] == '\0') { free(x); return mpc_fail("Invalid Regex Range Expression"); }  |   if (s[0] == '\0') { free(x); return mpc_fail("Invalid Regex Range Expression"); }  | ||||||
|   if (s[0] == '^' &&  |   if (s[0] == '^' &&  | ||||||
| @@ -2144,9 +2145,9 @@ static mpc_val_t *mpcf_escape_new(mpc_val_t *x, const char *input, const char ** | |||||||
|    |    | ||||||
|   int i; |   int i; | ||||||
|   int found; |   int found; | ||||||
|  |   char buff[2]; | ||||||
|   char *s = x; |   char *s = x; | ||||||
|   char *y = calloc(1, 1); |   char *y = calloc(1, 1); | ||||||
|   char buff[2]; |  | ||||||
|    |    | ||||||
|   while (*s) { |   while (*s) { | ||||||
|      |      | ||||||
| @@ -2180,10 +2181,10 @@ static mpc_val_t *mpcf_unescape_new(mpc_val_t *x, const char *input, const char | |||||||
|    |    | ||||||
|   int i; |   int i; | ||||||
|   int found = 0; |   int found = 0; | ||||||
|  |   char buff[2]; | ||||||
|   char *s = x; |   char *s = x; | ||||||
|   char *y = calloc(1, 1); |   char *y = calloc(1, 1); | ||||||
|   char buff[2]; |    | ||||||
|  |  | ||||||
|   while (*s) { |   while (*s) { | ||||||
|      |      | ||||||
|     i = 0; |     i = 0; | ||||||
| @@ -2201,7 +2202,7 @@ static mpc_val_t *mpcf_unescape_new(mpc_val_t *x, const char *input, const char | |||||||
|       } |       } | ||||||
|       i++; |       i++; | ||||||
|     } |     } | ||||||
|        |      | ||||||
|     if (!found) { |     if (!found) { | ||||||
|       y = realloc(y, strlen(y) + 2); |       y = realloc(y, strlen(y) + 2); | ||||||
|       buff[0] = *s; buff[1] = '\0'; |       buff[0] = *s; buff[1] = '\0'; | ||||||
| @@ -2228,6 +2229,12 @@ mpc_val_t *mpcf_unescape(mpc_val_t *x) { | |||||||
|   return y; |   return y; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | 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;   | ||||||
|  | } | ||||||
|  |  | ||||||
| mpc_val_t *mpcf_unescape_regex(mpc_val_t *x) { | 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); |   mpc_val_t *y = mpcf_unescape_new(x, mpc_escape_input_raw_re, mpc_escape_output_raw_re); | ||||||
|   free(x); |   free(x); | ||||||
| @@ -2276,8 +2283,9 @@ 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); } | mpc_val_t *mpcf_trd_free(int n, mpc_val_t **xs) { return mpcf_nth_free(n, xs, 2); } | ||||||
|  |  | ||||||
| mpc_val_t *mpcf_strfold(int n, mpc_val_t **xs) { | mpc_val_t *mpcf_strfold(int n, mpc_val_t **xs) { | ||||||
|   char *x = calloc(1, 1); |  | ||||||
|   int i; |   int i; | ||||||
|  |   char *x = calloc(1, 1); | ||||||
|  |  | ||||||
|   for (i = 0; i < n; i++) { |   for (i = 0; i < n; i++) { | ||||||
|     x = realloc(x, strlen(x) + strlen(xs[i]) + 1); |     x = realloc(x, strlen(x) + strlen(xs[i]) + 1); | ||||||
|     strcat(x, xs[i]); |     strcat(x, xs[i]); | ||||||
| @@ -2499,6 +2507,7 @@ void mpc_ast_delete(mpc_ast_t *a) { | |||||||
|   int i; |   int i; | ||||||
|    |    | ||||||
|   if (a == NULL) { return; } |   if (a == NULL) { return; } | ||||||
|  |    | ||||||
|   for (i = 0; i < a->children_num; i++) { |   for (i = 0; i < a->children_num; i++) { | ||||||
|     mpc_ast_delete(a->children[i]); |     mpc_ast_delete(a->children[i]); | ||||||
|   } |   } | ||||||
| @@ -2612,6 +2621,12 @@ 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) { | static void mpc_ast_print_depth(mpc_ast_t *a, int d, FILE *fp) { | ||||||
|    |    | ||||||
|   int i; |   int i; | ||||||
|  |    | ||||||
|  |   if (a == NULL) { | ||||||
|  |     fprintf(fp, "NULL\n"); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |    | ||||||
|   for (i = 0; i < d; i++) { fprintf(fp, "  "); } |   for (i = 0; i < d; i++) { fprintf(fp, "  "); } | ||||||
|    |    | ||||||
|   if (strlen(a->contents)) { |   if (strlen(a->contents)) { | ||||||
|   | |||||||
							
								
								
									
										9
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | |||||||
|  | { | ||||||
|  |   "name": "mpc", | ||||||
|  |   "version": "0.8.5", | ||||||
|  |   "repo": "orangeduck/mpc", | ||||||
|  |   "description": "A Parser Combinator library for C", | ||||||
|  |   "keywords": ["parser", "combinator", "library", "c", "mpc"], | ||||||
|  |   "license": "BSD", | ||||||
|  |   "src": ["mpc.c", "mpc.h"] | ||||||
|  | } | ||||||
							
								
								
									
										186
									
								
								tests/ptest.c
									
									
									
									
									
								
							
							
						
						
									
										186
									
								
								tests/ptest.c
									
									
									
									
									
								
							| @@ -26,32 +26,47 @@ static int suite_passing = 0; | |||||||
| /* Colors */ | /* Colors */ | ||||||
|  |  | ||||||
| enum { | enum { | ||||||
|   BLACK   = 0x0, |   BLACK   = 0, | ||||||
|   BLUE    = 0x1, |   BLUE    = 1, | ||||||
|   GREEN   = 0x2, |   GREEN   = 2, | ||||||
|   AQUA    = 0x3, |   AQUA    = 3, | ||||||
|   RED     = 0x4, |   RED     = 4, | ||||||
|   PURPLE  = 0x5, |   PURPLE  = 5, | ||||||
|   YELLOW  = 0x6, |   YELLOW  = 6, | ||||||
|   WHITE   = 0x7, |   WHITE   = 7, | ||||||
|   GRAY    = 0x8, |   GRAY    = 8, | ||||||
|   LIGHT_BLUE    = 0x9, |    | ||||||
|   LIGHT_GREEN   = 0xA, |   LIGHT_BLUE   = 9, | ||||||
|   LIGHT_AQUA    = 0xB, |   LIGHT_GREEN  = 10, | ||||||
|   LIGHT_RED     = 0xC, |   LIGHT_AQUA   = 11, | ||||||
|   LIGHT_PURPLE  = 0xD, |   LIGHT_RED    = 12, | ||||||
|   LIGHT_YELLOW  = 0xE, |   LIGHT_PURPLE = 13, | ||||||
|   LIGHT_WHITE   = 0xF |   LIGHT_YELLOW = 14, | ||||||
|  |   LIGHT_WHITE  = 15, | ||||||
|  |    | ||||||
|  |   DEFAULT      = 16, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #ifdef _WIN32 | #ifdef _WIN32 | ||||||
|  |  | ||||||
|   #include <windows.h> | #include <windows.h> | ||||||
|  |  | ||||||
|   static void pt_color(int color) { | static WORD defaults; | ||||||
|     HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE); | static int defaults_loaded = 0; | ||||||
|     SetConsoleTextAttribute(hCon, color); |  | ||||||
|  | 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); | ||||||
|  | } | ||||||
|  |  | ||||||
| #else | #else | ||||||
|  |  | ||||||
| @@ -71,14 +86,13 @@ static const char* colors[] = { | |||||||
|   "\x1B[31m", |   "\x1B[31m", | ||||||
|   "\x1B[35m", |   "\x1B[35m", | ||||||
|   "\x1B[33m", |   "\x1B[33m", | ||||||
|   "\x1B[37m" |   "\x1B[37m", | ||||||
|  |   "\x1B[39m", | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   static void pt_color(int color) { | static void pt_color(int color) {   | ||||||
|      |   printf("%s", colors[color]); | ||||||
|     printf("%s", colors[color]); | } | ||||||
|    |  | ||||||
|   } |  | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| @@ -92,16 +106,18 @@ static char assert_err[MAX_ERROR]; | |||||||
| static char assert_err_buff[MAX_ERROR]; | static char assert_err_buff[MAX_ERROR]; | ||||||
| static int assert_err_num = 0; | static int assert_err_num = 0; | ||||||
|  |  | ||||||
| void pt_assert_run(int result, const char* expr, const char* func, const char* file, int line) { | void pt_assert_run( | ||||||
|  |   int result, const char* expr, const char* func, const char* file, int line) { | ||||||
|    |    | ||||||
|   (void) func; |  | ||||||
|   num_asserts++; |   num_asserts++; | ||||||
|   test_passing = test_passing && result; |   test_passing = test_passing && result; | ||||||
|    |    | ||||||
|   if (result) { |   if (result) { | ||||||
|     num_assert_passes++; |     num_assert_passes++; | ||||||
|   } else { |   } else { | ||||||
|     sprintf(assert_err_buff, "        %i. Assert [ %s ] (%s:%i)\n", assert_err_num+1, expr, file, line ); |     sprintf(assert_err_buff,  | ||||||
|  |       "        %i. Assert [ %s ] (%s:%i)\n",  | ||||||
|  |       assert_err_num+1, expr, file, line ); | ||||||
|     strcat(assert_err, assert_err_buff); |     strcat(assert_err, assert_err_buff); | ||||||
|     assert_err_num++; |     assert_err_num++; | ||||||
|     num_assert_fails++; |     num_assert_fails++; | ||||||
| @@ -110,22 +126,29 @@ void pt_assert_run(int result, const char* expr, const char* func, const char* f | |||||||
| } | } | ||||||
|  |  | ||||||
| static void ptest_signal(int sig) { | static void ptest_signal(int sig) { | ||||||
|    |  | ||||||
|   test_passing = 0; |   test_passing = 0; | ||||||
|    |    | ||||||
|   switch( sig ) { |   switch( sig ) { | ||||||
|     case SIGFPE:  sprintf(assert_err_buff, "        %i. Division by Zero\n", assert_err_num+1); break; |     case SIGFPE:  sprintf(assert_err_buff, | ||||||
|     case SIGILL:  sprintf(assert_err_buff, "        %i. Illegal Instruction\n", assert_err_num+1); break; |       "        %i. Division by Zero\n", assert_err_num+1); | ||||||
|     case SIGSEGV: sprintf(assert_err_buff, "        %i. Segmentation Fault\n", assert_err_num+1); break; |     break; | ||||||
|     default: break; |     case SIGILL:  sprintf(assert_err_buff, | ||||||
|  |       "        %i. Illegal Instruction\n", assert_err_num+1); | ||||||
|  |     break; | ||||||
|  |     case SIGSEGV: sprintf(assert_err_buff, | ||||||
|  |       "        %i. Segmentation Fault\n", assert_err_num+1); | ||||||
|  |     break; | ||||||
|   } |   } | ||||||
|    |    | ||||||
|   assert_err_num++; |   assert_err_num++; | ||||||
|   strcat(assert_err, assert_err_buff); |   strcat(assert_err, assert_err_buff); | ||||||
|    |    | ||||||
|   pt_color(WHITE); pt_color(RED); printf("Failed! \n\n%s\n", assert_err); pt_color(WHITE); |   pt_color(RED);  | ||||||
|  |   printf("Failed! \n\n%s\n", assert_err); | ||||||
|  |   pt_color(DEFAULT); | ||||||
|    |    | ||||||
|   printf("    | Stopping Execution.\n"); |   puts("    | Stopping Execution."); | ||||||
|   fflush(stdout); |   fflush(stdout); | ||||||
|   exit(0); |   exit(0); | ||||||
|    |    | ||||||
| @@ -134,14 +157,14 @@ static void ptest_signal(int sig) { | |||||||
| /* Tests */ | /* Tests */ | ||||||
|  |  | ||||||
| static void pt_title_case(char* output, const char* input) { | static void pt_title_case(char* output, const char* input) { | ||||||
|    |  | ||||||
|   int space = 1; |   int space = 1; | ||||||
|   size_t i; |   unsigned int i; | ||||||
|    |    | ||||||
|   strcpy(output, input); |   strcpy(output, input); | ||||||
|    |    | ||||||
|   for(i = 0; i < strlen(output); i++) { |   for(i = 0; i < strlen(output); i++) { | ||||||
|      |  | ||||||
|     if (output[i] == '_' || output[i] == ' ') { |     if (output[i] == '_' || output[i] == ' ') { | ||||||
|       space = 1; |       space = 1; | ||||||
|       output[i] = ' '; |       output[i] = ' '; | ||||||
| @@ -173,19 +196,22 @@ static int num_tests_passes = 0; | |||||||
| static int num_tests_fails  = 0; | static int num_tests_fails  = 0; | ||||||
|  |  | ||||||
| void pt_add_test(void (*func)(void), const char* name, const char* suite) { | void pt_add_test(void (*func)(void), const char* name, const char* suite) { | ||||||
|    |  | ||||||
|   test_t test; |   test_t test; | ||||||
|  |  | ||||||
|   if (num_tests == MAX_TESTS) { |   if (num_tests == MAX_TESTS) { | ||||||
|     printf("ERROR: Exceeded maximum test count of %i!\n", MAX_TESTS); abort(); |     printf("ERROR: Exceeded maximum test count of %i!\n",  | ||||||
|  |       MAX_TESTS); abort(); | ||||||
|   } |   } | ||||||
|    |    | ||||||
|   if (strlen(name) >= MAX_NAME) { |   if (strlen(name) >= MAX_NAME) { | ||||||
|     printf("ERROR: Test name '%s' too long (Maximum is %i characters)\n", name, MAX_NAME); abort(); |     printf("ERROR: Test name '%s' too long (Maximum is %i characters)\n",  | ||||||
|  |       name, MAX_NAME); abort(); | ||||||
|   } |   } | ||||||
|    |    | ||||||
|   if (strlen(suite) >= MAX_NAME) { |   if (strlen(suite) >= MAX_NAME) { | ||||||
|     printf("ERROR: Test suite '%s' too long (Maximum is %i characters)\n", suite, MAX_NAME); abort(); |     printf("ERROR: Test suite '%s' too long (Maximum is %i characters)\n",  | ||||||
|  |       suite, MAX_NAME); abort(); | ||||||
|   } |   } | ||||||
|    |    | ||||||
|   test.func = func; |   test.func = func; | ||||||
| @@ -194,7 +220,6 @@ void pt_add_test(void (*func)(void), const char* name, const char* suite) { | |||||||
|    |    | ||||||
|   tests[num_tests] = test; |   tests[num_tests] = test; | ||||||
|   num_tests++; |   num_tests++; | ||||||
|    |  | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Suites */ | /* Suites */ | ||||||
| @@ -215,17 +240,18 @@ static char current_suite[MAX_NAME]; | |||||||
|  |  | ||||||
| int pt_run(void) { | int pt_run(void) { | ||||||
|    |    | ||||||
|   int i; |   unsigned int i; | ||||||
|   double total; |   double total; | ||||||
|  |   test_t test; | ||||||
|  |  | ||||||
|   printf("    \n"); |   puts(""); | ||||||
|   printf("    +-------------------------------------------+\n"); |   puts("    +-------------------------------------------+"); | ||||||
|   printf("    | ptest          MicroTesting Magic for C   |\n"); |   puts("    | ptest          MicroTesting Magic for C   |"); | ||||||
|   printf("    |                                           |\n"); |   puts("    |                                           |"); | ||||||
|   printf("    | http://github.com/orangeduck/ptest        |\n"); |   puts("    | http://github.com/orangeduck/ptest        |"); | ||||||
|   printf("    |                                           |\n"); |   puts("    |                                           |"); | ||||||
|   printf("    | Daniel Holden (contact@theorangeduck.com) |\n"); |   puts("    | Daniel Holden (contact@theorangeduck.com) |"); | ||||||
|   printf("    +-------------------------------------------+\n"); |   puts("    +-------------------------------------------+"); | ||||||
|    |    | ||||||
|   signal(SIGFPE,  ptest_signal); |   signal(SIGFPE,  ptest_signal); | ||||||
|   signal(SIGILL,  ptest_signal); |   signal(SIGILL,  ptest_signal); | ||||||
| @@ -235,12 +261,12 @@ int pt_run(void) { | |||||||
|   strcpy(current_suite, ""); |   strcpy(current_suite, ""); | ||||||
|    |    | ||||||
|   for(i = 0; i < num_tests; i++) { |   for(i = 0; i < num_tests; i++) { | ||||||
|      |  | ||||||
|     test_t test = tests[i]; |     test = tests[i]; | ||||||
|      |      | ||||||
|     /* Check for transition to a new suite */ |     /* Check for transition to a new suite */ | ||||||
|     if (strcmp(test.suite, current_suite)) { |     if (strcmp(test.suite, current_suite)) { | ||||||
|        |  | ||||||
|       /* Don't increment any counter for first entrance */ |       /* Don't increment any counter for first entrance */ | ||||||
|       if (strcmp(current_suite, "")) { |       if (strcmp(current_suite, "")) { | ||||||
|         if (suite_passing) { |         if (suite_passing) { | ||||||
| @@ -262,6 +288,7 @@ int pt_run(void) { | |||||||
|     strcpy(assert_err_buff, ""); |     strcpy(assert_err_buff, ""); | ||||||
|     assert_err_num = 0; |     assert_err_num = 0; | ||||||
|     printf("    | %s ... ", test.name); |     printf("    | %s ... ", test.name); | ||||||
|  |     fflush(stdout); | ||||||
|      |      | ||||||
|     test.func(); |     test.func(); | ||||||
|      |      | ||||||
| @@ -269,10 +296,14 @@ int pt_run(void) { | |||||||
|      |      | ||||||
|     if (test_passing) { |     if (test_passing) { | ||||||
|       num_tests_passes++; |       num_tests_passes++; | ||||||
|       pt_color(GREEN);  printf("Passed! \n"); pt_color(WHITE); |       pt_color(GREEN); | ||||||
|  |       puts("Passed!"); | ||||||
|  |       pt_color(DEFAULT); | ||||||
|     } else { |     } else { | ||||||
|       num_tests_fails++; |       num_tests_fails++; | ||||||
|       pt_color(RED);    printf("Failed! \n\n%s\n", assert_err); pt_color(WHITE); |       pt_color(RED);  | ||||||
|  |       printf("Failed! \n\n%s\n", assert_err); | ||||||
|  |       pt_color(DEFAULT); | ||||||
|     } |     } | ||||||
|      |      | ||||||
|   } |   } | ||||||
| @@ -285,28 +316,37 @@ int pt_run(void) { | |||||||
|    |    | ||||||
|   end = clock(); |   end = clock(); | ||||||
|    |    | ||||||
|   printf("  \n"); |   puts(""); | ||||||
|   printf("  +---------------------------------------------------+\n"); |   puts("  +---------------------------------------------------+"); | ||||||
|   printf("  |                      Summary                      |\n"); |   puts("  |                      Summary                      |"); | ||||||
|   printf("  +---------++------------+-------------+-------------+\n"); |   puts("  +---------++------------+-------------+-------------+"); | ||||||
|    |    | ||||||
|   printf("  | Suites  ||"); |   printf("  | Suites  ||"); | ||||||
|   pt_color(YELLOW); printf(" Total %4d ",  num_suites);        pt_color(WHITE); printf("|"); |   pt_color(YELLOW);  printf(" Total %4d ",  num_suites);         | ||||||
|   pt_color(GREEN);  printf(" Passed %4d ", num_suites_passes); pt_color(WHITE); printf("|"); |   pt_color(DEFAULT); putchar('|'); | ||||||
|   pt_color(RED);    printf(" Failed %4d ", num_suites_fails);  pt_color(WHITE); printf("|\n"); |   pt_color(GREEN);   printf(" Passed %4d ", num_suites_passes);  | ||||||
|  |   pt_color(DEFAULT); putchar('|'); | ||||||
|  |   pt_color(RED);     printf(" Failed %4d ", num_suites_fails);   | ||||||
|  |   pt_color(DEFAULT); puts("|"); | ||||||
|    |    | ||||||
|   printf("  | Tests   ||"); |   printf("  | Tests   ||"); | ||||||
|   pt_color(YELLOW); printf(" Total %4d ",  num_tests);         pt_color(WHITE); printf("|"); |   pt_color(YELLOW);  printf(" Total %4d ",  num_tests);          | ||||||
|   pt_color(GREEN);  printf(" Passed %4d ", num_tests_passes);  pt_color(WHITE); printf("|"); |   pt_color(DEFAULT); putchar('|'); | ||||||
|   pt_color(RED);    printf(" Failed %4d ", num_tests_fails);   pt_color(WHITE); printf("|\n"); |   pt_color(GREEN);   printf(" Passed %4d ", num_tests_passes);   | ||||||
|  |   pt_color(DEFAULT); putchar('|'); | ||||||
|  |   pt_color(RED);     printf(" Failed %4d ", num_tests_fails);    | ||||||
|  |   pt_color(DEFAULT); puts("|"); | ||||||
|    |    | ||||||
|   printf("  | Asserts ||"); |   printf("  | Asserts ||"); | ||||||
|   pt_color(YELLOW); printf(" Total %4d ",  num_asserts);       pt_color(WHITE); printf("|"); |   pt_color(YELLOW);  printf(" Total %4d ",  num_asserts);        | ||||||
|   pt_color(GREEN);  printf(" Passed %4d ", num_assert_passes); pt_color(WHITE); printf("|"); |   pt_color(DEFAULT); putchar('|'); | ||||||
|   pt_color(RED);    printf(" Failed %4d ", num_assert_fails);  pt_color(WHITE); printf("|\n"); |   pt_color(GREEN);   printf(" Passed %4d ", num_assert_passes);  | ||||||
|  |   pt_color(DEFAULT); putchar('|'); | ||||||
|  |   pt_color(RED);     printf(" Failed %4d ", num_assert_fails);   | ||||||
|  |   pt_color(DEFAULT); puts("|"); | ||||||
|    |    | ||||||
|   printf("  +---------++------------+-------------+-------------+\n"); |   puts("  +---------++------------+-------------+-------------+"); | ||||||
|   printf("  \n"); |   puts(""); | ||||||
|    |    | ||||||
|   total = (double)(end - start) / CLOCKS_PER_SEC; |   total = (double)(end - start) / CLOCKS_PER_SEC; | ||||||
|    |    | ||||||
|   | |||||||
| @@ -18,5 +18,4 @@ void pt_add_test(void (*func)(void), const char* name, const char* suite); | |||||||
| void pt_add_suite(void (*func)(void)); | void pt_add_suite(void (*func)(void)); | ||||||
| int pt_run(void); | int pt_run(void); | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
		Reference in New Issue
	
	Block a user
	 Daniel Holden
					Daniel Holden