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