From: ken Date: Fri, 16 Dec 2016 07:40:56 +0000 (-0800) Subject: Makefile v0.4 driver support added X-Git-Url: https://www.kengrimes.com/gitweb/?p=henge%2Fapc.git;a=commitdiff_plain;h=44adcae5601d919ab63f8241ebac4ddfc0bc69f5 Makefile v0.4 driver support added --- diff --git a/Makefile b/Makefile index d37a162..7968b66 100644 --- a/Makefile +++ b/Makefile @@ -21,10 +21,12 @@ CFLAGS ?= -Wall CCMD = $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< # Linker -LD ?= ld -LDFLAGS ?= -LDLIBS ?= -lunistring -LDCMD = $(LD) $(LDFLAGS) $(LDLIBS) -o $@ $^ +LD ?= ld +LDFLAGS ?= +LDLIBS ?= -lunistring +apcLIBS ?= +apc-dLIBS ?= +LDCMD = $(LD) $(LDFLAGS) $(LDLIBS) $($1LIBS) -o $@ $^ # APC is built from Ragel, Bison and C source code only. ySRC := $(shell find ./src -type f -name '*.y') @@ -35,17 +37,19 @@ cSRC := $(shell find ./src -type f -name '*.c') hGEN := $(ySRC:%.y=%.tab.h) cGEN := $(strip $(ySRC:%.y=%.tab.c) $(rlSRC:%.rl=%.c)) -# Functions -cGENDEP = $(if $(wildcard $1),$(subst src/,,$(filter-out $1 \ %:,$(shell $(CC) -MM -MG $1))),$(info <$1>)) -ldFLAGS = $(strip $(LDFLAGS) $(LDLIBS) $(VA_ARGS)) +# Deps generation function +cGENDEP = $(if $(wildcard $1),$(subst $(dir $1),,$(filter-out $1 \ %:,$(shell $(CC) -MM -MG $1))),$(info <$1>)) -# Rules -apcSRC := $(patsubst %.c,%.o,$(cSRC) $(cGEN)) -apc-dSRC := $(patsubst %.o,%-d.o,$(apcSRC)) +# Driver sources +DRIVERS := apc testapc +$(foreach drv,$(DRIVERS),\ +$(eval $(drv)SRC := $(patsubst %.c,%.o,$(filter-out $(patsubst %,src/%.c,$(filter-out $(drv),$(DRIVERS))),$(cSRC) $(cGEN))))\ +$(eval $(drv)-dSRC := $(patsubst %.o,%-d.o,$($(drv)SRC)))) +# Rules .SECONDEXPANSION: -apc-d apc: $$($$@SRC) | $(hGEN) - $(strip $(LDCMD)) +$(DRIVERS:%=%-d) $(DRIVERS): $$($$@SRC) | $(hGEN) + $(strip $(call LDCMD,$@)) %-d.o: CFLAGS+= -Og -ggdb %.o %-d.o: %.c $$(call cGENDEP,$$(dir $$@)%.c) @@ -59,4 +63,4 @@ apc-d apc: $$($$@SRC) | $(hGEN) $(strip $(RLCMD)) clean: $(wildcard $(cGEN) $(hGEN) $(apcSRC) $(apc-dSRC)) - rm $^ + $(if $^,rm $^) diff --git a/src/apc.c b/src/apc.c new file mode 100644 index 0000000..2307ccc --- /dev/null +++ b/src/apc.c @@ -0,0 +1,84 @@ +/*!@file + \brief APC main driver + \details The driver assumes the existence of a bison-generated parser, + referenced by the external function 'yyparse'. + It also assumes the existence of a lexer which must be initialized + before parsing, referenced by the external function 'lexer_init' + which assumes standard error handling. + All input arguments are made available through the exposed (that is, + non-static) array of character pointers 'cargs', which point + to the non-duplicated strings in 'argv' directly from the system. + \author Jordan Lavatai + \date Aug 2016 + ----------------------------------------------------------------------------*/ +/* Standard */ +#include //print +#include //errors +#include //strndupa +/* Posix */ +#include //exit +#include //getopt +/* Internal */ +#include //bison + +const char* cargs['Z'] = {0}; + +int main(int, char*[]); + +extern //bison +int yyparse(void); +extern //lexer.c +int lexer_init(void); + +extern //apc/parser.tab.c +YYSTYPE yylval; +extern //lexer.c +int lexer(void); + +/* Main entry from terminal + parses the command line and kicks off recursive scanning +*/ +int main +( int argc, + char* argv[] +) +#define $($)#$ //stringifier +#define MAXSTR 255 +#define MAXERR "-%c allows at most " $(MAXSTR) " input characters\n", opt +#define OPTS "d:o:h-" +#define USAGE "Usage %s [-d dir_root][-o output_file][-h]\n", argv[0] +#define USAGE_LONG \ + "\tOptions:\n" \ + "\t\t-d\tRoot directory to parse from \t[./]\n" \ + "\t\t-o\tOutput filename \t\t[a.asspak]\n" \ + "\t\t-h\tPrint this help\n" +#define DONE -1 +{ int opt; + + getopt: + switch (opt = getopt(argc, argv, OPTS)) + { case DONE: + break; + case 'd' : + case 'o' : + if (strnlen(optarg, MAXSTR) != MAXSTR) + { cargs[opt] = optarg; + goto getopt; + } + fprintf(stderr, MAXERR); + default : + fprintf(stderr, USAGE); + exit(EXIT_FAILURE); + case 'h' : + printf(USAGE); + printf(USAGE_LONG); + exit(EXIT_SUCCESS); + } + if (lexer_init()) + { perror("lexer"); + exit(EXIT_FAILURE); + } + yyparse(); + exit(EXIT_SUCCESS); +} + diff --git a/src/testapc.c b/src/testapc.c new file mode 100644 index 0000000..77b825e --- /dev/null +++ b/src/testapc.c @@ -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 //print +#include //errors +#include //strnlen +#include //non-local jumps +/* Posix */ +#include //exit +#include //getopt +/* Internal */ +#include //bison +#include //ir + +/* Import apc.c but redefine its primary symbols for jumping */ +#define main apc_main +#define yyparse testapc_yyparse +#include +#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; +}