diff lwasm/output.c @ 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 ade217fd76a5
children 7f538053492c
line wrap: on
line diff
--- 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