--- /dev/null
+/*!@file
+ \brief lexical analyzer implementation for APC
+ \details this lexer scans a root directory given from the command line
+ for subdirectories and files structured for the APC grammar.
+ \author Jordan Lavatai
+ \date Aug 2016
+ ----------------------------------------------------------------------------*/
+//stdc
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+//posix
+#include <unistd.h>
+#include <stdlib.h>
+//bison
+#include "fileparser.tab.h"
+#define TOKEN_BUF_SIZE 1024
+#define DIRP_STACK_SIZE 512
+
+int lexer_init(void);
+int lexer(void);
+
+static
+int lexer_scan(void);
+
+static
+int token_buf[TOKEN_BUF_SIZE], *tbp, *tbx;
+static
+DIR* dirp_stack[DIRP_STACK_SIZE], *dsp;
+
+/* Initialize pointers */
+int
+lexer_init()
+{ tbp = tbx = token_buf;
+ dsp = dirp_stack;
+ return 0;
+}
+
+/* Returns a token identifier and sets yylval */
+int
+lexer()
+{ if (lexer_scan() == 0)
+ return 0;
+ yylval = *tbp++;
+ return *tbp++;
+}
+
+/* Scanner
+ Scans a filename from its alphabetically ordered list of file elements
+ and tokenizes the result. If the file list is empty, then the stack of
+ directory elements will be popped and processed as they are encountered.
+
+ Returns the number of tokens generated.
+*/
+#define MAX_ENTITIES 256
+static
+int lexer_scan()
+{ static struct dirent* entity;
+ static struct dirent* files[MAX_ENTITIES];
+ static struct dirent* dirs = files + MAX_ENTITIES - 1;
+ static int num_files = 0;
+ static int num_dirs = 0;
+
+ //sort out files and directories, grow directories from bottom up
+ while ((entity = readdir(dirp)) != NULL)
+ { switch (entity->d_type)
+ { case DT_LNK:
+ case DT_REG:
+ files[num_files++] = entity;
+ break;
+ case DT_DIR:
+ *(dirs - num_dirs++) = entity;
+ break;
+ case DT_UNKNOWN:
+ default:
+ printf("Ignoring unknown file: %s\n", entity->d_name);
+ break;
+ }
+ }
+ if (errno)
+ perror("readdir");
+ qsort(&files[0], num_files, sizeof struct dirent*, qalpha);
+ num_ents = scandirat(dirfd, ".", &namelist, scanfilter, scancompar);
+ if (num_ents < 0)
+ { perror("scandirat");
+ return -1;
+ }
+ //process files
+
+ //recurse into directories
+
+}
--- /dev/null
+/*!@file
+ \brief APC main driver
+ \details The driver assumes the existence of a bison-generated parser,
+ referenced by the external function 'yyparse'.
+ It also assumes the existence of a lexer which must be initialized
+ before parsing, referenced by the external function 'lexer_init'
+ which assumes standard error handling.
+ All input arguments are made available through the exposed (that is,
+ non-static) array of character pointers 'cargs', which point
+ to the non-duplicated strings in 'argv' directly from the system.
+ \author Jordan Lavatai
+ \date Aug 2016
+ ----------------------------------------------------------------------------*/
+/* Standard */
+#include <errno.h>
+/* Posix */
+#include <unistd.h> //getopt
+
+int main(int, char*[]);
+
+const char* cargs['Z'] = {0};
+
+extern //bison
+void yyparse(void);
+extern //lexer.c
+int lexer_init(void);
+
+/* Main entry from terminal
+ parses the command line and kicks off recursive scanning
+*/
+int main
+( int argc,
+ char* argv[]
+)
+#define MAXERR "-%c allows at most " #MAX_STR_LEN " input characters", opt
+#define USAGE "Usage: %s [-r root]\n", argv[0]
+#define DONE -1
+{ int opt;
+
+ getopt:
+ switch (opt = getopt(argc, argv, "r:o:"))
+ { case DONE:
+ break;
+ case 'r' :
+ case 'o' :
+ if (strnlen(optarg, MAX_STR_LEN) != MAX_STR_LEN)
+ { cargs[opt] = optarg;
+ goto getopt;
+ }
+ fprintf(stderr, MAXERR);
+ default :
+ fprintf(stderr, USAGE);
+ exit(EXIT_FAILURE);
+ }
+ if (lexer_init())
+ { perror("lexer");
+ exit(EXIT_FAILURE);
+ }
+ yyparse();
+ exit(EXIT_SUCCESS);
+}
+
+++ /dev/null
-/*!@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;
- }
-
-
-
-}