moved
[henge/webcc.git] / .org / data / 2d / ec5876-7b81-4b9c-97fe-03b152fa276a / scanner.c
diff --git a/.org/data/2d/ec5876-7b81-4b9c-97fe-03b152fa276a/scanner.c b/.org/data/2d/ec5876-7b81-4b9c-97fe-03b152fa276a/scanner.c
deleted file mode 100755 (executable)
index f982cf2..0000000
+++ /dev/null
@@ -1,210 +0,0 @@
-/*!@file\r
-  \brief   APC Directory Scanner\r
-  \details This hand-written parser/scanner traverses a directory tree and\r
-           tokenizes elements of the structure which correspond to APC grammar.\r
-           The parser is implemented as a 2D stack which populates a list of\r
-           child directories at each depth, handling only the leaf nodes\r
-           (regular files) of the directory open at the current depth to\r
-           conserve memory and speed up traversal.\r
-           The scanner works with the lexer to lexically analyze text, and\r
-           assumes the existence of an external 'lex' function\r
-  \author  Jordan Lavatai\r
-  \date    Aug 2016\r
-  ----------------------------------------------------------------------------*/\r
-/* Standard */\r
-#include <stdio.h>  //print\r
-#include <errno.h>  //errno\r
-/* Posix */\r
-#include <err.h>    //warnx\r
-#include <stdlib.h> //exit\r
-#include <unistd.h> //chdir\r
-#include <dirent.h> //opendir\r
-\r
-#include "parser.tab.h"\r
-/* Public */\r
-int  scanner_init(void);\r
-void scanner_quit(void);\r
-int  scanner(void);\r
-/* Private */\r
-#ifndef DL_STACKSIZE\r
-#define DL_STACKSIZE     64\r
-#endif\r
-#ifndef DL_CD_STACKSIZE\r
-#define DL_CD_STACKSIZE  DL_STACKSIZE //square tree\r
-#endif\r
-extern //lexer.c\r
-int  lexer_lex(const char*);\r
-extern //lexer.c\r
-void lexer_pushtok(int, int);\r
-static\r
-int  dredge_current_depth(void);\r
-extern //lexer.c\r
-struct dirent* lexer_direntpa[], **lexer_direntpp;\r
-extern //SRC_DIR/bin/tools/apc.c\r
-const char* cargs['Z'];\r
-\r
-struct dirlist\r
-{ DIR*           dirp;\r
-  struct dirent* child_directory_stack[DL_CD_STACKSIZE],** cds;\r
-} directory_list_stack[DL_STACKSIZE + 1],* dls; //+1 for the root dir\r
-\r
-/* Directory Listing Stack\r
-   FILO Stack for keeping an open DIR* at each directory depth for treewalk.\r
-   This stack is depth-safe, checking its depth during push operations, but not\r
-   during pop operations, to ensure the thread doesn't open too many files at\r
-   once (512 in c runtime), or traverse too far through symbolic links.\r
-   A directory listing includes a DIR* and all DIR-typed entity in the directory\r
-   as recognized by dirent, populated externally (and optionally).\r
-   This stack behaves abnormally by incrementing its PUSH operation prior to\r
-   evaluation, and the POP operations after evaluation.  This behavior allows\r
-   the 'DL_CURDEPTH' operation to map to the current element in the 'dl_stack'\r
-   array, and it is always treated as the "current depth". This also allows us\r
-   to init the root directory to 'directory_list_stack'[0] and pop it in a safe\r
-   and explicit manner.\r
-*/\r
-#define DL_STACK        (directory_list_stack)\r
-#define DL_STACKP       (dls)\r
-#define DL_CD_STACK     ((*DL_STACKP).child_directory_stack)\r
-#define DL_CD_STACKP    ((*DL_STACKP).cds)\r
-#define DL_CURDIR()     ((*DL_STACKP).dirp)\r
-#define DL_LEN()        (DL_STACKP - DL_STACK)\r
-#define DL_CD_LEN()     (DL_CD_STACKP - DL_CD_STACK)\r
-#define DL_INIT()       (DL_STACKP = DL_STACK)\r
-#define DL_CD_INIT()    (DL_CD_STACKP = DL_CD_STACK)\r
-#define DL_POP()        ((*DL_STACKP--).dirp)\r
-#define DL_CD_POP()     (*--DL_CD_STACKP)\r
-#define DL_PUSH(D)      ((*++DL_STACKP).dirp = D)\r
-#define DL_CD_PUSH(E)   (*DL_CD_STACKP++ = E)\r
-\r
-\r
-/* Initializer\r
-   Initializer expects a function pointer to its lexical analysis function.\r
-   Sets up stack pointers and returns boolean true if 'opendir' encounters an\r
-   error, or if dredge_current_depth returns boolean true.\r
-*/\r
-int scanner_init\r
-#define CWDSTR  "./"\r
-#define ROOTDIR (cargs['d'] ? cargs['d'] : CWDSTR)\r
-()\r
-{ DL_INIT();\r
-  DL_STACK[0].dirp = opendir(ROOTDIR);\r
-  printf("Root dir %s\n",ROOTDIR);\r
-  return !chdir(ROOTDIR) && (DL_STACK[0].dirp == NULL || dredge_current_depth() == -1);\r
-}\r
-\r
-/* Quit */\r
-void scanner_quit\r
-()\r
-{ if (DL_CURDIR())\r
-    closedir(DL_CURDIR());\r
-}\r
-\r
-/* Scanner\r
-   The main driver of the scanner will advance the current treewalk state and\r
-   tokenize tree-based push/pop operations.  It will call 'lexer_lex' to\r
-   tokenize directory names prior to making a push operation. safe checking for\r
-   all returns from the filesystem handler will exit on serious system errors.\r
-\r
-   after pushing a new directory to the directory list, the scanner will dredge\r
-   the directory and alphabetically sort all file entries into the lexer's file\r
-   array, while placing all subdirectory entries in the current depth's child\r
-   directory stack to be scanned later.\r
-\r
-   Returns the number of elements added to the lexer's file array, or -1 on\r
-   error\r
-*/\r
-int scanner\r
-#define $($)#$ //stringifier\r
-#define ERR_CHILD  "Fatal: Maximum of " $(DL_CD_STACKSIZE)      \\r
-  " child directories exceeded for directory at depth %i\n"     \\r
-  ,DL_LEN()\r
-#define ERR_DEPTH  "Fatal: Maximum directory depth of " $(DL_STACKSIZE) \\r
-  " exceeded during directory scan\n"\r
-#define ERR_DL     "Fatal: Directory List Stack Corruption %x\n", DL_LEN()\r
-#define TOK_CLOPEN  0x55, 1 //TODO\r
-#define TOK_CLCLOSE 0x56, 1 //TODO\r
-()\r
-{ struct dirent* direntp;\r
-  struct DIR* DIRp;\r
- parse:\r
-  if (DL_CD_LEN() >= DL_CD_STACKSIZE)//fail if maxchildren exceeded\r
-    { fprintf(stderr, ERR_CHILD);\r
-      goto fail;\r
-    }\r
-  if (DL_CD_LEN() > 0)               //There are entities to process\r
-    { if ((direntp = DL_CD_POP()) == NULL)//If the dirent is null, the library\r
-        goto libfail;                     //function in dirent has failed\r
-      lexer_lex(direntp->d_name);         //lex the directory name\r
-      if (DL_LEN() >= DL_STACKSIZE)       //fail if maxdepth exceeded\r
-        { fprintf(stderr, ERR_DEPTH);\r
-          goto fail;\r
-        }\r
-      if (chdir(direntp->d_name))         //move into the new directory\r
-       goto libfail;\r
-      DL_PUSH(opendir(CWDSTR));\r
-      if (DL_CURDIR() == NULL)            //open the cwd\r
-       goto libfail;\r
-      lexer_pushtok(TOK_CLOPEN);          //Push "Open Directory" token\r
-      return dredge_current_depth();      //Filter and sort the current depth\r
-    }\r
-  else if (DL_LEN() >= 0)            //Any dirs left? (Including root)\r
-    { if (closedir(DL_POP()))             //close the directory we just left\r
-        goto libfail;\r
-      if (DL_LEN() == -1)                 //If we just popped root,\r
-        return 0;                         //we're done\r
-      lexer_pushtok(TOK_CLCLOSE);         //Else push "Close Directory" token,\r
-      if (!chdir(".."))                   //move up a directory and\r
-        goto parse;                       //start over\r
-    }\r
-  fprintf(stderr, ERR_DL);\r
- libfail:\r
-  perror("parsedir");\r
- fail:\r
-  exit(EXIT_FAILURE);\r
-}\r
-\r
-/* Directory Entity Sort and Filter (Dredge)\r
-   This filter removes all unhandled file types, and places any 'DT_DIR' type\r
-   files in the current Directory List's directory stack.  Upon finishing,\r
-   the 'CE_STACK' is sorted alphabetically, and the current 'DL_CD_STACK' is\r
-   populated.  Prints warnings for unhandled files.\r
-\r
-   Returns -1 if 'readdir' encounters an error, otherwise returns the number of\r
-   directory entries sent to the external 'lexer_direntpa' array.\r
-*/\r
-typedef\r
-int (*qcomp)(const void*, const void*);\r
-static inline\r
-int dredge_current_depth\r
-#define READDIR_ERROR (-1)\r
-#define READDIR_DONE  (0)\r
-#define DPS_LEN()     (lexer_direntpp - lexer_direntpa)\r
-#define DPS_PUSH(E)   (*lexer_direntpp++ = E)\r
-()\r
-{ struct dirent**  direntpp = lexer_direntpa;\r
-  DIR*             cwd      = DL_CURDIR();\r
-  struct dirent*   direntp;\r
-  DL_CD_INIT();\r
- scan_next:\r
-  if ((direntp = readdir(cwd)) != NULL)\r
-    { switch (direntp->d_type)\r
-        { case DT_REG:\r
-            DPS_PUSH(direntp);\r
-            goto scan_next;\r
-          case DT_DIR:\r
-           if (*(direntp->d_name) == '.') //skip hidden files and relative dirs\r
-              goto scan_next;\r
-           DL_CD_PUSH(direntp);\r
-            goto scan_next;\r
-          case DT_UNKNOWN:\r
-            warnx("unknown file %s: ignoring", direntp->d_name);\r
-          default:\r
-            goto scan_next;\r
-        }\r
-    }\r
-  if (errno)\r
-    return -1;\r
-  qsort(lexer_direntpa, DPS_LEN(), sizeof direntp, (qcomp)alphasort);\r
-  return DPS_LEN();\r
-}\r
-\r