added everything to src
[henge/apc.git] / scanner.c
diff --git a/scanner.c b/scanner.c
deleted file mode 100644 (file)
index 55245af..0000000
--- a/scanner.c
+++ /dev/null
@@ -1,255 +0,0 @@
-/*!@file
-  \brief   APC Directory Scanner
-  \details This hand-written parser/scanner traverses a directory tree and
-           tokenizes elements of the structure which correspond to APC grammar.
-           The parser is implemented as a 2D stack which populates a list of
-           child directories at each depth, handling only the leaf nodes
-           (regular files) of the directory open at the current depth to
-           conserve memory and speed up traversal.
-           The scanner works with the lexer to lexically analyze text, and
-           assumes the existence of an external 'lex' function
-  \author  Jordan Lavatai
-  \date    Aug 2016
-  ----------------------------------------------------------------------------*/
-/* Standard */
-#include <stdio.h>  //print
-#include <string.h> //strncmp
-#include <errno.h>  //errno
-#include <ctype.h>  //tolower
-/* Posix */
-#include <err.h>    //warnx
-#include <stdlib.h> //exit
-#include <unistd.h> //chdir
-#include <dirent.h> //opendir
-#include <unistr.h> //unicode strings
-/* Internal */
-#include "parser.tab.h"
-/* Public */
-int   scanner_init(void);
-void  scanner_quit(void);
-int   scanner(void);
-int   scanner_scanpixels(int*,int);
-/* Private */
-extern //lexer.c
-int   lexer_lexstring(const uint8_t*);
-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'];
-#ifndef DL_STACKSIZE
-#define DL_STACKSIZE     64
-#endif
-#ifndef DL_CD_STACKSIZE
-#define DL_CD_STACKSIZE  DL_STACKSIZE //square tree
-#endif
-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()        (DL_STACKP - DL_STACK)
-#define DL_CD_LEN()     (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 %x\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
-<<<<<<< HEAD
-      ntok += lexer_lexstring(DL_CD_CURNAME());//lex the directory name
-=======
-      ntok += lexer_lexstring(DL_CD_CURNAME());  //lex the directory name
->>>>>>> 15d3ab5e7871ff459af13089b82bf5f17f731ebd
-      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
-*/
-int scanner_scanpixels
-( int*  buf,
-  int   max_len
-)
-{ static int col_len, row_len, 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;
-}
-
-/* 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.
-*/
-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)
-()
-{ struct dirent**  direntpp = lexer_direntpa;
-  DIR*             cwd      = DL_CURDIR();
-  struct dirent*   direntp;
-  DL_CD_INIT();
- scan_next:
-  if ((direntp = readdir(cwd)) != 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;
-          case DT_UNKNOWN:
-            warnx("unknown file %s: ignoring", direntp->d_name);
-          default:
-            goto scan_next;
-        }
-    }
-  if (errno)
-    return -1;
-  qsort(lexer_direntpa, DPS_LEN(), sizeof direntp, (qcomp)alphasort);
-  return DPS_LEN();
-}