aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--listamsb.15
-rw-r--r--listamsb.c39
-rw-r--r--listamsb.rst5
3 files changed, 42 insertions, 7 deletions
diff --git a/listamsb.1 b/listamsb.1
index c416032..1302ae6 100644
--- a/listamsb.1
+++ b/listamsb.1
@@ -54,6 +54,9 @@ Programs created with \fISAVE "filename" LOCK\fP are autodetected,
and will be listed normally. It\(aqs also possible to convert a LOCKed
program to an unencrypted one, with the \fB\-l\fP option.
.sp
+Programs can be "crunched" and "decrunched" with the \fB\-C\fP and \fB\-D\fP
+options.
+.sp
If no \fBoutput\-file\fP is given, output is to \fBstdout\fP\&.
.SH OPTIONS
.INDENT 0.0
@@ -77,6 +80,7 @@ target of GOTO or GOSUB, the program won\(aqt run because all comment\-only
lines are removed.
.sp
This option must be used with an \fBoutput\-file\fP, since seeking is done.
+None of the other options have any effect with \fB\-C\fP\&.
.TP
.B \fB\-D\fP
"Decrunch" a crunched program. Puts spaces where they\(aqre required for
@@ -85,6 +89,7 @@ comments that were removed during crunching will not magically be
retored (they\(aqre gone).
.sp
This option must be used with an \fBoutput\-file\fP, since seeking is done.
+None of the other options have any effect with \fB\-D\fP\&.
.TP
.B \fB\-r\fP \fIline\-range\fP
Show only part of the listing. \fIline\-range\fP can be a single line, or
diff --git a/listamsb.c b/listamsb.c
index be6b307..a9f6505 100644
--- a/listamsb.c
+++ b/listamsb.c
@@ -548,6 +548,8 @@ int crunch_line(void) {
return codelen;
}
+/* only called during decrunching.
+ only handles one-byte tokens (only has to). */
void expand_token(unsigned char t, unsigned char *buf) {
if(t < 0x80) {
buf[0] = t;
@@ -558,6 +560,10 @@ void expand_token(unsigned char t, unsigned char *buf) {
strcpy((char *)buf, std_tokens[t - MIN_STD_TOK]);
}
+/* only called during decrunching.
+ the tokenizer in AMSB requires spaces to separate keywords
+ and variables/numbers. "IF A THEN 100" really needs the spaces
+ before and after the A, for example. */
int need_space_between(unsigned char t1, unsigned char t2) {
unsigned char tok1[10], tok2[10];
unsigned char t1last, t2first;
@@ -566,10 +572,24 @@ int need_space_between(unsigned char t1, unsigned char t2) {
if(!t2) return 0; /* end of line */
if(t1 < 0x80 && t2 < 0x80) return 0; /* 2 ASCII chars */
+ if(t1 > MAX_STD_TOK || t2 > MAX_STD_TOK)
+ die("invalid token in program, can't decrunch");
+
expand_token(t1, tok1);
expand_token(t2, tok2);
t1last = tok1[strlen((char *)tok1) - 1]; /* "PRINT" => "T" */
- t2first = tok2[0]; /* "PRINT" => "P" */
+ t2first = tok2[0]; /* "PRINT" => "P" */
+
+ /* space not really required between OPEN/PRINT/CLOSE and #,
+ but put one there for neatness. */
+ if(t2first == '#') return 1;
+
+ /* space not really required between a closing quote and
+ a keyword, but put it in for neatness. examples:
+ OPEN #1,"D:X" INPUT
+ IF A$="FOO" THEN 10
+ these look weird with the space before INPUT or THEN. */
+ if(t1last == '|' && isalnum(t2first)) return 1;
return(isalnum(t1last) && isalnum(t2first));
}
@@ -631,12 +651,14 @@ int decrunch_line(void) {
return codelen;
}
+/* despite the name, this handles both crunching and decrunching */
void crunch_program(void) {
int newproglen = 0, linelen = 0;
+ float percent;
fputc(0x00, outfile); /* signature (0 = not locked) */
fputc(0x00, outfile); /* length LSB (fill in later) */
- fputc(0x00, outfile); /* length MSB */
+ fputc(0x00, outfile); /* length MSB " " */
while((linelen = decrunch ? decrunch_line() : crunch_line()) != -1)
newproglen += linelen;
@@ -645,19 +667,22 @@ void crunch_program(void) {
fputc(0x00, outfile);
fputc(0x00, outfile);
- if(fseek(outfile, 1L, SEEK_SET) < 0)
- os_err("fseek() failed");
-
+ /* fill in length in header */
+ if(fseek(outfile, 1L, SEEK_SET) < 0) os_err("fseek() failed");
newproglen += 2; /* account for trailing $00 $00 */
fputc(newproglen & 0xff, outfile);
fputc((newproglen >> 8) & 0xff, outfile);
fclose(outfile);
+ /* show the user how the size changed */
newproglen += 3;
- verbose(1, "crunched %d byte program to %d bytes (%.1f%% savings)",
+ percent = 100.0 * (1.0 - (float)newproglen / (float)proglen);
+ verbose(1, "%scrunched %d byte program to %d bytes (%.1f%% %s)",
+ decrunch ? "de" : "",
bytes_read,
newproglen,
- 100.0 * (1.0 - (float)newproglen / (float)proglen));
+ percent < 0 ? -percent : percent,
+ percent < 0 ? "larger" : "smaller");
}
void print_help(void) {
diff --git a/listamsb.rst b/listamsb.rst
index 63d72ea..a76c22b 100644
--- a/listamsb.rst
+++ b/listamsb.rst
@@ -35,6 +35,9 @@ Programs created with *SAVE "filename" LOCK* are autodetected,
and will be listed normally. It's also possible to convert a LOCKed
program to an unencrypted one, with the **-l** option.
+Programs can be "crunched" and "decrunched" with the **-C** and **-D**
+options.
+
If no **output-file** is given, output is to **stdout**.
OPTIONS
@@ -59,6 +62,7 @@ OPTIONS
lines are removed.
This option must be used with an **output-file**, since seeking is done.
+ None of the other options have any effect with **-C**.
**-D**
"Decrunch" a crunched program. Puts spaces where they're required for
@@ -67,6 +71,7 @@ OPTIONS
retored (they're gone).
This option must be used with an **output-file**, since seeking is done.
+ None of the other options have any effect with **-D**.
**-r** *line-range*
Show only part of the listing. *line-range* can be a single line, or