Lexer actually lexes filenames now, and odats are made out of mapvariants
[henge/webcc.git] / src / apc / lexer.c
index 096016a..b6c6ca3 100644 (file)
 /* Standard */
 #include <stdio.h>
 #include <string.h>
+#include <stdint.h>
 #include <errno.h>
 /* Posix */
 #include <unistd.h>
+#include <unitypes.h>
+#include <unistr.h>
+#include <uniconv.h>
+#include <uniname.h>
+#include <unistdio.h>
 #include <stdlib.h>
-#include <limits.h> //realpath, NAME_MAX, PATH_MAX
+#include <limits.h> //realpath, NAME_MAX, FPATH_MAX
 #include <dirent.h>
+
 /* Local */
 #include "parser.tab.h"
 #ifndef DE_STACKSIZE
 #ifndef TK_STACKSIZE
 #define TK_STACKSIZE 1024
 #endif
+#ifndef MAX_SETNAME_LEN //max setname length
+#define MAX_SETNAME_LEN 32
+#endif
+#ifndef MAX_ELENAME_LEN //max setname length
+#define MAX_ELENAME_LEN 32
+#endif
+#define FNAME_MAX 1024
+#define FPATH_MAX 8192
+
 /* Public */
 int         lexer_init(void);
 int         lexer(void);
-int         lexer_lexfile(const char*);
+int         lexer_lexfile(const uint8_t*);
 void        lexer_pushtok(int, YYSTYPE);
-char const* lexer_get_current_filepath(void);
-struct dirent* lexer_direntpa[DE_STACKSIZE], **lexer_direntpp;
+uint8_t const* lexer_get_current_filepath(void);
+int         lexer_lexfilename(uint8_t*);
+struct dirent* lexer_direntpa[DE_STACKSIZE],** lexer_direntpp,** lexer_direntpb;
 /* Private */
-extern //lexer_lex.rl
-int         lexer_lex(const char*);
+extern //lexer_fsm.rl
+int         lexer_lexstring(uint8_t*, int);
+extern //lexer_fsm.rl
+int    lexer_setstr(uint8_t*, int);
 extern //scanner.c
 int         scanner_init(void);
 extern //scanner.c
@@ -47,7 +66,13 @@ int         dredge_current_depth(void);
 extern //bison
 YYSTYPE     yylval;
 static
-char const* current_filename;
+uint8_t const* current_filename;
+static
+uint8_t prev_setname[MAX_SETNAME_LEN];  
+static
+uint8_t prev_elename[MAX_ELENAME_LEN];
+static
+uint8_t map_key[] = "~";
 static
 struct tok
 { YYSTYPE lval;  //token val
@@ -58,13 +83,14 @@ struct tok
    Simple array for keeping track of dirents yet to be processed by the scanner.
    If this list is empty and there are no tokens, the lexer is done.
    This array is populated by the scanner as an array, and popped locally by the
-   lexer as a stack.
+   lexer as a stack, and is popped as a FIFO stack.
 */
 #define DE_STACK    (lexer_direntpa)
 #define DE_STACKP   (lexer_direntpp)
-#define DE_LEN()    (DE_STACKP - DE_STACK)
-#define DE_INIT()   (DE_STACKP = DE_STACK)
-#define DE_POP()    (*--DE_STACKP)
+#define DE_STACKB   (lexer_direntpb)
+#define DE_LEN()    (DE_STACKP - DE_STACKB)
+#define DE_INIT()   (DE_STACKP = DE_STACKB = DE_STACK)
+#define DE_POP()    (*DE_STACKB++)
 
 /* Token Stack
    This is a FIFO stack whose pointers are a union of either a pointer to an
@@ -111,10 +137,12 @@ int lexer
   } while (0)
 ()
 { struct tok token;
- start:
-  while (DE_LEN() > 0)    //lex any directory entries in our stack
-    if (lexer_lexfile(DE_POP()->d_name) == 0)
-      FAIL("Lexer failed to tokenize [%s]\n",(*DE_STACKP)->d_name);
+   start:
+  while (DE_LEN() > 0)//lex any directory entries in our stack
+    {
+      if (lexer_lexfile(DE_POP()->d_name) == 0)
+       FAIL("Lexer failed to tokenize [%s]\n",(*DE_STACKB)->d_name);
+    }
   if (TK_EMPTY)           //if there are no tokens,
     { TK_INIT();            //initialize the token stack back to 0
       switch (scanner())
@@ -154,37 +182,384 @@ void lexer_pushtok
 */
 int lexer_lexfile
 #define HIDDEN_WARNING "%s is hidden and will not be parsed!\n", filename
-( const char  *filename
+( const uint8_t  *filename
 )
-{ static char fname[NAME_MAX];
-  char        *last_period = NULL, *iter;
+{ static uint8_t fname[FNAME_MAX];
+  uint8_t        *last_period = NULL, *iter;
 
-  if (*filename == '.')
+  if (*filename ==  '.')
     { fprintf (stderr, HIDDEN_WARNING);
       return 0;
     }
   /* Copy the filename and remove its suffix */
-  strncpy(fname,filename,NAME_MAX);
+  u8_strncpy(fname,filename,FNAME_MAX);
   last_period = NULL;
   for (iter = fname; *iter; iter++)  //find the last '.' char
-    if (*iter == '.')
+    if (*iter ==  '.')
       last_period = iter;
   if (last_period)                   //if we found one,
-    *last_period = '\0';             //truncate the string there
+    *last_period =  0;             //truncate the string there
   /* Register the current_filename */
   current_filename = filename;
-  
-  return lexer_lex(fname);
+  printf("lexer_lexfilename(%s)\n",fname);
+  return lexer_lexfilename(fname);
 }
 
-char const* lexer_get_current_filepath
+uint8_t const* lexer_get_current_filepath
 ()
-{ static char        current_path[PATH_MAX];
-  static char const* last_filename;
+{ static uint8_t        current_path[FPATH_MAX];
+  static uint8_t const* last_filename;
   if ((!last_filename || last_filename != current_filename) &&
-      (realpath(current_filename, current_path) != current_path))
+      ((uint8_t*) realpath(current_filename, current_path) != (uint8_t*) current_path))
     { perror("realpath: ");
       return NULL;
     }
-  return (const char*)current_path;
+  return (const uint8_t*)current_path;
+}
+
+/* Returns 1 on success, 0 on failure */
+int
+lexer_ismapfile(uint8_t* str)
+{
+  int i, len;
+
+  len = u8_strlen(str);
+  for(i = 0; i < len; i++)
+    if(str[i] == '~')
+      return 1;
+}
+
+
+/* Scan filename and push the its tokens
+   onto the stack */
+int lexer_lexfilename
+(uint8_t* str)
+#define REF(STR) (STR[0] <= 0x39 && STR[0] >= 0x30)  
+#define DEL_FTOK(STR) (STR = u8_strchr(STR, '_') + 1)
+#define NEXT_TOK(STR) (u8_strchr(STR, '_') + 1)
+#define SET_CURR_SETNAME(STR)                   \
+  do {                                         \
+  printf("setting curr_setname of str(%s)\n", STR); \
+  setname_end = u8_chr(STR, FNAME_MAX, '_');   \
+  setname_len = setname_end - str;             \
+  u8_move(curr_setname, STR, setname_len);     \
+  printf("curr_setname is now %s\n",curr_setname); \
+   } while (0)
+#define SET_CURR_ELENAME(STR) \
+  do { \
+    printf("setting curr_elename of str(%s)\n", STR); \
+    setname_end = u8_chr(STR, FNAME_MAX, '_') + 1; \
+    if(REF(setname_end)) \
+      setname_end = u8_chr(setname_end, FNAME_MAX, '_') + 1; \
+    elename_end = u8_chr(setname_end, FNAME_MAX, '_'); \
+    elename_len = elename_end - setname_end; \
+    u8_move(curr_elename, setname_end, elename_len); \
+    printf("curr_elename is now %s\n", curr_elename); \
+  } while (0) 
+  
+#define SETNAME_MATCHES()  (u8_strcmp(curr_setname, prev_setname) == 0)
+#define ELENAME_MATCHES()  (u8_strcmp(curr_elename, prev_elename) == 0)
+#define UPDATE_PREV_SETNAME(STR) \
+  do { \
+    printf("updating prev_setname from (%s)", prev_setname);           \
+  u8_set(prev_setname , (ucs4_t) 0, MAX_SETNAME_LEN );  \
+  u8_move(prev_setname, curr_setname, setname_len);  \
+  printf(" to %s\n", prev_setname); \
+  } while (0)
+#define UPDATE_PREV_ELENAME(STR) \
+  do { \
+  u8_set(prev_elename , (ucs4_t) 0, MAX_ELENAME_LEN );  \
+  u8_move(prev_elename, curr_elename, elename_len);  \
+  } while (0)
+#define PREV_MAPFILE() (TK_STACKX - 5)->tok_t == MOPEN || (TK_STACKX-3)->tok_t == MOPEN
+#define SET_MAPSTR(STR)  (STR = u8_strstr(STR, map_key))
+
+{ int ntok, len, newstrt;
+  uint8_t *filepath;
+  typedef enum filetypes {
+    error = 0,
+    set_model,
+    set_map,
+    ele_model,
+    ele_map,
+    ele_vlink,
+    set_olink,
+    set_vlink
+  } filetypes;
+
+  ntok = 0;
+
+  printf("|---- Begin lexerfilename on %s ----|\n", str);
+  
+  if(*str == 0)
+    perror("Lexfilename:: str is NULL so fail\n");
+
+  /* Determine the filetype of str */
+  len = u8_strlen(str);
+  newstrt = lexer_setstr(str,len);
+
+  str = str + newstrt;
+
+  len = u8_strlen(str);
+  
+  ntok += lexer_lexstring(str, len);
+
+  /* Need to add map variant name 'default' if user did not specify a
+      map variant name */
+  /* if(filetype == ele_map) */
+  /*   { if(!u8_strchr(str, '_')) //map variant name not provided */
+  /*      { yylval.str = "default"; */
+  /*    lexer_pushtok(NAME, yylval); */
+  /*    ntok++; */
+  /*    printf("Pushing default ele_map name\n");     */
+  /*      }      */
+  /*  } */
+
+  /* Pass back filepath as end of statment operator */
+  filepath = u8_strdup(lexer_get_current_filepath());
+  yylval.str = filepath;
+  lexer_pushtok(NAME, yylval);
+  printf("Pushing filepath %s\n", filepath);
+  ntok++;
+     
+  printf("|---- Ending lexer_lexfilename on %s, %d tokens were lexed ----|\n", str, ntok);
+  return ntok;
+}
+
+int
+lexer_lexelemap
+( uint8_t* str)
+{ int setname_len, elename_len, strlen;
+  uint8_t* setname_end, *elename_end, *newstrt;
+  uint8_t curr_setname[MAX_SETNAME_LEN] = {0};
+  uint8_t curr_elename[MAX_ELENAME_LEN] = {0};
+
+  newstrt = str;
+  
+  SET_CURR_SETNAME(newstrt);
+  SET_CURR_ELENAME(newstrt);
+  if(PREV_MAPFILE())
+    { printf("*previous file was mapfile*\n");
+      SET_MAPSTR(newstrt);
+    }
+  else
+    { 
+      if(SETNAME_MATCHES())
+       { DEL_FTOK(newstrt);
+         if(REF(newstrt))
+           DEL_FTOK(newstrt);
+         printf("setname matches\n");
+         if(ELENAME_MATCHES())
+            DEL_FTOK(newstrt);
+         if(REF(str))
+           DEL_FTOK(newstrt);
+       }          
+     }
+  UPDATE_PREV_ELENAME(newstrt);
+  UPDATE_PREV_SETNAME(newstrt);
+
+  return newstrt - str;
+
+  
 }
+
+int 
+lexer_lexelemodel
+(uint8_t* str)
+{ int setname_len, elename_len;
+  uint8_t* setname_end, *elename_end, *newstrt;
+  uint8_t curr_setname[MAX_SETNAME_LEN] = {0};
+  uint8_t curr_elename[MAX_ELENAME_LEN] = {0};
+
+  printf("In lexelemodel, str is %s\n", str);
+
+  newstrt = str;
+  
+  SET_CURR_SETNAME(newstrt);
+  SET_CURR_ELENAME(newstrt);
+  if(SETNAME_MATCHES())
+    { printf("in ele_model: setname matches\n");
+      DEL_FTOK(newstrt);
+      printf("newstrt is now %s\n", newstrt);
+      if(REF(newstrt))
+       DEL_FTOK(newstrt);
+      if(ELENAME_MATCHES())
+       { printf("in ele_model: elename matches\n");
+         DEL_FTOK(newstrt);
+         if(REF(newstrt))
+           DEL_FTOK(newstrt);
+       }
+    }
+  UPDATE_PREV_ELENAME(newstrt);
+  UPDATE_PREV_SETNAME(newstrt);
+
+  return newstrt - str;
+}
+
+int
+lexer_lexsetmap
+(uint8_t* str)
+{ int setname_len, elename_len;
+  uint8_t* setname_end, *elename_end, *newstrt;
+  uint8_t curr_setname[MAX_SETNAME_LEN] = {0};
+  uint8_t curr_elename[MAX_ELENAME_LEN] = {0};
+
+  newstrt = str;
+  
+  SET_CURR_SETNAME(newstrt); 
+  if(PREV_MAPFILE())
+    SET_MAPSTR(newstrt);
+  else
+    if( SETNAME_MATCHES())
+      DEL_FTOK(newstrt);
+      if(REF(newstrt))
+       DEL_FTOK(newstrt);
+
+  UPDATE_PREV_SETNAME(newstrt);
+
+  return newstrt - str;
+}
+
+int
+lexer_lexsetmodel
+(uint8_t* str)
+{ int setname_len, elename_len;
+  uint8_t* setname_end, *elename_end, *newstrt;
+  uint8_t curr_setname[MAX_SETNAME_LEN] = {0};
+  uint8_t curr_elename[MAX_ELENAME_LEN] = {0};
+
+  newstrt = str;
+
+  SET_CURR_SETNAME(newstrt);
+  if( SETNAME_MATCHES())
+    DEL_FTOK(newstrt);
+  if(REF(newstrt))
+    DEL_FTOK(newstrt);
+  UPDATE_PREV_SETNAME(newstrt);
+
+  return newstrt - str;
+
+}
+
+int
+lexer_lexsetvlink
+(uint8_t* str)
+{ int setname_len, elename_len;
+  uint8_t* setname_end, *elename_end, *newstrt;
+  uint8_t curr_setname[MAX_SETNAME_LEN] = {0};
+  uint8_t curr_elename[MAX_ELENAME_LEN] = {0};
+
+  newstrt = str;
+
+  SET_CURR_SETNAME(newstrt);
+  if( SETNAME_MATCHES())
+    DEL_FTOK(newstrt);
+  if(REF((NEXT_TOK(newstrt)))) //if NAME REF REF
+    DEL_FTOK(newstrt);
+  UPDATE_PREV_SETNAME(newstrt);
+
+  return newstrt - str;
+
+}
+
+int
+lexer_lexelevlink
+(uint8_t* str)
+{ int setname_len, elename_len;
+  uint8_t* setname_end, *elename_end, *newstrt;
+  uint8_t curr_setname[MAX_SETNAME_LEN] = {0};
+  uint8_t curr_elename[MAX_ELENAME_LEN] = {0};
+
+  newstrt = str;
+
+  SET_CURR_SETNAME(newstrt);
+  SET_CURR_ELENAME(newstrt);
+  if(SETNAME_MATCHES())
+    { DEL_FTOK(newstrt);
+      if(REF(NEXT_TOK(newstrt))) //NAME REF REF, where  is set_label
+        DEL_FTOK(newstrt);
+    }
+       
+  return newstrt - str;
+}
+
+int
+lexer_lexsetolink
+(uint8_t* str)
+{ int setname_len, elename_len;
+  uint8_t* setname_end, *elename_end;
+  uint8_t curr_setname[MAX_SETNAME_LEN] = {0};
+  uint8_t curr_elename[MAX_ELENAME_LEN] = {0};
+
+  return 0;
+
+  //do nothing
+}
+
+int
+lexer_lexeleolink
+(uint8_t* str)
+{ int setname_len, elename_len;
+  uint8_t* setname_end, *elename_end, *newstrt;
+  uint8_t curr_setname[MAX_SETNAME_LEN] = {0};
+  uint8_t curr_elename[MAX_ELENAME_LEN] = {0};
+
+  newstrt = str;
+  
+  SET_CURR_SETNAME(newstrt);
+  printf("prev_setname %s, curr_setname %s\n", prev_setname, curr_setname);
+  if(SETNAME_MATCHES())
+    { DEL_FTOK(newstrt);
+      if(REF(newstrt))
+       DEL_FTOK(newstrt);
+    }
+
+  return newstrt - str;
+
+  
+}
+
+
+/**************************/
+/****Abandon All Hope******/
+/**************************/
+/***                    ***/
+/***                    ***/       
+/***                    ***/
+/***                    ***/
+
+
+
+/* int lexer_lexmapfile */
+/* #define INC_X() */
+/* (int height, int width) */
+/* { */
+/*   int x, y; */
+
+/*   /\* Give scanner_scanpixels a buffer and a len. Iterate through */
+/*      buf with buf[n]. If n == 0, do nothing. if n has a value, push x, */
+/*      push y, push (z = n << 24), push (ref_id = n >> 8) *\/ */
+/*   //scanner_scanpixels() */
+
+/*   for(i = 0; i < len; i++) */
+/*     if(buf[i] == 0) */
+/*       if(x == width) */
+/*     x = 0; */
+/*       else */
+       
+         
+      
+
+/* } */
+/* fname_bytes = (uint8_t*)(DE_POP()->d_name); */
+      /* printf("d_name is %s\n", fname_bytes); */
+      /* for (fnp = filename, i = 0; i < FNAME_MAX; i += unit_size, fnp++) */
+      /*       { unit_size = u8_mblen(fname_bytes + i, min(4, FNAME_MAX - i)); */
+      /*         if (u8_mbtouc(fnp, fname_bytes + i, unit_size) == -1) //add ucs4 char to the filename */
+      /*           FAIL("Lexer failed to convert ^%s to unicode\n", (fname_bytes + i)); */
+      /*         if (*fnp == 0) //added a terminating char */
+      /*           break; */
+      /*       } */
+      /* if(u8_mbtouc(filename, DE_POP()->d_name, FNAME_MAXy) == -1) */
+      /*       FAIL("Lexer failed to convert d_name into uint8_t\n"); */
+      /* ulc_fprintf(stdout, "filename is %11U\n c", filename); */