diff lwlink/readfiles.c @ 171:d610b8aef91b

Added LWAR skeleton
author lost
date Sun, 01 Mar 2009 19:37:03 +0000
parents 106c2fe3c9d9
children 0395e6fd67e9
line wrap: on
line diff
--- a/lwlink/readfiles.c	Sun Mar 01 00:53:21 2009 +0000
+++ b/lwlink/readfiles.c	Sun Mar 01 19:37:03 2009 +0000
@@ -30,17 +30,38 @@
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 
 #include "lwlink.h"
 #include "util.h"
 
 void read_lwobj16v0(fileinfo_t *fn);
+void read_lwar1v(fileinfo_t *fn);
 
 /*
 The logic of reading the entire file into memory is simple. All the symbol
 names in the file are NUL terminated strings and can be used directly without
 making additional copies.
 */
+void read_file(fileinfo_t *fn)
+{
+	if (!memcmp(fn -> filedata, "LWOBJ16", 8))
+		{
+			// read v0 LWOBJ16 file
+			read_lwobj16v0(fn);
+		}
+		else if (!memcmp(fn -> filedata, "LWAR1V", 6))
+		{
+			// archive file
+			read_lwar1v(fn);
+		}
+		else
+		{
+			fprintf(stderr, "%s: unknown file format\n", fn -> filename);
+			exit(1);
+		}
+}
+
 void read_files(void)
 {
 	int i;
@@ -73,16 +94,7 @@
 			
 		fclose(f);
 		
-		if (!memcmp(inputfiles[i] -> filedata, "LWOBJ16", 8))
-		{
-			// read v0 LWOBJ16 file
-			read_lwobj16v0(inputfiles[i]);
-		}
-		else
-		{
-			fprintf(stderr, "%s: unknown file format\n", inputfiles[i] -> filename);
-			exit(1);
-		}
+		read_file(inputfiles[i]);
 	}
 }
 
@@ -107,6 +119,7 @@
 // the function below can be switched to dealing with data coming from a
 // source other than an in-memory byte pool by adjusting the input data
 // in "fn" and the above two macros
+
 void read_lwobj16v0(fileinfo_t *fn)
 {
 	unsigned char *fp;
@@ -302,3 +315,64 @@
 		}
 	}
 }
+
+/*
+Read an archive file - this will create a "sub" record and farm out the
+parsing of the sub files to the regular file parsers
+
+The archive file format consists of the 6 byte magic number followed by a
+series of records as follows:
+
+- NUL terminated file name
+- 32 bit file length in big endian order
+- the file data
+
+An empty file name indicates the end of the file.
+
+*/
+void read_lwar1v(fileinfo_t *fn)
+{
+	unsigned long cc = 6;
+	unsigned long flen;
+	unsigned long l;
+	for (;;)
+	{
+		if (cc >= fn -> filesize || !(fn -> filedata[cc]))
+			return;
+
+		for (l = cc; cc < fn -> filesize && fn -> filedata[cc]; l++)
+			/* do nothing */ ;
+
+		if (cc >= fn -> filesize)
+		{
+			fprintf(stderr, "Malformed archive file %s.\n", fn -> filename);
+			exit(1);
+		}
+
+		if (cc + 4 > fn -> filesize)
+			return;
+
+		flen = (fn -> filedata[cc++] << 24) | (fn -> filedata[cc++] << 16)
+			| (fn -> filedata[cc++] << 8) | (fn -> filedata[cc]);
+
+		if (flen == 0)
+			return;
+		
+		if (cc + flen > fn -> filesize)
+		{
+			fprintf(stderr, "Malformed archive file %s.\n", fn -> filename);
+			exit(1);
+		}
+		
+		// add the "sub" input file
+		fn -> subs = lw_realloc(fn -> subs, sizeof(fileinfo_t *) * (fn -> nsubs + 1));
+		fn -> subs[fn -> nsubs] = lw_malloc(sizeof(fileinfo_t));
+		memset(fn -> subs[fn -> nsubs], 0, sizeof(fileinfo_t));
+		fn -> subs[fn -> nsubs] -> filedata = fn -> filedata + cc;
+		fn -> subs[fn -> nsubs] -> filesize = flen;
+		fn -> subs[fn -> nsubs] -> filename = lw_strdup(fn -> filedata + l);
+		fn -> subs[fn -> nsubs] -> parent = fn;
+		read_file(fn -> subs[fn -> nsubs]);
+		fn -> nsubs++;
+	}
+}