; Append a date/time stamp and message to a file ; ; nSTAMP.LIT (see .HLP file for docs) ; ; (C)1988 By Ami Bar-Yadin. ; AMUS ID: AMI/AM ; ; All commercial rights reserved, etc. ; ; If you want to include STAMP with a commercial package, ; go right ahead so long as you include the UNCHANGED source (.m68) with it. ; ; No warranties and/or guarranties of any kind, etc. ; ; Not responsible for damages resulting from the use of this program, etc. ; ; My employer (United Fashions) has nothing to do with this program and ; should not be blamed for it. ; ; I can be reached at: ; United Fashions of Texas, Inc. ; 200 Ash Ave. ; McAllen, TX 78501 ; (512) 631-2277/2276 ; 8am-6pm ; ; ; Revision history (latest to earliest): ; ; [102] 04/22/88 aby Released to AMUS ; Added alternate allocation of output buffer ; If there is not enough memory, STAMP will ; allocate the rest of memory except 8 bytes. ; STAMP will quit if there are not at least ; BUFMIN bytes available for the buffer. ; STAMP will now abort if the buffer gets full ; This could not really have happend before ; because of the 4Kb buffer size. ; Added buffer space countdown to text line prompt ; ; [101] 04/22/88 aby Added "An" pad type WOW! ; ; [2.1] 04/21/88 aby STAMP will now build the output in memory and will ; not write to the output file at all if there are ; ANY command line errors, ; The size of the buffer is controled by BUFSIZ. ; ; [2.0] 04/20/88 aby Major overhaul ; Redefined output and switches behavior ; Added various output switches ; Restructured mode switches to new specs ; Added text input line continuation ; with CR/LF suppress option ; ; [1.2] 10/20/86 aby Changed Default mode to Whole, added Brief mode ; Added CR after "Enter Message:" prompt ; ; CREDITS: GINDTA.SV offsets for AlphaBASE user name and user ID were ; plucked from LSTUSR.M68 available on the AMUS network. ; Unfortunatly the source does not include the author's name. ; ; And anyone else whose code I've seen for anything that may ; have been included here. ; ; L0: VMAJOR=2 VMINOR=1 VEDIT=102. SYM SEARCH SYS SEARCH SYSSYM SEARCH TRM RADIX 16. DEFAULT VEDIT,1 DEFAULT $$MFLG,PV$RSM!PV$WSM DEFAULT $$SFLG,PH$REE!PH$REU DEFAULT $$SFLG,0 DEFAULT $$LFLG,-1 PHDR $$LFLG,$$MFLG,$$SFLG EXTERN $ODTIM,$CMDER ;[102] ; offset of module name from module's (real) base ; M.NAM = 6 ; ; ascii chars ; CR = 13. LF = 10. ;[102] ; IMPGET macro (GETIMP with module name) ; IF NDF,IMPGET DEFINE IMPGET SIZE,IDX,NOMEM,MODNM1,MODNM2,MODEXT PUSH SIZE ; NOTE: MAC:SYS.M68 has PUSH #SIZE) PUSH GETMEM @SP IF B,NOMEM BEQ 10$$ EXIT 10$$: IFF JNE NOMEM ENDC POP IDX POP IF NB,MODNM1, MOVW #[MODNM1],M.NAM-ZID(IDX) IF NB,MODNM2, MOVW #[MODNM2],M.NAM+2-ZID(IDX) IF NB,MODEXT, MOVW #[MODEXT],M.NAM+4-ZID(IDX) ENDM ; allocate memory ENDC SM$D = 512. SM$T = 1 SM$W = 2 SM$N = 18678. SM$B = 0 SM$DEF = SM$W ; ; PAD$S = -1 ; pad with one space PAD$C = -2 ; comma PAD$T = -3 ; TAB PAD$A = -4 ; to field width+n [101] SPACE = 32. ; define ASCII equivelents TAB = 9. COMMA = ', BUFSIZ=4*1024. ; define size of output buffer to be 4Kb ; (51 lines of 80 chars, fill this up!) BUFMIN=80 ; define minimum buffer size as one line of 80 chars DSECT DDB: BLKB D.DDB ; output file DDB2: BLKB D.DDB ; 2nd ddb for /F use STMODE: BLKL 1 ; stamp output mode GINPTR: BLKL 1 ; pointer to MEM:GINDTA.SV OUTBUF: BLKL 1 ; pointer to beginning of output buffer OUTPTR: BLKL 1 ; pointer to next byte in output buffer OUTFRE: BLKL 1 ; number of bytes free in output buffer PADMOD: BLKB 1 ; 1..50 fixed width ; 0 natural fixed width ; PAD$S one space pad (-1) ; PAD$C comma pad (-2) ; PAD$T TAB pad (-3) PADADD: BLKB 1 ; will be added to width for PAD$A [101] ; total width must be 1..50 ECHOF: BLKB 1 ; non zero if terminal echo is on ; =2 if file output is (see /E) SNTL: BLKB 1 ; MUST be just before BUFFER and set to a non space. BUFFER: BLKB 51. ; (any value except 32.) IMPSIZ: PSECT STAMP: CALL SETUP ; allocate memory; init output buffer; ; plus misc BYP LIN JEQ USAGE ; type usage message if command line is blank CMPB @A2,#'? ; or ? JEQ USAGE ; i.e. "STAMP" or "STAMP ?" FSPEC DDB(A5),LOG ; process log file spec ; will abort on error ; output will be built in memory buffer [2.1] CALL SWITCH ; process switches CALL TXT ; process rest of command line for text CALL WRTBUF ; write buffer to file [2.1] EXIT: EXIT SETUP: IMPGET #IMPSIZ,A5,,STA,MP,IMP ; allocate impure memory INIT DDB(A5) ; initilize DDB (allocate IO buffer) INIT DDB2(A5) ; initilize DDB2 MOVB #0FF,SNTL(A5) ; set backscan stopgap for BUFFER MOV SM$DEF,STMODE(A5) ; set default stamp mode CALL INIBUF ; allocate/init output buffer [102] ; will abort on error [102] TRMRST D1 ; read terminal status OR #T$ILC,D1 ; enable lower case input TRMWST D1 ; write terminal status PUSH A2 ; save command line pointer LEA A2,PRGNAM ; set pointer to program name buffer LEA A1,L0-ZID+M.NAM ; set poitner to program name in MEM: UNPACK ; unpack program name to ASCII UNPACK POP A2 ; restore command line pointer RTN ; ;[102] added routine INIBUF ; ; Allocate and initilize output buffer ; ; INIBUF: ; try the easy way first, use standard allocate macro IMPGET #BUFSIZ,A3,10$,STA,MP,BUF ; allocate output buffer MOV #BUFSIZ,D2 ; allocated BUFSIZ bytes succesfully JMP 99$ 10$: ; gets here if simple allocation of BUFSIZ bytes fails ; now got to do it the hard way ; ; find out how much memory we've got left (everything else is already in) ; USRFRE D6 ; address of first free byte ; (just past last 0L in MEM: chain) USREND D2 ; address of last word in memory SUB D6,D2 ; D2 is bytes free SUB #8,D2 ; leave 8 bytes as safety margin ; check CMP D2,#BUFMIN ; have we got the minimum? JLOS 20$ ; YEAH TYPE MOV #BUFMIN,D1 DCVT 0,OT$TRM!OT$TSP TYPECR EXIT 20$: PUSH D2 ; I want it all! PUSH GETMEM @SP BEQ 30$ TYPE MOV D2,D1 DCVT 0,OT$TRM!OT$TSP TYPECR EXIT 30$: POP A3 POP 99$: MOV A3,OUTBUF(A5) ; initilize output buffer MOV A3,OUTPTR(A5) ; init pointer to next byte MOV D2,OUTFRE(A5) ; init free bytes count RTN ; ; terminate output buffer stream and write to output file ; WRTBUF: MOV OUTPTR(A5),A6 ; get pointer to next position in ; output buffer stream CLRB @A6 ; terminate output buffer stream MOV OUTBUF(A5),A3 ; get pointer to start of buffer CMPB ECHOF(A5),#2 ; output buffer to file? BEQ 10$ CALL OPNFIL ; open (append or create) output file LEA A2,DDB(A5) ; address output file OUTL @A3,OT$DDB ; output buffer to file CLOSE DDB(A5) ; close output file 10$: TSTB ECHOF(A5) ; echo to terminal? BEQ 99$ ; no OUTL @A3,OT$TRM ; echo output buffer to terminal 99$: RTN ; process command line switches SWITCH: 0$: BYP LIN JEQ 99$ ; exit if end of command line CMPB @A2,#'/ JNE 99$ ; exit if not switch introducer ("/") INC A2 10$: LIN JEQ 99$ ; exit if end of command line MOVB @A2,D7 CMPB D7,#SPACE BEQ 0$ ; reenter switches loop at top if blank switch CMPB D7,#'/ ; switch introducer again? BEQ 0$ ; yes, reenter switches loop at top LEA A6,SWTBL CLR D6 ; use D6 to index thru table 11$: CMPB D7,(A6)+ ; search switches table BEQ 15$ ; match! jump thru table INC D6 ; count table entries TSTB @A6 ; end of table? BNE 11$ ; no; loop till end of table 13$: LEA A1,SWERR1 ; unknown switch CALL $CMDER JMP EXIT 15$: INC A2 ; advance command line pointer LEA A6,SWJTBL ASL D6 ; computer address of jump table entry ADD D6,A6 MOVW @A6,D6 ; get offset to routine ADD D6,A6 ; compute subroutine address CALL @A6 ; execute switch processing subroutine BR 10$ ; continue switches loop 99$: RTN SWTBL: ASCIZ /AECGSJTDLPUVIF/ EVEN SWJTBL: OFFSET PSWA OFFSET PSWE OFFSET PSWC OFFSET PSWG OFFSET PSWS OFFSET PSWJ OFFSET PSWT OFFSET PSWD OFFSET PSWL OFFSET PSWP OFFSET PSWU OFFSET PSWV OFFSET PSWI OFFSET PSWF ; define Type string to Output Buffer macro DEFINE TOBUF STRING LEA A0,STRING ; get address of string CALL TOBUF ; call actual code ENDM ; ; Type string (@A0) to Output Buffer ; string must be null terminated ; updates A0 to past end of string ; ; ALL output to buffer goes thru here ; TOBUF: MOV OUTPTR(A5),A6 ; ->next byte in output buffer stream MOV OUTFRE(A5),D6 ; how many free bytes in buffer DEC D6 ; (for DBxx opcode) 10$: MOVB (A0)+,D7 ; copy string.... CMPB D7,#LF ; (skip line feeds) BEQ 10$ MOVB D7,(A6)+ ; ....to output buffer DBNE D6,10$ ; until terminating null OR buf full TST D6 BMI BUFULL ; BUFFER IS FULL DEC A6 ; next character will overlay ; terminating null ADD #2,D6 ; one for null one for DBxx MOV A6,OUTPTR(A5) ; update pointer MOV D6,OUTFRE(A5) ; update free count RTN BUFULL: TYPECR EXIT ; Switch processing subroutines ; define padding macro DEFINE DOPAD PADTYP POP A2 IF NB,PADTYP, MOV #PADTYP,D2 ; set default pad type CALL DOPAD ; process pad specs PUSH A2 ENDM ; ; process A switch: Abort if output file does not exists ; PSWA: LOOKUP DDB(A5) ; output file exists? BNE 1$ RTN ; file exists, continue as usual 1$: LEA A1,NOFILE ; file does not exits CALL $CMDER JMP EXIT ; ; process E switch: Echo output to terminal ; PSWE: MOVB #1,ECHOF(A5) ; enable terminal echo CMPB @A2,#'X ; if "/EX" BNE 99$ ; no INC A2 ; bypass "X" MOVB #2,ECHOF(A5) ; disable file output 99$: RTN ; ; process C switch: Output CR/LF pair ; PSWC: TOBUF CRLF ; place CR/LF in output buffer RTN ; ; process G switch: Set global padding default ; /G[ n | C | S |T ] ; PSWG: CALL PADSPC ; process padding specification (return D1) MOVB D1,PADMOD(A5) ; set global default padding mode CLRB PADADD(A5) ; clear additional width [101] CMPB D1,#PAD$A ; "An" pad type? [101] BNE 99$ ; no [101] MOVB D3,PADADD(A5) ; yes, set additional width value [101] 99$: RTN ; ; process S switch: Output date/time stamp with optinal format specification ; /S[ n | Fs | [ D | T | W | N | B ] ] ; PSWS: NUM BEQ 20$ ; process numeric specs CMPB @A2,#'^ BEQ 30$ ; process string flags ; ; process mode character ; MOVB @A2,D7 LEA A6,SWSTBL ; S switch mode characters/value table 10$: MOVB (A6)+,D6 ; get next valid mode char from table BEQ 15$ ; end of table - error CMPB D6,D7 ; search mode char/value table BEQ 13$ ; match ADD #3,A6 ; adjust to next table entry BR 10$ 13$: INC A2 ; adjust pointer past mode character MOVB (A6)+,D2 ; get padding type MOVW @A6,D1 ; match, get flags value BR 90$ ; set output mode and output stamp 15$: LEA A1,SWERR2 ; invalid mode character CALL $CMDER JMP EXIT ; ; process numeric mode specification ; 20$: GTOCT BMI 25$ ; if numeric error MOV #PAD$S,D2 ; pad with one space BR 90$ ; set output mode and output stamp 25$: LEA A1,SWERR3 ; invalid character in number CALL $CMDERR JMP EXIT ; ; process bit string mode specification ; 30$: MOV #PAD$S,D2 ; pad with one space INC A2 CLR D1 31$: BYP ; skip space(s) LIN JEQ 90$ ; end of line, set output mode and exit CMPB @A2,#'1 BEQ 33$ CMPB @A2,#'Y ; 1 or Y represent an ON bit BEQ 33$ CMPB @A2,#'0 ; 0 or N represent an OFF bit BEQ 32$ CMPB @A2,#'N BNE 90$ ; any other character terminates scan 32$: ASL D1 ; append a zero bit to mode value BR 31$ ; loop 33$: ASL D1 ; append a zero bit to mode value BSET #0,D1 ; change it to a one bit BR 31$ ; loop ; ; set output mode, output stamp and exit subroutine ; 90$: MOV D1,STMODE(A5) ; set STAMP output mode CALL ODTIM ; OUTPUT DATE/TIME STAMP 99$: RTN ; return to switches loop ; define switch /Sx table entry macro DEFINE SWSENT CHAR,ODTFLG,PADTYP ; mode char, $ODTIM format, pad type BYTE CHAR,PADTYP WORD ODTFLG ENDM SWSTBL: SWSENT 'D,SM$D,9. ; date only stamp, width 9 SWSENT 'T,SM$T,8. ; time only stamp, width 8 SWSENT 'W,SM$W,22. ; whole stamp, width 22 SWSENT 'N,SM$N,42. ; normal (full) stamp, width 42 SWSENT 'B,SM$B,18. ; brief stamp, width 18 ; ; Process J switch: Output job name with optional padding specification ; /J[ n | C | S | T ] ; PSWJ: PUSH A2 ; save command line pointer ; setup job's name in BUFFER LEA A2,BUFFER(A5) ; address work buffer JOBIDX ; get JCB pointer LEA A1,JOBNAM(A6) ; point to job name in JCB UNPACK ; unpack job name to ASCII UNPACK CLRB @A2 ; terminate job name string DOPAD 6 ; process pad specs TOBUF BUFFER(A5) ; copy work buffer to output buffer POP A2 ; restore command line pointer RTN ; return to switches loop ; ; Process T switch: Output terminal name with optional padding spcification ; /T[ n | C | S | T ] ; PSWT: PUSH A2 ; save command line pointer ; setup terminal name in BUFFER LEA A2,BUFFER(A5) JOBIDX ; get JCB pointer MOV JOBTRM(A6),A6 ; get TCB pointer LEA A1,-4(A6) ; point to terminal name before TCB UNPACK UNPACK CLRB @A2 DOPAD 6 ; process pad specs TOBUF BUFFER(A5) ; send to output buffer POP A2 ; restore command line pointer RTN ; return to switches loop ; ; Process D switch: Output terminal driver name with optional padding spcification ; /D[ n | C | S | T ] ; PSWD: PUSH A2 ; save command line pointer ; setup terminal driver name in BUFFER LEA A2,BUFFER(A5) JOBIDX ; get JCB pointer MOV JOBTRM(A6),A6 ; get TCB pointer MOV T.TDV(A6),A6 ; get TDV poiner LEA A1,-4(A6) ; point to driver name before TDV entry point UNPACK UNPACK CLRB @A2 DOPAD 6 ; process pad specs TOBUF BUFFER(A5) ; copy to output buffer POP A2 ; restore command line pointer RTN ; return to switches loop ; ; Process L switch: Output login location with optional padding specification ; /L[ n | C | S | T ] ; PSWL: PUSH A2 ; save command line pointer ; setup logged in location in BUFFER LEA A2,BUFFER(A5) JOBIDX A3 ; get JCB pointer LEA A1,JOBDEV(A3) UNPACK ; unpack device name CLR D1 MOVW JOBDRV(A3),D1 DCVT 0,OT$MEM ; unpack drive number MOVB #':,(A2)+ MOVB #'[,(A2)+ CALL OPPN ; unpack PPN MOVB #'],(A2)+ CLRB @A2 DOPAD 15. ; process pad specs TOBUF BUFFER(A5) ; copy to output buffer POP A2 ; restore command line pointer RTN ; return to switches loop OPPN: PUSHW JOBTYP(A3) ; save radix MOVW #^CJ.HEX,D7 ANDW D7,JOBTYP(A3) ; set octal MOVW JOBUSR(A3),D1 PUSHW D1 ; save D1 LSRW D1,#8 OCVT 0,OT$MEM ; unpack project number MOVB #COMMA,(A2)+ ; a comma POPW D1 ; get original D1 AND #0FF,D1 OCVT 0,OT$MEM ; unpack programmer number POPW JOBTYP(A3) ; restore radix RTN ; ; Process P switch: Output program name with optional padding specification ; /P[ n | C | S | T ] ; ; of course, program name will always be the name of the STAMP program; ; that is "STAMP" unless the program is renamed. ; PSWP: PUSH A2 ; save command line pointer ; setup program name in BUFFER LEA A2,BUFFER(A5) JOBIDX ; get JCB pointer LEA A1,JOBPRG(A6) ; point to program name in JCB UNPACK UNPACK CLRB @A2 DOPAD 6 ; process pad specs TOBUF BUFFER(A5) ; copy to output buffer POP A2 ; restore command line pointer RTN ; return to switches loop ; ; Process U switch: Output User name with optional padding specification ; /U[ n | C | S | T ] ; ; AMOSL 1.3 or latter ONLY ; PSWU: PUSH A2 ; save command line pointer ; setup user name in BUFFER LEA A2,BUFFER(A5) JOBIDX ; get JCB pointer LEA A1,JOBUSR(A6) ; point to user name in JCB MOV #20.-1,D6 ; 20 chars is max user name (-1 for DBxx) 1$: MOVB (A1)+,(A2)+ ; copy user name to buffer DBEQ D6,1$ CLRB @A2 DOPAD 20. ; process pad specification TOBUF BUFFER(A5) ; copy to output buffer POP A2 ; restore command line pointer RTN ; return to switches loop ; ; Process V switch: Output AlphaBase user name with optional padding specification ; /V[ n | C | S | T ] ; ; ONLY if GINDTA.SV is in MEM: ; ; PSWV: CALL FGINDT ; find MEM:GINDTA.SV (return A3) BNE 10$ LEA A1,SWERR4 ; Can't find MEM:GINDTA.SV CALL $CMDER JMP EXIT 10$: PUSH A2 ; save command line pointer ; setup user name in BUFFER LEA A2,BUFFER(A5) LEA A1,4C4(A3) ; point to user name in GINDTA MOV #30.-1,D6 ; 30 chars is max user name (-1 for DBxx) 20$: MOVB (A1)+,(A2)+ ; copy user name to buffer DBEQ D6,20$ CLRB @A2 DOPAD 30. ; process pad specification TOBUF BUFFER(A5) ; copy to output buffer POP A2 ; restore command line pointer RTN ; return to switches loop ; ; Process I switch: Output AlphaBase user ID with optional padding specification ; /I[ n | C | S | T ] ; ; ONLY if GINDTA.SV is in MEM: ; ; PSWI: CALL FGINDT ; find MEM:GINDTA.SV (return A3) BNE 10$ LEA A1,SWERR4 ; Can't find MEM:GINDTA.SV CALL $CMDER JMP EXIT 10$: PUSH A2 ; save command line pointer ; setup user ID in BUFFER LEA A2,BUFFER(A5) LEA A1,4BE(A3) ; point to user name in GINDTA MOV #6-1,D6 ; 6 chars is max user name (-1 for DBxx) 20$: MOVB (A1)+,(A2)+ ; copy user name to buffer DBEQ D6,20$ CLRB @A2 DOPAD 6 ; process pad specification TOBUF BUFFER(A5) ; copy to output buffer POP A2 ; restore command line pointer RTN ; return to switches loop ; ; process F switch: Output file name and version (if any) ; /Ffile ; Default extension is .LIT ; PSWF: FSPEC DDB2(A5),LIT ; process file spec (abort on error) OPENI DDB2(A5) PUSH A2 ; save command line pointer LEA A2,BUFFER(A5) ; address work buffer ; output file name to work buffer OFILE DDB2(A5),OT$MEM!OT$OFD!OT$OFN!OT$OFP CLRB @A2 ; terminate file name string DOPAD PAD$S ; pad buffer with one space TOBUF BUFFER(A5) ; copy to output buffer INPUT DDB2(A5),,0 ; Get first block MOV D.BUF+DDB2(A5),A4 ; get address of disk IO buffer ADD D.IDX+DDB2(A5),A4 ; adjust according to index CMPW @A4,#-1 ; program header exists? BEQ 10$ ; yes CMPW @A4,#-2 ; the other header prefix JNE 90$ ; no header 10$: LEA A2,BUFFER(A5) ; address work buffer VCVT 2(A4),OT$MEM ; output version to work buffer CLRB @A2 ; terminate file name string DOPAD PAD$S ; pad buffer with one space TOBUF BUFFER(A5) ; copy to output buffer 90$: POP A2 ; restore command line pointer RTN ; process text ; TXT: MOV OUTPTR(A5),A3 ; get pointer to output buffer stream MOV OUTFRE(A5),D3 ; get free bytes count BYP LIN BEQ 30$ ; no text on command line, prompt user CMPB (A2)+,#'! BNE TXT ; ; output text ; 0$: 10$: MOVB (A2)+,D1 BEQ 99$ ; end of text CMPB D1,#CR ; CR is end of text BEQ 99$ CMPB D1,#LF ; LF is end of text BEQ 99$ CMPB D1,#'+ ; + is end of text line/continue BEQ 20$ MOVB D1,(A3)+ DEC D3 BNE 10$ ; buffer still has room JMP BUFULL ; buffer is full ; ; process "+" or "++" ; 20$: CMPB @A2,#'+ ; (2nd "+") suppress CR/LF? BEQ 30$ ; yes MOVB #CR,(A3)+ ; output CR(/LF) to output buffer DEC D3 JEQ BUFULL ; buffer is full ; ; prompt user for continuation line ; 30$: TYPE MOV D3,D1 DCVT 0,OT$TRM!OT$TSP TYPECR KBD EXIT BR 0$ 99$: MOVB #CR,(A3)+ DEC D3 ; no buffer full check is done here MOV A3,OUTPTR(A5) ; update output buffer stream pointer MOV D3,OUTFRE(A5) CLRB @A3 RTN ; ; process padding mode specification ; return pad type in D1 ; return n in D3 for "An" (i.e. /GA3) ; PADSPC: NUM BNE 10$ ; process non-numeric specs ; ; process numeric field width ; GTDEC BPL 1$ LEA A1,SWERR3 ; invalid number CALL $CMDER EXIT 1$: CMPB D1,#50 BLE 99$ ; ok, exit LEA A1,SWERR5 ; fixed field width greater than 50 CALL $CMDER EXIT ; ; process non-numeric padding specification ; 10$: LEA A6,PADTBL ; padding character/value table MOVB @A2,D7 13$: CMPB D7,(A6)+ ; search padding table BEQ 16$ ; match; get value, set mode and exit INC A6 ; skip value byte TSTB @A6 ; end of table? BNE 13$ ; loop until end of table ; if end of table reached, set natural mode ; (neat little shortcut here: A6 points to the NULL table terminator ; and natural mode is a zero, so...) BR 17$ 16$: INC A2 ; advance A2 past padding spec 17$: CLR D1 MOVB @A6,D1 ; (match) get value from table and... CMPB D1,#PAD$A ; pad type "An"? [101] BNE 99$ ; no [101] PUSH D1 ; [101] GTDEC ; get n value [101] MOV D1,D3 ; [101] POP D1 ; [101] 99$: RTN PADTBL: BYTE 'A,PAD$A,'C,PAD$C,'S,PAD$S,'T,PAD$T,0 ; [101] EVEN ;[101] ; Override field padding type (D2) ; D1 is overriding padding type ; D3 is (optional: only if D1=PAD$A) additional field width ; SETPAD: TSTB D1 ; is there an override? BEQ 99$ ; no (or /G0 which is the same anyway) CMPB D1,#PAD$A ; is override a "An" type? BNE 90$ ; no TSTB D2 ; is default field padding a fixed field? BMI 99$ ; no, IGNORE /G value ADDB D3,D2 ; add /GAn value to field width BEQ 10$ ; erorr if resulting width = 0 BMI 10$ ; error if <0 (signed byte) CMPB D2,#50. BLE 99$ ; ok if <=50. 10$: LEA A1,SWERR6 ; field width out of range (<=0 or >50) CALL $CMDER JMP EXIT 90$: MOVB D1,D2 ; override natural pad type 99$: RTN ; ; processing optional padding spec for an output switch ; modify BUFFER as needed ; D2 is natural field width ; DOPAD: ; override natural width with global default if set up PUSH D2 ; save default padding for field MOVB PADMOD(A5),D1 ; get global default [101] MOVB PADADD(A5),D3 ; get optional additional width [101] CALL SETPAD ; override field pad if global default exists CALL PADSPC ; process padding spec (return D1) TSTB D1 ; user supplied padding type? BEQ 20$ ; no POP D2 ; restore original field padding type CALL SETPAD ; override field pad with user specs ; (if supplied) PUSH D2 20$: TSTB D2 BMI 30$ ; process S C or T modes ; ; process fixed width ; LEA A6,BUFFER(A5) DEC D2 22$: TSTB (A6)+ ; scan BUFFER to NULL or end of field DBEQ D2,22$ TSTW D2 BMI 99$ ; end of field reached, terminate string DEC A6 23$: MOVB #SPACE,(A6)+ DBEQ D2,23$ BR 99$ ; terminated string and exit ; ; process C S or T ; ; first, find end of string in BUFFER ; 30$: LEA A6,BUFFER(A5) 31$: TSTB (A6)+ ; scan BUFFER to terminating NULL BNE 31$ ; (A STATEMENT WITH INFINITE POTENTIAL) DEC A6 ; back to terminating null ; ; now scan BACKWARDS past any (trailing) spaces ; 32$: CMPB -(A6),#SPACE ; backscan past any trailing spaces BEQ 32$ ; will stop >for sure< on SNTL(impure) ; ; now append a space, a comma or a TAB to the string ; INC A6 ; move back to first of the trailing spaces CMPB D2,#PAD$C ; comma? BNE 33$ MOVB #COMMA,(A6)+ ; append a comma BR 99$ ; terminate string and exit 33$: CMPB D2,#PAD$S ; space? BNE 34$ MOVB #SPACE,(A6)+ ; append a space BR 99$ 34$: MOVB #TAB,(A6)+ ; append a TAB 99$: CLRB @A6 ; terminate string POP D2 ; restore field padding type RTN ; ; print help stuff ; USAGE: LEA A2,HLPCMD AMOS EXIT HLPCMD: ASCII /HELP / PRGNAM: ASCIZ /123456/ ; will be overlayd with program's name EVEN ; at startup ; ; OPEN OUTPUT FILE FOR APPEND, OR CREATE IF FILE DOES NOT EXISTS ; OPNFIL: LOOKUP DDB(A5) BEQ 1$ OPENO DDB(A5) BR 99$ 1$: OPENA DDB(A5) 99$: RTN ; ; find MEM:GINDTA.SV return A3 ; FGINDT: TST GINPTR(A5) ; have we located GINDTA? BEQ 10$ ; no, search for it MOV GINPTR(A5),A3 ; yes, get address RTN ; return with NE for success 10$: SRCH GINDTA,A3,F.USR BEQ 20$ ; BRANCH IF FOUND MEM:GINDTA.SV CLR GINPTR(A5) ; can't find GINDTA RTN ; return with EQ for fail 20$: MOV A3,GINPTR(A5) ; save address in case we need it again TST GINPTR(A5) RTN ; return with NE for success GINDTA: RAD50 /GINDTASV / ; ; OUTPUT DATE/TIME STAMP ACCORDING TO MODE IN STMODE(impure) ; ODTIM: PUSH A2 ; save command line pointer PUSH D2 ; save padding type LEA A2,BUFFER(A5) ; ODTIM will output to this buffer CLR D3 CLR D4 CLR D5 MOV STMODE(A5),D5 AND #07FFF,D5 ; FORCE BITS 15-31 OFF CALL $ODTIM CLRB @A2 ; terminated date/time stamp string POP D2 ; restore padding type DOPAD ; pad according to stamp type ; (unless /Gx override) TOBUF BUFFER(A5) ; place BUFFER in output buffer POP A2 ; restore command line pointer RTN ; ; ASCII TEXT AREA ; ; General purpose text ; CRLF: BYTE CR,0 ; (LF will be inserted by OUTL in ; WRTBUF routine) ; ; Error messages text ; NOFILE: BYTE CR,LF ASCIZ /%Output file not found; aborting as requested./ SWERR1: BYTE CR,LF ASCIZ /?Unknown switch/ SWERR2: BYTE CR,LF ASCIZ /?Invalid date output mode character/ SWERR3: BYTE CR,LF ASCIZ /?Invalid number/ SWERR4: BYTE CR,LF ASCIZ /?AlphaBASE user data requested but GINDTA.SV is not in MEM:/ SWERR5: BYTE CR,LF ASCIZ /?Fixed field width greater than 50/ SWERR6: BYTE CR,LF ASCIZ /?Resulting field width is less than zero or greater than 50/ EVEN ; ; END .