From 009ed5598365bf7fed5042496c070a40c7c9246d Mon Sep 17 00:00:00 2001 From: ken Date: Sat, 7 Jan 2017 19:34:48 -0800 Subject: [PATCH] fixes --- src/apc.c | 41 +++----- src/name.c | 41 -------- src/parser.y | 40 +++++--- src/scanner.c | 275 ++++++++++++++------------------------------------ 4 files changed, 118 insertions(+), 279 deletions(-) delete mode 100644 src/name.c diff --git a/src/apc.c b/src/apc.c index 9f267ac..0e7c124 100644 --- a/src/apc.c +++ b/src/apc.c @@ -23,31 +23,20 @@ #define DEFAULT_PAGESIZE 4096 const char* cargs['Z'] = {0}; -const long sys_pagesize; -yypstate* apc_pstate; -yycstate* apc_cstate; +long sys_pagesize; int main(int, char*[]); - -extern //bison -int yyparse(void); -extern //lexer.c -int lexer_init(void); -extern -int scanner_init(void); -extern -int scanner(yypstate*, yycstate*); -extern //ir.c -int ir_init(void); - -extern //apc/parser.tab.c -YYSTYPE yylval; -extern -yycstate* yycstate_new(void); - extern //lexer.c -int lexer(void); +int lexer_init(void); +extern //scanner.c +int scanner_init(void); +extern //scanner.c +void scanner_quit(void); +extern //scanner.c +int scanner_scanpath(char const*); +//extern //ir.c +//int ir_init(void); /* Main entry from terminal parses the command line and kicks off recursive scanning @@ -67,6 +56,7 @@ int main "\t\t-o\tOutput filename \t\t[a.asspak]\n" \ "\t\t-h\tPrint this help\n" #define DONE -1 +#define SCANPATH (cargs['d'] ? cargs['d'] : "./") { int opt; getopt: @@ -91,15 +81,12 @@ int main if ((sys_pagesize = sysconf(_SC_PAGESIZE)) == 0) sys_pagesize = DEFAULT_PAGESIZE; - apc_pstate = yypstate_new(); - apc_cstate = yycstate_new(); - - if (scanner_init() || ir_init()) + if (scanner_init())// || ir_init()) { perror("init"); exit(EXIT_FAILURE); } - scanner(); - + scanner_scanpath(SCANPATH); + scanner_quit(); exit(EXIT_SUCCESS); } diff --git a/src/name.c b/src/name.c deleted file mode 100644 index 9fd82de..0000000 --- a/src/name.c +++ /dev/null @@ -1,41 +0,0 @@ -/* Functions for operating on names */ -#include "apc.h" -#include - - -int -name_u8_cpy(struct name*, struct name*); - -int -name_u8_cmp(struct name*, struct name*); - - -/* Copies src into dst. 1 if sucessful, 0 if not */ -int -name_u8_cpy -( struct name* dst, - struct name* src -) -{ if(u8_stpncpy(dst->name, src->name, MAX_NAME_LEN)) - return 1; - - return 0; - -} - - -int -name_u8_cmp -( struct name* x, - struct name* y -) -{ return u8_strncmp(x->name, y->name, MAX_NAME_LEN); -} - -int -name_u8_set -( struct name* name, - ucs4_t uc -) -{ return u8_set(name->name, uc, MAX_NAME_LEN); -} diff --git a/src/parser.y b/src/parser.y index 9fe82df..41c4095 100644 --- a/src/parser.y +++ b/src/parser.y @@ -24,10 +24,10 @@ extern long sys_pagesize; extern int lexer(); - static void yyerror(char const*); + static void yyerror(yycstate*, char const*); + static inline ir_class yyclass_push(yycstate*, ir_class); + static inline ir_class yyclass_pop(yycstate*); /* Stack-based class handler */ - #define CLASS_POP(CS) (*--(CS-csp)) - #define CLASS_PUSH(CS,CL) (*(CS->csp)++ = CL) #define yyclass(CS) (*(CS->csp)) #define yyclassld(CS) (ir_classld_from_class(yyclass(CS))) } @@ -79,9 +79,9 @@ class_list: ; class: - NAME CLOPEN { CLASS_PUSH(cs,ir_class_addchild(yyclass, $1)); } + NAME CLOPEN { yyclass_push(cs,ir_class_addchild(yyclass(cs), $1)); } progn - CLCLOSE { CLASS_POP(cs); } + CLCLOSE { yyclass_pop(cs); } ; statement_list: @@ -109,13 +109,13 @@ data_spec: ; set_spec: - set_spec NAME { $$ = ir_set_addchild($1,$2); } -| NAME { $$ = ir_class_addset(yyclass,$1); } + set_spec NAME { $$ = ir_set_addchild($1,$2); } +| NAME { $$ = ir_class_addset(yyclass(cs),$1); } ; set_link: set_link NAME { $$ = ir_setld_addchild($1,$2); } -| NAME { $$ = ir_setld_from_classld(yyclassld,$1) } +| NAME { $$ = ir_setld_from_classld(yyclassld(cs),$1); } ; set_ld: @@ -133,7 +133,9 @@ frame_spec: static void yyerror -( char const *s ) +( yycstate* cs, + char const *s +) { fprintf(stderr, "%s\n", s); } yycstate* yycstate_new @@ -141,14 +143,28 @@ yycstate* yycstate_new { yycstate* class_state; class_state = (yycstate*) malloc((size_t) sys_pagesize); if(class_state == NULL) - { yyerror(ERR_MEM); - exit(1); + { yyerror(class_state, "Memory allocation error."); + return NULL; } class_state->csp = &class_state->class_stack[0]; - CLASS_PUSH(class_state, ir_class_root()); + yyclass_push(class_state, ir_class_root()); return class_state; } +static inline +ir_class yyclass_pop +( yycstate* cs ) +{ return *(cs->csp)--; } + +static inline +ir_class yyclass_push +( yycstate* cs, + ir_class class +) +{ *++cs->csp = class; + return class; +} + void yycstate_delete ( yycstate* class_state ) { free(class_state); } diff --git a/src/scanner.c b/src/scanner.c index 14266ca..6dcbc9d 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -13,9 +13,7 @@ ----------------------------------------------------------------------------*/ /* Standard */ #include //print -#include //strncmp #include //errno -#include //tolower /* Posix */ #include //warnx #include //exit @@ -27,222 +25,101 @@ /* Public */ int scanner_init(void); void scanner_quit(void); -int scanner(void); -int scanner_scanpixels(int*,int); +int scanner_scanpath(char const*); +int scanner_scandir(DIR*); +yypstate* apc_pstate; +yycstate* apc_cstate; /* Private */ extern //lexer.c -int lexer_lexstring(const char*); -extern //lexer.c -void lexer_pushtok(int, int); -static -int dredge_current_depth(void); -/* Mem */ -extern //lexer.c -struct dirent* lexer_direntpa[], **lexer_direntpp; -extern //SRC_DIR/bin/tools/apc.c -const char* cargs['Z']; -#define DL_STACKSIZE 64 -#define DL_CD_STACKSIZE DL_STACKSIZE //square tree +int lexer_lexfile(uint8_t const*); +extern //lexer.rl +int lexer_lexstring(uint8_t const*, int); +#define PUSHTOK(T,L) yypush_parse(apc_pstate, T, L, apc_cstate) -static -struct dirlist -{ DIR* dirp; - struct dirent* child_directory_stack[DL_CD_STACKSIZE],** cds; -} directory_list_stack[DL_STACKSIZE + 1],* dls; //+1 for the root dir -static -FILE* current_open_file = NULL; - -/* Directory Listing Stack - FILO Stack for keeping an open DIR* at each directory depth for treewalk. - This stack is depth-safe, checking its depth during push operations, but not - during pop operations, to ensure the thread doesn't open too many files at - once (512 in c runtime), or traverse too far through symbolic links. - A directory listing includes a DIR* and all DIR-typed entity in the directory - as recognized by dirent, populated externally (and optionally). - This stack behaves abnormally by incrementing its PUSH operation prior to - evaluation, and the POP operations after evaluation. This behavior allows - the 'DL_CURDEPTH' operation to map to the current element in the 'dl_stack' - array, and it is always treated as the "current depth". This also allows us - to init the root directory to 'directory_list_stack'[0] and pop it in a safe - and explicit manner. -*/ -#define DL_STACK (directory_list_stack) -#define DL_STACKP (dls) -#define DL_CD_STACK ((*DL_STACKP).child_directory_stack) -#define DL_CD_STACKP ((*DL_STACKP).cds) -#define DL_CURDIR() ((*DL_STACKP).dirp) -#define DL_LEN() ((int)(DL_STACKP - DL_STACK)) -#define DL_CD_LEN() ((int)(DL_CD_STACKP - DL_CD_STACK)) -#define DL_INIT() (DL_STACKP = DL_STACK) -#define DL_CD_INIT() (DL_CD_STACKP = DL_CD_STACK) -#define DL_POP() ((*DL_STACKP--).dirp) -#define DL_CD() (*DL_CD_STACKP) -#define DL_CD_CURNAME() (DL_CD()->d_name) -#define DL_CD_POP() (*--DL_CD_STACKP) -#define DL_PUSH(D) ((*++DL_STACKP).dirp = D) -#define DL_CD_PUSH(E) (*DL_CD_STACKP++ = E) - - -/* Initializer - Initializer expects a function pointer to its lexical analysis function. - Sets up stack pointers and returns boolean true if 'opendir' encounters an - error, or if dredge_current_depth returns boolean true. +/* Init + Establishes yy states */ int scanner_init -#define CWDSTR "./" -#define ROOTDIR (cargs['d'] ? cargs['d'] : CWDSTR) -() -{ DL_INIT(); - DL_STACK[0].dirp = opendir(ROOTDIR); - if (current_open_file != NULL) - { fclose(current_open_file); - current_open_file = NULL; - } - printf("Root dir %s\n",ROOTDIR); - return !chdir(ROOTDIR) && (DL_STACK[0].dirp == NULL || dredge_current_depth() == -1); +( void ) +{ if (apc_pstate != NULL || apc_cstate != NULL) + scanner_quit(); + apc_pstate = yypstate_new(); + apc_cstate = yycstate_new(); + return (apc_pstate != NULL && apc_cstate != NULL); } -/* Quit */ -void scanner_quit -() -{ if (DL_CURDIR()) - closedir(DL_CURDIR()); -} - -/* Scanner - The main driver of the scanner will advance the current treewalk state and - tokenize tree-based push/pop operations. It will call 'lexer_lex' to - tokenize directory names prior to making a push operation. safe checking for - all returns from the filesystem handler will exit on serious system errors. - - after pushing a new directory to the directory list, the scanner will dredge - the directory and alphabetically sort all file entries into the lexer's file - array, while placing all subdirectory entries in the current depth's child - directory stack to be scanned later. - - Returns the number of tokens generated on success, -1 on error. +/* Quit + Free initialized memory */ -int scanner -#define $($)#$ //stringifier -#define ERR_CHILD "Fatal: Maximum of " $(DL_CD_STACKSIZE) " child " \ - "directories exceeded for directory at depth %i\n",DL_LEN() -#define ERR_DEPTH "Fatal: Maximum directory depth of " $(DL_STACKSIZE) \ - " exceeded during directory scan\n" -#define ERR_DL "Fatal: Directory List Stack Corruption %i\n", DL_LEN() -() -{ int ntok = 0; - scan: - if (DL_CD_LEN() >= DL_CD_STACKSIZE)//fail if maxchildren exceeded - { fprintf(stderr, ERR_CHILD); - goto fail; - } - if (DL_CD_LEN() > 0) //There are entities to process - { if (DL_CD_POP() == NULL) //If the dirent is null, then the - goto libfail; //lib function in dirent has failed - ntok += lexer_lexstring(DL_CD_CURNAME());//lex the directory name - if (DL_LEN() >= DL_STACKSIZE) //fail if maxdepth exceeded - { fprintf(stderr, ERR_DEPTH); - goto fail; - } - if (chdir(DL_CD_CURNAME())) //move into the new directory - goto libfail; - if (DL_CURDIR() == NULL) //open the cwd - goto libfail; - lexer_pushtok(CLOPEN, 0); //Push "Open Directory" token - ntok++; - return dredge_current_depth(); //Filter and sort the current depth - } - else if (DL_LEN() >= 0) //Any dirs left? (Including root) - { if (closedir(DL_POP())) //close the directory we just left - goto libfail; - if (DL_LEN() == -1) //If we just popped root, - goto done; //we're done - lexer_pushtok(CLCLOSE, 0); //Else push "Close Directory" token, - ntok++; - if (!chdir("..")) //move up a directory and - goto scan; //start over - } - fprintf(stderr, ERR_DL); - libfail: - perror("scanner: "); - fail: - return -1; - done: - return ntok; +void scanner_quit +( void ) +{ yypstate_delete(apc_pstate); + yycstate_delete(apc_cstate); + apc_pstate = NULL; + apc_cstate = NULL; } -/* Scan Pixels - Scans up to 'len' pixels from the current file into 'buf'. - Returns the number of pixels scanned from the file, or -1 on error +/* Scan the provided path + Changes working directory to the provided pathname and, if successful, sends + a directory stream of the provided path to scanner_scandir */ -int scanner_scanpixels -( int* buf, - int max_len -) -{ static int /*col_len,*/ row_len = 0, row; - //Open the current file if not yet open - if (current_open_file == NULL) - { if ((current_open_file = fopen(DL_CD_CURNAME(),"rb")) == NULL) - { perror("fopen: "); - return -1; - } - //Verify file header, get row_len/col_len - //if (read_img_header(&row_len, &col_len)) - //return -1; - row = 0; - } - //Read pixels into the buffer if there are rows left in the image - if (row++ < row_len) - //TODO: return read_img_pixels(buf, col_len); - printf("SCANPIXELS NOT IMPLEMENTED\n."); - //Close the file and return 0 - fclose(current_open_file); - current_open_file = NULL; - return 0; +int scanner_scanpath +( char const* pathname ) +{ DIR* dirp; + errno = 0; + if ((dirp = opendir(pathname)) == NULL || errno) + return -1; + if (chdir(pathname)) + return -1; + return scanner_scandir(dirp); } -/* Directory Entity Sort and Filter (Dredge) - This filter removes all unhandled file types, and places any 'DT_DIR' type - files in the current Directory List's directory stack. Upon finishing, - the 'CE_STACK' is sorted alphabetically, and the current 'DL_CD_STACK' is - populated. Prints warnings for unhandled files. - - Returns -1 if 'readdir' encounters an error, otherwise returns the number of - directory entries sent to the external 'lexer_direntpa' array. +/* Scan directory stream + Recursively scans the provided directory, sending CLOPEN and CLCLOSE tokens + to the parser when entering new directories (classes) */ -typedef //so we can typecast dirent's 'alphasort()' to take const void*s -int (*qcomp)(const void*, const void*); -static inline -int dredge_current_depth -#define READDIR_ERROR (-1) -#define READDIR_DONE (0) -#define DPS_LEN() (lexer_direntpp - lexer_direntpa) -#define DPS_PUSH(E) (*lexer_direntpp++ = E) -() -{ DIR* cwd = DL_CURDIR(); +int scanner_scandir +( DIR* dirp ) +{ DIR* cdirp; struct dirent* direntp; - DL_CD_INIT(); - scan_next: + scan_next_dirent: errno = 0; - direntp = readdir(cwd); + direntp = readdir(dirp); if (errno) - return -1; + goto libfail; if (direntp != NULL) - { switch (direntp->d_type) - { case DT_REG: - DPS_PUSH(direntp); - goto scan_next; - case DT_DIR: - if (*(direntp->d_name) == '.') //skip hidden files and relative dirs - goto scan_next; - DL_CD_PUSH(direntp); - goto scan_next; + { if (*(direntp->d_name) == '.') //skip hidden or relative files + goto scan_next_dirent; + switch (direntp->d_type) + { case DT_REG: + printf("lexfile %s\n",direntp->d_name); + //lexer_lexfile((uint8_t*)direntp->d_name); + goto scan_next_dirent; + case DT_DIR: + //lexer_lexstring((uint8_t*)direntp->d_name); //lex the dirname + printf("lexdir %s\n",direntp->d_name); + if (chdir(direntp->d_name)) //change to the specified dir + goto libfail; + errno = 0; + if ((cdirp = opendir(".")) == NULL || errno) //open it + goto libfail; + //PUSHTOK(CLOPEN, 0); //push "Open Directory" token + printf("Scanner entered [%s]\n",direntp->d_name); + if(scanner_scandir(cdirp)) //scan the directory + goto libfail; + if (chdir("..")) //return to the parent dir + goto libfail; + //PUSHTOK(CLCLOSE, 0); //push "Close Directory" token + printf("Scanner returned\n"); + goto scan_next_dirent; //continue scan case DT_UNKNOWN: - warnx("unknown file %s: ignoring", direntp->d_name); + warnx("unknown file %s: ignoring", direntp->d_name); default: - goto scan_next; - } + goto scan_next_dirent; + } } - qsort(lexer_direntpa, DPS_LEN(), sizeof direntp, (qcomp)alphasort); - return DPS_LEN(); + return closedir(dirp); + libfail: + perror("scanner_scandir"); + return -1; } -- 2.18.0