home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.sys.hp48
- Path: sparky!uunet!cis.ohio-state.edu!pacific.mps.ohio-state.edu!linac!att!princeton!phoenix.Princeton.EDU!jonhiga
- From: jonhiga@phoenix.Princeton.EDU (Jonathan Tomohiko Higa)
- Subject: tasc v3beta: ->ASC / ASC->
- Message-ID: <1993Jan5.193859.4297@Princeton.EDU>
- Originator: news@nimaster
- Sender: news@Princeton.EDU (USENET News System)
- Nntp-Posting-Host: phoenix.princeton.edu
- Organization: Princeton AdTech
- Date: Tue, 5 Jan 1993 19:38:59 GMT
- Lines: 387
-
- BEGIN_DOC README
- TASC (version 3-beta) is an ASC <-> HP48 binary translator.
-
- Why do you want TASC at all?
- 1. Do the translation on another computer instead of on the HP48. A binary
- is approximately half the size of its ASC equivalent; therefore, you
- will require less battery power.
- 2. It behaves like uuencode to the extent that you don't have to strip off
- the non-ASC parts of a post or message if it contains only one ASCed object.
- I've been using commands like | "tasc - newgame.bin" within my mail reader
- to extract HP48 programs with ease.
- 3. There's no memory limit. Some programs are too large to be
- downloaded in ASC form but can still be downloaded in binary form.
-
- Why is it better than previous versions?
- 1. It determines the file type by inspecting the file instead of expecting
- a filename extension.
- 2. It determines how to invent a target file name by knowing the source
- file's type.
- 3. The target file is overwritten when translation begins, not upon
- program startup as before.
- END_DOC README
-
- BEGIN_DOC tasc.1
- TASC(1) USER COMMANDS TASC(1)
-
- NAMES
- tasc - translate HP48 binary files to and from ASC format
-
- SYNOPSIS
- tasc [opt ...] source [target]
-
- DESCRIPTION
- This program translates HP48 binary files to and from ASC
- format. It should be fully compatible with Bill Wickes's
- original ->ASC-> programs. The symbol "-" in place of a
- filename represents the terminal. If a target filename is
- not provided, one will be invented by changing the source
- filename's suffix to ".asc" or ".bin". Note that a target
- filename cannot be invented if the standard input is the
- source.
-
- OPTIONS
- -d Force ASC->bin (ASC decoding) mode.
-
- -e Force bin->ASC (ASC encoding) mode.
-
- -q Don't print reports (quiet).
-
- DIAGNOSTICS
- Returns 0 on success, 1 on error. On successful exit, a
- BYTES statement is given if not in quiet mode.
-
- AUTHOR
- Jonathan T. Higa (jonhiga@phoenix.princeton.edu)
-
- CREDITS
- - ASC: Bill Wickes (billw@hpcvdw.cv.hp.com).
- - Cyclic Redundancy Check: da Cruz, Frank. _K_e_r_m_i_t: _A _F_i_l_e
- _T_r_a_n_s_f_e_r _P_r_o_t_o_c_o_l. Bedford, MA: Digital Press, 1987.
- - Object structure: HP48 Tools Manual; "HP48SX Internals,"
- by Derek S. Nickel.
- - Guidance: Joe Horn (akcs.joehorn@hpcvbbs.cv.hp.com)
- - Original inspiration: miscellaneous asc2bin programs on
- seq.uncwil.edu
-
- Sun Release 4.1 Last change: 1992 December 26 1
- END_DOC
-
- BEGIN_SRC tasc.c
- /* tasc (version 3): ASC-encoder/decoder for HP48 files
- Copyright 1992 by Jonathan T. Higa
- Credits:
- - ASC: Bill Wickes (billw@hpcvdw.cv.hp.com).
- - Cyclic Redundancy Check:
- da Cruz, Frank. _Kermit: A File Transfer Protocol._
- Bedford, MA: Digital Press, 1987.
- - Object structure:
- HP48 Tools Manual;
- "HP48SX Internals," by Derek S. Nickel.
- - Guidance: Joe Horn (akcs.joehorn@hpcvbbs.cv.hp.com)
- - Original inspiration:
- miscellaneous asc2bin programs on seq.uncwil.edu
- */
-
- #include <stdio.h>
- #include <string.h>
-
- struct hexbuf {
- unsigned long bits;
- long nibs;
- int bsize;
- unsigned short crc;
- };
-
- enum hpdatatype { HPBIN, HPASC, UNKNOWN = -1 };
-
- int verbose = 1;
-
- void pushhex(struct hexbuf *b, int h)
- /* Add a hex digit to the bit buffer. */
- {
- b->bits |= (h & 0xfuL) << b->bsize;
- b->bsize += 4;
- }
-
- int pophex(struct hexbuf *b)
- /* Remove and return a hex digit from the bit buffer, and
- include it in the CRC. */
- {
- int h = b->bits & 0xf;
- b->crc = (b->crc >> 4) ^ (((b->crc ^ h) & 0xf) * 0x1081);
- b->nibs++;
- b->bits >>= 4;
- b->bsize -= 4;
- return h;
- }
-
- enum hpdatatype hptype(FILE *f)
- /* Determine the type of HP file by scanning the beginning of the file.
- If the type is known, put the file pointer at the start of data. */
- {
- char c;
- if (fscanf(f, "HPHP48-%c", &c) == 1)
- return HPBIN;
- else
- for (; ; )
- switch (fscanf(f, "%*[%]HP:%*[^;]%c", &c)) {
- case 1:
- while (fscanf(f, " @%c", &c) == 1) {
- if (c != '\n') {
- fscanf(f, "%*[^\n]");
- fscanf(f, "%*1[\n]");
- }
- }
- return fscanf(f, "%c", &c) == 1 && c == '"' ? HPASC : UNKNOWN;
- case 0:
- fscanf(f, "%*[^\n]");
- fscanf(f, "%*1[\n]");
- break;
- case EOF:
- return UNKNOWN;
- }
- }
-
- char *newext(char *new, const char *old, const char *ext)
- /* Create a new filename from the old filename and extension. */
- {
- char *p = strrchr(strcpy(new, old), ext[0]);
- if (p) strcpy(p, ext);
- else strcat(new, ext);
- if (verbose) fprintf(stderr, "tasc: inventing filename \"%s\"\n", new);
- return new;
- }
-
- int asctobin(FILE *fasc, FILE *fbin)
- {
- struct hexbuf hb = {0, 0, 0, 0};
- int d;
-
- /* write header into binary file */
- fputs("HPHP48-E", fbin);
-
- /* translate data */
- while (fscanf(fasc, "%1x", &d) == 1) {
- pushhex(&hb, d);
- if (hb.bsize >= 24) {
- d = pophex(&hb);
- d |= pophex(&hb) << 4;
- putc(d, fbin);
- }
- }
- if (hb.bsize > 16) {
- d = pophex(&hb);
- putc(d, fbin);
- }
-
- /* check CRC */
- if (hb.crc != hb.bits || hb.bsize != 16) {
- fprintf(stderr, "tasc: ASC->bin: CRC is incorrect\n");
- return 1;
- }
- if (verbose)
- fprintf(stderr, "tasc: ASC->bin: BYTES: #%hXh %ld%s\n",
- hb.crc, hb.nibs/2, hb.nibs & 1 ? ".5" : "");
- return 0;
- }
-
- int bintoasc(FILE *fbin, FILE *fasc)
- {
- struct hexbuf hb = {0, 0, 0, 0};
- unsigned long fldlen = 0;
- enum { SIZE, ASCIC, ASCIX, DIR, ANY = -1 } fldnxt = ANY;
- int c, width = 0;
-
- /* write header into ASC file */
- fprintf(fasc, "%%%%HP: T(1);\n\"");
-
- /* parse binary */
- while ((c = getc(fbin)) != EOF) {
- pushhex(&hb, c);
- pushhex(&hb, c >> 4);
- if (!fldlen) /* done with previous field */
- switch (fldnxt) { /* now for the current field */
- case SIZE:
- if (hb.bsize >= 20) {
- /* this object's length is known by the size field */
- fldlen = hb.bits & 0xfffff;
- fldnxt = ANY;
- }
- break;
- case ASCIC:
- if (hb.bsize >= 8) {
- /* ASCII-char identifier */
- fldlen = 2 + 2 * (hb.bits & 0xff);
- fldnxt = ANY;
- }
- break;
- case ASCIX:
- if (hb.bsize >= 8) {
- /* ASCII-extended identifier */
- fldlen = 4 + 2 * (hb.bits & 0xff);
- fldnxt = ANY;
- }
- break;
- case DIR:
- if (hb.bsize >= 20) {
- /* first object pointer in a directory, to an ASCIX name */
- fldlen = hb.bits & 0xfffff;
- fldnxt = ASCIX;
- }
- break;
- default:
- if (hb.bsize >= 20) {
- unsigned long pro = hb.bits & 0xfffff;
- fldlen = 5; /* the prolog field is 5 nibbles long */
- if (pro == 0x29e8uL || pro == 0x2a0auL || pro == 0x2a2cuL
- || pro == 0x2a4euL || pro == 0x2b1euL || pro == 0x2b40uL
- || pro == 0x2b62uL || pro == 0x2b88uL || pro == 0x2dccuL)
- fldnxt = SIZE; /* expect a size field */
- else if (pro == 0x2e48uL || pro == 0x2e6duL || pro == 0x2afcuL)
- fldnxt = ASCIC; /* expect an ASCIC object */
- else if (pro == 0x2a96uL) {
- /* expect the directory pointer after the first 8 nibbles */
- fldlen = 8;
- fldnxt = DIR;
- }
- else if (pro == 0x2911uL) fldlen = 10; /* is system binary */
- else if (pro == 0x2933uL) fldlen = 21; /* is real */
- else if (pro == 0x2955uL) fldlen = 26; /* is long real */
- else if (pro == 0x2977uL) fldlen = 37; /* is complex */
- else if (pro == 0x299duL) fldlen = 47; /* is long complex */
- else if (pro == 0x29bfuL) fldlen = 7; /* is char */
- else if (pro == 0x2e92uL) fldlen = 11; /* is XLIB name */
- }
- break;
- }
-
- /* write out the current field */
- while (fldlen && hb.bsize) {
- c = pophex(&hb);
- if (width == 64) {
- putc('\n', fasc);
- width = 0;
- }
- fprintf(fasc, "%X", c);
- width++;
- fldlen--;
- }
- }
- if (hb.bits) {
- fprintf(stderr, "tasc: bin->ASC: end of last object not found\n");
- return 1;
- }
-
- /* append CRC */
- if (verbose)
- fprintf(stderr, "tasc: bin->ASC: BYTES: #%hXh %ld%s\n",
- hb.crc, hb.nibs / 2, hb.nibs & 1 ? ".5" : "");
- hb.bits = hb.crc;
- hb.bsize = 16;
- while (hb.bsize) {
- if (width == 64) {
- putc('\n', fasc);
- width = 0;
- }
- fprintf(fasc, "%X", pophex(&hb));
- width++;
- }
- fprintf(fasc, "\"\n");
- return 0;
- }
-
- int main(int argc, char **argv)
- {
- const char *STDIO = "-";
- enum hpdatatype coding = UNKNOWN;
- int i = 1;
- char *iname, *oname, temp[256];
- if (argc > i && argv[i][0] == '-') {
- switch (argv[i][1]) {
- case 'd':
- coding = HPASC;
- i++;
- break;
- case 'e':
- coding = HPBIN;
- i++;
- break;
- case 'q':
- verbose = 0;
- i++;
- break;
- }
- }
- argc -= i;
- if (argc < 1 || argc > 2) {
- fprintf(stderr, "Use: %s [opt ...] source [target]\n"
- "opt\taction\n"
- " -d\tForce ASC->bin (ASC decode)\n"
- " -e\tForce bin->ASC (ASC encode)\n"
- " -q\tSuppress non-error messages (quiet)\n"
- "The filename \"-\" represents the terminal.\n",
- argv[0]);
- return 1;
- }
- iname = argv[i];
- if (strcmp(iname, STDIO)) {
- if (!freopen(iname, "rb", stdin)) {
- fprintf(stderr, "tasc: ");
- perror(iname);
- return 1;
- }
- } else if (argc == 1) {
- fprintf(stderr, "tasc: cannot invent output filename for stdin\n");
- return 1;
- }
- switch (hptype(stdin)) {
- case HPASC:
- if (coding == HPBIN) {
- fprintf(stderr, "tasc: ASC->bin mode was disallowed\n");
- return 1;
- }
- if (verbose) fprintf(stderr, "tasc: entering ASC->bin mode\n");
- oname = argc == 1 ? newext(temp, iname, ".bin") : argv[i+1];
- if (strcmp(oname, STDIO) && !freopen(oname, "wb", stdout)) {
- fprintf(stderr, "tasc: ");
- perror(oname);
- return 1;
- }
- if (asctobin(stdin, stdout))
- return 1;
- break;
- case HPBIN:
- if (coding == HPASC) {
- fprintf(stderr, "tasc: bin->ASC mode was disallowed\n");
- return 1;
- }
- if (verbose) fprintf(stderr, "tasc: entering bin->ASC mode\n");
- oname = argc == 1 ? newext(temp, iname, ".asc") : argv[i+1];
- if (strcmp(oname, STDIO) && !freopen(oname, "w", stdout)) {
- fprintf(stderr, "tasc: ");
- perror(oname);
- return 1;
- }
- if (bintoasc(stdin, stdout))
- return 1;
- break;
- default:
- fprintf(stderr, "tasc: unknown input type\n");
- return 1;
- }
- if (fclose(stdin)) {
- fprintf(stderr, "tasc: ");
- perror(iname);
- return 1;
- }
- if (fclose(stdout)) {
- fprintf(stderr, "tasc: ");
- perror(oname);
- return 1;
- }
- return 0;
- }
- END_SRC
- --
- Jon (jonhiga@phoenix.princeton.edu)
-