mirror of
https://github.com/deater/dos33fsprogs.git
synced 2024-12-25 20:30:31 +00:00
Add "asoft_compact" which tries to compact applesoft BASIC programs
currently only drops "LET" and converts "THEN GOTO" to "THEN"
This commit is contained in:
parent
e5ea444c99
commit
c584e529b3
10
Makefile
10
Makefile
@ -4,9 +4,14 @@ LFLAGS =
|
||||
|
||||
all: dos33 asoft_detoken mkdos33fs make_b tokenize_asoft \
|
||||
dos33_text2ascii integer_detoken char2hex pcx2hgr \
|
||||
asoft_presenter shape_table
|
||||
asoft_presenter shape_table asoft_compact
|
||||
|
||||
|
||||
asoft_compact: asoft_compact.o
|
||||
$(CC) $(LFLAGS) -o asoft_compact asoft_compact.o
|
||||
|
||||
asoft_compact.o: asoft_compact.c
|
||||
$(CC) $(CFLAGS) -c asoft_compact.c
|
||||
|
||||
asoft_detoken: asoft_detoken.o
|
||||
$(CC) $(LFLAGS) -o asoft_detoken asoft_detoken.o
|
||||
@ -82,7 +87,8 @@ install:
|
||||
clean:
|
||||
rm -f *~ *.o asoft_detoken dos33 make_b mkdos33fs \
|
||||
tokenize_asoft dos33_text2ascii integer_detoken \
|
||||
char2hex pcx2hgr asoft_presenter shape_table
|
||||
char2hex pcx2hgr asoft_presenter shape_table \
|
||||
asoft_compact
|
||||
cd tests && make clean
|
||||
cd presenter_demo && make clean
|
||||
|
||||
|
406
asoft_compact.c
Normal file
406
asoft_compact.c
Normal file
@ -0,0 +1,406 @@
|
||||
/* asoft_compact */
|
||||
/* make applesoft code as compact as possible */
|
||||
/* + Renumber lines to be as short as possible */
|
||||
/* + Remove extraneous "LET" commands */
|
||||
/* + Transform "THEN GOTO" to "THEN" */
|
||||
/* + Make variables as short as possible */
|
||||
/* + Remove REM statements */
|
||||
/* + Combine lines right up to 255 char limit */
|
||||
|
||||
/* Example */
|
||||
/* demo.bas = 22,219 bytes */
|
||||
/* tokenized = 17,407 bytes */
|
||||
/* compacted = */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h> /* strlen() */
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "version.h"
|
||||
|
||||
#define LOW(_x) ((_x)&0xff)
|
||||
#define HIGH(_x) (((_x)>>8)&0xff)
|
||||
|
||||
|
||||
/* Starting at 0x80 */
|
||||
char applesoft_tokens[][8]={
|
||||
/* 80 */ "END","FOR","NEXT","DATA","INPUT","DEL","DIM","READ",
|
||||
/* 88 */ "GR","TEXT","PR #","IN #","CALL","PLOT","HLIN","VLIN",
|
||||
/* 90 */ "HGR2","HGR","HCOLOR=","HPLOT","DRAW","XDRAW","HTAB","HOME",
|
||||
/* 98 */ "ROT=","SCALE=","SHLOAD","TRACE","NOTRACE","NORMAL","INVERSE","FLASH",
|
||||
/* A0 */ "COLOR=","POP","VTAB ","HIMEM:","LOMEM:","ONERR","RESUME","RECALL",
|
||||
/* A8 */ "STORE","SPEED=","LET","GOTO","RUN","IF","RESTORE","&",
|
||||
/* B0 */ "GOSUB","RETURN","REM","STOP","ON","WAIT","LOAD","SAVE",
|
||||
/* B8 */ "DEF FN","POKE","PRINT","CONT","LIST","CLEAR","GET","NEW",
|
||||
/* C0 */ "TAB","TO","FN","SPC(","THEN","AT","NOT","STEP",
|
||||
/* C8 */ "+","-","*","/","^","AND","OR",">",
|
||||
/* D0 */ "=","<","SGN","INT","ABS","USR","FRE","SCRN (",
|
||||
/* D8 */ "PDL","POS","SQR","RND","LOG","EXP","COS","SIN",
|
||||
/* E0 */ "TAN","ATN","PEEK","LEN","STR$","VAL","ASC","CHR$",
|
||||
/* E8 */ "LEFT$","RIGHT$","MID$","","","","","",
|
||||
/* F0 */ "","","","","","","","",
|
||||
/* F8 */ "","","","","","(","(","("
|
||||
};
|
||||
|
||||
#define TOKEN_END 0
|
||||
#define TOKEN_FOR 1
|
||||
#define TOKEN_NEXT 2
|
||||
#define TOKEN_DATA 3
|
||||
#define TOKEN_INPUT 4
|
||||
#define TOKEN_DEL 5
|
||||
#define TOKEN_DIM 6
|
||||
#define TOKEN_READ 7
|
||||
#define TOKEN_GR 8
|
||||
#define TOKEN_TEXT 9
|
||||
#define TOKEN_PR 10
|
||||
#define TOKEN_IN 11
|
||||
#define TOKEN_CALL 12
|
||||
#define TOKEN_PLOT 13
|
||||
#define TOKEN_HLIN 14
|
||||
#define TOKEN_VLIN 15
|
||||
#define TOKEN_HGR2 16
|
||||
#define TOKEN_HGR 17
|
||||
#define TOKEN_HCOLOR 18
|
||||
#define TOKEN_HPLOT 19
|
||||
#define TOKEN_DRAW 20
|
||||
#define TOKEN_XDRAW 21
|
||||
#define TOKEN_HTAB 22
|
||||
#define TOKEN_HOME 23
|
||||
#define TOKEN_ROT 24
|
||||
#define TOKEN_SCALE 25
|
||||
#define TOKEN_SHLOAD 26
|
||||
#define TOKEN_TRACE 27
|
||||
#define TOKEN_NOTRACE 28
|
||||
#define TOKEN_NORMAL 29
|
||||
#define TOKEN_INVERSE 30
|
||||
#define TOKEN_FLASH 31
|
||||
#define TOKEN_COLOR 32
|
||||
#define TOKEN_POP 33
|
||||
#define TOKEN_VTAB 34
|
||||
#define TOKEN_HIMEM 35
|
||||
#define TOKEN_LOMEM 36
|
||||
#define TOKEN_ONERR 37
|
||||
#define TOKEN_RESUME 38
|
||||
#define TOKEN_RECALL 39
|
||||
#define TOKEN_STORE 40
|
||||
#define TOKEN_SPEED 41
|
||||
#define TOKEN_LET 42
|
||||
#define TOKEN_GOTO 43
|
||||
#define TOKEN_RUN 44
|
||||
#define TOKEN_IF 45
|
||||
#define TOKEN_RESTORE 46
|
||||
#define TOKEN_AMP 47
|
||||
#define TOKEN_GOSUB 48
|
||||
#define TOKEN_RETURN 49
|
||||
#define TOKEN_REM 50
|
||||
#define TOKEN_STOP 51
|
||||
#define TOKEN_ON 52
|
||||
#define TOKEN_WAIT 53
|
||||
#define TOKEN_LOAD 54
|
||||
#define TOKEN_SAVE 55
|
||||
#define TOKEN_DEFFN 56
|
||||
#define TOKEN_POKE 57
|
||||
#define TOKEN_PRINT 58
|
||||
#define TOKEN_CONT 59
|
||||
#define TOKEN_LIST 60
|
||||
#define TOKEN_CLEAR 61
|
||||
#define TOKEN_GET 62
|
||||
#define TOKEN_NEW 63
|
||||
#define TOKEN_TAB 64
|
||||
#define TOKEN_TO 65
|
||||
#define TOKEN_FN 66
|
||||
#define TOKEN_SPC 67
|
||||
#define TOKEN_THEN 68
|
||||
#define TOKEN_AT 69
|
||||
#define TOKEN_NO 70
|
||||
#define TOKEN_STEP 71
|
||||
#if 0
|
||||
/* C8 */ "+","-","*","/","^","AND","OR",">",
|
||||
/* D0 */ "=","<","SGN","INT","ABS","USR","FRE","SCRN (",
|
||||
/* D8 */ "PDL","POS","SQR","RND","LOG","EXP","COS","SIN",
|
||||
/* E0 */ "TAN","ATN","PEEK","LEN","STR$","VAL","ASC","CHR$",
|
||||
/* E8 */ "LEFT$","RIGHT$","MID$","","","","","",
|
||||
#endif
|
||||
|
||||
static void color_red(void) {
|
||||
fprintf(stderr,"%c[1;31;40m",27);
|
||||
}
|
||||
|
||||
static void color_green(void) {
|
||||
fprintf(stderr,"%c[1;32;40m",27);
|
||||
}
|
||||
|
||||
static void color_cyan(void) {
|
||||
fprintf(stderr,"%c[1;36;40m",27);
|
||||
}
|
||||
|
||||
static void color_yellow(void) {
|
||||
fprintf(stderr,"%c[1;33;40m",27);
|
||||
}
|
||||
|
||||
static void color_normal(void) {
|
||||
fprintf(stderr,"%c[0m",27);
|
||||
}
|
||||
|
||||
static int linenums[65536]; /* lazy */
|
||||
static int output[65536];
|
||||
|
||||
|
||||
static void print_int(int value, int *offset) {
|
||||
|
||||
unsigned char buffer[16];
|
||||
int pointer=15;
|
||||
int r,q;
|
||||
|
||||
q=value;
|
||||
|
||||
while(1) {
|
||||
r=q%10;
|
||||
q/=10;
|
||||
|
||||
buffer[pointer]=r+'0';
|
||||
|
||||
if (q==0) break;
|
||||
|
||||
pointer--;
|
||||
}
|
||||
|
||||
while(pointer<16) {
|
||||
output[*offset]=buffer[pointer];
|
||||
pointer++;
|
||||
(*offset)++;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
int ch1;
|
||||
int size1,size2;
|
||||
int line1,line2;
|
||||
int link1,link2,link;
|
||||
int debug=1;
|
||||
int token,last_token=0;
|
||||
int line_no=0;
|
||||
int i;
|
||||
FILE *fff;
|
||||
|
||||
int offset,link_offset,line_offset;
|
||||
|
||||
if (argc<2) {
|
||||
fprintf(stderr,"Usage: %s FILENAME -1 -2 -3 -4\n",argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fff=fopen(argv[1],"r");
|
||||
if (fff==NULL) {
|
||||
fprintf(stderr,"Error opening %s\n",argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/* read size, first two bytes */
|
||||
size1=fgetc(fff);
|
||||
size2=fgetc(fff);
|
||||
|
||||
if (debug) fprintf(stderr,"File size: %x %x\n",size1,size2);
|
||||
|
||||
while(!feof(fff)) {
|
||||
|
||||
/* link points to the next line */
|
||||
link1=fgetc(fff);
|
||||
link2=fgetc(fff);
|
||||
link=(link1<<8)|link2;
|
||||
/* link==0 indicates EOF */
|
||||
if (link==0) goto the_end;
|
||||
|
||||
/* line number is little endian 16-bit value */
|
||||
line1=fgetc(fff);
|
||||
line2=fgetc(fff);
|
||||
if (feof(fff)) goto the_end;
|
||||
|
||||
color_red();
|
||||
fprintf(stderr,"%4d ",((line2)<<8)+line1);
|
||||
color_normal();
|
||||
|
||||
/* repeat until EOL character (0) */
|
||||
while(1) {
|
||||
|
||||
ch1=fgetc(fff);
|
||||
after_read:
|
||||
if (ch1==0) break;
|
||||
|
||||
/* if > 0x80 it's a token */
|
||||
if (ch1>=0x80) {
|
||||
color_green();
|
||||
fprintf(stderr,"%s",applesoft_tokens[ch1-0x80]);
|
||||
color_normal();
|
||||
last_token=ch1&0x7f;
|
||||
}
|
||||
|
||||
|
||||
/* otherwise it is an ascii char */
|
||||
else {
|
||||
if (ch1<0x20) {
|
||||
color_cyan();
|
||||
fprintf(stderr,"%d",ch1);
|
||||
color_normal();
|
||||
}
|
||||
|
||||
if ((ch1>='0') && (ch1<='9')) {
|
||||
if ((last_token==TOKEN_GOTO) ||
|
||||
(last_token==TOKEN_GOSUB) ||
|
||||
(last_token==TOKEN_THEN)) {
|
||||
|
||||
line_no=ch1-'0';
|
||||
|
||||
while(1) {
|
||||
ch1=fgetc(fff);
|
||||
if ((ch1<'0') || (ch1>'9')) break;
|
||||
line_no*=10;
|
||||
line_no+=(ch1-'0');
|
||||
}
|
||||
|
||||
color_yellow();
|
||||
fprintf(stderr,"%d",line_no);
|
||||
color_normal();
|
||||
linenums[line_no]++;
|
||||
goto after_read;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fputc(ch1,stderr);
|
||||
}
|
||||
|
||||
}
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
the_end:;
|
||||
|
||||
fprintf(stderr,"Used Line Numbers:\n");
|
||||
for(i=0;i<65536;i++) {
|
||||
if(linenums[i]) fprintf(stderr,"\t%d\t%d\n",i,linenums[i]);
|
||||
}
|
||||
|
||||
rewind(fff);
|
||||
|
||||
/*********************/
|
||||
/* Create new output */
|
||||
/*********************/
|
||||
|
||||
/* skip size bytes */
|
||||
offset=2;
|
||||
size1=fgetc(fff);
|
||||
size2=fgetc(fff);
|
||||
|
||||
|
||||
while(!feof(fff)) {
|
||||
|
||||
link_offset=offset;
|
||||
|
||||
link1=fgetc(fff);
|
||||
link2=fgetc(fff);
|
||||
link=(link1<<8)|link2;
|
||||
|
||||
output[offset]=link1;
|
||||
output[offset+1]=link2;
|
||||
|
||||
/* link==0 indicates end */
|
||||
if (link==0) break;
|
||||
offset+=2;
|
||||
|
||||
|
||||
/* line number is little endian 16-bit value */
|
||||
|
||||
line_offset=offset;
|
||||
|
||||
line1=fgetc(fff);
|
||||
line2=fgetc(fff);
|
||||
|
||||
output[offset]=line1;
|
||||
output[offset+1]=line2;
|
||||
|
||||
offset+=2;
|
||||
|
||||
if (feof(fff)) break;
|
||||
|
||||
/* repeat until EOL character (0) */
|
||||
while(1) {
|
||||
|
||||
ch1=fgetc(fff);
|
||||
after_read2:
|
||||
if (ch1==0) break;
|
||||
|
||||
/* if > 0x80 it's a token */
|
||||
if (ch1>=0x80) {
|
||||
|
||||
token=ch1&0x7f;
|
||||
|
||||
if (token==TOKEN_LET) {
|
||||
/* Skip superfluous LET */
|
||||
}
|
||||
else if ((token==TOKEN_GOTO) && (last_token==TOKEN_THEN)) {
|
||||
/* Skip superfluous GOTO if THEN GOTO */
|
||||
|
||||
}
|
||||
else {
|
||||
output[offset]=ch1;
|
||||
offset++;
|
||||
}
|
||||
last_token=token;
|
||||
}
|
||||
|
||||
|
||||
/* otherwise it is an ascii char */
|
||||
else {
|
||||
|
||||
if ((ch1>='0') && (ch1<='9')) {
|
||||
if ((last_token==TOKEN_GOTO) ||
|
||||
(last_token==TOKEN_GOSUB) ||
|
||||
(last_token==TOKEN_THEN)) {
|
||||
|
||||
line_no=ch1-'0';
|
||||
|
||||
while(1) {
|
||||
ch1=fgetc(fff);
|
||||
if ((ch1<'0') || (ch1>'9')) break;
|
||||
line_no*=10;
|
||||
line_no+=(ch1-'0');
|
||||
}
|
||||
|
||||
print_int(line_no,&offset);
|
||||
|
||||
goto after_read2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
output[offset]=ch1;
|
||||
offset++;
|
||||
}
|
||||
|
||||
}
|
||||
output[offset]=0;
|
||||
offset++;
|
||||
|
||||
output[link_offset]=LOW(offset+0x7ff);
|
||||
output[link_offset+1]=HIGH(offset+0x7ff);
|
||||
|
||||
}
|
||||
|
||||
/* write out our program */
|
||||
|
||||
/* set last link field to $00 $00 which indicates EOF */
|
||||
output[offset]='\0';
|
||||
output[offset+1]='\0';
|
||||
offset+=2;
|
||||
|
||||
/* Set filesize */
|
||||
/* -1 to match observed values */
|
||||
output[0]=LOW(offset-1);
|
||||
output[1]=HIGH(offset-1);
|
||||
/* output our file */
|
||||
for(i=0;i<offset;i++) putchar(output[i]);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user