# HG changeset patch # User lost # Date 1267333291 0 # Node ID c15cca3ae6a2e00aa5b3cf4544e93e7955eae029 # Parent 591d01b343b92385231bfca87d767b8d7376efae Created first pass of input layer diff -r 591d01b343b9 -r c15cca3ae6a2 lwasm/Makefile.am --- a/lwasm/Makefile.am Sat Feb 13 06:08:26 2010 +0000 +++ b/lwasm/Makefile.am Sun Feb 28 05:01:31 2010 +0000 @@ -1,5 +1,5 @@ AM_CPPFLAGS = -I$(top_builddir)/lib -I$(top_srcdir)/lib -I$(top_builddir)/lwlib -I$(top_srcdir)/lwlib bin_PROGRAMS = lwasm -lwasm_SOURCES = main.c pragma.c +lwasm_SOURCES = main.c pragma.c input.c lwasm_LDADD = -L$(top_builddir)/lib -L$(top_srcdir)/lib -L$(top_builddir)/lwlib -L$(top_srcdir)/lwlib -lgnu -llw EXTRA_DIST = lwasm.h diff -r 591d01b343b9 -r c15cca3ae6a2 lwasm/input.c --- 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 +#include +#include + #include #include +#include +#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"); + } } diff -r 591d01b343b9 -r c15cca3ae6a2 lwasm/lwasm.h --- a/lwasm/lwasm.h Sat Feb 13 06:08:26 2010 +0000 +++ b/lwasm/lwasm.h Sun Feb 28 05:01:31 2010 +0000 @@ -23,6 +23,7 @@ #define ___lwasm_h_seen___ #include +#include enum lwasm_output_e { @@ -68,6 +69,7 @@ char *output_file; // output file name lw_stringlist_t input_files; // files to assemble lw_stringlist_t include_list; // include paths + lw_stack_t file_dir; // stack of the "current file" dir } asmstate_t; #endif /* ___lwasm_h_seen___ */ diff -r 591d01b343b9 -r c15cca3ae6a2 lwasm/main.c --- a/lwasm/main.c Sat Feb 13 06:08:26 2010 +0000 +++ b/lwasm/main.c Sun Feb 28 05:01:31 2010 +0000 @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -168,8 +169,10 @@ program_name = argv[0]; /* initialize assembler state */ + asmstate.include_list = lw_stringlist_create(); asmstate.input_files = lw_stringlist_create(); - asmstate.include_list = lw_stringlist_create(); + asmstate.file_dir = lw_stack_create(lw_free); + input_init(); /* parse command line arguments */ argp_parse(&argp, argc, argv, 0, 0, &asmstate); diff -r 591d01b343b9 -r c15cca3ae6a2 lwlib/Makefile.am --- a/lwlib/Makefile.am Sat Feb 13 06:08:26 2010 +0000 +++ b/lwlib/Makefile.am Sun Feb 28 05:01:31 2010 +0000 @@ -1,3 +1,3 @@ noinst_LIBRARIES = liblw.a -liblw_a_SOURCES = lw_alloc.c lw_stringlist.c lw_string.c -EXTRA_DIST = lw_alloc.h lw_stringlist.h lw_string.h +liblw_a_SOURCES = lw_alloc.c lw_stringlist.c lw_string.c lw_stack.c lw_error.c +EXTRA_DIST = lw_alloc.h lw_stringlist.h lw_string.h lw_stack.h lw_error.h diff -r 591d01b343b9 -r c15cca3ae6a2 lwlib/lw_error.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lwlib/lw_error.c Sun Feb 28 05:01:31 2010 +0000 @@ -0,0 +1,38 @@ +/* +lw_error.c + +Copyright © 2010 William Astle + +This file is part of LWTOOLS. + +LWTOOLS is free software: you can redistribute it and/or modify it under the +terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see . +*/ + +#include + +#define ___lw_error_c_seen___ +#include + +#include +#include +#include + +void lw_error(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + exit(1); +} diff -r 591d01b343b9 -r c15cca3ae6a2 lwlib/lw_error.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lwlib/lw_error.h Sun Feb 28 05:01:31 2010 +0000 @@ -0,0 +1,34 @@ +/* +lw_error.h + +Copyright © 2010 William Astle + +This file is part of LWTOOLS. + +LWTOOLS is free software: you can redistribute it and/or modify it under the +terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see . +*/ + +#ifndef ___lw_error_h_seen___ +#define ___lw_error_h_seen___ + + +#ifdef ___lw_error_c_seen___ + +#else /* def ___lw_error_c_seen___ */ + +extern void lw_error(const char *fmt, ...); + +#endif /* def ___lw_error_c_seen___ */ + +#endif /* ___lw_error_h_seen___ */ diff -r 591d01b343b9 -r c15cca3ae6a2 lwlib/lw_stack.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lwlib/lw_stack.c Sun Feb 28 05:01:31 2010 +0000 @@ -0,0 +1,80 @@ +/* +lw_stack.c + +Copyright © 2010 William Astle + +This file is part of LWTOOLS. + +LWTOOLS is free software: you can redistribute it and/or modify it under the +terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see . +*/ + +#include + +#define ___lw_stack_c_seen___ +#include +#include + +/* this is technically valid but dubious */ +#define NULL 0 + +lw_stack_t lw_stack_create(void (*freefn)(void *d)) +{ + lw_stack_t S; + + S = lw_alloc(sizeof(lw_stack_t)); + S -> head = NULL; + S -> freefn = freefn; + return S; +} + +void *lw_stack_pop(lw_stack_t S) +{ + if (S -> head) + { + void *ret, *r2; + + ret = S -> head -> data; + r2 = S -> head; + S -> head = S -> head -> next; + lw_free(r2); + return ret; + } + return NULL; +} + +void lw_stack_destroy(lw_stack_t S) +{ + void *d; + + while (d = lw_stack_pop(S)) + (S->freefn)(d); + lw_free(S); +} + +void *lw_stack_top(lw_stack_t S) +{ + if (S -> head) + return S -> head -> data; + return NULL; +} + +void lw_stack_push(lw_stack_t S, void *item) +{ + struct lw_stack_node_priv *t; + + t = lw_alloc(sizeof(struct lw_stack_node_priv)); + t -> next = S -> head; + S -> head = t; + t -> data = item; +} diff -r 591d01b343b9 -r c15cca3ae6a2 lwlib/lw_stack.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lwlib/lw_stack.h Sun Feb 28 05:01:31 2010 +0000 @@ -0,0 +1,53 @@ +/* +lw_stack.h + +Copyright © 2010 William Astle + +This file is part of LWTOOLS. + +LWTOOLS is free software: you can redistribute it and/or modify it under the +terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see . +*/ + +#ifndef ___lw_stack_h_seen___ +#define ___lw_stack_h_seen___ + + +#ifdef ___lw_stack_c_seen___ + +struct lw_stack_node_priv +{ + void *data; + struct lw_stack_node_priv *next; +}; + +struct lw_stack_priv +{ + struct lw_stack_node_priv *head; + void (*freefn)(void *d); +}; + +typedef struct lw_stack_priv * lw_stack_t; + +#else /* def ___lw_stack_c_seen___ */ + +typedef void * lw_stack_t; +extern lw_stack_t lw_stack_create(void (*freefn)(void *d)); +extern void lw_stack_destroy(lw_stack_t S); +extern void *lw_stack_top(lw_stack_t S); +extern void *lw_stack_pop(lw_stack_t S); +extern void lw_stack_push(lw_stack_t S, void *item); + +#endif /* def ___lw_stack_c_seen___ */ + +#endif /* ___lw_stack_h_seen___ */ diff -r 591d01b343b9 -r c15cca3ae6a2 lwlib/lw_string.c --- a/lwlib/lw_string.c Sat Feb 13 06:08:26 2010 +0000 +++ b/lwlib/lw_string.c Sun Feb 28 05:01:31 2010 +0000 @@ -40,6 +40,21 @@ return r; } +char *lw_strndup(const char *s, int len) +{ + char *r; + int sl; + + sl = strlen(s); + if (sl > len) + sl = len; + + r = lw_alloc(sl + 1); + memmove(r, s, sl); + r[sl] = '\0'; + return r; +} + char *lw_token(const char *s, int sep, const char **ap) { const char *p; diff -r 591d01b343b9 -r c15cca3ae6a2 lwlib/lw_string.h --- a/lwlib/lw_string.h Sat Feb 13 06:08:26 2010 +0000 +++ b/lwlib/lw_string.h Sun Feb 28 05:01:31 2010 +0000 @@ -28,6 +28,7 @@ #else /* def ___lw_string_c_seen___ */ extern char *lw_strdup(const char *s); +extern char *lw_strndup(const char *s, int len); extern char *lw_token(const char *s, int sep, const char **ap); #endif /* def ___lw_string_c_seen___ */ diff -r 591d01b343b9 -r c15cca3ae6a2 m4/gnulib-cache.m4 --- a/m4/gnulib-cache.m4 Sat Feb 13 06:08:26 2010 +0000 +++ b/m4/gnulib-cache.m4 Sun Feb 28 05:01:31 2010 +0000 @@ -15,12 +15,13 @@ # Specification in the form of a command-line invocation: -# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=. --no-libtool --macro-prefix=gl argp +# gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=. --no-libtool --macro-prefix=gl argp vasprintf # Specification in the form of a few gnulib-tool.m4 macro invocations: gl_LOCAL_DIR([]) gl_MODULES([ argp + vasprintf ]) gl_AVOID([]) gl_SOURCE_BASE([lib])