changeset 406:4411a6123716

Add "basic" output format Add "basic" output format. This outputs the code in the form of a Basic program that installs the assembled output. If an execution address is provided to the END pseudo operation, it will transfer control there using the Basic EXEC command. Thanks to Tim Lindner <tlindner@macmess.org> for the original patch. I used it mostly as is except for a couple of minor fixes for coding style and removing a variable declaration from inside a for() statement for portability reasons.
author William Astle <lost@l-w.ca>
date Thu, 03 Mar 2016 21:04:39 -0700
parents 4c8925f97eb5
children c501b3ce39c8
files lwasm/lwasm.h lwasm/main.c lwasm/output.c lwasm/pseudo.c
diffstat 4 files changed, 107 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/lwasm/lwasm.h	Thu Mar 03 20:52:15 2016 -0700
+++ b/lwasm/lwasm.h	Thu Mar 03 21:04:39 2016 -0700
@@ -54,6 +54,7 @@
 enum lwasm_output_e
 {
 	OUTPUT_DECB = 0,	// DECB multirecord format
+	OUTPUT_BASIC,		// Color BASIC program
 	OUTPUT_RAW,			// raw sequence of bytes
 	OUTPUT_OBJ,			// proprietary object file format
 	OUTPUT_RAWREL,		// raw bytes where ORG causes a SEEK in the file
--- a/lwasm/main.c	Thu Mar 03 20:52:15 2016 -0700
+++ b/lwasm/main.c	Thu Mar 03 21:04:39 2016 -0700
@@ -44,7 +44,7 @@
 {
 	{ "output",		'o',	"FILE",		0,							"Output to FILE"},
 	{ "debug",		'd',	"LEVEL",	lw_cmdline_opt_optional,	"Set debug mode"},
-	{ "format",		'f',	"TYPE",		0,							"Select output format: decb, raw, obj, os9"},
+	{ "format",		'f',	"TYPE",		0,							"Select output format: decb, basic, raw, obj, os9"},
 	{ "list",		'l',	"FILE",		lw_cmdline_opt_optional,	"Generate list [to FILE]"},
 	{ "symbols",	's',	0,			lw_cmdline_opt_optional,	"Generate symbol list in listing, no effect without --list"},
 	{ "symbols-nolocals", 0x103,	0,	lw_cmdline_opt_optional,	"Same as --symbols but with local labels ignored"},
@@ -175,6 +175,8 @@
 	case 'f':
 		if (!strcasecmp(arg, "decb"))
 			as -> output_format = OUTPUT_DECB;
+		else if (strcasecmp(arg, "basic"))
+			as -> output_format = OUTPUT_BASIC;
 		else if (!strcasecmp(arg, "raw"))
 			as -> output_format = OUTPUT_RAW;
 		else if (!strcasecmp(arg, "rawrel"))
--- a/lwasm/output.c	Thu Mar 03 20:52:15 2016 -0700
+++ b/lwasm/output.c	Thu Mar 03 21:04:39 2016 -0700
@@ -35,6 +35,7 @@
 
 void write_code_raw(asmstate_t *as, FILE *of);
 void write_code_decb(asmstate_t *as, FILE *of);
+void write_code_BASIC(asmstate_t *as, FILE *of);
 void write_code_rawrel(asmstate_t *as, FILE *of);
 void write_code_obj(asmstate_t *as, FILE *of);
 void write_code_os9(asmstate_t *as, FILE *of);
@@ -73,6 +74,10 @@
 	case OUTPUT_DECB:
 		write_code_decb(as, of);
 		break;
+	
+	case OUTPUT_BASIC:
+		write_code_BASIC(as, of);
+		break;
 		
 	case OUTPUT_RAWREL:
 		write_code_rawrel(as, of);
@@ -108,6 +113,103 @@
 	fclose(of);
 }
 
+int write_code_BASIC_fprintf(FILE *of, int linelength, int *linenumber, int value)
+{
+	if (linelength > 247)
+	{
+		fprintf(of, "\n");
+		linelength = fprintf(of, "%d DATA ", *linenumber);
+		*linenumber += 10;
+	}
+	else
+	{
+		linelength += fprintf(of, ",");
+	}
+	linelength += fprintf(of, "%d", value);
+
+	return linelength;
+}
+
+void write_code_BASIC(asmstate_t *as, FILE *of)
+{
+	line_t *cl;
+	line_t *startblock = as -> line_head;
+	line_t *endblock;
+	int linenumber, linelength, startaddress, lastaddress, address;
+	int outidx;
+	
+	fprintf(of, "10 READ A,B\n");
+	fprintf(of, "20 IF A=-1 THEN 70\n");
+	fprintf(of, "30 FOR C = A TO B\n");
+	fprintf(of, "40 READ D:POKE C,D\n");
+	fprintf(of, "50 NEXT C\n");
+	fprintf(of, "60 GOTO 10\n");
+	
+	if (as -> execaddr == 0)
+	{
+		fprintf(of, "70 END");
+	}
+	else
+	{
+		fprintf(of, "70 EXEC %d", as -> execaddr);
+	}
+	
+	linenumber = 80;
+	linelength = 255;
+	
+	while(startblock)
+	{
+		startaddress = -1;
+		endblock = NULL;
+		
+		for (cl = startblock; cl; cl = cl -> next)
+		{
+			if (cl -> outputl < 0)
+				continue;
+		
+			address = lw_expr_intval(cl -> addr);
+		
+			if (startaddress == -1)
+			{
+				startaddress = address;
+				lastaddress = address + cl -> outputl - 1;
+			}
+			else
+			{
+				if (lastaddress != address - 1)
+				{
+					endblock = cl;
+					break;
+				}
+				
+				lastaddress += cl -> outputl;
+			}
+		}
+	
+		linelength = write_code_BASIC_fprintf(of, linelength, &linenumber, startaddress);
+		linelength = write_code_BASIC_fprintf(of, linelength, &linenumber, lastaddress);
+	
+		for (cl = startblock; cl != endblock; cl = cl -> next)
+		{
+			if (cl -> outputl < 0)
+				continue;
+		
+			for (outidx=0; outidx<cl -> outputl; outidx++)
+			{
+				linelength = write_code_BASIC_fprintf(of, linelength, &linenumber, cl -> output[outidx]);
+			}
+		}
+	
+		startblock = cl;
+	}
+	
+	linelength = write_code_BASIC_fprintf(of, linelength, &linenumber, -1);
+	linelength = write_code_BASIC_fprintf(of, linelength, &linenumber, -1);
+	
+	fprintf(of, "\n");
+}
+
+
 /*
 rawrel output treats an ORG directive as an offset from the start of the
 file. Undefined results will occur if an ORG directive moves the output
--- a/lwasm/pseudo.c	Thu Mar 03 20:52:15 2016 -0700
+++ b/lwasm/pseudo.c	Thu Mar 03 21:04:39 2016 -0700
@@ -102,7 +102,7 @@
 
 	as->endseen = 1;
 
-	if (as -> output_format != OUTPUT_DECB)
+	if ((as -> output_format != OUTPUT_DECB) && (as -> output_format != OUTPUT_BASIC))
 	{
 		skip_operand(p);
 		return;