diff lwlink/link.c @ 148:08fb11004df9

Initial pass at OS9 module support for lwlink
author lost@l-w.ca
date Fri, 26 Aug 2011 23:26:00 -0600
parents fdc11ef4115b
children 729a9c70934e
line wrap: on
line diff
--- a/lwlink/link.c	Thu Aug 25 22:29:58 2011 -0600
+++ b/lwlink/link.c	Fri Aug 26 23:26:00 2011 -0600
@@ -30,6 +30,8 @@
 #include "expr.h"
 #include "lwlink.h"
 
+void check_os9(void);
+
 struct section_list *sectlist = NULL;
 int nsects = 0;
 static int nforced = 0;
@@ -390,6 +392,9 @@
 	
 	if (symerr)
 		exit(1);
+	
+	if (outformat == OUTPUT_OS9)
+		check_os9();	
 }
 
 /*
@@ -460,3 +465,106 @@
 		fprintf(stderr, "Warning: %s (%d) does not resolve any symbols\n", inputfiles[fn] -> filename, fn);
 	}
 }
+void find_section_by_name_once_aux(char *name, fileinfo_t *fn, section_t **rval, int *found);
+void find_section_by_name_once_aux(char *name, fileinfo_t *fn, section_t **rval, int *found)
+{
+	int sn;
+	
+	if (fn -> forced == 0)
+		return;
+
+	for (sn = 0; sn < fn -> nsections; sn++)
+	{
+		if (!strcmp(name, (char *)(fn -> sections[sn].name)))
+		{
+			(*found)++;
+			*rval = &(fn -> sections[sn]);
+		}
+	}
+	for (sn = 0; sn < fn -> nsubs; sn++)
+	{
+		find_section_by_name_once_aux(name, fn -> subs[sn], rval, found);
+	}
+}
+
+section_t *find_section_by_name_once(char *name)
+{
+	int fn;
+	int found = 0;
+	section_t *rval = NULL;
+	
+	for (fn = 0; fn < ninputfiles; fn++)
+	{
+		find_section_by_name_once_aux(name, inputfiles[fn], &rval, &found);
+	}
+	if (found != 1)
+	{
+		rval = NULL;
+		fprintf(stderr, "Warning: multiple instances of section %s found; ignoring all of them which is probably not what you want\n", name);
+	}
+	return rval;
+}
+
+void check_os9(void)
+{
+	section_t *s;
+	symtab_t *sym;
+	
+	s = find_section_by_name_once("__os9");
+	linkscript.name = outfile;
+	
+	if (!s)
+	{
+		// use defaults if not found
+		return;
+	}	
+
+	// this section is special
+	// several symbols may be defined as LOCAL symbols:
+	// type: module type
+	// lang: module language
+	// attr: module attributes
+	// rev: module revision
+	//
+	// the symbols are not case sensitive
+	//
+	// any unrecognized symbols are ignored
+	
+	// the contents of the actual data to the first NUL
+	// is assumed to be the module name unless it is an empty string
+	if (s -> codesize > 0 && (s -> flags & SECTION_BSS) == 0 && s -> code[0] != 0)
+	{
+		linkscript.name = (char *)(s -> code);
+	}
+	
+	for (sym = s -> localsyms; s; sym = sym -> next)
+	{
+		char *sm = (char *)(sym -> sym);
+		if (!strcasecmp(sm, "type"))
+		{
+			linkscript.modtype = sym -> offset;
+		}
+		else if (!strcasecmp(sm, "lang"))
+		{
+			linkscript.modlang = sym -> offset;
+		}
+		else if (!strcasecmp(sm, "attr"))
+		{
+			linkscript.modlang = sym -> offset;
+		}
+		else if (!strcasecmp(sm, "rev"))
+		{
+			linkscript.modrev = sym -> offset;
+		}
+	}
+	if (linkscript.modtype > 15)
+		linkscript.modtype = linkscript.modtype >> 4;
+	
+	if (linkscript.modattr > 15)
+		linkscript.modattr = linkscript.modattr >> 4;
+	
+	linkscript.modlang &= 15;
+	linkscript.modtype &= 15;
+	linkscript.modrev &= 15;
+	linkscript.modattr &= 15;
+}