casper@wacsvax.OZ (Casper A Boon) (09/19/85)
Here is the second part of the offering, MWRescue, Stripper and sundries. Casper Boon, Dept of Computer Science, University of Western Australia, casper@wacsvax.oz (OZNet, CSNET) ...!{decvax|seismo}!mulga!wacsvax.oz!casper (UUCP) casper%wacsvax.oz@seismo.arpa (ARPA) "When all else fails read the instructions..." ------------------------- Cut Here -------------------------- #! /bin/sh # This is a shell archive - extract with sh not csh # cat << \SHAR_EOF > 'Stripper.c' /* * stripper.c -- strip control characters from a TEXT or WORD file. * * Copyright Casper A Boon, University of Western Australia * * * This source may be freely distributed to other educational institutions * on the following conditions: * * 1) This copyright notice accompanies it, * 2) No profit may be made from such distribution * * * History: * Created August '85 * */ #include <MacCdefs.h> #include <quickdraw.h> #include <stdio.h> #include <packages.h> #define TRUE 1 #define FALSE 0 #define MaxChars 16000 short int infile, outfile; char nullstr[] = {'\0','\0'}; char str1[] = { '\12', 'S','t','r','i','p',' ','F','i','l','e','\0'}; char str2[] = { '\14', 'S','t','r','i','p','p','e','d','F','i','l','e','\0'}; char str3[] = { '\11', 'S','a','v','e',' ','A','s',' ',':','\0'}; char CarrRet = '\15'; char infname[255], outfname[255]; char CharsBuffer[MaxChars]; long int stripcount = 0; long int count; extern short int FSOpen(); extern short int FSClose(); extern short int FSRead(); extern short int FSWrite(); extern short int Create(); char isprint(c) char c; { if (((c >= 32) && (c <= 126)) || (c == 10) || (c == 13)) return(TRUE); return(FALSE); } short int OpenInFile(inf, infnam) short int *inf; char * infnam; { Point apoint; SFReply theReply; SFTypeList typelist; apoint.v = 80; apoint.h = 80; typelist.ftype[0] = 'TEXT'; typelist.ftype[1] = 'WORD'; SFGetFile(&apoint, str1, (ProcPtr) 0, 2, &typelist, (ProcPtr) 0, &theReply); if ( theReply.good ) { BlockMove(&theReply.Namelength, infnam, 255); return (FSOpen(&theReply.Namelength,theReply.vRefNum,inf)); } else return (-1); } OpenOutFile(outf, outfnam) short int *outf; char * outfnam; { Point apoint; SFReply theReply; short int err; apoint.v = 80; apoint.h = 80; SFPutFile(&apoint, str3, str2, (ProcPtr) 0, &theReply); if ( theReply.good ) { BlockMove(&theReply.Namelength, outfnam, 255); err = Create(&theReply.Namelength, theReply.vRefNum, 'EDIT','TEXT'); return ( FSOpen(&theReply.Namelength, theReply.vRefNum, outf) ); } else return(-1); } char GetAByte() { long int lcount = 1; short int err; char c; if ( (err = FSRead(infile, &lcount, &c)) != 0 ) { if (err != -39) { fprintf(stdout, " Read Error # %d Click mouse to continue.\r", err); beepnwait(); } err = FSWrite(outfile, &count, CharsBuffer); FSClose(outfile); FSClose(infile); fprintf(stdout, "\r %ld Characters stripped from file.\r", stripcount); exit(1) ; } return ( c ) ; } main() { char c ; short int err; InitPack(3); if ( err = OpenInFile(&infile, infname) != 0 ) { fprintf(stdout, " Cannot open input file. Error #%d \r Click mouse to continue.\r",err); beepnwait(); exit(1); } if ( err = OpenOutFile(&outfile, outfname) != 0 ) { fprintf(stdout, " Cannot open output file. Error #%d \r Click mouse to continue.\r",err); beepnwait(); exit(1); } do macputchar( GetAByte()) ; while ( TRUE ) ; } macputchar( c ) char c; { if ( isprint(c) || (c == '\11') ) { DumpChar(c); putchar(c) ; } else stripcount++; } beepnwait() { SysBeep(5); while ( !Button() ); while ( Button() ); } DumpChar(c) char c; { short int err; if (count >= MaxChars) { err = FSWrite(outfile, &count, CharsBuffer); count = 0; } CharsBuffer[count++] = c; } SHAR_EOF cat << \SHAR_EOF > 'Stripper.r' * input for resource compiler * StrippRes.Rel Type CAB1 = STR ,0 Stripper V1.0 Type ICN# = GNRL ,128 * cab1 icon 3FFF8000 60004000 90002000 97FF2000 F0001000 10001000 17FE1000 10001000 10031000 138F1000 103F9000 10FF9000 11FF9000 13FF9000 10FF1F00 107FE080 100FC040 09B3F020 0807F010 0404700F 04720007 02010007 01008007 00806007 00B79FE7 0080009F 0FC00087 08400080 08400100 08400100 04800200 03FFFC00 * cab1 mask 3FFF8000 7FFFC000 FFFFE000 FFFFE000 FFFFF000 1FFFF000 1FFFF000 1FFFF000 1FFFF000 1FFFF000 1FFFF000 1FFFF000 1FFFF000 1FFFF000 1FFFFF00 1FFFFF80 1FFFFFC0 0FFFFFE0 0FFFFFF0 07FFFFFF 07FFFFFF 03FFFFFF 01FFFFFF 00FFFFFF 00FFFFFF 00FFFF9F 0FFFFF87 0FFFFF80 0FFFFF00 0FFFFF00 07FFFE00 03FFFC00 Type FREF ,128 * APPL uses loc icon 0, no tagalongs APPL 0 Type BNDL ,128 CAB1 0 * 2 types * ICN#, 1 entry, loc 0 to glob 128 ICN# 0 128 * FREF, 1 entry, loc 0 to glob 128 FREF 0 128 SHAR_EOF cat << \SHAR_EOF > 'Stripper.Link' /Bundle /Type 'APPL' 'CAB1' !start stdlib stdFileIO stdIOPrim FSStuff SFpacks Stripper /Resources StrippRes $ SHAR_EOF cat << \SHAR_EOF > 'MWRescue.c' /* * mwrescue.c -- rescue a damaged MacWrite file (version 3.0 and later) * * * History: * * 5/11/85 Winkler Created * * 12 Aug '85 Boon Hacked to Mac. * * */ #include <MacCdefs.h> #include <quickdraw.h> #include <stdio.h> #include <packages.h> #define TRUE 1 #define FALSE 0 #define MaxChars 16000 /* Compressed characters for English. MacWrite stores this string * in the resource fork of the document. A future improvement would * be to find the string there (presumably in file.rsrc on Unix) rather * than assume this one. */ char compchars[] = {' ', 'e', 't', 'n', 'r', 'o', 'a', 'i', 's', 'd', 'l', 'h', 'c', 'f', 'p', '\n' } ; /* the Macintosh has several veiws on string. The ROMs were written in * Pascal and hence have pascal strings. These then are prefixed with a * length byte. Consulair Mac C uses C strings which are postfixed with * a NUL byte. This causes many problems in using the Mac ROM calls. * A further problem manifests itself in using any string. A simple * declaration such as: * * char *str = 'a junk string'; * * will have the string pointer set to point to the string at the end of * the code. The memory manager moves the code segment around and resets * register A5 accourdingly but that doesn't always leave the pointer * for the string pointing to the right places. At least that is my guess * at the reason behind the strange behaviour with strings. * my solution was to be explicit about all assignment, allocate the space * explicitly as the following demonstrates. */ char nullstr[] = {'\0','\0'}; char str1[] = { '\14', 'R','e','c','o','v','e','r',' ','F','i', 'l','e','\0'}; char str2[] = { '\15', 'R','e','c','o','v','e','r','e','d','F','i', 'l','e','\0'}; char str3[] = { '\11', 'S','a','v','e',' ','A','s',' ',':','\0'}; char CarrRet = '\15'; char infname[255], outfname[255]; char CharsBuffer[MaxChars]; short int infile, outfile; long int count; /* these Mac routines were not implemented in MacC so they appear in an external library which I hacked together. They are declared here to avoid the long int/short int difference */ extern short int FSOpen(); extern short int FSClose(); extern short int FSRead(); extern short int FSWrite(); extern short int Create(); char isprint(c) char c; { if (((c >= 32) && (c <= 126)) || (c == 10) || (c == 13)) return(TRUE); return(FALSE); } /* OpenInFile was created to give the prompt Dialog box for opening the source file */ short int OpenInFile(inf, infnam) short int *inf; char * infnam; { Point apoint; SFReply theReply; SFTypeList typelist; apoint.v = 80; apoint.h = 80; typelist.ftype[0] = 'WORD'; SFGetFile(&apoint, str1, (ProcPtr) 0, 1, &typelist, (ProcPtr) 0, &theReply); if ( theReply.good ) { BlockMove(&theReply.Namelength, infnam, 255); return (FSOpen(&theReply.Namelength,theReply.vRefNum,inf)); } else return (-1); } /* OpenOutFile for the standard dialog for the output file */ OpenOutFile(outf, outfnam) short int *outf; char * outfnam; { Point apoint; SFReply theReply; short int err; apoint.v = 80; apoint.h = 80; SFPutFile(&apoint, str3, str2, (ProcPtr) 0, &theReply); if ( theReply.good ) { BlockMove(&theReply.Namelength, outfnam, 255); err = Create(&theReply.Namelength, theReply.vRefNum, 'EDIT','TEXT'); return ( FSOpen(&theReply.Namelength, theReply.vRefNum, outf) ); } else return(-1); } main() /* read encoded file from stdin and write text to stdout */ { int c ; short int err; InitPack(3); fprintf(stdout, " Mac Write Document Rescuer \r"); if ( err = OpenInFile(&infile, infname) != 0 ) { fprintf(stdout, " Cannot open input file. Error #%d \r Click mouse to continue.\r",err); beepnwait(); exit(1); } if ( err = OpenOutFile(&outfile, outfname) != 0 ) { fprintf(stdout, " Cannot open output file. Error #%d \r Click mouse to continue.\r",err); beepnwait(); exit(1); } /* this following bit of the main() is as it came */ do { c = getnibble() ; if ( c != 0x000f ) macputchar( compchars[c] ) ; else { int c2 ; c = getnibble() ; c2 = getnibble() ; /* need variables because C doesn't guarantee * the order of evaluation of arguments. So if * c and c2 below were replaced by getnibble()'s * there would be no way of knowing which of the * next two nibbles on stdin would be shifted */ macputchar( (c << 4) + c2 ) ; } } while ( TRUE ) ; /* infinite loop. getnibble() exits on EOF */ } macputchar( c ) /* translate returns to newlines and suppress nonprinting characters */ /* Hacked to include the DumpChar for dumping to files */ char c; { short int err; if ( isprint(c) ) { if ( c != '\r' ) { DumpChar(c); putchar(c) ; } else { DumpChar(CarrRet); putchar('\n'); } } } getnibble() /* return the next nibble from stdin. exits on EOF. */ /* Haqued to read from other than standard in (ie using the Mac FSRead()) */ { static int got = FALSE ; static int chr ; char c; long int lcount = 1; short int err; if ( ! got ) { if ( (err = FSRead(infile, &lcount, &c)) != 0 ) { if (err != -39) { fprintf(stdout, " Read Error # %d Click mouse to continue.\r", err); beepnwait(); } err = FSWrite(outfile, &count, CharsBuffer); FSClose(outfile); FSClose(infile); exit(1) ; } got = TRUE ; chr = c; return ( ( chr >> 4 ) & 0x0f) ; } else { got = FALSE ; return (chr & 0x0f) ; } } /* a little procedure for debugging. Easier to make a sound and wait for the mouse click than to write to the screen in initial stages */ beepnwait() { SysBeep(5); while ( !Button() ); while ( Button() ); } /* put chars in a large buffer, and dump the buffer when full */ DumpChar(c) char c; { short int err; if (count >= MaxChars) { err = FSWrite(outfile, &count, CharsBuffer); count = 0; } CharsBuffer[count++] = c; } SHAR_EOF cat << \SHAR_EOF > 'MWRescue.r' * input for resource compiler * MWRescRes.Rel Type CAB0 = STR ,0 Mac Write Rescue V 1.0 Type ICN# = GNRL ,128 * cab0 icon 00000000 00010000 00010000 00010000 0007C000 00393800 00C10600 01010100 02010080 03895980 05555540 05955540 0555D540 09895920 0803BF20 7FFFC0FC 08638060 09813020 0601F810 0402780F 0C023007 0A010007 12018007 11016007 20C11FE7 2039381F 4007C007 40010004 40010004 7FFFFFFC 00000000 00000000 * cab0 mask 00000000 00010000 00010000 00010000 0007C000 003FF800 00FFFE00 01FFFF00 03FFFF80 03FFFF80 07FFFFC0 07FFFFC0 07FFFFC0 0FFFFFE0 0FFFFFE0 7FFFFFFC 0FFFFFE0 0FFFFFE0 07FFFFF0 07FFFFFF 0FFFFFFF 0FFFFFFF 1FFFFFFF 1FFFFFFF 3FFFFFFF 3FFFFFFF 7FFFFFFF 7FFFFFFC 7FFFFFFC 7FFFFFFC 00000000 00000000 Type FREF ,128 * APPL uses loc icon 0, no tagalongs APPL 0 Type BNDL ,128 CAB0 0 * 2 types * ICN#, 1 entry, loc 0 to glob 128 ICN# 0 128 * FREF, 1 entry, loc 0 to glob 128 FREF 0 128 SHAR_EOF cat << \SHAR_EOF > 'MWRescue.link' /Bundle /Type 'APPL' 'CAB0' !start stdlib stdFileIO stdIOPrim FSStuff VolStuff SFpacks mwrescue /Resources MWRescRes $ SHAR_EOF cat << \SHAR_EOF > 'FSStuff.c' #include "pbDefs.h" #define NIL 0 typedef struct PARAMBLK { long int qLink; // next queue entry short int qType; // queue type short int ioTrap; // routine trap long int ioCmdAddr; // routine address char *ioCompletion; // completion routine short int ioResult; // result code struct P_Str *ioFileName; // volume or file name short int ioVRefNum; // volume reference or drive number short int ioRefNum; // path reference number char ioVersNum; // version number char ioPermission; // read/write permission long int ioMisc; // miscellaneous pointer char *ioBuffer; // data buffer long int ioReqCount; // requested number of bytes long int ioActCount; // actual number of bytes short int ioPosMode; // newline char and type of positioning op long int ioPosOffset; // size of positioning ofset }; short int Create(str,mode, creator, filetype) struct P_Str * str; short int mode; long int creator, filetype; { struct PARAMBLK myparamblk; short int retval; long int TheTime; myparamblk.ioCompletion = NIL; myparamblk.ioMisc = 0; myparamblk.ioFileName = str; myparamblk.ioVRefNum = mode; myparamblk.ioVersNum = 0; #asm CLR.W -(SP) PEA -76(A6) DC.W $A039 TST (SP)+ #endasm myparamblk.ioRefNum = 0; myparamblk.ioReqCount = creator; myparamblk.ioBuffer = (char *) filetype; retval = PBCreate(&myparamblk, 0); retval = PBSetFInfo(&myparamblk, 0); return(retval); } short int FSOpen(str,mode,chan) struct P_Str * str; short int mode; short int * chan; { struct PARAMBLK myparamblk; short int retval; myparamblk.ioCompletion = NIL; myparamblk.ioFileName = str; myparamblk.ioVRefNum = mode; myparamblk.ioVersNum = 0; myparamblk.ioPermission = 0; myparamblk.ioMisc = NIL; retval = PBOpen(&myparamblk, 0); *chan = myparamblk.ioRefNum; return(retval); } short int FSRead(chan, count, c) short int chan; long int * count; char * c; { struct PARAMBLK myparamblk; short int retval; myparamblk.ioCompletion = NIL; myparamblk.ioReqCount = *count; myparamblk.ioRefNum = chan; myparamblk.ioBuffer = c; myparamblk.ioPosMode = 0; myparamblk.ioPosOffset = 0; retval = PBRead(&myparamblk, 0); *count = myparamblk.ioActCount; return(retval); } short int FSWrite(chan, count, c) short int chan; long int * count; char * c; { struct PARAMBLK myparamblk; short int retval; myparamblk.ioCompletion = NIL; myparamblk.ioReqCount = *count; myparamblk.ioRefNum = chan; myparamblk.ioBuffer = c; myparamblk.ioPosMode = 0; myparamblk.ioPosOffset = 0; retval = PBWrite(&myparamblk, 0); *count = myparamblk.ioActCount; return(retval); } short int FSClose(refnum) short int refnum; { struct PARAMBLK myparamblk; short int retval; myparamblk.ioCompletion = 0; myparamblk.ioRefNum = refnum; return(PBClose(&myparamblk, 0)); } short int FSDelete(name,vrefnum) struct P_Str * name; short int vrefnum; { struct PARAMBLK myparamblk; short int retval; myparamblk.ioCompletion = 0; myparamblk.ioFileName = name; myparamblk.ioVersNum = 0; myparamblk.ioVRefNum = vrefnum; return(PBDelete(&myparamblk, 0)); } SHAR_EOF cat << \SHAR_EOF > 'SFPacks.c' #include <MacCdefs.h> #include <quickdraw.h> #include <packages.h> #define TRUE 1 #define FALSE 0 SFGetFile(where,prompt,fileFilter,numTypes,typeList,dlgHook,reply) Point *where; struct P_Str *prompt; int (*fileFilter)(); short numTypes; SFTypeList *typeList; int (*dlgHook)(); SFReply *reply; { #asm MOVE.L SP, A1 ;SAVE ORIGINAL SP MOVE.L D0, A0 ;DEREFERENCE POINT SINCE ;STRUCTURE SIZE IS SMALLER ;THAN 33 BITS MOVE.L (A0), -(SP) ;WHERE MOVE.L D1, -(SP) ;PROMPT MOVE.L D2, -(SP) ;fileFilter MOVE.W D3, -(SP) ;numTypes MOVE.L D4, -(SP) ;typeList MOVE.L D5, -(SP) ;dlgHook MOVE.L D6, -(SP) ;reply MOVE.W #2, -(SP) ;Select SFPGetFile DC.W $A9EA ;_Pack3 #endasm } SFPutFile(where,prompt,origname,dlgHook,reply) Point *where; struct P_Str *prompt; struct P_Str *origname; int (*dlgHook)(); SFReply *reply; { #asm MOVE.L SP, A1 ;SAVE ORIGINAL SP MOVE.L D0, A0 ;DEREFERENCE POINT SINCE ;STRUCTURE SIZE IS SMALLER ;THAN 33 BITS MOVE.L (A0), -(SP) ;WHERE MOVE.L D1, -(SP) ;PROMPT MOVE.L D2, -(SP) ;origname MOVE.L D3, -(SP) ;dlghook MOVE.L D4, -(SP) ;reply MOVE.W #1, -(SP) ;Select SFPutFile DC.W $A9EA ;_Pack3 #endasm } SHAR_EOF cat << \SHAR_EOF > 'VolStuff.c' #include "pbDefs.h" #define NIL 0 typedef struct PARAMBLK { long int qLink; // next queue entry short int qType; // queue type short int ioTrap; // routine trap long int ioCmdAddr; // routine address char *ioCompletion; // completion routine short int ioResult; // result code char *ioFileName; // volume or file name short int ioVRefNum; // volume reference or drive number short int ioRefNum; // path reference number short int filler; // not used short int ioVolIndex; // volume index long int ioVCrDate; // date and time of initialization long int ioVLsBkUp; // date & time of last backup short int ioVAtrb; // bit 15 = 1 if volume locked short int ioVNmFls; // number of files short int ioVDirSt; // first block of file directory short int ioVBlLn; // number blocks in file directory short int ioVNmAlBlks; // number alloc blocks in volume long int ioVAlBlkSiz; // number bytes per allocation block long int ioVClpSiz; // bytes to allocate short int ioAlBlSt; // first block in vol block map long int ioVNxtFNum; // next free file number short int ioVFrBlk; // number free alloc blocks }; short int GetVInfo(drvnum, vnam, vrefno, freeBytes) short int drvnum; char * vnam; short int *vrefno; long int * freeBytes; { struct PARAMBLK myparamblk; short int retval; myparamblk.ioCompletion = 0; myparamblk.ioVRefNum = drvnum; if (vnam == (char *) -1) myparamblk.ioVolIndex = -1; else myparamblk.ioVolIndex = 0; myparamblk.ioFileName = vnam; retval = PBGetVInfo(&myparamblk, 0); *freeBytes = (myparamblk.ioVFrBlk * myparamblk.ioVAlBlkSiz); *vrefno = myparamblk.ioVRefNum; vnam = myparamblk.ioFileName; return(retval); } short int GetVol(vnam, vrefno) char * vnam; short int * vrefno; { struct PARAMBLK myparamblk; short int retval; myparamblk.ioCompletion = 0; retval = PBGetVol(&myparamblk, 0); *vrefno = myparamblk.ioVRefNum; vnam = myparamblk.ioFileName; return(retval); } short int SetVol(vnam, vrefno) char * vnam; short int vrefno; { struct PARAMBLK myparamblk; short int retval; myparamblk.ioCompletion = 0; myparamblk.ioVRefNum = vrefno; myparamblk.ioFileName = vnam; return(PBSetVol(&myparamblk, 0)); } short int FlushVol(vnam, vrefno) char * vnam; short int vrefno; { struct PARAMBLK myparamblk; short int retval; myparamblk.ioCompletion = 0; myparamblk.ioVRefNum = vrefno; myparamblk.ioFileName = vnam; return(PBFlshVol(&myparamblk, 0)); } short int UnmountVol(vnam, vrefno) char * vnam; short int vrefno; { struct PARAMBLK myparamblk; short int retval; myparamblk.ioCompletion = 0; myparamblk.ioVRefNum = vrefno; myparamblk.ioFileName = vnam; return(PBUnmountVol(&myparamblk, 0)); } short int Eject(vnam, vrefno) char * vnam; short int vrefno; { struct PARAMBLK myparamblk; short int retval; myparamblk.ioCompletion = 0; myparamblk.ioVRefNum = vrefno; myparamblk.ioFileName = vnam; return(PBEject(&myparamblk, 0)); } SHAR_EOF