Mercurial > hg > index.cgi
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