X-Git-Url: https://www.kengrimes.com/gitweb/?p=henge%2Fwebcc.git;a=blobdiff_plain;f=src%2Fapc%2Flexer.c;h=940ee8163968151c90e9ec508e81ba722265ad3b;hp=4e0a611faa06bf16bd4501dd0bed73fa850f34ce;hb=957d4c384203bdc325c81a594943a5790dcb32aa;hpb=882513ad6569a640cb5c90b83e27e742ace71b63 diff --git a/src/apc/lexer.c b/src/apc/lexer.c index 4e0a611..940ee81 100644 --- a/src/apc/lexer.c +++ b/src/apc/lexer.c @@ -18,49 +18,54 @@ /* Posix */ #include #include +#include //realpath, NAME_MAX, PATH_MAX #include /* Local */ -//#include "parser.tab.h" -#ifndef DP_STACKSIZE -#define DP_STACKSIZE 1024 +#include "parser.tab.h" +#ifndef DE_STACKSIZE +#define DE_STACKSIZE 1024 #endif #ifndef TK_STACKSIZE #define TK_STACKSIZE 1024 #endif /* Public */ -struct tok -{ int lval; - int tok; -}; -int lexer_init(void); -int lexer(void); -inline -void lexer_pushtok(int int); -struct dirent* lexer_direntpa[DP_STACKSIZE]; +int lexer_init(void); +int lexer(void); +int lexer_lexfile(const char*); +void lexer_pushtok(int, YYSTYPE); +char const* lexer_get_current_filepath(void); +struct dirent* lexer_direntpa[DE_STACKSIZE],** lexer_direntpp,** lexer_direntpb; /* Private */ +extern //lexer_lex.rl +int lexer_lex(const char*); +extern //scanner.c +int scanner_init(void); +extern //scanner.c +int scanner(void); static inline -int scan(void); -static inline -int dredge_current_depth(void); -static -struct dirent** dps; +int dredge_current_depth(void); +extern //bison +YYSTYPE yylval; static -struct tok token_stack[TK_STACKSIZE]; +char const* current_filename; static -union tokp -{ int* i; - struct tok* t; -} tks, tkx; +struct tok +{ YYSTYPE lval; //token val + int tok_t; //token type +} token_stack[TK_STACKSIZE], *tsp, *tsx; /* Directory Entity Array/Stack Simple array for keeping track of dirents yet to be processed by the scanner. If this list is empty and there are no tokens, the lexer is done. + This array is populated by the scanner as an array, and popped locally by the + lexer as a stack, and is popped as a FIFO stack. */ -#define DP_STACK (lexer_direntpa) -#define DP_STACKP (dps) -#define DP_LEN() (DP_STACKP - DP_STACK) -#define DP_INIT() (DP_STACKP = DP_STACK) -#define DP_POP() (*--DP_STACKP) +#define DE_STACK (lexer_direntpa) +#define DE_STACKP (lexer_direntpp) +#define DE_STACKB (lexer_direntpb) +#define DE_LEN() (DE_STACKP - DE_STACKB) +#define DE_INIT() (DE_STACKP = DE_STACKB = DE_STACK) +#define DE_POP() (*DE_STACKB++) /* Token Stack This is a FIFO stack whose pointers are a union of either a pointer to an @@ -70,100 +75,118 @@ union tokp An alignment error will occur if IPOP or IPUSH are used a non-even number of times in a sequence! */ -#define TK_STACK (token_stack) -#define TK_STACKP (tks.t) -#define TK_STACKPI (tks.i) -#define TK_STACKX (tkx.t) -#define TK_STACKXI (tkx.i) -#define TK_LEN() (TK_STACKP - TK_STACKX) -#define TK_INIT() (TK_STACKP = TK_STACKX = TK_STACK) -#define TK_POP() (*TK_STACKP++) -#define TK_POPI() (*TK_STACKPI++); -#define TK_PUSH(T) (*TKSTACKX++ = T) -#define TK_PUSHI(I) (*TKSTACKXI++ = (I)) - -extern //main.c -const char* cargs['Z']; - -extern //scanner.c -int scanner_init(void); -extern //scanner.c -int scanner(struct dirent**); +#define TK_STACK (token_stack) +#define TK_STACKP (tsp) +#define TK_STACKX (tsx) +#define TK_LEN() (TK_STACKX - TK_STACKP) +#define TK_INIT() (TK_STACKP = TK_STACKX = TK_STACK) +#define TK_POP() (*TK_STACKP++) +#define TK_PUSH(T,L) (*TK_STACKX++ = (struct tok){L,T}) /* Initializer - The initializer returns boolean true if an error occurs, which may be handled with standard errno. + The initializer returns boolean true if an error occurs, which may be handled + with standard errno. */ int lexer_init () { TK_INIT(); - DP_INIT(); + DE_INIT(); + current_filename = NULL; return scanner_init(); } /* Lexer If the token buffer is empty, 'lexer' will initialize the token buffer and - call 'lexer_scandir'. If #SCANDIR_ERROR is returned, an error is printed + call 'lexer_scandir'. If SCAN_ERROR is returned, an error is printed before sending a null return to bison. If 0 tokens are generated, the error printing is skipped. In all other cases, 'yylval' is set, and the token's integer representation is returned. */ int lexer +#define $($)#$ #define SCAN_ERROR -1 #define TK_EMPTY (TK_STACKP == TK_STACKX) +#define FAIL(...) \ + do { \ + fprintf(stderr,__VA_ARGS__); \ + goto done; \ + } while (0) () -{ if (TK_EMPTY) - { switch (parsedir()) - { case SCAN_ERROR: - perror("lexer_scan"); - case 0: - yylval = 0; - return 0; - default: - break; +{ struct tok token; + start: + while (DE_LEN() > 0) //lex any directory entries in our stack + if (lexer_lexfile(DE_POP()->d_name) == 0) + FAIL("Lexer failed to tokenize [%s]\n",(*DE_STACKB)->d_name); + if (TK_EMPTY) //if there are no tokens, + { TK_INIT(); //initialize the token stack back to 0 + switch (scanner()) + { case SCAN_ERROR: //if an error occurred, + FAIL("Scanner error\n"); + case 0: //if the the scanner finds no dirents, + goto done; //then we are done + default: //if we found some elements to scan, + goto start; //start over and lex them } } - yylval = TK_IPOP(); - return TK_IPOP(); + token = TK_POP(); + yylval = token.lval; + return token.tok_t; + done: + yylval.val = 0; + return 0; } + /* Token Receiver This receiver takes a struct tok and pushes it to the FIFO stack. */ -inline void lexer_pushtok -#define ERR_TK "Fatal: Generated over " S(TK_STACKSIZE) " tokens in one pass." -( struct tok token ) -{ if (TK_LEN >= TK_STACKSIZE) +#define $($)#$ //stringifier +#define ERR_TK "Fatal: Generated over " $(TK_STACKSIZE) " tokens in one pass." +( int tok, YYSTYPE lval ) +{ if (TK_LEN() >= TK_STACKSIZE) { fprintf(stderr, ERR_TK); exit(EXIT_FAILURE); } - TK_PUSH(token); + TK_PUSH(tok, lval); } -/* Lexical Analysis - Ragel state machine for tokenizing text. - */ -void lexer_lex -(const char* str) -{ struct tok token; - token.TOK = 1; - token.LVAL = 2; - lexer_pushtok(token); - printf (str); -} +/* Lexical analysis of a file + Strips a filename to its base name, then sends it to lexer_lex +*/ +int lexer_lexfile +#define HIDDEN_WARNING "%s is hidden and will not be parsed!\n", filename +( const char *filename +) +{ static char fname[NAME_MAX]; + char *last_period = NULL, *iter; -/* init_file: - if (lsp != NULL) - while ((c = *lsp++) == *csp) - { switch (c) - { case DELIM: - delimeters_skipped++; - default: - csp++; //delayed to ensure csp is the start of scannable text - break; + if (*filename == '.') + { fprintf (stderr, HIDDEN_WARNING); + return 0; } + /* Copy the filename and remove its suffix */ + strncpy(fname,filename,NAME_MAX); + last_period = NULL; + for (iter = fname; *iter; iter++) //find the last '.' char + if (*iter == '.') + last_period = iter; + if (last_period) //if we found one, + *last_period = '\0'; //truncate the string there + /* Register the current_filename */ + current_filename = filename; + + return lexer_lex(fname); +} + +char const* lexer_get_current_filepath +() +{ static char current_path[PATH_MAX]; + static char const* last_filename; + if ((!last_filename || last_filename != current_filename) && + (realpath(current_filename, current_path) != current_path)) + { perror("realpath: "); + return NULL; } - last_string = string; - scan_text: - return scanner_tokenize(csp); -*/ + return (const char*)current_path; +}