Lexer actually lexes filenames now, and odats are made out of mapvariants
[henge/webcc.git] / src / apc / scanner.c
index 86c096e..b1b7998 100644 (file)
   ----------------------------------------------------------------------------*/
 /* Standard */
 #include <stdio.h>  //print
   ----------------------------------------------------------------------------*/
 /* Standard */
 #include <stdio.h>  //print
+#include <string.h> //strncmp
 #include <errno.h>  //errno
 #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
 /* 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);
 #include "parser.tab.h"
 /* Public */
 int   scanner_init(void);
 void  scanner_quit(void);
 int   scanner(void);
+int   scanner_scanpixels(int*,int);
 /* Private */
 /* Private */
-#ifndef DL_STACKSIZE
-#define DL_STACKSIZE     64
-#endif
-#ifndef DL_CD_STACKSIZE
-#define DL_CD_STACKSIZE  DL_STACKSIZE //square tree
-#endif
 extern //lexer.c
 extern //lexer.c
-int  lexer_lex(const char*);
+int   lexer_lexstring(const uint8_t*);
 extern //lexer.c
 extern //lexer.c
-void lexer_pushtok(int, int);
+void  lexer_pushtok(int, int);
 static
 static
-int  dredge_current_depth(void);
+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'];
 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
 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.
 
 /* Directory Listing Stack
    FILO Stack for keeping an open DIR* at each directory depth for treewalk.
@@ -72,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_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)
 #define DL_CD_POP()     (*--DL_CD_STACKP)
 #define DL_PUSH(D)      ((*++DL_STACKP).dirp = D)
 #define DL_CD_PUSH(E)   (*DL_CD_STACKP++ = E)
@@ -88,6 +97,10 @@ int scanner_init
 ()
 { DL_INIT();
   DL_STACK[0].dirp = opendir(ROOTDIR);
 ()
 { 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);
 }
   printf("Root dir %s\n",ROOTDIR);
   return !chdir(ROOTDIR) && (DL_STACK[0].dirp == NULL || dredge_current_depth() == -1);
 }
@@ -110,57 +123,91 @@ void scanner_quit
    array, while placing all subdirectory entries in the current depth's child
    directory stack to be scanned later.
 
    array, while placing all subdirectory entries in the current depth's child
    directory stack to be scanned later.
 
-   Returns the number of elements added to the lexer's file array, or -1 on
-   error
+   Returns the number of tokens generated on success, -1 on error.
 */
 int scanner
 #define $($)#$ //stringifier
 */
 int scanner
 #define $($)#$ //stringifier
-#define ERR_CHILD  "Fatal: Maximum of " $(DL_CD_STACKSIZE)      \
-  " child directories exceeded for directory at depth %i\n"     \
+#ifdef _DIRENT_HAVE_D_NAMLEN
+#define MAX_DNAME _D_ALLOC_NAMLEN(DL_CD())
+#else
+#define MAX_DNAME 1024
+#endif
+#define ERR_CHILD  "Fatal: Maximum of " $(DL_CD_STACKSIZE)                  \
+  " child directories exceeded for directory at depth %i\n"                \
   ,DL_LEN()
   ,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()
   " exceeded during directory scan\n"
 #define ERR_DL     "Fatal: Directory List Stack Corruption %x\n", DL_LEN()
-#define TOK_CLOPEN  0x55, 1 //TODO
-#define TOK_CLCLOSE 0x56, 1 //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
   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 ((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_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 (DL_LEN() >= DL_STACKSIZE)       //fail if maxdepth exceeded
         { fprintf(stderr, ERR_DEPTH);
           goto fail;
         }
-      if (chdir(direntp->d_name))         //move into the new directory
+      if (chdir(DL_CD_CURNAME()))         //move into the new directory
        goto libfail;
        goto libfail;
-      DL_PUSH(opendir(CWDSTR));
       if (DL_CURDIR() == NULL)            //open the cwd
        goto libfail;
       if (DL_CURDIR() == NULL)            //open the cwd
        goto libfail;
-      lexer_pushtok(TOK_CLOPEN);          //Push "Open Directory" token
+      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,
       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,
-        return 0;                         //we're done
-      lexer_pushtok(TOK_CLCLOSE);         //Else push "Close Directory" token,
+        goto done;                          //we're done
+      lexer_pushtok(CLCLOSE, 0);          //Else push "Close Directory" token,
+      ntok++;
       if (!chdir(".."))                   //move up a directory and
       if (!chdir(".."))                   //move up a directory and
-        goto parse;                       //start over
+        goto scan;                          //start over
     }
   fprintf(stderr, ERR_DL);
  libfail:
     }
   fprintf(stderr, ERR_DL);
  libfail:
-  perror("parsedir");
+  perror("scanner: ");
  fail:
  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)
 }
 
 /* Directory Entity Sort and Filter (Dredge)
@@ -172,7 +219,7 @@ int scanner
    Returns -1 if 'readdir' encounters an error, otherwise returns the number of
    directory entries sent to the external 'lexer_direntpa' array.
 */
    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
 int (*qcomp)(const void*, const void*);
 static inline
 int dredge_current_depth
@@ -207,5 +254,3 @@ int dredge_current_depth
   qsort(lexer_direntpa, DPS_LEN(), sizeof direntp, (qcomp)alphasort);
   return DPS_LEN();
 }
   qsort(lexer_direntpa, DPS_LEN(), sizeof direntp, (qcomp)alphasort);
   return DPS_LEN();
 }
-
-