;***************************************************************************** ; Filename: TEETO.M68 Date: 8/7/90 ; Category: UTIL Hash Code: 447-557-506-065 Version: 1.0(100) ; Initials: ROBB/AM Name: Erik Petrich ; Company: Microlink Computing Systems, Inc. Telephone #: 4053218333 ; Related Files: ; Min. Op. Sys.: NONE Expertise Level: ADV ; Special: ; Description: This program will tee standard output to both a terminal as ; well as a file. ;***************************************************************************** ;PROGRAM Description ; TeeTo Tee standard output to a file also ; ; Copyright 1990 Microlink Computing Systems, Inc. ; ;Edit History: ;[100] 16 April 1990 12:13 Written by Erik Petrich ; 07 August 1990 03:20 Uploaded to AMUS network ; Lots of small bugs suddenly appear after this event. (of course!) ;[101] 09 August 1990 03:46 Edited by Erik Petrich ; Forced output buffer size to be small, consolidated TRMDEF reset. ;[102] 09 August 1990 04:02 Edited by Erik Petrich ; Changed to allow abort during sleep. ;[103] 09 August 1990 04:23 Edited by Erik Petrich ; Undid part of edit #101 -- leave output buffer size alone. ;[104] 09 August 1990 05:07 Edited by Erik Petrich ; Fixed TEEOUT not to display the TCRT toggle code. ;[105] 10 August 1990 00:02 Edited by Erik Petrich ; Changed SAVEW D0-D2 to SUB #6,A7 since SUB is faster and ; was what all I really needing anyway. ;[106] 15 August 1990 09:43 Edited by Erik Petrich ; Changed RTE to a LSTS/RTN to avoid problems on 68010/20/30 ; ; ; ; This was written out of frustration that AMOS/L doesn't support ; redirectable input/output or pipes, like some "other" operating systems ; do. This takes care of standard output, which is what I mostly needed; ; perhaps I'll get around to redirectable input & pipes later. ; ; Some examples: ; ; TEETO /O DIRECT.LST DIR ; This is equivilent to DIR = ; ; The same general pattern can be used with programs that don't support ; disk output. ; ; TEETO /O DIRECT.LST ARCDIR YAZ ; Saves the directory listing of ; ; archive YAZ into DIRECT.LST ; ; TeeTo is also useful for putting examples of program use into a file ; so that it can be more easily added to the documentation. ; ; TEETO EXAMPL.TXT PROGRAM ; output goes both to file & terminal ; ; And when you really get serious about your game play, make a recording of ; it so decide how to do better next time. ; ; TEETO /T PONG.SCR PONG ; saves TCRT sequences too ; TYPE PONG.SCR ; instant replay ; SEARCH SYS SEARCH SYSSYM SEARCH TRM VMAJOR = 1. VMINOR = 0. VEDIT = 106. .ofini .ofdef ourdev,2 ; TeeTo file device .ofdef ourdrv,2 ; TeeTo file drive .ofdef ourppn,2 ; TeeTo file ppn .ofdef oldcmz,2 ; Starting command file size .ofdef oldtdv,4 ; Pointer to original terminal driver .ofdef oldobs,4 ; Old output buffer size [101] .ofdef ourjcb,4 ; Pointer to our JCB .ofdef ourdvt,4 ; Pointer to TeeTo file device table entry .ofdef outfil,d.ddb ; TeeTo file DDB .ofdef filbuf,512. ; Buffer for TeeTo file .ofdef datbuf,8192. ; Buffer that the TEETO.TDV drive writes to .ofdef filler,8. ; Buffer safety factor .ofdef bufsiz,4 ; Bytes in use in DATBUF .ofdef abortd,2 ; non-zero indicates TEETO.TDV has aborted ; its host job and spliced in .ofdef oldpc,4 ; host job's PC counter .ofdef oldsr,2 ; host job's status register .ofdef notcrt,2 ; no tcrt sequences switch .ofdef prtcrt,2 ; currently processing tcrt .ofdef notty,2 ; no output to screen .ofdef column,2 ; current logical column .ofsiz impsiz phdr -1,0,ph$reu byp lin jne start usage: typecr crlf typecr ttyi byte 13. ascii /Options:/ byte 13. ascii % /T - Include TCRT sequences in file% byte 13. ascii % /O - Omit output to screen% byte 13.,13.,0 even exit start: lea a5,impure movw #-1,d7 10$: clrw (a5)+ dbf d7,10$ lea a5,impure jobidx mov a6,ourjcb(a5) movw jobdev(a6),ourdev(a5) movw jobdrv(a6),ourdrv(a5) movw jobusr(a6),ourppn(a5) movw jobcmz(a6),oldcmz(a5) mov jobtrm(a6),a6 mov t.tdv(a6),oldtdv(a5) mov t.obs(a6),oldobs(a5) ;[101] call getopt fspec outfil(a5),TXT lea a1,filbuf(a5) mov a1,d.buf+outfil(a5) orb #d$ini,d.flg+outfil(a5) mov #512.,d.siz+outfil(a5) call chkdev call fnddvt lookup outfil(a5) bne 20$ dskdel outfil(a5) 20$: openo outfil(a5) type <(TeeTo > pfile outfil(a5) typecr < open)> byp lin beq 30$ save a2 orb #d$erc!d$byp,d.flg+outfil(a5) call watoip call chgtdv rest a2 25$: save a5 amos rest a5 mov jobcur,a6 tstb @a6 bmi 30$ movw oldcmz(a5),d7 cmpw d7,jobcmz(a6) bhis 30$ mov jobcur,a6 movb jobcms(a6),d7 andb #c.trc,d7 beq 27$ ttyl jobprm(a6) 27$: mov jobcur,a6 orb #c.mon,jobcms(a6) mov jobtrm(a6),a6 andw #^C,@a6 kbd 30$ mov jobcur,a6 andb #^C,jobcms(a6) br 25$ 30$: call watoip ; mov jobcur,a6 ;[101] ; mov jobtrm(a6),a6 ;[101] ; mov oldtdv(a5),t.tdv(a6) ;[101] call rsttdv ;[101] incw abortd(a5) 35$: call wrtbuf tstw bufsiz(a5) bne 35$ andb #^C,d.flg+outfil(a5) close outfil(a5) type <(TeeTo > pfile outfil(a5) typecr < closed)> exit watoip: 30$: mov jobcur,a6 mov jobtrm(a6),a6 35$: movw @a6,d7 andw #t$oip,d7 bne 35$ rtn chkdev: movw d.dev+outfil(a5),d7 cmpw d7,#[MEM] jeq baddev cmpw d7,#[RES] jeq baddev cmpw d7,#[TRM] beq 10$ rtn 10$: movw d.fil+outfil(a5),d7 mov jobcur,a6 mov jobtrm(a6),a6 cmp d6,-8.(a7) beq 20$ rtn 20$: typecr <%Can't TeeTo your own terminal> exit baddev: type <%Can't TeeTo MEM: or RES:> exit fnddvt: jobidx movw d.dev+outfil(a5),d1 bne 10$ movw jobdev(a6),d1 10$: movw d.drv+outfil(a5),d2 cmpw d2,#-1 bne 20$ movw jobdrv(a6),d2 20$: mov devtbl,a0 30$: cmpw d1,dv.dev(a0) bne 40$ cmpw d2,dv.unt(a0) bne 40$ mov @a0,a0 mov a0,d7 bne 30$ typecr exit 40$: mov a0,ourdvt(a5) rtn getopt: setw notcrt(a5) 5$: byp movb @a2,d1 cmpb d1,#'/ beq 10$ rtn 10$: inc a2 movb (a2)+,d1 cmpb d1,#'T bne 20$ clrw notcrt(a5) br 5$ 20$: cmpb d1,#'O bne 30$ setw notty(a5) br 5$ 30$: typecr exit define fixjmp addr,ofs lea a3,addr lea a6,ofs(a1) movw #^h4ef9,(a3)+ ; jmp long absolute opcode mov a6,(a3)+ ; operand endm chgtdv: save a0-a3 mov oldtdv(a5),a1 lea a0,newtdv mov -8.(a1),-8.(a0) ; copy link to next TDV mov -4(a1),-4(a0) ; copy name movw td.typ(a1),td.typ(a0) movw td.imp(a1),td.imp(a0) movw td.row(a1),td.row(a0) mov td.flg(a1),td.flg(a0) fixjmp jmpinp,td.inp fixjmp jmpech,td.ech fixjmp jmpout,td.otp fixjmp jmpcrt,td.crt fixjmp jmpini,td.ini fixjmp jmptch,td.tch jobidx mov jobtrm(a6),a6 10$: tst t.obx(a6) ;[101] beq 20$ ;[101] save a6 ;[101] sleep #100. ;[101] rest a6 ;[101] br 10$ ;[101] 20$: ; mov #2,t.obs(a6) ;[101] [103] mov a0,t.tdv(a6) rest a0-a3 rtn ; ; Starting here is the terminal driver that gets attached to the current ; job. It intercepts all output, deals with it, and then passes control back ; to the original terminal driver. ; lword 0 tdvnam: rad50 /TEETO / newtdv: word 0 br jmpinp br teeout br jmpech br teecrt br jmpini word 0 byte 0 byte 0 lword 0 br teetch jmpinp: blkw 3 jmpech: blkw 3 jmpcrt: blkw 3 jmpini: blkw 3 teetch: lea a2,impure mov oldtdv(a2),a2 jmptch: blkw 3 teecrt: call tcrtgl call jmpcrt call tcrtgl rtn teeout: save a0-a6,d0-d7 lea a5,impure tstw notcrt(a5) beq 3$ cmpb d1,#255. bne 2$ movw prtcrt(a5),d7 ; toggle TCRT processing status xorw #1,d7 movw d7,prtcrt(a5) ; jmp 90$ ; [104] jmp igntty ; don't display the TCRT toggle code [104] 2$: tstw prtcrt(a5) jne 90$ 3$: lea a1,datbuf(a5) mov bufsiz(a5),d0 cmp d0,#8191. jhis 90$ ; no more room in buffer... we have failed. ; bummer dude! incw column(a5) cmpb d1,#13. bne 10$ clrw column(a5) 10$: cmpb d1,#9. ; convert tabs to spaces bne 50$ ; because TRMSER will do it also movb #32.,d1 tstw notty(a5) beq 50$ ; nothing special... TRMSER will take care ; of the rest of the spacing cmp d0,#8191.-10. bhis 50$ ; can't tab-- no buffer space add d0,a1 20$: movb d1,(a1)+ inc d0 movw column(a5),d7 andw #7,d7 cmpw d7,#1 beq 80$ incw column(a5) br 20$ 50$: add d0,a1 movb d1,@a1 inc d0 80$: mov d0,bufsiz(a5) cmp d0,#512. jlos 90$ ; nothing of interest yet... call tryabt 90$: tstw notty(a5) bne igntty lcc #ps.n rest a0-a6,d0-d7 jmpout: blkw 3 igntty: mov bufsiz(a5),d7 cmp d7,#512. bhi 10$ lcc #ps.z rest a0-a6,d0-d7 rtn 10$: rest a0-a6,d0-d7 clrb d1 ; output a null in an attempt to lcc #ps.n ; suspend the host job in tow br jmpout ; try to abort the job that originally ran TeeTo, so we can steal a valid ; context to do file operations with. (can't do disk i/o in a terminal ; driver, normally) tryabt: tstw abortd(a5) jne 90$ ; already aborted, just have to wait mov ourjcb(a5),a4 movw jobsts(a4),d7 andw #j.iow!j.exw!j.smw!j.msg!j.fil!j.lok!j.sus,d7 jne 90$ ; don't abort during these states movw jobsts(a4),d7 andw #j.tow!j.tiw!j.slp,d7 ;[102] jeq 90$ ; need to be in tow, tiw, or slp state tst ddbchn bne 90$ ; DONT'T abort in the middle of disk i/o tst loksem bmi 90$ ; don't abort in LOKSER mov ourdvt(a5),a6 tst dv.sem(a6) bmi 90$ ; make sure device would be available mov dv.bmp(a6),a6 movw bm.sts(a6),d7 andw #bm$lok,d7 bne 90$ ; make sure bitmap is not locked mov jobcur,a3 cmp a3,a4 beq 90$ ; can't abort if currently running mov jobrnq+10(a4),a1 ; index saved system stack pointer mov 76(a1),oldpc(a5) ; save the job's program counter movw 74(a1),oldsr(a5) ; and status register, so the running ; process can be resumed after we're ; done with it. lea a6,iwrtbf MOV A6,76(A1) ; chain to our buffer write routine andw #^h7fff,74(a1) ; disable trace orw #^h2000,74(a1) ; set supervisor bit incw abortd(a5) 90$: rtn iwrtbf: sub #4,a7 ; reserve space for RTN [106] ; sub #6,a7 ; reserve space for RTE info [105] ; savew d0-d2 ; [105] save a0-a6,d0-d7 ; reverify that it's really ok to go ahead with this. ; (paranoid mode on) lea a5,impure tst ddbchn bne 10$ tst loksem bmi 10$ mov ourdvt(a5),a6 tst dv.sem(a6) bmi 10$ ; make sure device would be available mov dv.bmp(a6),a6 movw bm.sts(a6),d7 andw #bm$lok,d7 bne 10$ ; make sure bitmap is not locked ; (paranoid mode off) call wrtbuf ; save that buffer! 10$: ; movw oldsr(a5),60.(a7) ; [106] ; mov oldpc(a5),62.(a7) ; [106] mov oldpc(a5),60.(a7) ; [106] lsts oldsr(a5) ; [106] decw abortd(a5) rest a0-a6,d0-d7 ; rte ; [106] rtn ; [106] wrtbuf: save d0,d1,a1 cmpw abortd(a5),#1 bne 20$ clr d0 tst bufsiz(a5) beq 20$ mov jobcur,a6 pushw jobdev(a6) pushw jobdrv(a6) pushw jobusr(a6) movw ourdev(a5),jobdev(a6) movw ourdrv(a5),jobdrv(a6) movw ourppn(a5),jobusr(a6) lea a1,datbuf(a5) 10$: movb (a1)+,d1 filotb outfil(a5) jne 30$ inc d0 cmp d0,bufsiz(a5) blo 10$ 15$: clr bufsiz(a5) mov jobcur,a6 popw jobusr(a6) popw jobdrv(a6) popw jobdev(a6) 20$: rest d0,d1,a1 rtn 30$: ; mov jobcur,a6 ;[101] ; mov jobtrm(a6),a6 ;[101] ; mov oldtdv(a5),t.tdv(a6) ;[101] call rsttdv ;[101] typecr <(device error, TeeTo halted)> jmp 15$ ; output the TCRT toggle code ; tcrtgl: save d1,a5 lea a5,impure tstw notcrt(a5) beq 10$ movb #255.,d1 tty 10$: rest d1,a5 rtn rsttdv: mov jobcur,a6 ;[101] mov jobtrm(a6),a6 ;[101] mov oldtdv(a5),t.tdv(a6) ;[101] mov oldobs(a5),t.obs(a6) ;[101] rtn impure: blkb impsiz even end .