merged
[henge/webcc.git] / src / apc / scanner.c
index c669b10..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);
-void scanner_quit(void);
-int  scanner(void);
+int   scanner_init(void);
+void  scanner_quit(void);
+int   scanner(void);
+int   scanner_scanpixels(int*,int);
 /* 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
-int  lexer_lex(const char*);
+int   lexer_lexstring(const uint8_t*);
 extern //lexer.c
-void lexer_pushtok(int, int);
+void  lexer_pushtok(int, int);
 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'];
-
+#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.
@@ -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_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)
@@ -88,6 +97,10 @@ int scanner_init
 ()
 { 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);
 }
@@ -110,58 +123,90 @@ void scanner_quit
    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
-#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, 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 ((direntp = DL_CD_POP()) == NULL)//If the dirent is null, the library
-        goto libfail;                     //function in dirent has failed
-      printf("Lexdir %s\n",direntp->d_name);
-      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
+<<<<<<< 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
+      if (chdir(DL_CD_CURNAME()))         //move into the new directory
        goto libfail;
-      DL_PUSH(opendir(CWDSTR));
       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 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
-        goto parse;                       //start over
+        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)
@@ -173,7 +218,7 @@ 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
@@ -208,4 +253,3 @@ int dredge_current_depth
   qsort(lexer_direntpa, DPS_LEN(), sizeof direntp, (qcomp)alphasort);
   return DPS_LEN();
 }
-