X-Git-Url: https://www.kengrimes.com/gitweb/?p=henge%2Fwebcc.git;a=blobdiff_plain;f=src%2Fapc%2Flexer.c;h=940ee8163968151c90e9ec508e81ba722265ad3b;hp=4d3ab0a32ee4dee025e5851c4f859ecd387de456;hb=957d4c384203bdc325c81a594943a5790dcb32aa;hpb=dc6e33a26d6488e388817d4dd255dcdff22b4a2a diff --git a/src/apc/lexer.c b/src/apc/lexer.c index 4d3ab0a..940ee81 100644 --- a/src/apc/lexer.c +++ b/src/apc/lexer.c @@ -18,6 +18,7 @@ /* Posix */ #include #include +#include //realpath, NAME_MAX, PATH_MAX #include /* Local */ #include "parser.tab.h" @@ -28,46 +29,43 @@ #define TK_STACKSIZE 1024 #endif /* Public */ -int lexer_init(void); -int lexer(void); -void lexer_pushtok(int, YYSTYPE); -extern //ragel -int lexer_lex(const char*); -struct dirent* lexer_direntpa[DE_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); +int scanner_init(void); extern //scanner.c -int scanner(void); +int scanner(void); static inline -int dredge_current_depth(void); +int dredge_current_depth(void); extern //bison -YYSTYPE yylval; +YYSTYPE yylval; static -struct tok -{ union YYSTYPE val; //token val - int tt; //token type -} token_stack[TK_STACKSIZE]; -static -union tokp -{ int* tpt; //token pointer type - struct tok* tok; - union YYSTYPE* tvp; //token value pointer -} tks, tkx; +char const* current_filename; static -struct dirent** dps; +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. + lexer as a stack, and is popped as a FIFO stack. */ #define DE_STACK (lexer_direntpa) -#define DE_STACKP (dps) -#define DE_LEN() (DE_STACKP - DE_STACK) -#define DE_INIT() (DE_STACKP = DE_STACK) -#define DE_POP() (*--DE_STACKP) +#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 @@ -78,48 +76,64 @@ struct dirent** dps; times in a sequence! */ #define TK_STACK (token_stack) -#define TK_STACKP (tks.tok) -#define TK_STACKPI (tks.tpt) -#define TK_STACKPL (tks.tvp) -#define TK_STACKX (tkx.tok) -#define TK_STACKXI (tkx.tpt) -#define TK_LEN() (TK_STACKP - TK_STACKX) +#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_POPI() (*TK_STACKPI++); -#define TK_POPL() (*TK_STACKPL++); #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(); 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) - { TK_INIT(); - if (scanner() == 0) - { yylval.val = 0; - return 0; +{ 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_POPL(); - return TK_POPI(); + token = TK_POP(); + yylval = token.lval; + return token.tok_t; + done: + yylval.val = 0; + return 0; } @@ -127,8 +141,8 @@ int lexer This receiver takes a struct tok and pushes it to the FIFO stack. */ void lexer_pushtok -#define S(S)#S //stringifier -#define ERR_TK "Fatal: Generated over " S(TK_STACKSIZE) " tokens in one pass." +#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); @@ -136,18 +150,43 @@ void lexer_pushtok } TK_PUSH(tok, lval); } -/* 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; + +/* 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; + + 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; +}