Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!uunet!jarthur!nntp-server.caltech.edu!pooh!madler From: madler@pooh.caltech.edu (Mark Adler) Newsgroups: comp.sys.handhelds Subject: Re: Why ASC over UUENCODE? Message-ID: <1991Feb14.202321.23152@nntp-server.caltech.edu> Date: 14 Feb 91 20:23:21 GMT References: <5936D424400019B9@gacvx2.gac.edu> <1991Feb14.194901.4798@portia.Stanford.EDU> Sender: news@nntp-server.caltech.edu Organization: California Institute of Technology, Pasadena Lines: 334 Nntp-Posting-Host: pooh >> How about a portable version of ASC-> and ->ASC in C I portabilized Pete Wilson's program that was recently posted and I am posting it at the end of this message. >> AND which is distributed in EXECUTABLE form I leave it to others to compile it for PC's or whatnot and put it on some ftp site. >> on the HP software disks included with the cables? Well, I would prefer a uu-like thing instead. But until then, this program should be useful. >> That way, all that whining about UUENCODE would be bunk Not in my opinion, but I won't rehash what I've posted already. Mark Adler madler@pooh.caltech.edu --- asc2bin.c --- /* This programs reads an up to 127K ASCII (RPL) file consisting of a string intended for ASC-> and converts it into a binary object file. This program was compiled with Microsoft C 5.1 and Turbo C. ANSI C conventions are mostly followed. The original algorithm for CRC computation was extracted from Li Sheng's posting to comp.sys.handhelds. 01/19/91 PMW created 02/14/91 MAdler modified for portability */ #include #include #ifdef __STDC__ # define MODERN #endif #ifdef __TURBOC__ # ifndef MODERN # define MODERN # endif #endif #ifdef MODERN # include # include # include # define FOPR "rb" # define FOPW "wb" #else # define void int # define size_t unsigned int extern char *strcat(); extern char *strcpy(); # define FOPR "r" # define FOPW "w" #endif typedef unsigned char BYTE; typedef unsigned int WORD; /* Function prototypes for ANSI C */ #ifdef MODERN int FileExists(char *); long FileSize(FILE *); WORD crcBlock(BYTE *, size_t); void CopyLine(BYTE **, char **, WORD *); void ReadFile(char *, BYTE **, WORD *); void WriteFile(char *, BYTE *, WORD ); int main(int, char **); #endif #define MAX_READ_SIZE 127 #ifndef FILENAME_MAX # define FILENAME_MAX 65 #endif #ifndef EXIT_FAILURE # define EXIT_FAILURE 1 #endif #ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 #endif #ifndef SEEK_SET # define SEEK_SET 0 #endif #ifndef SEEK_END # define SEEK_END 2 #endif #ifndef isxdigit # define isxdigit(c) (c >= '0' && c <= '9' || c >= 'A' && c <= 'F') #endif #define HEX2INT(hc) ((unsigned int) (isdigit(hc) ? (hc)-'0' : (hc)-'A'+10)) int FileExists(f) char *f; { FILE *tf; if ((tf = fopen(f, FOPR)) != NULL) { fclose(tf); return 1; } else return 0; } long FileSize(f) FILE *f; { long origPos = ftell(f), fileSize = 0; fseek(f, 0L, SEEK_END); fileSize = ftell(f); fseek(f, origPos, SEEK_SET); return fileSize; } #define CALC_CRC(c, i) (((((c)^(i)) & 0xF) * 0x1081) ^ ((c) >> 4)) WORD crcBlock(mb, len) BYTE *mb; size_t len; { WORD crc = 0, bObjSize = len/2; while (bObjSize--) { crc = CALC_CRC(crc, (WORD) (*mb) & 0xF); crc = CALC_CRC(crc, (WORD) ((*mb) >> 4)); ++mb; } if (len & 1) crc = CALC_CRC(crc, (WORD) (*mb) & 0xF); return crc; } void CopyLine(mb, s, objSize) BYTE **mb; char **s; WORD *objSize; { char *ts = *s; BYTE *tmb = *mb; WORD ls = 0; while (isxdigit(ts[0]) && isxdigit(ts[1])) { *tmb++ = (BYTE) (HEX2INT(ts[0]) + (HEX2INT(ts[1]) << 4)); ls += 2; ts += 2; } if (isxdigit(ts[0]) && ts[1] == '"') { /* we ended on a nibble boundary!! */ BYTE crc1, crc2; /* correct crc by nibble shifting end */ crc2 = (BYTE) ((tmb[-1] >> 4) + (HEX2INT(ts[0]) << 4)); crc1 = (BYTE) ((tmb[-2] >> 4) + ((tmb[-1] & 0xF) << 4)); /* fix memory buffer */ tmb[-2] &= 0xf; tmb[-1] = crc1; *tmb++ = crc2; ++ls; ++ts; } *s = ts; *mb = tmb; *objSize += ls; } #define READLN(s, f) fgets((s), sizeof(s), (f)) void ReadFile(filepath, mb, objSize) char *filepath; BYTE **mb; WORD *objSize; { FILE *infile; char lineBuf[250], *p; WORD bufSize; long fileSize; BYTE *wmb; if (!strchr(filepath, '.')) strcat(filepath, ".rpl"); if (!(infile = fopen(filepath, "r"))) { fprintf(stderr, "asc2bin: can't open %s\n", filepath); exit(EXIT_FAILURE); } fileSize = FileSize(infile); if (fileSize > MAX_READ_SIZE*1024L) { fprintf(stderr, "asc2bin: File %s is too long\n", filepath); exit(EXIT_FAILURE); } bufSize = 4+(WORD) (fileSize / 2); /* approximate byte size of object */ if (!(*mb = (BYTE *) malloc(bufSize))) { fprintf(stderr, "asc2bin: Unable to allocate %u bytes\n", bufSize); exit(EXIT_FAILURE); } wmb = *mb; /* find string */ while (!feof(infile)) { if (!READLN(lineBuf, infile)) { if (feof(infile)) fputs("asc2bin: Unable to locate string\n", stderr); else perror("asc2bin: Read error"); fclose(infile); exit(EXIT_FAILURE); } if (*lineBuf == '"') break; } *objSize = 0; /* put string into buffer */ p = &lineBuf[1]; /* skip opening quote */ CopyLine(&wmb, &p, objSize); /* copy remainder into buffer */ while (*p != '"' && !feof(infile)) { if (!READLN(lineBuf, infile)) { if (feof(infile)) fputs("asc2bin: Unable to locate closing quote\n", stderr); else perror("asc2bin: Read error"); fclose(infile); exit(EXIT_FAILURE); } p = lineBuf; CopyLine(&wmb, &p, objSize); } fclose(infile); } void WriteFile(filepath, mb, objSize) char *filepath; BYTE *mb; WORD objSize; { FILE *outfile; char *extpos = strchr(filepath, '.'); strcpy(extpos+1, "bin"); if (FileExists(filepath)) { fprintf(stderr, "asc2bin: file already exists: %s\n", filepath); exit(EXIT_FAILURE); } if (!(outfile = fopen(filepath, FOPW))) { fprintf(stderr, "asc2bin: unable to create %s\n", filepath); exit(EXIT_FAILURE); } fputs("HPHP48-C", outfile); /* my own version */ while (objSize--) fputc(*mb++, outfile); fclose(outfile); } int main(argc, argv) int argc; char **argv; { char filepath[FILENAME_MAX]; BYTE *mb; WORD objSize, rcrc, crc,bObjSize; /* NOTE: objSize is in nibbles! */ if (argc < 2) { fputs("usage: asc2bin infile[.ext]\n", stderr); fputs("\treads infile.ext and creates infile.bin\n", stderr); fputs("\tif omitted, .ext is assumed to be .rpl\n", stderr); exit(EXIT_FAILURE); } strcpy(filepath, argv[1]); ReadFile(filepath, &mb, &objSize); if (objSize < 2) { fputs("asc2bin: String too short to include crc\n", stderr); exit(EXIT_FAILURE); } objSize -= 4; /* nibbles */ bObjSize = objSize / 2 + (objSize & 1); rcrc = (WORD) mb[bObjSize] + ((WORD) mb[bObjSize+1] << 8); crc = crcBlock(mb, objSize); if (crc != rcrc) { fprintf(stderr, "asc2bin: Calculated CRC # %Xh does not match read CRC # %Xh\n", crc, rcrc); exit(EXIT_FAILURE); } WriteFile(filepath, mb, bObjSize); return EXIT_SUCCESS; }