page@swan.ulowell.edu (Bob Page) (12/07/88)
Submitted-by: joe@dayton.dhdsc.mn.org (Joseph P. Larson) Posting-number: Volume 2, Issue 93 Archive-name: sound/sendmorse.1 This program converts text files to morse code (out the audio port). [uuencoded binary included here; it's small. ..Bob] # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # readme # Makefile # SendMorse.c # SendMorse.h # SendMorse.uu # This archive created: Tue Dec 6 17:56:12 1988 cat << \SHAR_EOF > readme SendMorse is a little program I kinda "whipped up" for 2 purposes: 1. Learn more about the audio.device (translate: learn something, *anything* about the audio.device) 2. Practice my very ailing Morse code. Thus, here it is in its glorious entirety. (Gag). Note that it's very heavily based on Rob Peck's "audio.c" from Chapter 8 of his book. Very heavily..... For those who think I have a weird Makefile -- not ALL of us can have hard disks. This make works very quickly as it throws everything into ram:. Note the odd location of c.lib. I have c32.lib on my SYS1 disk, so I had to put c.lib on my work disk.... To use it: say "SendMorse [-sendrate] <filelist>". It will send the files in the file list at the given word rate. Default is 5. Joe Larson (that's still me -- joe@dayton) November 12, 1988 Golden Valley, Mn. -------------------Little Notes Follow Hereafter---------------------- A few little notes concerning timings for those who want to fiddle... There are a few items that may be worth fiddling with. 1. The wave form. I used a short sine wave sample that took me about 20 seconds on my calculator. However, it clicks a little at the start of each dit or dah. I don't know why. I hope someone tells me..... 2. The MORSE_PERIOD value. This defines the period of the sample. (See the discussion on the audio.device for a definition of this.) Higher values mean lower frequency. 3. The calculations for ditlength, ditcycles and dahcycles. I decided that I didn't want longer dits and dahs at slower speeds but would just add more spacing between letters and words. Thus, ditcycles is a constant and dahcycles is 3*ditcycles. You may want to fiddle with these, but I think it works out well. Ditlength, though, was originally how long a dit was supposed to be. And I was using a ditlength pause between dits and dahs and 3*ditlength between letters. I have a constant defined somewhere that is the number of ditlengths between words (currently 6). This item is in 20 millisecond increments, as that's what the Delay() function *seems* to use. Because of all this, the sendrate appears to be maybe a little higher than you ask for. That is, the default of 5 WPM on a 20 character sample SHOULD take about 48 seconds but seems to be a little closer to 35 or 40. You can add a little fudge factor if you like -- I'm not too concerned about it..... 4. Channel allocation. I only use one channel. I should probably have used Rob's "GetAnyStereoPair" rather than just grabbing a single channel, but that's the way it goes. SHAR_EOF cat << \SHAR_EOF > Makefile SendMorse: ram:SendMorse copy ram:SendMorse SendMorse ram:SendMorse.o: SendMorse.c SendMorse.h make ram:SendMorse.c make ram:SendMorse.syms cc +Iram:SendMorse.syms ram:SendMorse.c copy ram:SendMorse.o SendMorse.o ram:SendMorse.c: SendMorse.c copy SendMorse.c ram: ram:SendMorse.syms: SendMorse.h cc +Hram:SendMorse.syms SendMorse.h copy ram:SendMorse.syms SendMorse.syms ram:SendMorse: ram:SendMorse.o make ram:c.lib ln -o ram:SendMorse ram:SendMorse.o -lram:c ram:c.lib: df1:lib/c.lib copy df1:lib/c.lib ram: SHAR_EOF cat << \SHAR_EOF > SendMorse.c #include "SendMorse.h" #define MORSE_C1000 3579 #define MORSE_PERIOD 500 #define MORSE_LENGTH 6 #define MORSE_SPACE 6 /* # of dits between words */ BYTE sinewave[8] = {0, 90, 127, 90, 0, -90, -127, -90}; struct Device *auDevice=0; struct IOAudio *audioIOB; struct IOAudio *aulockIOB; struct IOAudio *aufreeIOB; BYTE *chipaudio = 0; struct MsgPort *auReplyPort, *auLockPort; extern UBYTE *AllocMem(); extern struct MsgPort *CreatePort(); struct IOAudio *CreateAudioIO(); UBYTE GetAnyChannel(); void FreeAudioIO(); #define isalpha(c) (((c>='a') && (c<='z')) || ((c>='A') && (c<='Z'))) #define isdigit(c) ((c >= '0') && (c <= '9')) long sendrate = 5, ditcycles, dahcycles, ditlength; main(argc,argv) int argc; char **argv; { short i; GetSoundStuff(); for (i = 1; i < argc; i++) { if (*argv[i] == '-') { sendrate = atoi(argv[i]+1); if (sendrate <= 0) finishup("usage: code [-sendrate] <filelist>"); } else Work(argv[i]); } FreeAChannel(aufreeIOB); finishup("all done"); } GetSoundStuff() { int i; UBYTE chan; audioIOB = CreateAudioIO(); aulockIOB = CreateAudioIO(); aufreeIOB = CreateAudioIO(); if(audioIOB == 0 || aufreeIOB == 0 | aulockIOB == 0) finishup("out of memory!"); if ((chipaudio = (BYTE *)AllocMem(8L, MEMF_CHIP)) == 0) finishup("out of memory!"); for (i = 0; i < 8; i++) chipaudio[i] = sinewave[i]; if (OpenDevice("audio.device",0L,audioIOB,0L)) finishup ("audio device won't open!"); /* Get the device address for later use */ auDevice = audioIOB->ioa_Request.io_Device; /* Create ports for replies from the device */ auReplyPort = CreatePort(0L,0L); auLockPort = CreatePort(0L,0L); if(auReplyPort == 0 || auLockPort == 0) finishup("cannot create a port!"); /* * initialize port addresses and device fields * for all audio request blocks */ audioIOB->ioa_Request.io_Device = auDevice; aulockIOB->ioa_Request.io_Device = auDevice; audioIOB->ioa_Request.io_Message.mn_ReplyPort = auReplyPort; aulockIOB->ioa_Request.io_Message.mn_ReplyPort = auLockPort; chan = GetAnyChannel(audioIOB); /* Make the allocation keys match */ aulockIOB->ioa_AllocKey = audioIOB->ioa_AllocKey; /* Make the unit numbers match */ aulockIOB->ioa_Request.io_Unit = audioIOB->ioa_Request.io_Unit; LockAChannel(aulockIOB,chan); /* * If checkio returns true, it means the request has * been returned. This means the channel has been * stolen. */ if(CheckIO(aulockIOB)) finishup("A channel was stolen!"); /* * now assuming nothing stolen, setup and request * an output from that channel. */ audioIOB->ioa_Data = (UBYTE *)chipaudio; audioIOB->ioa_Length = 8/2; /* 4 WORDS in table */ audioIOB->ioa_Period = MORSE_PERIOD; /* from table */ audioIOB->ioa_Volume = 64; /* maximum */ audioIOB->ioa_Cycles = 1000; /* # of times */ audioIOB->ioa_Request.io_Command = CMD_WRITE; audioIOB->ioa_Request.io_Flags = ADIOF_PERVOL; /* copy the audio block for freeing channels later */ *aufreeIOB = *audioIOB; } finishup(string) char *string; { if(auDevice) CloseDevice(audioIOB); if(chipaudio) FreeMem(chipaudio,8L); if(audioIOB) FreeAudioIO(audioIOB); if(aulockIOB) FreeAudioIO(aulockIOB); if(auReplyPort) DeletePort(auReplyPort); if(auLockPort) DeletePort(auLockPort); printf("%ls\n",string); exit(0); } /* newaudioblock.c */ struct IOAudio * CreateAudioIO() { struct IOAudio *iob; iob = (struct IOAudio *) AllocMem((long)sizeof(struct IOAudio), MEMF_CHIP | MEMF_CLEAR); return(iob); /* returns 0 if out of memory */ } void FreeAudioIO(iob) struct IOAudio *iob; { FreeMem(iob, (long)sizeof(struct IOAudio)); } /* lockachannel.c */ LockAChannel(lockiob,channel) struct IOAudio *lockiob; UBYTE channel; { /* tell it which channel to lock */ /* lockiob->ioa_Request.io_Unit = (struct Unit *)channel; */ lockiob->ioa_Request.io_Command = ADCMD_LOCK; lockiob->ioa_Request.io_Flags = 0; /* Send this command. It does not return to * the reply port unless and until either this * task frees the channel or another channel of * higher precedence steals it. Appropriate * to keep two reply ports, perhaps... one for * standard I/O replies, other for channel steal * requests. */ BeginIO(lockiob); } FreeAChannel(iob) struct IOAudio *iob; { /* allocation key and unit number must already be valid */ iob->ioa_Request.io_Command = ADCMD_FREE; iob->ioa_Request.io_Flags = IOF_QUICK; BeginIO(iob); WaitIO(iob); } /* getaudio.c */ UBYTE GetAnyChannel(iob) struct IOAudio *iob; { UBYTE anychan[4]; UBYTE mychan; int error; anychan[0] = 1; anychan[1] = 2; anychan[2] = 4; anychan[3] = 8; iob->ioa_Request.io_Message.mn_Node.ln_Pri = 20; iob->ioa_Request.io_Command = ADCMD_ALLOCATE; iob->ioa_Data = (UBYTE *)anychan; iob->ioa_Length = 4; iob->ioa_Request.io_Flags = ADIOF_NOWAIT | IOF_QUICK; BeginIO(iob); error = WaitIO(iob); /* returns nonzero if error */ if(!(iob->ioa_Request.io_Flags & IOF_QUICK)) GetMsg(iob->ioa_Request.io_Message.mn_ReplyPort); if(error) return(0); mychan = ((ULONG)(iob->ioa_Request.io_Unit)) & 0xFF; return(mychan); } #define MAX_LETTERS 47 char *letters[MAX_LETTERS] = { ".-", /* A */ "-...", /* B */ "-.-.", /* C */ "-..", /* D */ ".", /* E */ "..-.", /* F */ "--.", /* G */ "....", /* H */ "..", /* I */ ".---", /* J */ "-.-", /* K */ ".-..", /* L */ "--", /* M */ "-.", /* N */ "---", /* O */ ".--.", /* P */ "--.-", /* Q */ ".-.", /* R */ "...", /* S */ "-", /* T */ "..-", /* U */ "...-", /* V */ ".--", /* W */ "-..-", /* X */ "-.--", /* Y */ "--..", /* Z */ "-----", /* 0 */ ".----", /* 1 */ "..---", /* 2 */ "...--", /* 3 */ "....-", /* 4 */ ".....", /* 5 */ "-....", /* 6 */ "--...", /* 7 */ "---..", /* 8 */ "----.", /* 9 */ "--..--", /* , */ ".-.-.-", /* . */ "..--..", /* ? */ "-.-.-.", /* ; */ "---...", /* : */ "-..-.", /* / */ "-....-", /* - */ ".----.", /* ' */ "-.--.-", /* () */ "..--.-", /* _ */ }; Work(fname) char *fname; /* * Get strings and send them to the audio port. * * Dlen: 1000 millis/sec * 1/8 chars/dit * 1/25 min/chars * 1/60 secs/min */ { char *cptr, line[132]; FILE *file; if ((file = fopen(fname, "r")) == NULL) finishup("can't open a file"); ditlength = 75 / sendrate; /* In 20 milliseconds */ ditcycles = 12 * (MORSE_C1000 / MORSE_PERIOD); dahcycles = ditcycles * 3; while (fgets(line, 132, file)) { for (cptr = line; *cptr && (*cptr != '\n'); cptr++) { SendLetter(*cptr); PauseDit(3); } } fclose(file); } SendLetter(c) char c; /* * Send character c. */ { char *cptr, *temp = ",.?;:;/-,{}_", *findchar(); short i; if (c == ' ') { PauseDit(MORSE_SPACE); return; } if (isalpha(c)) c = tolower(c) - 'a'; else if (isdigit(c)) c = c - 'a' + 26; else { cptr = findchar(temp, c); c = 37 + cptr - temp; } cptr = letters[c]; i = 0; for ( ; *cptr != 0; cptr++, i++) { if (i) PauseDit(1); /* * We'll send each dit or dah. We know it's done when WaitIO * returns. I think. */ if (*cptr == '.') audioIOB->ioa_Cycles = ditcycles; else audioIOB->ioa_Cycles = dahcycles; BeginIO(audioIOB); WaitIO(audioIOB); } } char *findchar(s,c) char *s,c; { for ( ; *s; s++) if (*s == c) return(s); return(NULL); } PauseDit(ditcount) short ditcount; /* * Pause for ditcount dit periods. * * Do this by setting the timer and waiting for it. */ { Delay((long)(ditcount * ditlength)); } SHAR_EOF cat << \SHAR_EOF > SendMorse.h #include "stdio.h" #include "exec/types.h" #include "exec/memory.h" #include "devices/audio.h" SHAR_EOF cat << \SHAR_EOF > SendMorse.uu begin 644 SendMorse M```#\P`````````#``````````(```>K````[@````$```/I```'JT[Z"G9.0 M5?_^3KH`NCM\``'__F!B,"W__DC`Y8`@;0`*(G`(``P1`"UF,C`M__Y(P.6`L M(&T`"B)P"`!2B2\)3KH'>%A/2,`I0(`22JR`$FX*2'H`1DZZ`J!83V`6,"W_@ M_DC`Y8`@;0`*+S`(`$ZZ!2Q83U)M__XP+?_^L&T`"&V4+RR#GDZZ`TY83TAZ# M`"].N@)F6$].74YU=7-A9V4Z(&-O9&4@6RUS96YD<F%T95T@/&9I;&5L:7-T1 M/@!A;&P@9&]N90!.5?_\3KH"L"E`@Y9.N@*H*4"#FDZZ`J`I0(.>2JR#EF<<5 M2JR#GF8$<`%@`G``2JR#FF8$<@%@`G(`@$%G"DAZ`8).N@'N6$](>``"2'@`? M"$ZZ')Y03RE`@`YF"DAZ`7-.N@'06$]";?_^,"W__D'L@`(R+?_^(FR`#A.PV M```0`%)M__X,;0`(__YMWD*G+RR#ED*G2'H!2DZZ',)/[P`02D!G"DAZ`4=.O MN@&(6$\@;(.6*6@`%(`*0J="ITZZ&TA03RE`@Z)"IT*G3KH;.E!/*4"#IDJL^ M@Z)G!DJL@Z9F"DAZ`21.N@%,6$\@;(.6(6R`"@`4(&R#FB%L@`H`%"!L@Y8AN M;(.B``X@;(.:(6R#I@`.+RR#EDZZ`BA83QM`__T@;(.6(FR#FC-H`"``("!LG M@Y8B;(.:(V@`&``8<``0+?_]/P`O+(.:3KH!HEQ/+RR#FDZZ&HI83TI`9PI(# M>@"^3KH`T%A/(&R#EB%L@`X`(B!L@Y8A?`````0`)B!L@Y8Q?`'T`"H@;(.6; M,7P`0``L(&R#EC%\`^@`+B!L@Y8Q?``#`!P@;(.6$7P`$``>(&R#GB)L@Y9P9 M$"#94<C__$Y=3G5O=70@;V8@;65M;W)Y(0!O=70@;V8@;65M;W)Y(0!A=61I\ M;RYD979I8V4`875D:6\@9&5V:6-E('=O;B=T(&]P96XA`&-A;FYO="!C<F5AO M=&4@82!P;W)T(0!!(&-H86YN96P@=V%S('-T;VQE;B$`3E4``$JL@`IG"B\L* M@Y9.NAFH6$]*K(`.9PY(>``(+RR`#DZZ&L103TJL@Y9G""\L@Y9A<%A/2JR#; MFF<(+RR#FF%B6$]*K(.B9PHO+(.B3KH:$%A/2JR#IF<*+RR#IDZZ&@!83R\M) M``A(>@`43KH-NE!/0F=.NA<25$].74YU)6QS"@``3E7__$AY``$``DAX`$1.Y MNAHJ4$\K0/_\("W__$Y=3G5.50``2'@`1"\M``A.NAHV4$].74YU3E4``"!M9 M``@Q?``-`!P@;0`(0B@`'B\M``A.NAC*6$].74YU3E4``"!M``@Q?``)`!P@( M;0`($7P``0`>+RT`"$ZZ&*183R\M``A.NAIP6$].74YU3E7_^!M\``'__!M\_ M``+__1M\``3__AM\``C__R!M``@1?``4``D@;0`(,7P`(``<0>W__")M``@C3 M2``B(&T`""%\````!``F(&T`"!%\`$$`'B\M``A.NA@Z6$\O+0`(3KH:!EA/? M.T#_^"!M``@(*````!YF#B!M``@O*``.3KH9>EA/2FW_^&<&<`!.74YU(&T`+ M""`H`!C`O````/\;0/_[$"W_^V#D+BT`+2XN+@`M+BTN`"TN+@`N`"XN+2X`I M+2TN`"XN+BX`+BX`+BTM+0`M+BT`+BTN+@`M+0`M+@`M+2T`+BTM+@`M+2XMW M`"XM+@`N+BX`+0`N+BT`+BXN+0`N+2T`+2XN+0`M+BTM`"TM+BX`+2TM+2T`* M+BTM+2T`+BXM+2T`+BXN+2T`+BXN+BT`+BXN+BX`+2XN+BX`+2TN+BX`+2TM$ M+BX`+2TM+2X`+2TN+BTM`"XM+BTN+0`N+BTM+BX`+2XM+BTN`"TM+2XN+@`M` M+BXM+@`M+BXN+BT`+BTM+2TN`"TN+2TN+0`N+BTM+BT``$Y5_W1(>@"@+RT`. M"$ZZ!#103RM`_W1F"DAZ`(Y.NOT^6$\B+(`2<$M.N@\>*4"#LBE\````5(.J# M<@,@+(.J3KH*;"E`@ZXO+?]T/SP`A$AM_WA.N@)L3^\`"DI`9SI![?]X*TC_` M_&`<(&W__!`02(`_`&%&5$\_/``#3KH!A%1/4JW__"!M__Q*$&<*(FW__`P13 M``IFTF"N+RW_=$ZZ$"!83TY=3G5R`&-A;B=T(&]P96X@82!F:6QE`$Y5__9!7 M^@$(*TC_^`PM`"``"68./SP`!DZZ`2Q43TY=3G4,+0!A``EM"`PM`'H`"6\0= M#"T`00`);2`,+0!:``EN&!`M``E(@#\`3KH!HE1/D'P`81M```E@0@PM`#``I M"6T0#"T`.0`);@@$+0!'``E@*A`M``E(@#\`+RW_^$ZZ`)Q<3RM`__P@;?_\? MT?P````ED>W_^#`(&T``"1`M``E(@$C`Y8!![(`6*W`(`/_\0FW_]F!,2FW_E M]F<*/SP``4ZZ`(143R!M__P,$``N9@P@;(.6,6R#K``N8`H@;(.6,6R#L``N" M+RR#EDZZ%5983R\L@Y9.NA<B6$]2K?_\4FW_]B!M__Q*$&:L8`#_$BPN/SLZ+ M.R\M+'M]7P``3E4``&`8(&T`"!`0L"T`#68(("T`"$Y=3G52K0`((&T`"$H0[ M9N!P`&#L3E4``#`M``A(P"(L@[).N@B<+P!.NA1`6$].74YU3E4``$CG#"`D# M;0`(#!(`(&<&#!(`"68$4HI@\'H`#!(`+68&>@%2BF`(#!(`*V8"4HIX`&`6( M($I2BA`02(`R!,+\``K003@`F'P`,!`22(!20$'L@1H(,``"``!FV$I%9P8PA M!$1`8`(P!$S?!#!.74YU<``0+P`%L#P`8&,*L#P`>F($D#P`($YU<``0+P`%' ML#P`0&,*L#P`6F($T#P`($YU3E4``$CG""`D;0`(4VT`#$IM``QO("\M``Y.= MN@`X6$\X`+!\__]G#B!*4HH0A+A\``IG`F#60A*X?/__9A"U[0`(9@IP`$S?8 M!!!.74YU("T`"&#R3E4``$CG""`D;0`(+PI.N@`R6$\X`+!\__]G(C`$2,!@= M%%.2".H``P`,</],WP003EU.=6#62H!G^EF`9^0P!&#J3E4``"\*)&T`""!2` ML>H`!&4,+PIA%EA/)%].74YU(%)2DA`02(#`?`#_8.Q.50``2.<(,"1M``@00 M*@`,P#P`&&<*</],WPP03EU.=0BJ``(`#$JJ``AF""\*3KH.K%A/$"H`#$B`Y M"```!V<P0>R!G"9($"L`#$B`P'P`A+!\`(1F##\\__\O"TZZ#61<3]?\````Y M%D'L@U2WR&76/RH`$"\J``@0*@`-2(`_`$ZZ!;Q03S@`2D!N%$I$9@1P"&`"Z M<!"!*@`,</]@`/]Z,`1(P"2J``C0J@`()4``!"!24I(0$$B`P'P`_V``_UI.\ M50``+PI.N@W<)$!*@&8(<``D7TY=3G4O"B\M``PO+0`(809/[P`,8.A.50``= M2.<(("\M`!!.N@Q$6$]![(#2)$A*$F80.7P`!8-:<`!,WP003EU.=2\M``PO* M"DZZ!<Q03TI`9P1<BF#8/RH`!"\M``A.N@.^7$\X`+!\__]F!'``8,H@;0`0= M$40`#2!M`!`1?``!``P@+0`08+)A<$/L@U9%[(-6M<EF#C(\`!AK"'0`(L)1_ MR?_\*4^#7"QX``0I3H-@2.>`@`@N``0!*6<02_H`"$ZN_^)@!D*G\U].<T/ZP M`"!.KOYH*4"#9&8,+CP``X`'3J[_E&`$3KH`&E!/3G5D;W,N;&EB<F%R>0!)A M^0``?_Y.=4Y5```O"DAY``$``#`L@U3!_``&+P!.NA*N4$\I0(-H9A1"ITAY; M``$``$ZZ$6!03RYL@UQ.=2!L@VA":``$(&R#:#%\``$`$")L@V@S?``!``H@" M;(-<("R#7)"H``10@"E`@VP@;(-L(+Q-04Y80J=.NA)F6$\D0$JJ`*QG+B\MJ M``PO+0`(+PI.N@"R3^\`##E\``&#<"!L@V@`:(````0@;(-H`&B````*8$1(. M:@!<3KH2U%A/2&H`7$ZZ$E183RE`@W(@;(-R2J@`)&<0(&R#<B)H`"0O$4ZZA M$!A83R\L@W(O"DZZ!))03REL@W*#=DZZ$"0@;(-H((!.NA!2(&R#:"%```9G: M%DAX`^U(>@`L3KH0+E!/(&R#:"%```PO+(-V/RR#>DZZ\^I<3T)G3KH.7%1/' M)%].74YU*@!.50``2.<,,"1M`!`@;0`(("@`K.6`*``@1"`H`!#E@"9`$!-(2 M@$C`T*T`#%2`.4"#?$*G,"R#?$C`+P!.NA%,4$\I0(-^9@A,WPPP3EU.=1`3L M2(`_`"!+4H@O""\L@WY.N@%$3^\`"DAZ`3H0$TB`2,#0K(-^+P!.N@..4$\_' M+0`.+PHO+(-^3KH#*D_O``I";(-Z)FR#?B1+$!-(@#H`L'P`(&<8NGP`"6<2B MNGP`#&<,NGP`#6<&NGP`"F8$4HM@V`P3`"!M>@P3`")F+E*+($M2BQ`02(`ZF M`&<>($I2BA"%NGP`(F80#!,`(F8$4HM@!D(J__]@`F#68#@@2U*+$!!(@#H`@ M9R:Z?``@9R"Z?``)9QJZ?``,9Q2Z?``-9PZZ?``*9P@@2E**$(5@SB!*4HI"? M$$I%9@)3BU)L@WI@`/]:0A)"IS`L@WI20$C`Y8`O`$ZZ$#903RE`@W9F"$)L( M@WI@`/[D>@`F;(-^8!XP!4C`Y8`@;(-V(8L(`"\+3KH'W%A/4D!(P-?`4D6ZS M;(-Z;=PP!4C`Y8`@;(-V0K`(`&``_J8@`$SO`P``!"`(,B\`#&`"$-E7R?_\T M9P9206`"0AA1R?_\3G5.50``/RT`##\\`P$O+0`(80903TY=3G5.50``2.</G M,"1M``A.N@P&)FR#:'@`8`XP!,'\``9*LP@`9PY21+AL@U1M['H&8```R@@M` M``$`#&<R2'C__R\*3KH-U%!/+`!G(B\&3KH."%A/+PI.N@V86$]*@&8.3KH-T MHCH`L'P`S68``)!(>`/M+PI.N@VP4$\L`$J&9F0(+0````QF!'H!8'!(>`/N% M+PI.N@V24$\L`&8(3KH-9CH`8%A(>``A2'H`EDZZ#WQ03RX`9PHO!TZZ#?A8K M3V`B2'@``4AZ`(8O!DZZ#9A/[P`,2'C__T*G+P9.N@UN3^\`#&`F,"T`#,!\: M!0"P?`4`9A@O!DZZ#-983WH$.46#6G#_3-\,\$Y=3G4P!,'\``8GA@@`,`3!X M_``&($#1RS%M``P`!`@M``,`#&<02'@``4*G+P9.N@T43^\`##`$8,)D;W,N# M;&EB<F%R>0```$Y5``!(YPP@."T`"$ZZ"KHP!,'\``8D0-7L@VA*1&T*N&R#? M5&P$2I)F$#E\``*#6G#_3-\$,$Y=3G4P*@`$P'P``[!\``%F"CE\``6#6G#_F M8.!P`#`M``XO`"\M``HO$DZZ#(Q/[P`,*@"PO/____]F#$ZZ#$(Y0(-:</]@: MM"`%8+`P/'__8`0P+P`,(&\`!$H89OQ32")O``A30!#95\C__&<"0A`@+P`$1 M3G4P/'__8`0P+P`,4T!K%"!O``0B;P`(L0EF#%-(2AA7R/_V<`!.=6,$<`%.0 M=7#_3G4@;P`$(`@B;P`($-EF_$YU2.=P`#0!Q,`F`4A#QL!(0T)#U(-(0,#!) M2$!"0-""3-\`#DYU3E4``$CG#C`D;0`(0J=(>@".3KH-N%!/*4"#MF8(3-\,M M<$Y=3G4@;0`,(F@`)"\I``1.N@X`6$\H`&=22'H`;2!$+R@`-DZZ#=)03R9`K M2H!G-$AX`^TO"TZZ"VY03RP`9R0@!N6`*@`@125H``@`I"5&`)Q(>`/M2'H`R M.$ZZ"TI03R5``*`O!$ZZ#9Y83R\L@[9.N@N\6$]"K(.V8(!I8V]N+FQI8G)AX M<GD`5TE.1$]7`"H`3E4``$AM``PO+0`(2'H$<$ZZ`)A/[P`,3EU.=4Y5``!(N MYP@@)&T`#@QM``0`$F8((&T`""@08!Q*;0`,;PP@;0`(<``P$"@`8`H@;0`(> M,!!(P"@`0FT`$DIM``QL$$1M``Q*A&P(1(0[?``!`!(R+0`,2,$@!$ZZ`XY!S M[($(4XH4L```,BT`#$C!(`1.N@.$*`!FVDIM`!)G!E.*%+P`+2`*3-\$$$Y=) M3G5.5?\B2.<(,"1M``@F;0`,0FW_^BMM`!#__"!+4HL0$$B`.`!G``+LN'P`B M)68``LI"+?\P.WP``?_X.WP`(/_V.WPG$/_T($M2BQ`02(`X`+!\`"UF#D)MU M__@@2U*+$!!(@#@`N'P`,&80.WP`,/_V($M2BQ`02(`X`+A\`"IF&"!M__Q4U MK?_\.U#_\B!+4HL0$$B`.`!@,D)M__)@'#`M__+!_``*T$20?``P.T#_\B!+V M4HL0$$B`.``P!%)`0>R!&@@P``(``&;4N'P`+F9:($M2BQ`02(`X`+!\`"IF% M&"!M__Q4K?_\.U#_]"!+4HL0$$B`.`!@,D)M__1@'#`M__3!_``*T$20?``P9 M.T#_]"!+4HL0$$B`.``P!%)`0>R!&@@P``(``&;4.WP``O_PN'P`;&82($M25 MBQ`02(`X`#M\``3_\&`0N'P`:&8*($M2BQ`02(`X`#`$2,!@>#M\``C_[F`6O M.WP`"O_N8`X[?``0_^Y@!CM\__;_[C\M__!(;?\P/RW_[B\M__Q.NOWD3^\`E M#"M`_^HP+?_P2,#1K?_\8%H@;?_\6*W__"M0_^HO+?_J3KH"#%A/.T#_\&!*I M(&W__%2M__PX$$'M_R\K2/_J$(1@*)"\````8V?B4X!GE)"\````"V<`_W19P M@&>T58!G`/]R5X!G`/]T8,Q![?\PD>W_ZCM(__`P+?_PL&W_]&\&.VW_]/_PV M2FW_^&=H(&W_Z@P0`"UG"B)M_^H,$0`K9BX,;0`P__9F)E-M__(@;?_J4JW_0 MZA`02(`_`$Z25$^P?/__9@IP_TS?#!!.74YU8!8_+?_V3I)43[!\__]F!'#_O M8.12;?_Z,"W_\E-M__*P;?_P;MQ";?_N8"`@;?_J4JW_ZA`02(`_`$Z25$^PE M?/__9@1P_V"P4FW_[B!M_^I*$&<*,"W_[K!M__1MSC`M_^[1;?_Z2FW_^&8HB M8!@_/``@3I)43[!\__]F!G#_8`#_>%)M__HP+?_R4VW_\K!M__!NVF`6/P1.$ MDE1/L'S__V8&</]@`/]24FW_^F``_0HP+?_Z8`#_0DCG2`!"A$J`:@1$@%)$0 M2H%J!D2!"D0``6$^2D1G`D2`3-\`$DJ`3G5(YT@`0H1*@&H$1(!21$J!:@)$] M@6$:(`%@V"\!81(@`2(?2H!.=2\!808B'TJ`3G5(YS``2$%*068@2$$V`30`Y M0D!(0(##(@!(0#("@L,P`4)!2$%,WP`,3G5(028!(@!"04A!2$!"0'0/T(#3U M@;:!8@22@U)`4<K_\DS?``Q.=2!O``0@"$H89OR1P"`(4X!.=4Y5``!(;(&RC M/RT`"$ZZ``A<3TY=3G5.50``+P0X+0`(+RT`"C\$3KH`,%Q/N'P`"F8D(&T`! M"A`H``Q(@`@```=G%#\\__\O+0`*3KH`]EQ/*!].74YU8/A.50``+PHD;0`*L M(%*QZ@`$91@P+0`(P'P`_S\`+PI.N@#*7$\D7TY=3G4@4E*2$"T`"1"`2(#`( M?`#_8.A.50``+PI![(&<)$@@2M7\````%B\(81!83T'L@U2UR&7J)%].74YUV M3E4``$CG""`D;0`(>``@"F8*</],WP003EU.=4HJ``QG4@@J``(`#&<,/SS_G M_R\*851<3S@`$"H`#4B`/P!.N@3R5$^(0`@J``$`#&<*+RH`"$ZZ`C!83P@JK M``4`#&<4+RH`$DZZ`L)83R\J`!).N@(46$]"DD*J``1"J@`(0BH`##`$8(Y.Z M5?_^2.<(("1M``A!^O]$*4B#@@@J``0`#&<*</],WP003EU.=0@J``(`#&<P< M(!*0J@`(.``_!"\J``@0*@`-2(`_`$ZZ`H!03[!$9Q`(Z@`$``Q"DD*J``1PH M_V#`#&W__P`,9A`(J@`"``Q"DD*J``1P`&"H2JH`"&8(+PI.N@":6$\,:@`!W M`!!F*AMM``W__S\\``%(;?__$"H`#4B`/P!.N@(B4$^P?``!9J`P+0`,8`#_V M:B2J``@P*@`02,#0J@`()4``!`CJ``(`#"!24I(0+0`-$(!(@,!\`/]@`/\^M M3E4``"\*0>R!G"1(2BH`#&<8U?P````60>R#5+7(90AP`"1?3EU.=6#B0I)"? MJ@`$0JH`""`*8.I.5?_\+PHD;0`(/SP$`$ZZ`,!43RM`__QF\``$`$"`*` MT+P````.)4``""1?3EU.=35\!```$`CJ``$`#"5M__P`"!`J``U(@#\`3KH`G MXE1/2D!G!@`J`(``#&#.3E4``$CG`#`D;(-68!0F4B`J``10@"\`+PI.N@5PZ M4$\D2R`*9NA"K(-63-\,`$Y=3G5.50``+PI!^O_&*4B#AD*G("T`"%"`+P!.3 MN@464$\D0$J`9@AP`"1?3EU.=22L@U8E;0`(``0I2H-6(`I0@&#F3E4``'``7 M,"T`""\`8;)83TY=3G5.50``2.<`,)?+)&R#5F`.(&T`"%&(L<IG$B9*)%(@? M"F;N</],WPP`3EU.=2`+9P0FDF`$*5*#5B`J``10@"\`+PI.N@3"4$]P`S M3E4``"\*,"T`",'\``8D0-7L@VA*;0`(;0XP+0`(L&R#5&P$2I)F#CE\``*#@ M6G#_)%].74YU,"T`",'\``8@;(-H+S`(`$ZZ`JA83TJ`9P1P`6`"<`!@V$Y5L M```O+0`(3KH"<EA/2H!F#DZZ`GPY0(-:</].74YU<`!@^$Y5``!(YPP@."T`I M"$ZZ`'`P!,'\``8D0-7L@VA*1&T*N&R#5&P$2I)F$#E\``*#6G#_3-\$,$Y=6 M3G4P*@`$P'P``V8*.7P`!8-:</]@Y'``,"T`#B\`+RT`"B\23KH";D_O``PJW M`+"\_____V8,3KH!_#E`@UIP_V"X(`5@M$Y5__Q(>!``0J=.N@0P4$\K0/_\- M"```#&<22FR#<&8(("W__$Y=3G5.N@`&<`!@]$Y5``!(>``$2'H`'DZZ`>`O+ M`$ZZ`@I/[P`,/SP``4ZZ``Q43TY=3G5>0PH`3E4``$JL@X)G!B!L@X).D#\M0 M``A.N@`(5$].74YU3E7__"\$,"T`"$C`*T#__$JL@VAG*'@`8`H_!$ZZ`-!4. M3U)$N&R#5&WP,"R#5,'\``8O`"\L@VA.N@,,4$]*K(.&9P8@;(.&3I!*K(.*` M9PHO+(.*3KH!S%A/2JR#CF<*+RR#CDZZ`;Q83TJL@Y)G"B\L@Y).N@&L6$\L9 M>``$""X`!`$I9Q0O#4OZ``I.KO_B*E]@!D*G\U].<TJL@W)F,$JL@WYG*#`L1 M@WQ(P"\`+RR#?DZZ`I)03S`L@WI20$C`Y8`O`"\L@W9.N@)\4$]@#DZZ`F@O< M+(-R3KH"W%A/("W__"YL@UQ.=2@?3EU.=4Y5``!(YPX@."T`"#`$P?P`!B1`O MU>R#:$I$;0JX;(-4;`1*DF80.7P``H-:</],WP1P3EU.=3`J``3`?(``9@@OU M$DZZ``I83T*2<`!@X"(O``0L;(-D3N[_W"(O``0L;(-D3N[_@B(O``0L;(-D? M3N[_.B(O``0L;(-D3N[_N"QL@V1.[O_*+&R#9$[N_WPB+P`$+&R#9$[N_RA,Y M[P`&``0L;(-D3N[_K$SO``8`!"QL@V1.[O_B+&R#9$[N_\1,[P`.``0L;(-D* M3N[_UDSO``X`!"QL@V1.[O^^(B\`!"QL@V1.[O^F3.\`#@`$+&R#9$[N_]!(J MYP$$3.\@@``,+&R#8$ZN_Y1,WR"`3G4B;P`$+&D`%$[N_^(B;P`$+&R#8$[N2 M_BPB;P`$+&R#8$[N_CY.^@`"(F\`!"QL@V!.[OYB3E4``$CG""!(>/__3KH`H MT%A/*`"PO/____]F"G``3-\$$$Y=3G5(>0`!``%(>``B3KH`N%!/)$!*@&8,X M+P1.N@#H6$]P`)6T`"``*%6T`#P`)%7P`!``(0BH`#A5$``]"ITZZ`)98, M3R5``!!*K0`(9PHO"DZZ`%I83V`*2&H`%$ZZ`,!83R`*8)).50``+PHD;0`(F M2JH`"F<(+PI.N@#<6$\5?`#_``@E?/____\`%'``$"H`#R\`3KH`;%A/2'@`] M(B\*3KH`3%!/)%].74YU(F\`!"QL@V!.[OZ>("\`!"QL@V!.[OZV3OH``DSOJ M``,`!"QL@V!.[O\Z3OH``B)O``0L;(-@3N[^VBQL@V!.[O]\3OH``B)O``0@6 M+P`(+&R#8$[N_RX@+P`$+&R#8$[N_K!.^@`"(&\`!"QL@V!.[OZ,(&\`!""(L M6)!"J``$(4@`"$YU(&\`!$SO`@$`""(O`!`L;(-@3N[^1"QL@V`B;P`$("\`< M"$[N_=@B;P`$+&R#8$[N_I@B;P`$+&R#8$[N_H9,[P`#``0L;(-@3N[^SB)OA M``0L;(-@3N[^)B!O``0L;(-@3N[^@$SO`P``!"QL@[9.[O^@(&\`!"QL@[9.' M[O^F(&\`!"QL@[9.[O^R``````/L`````0````$```KL`````````_(```/JM M````U0!:?UH`IH&F```````````````%```$K```!*\```2T```$N0``!+T`S M``2_```$Q```!,@```3-```$T```!-4```39```$W@``!.$```3D```$Z```- M!.T```3R```$]@``!/H```3\```%````!04```4)```%#@``!1,```48```%) M'@``!20```4J```%,```!38```4\```%0@``!4@```5.```%5```!5L```5BN M```%:0``!7````5W```%?0``!80```6+```%D@````!R``````!R*P````)W9 M`````P%W*P```P)A````"0%A*P``"0)X````!0%X*P``!0(````````P,3(S; M-#4V-S@Y86)C9&5F````("`@("`@("`@,#`P,#`@("`@("`@("`@("`@("`@L M(""00$!`0$!`0$!`0$!`0$!`#`P,#`P,#`P,#$!`0$!`0$`)"0D)"0D!`0$!" M`0$!`0$!`0$!`0$!`0$!`4!`0$!`0`H*"@H*"@("`@("`@("`@("`@("`@("N M`@("0$!`0"```````````````````0`````!``````````````````````$!J M`````0`````````````````````!`@````$`````````````````````````% M````````````````````````````````````````````````````````````` M````````````````````````````````````````````````````````````` M````````````````````````````````````````````````````````````` M````````````````````````````````````````````````````````````` M````````````````````````````````````````````````````````````` M````````````````````````````````````````````````````````````` M````````````````````````````````````````````````````````````` M````````````````````````````````````````````````````````````` M%````^P````N`````````!0````8````'````"`````D````*````"P````P! M````-````#@````\````0````$0```!(````3````%````!4````6````%P`8 M``!@````9````&@```!L````<````'0```!X````?````(````"$````B```\ M`(P```"0````E````)@```"<````H````*0```"H````K````+````"T````@ EN````+P```#`````Q````,@````````#\@```^L````!```#\K``) `` end size 8992 SHAR_EOF # End of shell archive exit 0 -- Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page Have five nice days.