diff options
-rw-r--r-- | listamsb.1 | 5 | ||||
-rw-r--r-- | listamsb.c | 39 | ||||
-rw-r--r-- | listamsb.rst | 5 |
3 files changed, 42 insertions, 7 deletions
@@ -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 @@ -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 |