changeset 329:c15cca3ae6a2

Created first pass of input layer
author lost
date Sun, 28 Feb 2010 05:01:31 +0000
parents 591d01b343b9
children 81c005b82775
files lwasm/Makefile.am lwasm/input.c lwasm/lwasm.h lwasm/main.c lwlib/Makefile.am lwlib/lw_error.c lwlib/lw_error.h lwlib/lw_stack.c lwlib/lw_stack.h lwlib/lw_string.c lwlib/lw_string.h m4/gnulib-cache.m4
diffstat 12 files changed, 523 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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");
+	}
 }
--- 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 <lw_stringlist.h>
+#include <lw_stack.h>
 
 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___ */
--- 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 <stdio.h>
 #include <stdlib.h>
 
+#include <lw_alloc.h>
 #include <lw_string.h>
 #include <lw_stringlist.h>
 
@@ -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);
--- 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
--- /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 <http://www.gnu.org/licenses/>.
+*/
+
+#include <config.h>
+
+#define ___lw_error_c_seen___
+#include <lw_error.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+void lw_error(const char *fmt, ...)
+{
+	va_list args;
+	va_start(args, fmt);
+	vfprintf(stderr, fmt, args);
+	va_end(args);
+	exit(1);
+}
--- /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 <http://www.gnu.org/licenses/>.
+*/
+
+#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___ */
--- /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 <http://www.gnu.org/licenses/>.
+*/
+
+#include <config.h>
+
+#define ___lw_stack_c_seen___
+#include <lw_stack.h>
+#include <lw_alloc.h>
+
+/* 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;
+}
--- /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 <http://www.gnu.org/licenses/>.
+*/
+
+#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___ */
--- 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;
--- 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___ */
--- 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])