# HG changeset patch # User William Astle # Date 1457064279 25200 # Node ID 4411a612371698bc0a7ffbca056e635c87ca9550 # Parent 4c8925f97eb53f6ea167ed5db824fccae9704d29 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 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. diff -r 4c8925f97eb5 -r 4411a6123716 lwasm/lwasm.h --- 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 diff -r 4c8925f97eb5 -r 4411a6123716 lwasm/main.c --- 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")) diff -r 4c8925f97eb5 -r 4411a6123716 lwasm/output.c --- 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 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 diff -r 4c8925f97eb5 -r 4411a6123716 lwasm/pseudo.c --- 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;