Lexer actually lexes filenames now, and odats are made out of mapvariants
[henge/webcc.git] / src / bin / tools / testapc.c
index ea9cbe3..77b825e 100644 (file)
@@ -9,6 +9,7 @@
 #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
 
 int main(int, char*[]);
 int testapc_yyparse(void);
+int test_yyparse(void);
 
 extern //bison
-int yyparse(void);
+int  yyparse(void);
 extern //lexer.c
 int  lexer_init(void);
+extern //scanner.c
+int  scanner_init(void);
 extern //apc.c
 const char* cargs['Z'];
 
@@ -38,6 +42,9 @@ YYSTYPE yylval;
 extern //lexer.c
 int  lexer(void);
 
+static
+jmp_buf testapc_jump;
+
 /* Ansi Term Colors */
 #define RED     "\x1b[31m"
 #define GREEN   "\x1b[32m"
@@ -54,38 +61,86 @@ int main
 ( int   argc,
   char* argv[]
 )
-{ apc_main(argc, argv);
-  printf(GREEN "PASS\n");
+{ 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 */
+/* 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;
-  char* tok_pattern = "T[%i]L[%i]";
-  char* lval_type   = tok_pattern + 8; //location of i
-  tok_lval[NUM]  = 'i';
-  tok_lval[STR]  = 's';
-  tok_lval[SS]   = 'i';
-  tok_lval[NAME] = 's';
-  tok_lval[REF]  = 'x';
-  tok_lval[SSD]  = 'i';
-  tok_lval[FPTR] = 'x';
-  //lex 10 tokens
-  printf(YELLOW);
-  for (i = 0; i < 10; i++)
-    { if ((tok = lexer()) != 0)
-       { *lval_type = tok_lval[tok] ? tok_lval[tok] : 'i';
+  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
-       { printf(";");
-         break;
+       { tok_pattern[TOFFS] = 's';
+         printf(tok_pattern, tok_string, yylval.val);
        }
+      if (i % 4 == 0 || yylval.val == 0)
+       printf(";\n");
     }
-  printf("\n" CLRC);
+ done:
+  printf(";\n" GREEN "Done" CLRC ".\n");
+  return 0;
+ error:
+  printf(";\n" RED "FAILED" CLRC ".\n");
+  return -1;
 }