Mercurial > hg-old > index.cgi
diff lwasm/input.c @ 329:c15cca3ae6a2
Created first pass of input layer
author | lost |
---|---|
date | Sun, 28 Feb 2010 05:01:31 +0000 |
parents | 591d01b343b9 |
children | 81c005b82775 |
line wrap: on
line diff
--- a/lwasm/input.c Sat Feb 13 06:08:26 2010 +0000 +++ b/lwasm/input.c Sun Feb 28 05:01:31 2010 +0000 @@ -27,57 +27,316 @@ less difficult. */ +#include <errno.h> +#include <stdio.h> +#include <string.h> + #include <lw_alloc.h> #include <lw_stringlist.h> +#include <lw_string.h> +#include "lwasm.h" -struct input_layer +/* +Data type for storing input buffers +*/ + +enum input_types_e { - lw_stringlist_t inputlist; - struct input_layer *nextlayer; - - FILE *fp; + input_type_file, // regular file, no search path + input_type_include, // include path, start from "local" + input_type_string, // input from a string + + input_type_error // invalid input type +}; + +struct input_stack +{ + struct input_stack *next; + int type; + void *data; + int data2; + char *filespec; }; +static struct input_stack *is = NULL; -static struct input_layer *layerstack = NULL; +void input_init(asmstate_t *as) +{ + struct input_stack *t; + + lw_stringlist_reset(as -> input_files); + while (is) + { + t = is; + is = is -> next; + lw_free(t); + } +} -void input_push(lw_stringlist_t list) +void input_pushpath(asmstate_t *as, char *fn) { - struct input_layer *i; + /* take apart fn into path and filename then push the path */ + /* onto the current file path stack */ + char *dn, *dp; + int o; + + dn = lw_strdup(fn); + dp = dn + strlen(dp); + + while (--dp != dn) + { + if (*dp == '/') + break; + } + if (*dp == '/') + *dp = '\0'; - i = lw_alloc(sizeof(struct input_layer)); - i -> nextlayer = layerstack; - layerstack = i; - i -> inputlist = lw_stringlist_copy(list); + if (dp == dn) + { + lw_free(dn); + dn = lw_strdup("."); + lw_stack_push(as -> file_dir, dn); + return; + } + dp = lw_strdup(dn); + lw_free(dn); + lw_stack_push(as -> file_dir, dp); +} + +void input_openstring(asmstate_t *as, char *s, char *str) +{ + struct input_stack *t; + + t = lw_alloc(sizeof(struct input_stack)); + t -> filespec = lw_strdup(s); + + t -> type = input_type_string; + t -> data = lw_strdup(str); + t -> data2 = 0; + t -> next = is; + is = t; + t -> filespec = lw_strdup(s); } -/* fetch a line of input from the top of the input stack */ -/* return NULL if no input left */ -char *input_fetchline(void) +void input_open(asmstate_t *as, char *s) { -again: - if (!layerstack) - return NULL; - - if (!layerstack -> fp) + struct input_stack *t; + char *s2; + char *p, *p2; + + t = lw_alloc(sizeof(struct input_stack)); + t -> filespec = lw_strdup(s); + + for (s2 = s; *s2 && *s2 != ':'; s2++) + /* do nothing */ ; + if (!s2) + { + t -> type = input_type_file; + } + else { - // no open file - char *fn; + char *ts; + + ts = lw_strndup(s, s2 - s); + s = s2 + 1; - fn = lw_stringlist_current(layerstack -> inputlist); - lw_stringlist_next(layerstack -> inputlist); - if (!fn) + if (!strcmp(ts, "include")) + t -> type = input_type_include; + else if (!strcmp(ts, "file")) + t -> type = input_type_file; + else + t -> type = input_type_error; + } + + t -> next = is; + is = t; + + switch (is -> type) + { + case input_type_include: + /* first check for absolute path and if so, skip path */ + if (*s == '/') { - struct input_list *t; - t = layerstack; - layerstack = layerstack -> nextlayer; - lw_stringlist_destroy(t -> inputlist); - lw_free(t); - goto again; + /* absolute path */ + is -> data = fopen(s, "rb"); + if (!is -> data) + { + lw_error("Cannot open file '%s': %s", s, strerror(errno)); + } + input_pushpath(as, s); + break; } - // open the file here + /* relative path, check relative to "current file" directory */ + p = lw_stack_top(as -> file_dir); + 0 == asprintf(&p2, "%s/%s", p, s); + is -> data = fopen(p2, "rb"); + if (is -> data) + { + input_pushpath(as, p2); + lw_free(p2); + break; + } + lw_free(p2); + + /* now check relative to entries in the search path */ + lw_stringlist_reset(as -> include_list); + while (p = lw_stringlist_current(as -> include_list)) + { + 0 == asprintf(&p2, "%s/%s", p, s); + is -> data = fopen(p2, "rb"); + if (is -> data) + { + input_pushpath(as, p2); + lw_free(p2); + return; + } + lw_free(p2); + lw_stringlist_next(as -> include_list); + } + lw_error("Cannot open include file '%s': %s", s, strerror(errno)); + + case input_type_file: + is -> data = fopen(s, "rb"); + + if (!is -> data) + { + lw_error("Cannot open file '%s': %s", s, strerror(errno)); + } + input_pushpath(as, s); + return; + } + + lw_error("Cannot figure out how to open '%s'.", s); +} + +char *input_readline(asmstate_t *as) +{ + char *s; + char linebuff[2049]; + int lbloc; + int eol = 0; + + /* if no file is open, open one */ +nextfile: + if (!is) { + s = lw_stringlist_current(as -> input_files); + if (!s) + return NULL; + lw_stringlist_next(as -> input_files); + input_open(as, s); } + switch (is -> type) + { + case input_type_file: + case input_type_include: + /* read from a file */ + for (;;) + { + int c, c2; + c = fgetc(is -> data); + lbloc = 0; + if (c == EOF) + { + if (lbloc == 0) + { + struct input_stack *t; + fclose(is -> data); + lw_free(lw_stack_pop(as -> file_dir)); + lw_free(is -> filespec); + t = is -> next; + lw_free(is); + is = t; + goto nextfile; + } + linebuff[lbloc] = '\0'; + eol = 1; + } + else if (c == '\r') + { + linebuff[lbloc] = '\0'; + eol = 1; + c2 = fgetc(is -> data); + if (c2 == EOF) + c = EOF; + else if (c2 != '\n') + ungetc(c2, is -> data); + } + else if (c == '\n') + { + linebuff[lbloc] = '\0'; + eol = 1; + c2 = fgetc(is -> data); + if (c2 == EOF) + c = EOF; + else if (c2 != '\r') + ungetc(c2, is -> data); + } + else + { + if (lbloc < 2048) + linebuff[lbloc++] = c; + } + if (eol) + { + s = lw_strdup(linebuff); + return s; + } + } + + case input_type_string: + /* read from a string */ + if (((char *)(is -> data))[is -> data2] == '\0') + { + struct input_stack *t; + lw_free(is -> data); + lw_free(is -> filespec); + t = is -> next; + lw_free(is); + is = t; + goto nextfile; + } + s = (char *)(is -> data); + lbloc = 0; + for (;;) + { + int c; + c = s[is -> data2]; + if (c) + is -> data2++; + if (c == '\0') + { + linebuff[lbloc] = '\0'; + eol = 1; + } + else if (c == '\r') + { + linebuff[lbloc] = '\0'; + eol = 1; + if (s[is -> data2] == '\n') + is -> data2++; + } + else if (c == '\n') + { + linebuff[lbloc] = '\0'; + eol = 1; + if (s[is -> data2] == '\r') + is -> data2++; + } + else + { + if (lbloc < 2048) + linebuff[lbloc++] = c; + } + if (eol) + { + s = lw_strdup(linebuff); + return s; + } + } + default: + lw_error("Problem reading from unknown input type"); + } }