-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.
-*/
-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);
-}
-
-/* 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.
-*/
-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;
-}
-
-/* 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