/* */ #include #include #include // mmap(2) #include // stat(2) #include #include #include // open(2) #include // va_arg(3) #include // terminals #include "grammar.h" #include "figure2-15-calc.h" // forward declarations void program(void); void parse(char *file); void get_nexttoken(void); char *scanToken(char *ptr, char *lastchar, int *token_type, int *token_value, struct ParseState *ps); void memorymap_file(char *file, char **start, char **lastchar); void error_out(int error_code, const char *error_description, ...) __attribute__ ((noreturn)) __attribute__ ((format (printf, 2, 3))) ; int usage(void); int main(int argc, char **argv) { argc--; parse(argv[1]); } // state variables int nextToken = 0; int tokenValue = 0; char *where = NULL; char *lastchar = NULL; void parse(char *file) { // It's a lot easier to treat a file as a sequence of bytes, implying // we should use mmap(2)... memorymap_file(file,&where,&lastchar); get_nexttoken(); printf("digraph {\n"); printf("node [shape=none]\n"); program(); // first production in parser.c printf("}\n"); } void get_nexttoken() { static struct ParseState ParseState = {1,0,0}; while(where < lastchar) { where = scanToken(where,lastchar,&nextToken,&tokenValue,&ParseState); return; } nextToken = 0; return; } // UTILITY void memorymap_file(char *file, char **start, char **lastchar) { struct stat stat_buff; int ret = stat(file,&stat_buff); if(ret == -1) { error_out(1,"Error: stat(2) failed for file '%s'\n",file); } size_t file_size = (size_t) stat_buff.st_size; // mmap(2) the file into memory int fd = open(file,O_RDONLY); if(fd == -1) { error_out(1,"Error: open(2) failed for file %s\n",file); } *start = mmap(NULL, // Any location in memory is fine file_size, // Length of the file PROT_READ, // Let us read the file MAP_PRIVATE, // We don't need to share this fd, // Our file descriptor 0); // Start at the beginning *lastchar = *start + file_size; close(fd); // Apparently this is fine; look at man mmap(2) return; } void error_out(int error_code, const char *error_description, ...) { va_list ap; va_start(ap,error_description); vfprintf(stderr,(const char *)error_description,ap); usage(); exit(error_code); } int usage() { fprintf(stderr,"Usage: ./figure2-15-calc FILENAME\n"); return(0); }