merged
[henge/webcc.git] / src / apc / scanner.c
index b20a92f..55245af 100644 (file)
   ----------------------------------------------------------------------------*/
 /* 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);
-int scanner(void);
+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
-extern //lexer.c
-int  lexer_lex(const char*);
-extern //lexer.c
-void lexer_pushtok(int, int);
 static
-int  dredge_current_depth(void);
-extern //lexer.c
-struct dirent* lexer_direntpa[];
-extern //SRC_DIR/bin/tools/apc.c
-const char* cargs['Z'];
-
 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.
@@ -71,6 +79,8 @@ struct dirlist
 #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)
@@ -83,11 +93,23 @@ struct dirlist
 */
 int scanner_init
 #define CWDSTR  "./"
-#define ROOTDIR (cargs['r'] ? cargs['r'] : CWDSTR)
+#define ROOTDIR (cargs['d'] ? cargs['d'] : CWDSTR)
 ()
 { DL_INIT();
   DL_STACK[0].dirp = opendir(ROOTDIR);
-  return DL_STACK[0].dirp == NULL || dredge_current_depth() == 0;
+  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
@@ -99,60 +121,92 @@ int scanner_init
    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 the scanned later.
+   directory stack to be scanned later.
 
-   Returns the number of elements added to the lexer's file array.
+   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"     \
+#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) \
+#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()
-#define TOK_CLOPEN  0x55, 0 //TODO
-#define TOK_CLCLOSE 0x56, 0 //TODO
 ()
-{ struct dirent* direntp;
-  struct DIR* DIRp;
- parse:
+{ 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 at this depth
-    { if ((direntp = DL_CD_POP()) == NULL)  //If the dirent is null, the library
-        goto libfail;                 //function in dirent has failed
-      lexer_lex(direntp->d_name);     //lex the directory name
-      if (DL_LEN() >= DL_STACKSIZE)   //fail if maxdepth exceeded
+  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(direntp->d_name))     //move into the new directory
-        goto libfail;
-      DL_PUSH(opendir(CWDSTR));
-      if (DL_CURDIR() == NULL)   //open the cwd
-       { printf("DL_PUSH(opendir failed.\n");
-         goto libfail;
-       }
-      lexer_pushtok(TOK_CLOPEN);      //Push "Open Directory" token
-      return dredge_current_depth();  //Filter and sort the current depth
+      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
+  else if (DL_LEN() >= 0)            //Any dirs left? (Including root)
+    { if (closedir(DL_POP()))             //close the directory we just left
         goto libfail;
-      lexer_pushtok(TOK_CLCLOSE);     //Push "Close Directory" token
-      if (DL_LEN() == -1)             //If we just popped root, we're done
-        return 0;
-      if (!chdir(".."))               //Move up a directory and start over
-        goto parse;
+      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("parsedir");
+  perror("scanner: ");
  fail:
-  exit(EXIT_FAILURE);
+  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)
@@ -164,14 +218,14 @@ int scanner
    Returns -1 if 'readdir' encounters an error, otherwise returns the number of
    directory entries sent to the external 'lexer_direntpa' array.
 */
-typedef
+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()     (direntpp - lexer_direntpa)
-#define DPS_PUSH(E)   (*direntpp++ = E)
+#define DPS_LEN()     (lexer_direntpp - lexer_direntpa)
+#define DPS_PUSH(E)   (*lexer_direntpp++ = E)
 ()
 { struct dirent**  direntpp = lexer_direntpa;
   DIR*             cwd      = DL_CURDIR();
@@ -184,7 +238,9 @@ int dredge_current_depth
             DPS_PUSH(direntp);
             goto scan_next;
           case DT_DIR:
-            DL_CD_PUSH(direntp);
+           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);
@@ -197,4 +253,3 @@ int dredge_current_depth
   qsort(lexer_direntpa, DPS_LEN(), sizeof direntp, (qcomp)alphasort);
   return DPS_LEN();
 }
-