271 lines
4.0 KiB
C
271 lines
4.0 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sysexits.h>
|
|
#include <unistd.h>
|
|
|
|
const char *tokens[]={
|
|
/*80*/ " END ",
|
|
" FOR ",
|
|
" NEXT ",
|
|
" DATA ",
|
|
" INPUT ",
|
|
" DEL ",
|
|
" DIM ",
|
|
" READ ",
|
|
" GR ",
|
|
" TEXT ",
|
|
" PR# ",
|
|
" IN# ",
|
|
" CALL ",
|
|
" PLOT ",
|
|
" HLIN ",
|
|
" VLIN ",
|
|
" HGR2 ",
|
|
" HGR ",
|
|
" HCOLOR= ",
|
|
" HPLOT ",
|
|
" DRAW ",
|
|
" XDRAW ",
|
|
" HTAB ",
|
|
" HOME ",
|
|
" ROT= ",
|
|
" SCALE= ",
|
|
" SHLOAD ",
|
|
" TRACE ",
|
|
" NOTRACE ",
|
|
" NORMAL ",
|
|
" INVERSE ",
|
|
" FLASH ",
|
|
" COLOR= ",
|
|
" POP ",
|
|
" VTAB ",
|
|
" HIMEM: ",
|
|
" LOMEM: ",
|
|
" ONERR ",
|
|
" RESUME ",
|
|
" RECALL ",
|
|
" STORE ",
|
|
" SPEED= ",
|
|
" LET ",
|
|
" GOTO ",
|
|
" RUN ",
|
|
" IF ",
|
|
" RESTORE ",
|
|
" & ",
|
|
/*B0*/ " GOSUB ",
|
|
" RETURN ",
|
|
" REM ",
|
|
" STOP ",
|
|
" ON ",
|
|
" WAIT ",
|
|
" LOAD ",
|
|
" SAVE ",
|
|
" DEF ",
|
|
" POKE ",
|
|
" PRINT ",
|
|
" CONT ",
|
|
" LIST ",
|
|
" CLEAR ",
|
|
" GET ",
|
|
" NEW ",
|
|
" TAB( ",
|
|
" TO ",
|
|
" FN ",
|
|
" SPC( ",
|
|
" THEN ",
|
|
" AT ",
|
|
" NOT ",
|
|
" STEP ",
|
|
" + ",
|
|
" - ",
|
|
" * ",
|
|
" / ",
|
|
" ^ ",
|
|
" AND ",
|
|
" OR ",
|
|
" > ",
|
|
" = ",
|
|
" < ",
|
|
" SGN ",
|
|
" INT ",
|
|
" ABS ",
|
|
" USR ",
|
|
" FRE ",
|
|
" SCRN( ",
|
|
" PDL ",
|
|
" POS ",
|
|
" SQR ",
|
|
" RND ",
|
|
" LOG ",
|
|
" EXP ",
|
|
" COS ",
|
|
" SIN ",
|
|
" TAN ",
|
|
" ATN ",
|
|
" PEEK ",
|
|
" LEN ",
|
|
" STR$ ",
|
|
" VAL ",
|
|
" ASC ",
|
|
" CHR$ ",
|
|
" LEFT$ ",
|
|
" RIGHT$ ",
|
|
" MID$ ",
|
|
/*EB*/ " ?? ", /* I'm pretty sure these aren't valid ... */
|
|
" ?? ",
|
|
" ?? ",
|
|
" ?? ",
|
|
" ?? ",
|
|
" ?? ",
|
|
" ?? ",
|
|
" ?? ",
|
|
" ?? ",
|
|
" ?? ",
|
|
" ?? ",
|
|
" ?? ",
|
|
" ?? ",
|
|
" ?? ",
|
|
" ?? ",
|
|
" ?? ",
|
|
" ?? ",
|
|
" ?? ",
|
|
" ?? ",
|
|
" ?? ",
|
|
};
|
|
|
|
/*
|
|
|
|
This is where the actual work is done.
|
|
An Applesoft file is laid out like so:
|
|
|
|
word word [variable # of bytes] <0x00> <-eol marker
|
|
| | |
|
|
| | |if >0x7F, it is a token, otherwise, it's a printed
|
|
| |
|
|
| |The line # (65535 max)
|
|
|
|
|
| This is an offset to the next line (?) if 0, the file is done.
|
|
|
|
repeating over and over...
|
|
|
|
*/
|
|
|
|
|
|
int translate(FILE *f, FILE *out)
|
|
{
|
|
for(;;)
|
|
{
|
|
int x;
|
|
//offset to next line
|
|
x = fgetc(f) | (fgetc(f) << 8);
|
|
if (feof(f))
|
|
{
|
|
fprintf(stderr, "Unexpected eof.\n");
|
|
return EX_DATAERR;
|
|
}
|
|
|
|
// last line.
|
|
if (x == 0) break;
|
|
|
|
// line number.
|
|
x = fgetc(f) | (fgetc(f) << 8);
|
|
if (feof(f))
|
|
{
|
|
fprintf(stderr, "Unexpected eof.\n");
|
|
return EX_DATAERR;
|
|
}
|
|
|
|
fprintf(out, "% 5d: ", x);
|
|
|
|
for (;;)
|
|
{
|
|
x = fgetc(f);
|
|
if (x == 0) break;
|
|
|
|
if (x < 0)
|
|
{
|
|
fprintf(stderr, "Unexpected eof.\n");
|
|
return EX_DATAERR;
|
|
}
|
|
if (x > 0x7f)
|
|
fputs(tokens[x & 0x7f], out);
|
|
else if (x > 0x1f) fputc(x, out);
|
|
|
|
}
|
|
|
|
fprintf(out, "\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
void usage(void)
|
|
{
|
|
fputs("Usage: blist [-o output file] input file\n",stdout);
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
int c, rv;
|
|
const char *outfile = NULL;
|
|
FILE *input = stdin;
|
|
FILE *output = stdout;
|
|
|
|
while ((c = getopt(argc, argv, "ho:")) != -1)
|
|
{
|
|
switch(c)
|
|
{
|
|
case 'o':
|
|
outfile = optarg;
|
|
break;
|
|
case 'h':
|
|
usage();
|
|
return 0;
|
|
default:
|
|
usage();
|
|
return EX_USAGE;
|
|
}
|
|
}
|
|
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
|
|
switch (argc)
|
|
{
|
|
case 0:
|
|
break;
|
|
case 1:
|
|
input = fopen(argv[0], "r");
|
|
if (!input)
|
|
{
|
|
perror(argv[0]);
|
|
return EX_NOINPUT;
|
|
}
|
|
break;
|
|
default:
|
|
usage();
|
|
return EX_USAGE;
|
|
}
|
|
|
|
if (outfile && strcmp(outfile, "-")) {
|
|
output = fopen(outfile, "w");
|
|
if (!output)
|
|
{
|
|
perror(outfile);
|
|
if (input != stdin) fclose(input);
|
|
return EX_CANTCREAT;
|
|
}
|
|
}
|
|
|
|
rv = translate(input, output);
|
|
|
|
if (input != stdin) fclose(input);
|
|
if (output != stdout) fclose(output);
|
|
|
|
return rv;
|
|
}
|
|
|