+/*!@file
+ \brief lexical analyzer implementation for APC
+ \details lexer for tokenizing filenames from a directory root
+ \author Jordan Lavatai
+ \date Aug 2016
+ ----------------------------------------------------------------------------*/
+//stdc
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+//posix
+#include <unistd.h>
+#include <dirent.h>
+//bison
+#include "fileparser.tab.h"
+
+int lexer_init(void);
+int lexer();
+
+#define BUF_SIZE 256
+#define STACK_BUF_SIZE (BUF_SIZE >> 2)
+static DIR* dp_stack_buf[STACK_BUF_SIZE];
+static char path_buf[BUF_SIZE];
+static char storage_buf[BUF_SIZE];
+
+/* Setup stack and first directory to read from */
+int
+lexer_init()
+{ char cwd_buf[MAX_TOK_LEN];
+
+ dsp = dp_stack_base;
+ getcwd(path_buf, MAX_TOK_LEN);
+ printf("|------cwd is %s------|\n", path_buf);
+ if(!(*dsp = opendir(path_buf)))
+ printf("opendir(cwd) failed in linit()\n");
+
+ *dsp = dp;
+ printf("dp_stack is %x, dsp is %x size is %d\n",*dp_stack, *dsp, sizeof dp);
+
+ return 0;
+}
+
+/* Returns token identifier and sets yylval */
+int
+lexer()
+{ static DIR** dsp = &dp_stack_buf;
+ int tok_t;
+ char buf[MAX_TOK_LEN];
+ char* file_name;
+
+ printf("|------in yylex(), calling tok_dir------|\n");
+ if((tok_t = tok_dir(*dsp, yylval.str)) == -1)
+ printf("tok_dir returned -1, something is broken\n");
+ printf("|------in yylex(), returning tok_t = %d | err = %s------|\n", tok_t, strerror(errno));
+ return tok_t;
+}
+
+#define DSP_PUSH(_val) *++dsp = (_val)
+
+int
+tok_dir(DIR* dp, char buf[])
+{
+ struct dirent* de; /* directory entry */
+ static DIR *tmp_dp;
+ char *tmp_path;
+ int path_len;
+
+
+tok_start:
+ if((*dsp == NULL) || (de = readdir(*dsp)) == NULL)
+ {
+ if(errno)
+ { printf("Error:%s in tok_dir\n", strerror(errno));
+ return errno;
+ }
+ if( (dsp - dp_stack) >= 0)
+ {
+ printf("Current directory is null, pop one off ");
+#define DSP_POP() *dsp--
+
+ dp = DSP_POP();
+
+ /* Remove directory that was popped from path */
+#define SUB_PATH() tmp_path = strrchr(path, '/'); \
+ path_len = strlen(tmp_path); \
+ memset(tmp_path, 0, path_len)
+
+ SUB_PATH();
+
+ goto tok_start;
+ }
+ return 0; /* Done */
+ }
+
+ else if(de->d_type == DT_REG)
+ { printf("|------dir_ent is a file, "\
+ "setting yylval to %s------|\n", de->d_name);
+ memmove(buf, de->d_name, MAX_TOK_LEN);
+ return FDAT;
+ }
+ else if (de->d_type == DT_DIR )
+ { if ((dsp - dp_stack) >= MAX_DIR_DEP) /* We've opened to many directories */
+ {
+ printf("Too many directories!\n");
+ return 1;
+ }
+ if(strcmp(de->d_name,".") == 0 || strcmp(de->d_name,"..") == 0)
+ {
+ printf("directory is %s \n", de->d_name);
+ goto tok_start;
+ }
+
+ printf("|------ dir_ent is directory %s, "\
+ "cwd = %s, path = %s ------|\n", de->d_name, get_current_dir_name(), path);
+
+
+ /* Add directory name to path */
+#define ADD_PATH(_name) strcat(path, "/"); \
+ strcat(path, _name)
+
+ ADD_PATH(de->d_name);
+
+ tmp_dp = opendir(path);
+ if(tmp_dp == 0)
+ { printf("opening the directory failed,"\
+ "errno = %s\n", strerror(errno));
+ return -1;
+ }
+
+ DSP_PUSH(tmp_dp);
+
+ goto tok_start;
+
+ }
+ else
+ {
+ printf("A file that is not a diretory or a regular file is unable to be tokenized: %s\n", de->d_name);
+ return -1;
+ }
+
+
+
+}