Makefile v0.4 driver support added
[henge/apc.git] / src / testapc.c
diff --git a/src/testapc.c b/src/testapc.c
new file mode 100644 (file)
index 0000000..77b825e
--- /dev/null
@@ -0,0 +1,146 @@
+/*!@file
+  \brief   APC test driver
+  \details This driver does what APC does, but in staggered stages with
+           additional debugging information
+  \author  Jordan Lavatai
+  \date    Aug 2016
+  ----------------------------------------------------------------------------*/
+/* Standard */
+#include <stdio.h>  //print
+#include <errno.h>  //errors
+#include <string.h> //strnlen
+#include <setjmp.h> //non-local jumps
+/* Posix */
+#include <stdlib.h> //exit
+#include <unistd.h> //getopt
+/* Internal */
+#include <apc/parser.tab.h> //bison
+#include <apc/ir.h>         //ir
+
+/* Import apc.c but redefine its primary symbols for jumping */
+#define main apc_main
+#define yyparse testapc_yyparse
+#include <bin/tools/apc.c>
+#undef yyparse
+#undef main
+
+int main(int, char*[]);
+int testapc_yyparse(void);
+int test_yyparse(void);
+
+extern //bison
+int  yyparse(void);
+extern //lexer.c
+int  lexer_init(void);
+extern //scanner.c
+int  scanner_init(void);
+extern //apc.c
+const char* cargs['Z'];
+
+extern //apc/parser.tab.c
+YYSTYPE yylval;
+extern //lexer.c
+int  lexer(void);
+
+static
+jmp_buf testapc_jump;
+
+/* Ansi Term Colors */
+#define RED     "\x1b[31m"
+#define GREEN   "\x1b[32m"
+#define YELLOW  "\x1b[33m"
+#define BLUE    "\x1b[34m"
+#define MAGENTA "\x1b[35m"
+#define CYAN    "\x1b[36m"
+#define CLRC    "\x1b[0m" //clear current color
+
+/* Main entry from terminal
+   parses debugging options for testing apc, and calls apc_main
+*/
+int main
+( int   argc,
+  char* argv[]
+)
+{ setjmp(testapc_jump);
+  apc_main(argc, argv);
+  printf(GREEN "PASS" CLRC "\n");
+  exit(EXIT_SUCCESS);
+}
+
+#define MAX_TOK 1024
+char tok_lval[MAX_TOK];
+
+/* yyparse intercept 
+   tests yyparse internally, then resets the scanner and runs bison's 'yyparse'
+   implementation after validating it with 'test_yyparse'.
+*/
+int testapc_yyparse
+#ifndef YYABORT
+#define YYABORT 1
+#endif
+()
+{ static char bPassedTest = 'f';
+  if (bPassedTest == 'f')
+    { if (test_yyparse())
+       { printf("Parse test aborted\n");
+         return YYABORT;
+       }
+      bPassedTest = 't';
+      longjmp(testapc_jump,0);
+    }
+  return yyparse();
+}
+
+/* test_yyparse
+   runs 'lexer' 'PASSES' times, or until finished
+*/
+int test_yyparse
+#define PASSES 1000
+()
+{ int i, tok;
+  static char* tok_string;
+  static char  tok_pattern[] = "[" RED " %9s " CLRC "][" CYAN " %-12i " CLRC "]";
+  for (i = 0; i < PASSES; i++)
+    { switch (tok = lexer())
+      #define TOFFS 9
+      #define LOFFS 27
+      #define $($)#$
+      #define TOK_CASE(T,C)                    \
+       case T:                                 \
+         tok_string = $(T);                    \
+         tok_pattern[LOFFS] = C;               \
+         break
+       { TOK_CASE(STR,'s');
+         TOK_CASE(NAME,'s');
+         TOK_CASE(REF,'x');
+         TOK_CASE(FPTR,'x');
+         TOK_CASE(NUM,'i');
+         TOK_CASE(SS,'i');
+         TOK_CASE(SSD,'i');
+         TOK_CASE(CLOPEN,'i');
+         TOK_CASE(CLCLOSE,'i');
+         default:
+           tok_string = 0;
+           tok_pattern[LOFFS] = 'i';
+           break;
+          case 0:
+           goto done;
+       }
+      if (tok_string == NULL)
+       { tok_pattern[TOFFS] = 'i';
+         printf(tok_pattern, tok, yylval.val);
+       }
+      else
+       { tok_pattern[TOFFS] = 's';
+         printf(tok_pattern, tok_string, yylval.val);
+       }
+      if (i % 4 == 0 || yylval.val == 0)
+       printf(";\n");
+    }
+ done:
+  printf(";\n" GREEN "Done" CLRC ".\n");
+  return 0;
+ error:
+  printf(";\n" RED "FAILED" CLRC ".\n");
+  return -1;
+}