Trailing-Edge
-
PDP-10 Archives
-
bb-kl11k-bm_tops20_v7_0_tsu02_2_of_2
-
t20src/acjlog.mac
There are 9 other files named acjlog.mac in the archive. Click here to see a list.
; Edit= 16 to ACJLOG.MAC on 25-Sep-89 by GSCOTT
;Add recently implemented function from ACJUSR.MAC (up to edit 133 of ACJ).
; Edit= 15 to ACJLOG.MAC on 14-Sep-89 by GSCOTT
;Set edit number to decimal for GIMME program.
;RIP:<7.UTILITIES>ACJLOG.MAC.352 8-Apr-89 16:20:38, Edit by GSCOTT
;(14) Get latest function from ACJUSR.MAC
;RIP:<7.UTILITIES>ACJLOG.MAC.349 29-Mar-89 13:08:19, Edit by GSCOTT
;(13) Output number of files read too.
;RIP:<7.UTILITIES>ACJLOG.MAC.348 20-Mar-89 10:24:45, Edit by GSCOTT
;(12) Fix problem with FUNWDS definition.
;RIP:<7.UTILITIES>ACJLOG.MAC.341 16-Mar-89 22:27:07, Edit by GSCOTT
;(11) Add select function command.
;RIP:<7.UTILITIES>ACJLOG.MAC.295 13-Mar-89 15:45:43, Edit by GSCOTT
;(10) Output date time of first and last record read for summary.
;RIP:<7.UTILITIES>ACJLOG.MAC.289 2-Mar-89 21:48:33, Edit by GSCOTT
;(7) Be smart about output to the TTY.
;RIP:<7.UTILITIES>ACJLOG.MAC.277 26-Feb-89 14:16:38, Edit by GSCOTT
;(6) Clean up comments here and there, fix EMSG macro.
;RIP:<7.UTILITIES>ACJLOG.MAC.269 22-Feb-89 00:58:52, Edit by GSCOTT
;(5) Stats on total events.
;RIP:<7.UTILITIES>ACJLOG.MAC.253 22-Feb-89 00:07:23, Edit by GSCOTT
;(4) SELECT STATUS command.
;RIP:<7.UTILITIES>ACJLOG.MAC.217 21-Feb-89 15:45:47, Edit by GSCOTT
;(3) Add SELECT command and record parsing.
;RIP:<7.UTILITIES>ACJLOG.MAC.109 20-Feb-89 10:31:51, Edit by GSCOTT
;(2) Output header even if no entries for that day.
;RIP:<7.UTILITIES>ACJLOG.MAC.107 17-Feb-89 15:55:59, Edit by GSCOTT
;(1) Creation.
; COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1989.
; ALL RIGHTS RESERVED.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
; ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE
; INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER
; COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
; OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY
; TRANSFERRED.
;
; THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE
; AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT
; CORPORATION.
;
; DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS
; SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY DIGITAL.
TITLE ACJLOG - ACJ log file reader
SUBTTL Gregory A. Scott
COMMENT ~
Written Febuary 1989 by Gregory A. Scott, Digital Equipment Corportation,
Marlboro, Massachusetts.
This program reads the ACJ log files and produces a summary. Selection
criteria for events may be (1) event status (2) time of event (3) username.
The output is written to another file which can be displayed (or mailed).
Future enhancements to consider: selection based on event type (GETOK function
code), selection based on optional data (after the comma in each record).
~
Subttl Table of Contents
; Table of Contents for ACJLOG
;
; Section Page
;
;
; 1. Definitions
; 1.1 Version and Entry Vector . . . . . . . . . . . 4
; 1.2 Macros . . . . . . . . . . . . . . . . . . . . 5
; 1.3 Flags and Constants . . . . . . . . . . . . . 7
; 1.4 Storage
; 1.4.1 Big Buffers . . . . . . . . . . . . . . 8
; 1.4.2 Command Parsing . . . . . . . . . . . . 9
; 1.4.3 Extraction . . . . . . . . . . . . . . . 10
; 1.5 Tables
; 1.5.1 GTJFN Block Templates . . . . . . . . . 11
; 1.5.2 Main Command Tables . . . . . . . . . . 12
; 1.5.3 Select Command Tables . . . . . . . . . 13
; 1.5.4 Set Command Tables . . . . . . . . . . . 17
; 2. Initialization . . . . . . . . . . . . . . . . . . . . 18
; 3. Commands
; 3.1 Top Level . . . . . . . . . . . . . . . . . . 19
; 3.2 Begin Command . . . . . . . . . . . . . . . . 20
; 3.3 Exit Command . . . . . . . . . . . . . . . . . 21
; 3.4 Help Command . . . . . . . . . . . . . . . . . 22
; 3.5 Read Command . . . . . . . . . . . . . . . . . 23
; 3.6 Select Command . . . . . . . . . . . . . . . . 24
; 3.7 Set Command . . . . . . . . . . . . . . . . . 28
; 3.8 Show Command . . . . . . . . . . . . . . . . . 29
; 3.9 Take Command . . . . . . . . . . . . . . . . . 33
; 3.10 Write Command . . . . . . . . . . . . . . . . 36
; 3.11 Subroutines . . . . . . . . . . . . . . . . . 37
; 4. Extract . . . . . . . . . . . . . . . . . . . . . . . 41
; 4.1 Initialization . . . . . . . . . . . . . . . . 42
; 4.2 Extract One File . . . . . . . . . . . . . . . 43
; 4.3 Extract Header . . . . . . . . . . . . . . . . 44
; 4.4 Check Line . . . . . . . . . . . . . . . . . . 46
; 4.4.1 Time of Entry . . . . . . . . . . . . . 47
; 4.4.2 Username . . . . . . . . . . . . . . . . 48
; 4.4.3 Function . . . . . . . . . . . . . . . . 49
; 4.4.4 Messages . . . . . . . . . . . . . . . . 50
; 4.5 Statistics
; 4.5.1 Start . . . . . . . . . . . . . . . . . 52
; 4.5.2 Finished . . . . . . . . . . . . . . . . 53
; 4.5.3 Summary Message . . . . . . . . . . . . 54
; 5. Read Disk File
; 5.1 Get Next File . . . . . . . . . . . . . . . . 57
; 5.2 Open Input File . . . . . . . . . . . . . . . 58
; 5.3 Get Input File Byte . . . . . . . . . . . . . 59
; 5.4 Map Chunk of Pages . . . . . . . . . . . . . . 60
; 5.5 Unmap File . . . . . . . . . . . . . . . . . . 61
; 5.6 Close File . . . . . . . . . . . . . . . . . . 62
; 5.7 Error Recovery . . . . . . . . . . . . . . . . 63
Subttl Table of Contents (page 2)
; Table of Contents for ACJLOG
;
; Section Page
;
;
; 6. Write Disk File
; 6.1 Open and Close . . . . . . . . . . . . . . . . 64
; 6.2 Write Header . . . . . . . . . . . . . . . . . 65
; 6.3 Write Summary . . . . . . . . . . . . . . . . 66
; 6.4 Write String . . . . . . . . . . . . . . . . . 67
; 7. Subroutines
; 7.1 Input Time . . . . . . . . . . . . . . . . . . 68
; 7.2 Simulate SIN . . . . . . . . . . . . . . . . . 69
; 7.3 Simulate SOUT . . . . . . . . . . . . . . . . 70
; 7.4 Small Output Routines . . . . . . . . . . . . 71
; 7.5 Output Time in Milliseconds . . . . . . . . . 72
; 7.6 Output Time in Internal Format . . . . . . . . 73
; 7.7 Output Filenames and Usernames . . . . . . . . 74
; 7.8 Error Messages . . . . . . . . . . . . . . . . 75
; 8. End of ACJLOG . . . . . . . . . . . . . . . . . . . . 76
SUBTTL Definitions -- Version and Entry Vector
;Search the usual things
SEARCH MONSYM,MACSYM
.DIREC FLBLST ;First line binary only
SALL ;Clean listing
STDAC. ;Get usual ACs
.CPYRT <<1989>> ;Set copyright
;Define the version of today's program.
VMAJOR==1 ;Version
VEDIT==DEC 16 ;Edit in decimal for stupid GIMME program
VACJLOG==BYTE(3)0(9)VMAJOR(6)0(18)VEDIT+VI%DEC ;Build version number
;Define the entry vector
EV: JRST START ;Normal start
JRST START ;Reenter start
EVER: EXP VACJLOG ;Version
EVLEN==.-EV ;Length of entry vector
;Make a string with the version in it
DEFINE VG(MAJOR,EDIT),<
ASCIZ/ACJLOG MAJOR(EDIT)/>
VERS: RADIX 5+5 ;[15] Set decimal radix
VG(\VMAJOR,\VEDIT) ;[15] Make version string
RADIX 4+4 ;[15] Set octal again
SUBTTL Definitions -- Macros
;Macro to parse noise words
DEFINE NOISE (GWRD) <
MOVEI T2,[FLDDB. .CMNOI,,<-1,,[ASCIZ /GWRD/]>]
CALL COMANE>
;Macro to output just error message text.
DEFINE EMSG (TEXT),<
CALL [JSP CX,EMSG1
ASCIZ |TEXT|]
>
;Macro to catch a JSYS error. First argument is the error string to print, it
;will be followed by the last JSYS error. The second argument is optional code
;to execute and the third argument is a place to JRST to.
DEFINE JSERR(TEXT,CODE,WHERE),<
IFB <WHERE>,<
IFB <CODE>,<
ERCAL [ JSP CX,JSERR1
ASCIZ/TEXT: /]
>; End of IFB <CODE>
IFNB <CODE>,<
ERCAL [ MOVEI CX,[ASCIZ/TEXT: /]
CALL JSERR1
CODE
RET]
>; End of IFNB <CODE>
>;End of IFB <WHERE>
IFNB <WHERE>,<
ERJMP [ MOVEI CX,[ASCIZ/TEXT: /]
CALL JSERR1
CODE
JRST WHERE]
>;End of IFB <WHERE>
>;End of DEFINE JSERR
;Macro to just output a string and the last JSYS error.
DEFINE OJSERR(TEXT,CODE,WHERE),<
IFB <WHERE>,<
IFB <CODE>,<
CALL [ JSP CX,JSERR1
ASCIZ/TEXT: /]
>; End of IFB <CODE>
IFNB <CODE>,<
CALL [ MOVEI CX,[ASCIZ/TEXT: /]
CALL JSERR1
CODE
RET]
>; End of IFNB <CODE>
>;End of IFB <WHERE>
IFNB <WHERE>,<
JRST [ MOVEI CX,[ASCIZ/TEXT: /]
CALL JSERR1
CODE
JRST WHERE]
>;End of IFB <WHERE>
>;End of DEFINE JSERR
SUBTTL Definitions -- Flags and Constants
;Flags in F
ABORTF==1B1 ;Aborting current run
NOF==1B2 ;NO typed
ALLF==1B3 ;ALL typed
FILESF==1B10 ;Output filespecs as read
OTTYF==1B11 ;Output is to tty so no filespecs now
DENYF==1B14 ;Selecting denied entries
FAILF==1B15 ;Selecting failed entries
UNUSF==1B16 ;Selecting unusual entries
NORMF==1B17 ;Selecting normal status entries
;Constants.
PLEN==200 ;Generous stack
MAXLPP==^D60 ;Maximum lines per page of output file
CBUFSZ==100 ;Command buffer size in words
ABUFSZ==40 ;Atom buffer size in words
SUBTTL Definitions -- Storage -- Big Buffers
;Define a macro to allocate buffers in memory, allocated from the top of memory
;down. Pages 0-27 are reserved to the program.
APAGE==777 ;Start at the top of section zero
DEFINE ALLOCP (ASIZE,SYMBPG,SYMBBU,SYMBLP),<
APAGE==APAGE-ASIZE ;Find where to start this buffer
IFE APAGE-30,<
PRINTX ? Too much buffer space allocated
PASS2 ;Punt
END ; and get out of here
> ;End of IFE APAGE-30
SYMBPG==APAGE+1 ;Define first page number
SYMBBU=SYMBPG_9 ;Address of page map buffer
SYMBLP==SYMBPG+<ASIZE-1> ;Last page of mapping buffer
> ;End of DEFINE ALLOCP
;Allocate the pages that we will be using today.
ALLOCP (200,PGBUPG,PGBUFF,PGBULP) ;File reading page buffer
ALLOCP (20,TEXTPG,TEXTBU,TEXTLP) ;Text string (general) buffer
ALLOCP (1,LINEPG,LINEBU,LINELP) ;Line from file
ALLOCP (1,HEADPG,HEADBU,HEADLP) ;Header string from file
SUBTTL Definitions -- Storage -- Command Parsing
;Storage for command parsing
CSBLOK: BLOCK .CMGJB+1 ;Command state block
CMDBUF: BLOCK <CBUFSZ==100> ;Command buffer
ATMBUF: BLOCK <ABUFSZ==40> ;Atom buffer
GTJBLK: BLOCK .GJATR+1 ;Long form GTJFN buffer
TIMBLK: BLOCK 3 ;Place to store parsed time
PRSJFN: BLOCK 1 ;Parsing JFN
TAKJFN: BLOCK 1 ;Take file JFN
;Command state block
CSBTPL: EXP COM2 ;(.CMFLG) Reparse at COM2
XWD .PRIIN,.PRIOU ;(.CMIOJ) Input and output JFNs
POINT 7,PROMPT ;(.CMRTY) Pointer to prompt string
POINT 7,CMDBUF ;(.CMBFP) Pointer to start of buffer
POINT 7,CMDBUF ;(.CMPTR) Pointer to next input
EXP 5*CBUFSZ-1 ;(.CMCNT) Count of space remaining after .CMPTR
EXP 0 ;(.CMINC) Number of unparsed chars after .CMPTR
POINT 7,ATMBUF ;(.CMABP) Atom buffer pointer
EXP 5*ABUFSZ-1 ;(.CMABC) Atom buffer size in characters
EXP GTJBLK ;(.CMGJB) Address of long form GTJFN block
PROMPT: EXP ASCII "ACJLO",BYTE(7)"G",76,0 ;Our prompt string
SUBTTL Definitions -- Storage -- Extraction
;Misc storage.
STACK: BLOCK PLEN ;Program stack
ERRBUF: BLOCK ^D400/5 ;Place to make error strings
;Statistics storage.
RUNTIM: BLOCK 1 ;Our runtime at program start
PEOPLE: BLOCK 1 ;Elapsed time at program start
STATPA: BLOCK 1 ;Count of pages read
STATFL: BLOCK 1 ;Count of files read
STATNR: BLOCK 1 ;Count of files not read
STATEX: BLOCK 1 ;Count of events extracted
STATTE: BLOCK 1 ;Count of total events
;Storage used to read files.
INPJFN: BLOCK 1 ;The input file JFN
INPFIL: BLOCK ^D40*5 ;The input file spec
BYTPTR: BLOCK 1 ;Pointer to current data area
BYTCNT: BLOCK 1 ;Number of bytes not read in current chunk
PGSIZF: BLOCK 1 ;Pages left to read in current file
PGCHNK: BLOCK 1 ;Number of pages mapped in this chunk
PGSTAR: BLOCK 1 ;First page of used pages in file
PGMAXI: BLOCK 1 ;Maximum pages to map at a time
;Storage used in writing files.
OUTJFN: BLOCK 1 ;The output file JFN
OUTFIL: BLOCK <^D40*5>/5 ;The output file spec
;Storage used in selecting records to extract.
FSTTIM: BLOCK 1 ;Date time of first record read
LSTTIM: BLOCK 1 ;Date time of last record read
BEGTIM: BLOCK 1 ;Date time of first desired record
ENDTIM: BLOCK 1 ;Date time of last desired record
HDRTIM: BLOCK 3 ;Date time from last header record seen
SELUSR: BLOCK ^D40/5 ;Username selected
RECUSR: BLOCK ^D40/5 ;Username of current record
RECFUN: BLOCK ^D40/5 ;Function name of current record
RECMES: BLOCK ^D40/5 ;Message string
SUBTTL Definitions -- Tables -- GTJFN Block Templates
;Read command parse GTJFN block
REAGTJ: GJ%OLD!GJ%IFG!GJ%FLG!.GJALL ;(.GJGEN) Flags and generation
XWD .NULIO,.NULIO ;(.GJSRC) No JFNs
POINT 7,[ASCIZ/DSK/] ;(.GJDEV) Default device
0 ;(.GJDIR) Default directory
POINT 7,[ASCIZ /LOGFILE/] ;(.GJNAM) Default file
POINT 7,[ASCIZ /LOG/] ;(.GJEXT) Default type
0 ;(.GJPRO) No default protection
0 ;(.GJACT) No default account
0 ;(.GJJFN) No specified JFN
0 ;(.GJF2) No additional flags
;Take file GTJFN block
TAKGTJ: GJ%OLD ;(.GJGEN) Flags and generation
XWD .NULIO,.NULIO ;(.GJSRC) No JFNs
0 ;(.GJDEV) No default device
0 ;(.GJDIR) No default directory
Point 7,[ASCIZ/ACJLOG/] ;(.GJNAM) Default file
Point 7,[ASCIZ/CMD/] ;(.GJEXT) Default type
0 ;(.GJPRO) No default protection
0 ;(.GJACT) No default account
0 ;(.GJJFN) No specified JFN
0 ;(.GJF2) No additional flags
;Write command GTJFN block
WRIGTJ: GJ%FLG!GJ%DEL!GJ%FOU!GJ%FLG!GJ%MSG ;(.GJGEN) Flags and generation
XWD .NULIO,.NULIO ;(.GJSRC) No IO JFNs
POINT 7,[ASCIZ/DSK/] ;(.GJDEV) Destination logical name
0 ;(.GJDIR) Directory
POINT 7,[ASCIZ/LOGFILE/] ;(.GJNAM) File
POINT 7,[ASCIZ/SUM/] ;(.GJEXT) Type
0 ;(.GJPRO) No default protection
0 ;(.GJACT) or account
0 ;(.GJJFN) No specified JFN
0 ;(.GJF2) No extra flags
SUBTTL Definitions -- Tables -- Main Command Tables
;Command table - must be in alphabetical order
; One entry for each command in the table
; CMND(name,help,routine,noflag)
DEFINE COMGEN<
XLIST
CMND(BEGIN,<(processing)>,DOBEGI)
CMND(EXIT,<(program)>,DOEXIT)
CMND(HELP,<(message)>,DOHELP)
CMND(READ,<(log files) logfile.log.*>,DOREAD)
CMND(SELECT,<(criteria) keyword value>,DOSELE)
CMND(SET,<(mode) mode>,DOSET)
CMND(SHOW,<(status)>,DOSHOW)
CMND(TAKE,<(commands from) acjlog.cmd>,DOTAKE)
CMND(WRITE,<(summary to) logfile.sum.-1>,DOWRIT)
LIST
>
;Command table suitable for use from COMND.
DEFINE CMND(A,B,C)<
XWD [ASCIZ/A/],C
>
CMDTBL: XWD COMNUM,COMNUM ;Table header
COMGEN ;Generate top level keywords
COMNUM==.-CMDTBL-1 ;Compute number of keywords
;Table of keywords for HELP command.
DEFINE CMND(A,B,C)<
[ASCIZ\ A 'B'
\]
>
COMHLP: COMGEN ;Generate help text
HLPNUM==.-COMHLP ;Set number of entries
SUBTTL Definitions -- Tables -- Select Command Tables
;Select Command table - must be in alphabetical order
; One entry for each command in the table
; SELCOM(name,routine)
DEFINE SELGEN<
XLIST
SELCOM(BEGIN-TIME,SELBEG)
SELCOM(END-TIME,SELEND)
SELCOM(FUNCTION,SELFUN)
SELCOM(STATUS,SELSTA)
SELCOM(USER,SELUSE)
LIST
>
;Command table for SELECT command.
DEFINE SELCOM(A,B)<
XWD [ASCIZ/A/],B
>
SELTBL: XWD SELNUM,SELNUM ;Table header
SELGEN ;Generate top level keywords
SELNUM==.-SELTBL-1 ;Compute number of keywords
;Select Status Command table - must be in alphabetical order
; One entry for each command in the table
; STACOM(name,flag,noflag)
DEFINE STAGEN<
XLIST
STACOM(ALL,DENYF!FAILF!NORMF!UNUSF)
STACOM(DENIED,DENYF)
STACOM(FAILED,FAILF)
STACOM(NO,NOF)
STACOM(NORMAL,NORMF)
STACOM(UNUSUAL,UNUSF)
LIST
>
;Command table for Select Status command
DEFINE STACOM(A,B)<
XWD [ASCIZ/A/],[B]
>
STATBL: XWD STANUM,STANUM ;Table header
STAGEN ;Generate top level keywords
STANUM==.-STATBL-1 ;Compute number of keywords
;Command table for SELECT STATUS NO commands
DEFINE STACOM(A,B)<
IFN B-NOF,<XWD [ASCIZ/A/],[B]>
>
STNTBL: XWD STNNUM,STNNUM ;Table header
STAGEN ;Generate top level keywords
STNNUM==.-STNTBL-1 ;Compute number of keywords
;Select Function Command table - must be in alphabetical order
;The easiest way to maintain this tabls is to steal it from ACJUSR.MAC
DEFINE GFUNCT,<
XLIST
FUN(ACCESS,<Access>,GOACC)
FUN(ARPANET-ACCESS,<Arpanet>,GOANA)
FUN(ASSIGN-DEVICE,<Assign>,GOASD)
FUN(ASSIGN-DUE-TO-OPENF,<Open-assign>,GOOAD)
FUN(ATTACH-JOB,<Attach>,GOATJ)
FUN(CAPABILITIES,<Caps>,GOCAP)
FUN(CLASS-ASSIGNMENT,<Class>,GOCLS)
FUN(CLASS-SET-AT-LOGIN,<Class-set-at-login>,GOCL0)
FUN(CREATE-DIRECTORY,<Create-directory>,GOCRD)
FUN(CREATE-FORK,<Create-fork>,GOCFK)
FUN(CREATE-JOB,<CRJOB>,GOCJB)
FUN(CREATE-LOGICAL-NAME,<Create-logical-name>,GOCRL)
FUN(CTERM,<Cterm>,GOCTM)
FUN(DECNET-ACCESS,<DECnet>,GODNA)
FUN(DETACH,<Detach>,GODTC)
FUN(DSKOP,<DSKOP>,GODSK)
FUN(ENQ-QUOTA,<ENQ-quota>,GOENQ)
FUN(GET-DIRECTORY,<Get-directory>,GOGTD)
FUN(GETAB,<GETAB>,GOGTB)
FUN(HSYS,<HSYS>,GOHSY)
FUN(INFO,<INFO>,GOINF)
FUN(LATOP,<LATOP>,GOLAT)
FUN(LOGIN,<Login>,GOLOG)
FUN(LOGOUT,<Logout>,GOLGO)
FUN(MDDT,<MDDT>,GOMDD)
FUN(MTA-ACCESS,<MTA-access>,GOMTA)
FUN(SECURE-CHFDB,<Secure-CHFDB>,GOCFD)
FUN(SECURE-DELF,<Secure-DELF>,GODLF)
FUN(SECURE-OPENF,<Secure-OPENF>,GOOPN)
FUN(SECURE-RNAMF,<Secure-RNAMF>,GORNF)
FUN(SET-TIME,<Set-time>,GOSTD)
FUN(SJPRI,<SJPRI>,GOSJP)
FUN(SMON,<SMON>,GOSMN)
FUN(SPRIW,SPRIW,GOSPR)
FUN(STRUCTURE-MOUNT,<Str-mount>,GOSMT)
FUN(SYSGT,<SYSGT>,GOSGT)
FUN(TERMINAL-SPEED,<Terminal-speed>,GOTBR)
FUN(TLINK,<TLINK>,GOTLK)
FUN(TTMSG,<TTMSG>,GOTTM)
FUN(USER-TEST,<User-test-function>,GOUSR)
LIST
> ;End of DEFINE GFUNCT
;Command table for Select function command.
.GOUSR=400000 ;User function codes from here to 777777
DEFINE FUN(A,B,C),<
IFL .'C-.GOUSR,<XWD [ASCIZ/A/],[.'C]>
IFGE .'C-.GOUSR,<XWD [ASCIZ/A/],[0]>>
FUNTBL: XWD FUNNUM,FUNNUM ;Table header
FUNKEY: GFUNCT ;Generate top level keywords
FUNNUM==.-FUNTBL-1 ;Compute number of keywords
;TBLUK table for function keywords in log files
DEFINE FUN(A,B,C),<
IFL .'C-.GOUSR,<XWD [ASCIZ/B/],[.'C]>
IFGE .'C-.GOUSR,<XWD [ASCIZ/B/],[0]>>
FUXTBL: XWD FUXNUM,FUXNUM ;Table header
FUXKEY: GFUNCT ;Generate top level keywords
FUXNUM==.-FUXTBL-1 ;Compute number of keywords
;Define table for enable bits, defaulting to all on.
FUNMAX==0 ;Start out with max code of zero
DEFINE FUN(A,B,C),<IFL .'C-.GOUSR,<IFG .'C-FUNMAX,<FUNMAX==.'C>>>
GFUNCT ;Make MAXFUN value up
FUNWDS==1+<FUNMAX/^D36> ;Get number of words in enable table
FUNENA: REPEAT FUNWDS,<EXP -1> ;Table for enabled function bits
FUNENT: REPEAT FUNWDS,<EXP -1> ;Table for use in command
;Two little tables used whenever needed to allow ALL or NO.
ALLTBL: XWD 1,1 ;Only one keyword
XWD [ASCIZ/ALL/],[ALLF] ;All
NOTBL: XWD 1,1 ;Only one keyword
XWD [ASCIZ/NO/],[NOF] ;No
SUBTTL Definitions -- Tables -- Set Command Tables
;Set Command table - must be in alphabetical order
; One entry for each command in the table
; SETCOM(name,flag,noflag)
DEFINE SETGEN<
XLIST
SETCOM(DISPLAY-FILESPECS,FILESF,1)
SETCOM(NO,NOF,0)
LIST
>
;Command table for SET command
DEFINE SETCOM(A,B,C)<
XWD [ASCIZ/A/],[B]
>
SETTBL: XWD SETNUM,SETNUM ;Table header
SETGEN ;Generate top level keywords
SETNUM==.-SETTBL-1 ;Compute number of keywords
;Command table for SET NO commands
DEFINE SETCOM(A,B,C)<
IFN C,<XWD [ASCIZ/A/],[B]>
>
SNOTBL: XWD SNONUM,SNONUM ;Table header
SETGEN ;Generate top level keywords
SNONUM==.-SNOTBL-1 ;Compute number of keywords
SUBTTL Initialization
;Here to start up the program
START: RESET% ;The world
MOVE P,[IOWD PLEN,STACK] ;Load stack pointer
SETZM PRSJFN ;No JFNs parsing
SETZM INPJFN ; or input
SETZM OUTJFN ; or output
SETZM TAKJFN ; or command
MOVE T1,[XWD CSBTPL,CSBLOK] ;Get BLT pointer for command state block
BLT T1,CSBLOK+.CMGJB ;Move it to the command state block
;Set defaults.
TXNN F,NORMF!DENYF!FAILF!UNUSF ;Need to default flags today?
MOVX F,FILESF!DENYF!FAILF!UNUSF ;Load default flags today
SKIPN T1,ENDTIM ;Ending date set?
MOVX T1,.INFIN ;Nope, load this
MOVEM T1,ENDTIM ;Save ending date
MOVE T1,[ASCIZ/*/] ;Load default user
SKIPN SELUSR ;Any user selected yet?
MOVEM T1,SELUSR ;Nope, select user *
SKIPN T1,PGMAXI ;Maximum set?
MOVEI T1,<PGBULP-PGBUPG>+1 ;Nope load default (use it all)
MOVEM T1,PGMAXI ;Set maximum chunk size
HRROI T1,INPFIL ;Point to input file spec
HRROI T2,[ASCIZ/LOGFILE.LOG.*/] ;Point to default file spec
SKIPN INPFIL ;Any set?
CALL ISOUT ;(T1,T2/T1) Nope, set the default
HRROI T1,OUTFIL ;Point to output file spec
HRROI T2,[ASCIZ/LOGFILE.SUM/] ;Point to default file spec
SKIPN OUTFIL ;Any set?
CALL ISOUT ;(T1,T2/T1) Nope, set the default
;Give an initialization message
HRROI T1,TEXTBU ;Point to text buffer to build string
HRROI T2,VERS ;Point to version string
CALL ISOUT ;(T1,T2/T1) Start off with that string
CALL OCRLF ;(T1/T1) Append in a crlf
CALL PTEXT ;(/) Output all of that to the terminal
SUBTTL Commands -- Top Level
;Here when ready to read a command from the terminal.
COM1: TXZ F,NOF!ABORTF ;Indicate that NO not typed, not aborting
MOVEI T2,[FLDDB. .CMINI] ;Get init function
CALL COMAND ;(T2/T1,T2) Do it
JRST COMERR ;Lose big
;See if we are doing a TAKE file and if so process another line out of it.
CALL TAKCHK ;(/) Read a line from the TAKE file
;Here on a reparse.
COM2: MOVE P,[IOWD PLEN,STACK] ;Load stack pointer
SKIPE T1,PRSJFN ;Load the closed input JFN
RLJFN% ;Release it forever
ERJMP .+1 ;Ignore errors
SETZM PRSJFN ;Clear that JFN please
MOVEI T2,[FLDDB. .CMKEY,CM%HPP,CMDTBL,<a command,>] ;Point to commands
CALL COMAND ;(T2/T1,T2) Get a command
JRST COMERR ;Lose
HRRZ T2,(T2) ;Get dispatch address
CALL (T2) ;(/) Do it
JRST COM1 ;Loop for more commands
SUBTTL Commands -- Begin Command
;BEGIN (processing)
DOBEGI: NOISE (processing) ;Output the noise
CALL CONFIR ;(/T1,T2) Confirm the command
CALLRET XTRACT ;(/) Extract and dump the stuff out
SUBTTL Commands -- Exit Command
;EXIT (program)
DOEXIT: NOISE (program) ;Output the noise
CALL CONFIR ;(/) Confirm command
;Exit the program!
CALL TAKCLS ;(/) Shut off the TAKE file if any
HALTF% ;Take a dirt nap
RET ;The toe tag has been removed!
SUBTTL Commands -- Help Command
;HELP (message)
DOHELP: NOISE (message) ;Parse noise word
CALL CONFIR ;(T2/T1,T2) Confirm, maybe log or echo it
HRROI T1,TEXTBU ;Point to usual spot for such things
CALL OCRLF ;(T1/T1) Append a crlf
HRROI T2,VERS ;Point to version string
CALL ISOUT ;(T1,T2/T1) Append that string
HRROI T2,[ASCIZ/ commands:
/] ;Tell him what we are doing
CALL ISOUT ;(T1,T2/T1) Append that string
MOVSI T3,-HLPNUM ;Get number of elements in table
HELPLP: HRRO T2,COMHLP(T3) ;Get pointer to help text
CALL ISOUT ;(T1,T2/T1) Append that string
AOBJN T3,HELPLP ;Loop for all commands
CALL OCRLF ;(T1/T1) Output that final crlf
CALLRET PTEXT ;(/) Output help text and return
SUBTTL Commands -- Read Command
;READ (ACJ log file) logfile.log.*
DOREAD: NOISE (ACJ log file) ;Give noise
;Get the filespec, confirm the command, remember filename for later.
MOVE T1,[XWD REAGTJ,GTJBLK] ;Make BLT pointer for source GTJFN
BLT T1,GTJBLK+.GJF2 ;Copy GTJFN block over there
MOVEI T2,[FLDDB. .CMFIL,CM%SDH!CM%HPP,,<Source MACRO files>]
CALL COMAND ;(T2/T1,T2) Parse input filespec
IFSKP. ;If that worked
MOVEM T2,PRSJFN ;Save that as JFN for now
CALL CONFIR ;(/) Confirm the command
HRROI T1,INPFIL ;Point to filespec
MOVE T2,PRSJFN ;Load the JFN that we just got
CALLRET OJFNS ;(T1,T2/T1) Save the filespec and return
ENDIF. ;Something wrong otherwise
OJSERR (<Illegal input filespec>) ;Input owie
RET ;Return
SUBTTL Commands -- Select Command
;SELECT keyword value
DOSELE: NOISE (criteria) ;Output some noise first of course
MOVEI T2,[FLDDB. .CMKEY,,SELTBL] ;We want to parse table of SETs
CALL COMAND ;(T2/T1,T2) Parse keyword
JRST COMERR ;Owie command
HRRZ T2,(T2) ;Load address of action routine
CALLRET (T2) ;Find our way to the next command
;Here for SELECT USER command.
SELUSE: MOVEI T2,[FLDDB. .CMUSR,CM%SDH,,<Username>,,[
FLDBK. .CMFLD,CM%SDH,,<Wild user specification>,,[
EXP USRB0.,USRB1.,USRB2.,USRB3.]]]
CALL COMANE ;(T2/T1-T3) Parse username field
LDB T3,[POINTR .CMFNP(T3),CM%FNC] ;Load the function parsed
DMOVE Q2,T2 ;Copy T2 and T3 away for a second
CALL CONFIR ;(/) Confirm the command
SETZM SELUSR ;Clear first word for later checks
HRROI T1,SELUSR ;Place to keep user string
CAIE Q3,.CMFLD ;Was it the field parse?
IFSKP. ;Yes
HRROI T2,ATMBUF ;Point to atom buffer source
CALLRET ISOUT ;(T1,T2/T1) Copy the user name down there
ENDIF. ;End of field parse
MOVE T2,Q2 ;Copy the user number back
CALLRET ODIRST ;(T1,T2/T1) Send username in there and return
;Here for SELECT END-TIME and SELECT BEGIN-TIME.
SELBEG: CALL TIMFLD ;(/T2) Get time from user
MOVE Q2,T2 ;Save it
CALL CONFIR ;(/) Confirm that
MOVEM Q2,BEGTIM ;Save ending time
RET ;Return now
;Here for SELECT END-TIME.
SELEND: CALL TIMFLD ;(/T2) Get time from user
MOVE Q2,T2 ;Save it
CALL CONFIR ;(/) Confirm that
MOVEM Q2,ENDTIM ;Save ending time
RET ;Return now
;Here for SELECT FUNCTION command.
SELFUN: SETZM FUNENT ;Start out with NO ALL
IFG FUNWDS-1,< ;Only if more than one word
MOVE T1,[XWD FUNENT,FUNENT+1] ;Load BLT pointer
BLT T1,FUNENT+FUNWDS-1 ;Copy all of those words
> ;End of IFG FUNWDS-1
CALL SELFUP ;(/) Parse keywords to make FUNENT bits
MOVSI T1,-FUNWDS ;Load -wordcount,,0
DO. ;Loop throught the bits looking for one one
SKIPE FUNENT(T1) ;Skip if all bits zero
EXIT. ;At least one bit on
AOBJN T1,TOP. ;Loop for all of them
EMSG <At least one function must be selected>
RET ;Get out
OD. ;End of check for at least one bit
MOVE T1,[XWD FUNENT,FUNENA] ;Load BLT pointer
BLT T1,FUNENA+FUNWDS-1 ;Copy all of those words
RET ; and then return
;Local routine to parse function keywords list for SELECT FUNCTION comamnd.
;Returns +1 always.
SELFUP: DO. ;Loop to read function bits
MOVEI T2,[FLDDB. .CMKEY,,FUNTBL,,,[
FLDDB. .CMKEY,,NOTBL,,,[
FLDDB. .CMKEY,,ALLTBL,,,[
FLDDB. .CMCFM]]]] ;Parse this
CALL COMANE ;(T2/T1,T2,T3) Parse keyword
LDB T3,[POINTR .CMFNP(T3),CM%FNC] ;Load the function parsed
CAIN T3,.CMCFM ;Was it the confirm parse?
RET ;Yes, get out now
HRRZ P1,(T2) ;Load entry from that table
MOVE P1,(P1) ;It must contain an address
TXNN P1,NOF ;Is it NO something?
IFSKP. ;Yes
MOVEI T2,[FLDDB. .CMKEY,,FUNTBL,,,[
FLDDB. .CMKEY,,ALLTBL]] ;Parse keyword or all
CALL COMANE ;(T2/T1,T2,T3) Parse keyword
HRRZ P1,(T2) ;Load entry from that table
MOVE P1,(P1) ;Yes, get the flags
TXO F,NOF ;Set the NO flag
ENDIF. ;End of NO code
TXNN P1,ALLF ;Was it ALL?
IFSKP. ;Yes, it was ALL
SETOM FUNENT ;Assume just ALL
TXZE F,NOF ;NO set?
SETZM FUNENT ;Yes, it was NO ALL
IFG FUNWDS-1,< ;Only if more than one word
MOVE T1,[XWD FUNENT,FUNENT+1] ;Load BLT pointer
BLT T1,FUNENT+FUNWDS-1 ;Copy all of those words
> ;End of IFG FUNWDS-1
LOOP. ;Get another keyword
ENDIF. ;End of ALL code
HRRZ T2,P1 ;Load the function code from the table
IDIVI T2,^D36 ;Find word in enable table
MOVX T4,1B0 ;Load bit zero
MOVN T3,T3 ;Make -ive for LSH
LSH T4,(T3) ;Find bit position in word
IORM T4,FUNENT(T2) ;Assume that enabling this function
TXZE F,NOF ;Did I really mean to not do this?
ANDCAM T4,FUNENT(T2) ;Turn off the bit if NO said
LOOP. ;Get another keyword
OD. ;End of SELFUP
;Here for SELECT STATUS command.
SELSTA: SETZ Q1, ;Load zero for nothing selected right now
DO. ;Loop parsing keywords
MOVEI T2,[FLDDB. .CMKEY,,STATBL,,,[
FLDDB. .CMCFM]] ;We want to parse keyword or confirm
CALL COMANE ;(T2/T1,T2,T3) Parse keyword
LDB T3,[POINTR .CMFNP(T3),CM%FNC] ;Load the function parsed
CAIN T3,.CMCFM ;Was it the confirm parse?
EXIT. ;Yes, get out of loop
MOVE T2,(T2) ;Load the entry causing this
MOVE T2,(T2) ;Load the flags bits today
TXNE T2,NOF ;Is it NO?
IFSKP. ;No
TDO Q1,T2 ;Set the requested bits
LOOP. ;And get another keyword or confirm
ENDIF. ;End of its not no code
MOVEI T2,[FLDDB. .CMKEY,,STNTBL] ;We want to parse table of NO
CALL COMANE ;(T2/T1,T2) Parse keyword after "NO"
MOVE T2,(T2) ;Load the address of the flags
TDZ Q1,(T2) ;Clear the specified flag
LOOP. ;Keep getting keywords
OD. ;End of keyword reading loop
TXNE Q1,DENYF!FAILF!NORMF!UNUSF ;Any set now?
IFSKP. ;If not
EMSG <At least one message status must be selected> ;Give error
RET ; and return
ENDIF. ;Otherwise there are some set in new word
MOVE F,Q1 ;Load new flags word
RET ; and return
SUBTTL Commands -- Set Command
;SET [NO] keyword
DOSET: MOVEI T2,[FLDDB. .CMKEY,,SETTBL] ;We want to parse table of SETs
CALL COMAND ;(T2/T1,T2) Parse keyword
JRST COMERR ;Owie command
MOVE T2,(T2) ;Load the entry causing this
MOVE Q1,(T2) ;Load the flags bits today
TXNN Q1,NOF ;Is it NO?
JRST DOSET3 ;Nope, set the bt
DOSET2: MOVEI T2,[FLDDB. .CMKEY,,SNOTBL] ;We want to parse table of NO keywords
CALL COMAND ;(T2/T1,T2) Parse keyword after "NO"
JRST COMERR ;Owie command
MOVE Q1,(T2) ;Load the address of the flags
CALL CONFIR ;(/) Confirm that command
TDZ F,(Q1) ;Clear the flag specified
RET
DOSET3: CALL CONFIR ;(/) Confirm that command
TDO F,Q1 ;Set the indicated bits
RET ;Return
SUBTTL Commands -- Show Command
;SHOW (status)
DOSHOW: NOISE (status) ;Output noise
CALL CONFIR ;(/) Confirm command
HRROI T1,TEXTBU ;Point to text buffer page
;Output each item by using a table to call a response routine.
MOVSI Q1,-SHONUX ;Load -strings,,0
DO. ;For each string to output
HRRZ T3,SHOTXT(Q1) ;Load address of action routine
HLRO T2,SHOTXT(Q1) ;Load the fixed part of the string
CALL (T3) ;(Q1,T1,T2/T1) Append in desired text
AOBJN Q1,TOP. ;Loop for all of them
OD. ;End of per string loop
;Now send all of that text to terminal and return.
CALLRET PTEXT ;Output buffer and return
;For the show tables, one of the following action routines is specified.
;Called with
; Q1/ offset into tables
; T1/ Output pointer
; T2/ Pointer to fixed text, -1,,<lh of SHOTXT(Q1)>
;Returns +1 always, T1/ updated
SHOSTR: CALL ISOUT ;(T1,T2/T1) Send fixed part
HRRO T2,SHOTAB(Q1) ;Here for string, load its address
CALL ISOUT ;(T1,T2/T1) Send just the string
CALLRET OCRLF ;(T1/T1) Send a crlf last
SHODAT: CALL ISOUT ;(T1,T2/T1) Send fixed part
MOVE T2,@SHOTAB(Q1) ;Here for date time, load its address
CALL OODTIM ;(T1,T2/T1) Output date and time
CALLRET OCRLF ;(T1/T1) Send a crlf last
SHOBIT: HRROI T2,[ASCIZ/ Set /] ;Load initial text
CALL ISOUT ;(T1,T2/T1) Send first part of command
HRROI T2,[ASCIZ/no /] ;Bit is off if we say this
TDNN F,SHOTAB(Q1) ;Skip if the bit is on
CALL ISOUT ;(T1,T2/T1) Send no part
HLRO T2,SHOTXT(Q1) ;Load the fixed part of the string
CALL ISOUT ;(T1,T2/T1) Output the bit name
CALLRET OCRLF ;(T1/T1) Send a crlf last
SHOSTA: TDNE F,SHOTAB(Q1) ;Skip if the bit is off
CALL ISOUT ;(T1,T2/T1) Output fixed part if bit is on
RET ;Return
SHOFUN: CALL ISOUTC ;(T1,T2/T1,T3) Send fixed part, get length
MOVSI Q2,-FUNWDS ;Load number of function words
DO. ;Loop to check them
MOVE T2,FUNENA(Q2) ;Is this one
CAME T2,[-1] ; all ones?
EXIT. ;Nope, have to output them
AOBJN Q2,TOP. ;Loop for all of them
HRROI T2,[ASCIZ/ all/] ;Point to keyword
CALL ISOUT ;(T1,T2/T1) Send it
CALLRET OCRLF ;(T1/T1) Append crlf and return
OD. ;So its not ALL
MOVE Q3,T3 ;Copy count of characters so far
MOVSI Q2,-FUNNUM ;Load number of function words
DO. ;Loop to output them
HRRZ T2,FUNKEY(Q2) ;Load address of function code
HRRZ T2,(T2) ;Load the function code itself
IDIVI T2,^D36 ;Find word in enable table
MOVX T4,1B0 ;Load bit zero
MOVN T3,T3 ;Make -ive for LSH
LSH T4,(T3) ;Find bit position in word
TDNN T4,FUNENA(T2) ;Is the bit on?
IFSKP. ;Yes, in fact it is
MOVE T4,T1 ;Copy pointer to T4
CALL OSPACE ;(T1/T1) First a space
HLRO T2,FUNKEY(Q2) ;Load string to print
CALL ISOUTC ;(T1,T2/T1,T3) Send keyword counting
ADDI Q3,1(T3) ;Count the word and its space
CAIG Q3,^D79-2 ;Long line?
IFSKP. ;Yes
MOVE T1,T4 ;Get old pointer back
HRROI T2,[BYTE(7)" ","-",.CHCRT,.CHLFD," "," ",0] ;Cont string
CALL ISOUT ;(T1,T2/T1) Send that
MOVEI Q3,2 ;Load where we are now
LOOP. ;And start this keyword over
ENDIF. ;End of line overflow code
ENDIF. ;End of output code
AOBJN Q2,TOP. ;Loop for all of them
OD. ;End of per keyword loop
CALLRET OCRLF ;(T1/T1) Append crlf and return
;Make tables for string output above.
DEFINE SHOGEN,<
XLIST
SHO(<Status of >,VERS,SHOSTR)
SHO(< Read >,INPFIL,SHOSTR)
SHO(< Write >,OUTFIL,SHOSTR)
SHO(< Select user >,SELUSR,SHOSTR)
SHO(< Select begin >,BEGTIM,SHODAT)
SHO(< Select end >,ENDTIM,SHODAT)
SHO(< Select function>,,SHOFUN)
SHO(< Select status>,,ISOUT)
SHO(< denied>,DENYF,SHOSTA)
SHO(< failed>,FAILF,SHOSTA)
SHO(< normal>,NORMF,SHOSTA)
SHO(< unusual>,UNUSF,SHOSTA)
SHO(,,OCRLF)
SHO(<display-filespecs>,FILESF,SHOBIT)
LIST
>
;Now invoke the macro to build paralell tables.
DEFINE SHO(A,B,C),<XWD [ASCIZ\A\],C>
SHOTXT: SHOGEN
SHONUX==.-SHOTXT
DEFINE SHO(A,B,C),<EXP B>
SHOTAB: SHOGEN
SUBTTL Commands -- Take Command
;TAKE (commands from) file.typ
DOTAKE: SKIPN TAKJFN ;Are we in a TAKE now?
IFSKP. ;Yes
EMSG <Nested TAKE commands are illegal> ;Nope
JRST TAKEOF ;Abort this take command
ENDIF. ;That's all
NOISE (commands from file) ;Mumble
MOVE T1,[XWD TAKGTJ,GTJBLK] ;Make BLT pointer for source GTJFN
BLT T1,GTJBLK+.GJF2 ;Copy GTJFN block over there
MOVEI T2,[FLDDB. .CMFIL,CM%SDH,,<take filename>]
CALL COMAND ;(T1/T1,T2,T3) Get filename
JRST COMERR ;Owie
MOVEM T2,PRSJFN ;Save JFN
CALL CONFIR ;(/) Confirm that command
;Open up the file, set the I/o JFNs and so forth, and then return.
MOVE T1,PRSJFN ;Load JFN again
MOVX T2,<FLD(7,OF%BSZ)!OF%RD> ;Read 7-bit bytes
OPENF% ;Pry it open
ERJMP COMERR ;Error, return
SETZM PRSJFN ;Don't release the JFN now
MOVEM T1,TAKJFN ;Reload that JFN please
MOVE T1,TAKGTJ+.GJSRC ;Load .NULIO,,.NULIO JFNs
MOVEM T1,CSBLOK+.CMIOJ ;That is the input JFN now
RET ;Return for all commands
;Routine to call after call to .CMINI function to process take file.
;Returns +1 always
TAKCHK: SKIPN T1,TAKJFN ;Do we have a take JFN?
RET ;Nope, return now
HRROI T2,CMDBUF ;Point to command buffer
MOVEI T3,<CBUFSZ*5>-1 ;Load characters we can supply to buffer
MOVEI T4,.CHLFD ;Load terminating character
;Loop reading one command from the file. Check for hyphen at end of line.
TAKCH1: SIN% ;String INput
ERJMP TAKEOF ;Check for EOF if error
CAILE T3,<CBUFSZ*5>-4 ;Have at least 3 characters been read?
JRST TAKCH5 ;Nope, no continuation possible
MOVNI Q1,3 ;Backup by this many bytes
ADJBP Q1,T2 ;Point back three
ILDB Q2,Q1 ;Get character two back
CAIE Q2,"-" ;Hyphen?
JRST TAKCH5 ;No, cannot be continuation then
ILDB Q2,Q1 ;Get the next character
CAIN Q2,.CHCRT ;Was it a return?
JRST TAKCH1 ;Yes, get the next line also please
;Entire command line has been read now, set up CSB, echo command, and return.
TAKCH5: MOVEI T4,<CBUFSZ*5>-1 ;Load mas possible characters transferred
SUB T4,T3 ;Compute number stored in buffer
MOVEM T4,CSBLOK+.CMINC ;Save that as number of unparsed characters
MOVEI T3,0 ;Load a null character
IDPB T3,T2 ;Insure a null at end of text string
MOVE T1,CSBLOK+.CMRTY ;Load the pointer to prompt string
PSOUT% ;Send that to the terminal please
HRROI T1,CMDBUF ;Point to command buffer again
PSOUT% ;Send it to the terminal
RET ;Back in the saddle again
;Come here when error reading from take file. If IOX4 it must be the end of
;the take file, otherwise give error message. Then close the TAKE file and go
;to COM1 to start getting commands from the terminal.
TAKEOF: CALL GETERR ;(/T2) Get last error code into T2
CAIE T2,IOX4 ;Is it end of file on take command?
OJSERR (<Error reading command file>) ;Nope, mumble about error instead
HRROI T1,TEXTBU ;Point to text buffer
HRROI T2,[ASCIZ/[End of /] ;Point bracket and start of message
CALL ISOUT ;(T1,T2/T1) Send that along
MOVE T2,TAKJFN ;Reload the JFN
SETZ T3, ;Default format
JFNS% ;Make into a string
HRROI T2,[ASCIZ/]
/] ;Point to bracket cr lf string
CALL ISOUT ;(T1,T2/T1) Send that along
CALL PTEXT ;(/) Send all of that to terminal
CALL TAKCLS ;(/) Close out the take file JFN
JRST COM1 ;Restart command
;Here to close TAKE file.
;Returns +1 always.
TAKCLS: SKIPN T1,TAKJFN ;Reload the file's JFN
RET ;None there
CLOSF% ;Close it
ERCAL TAKCL3 ;Maybe it wasn't open
SETZM TAKJFN ;No more JFN
MOVE T1,CSBTPL+.CMIOJ ;Load the primary input JFN
MOVEM T1,CSBLOK+.CMIOJ ;That is the input JFN now
RET
TAKCL3: MOVE T1,TAKJFN ;Reload the JFN
RLJFN% ;Release it
ERJMP .+1 ;Ignore any error
RET ;Return to above
SUBTTL Commands -- Write Command
;WRITE (summary to) logfile.sum.-1
DOWRIT: NOISE (summary to) ;Give noise
;Get the filespec, confirm, save filespec, and return.
MOVE T1,[XWD WRIGTJ,GTJBLK] ;Make BLT pointer for source GTJFN
BLT T1,GTJBLK+.GJF2 ;Copy GTJFN block over there
MOVEI T2,[FLDDB. .CMFIL,CM%SDH!CM%HPP,,<File to write summary to>]
CALL COMAND ;(T2/T1,T2) Parse input filespec
IFSKP. ;If that worked
HRRZM T2,PRSJFN ;Save that as the JFN for now
CALL CONFIR ;(/) Confirm the command
HRROI T1,OUTFIL ;Point to output filespec
MOVE T2,PRSJFN ;Load the JFN that we just got
CALLRET OJFNS ;(T1,T2/T1) Get the full output filespec
ENDIF. ;Otherwise there was a problem
OJSERR (<Illegal output filespec>) ;Owie
RET ;Return
SUBTTL Commands -- Subroutines
;Here to parse something using COMND JSYS.
;Call with T2/ address of command function block chain
;Returns +1 if no parse
;Returns +2 if parsed OK
COMAND: MOVEI T1,CSBLOK ;Point to command state block
COMND% ;Parse that function please
ERJMP COMAN3 ;Owie if error!
TXNN T1,CM%NOP ;Error during confirm parse?
RSKP: AOS (P) ;Nope, give skip return
R: RET ;Nope, return OK
COMAN3: CALL GETERR ;(/T2) Get last error code
CAIN T2,IOX4 ;Is it "End of file reached"?
JRST COM1 ;Yes, handle it by going to COM1
RET ;No, return
;Call CONFIR to parse a confirm.
;Returns +1 always, goes to COMERR if there is a problem.
CONFIR: MOVEI T2,[FLDDB. .CMCFM] ;Point to confirm function
; CALLRET COMANE ;Get the function done possibly
;Here to perform a COMND JSYS function and go to COMERR if error.
;Call with T2/ function block
;Returns +1 always (goes to COMERR if there is a problem).
COMANE: CALL COMAND ;Do the function
JRST COMERR ;Give error message
RET ;Return to caller
;Here when some kind of command error.
COMERR: OJSERR (<ACJLOG command error>) ;Nope, an owie instead of EOF
JRST COM1 ;Reset stack and continue parsing commands
;Here to input a date time, either:
; dd-mmm-yy hh:mm[:ss]
; TODAY|NOW [+|-[hh:]mm]
; EARLIEST|LATEST
;Returns +1 always, T2/ time
TIMFLD: SAVEAC <Q1,Q2,Q3> ;Save some ACs for later
MOVEI T2,[FLDDB. .CMTAD,CM%SDH,CM%IDA!CM%ITM,<date and time>,,[
FLDDB. .CMKEY,,TIMKEY]] ;Point to functions to parse
CALL COMANE ;(T2/T1-T3) Parse date time or whatever
LDB T3,[POINTR .CMFNP(T3),CM%FNC] ;Load the function parsed
CAIN T3,.CMTAD ;Was it the date time that parsed?
RET ;Yes, return T2/ time
;Keyword parsed, dispatch to routime to do the work.
HRRZ T2,(T2) ;Load address to dispatch to
CALLRET (T2) ;(/T2) Get time base for this keyword
;Here if EARLIEST typed.
TIMEAR: SETZ T2, ;No time is less than this
RET ;Return
;Here if LATEST typed.
TIMLAT: MOVX T2,.INFIN ;Load +infinity for a time
RET ;Return that
;Here if TODAY typed.
TIMTOD: SETO T2, ;Use current time
SETZ T3, ;No special formatting flags
ODCNV% ;Get the time as seperate numbers
ERJMP .+1 ;Ignore errors
TRZ T4,-1 ;Clear seconds since midnight
IDCNV% ;Convert back to internal date time in T2
ERJMP .+1 ;Ignore errors
MOVE Q1,T2 ;Return time in proper place
CALLRET TIMOFF ;(Q1/T2) Return time in T2
;Here if NOW typed.
TIMNOW: GTAD% ;Get current time
MOVE Q1,T1 ;Return time in proper place
; CALLRET TIMOFF ;(Q1/T2) Fall through to gather offset if any
;Parse time offset (+|- hh:mm).
TIMOFF: MOVEI T2,TIMFDB ;Point to token function desc block
CALL COMAND ;(T2/T1,T2,T3) Parse one of them
CAIA ;Didn't parse, assume plus time
CAMN T3,[XWD TIMFDB,TIMFDB] ;Plus used?
SKIPA Q2,[1] ;Yes, plus or nothing, load a +1
MOVNI Q2,1 ;No, minus was used, load a -1
;Now Q1/ time base, Q2/ offset multiplier, get Q3/ minutes.
SETZ Q3, ;Load a zero offset for the time
MOVEI T2,[FLDDB. .CMNUM,CM%SDH,^D10,<minutes or hours:minutes (optional)>]
CALL COMAND ;(T2/T1,T2,T3) Parse a number for the time
IFSKP. ;If that parse minutes worked
MOVEM T2,Q3 ;Save that number of minutes
MOVEI T2,[FLDDB. .CMTOK,CM%SDH,<-1,,[ASCIZ/:/]>,<colon followed by minutes (optional)>]
CALL COMAND ;Try to parse a colon
IFSKP. ;If that parsed, minutes follow
MOVEI T2,[FLDDB. .CMNUM,CM%SDH,^D10,<minutes>] ;Parse the minutes
CALL COMANE ;(T2/T1-T3) Must furnish minutes now
IMULI Q3,^D60 ;That first number was hours, make it minutes
ADD Q3,T2 ;Get the total time offset now in minutes
ENDIF. ;End of minutes parse
ENDIF. ;End of additional time parse
;Now combine offset, flag, and time base and return that in T2.
HRLZ T2,Q3 ;Load minutes,,0 (or 0 if no minutes typed)
IDIVI T2,^D60*^D24 ;Divide by mins/day to get 0,,fraction_of_day
IMUL T2,Q2 ;Make +ive or -ive time offset
ADD T2,Q1 ;Add in time base that was specified
RET ;Return with T2/ time
;Table of keywords to parse as an alternate to date-time.
TIMKEY: XWD TIMNUM,TIMNUM ;Mini keyword table of keywords for time input
XWD [ASCIZ/EARLIEST/],TIMEAR
XWD [ASCIZ/LATEST/],TIMLAT
XWD [ASCIZ/NOW/],TIMNOW
XWD [ASCIZ/TODAY/],TIMTOD
TIMNUM==.-TIMKEY
;Function desc block for parsing plus and minus token.
TIMFDB: FLDDB. .CMTOK,CM%SDH,<-1,,[ASCIZ/+/]>,<+hours:minutes or hours:minutes (optional)>,,[
FLDDB. .CMTOK,CM%SDH,<-1,,[ASCIZ/-/]>,<-hours:minutes (optional)>]
SUBTTL Extract
;Here to read a set of files for BUGs and load them into memory.
;Returns +1 always.
XTRACT: CALL STATST ;(/) Start stats
CALL XTRINI ;(/) Init variables, open files
;Loop through each file and write selected lines from it to the output.
XLOOP: CALL FILOPN ;(/) Open input file
JRST NXTFIL ;Error, get next file
CALL XTRFIL ;(/) Extract lines from the file
CALL FILUNM ;(/) Unmap pages
CALL FILCLS ;(/) Close input file
;Here is where we cycle through to the next input file.
NXTFIL: CALL FILNXT ;(/) Get next file
JRST XLOOP ;Another file to do, loop around
;All done looping through files, close output file and return.
CALL WRISUM ;(/) Write summary info
CALL WRICLS ;(/) Close output file
CALL STATFI ;(/) Finish run
CALLRET STATUS ;(/) Output used and so forth to terminal
SUBTTL Extract -- Initialization
;Here to init varaibles before proceeding with extraction loop.
;Returns +1 always.
XTRINI: SETZM HEADBU ;No current header
MOVX T1,.INFIN ;Load +infinity for a time
MOVEM T1,FSTTIM ; set date time of first record read
SETZM LSTTIM ;Clear date time of last record read
CALL FILFND ;(/) Get a JFN on the input spec
TXOA F,ABORTF ;Can't do it
CALL WRIFND ;(/) Get a JFN for output file
TXOA F,ABORTF ;Can't do it
CALL WRIOPN ;(/) Open file for output
TXOA F,ABORTF ;Can't do it
CALLRET WRIHDR ;(/) Write our header
RET ;Return
SUBTTL Extract -- Extract One File
;Here to read through all lines in a file and write lines to the output file.
;Returns +1 always.
XTRFIL: TXNN F,OTTYF ;Not output to TTY
TXNN F,FILESF ; and display files?
IFSKP. ;Yes
HRROI T1,TEXTBU ;Point to somewhere
CALL OSPACE ;(T1/T1) Send a space
HRRZ T2,INPJFN ;Load input JFN
CALL OJFNS ;(T1,T2/T1) Send that along
CALL PTEXT ;(/) Print that
ENDIF. ;End of file print code
;For each line in the file: see if this line is a header line and handle
;specially, otheriwse see if it meets our selection criteria and if so write
;the event to the output file.
SETZ P1, ;Clear count of selected events
DO. ;For each line in the file
MOVE Q1,[Point 7,LINEBU] ;Point to place to store line
CALL FILLIN ;(Q1/) Get a line from the file
EXIT. ;EOF probably
CALL XTRHDR ;(/) See if this is a header line
LOOP. ;Yes, it was
AOS STATTE ;Count line as an event
CALL XTRSEL ;(/) Line meet selection criteria?
LOOP. ;Nope, get next line
HRROI T2,LINEBU ;Point to line buffer
CALL WRISTR ;(T2/) Yes, write out the line
AOS STATEX ;Count this bug as written
AOJA P1,TOP. ;Count event and get another line
OD. ;End of for each line loop
;Output a message indicating the number of events found today.
TXNN F,OTTYF ;Output to terminal?
TXNN F,FILESF ;Doing files?
RET ;Say nothing
HRROI T1,TEXTBU ;Point to text buffer
HRROI T2,[ASCIZ/ [/] ;Start text
CALL ISOUT ;(T1,T2/T1) Start with this string
SKIPN T2,P1 ;Load number of bugs
CALLRET PCRLF ;(/) None there, just output crlf and rtn
HRROI T3,[ASCIZ/ event/] ;Load this text to pluralize
CALL OPLURA ;(T1-T3/T1) Output events
HRROI T2,[ASCIZ/]
/] ;Close that off
CALL ISOUT ;(T1,T2/T1) Append that string in there
CALLRET PTEXT ;(/) Output that text and return
SUBTTL Extract -- Extract Header
;Here to check if first character not numeric, it may be header data.
;Writes "new" (changed) headers to output file.
;Returns +1 if header data, data stored
;Returns +2 if not header data
XTRHDR: MOVE T1,[Point 7,LINEBU] ;Point to text buffer
ILDB T2,T1 ;Load first character of the line
JUMPE T2,R ;Jump for next line if null here
CAIL T2,"0" ;Is the first character
CAILE T2,"9" ; numeric?
CAIA ;Yes
RETSKP ;Nope, give +2 return
CAIE T2,.CHFFD ;Is this a form feed?
RET ;Nope, junk header information, get next line
MOVE Q1,[Point 7,LINEBU] ;Point to utility player position
CALL FILLIN ;(Q1/) Get a line from the file
RET ;EOF probably
;Skip until second comma, then read date time on the line.
MOVEI Q1,2 ;Load number of commas to look for
MOVE Q2,[Point 7,LINEBU] ;Point to text buffer
DO. ;Loop for eating until comma
ILDB T2,Q2 ;Load a character from line
JUMPE T2,R ;If null get out of here
CAIE T2,"," ;Is it a comma?
LOOP. ;Nope, loop unconditionally
SOJG Q1,TOP. ;Yes, loop if not second one
OD. ;End of looking for mister goodcomma
MOVE T1,Q2 ;Point to the date-time
MOVX T2,0 ;No particular format options
IDTNC% ;Input Date and Time No Conversion
IFNJE. ;If that worked
DMOVEM T2,HDRTIM ;Save year,,month and day,,day_of_week
MOVEM T4,HDRTIM+2 ;Save flags,,seconds_since_midnight
ENDIF. ;End of IDTIM worked code
;Sniff line just read in and bind off with CRLF at last space before time.
MOVE T1,Q2 ;Keep pointer to where last seen space is
DO. ;Loop through this line
ILDB T2,Q2 ;Load character from line just read
CAIN T2,.CHCRT ;Is it end of header line?
EXIT. ;Yes, get out of here now
CAIN T2," " ;Was the character a space?
MOVE T1,Q2 ;Yes, remember this for later
CAIN T2,":" ;Colon?
EXIT. ;Yes, end of string to search
JUMPN T2,TOP. ;Loop unless null
OD. ;End of copy header loop
CALL OCRLF ;(T1/T1) Bind off header with CRLF string
;Now see if header line just read in is different from one stored.
MOVE Q2,[Point 7,LINEBU] ;Point to text buffer
MOVE Q3,[Point 7,HEADBU] ;Point to header buffer
DO. ;Loop through the header buffer
ILDB T2,Q2 ;Load a character from new header line
ILDB T3,Q3 ;Load character from old header line
CAIE T2,(T3) ;Characters still match?
EXIT. ;Nope, get out
JUMPN T2,TOP. ;Loop until null seen
RET ;Return now if both strings ended
OD. ;End of header check looop
;Header is different than last header, copy non matching part over.
DPB T2,Q3 ;Store first non-null non-matching character
DO. ;Copy non-matching part of header string
ILDB T2,Q2 ;Get next character in header
IDPB T2,Q3 ;Store in output place
JUMPN T2,TOP. ;Loop until null seen
OD. ;End of header copy loop
HRROI T2,HEADBU ;Pointer to header line
CALLRET WRISTR ;(T2/) Write header to file and return
SUBTTL Extract -- Check Line
;Routine to see if string in LINEBU meets selection criteria.
;Returns +1 if fails selection criteria
;Returns +2 if meets selection criteria
;Format of record is: hh:mm:ss username access-type job-info, data [message]
XTRSEL: MOVE T1,[Point 7,LINEBU] ;Point to text buffer
CALL XTRSTI ;(T1/T1) See if time criteria OK
RET ;Nope
CALL XTRSUS ;(T1/T1) See if username criteria OK
RET ;Nope
CALL XTRSFC ;(T1/T1) See if function code OK
RET ;Nope
;Parse any addition fields here before searching for "[message]".
CALL XTRSME ;(T1/) See if message criteria OK
RET ;Nope
RETSKP ;Skip return everything is OK
SUBTTL Extract -- Check Line -- Time of Entry
;Routine to read time and see if it matches time criteria.
;Call with T1/ pointer to beginning of record
;Returns +1 if no match
;Returns +2 if ok, T1/ updated
XTRSTI: CALL ITIME ;(T1/T1,T2,T3,T4) Input the time
RET ;EOF or format error, reject record
DMOVE T2,HDRTIM ;Get header year,,month and day,,0
HLL T4,HDRTIM+2 ;Get flags,,time_since_midnight
IDCNV% ;Convert that time to a universal date time
ERJMP R ;Return +1 if errors
CAMG T2,FSTTIM ;Is that time less than first time seen?
MOVEM T2,FSTTIM ;Yes, store the new first time seen
CAML T2,LSTTIM ;Is that time greater than last time seen?
MOVEM T2,LSTTIM ;Yes, store the new last time seen
CAMG T2,ENDTIM ;Is record's date-time greater than end d-t?
CAMGE T2,BEGTIM ; or record's d-t less than begin date-time?
RET ;Out of range, return +1
RETSKP ;In range, return +2
SUBTTL Extract -- Check Line -- Username
;Routine to read username and see if this record matches the username criteria.
;Call with T1/ pointing to username
;Returns +1 if no match
;Returns +2 if ok, T1/ updated
XTRSUS: HRROI T2,RECUSR ;Point to username storage for record
MOVEI T3,^D39 ;Load max string length
MOVEI T4," " ;Load terminator character
CALL ISIN ;(T1,T2,T3,T4/T1,T2,T3) Input the username
SKIPE T3 ;Unless space ran out(!)
ILDB T2,T1 ;Eat terminator character
MOVE T4,T1 ;Copy pointer to the text line over to T4
MOVE T2,SELUSR ;Load selected username
CAMN T2,[ASCIZ/*/] ;Is it all users?
RETSKP ;Yes, just return now with T1
MOVX T1,.WLSTR ;Matching strings today please
HRROI T2,SELUSR ;Load pointer to string that is wild
HRROI T3,RECUSR ;Load pointer to string to compare against
WILD% ;See if they match
ERJMP .+1 ;How could this fail?
EXCH T1,T4 ;Return the string pointer in T1 please
JUMPN T4,R ;Reject if no match
RETSKP ;Skip return to accept record
SUBTTL Extract -- Check Line -- Function
;Routine to read function and see if this record matches the function criteria.
;Call with T1/ pointing to place where function should be
;Returns +1 if no match
;Returns +2 if ok, T1/ updated
XTRSFC: HRROI T2,RECFUN ;Point to username storage for record
MOVEI T3,^D39 ;Load max string length
MOVEI T4," " ;Load terminator character
CALL ISIN ;(T1,T2,T3,T4/T1,T2,T3) Input the function
SKIPE T3 ;Unless space ran out(!)
ILDB T2,T1 ;Eat terminator space character
MOVE T4,T1 ;Copy pointer to the text line over to T4
MOVEI T1,FUXTBL ;Load address of table to look in
HRROI T2,RECFUN ;Point to string we just read in
TBLUK% ;Look it up
EXCH T4,T1 ;Swap the pointer back with the matching entry
TXNE T2,TL%NOM!TL%AMB ;No match or ambiguous?
RET ;Return +1 it can't match
HRRZ T2,(T4) ;Load the address of function code from table
MOVE T2,(T2) ;Load the function code from the table
IDIVI T2,^D36 ;Find word in enable table
MOVX T4,1B0 ;Load bit zero
MOVN T3,T3 ;Make -ive for LSH
LSH T4,(T3) ;Find bit position in word
TDNN T4,FUNENA(T2) ;Is the bit on?
RET ;Nope, function not enabled
RETSKP ;Function was enabled, keep checking
SUBTTL Extract -- Check Line -- Messages
;See if record has [text] in it and if so see if we want that type of record.
;Call with T1/ pointer to input characters
;Returns +1 if no match
;Returns +2 if match
XTRSME: SETZ Q3, ;Clear count of [status] messages
DO. ;Loop through this line
ILDB T2,T1 ;Load character from line
JUMPE T2,TOP. ;Loop if null seen
CAIE T2,.CHCRT ;End of record?
IFSKP. ;Yes
JUMPN Q3,R ;Return if record had status messages
TXNN F,NORMF ;Record is normal, including these?
RET ;Nope, do not select this record
RETSKP ;Yes, select normal status record
ENDIF. ;End of end of record code
CAIE T2,"[" ;Is this the start of a secret word?
LOOP. ;Loop for all of the characters
CALL XTRSMT ;(T1,Q3/T1,Q3) Try for a match
LOOP. ;Nope, go for next character please
RETSKP ;OK, select this record
OD. ;End of loop
;Local routine called from XTRSME when a open square bracket seen.
;Reads in the word around the brackets and sees if it is selected.
;Returns +1 to keep looking
;Returns +2 if found
XTRSMT: MOVE Q1,T1 ;Save pointer
SETZM RECMES+1 ;Clear second word of string
HRROI T2,RECMES ;Point to place to store the text
MOVEI T3,^D39 ;Load maximum characters in word
MOVEI T4,"]" ;Terminate on this one character
CALL ISIN ;(T1,T2,T3,T4/T1,T3) Copy that word
MOVE T1,Q1 ;Restore pointer in case failure
;Look for [Denied] [Failed] [Unusual] words.
DMOVE T2,RECMES ;Load the text read in today
CAMN T2,[ASCIZ/Denie/] ;Is it a
CAME T3,[ASCIZ/d/] ; denied request?
IFSKP. ;Yes
TXNE F,DENYF ;Selecting these records?
AOJA Q3,RSKP ;Yes, skip return
AOJA Q3,R ;Nope, but count this as not normal record
ENDIF. ;Not a denied request
CAMN T2,[ASCIZ/Faile/] ;Is it a
CAME T3,[ASCIZ/d/] ; failed request?
IFSKP. ;Yes
TXNE F,FAILF ;Selecting these records?
AOJA Q3,RSKP ;Yes, skip return
AOJA Q3,R ;Nope, but count this as not normal record
ENDIF. ;Not a failed request
CAMN T2,[ASCIZ/Unusu/] ;Is it a
CAME T3,[ASCIZ/al/] ; unusual request?
IFSKP. ;Yes
TXNE F,UNUSF ;Selecting these records?
AOJA Q3,RSKP ;Yes, skip return
AOJA Q3,R ;Nope, but count this as not normal record
ENDIF. ;Not a unusual request
RET ;Return +1 if word in brackets not known
SUBTTL Extract -- Statistics -- Start
;Here to initialize statistics.
;Returns +1 always
STATST: SETZM STATFL ;Zero the files looked atcount
SETZM STATNR ;Zero the files not looked at count
SETZM STATPA ;Zero the page count
SETZM STATEX ;Zero the extracted count
SETZM STATTE ;Zero the total events count
;Save runtime and elapsed time for later.
MOVEI T1,.HPRNT ;Get program runtime
HPTIM% ;From the monitor
JSERR (<HPTIM function .HPRNT failed to get initial runtime>)
MOVEM T1,RUNTIM ;Save it
MOVEI T1,.HPELP ;Get elapsed system time
HPTIM% ;From the monitor
JSERR (<HPTIM function .HPELP failed to get initial elapsed time>)
MOVEM T1,PEOPLE ;Save that
;Output the time we are starting and return.
HRROI T1,TEXTBU ;Point to the text buffer
HRROI T2,[ASCIZ/ Starting at /] ;The string to start the message with
CALL ISOUT ;(T1,T2/T1) Output starting message
SETO T2, ;The time is now
CALL OODTIM ;(T1,T2/T1) Output date and time
CALL OCRLF ;(T1/T1) and a crlf and return
CALLRET PTEXT ;(/) Output all of that text and return
SUBTTL Extract -- Statistics -- Finished
;Here when finished with taking stats.
;Call after STATST called and after work has been done.
;Returns +1 always
STATFI: MOVEI T1,.HPRNT ;Get our runtime
HPTIM% ;In high precsion units
JSERR (<HPTIM failure to get ending runtime>)
SUBM T1,RUNTIM ;Get our elapsed runtime
MOVEI T1,.HPELP ;Get the system elapsed time
HPTIM% ;In high precision units
JSERR (<HPTIM failure to get ending elapsed time>)
SUBM T1,PEOPLE ;Get our elapsed people time
;Output the finish message, starting with CPU time used.
HRROI T1,TEXTBU ;Point to the usual construction area
HRROI T2,[ASCIZ/ Finished at /] ;Normal end
CALL ISOUT ;(T1,T2/T1) Append that next
MOVE T2,T1 ;Save output pointer
GTAD% ;Load system's time and date
EXCH T2,T1 ;Swap the pointer with the time
CALL OODTIM ;(T1,T2/T1) Output time
CALL OCRLF ;(T1/T1) Finish with CRLF
CALLRET PTEXT ;(/) Output that stuff
SUBTTL Extract -- Statistics -- Summary Message
;Here to output summary message.
;Returns +1 always, just call STATFI first.
STATUS: HRROI T1,TEXTBU ;Use usual text buffer
;Summary line first.
CALL STATSU ;(T1/T1) Append in the summary line
;Next is "used blah in blah".
HRROI T2,[ASCIZ/ Used /] ;Label for next numbers
CALL ISOUT ;(T1,T2/T1) Append that label
MOVE T2,RUNTIM ;Load run time
CALL OTIME ;(T1,T2/T1) Output time
HRROI T2,[ASCIZ/ in /] ;In
CALL ISOUT ;(T1,T2/T1) Append that tiny string
MOVE T2,PEOPLE ;Load peopletime
CALL OTIME ;(T1,T2/T1) Output elapsed people time
CALL OCRLF ;(T1/T1) Finish with a crlf
;Output ratios.
CALL STATRA ;(T1/T1) Append in the ratios
;Now we are really done making all of that, output it and return.
CALLRET PTEXT ;(/) Output the ending message, return
;Output pages per CPU second and pages per people second.
;Call with T1/ output pointer
;Returns +1 always, T1/ updated
STATRA: SKIPN STATPA ;Get pages?
IFSKP. ;Yes
CALL OSPACE ;(T1/T1) A space first
FLTR T2,STATPA ;Get pages read
FLTR T3,RUNTIM ;Make it floating point
FDVR T3,[100000.0] ;Get seconds
FDVR T2,T3 ;Get pages/CPU second
CALL OFLOUT ;(T1,T2/T1) Output that
HRROI T2,[ASCIZ\ pages/CPU second, \] ;Output the label for the ratio
CALL ISOUT ;(T1,T2/T1) Ho hum that to the string
FLTR T2,STATPA ;Get pages read
FLTR T3,PEOPLE ;Float people time
FDVR T3,[100000.0] ;Get seconds
FDVR T2,T3 ;Get pages/People second
CALL OFLOUT ;(T1,T2/T1) Output that please
HRROI T2,[ASCIZ\ pages/people second
\] ;Label that last one
CALL ISOUT ;(T1,T2/T1) Output that mess next
ENDIF. ;End of pages output code
;Output events per CPU second and events per people second.
SKIPN STATEX ;Any extracted?
IFSKP. ;Yes
FLTR T2,STATEX ;Get events extracted
FLTR T3,RUNTIM ;Get floating point runtime
FDVR T3,[100000.0] ;Get seconds
FDVR T2,T3 ;Get events/CPU second
CALL OFLOUT ;(T1,T2/T1) Output that
HRROI T2,[ASCIZ\ extracted/CPU second, \] ;Ratio label
CALL ISOUT ;(T1,T2/T1) Ho hum that to the string
FLTR T2,STATEX ;Float events read
FLTR T3,PEOPLE ;Float people time
FDVR T3,[100000.0] ;Get seconds
FDVR T2,T3 ;Get events/People second
CALL OFLOUT ;(T1,T2/T1) Output that please
HRROI T2,[ASCIZ\ extracted/people second
\] ;Label that last one
CALL ISOUT ;(T1,T2/T1) Append the final text
ENDIF. ;End of event output
RET ;Now return
;Construct summary line.
;Call with T1/ output pointer
;Returns +1 always, T1/ updated
STATSU: SKIPN FSTTIM ;Any times seen?
IFSKP. ;Yes output them
HRROI T2,[ASCIZ/ Earliest at /]
CALL ISOUT ;(T1,T2/T1) Output that label
MOVE T2,FSTTIM ;Load first time seen
CALL OODTIM ;(T1,T2/T1) Output that time
HRROI T2,[ASCIZ/, latest at /]
CALL ISOUT ;(T1,T2/T1) Output that label
MOVE T2,LSTTIM ;Load last time seen
CALL OODTIM ;(T1,T2/T1) Output that time
CALL OCRLF ;(T1/T1) Send a crlf along
ENDIF. ;End of time summary
HRROI T2,[ASCIZ/ Extracted /] ;Label for following
CALL ISOUT ;(T1,T2/T1) Output that label
MOVE T2,STATEX ;Load events extracted
CALL ODEC ;(T1,T2/T1) Output that number
HRROI T2,[ASCIZ/ out of /] ;Seperator text
CALL ISOUT ;(T1,T2/T1) is appended next
MOVE T2,STATTE ;Load total events
HRROI T3,[ASCIZ/ event/] ;Load singular label
CALL OPLURA ;(T1,T2,T3/T1) Send that along
HRROI T2,[ASCIZ/ in /] ;Label for following
CALL ISOUT ;(T1,T2/T1) Output that label
MOVE T2,STATPA ;Load pages read
HRROI T3,[ASCIZ/ page/] ;Load singular label
CALL OPLURA ;(T1,T2,T3/T1) Send that along
MOVE T2,STATFL ;Load number of pages
CAIG T2,1 ;More than one?
IFSKP. ;Yes
HRROI T2,[ASCIZ/ from /] ;Label for following
CALL ISOUT ;(T1,T2/T1) Output that label
MOVE T2,STATFL ;Load pages read
HRROI T3,[ASCIZ/ file/] ;Load singular label
CALL OPLURA ;(T1,T2,T3/T1) Send that along
ENDIF. ;End of more than one file read code
CALLRET OCRLF ;(T1/T1) Append crlf and return
SUBTTL Read Disk File -- Get Next File
;Here to get next file to copy.
;Returns +1 if another file to do
;Returns +2 if done (or if aborting copy)
FILNXT: TXNE F,ABORTF ;Aborting?
RETSKP ;Yes, return now
MOVE T1,INPJFN ;Get the indexable file handle
GNJFN% ;Get the next file for that wild JFN please
ERJMP FILN2 ;Error, probably last file
RET ;Return
;Here if GNJFN error, probably last file.
FILN2: CALL GETERR ;(/T2) Get error in T2
CAIN T2,GNJFX1 ;No more files?
JRST FILN3 ;Yes, skip return
OJSERR (<GNJFN failure>) ;Nope, owie
JRST FILABT ;Abort this run
FILN3: SETZM INPJFN ;Clear JFN
RETSKP ;Skip return
SUBTTL Read Disk File -- Open Input File
;Here to get a JFN on the input filespec.
;Returns +1 if error, +2 if OK.
FILFND: MOVX T1,GJ%SHT!GJ%OLD!GJ%IFG!GJ%FLG ;Short old wild with flags
HRROI T2,INPFIL ;Point to input file spec
GTJFN% ;Get a JFN on that
JSERR (<Can't find input file>,,R)
MOVEM T1,INPJFN ;Save flags,,JFN
RETSKP ;Skip return
;Here with filename defaulted, get a JFN for the input file.
;Returns +1 if error, +2 if success and ready to copy
FILOPN: TXNE F,ABORTF ;Aborting?
RET ;Yes, return +1 now
HRRZ T1,INPJFN ;Get the JFN
MOVX T2,OF%RD+OF%PDT ;Don't change dates and read
OPENF% ;Pry it open
JSERR (<Can't open input file>,,FILERR)
;Do housekeeping associated with reading this file.
SIZEF% ;Get the file's size
JSERR (<Can't get file size>,,FILERR)
MOVEM T3,PGSIZF ;Save as pages left to read today
SETZM PGCHNK ;No last chunk transferred
SETZM PGSTAR ;Start at page 0 of the file
SETZM BYTCNT ;Clear byte count
RETSKP ; and return
SUBTTL Read Disk File -- Get Input File Byte
;We get bytes one from the file here
;Return +1 if EOF
;Return +2 if not, T1/ character
FILBYT: SOSGE BYTCNT ;Count down the bytes in the file
JRST FILBY1 ;Oops none left
ILDB T1,BYTPTR ;Get one
JUMPE T1,FILBYT ;Loop if null seen
AOS (P) ;Skip inline for speed
RET ; (JRST RSKP is one more instruction)
;Here if we need to fill the file again
FILBY1: CALL FILMAP ;(/) Map a chunk from the file
RET ;Return +1 if EOF
JRST FILBYT ;Loop for more bytes
;Routine to copy one line out of the input file.
;Call with Q1/ output byte pointer
;Returns +1 if error, +2 with line copied
FILLIN: CALL FILBYT ;(/T1) Get a byte from the file
RET ;End of file
IDPB T1,Q1 ;Store a byte there
CAIE T1,.CHCRT ;Is it a return?
JRST FILLIN ;Get more stuff
CALL FILBYT ;(/T1) Get another byte please
RET ;End of file
CAIN T1,.CHLFD ;Better be line feed
IDPB T1,Q1 ;Yes, it was, store a byte there
SETZ T1, ;Load a null
IDPB T1,Q1 ;Store it there
RETSKP ;Successful return
SUBTTL Read Disk File -- Map Chunk of Pages
;Find the (next) used and the (next) free page so that we know how much to map
;in this gulp. Returns +1 if EOF, +2 with pages mapped.
;Following are maintained in this routine:
; PGCHNK/ chunk size mapped in last try (0 at BOF)
; PGSIZF/ pages to read today (size of file in pages at BOF)
; PGSTAR/ place to start this map (0 at BOF)
; PGMAXI/ maximum size of each map
;Returns +1 if error or EOF, +2 if no error
FILMAP: SKIPE PGCHNK ;Skip if a chunk not mapped right now
CALL FILUNM ;(/) Unmap previously mapped pages
;We have a number of contiguous chunks of file, map them in
MOVE T4,PGCHNK ;Load chunk size last used
ADD T4,PGSTAR ;Compute next place to start
CAML T4,PGSIZF ;Done with all of this file yet?
RET ;Yes, reached end of file
MOVEM T4,PGSTAR ;Store new starting page
MOVE T4,PGSIZF ;Get final page number+1
SUB T4,PGSTAR ;Compute number of pages to map
CAMLE T4,PGMAXI ;Bigger than chunk size?
MOVE T4,PGMAXI ;Do a buffer worth and no more
MOVEM T4,PGCHNK ;Count these pages
HRL T1,INPJFN ;Get the input JFN
HRR T1,PGSTAR ;Map in from here
MOVX T2,<.FHSLF,,PGBUPG> ;Map to there
MOVX T3,PM%CNT!PM%RD ;With these bits not PM%PLD
HRR T3,PGCHNK ; and this page count
PMAP% ;Map them please
JSERR (<Can't map input file pages>,,FILERR) ;Abort this file
ADDM T4,STATPA ;Count as pages looked through
;We have a chunk of pages, set up the byte pointer and count then return
MOVE T3,PGCHNK ;Load count again
IMULI T3,5*1000 ;Compute ASCII bytes in the chunk
MOVEM T3,BYTCNT ;Save as byte count
MOVE T3,[Point 7,PGBUFF] ;Load byte pointer to that thing
MOVEM T3,BYTPTR ;Save as byte pointer
RETSKP ;Skip return if all OK
SUBTTL Read Disk File -- Unmap File
;Here to unmap some pages from the file window.
;Returns +1 always
FILUNM: SETO T1, ;Indicate no mapping desired
MOVX T2,<.FHSLF,,PGBUPG> ;Unmap from there
MOVE T3,PGCHNK ;Load chunk size
TXO T3,PM%CNT ;Count is in T3
PMAP% ;Map them please
JSERR (<Can't unmap input file pages>,,FILERR) ;Owie
RET
SUBTTL Read Disk File -- Close File
;This is were we close the file.
;Returns +1 always.
FILCLS: AOS STATFL ;Increment count of files read
HRRZ T1,INPJFN ;Just load the JFN
TXO T1,CO%NRJ!CZ%NUD ;Don't update disk
CLOSF% ;Slam
JSERR (<Error closing input file>)
RET ;Return
;Here to abort the input file.
;Returns +1 always.
FILCLA: AOS STATNR ;Here to abort, count one aborted
HRRZ T1,INPJFN ;Just load the JFN
TXO T1,CO%NRJ!CZ%ABT ;Don't release the JFN, abort this one
CLOSF% ;Slam
ERJMP .+1 ;Ignore errors
RET ;Return
;Here to release JFN
;Returns +1 always.
FILRLS: HRRZ T1,INPJFN ;Load the JFN
CLOSF% ;Close it
ERCAL FILRJF ;Uh oh
SETZM INPJFN ;No more JFN please
RET ;Return
FILRJF: HRRZ T1,INPJFN ;Reload JFN
RLJFN% ;Release it
ERJMP .+1 ;Ignore error
RET ; and return
SUBTTL Read Disk File -- Error Recovery
repeat 0,<
;Here to print file name for errors that we continue on.
;Returns +1 always.
FILWRN: HRROI T1,TEXTBU ;Point to text buffer
HRROI T2,[ASCIZ/ file /] ;Output label
CALL ISOUT ;(T1,T2/T1) Send that next
HRRZ T2,OUTJFN ;Load output JFN
CALL OJFNS ;(T1,T2/T1) Output the filename
HRROI T2,[ASCIZ/, will continue
/] ;Rest of the string
CALL ISOUT ;(T1,T2/T1) Send that to the file
CALLRET PTEXT ;(/) Send that to the terminal and return
> ;End of repeat 0
;Here when an error processing a input file to output the filename and next
;input file for processing today.
FILABT: HRROI T2,[ASCIZ/
Aborting command on file /] ;Load abort text
TXOA F,ABORTF ;Abort entire copy
FILERR: HRROI T2,[ASCIZ/
Skipping file /] ;Label this
HRROI T1,TEXTBU ;Point at text buffer
CALL ISOUT ;(T1,T2/T1) Start the error string
HRRZ T2,OUTJFN ;Load output JFN
CALL OJFNS ;(T1,T2/T1) Output the filename
CALL OCRLF ;(T1/T1) Append a CRLF
CALL PTEXT ;(/) Send the entire error message
;Clean up after this abort of the file.
CALL FILUNM ;(/) Unmap file pages
CALL FILCLA ;(/) Abort this input file
TXNN F,ABORTF ;Aborting?
RET ;Return to caller
CALL FILRLS ;(/) Release the JFN
JRST COM1 ;Restart command scanner
SUBTTL Write Disk File -- Open and Close
;Get a JFN for output file.
;Returns +1 if error, +2 if OK and OUTJFN set up.
WRIFND: MOVX T1,GJ%SHT!GJ%FOU ;Load short form and output bits
HRROI T2,OUTFIL ;Point to output spec
GTJFN% ;Get a JFN on that file
JSERR (<Can't use output file>,,R) ;Owie
MOVEM T1,OUTJFN ;Store JFN
DVCHR% ;Get device characteristics
ERJMP RSKP ;Ignore this if error
LOAD T3,DV%TYP,T2 ;Load device type
CAIE T3,.DVTTY ;Terminal?
TXZA F,OTTYF ;Nope
TXO F,OTTYF ;Yep
RETSKP ;Skip return
;Open output file for write.
;Returns +1 if error, +2 with file open for write
WRIOPN: HRRZ T1,OUTJFN ;Load the ouput JFN
MOVX T2,FLD(7,OF%BSZ)!OF%WR ;7 bit byte write
OPENF% ;Pry it open
JSERR (<Can't open output file>,,R) ;Owie!
RETSKP ;Nope
;Close output file.
;Returns +1 always.
WRICLS: SKIPE T1,OUTJFN ;Load output JFN
CLOSF% ;Close it
JSERR(<Can't close output file>)
SETZM OUTJFN ;Clear this since JFN closed and released
RET ;Return to caller
SUBTTL Write Disk File -- Write Header
;Routine to write header to output file.
;Returns +1 always.
WRIHDR: HRROI T1,TEXTBU ;Point to usual spot
HRROI T2,[ASCIZ/ Summary by /] ;Label next part
CALL ISOUT ;(T1,T2/T1) Send label
HRROI T2,VERS ;Point to version
CALL ISOUT ;(T1,T2/T1) Send version string
HRROI T2,[ASCIZ/ at /] ;Load little string
CALL ISOUT ;(T1,T2/T1) Append that little string in there
SETO T2, ;The time is now
CALL OODTIM ;(T1,T2/T1) Send time along
CALL OCRLF ;(T1/T1) and a crlf
HRROI T2,TEXTBU ;Point back to buffer
CALLRET WRISTR ;Send that string and return
SUBTTL Write Disk File -- Write Summary
;Routine to write summary to log file.
;Returns +1 always.
WRISUM: TXNE F,OTTYF ;Output to TTY?
RET ;Yes, return now!
HRROI T1,TEXTBU ;Point to text buffer
CALL STATSU ;(T1/T1) Make summary line
HRROI T2,[ASCIZ/ Events written to /] ;Start another line
CALL ISOUT ;(T1,T2/T1) with this string
HRRZ T2,OUTJFN ;Load output JFN
CALL OJFNS ;(T1,T2/T1) Send filename
CALL OCRLF ;(T1/T1) And a crlf
HRROI T2,TEXTBU ;Point to buffer
CALLRET WRISTR ;(T2/) Send that along to the file and return
SUBTTL Write Disk File -- Write String
;Local routine to do a SOUT.
;Call with T2/ pointer to string
;Uses WRILIN to determine what line of the file we are writing
;Returns+1 always
WRISTR: SETZB T3,T4 ;End on a null, write to file
SKIPE T1,OUTJFN ;Load JFN
SOUT% ;Send that to the file
JSERR(<Can't write output file>,,WRICLS)
RET ;Return
SUBTTL Subroutines -- Input Time
;Here to input time from a string, call with T1/ string pointer
;Returns +1 if error (illegal digits or eol)
;Returns +2 if time, T1/ updated, T2/ 0,,frac days, T3/ terminator, T4/ seconds
ITIME: CALL ITIME2 ;(T1/T1,T2,T3) Get two digits (hours)
RET ;EOF, return error
CAIE T3,":" ;Must be colon
RET ;Owie, return error
MOVE T4,T2 ;Copy the first number to T4
CALL ITIME2 ;(T1/T1,T2,T3) Get 2 digits (minutes)
RET ;Owie, something wrong
CAIE T3,":" ;Must be colon
RET ;Owie, return error
IMULI T4,^D60 ;Multiply hours by number of minutes/hour
ADD T4,T2 ;Fold in the minutes to get total
CALL ITIME2 ;(T1/T1,T2,T3) Get the next 2 digits (seconds)
RET ;Owie
CAIE T3," " ;Must be a space after the seconds
RET ;Owie
IMULI T4,^D60 ;Multiply minutes by number of seconds/minute
ADD T4,T2 ;Fold in the minutes to get total seconds
HRLZ T2,T4 ;Load minutes,,0 (or 0 if no minutes typed)
IDIVI T2,^D60*^D60*^D24 ;Divide by secs/day to get 0,,fraction_of_day
RETSKP ;Skip return T2/ frac days, T4/ seconds
;Local routine used only by ITIME routine to read two digits.
;Returns +1 if error (illegal digits or eol)
;Returns +2 if OK, T2/ number, T3/ terminator character
ITIME2: ILDB T2,T1 ;Load a digit into T2
CAIL T2,"0" ;Is it a
CAILE T2,"9" ; digit?
RET ;Nope, return error
ILDB T3,T1 ;Load a digit into T3
CAIL T3,"0" ;Is it a
CAILE T3,"9" ; digit?
RET ;Nope, return error
SUBI T2,"0" ;Convert ASCII to binary
IMULI T2,^D10 ;Shift over in the decimal radix
ADDI T2,-"0"(T3) ;Add this digit in please
ILDB T3,T1 ;Get the next character and
RETSKP ; skip return
SUBTTL Subroutines -- Simulate SIN
;Here to copy ASCIZ string, insures null at end of string.
;Call with
; T1/ source byte pointer
; T2/ destination byte pointer
; T3/ +ive count of maximum characters
; T4/ terminator character
;Returns +1 always, string copied, T1 and T2/ updated, T3/ remaining count
ISIN: TLC T1,-1 ;Complement left half
TLCN T1,-1 ;Was the left half -1?
HRLI T1,(Point 7) ;Yes, make it a byte pointer
TLC T2,-1 ;Complement left half
TLCN T2,-1 ;Was the neft half -1?
HRLI T2,(Point 7) ;Yes, make it a byte pointer
DO. ;Loop for those characters
ILDB CX,T1 ;Load a byte
SKIPE CX ;Is a null?
CAMN CX,T4 ;Is it time to quit?
EXIT. ;Yes, get out
IDPB CX,T2 ;Store that character
SOJGE T3,TOP. ;Loop for entire count please
OD. ;End of loop
SETZ CX, ;Load a null character
IDPB CX,T2 ;Store it back there please
MOVNI CX,1 ;Back up the destination byte pointer
ADJBP CX,T2 ; by one and
MOVEM CX,T2 ; store back the byte pointer
MOVNI CX,1 ;Back up the source byte pointer
ADJBP CX,T1 ; by one and
MOVEM CX,T1 ; store back the byte pointer
RET ;Return to caller with all ACs updated
SUBTTL Subroutines -- Simulate SOUT
;Here to quickly/cheaply copy ASCIZ string, insures null at end of string.
;Call with T1/ destination byte pointer, T2/ source byte pointer
;Returns +1 always, string copied, T1 and T2 updated
ISOUT: TLC T1,-1 ;Complement left half
TLCN T1,-1 ;Was the neft half -1?
HRLI T1,(Point 7) ;Yes, make it a byte pointer
TLC T2,-1 ;Complement left half
TLCN T2,-1 ;Was the neft half -1?
HRLI T2,(Point 7) ;Yes, make it a byte pointer
ISOUT1: ILDB CX,T2 ;Load a byte
IDPB CX,T1 ;Store it
JUMPN CX,ISOUT1 ;Jump if not done
MOVNI CX,1 ;Back up the byte pointer
ADJBP CX,T1 ; by one and
MOVEM CX,T1 ; store back the byte pointer
RET ;Return
;Here to copy ASCIZ string, insures null at end of string, returns length.
;Call with T1/ destination byte pointer, T2/ source byte pointer
;Returns +1 always, string copied, T1 and T2 updated, T3/ count
ISOUTC: TLC T1,-1 ;Complement left half
TLCN T1,-1 ;Was the neft half -1?
HRLI T1,(Point 7) ;Yes, make it a byte pointer
TLC T2,-1 ;Complement left half
TLCN T2,-1 ;Was the neft half -1?
HRLI T2,(Point 7) ;Yes, make it a byte pointer
SETZ T3, ;Clear the counter for this string
ISOUT4: ILDB CX,T2 ;Load a byte
IDPB CX,T1 ;Store it
JUMPE CX,ISOUT5 ;Jump if not done
AOJA T3,ISOUT4 ;Continus until null seen
ISOUT5: MOVNI CX,1 ;Back up the byte pointer
ADJBP CX,T1 ; by one and
MOVEM CX,T1 ; store back the byte pointer
RET ;Return
SUBTTL Subroutines -- Small Output Routines
;Here to output CRLF (PCRLF) or text buffer (PTEXT).
;Returns +1 always
ACRLF: ASCIZ /
/
PTEXT: SKIPA T1,[XWD -1,TEXTBU] ;Point to text area and skip always
PCRLF: HRROI T1,ACRLF ;Point to crlf
PSOUT% ;Send to terminal
RET ; and return
;Here to append a CRLF to the string pointed to by T1.
;Returns +1 always
OSPACE: SKIPA T2,[-1,,[ASCIZ/ /]] ;Point to a space string
OCRLF: HRROI T2,ACRLF ;Point to crlf string
CALLRET ISOUT ;(T1,T2/T1) Append that to string and return
;Here to output number from T2, T1/ destination pointer
;Returns +1 always
OOCT: SKIPA T3,[4+4] ;Radix 8
ODEC: MOVEI T3,5+5 ;Radix 10
NOUT% ;Kachunk
JSERR (<NOUT failed>) ;Someone out of control here
RET ;Return
;Here to output number and name of it with "S" as appropriate.
;Call with T1/destination T2/ number and T3/ pointer to ASCIZ
OPLURA: PUSH P,T3 ;Save pointer to text
CALL ODEC ;(T1,T2/T1) Output number
EXCH T2,(P) ;Save number back, get text pointer
CALL ISOUT ;(T1,T2/T1) Output that string next
POP P,T2 ;Restore number
CAIN T2,1 ;Only one?
RET ;Yep, done
HRROI T2,[ASCIZ/s/] ;Load your S up
CALLRET ISOUT ;(T1,T2/T1) Output and insure a null on end
;Here to output floating point number in T2, T1/ destination pointer
;Returns +1 always
OFLOUT: MOVX T3,FL%ONE!FL%PNT!FLD(4,FL%RND)!FLD(3,FL%SND) ;Format bits
FLOUT% ;Output that
JSERR (<FLOUT failure>) ;Snowballs exist in hell today
RET ;Return to sender
SUBTTL Subroutines -- Output Time in Milliseconds
;Output time in HPTIM units in the form "h:mm:ss.tt"
;Call with T1/ destination designator, T2/ time
;Returns +1 always
OTIME: MOVE CX,T1 ;Save output designator in dangerous spot
MOVE T1,T2 ;Copy time over
ADDI T1,^D500 ;Round up the hundredths of seconds
IDIVI T1,^D1000 ;Get units into hundredths of seconds
IDIV T1,[^D<100*60*60>] ;Get hours from hundreths of seconds
IDIVI T2,^D<100*60> ;Get minutes from fractional hours
IDIVI T3,^D100 ;Get seconds from fractional minutes
PUSH P,T4 ;Save hundredths of secs from fractional secs
PUSH P,T3 ;Save seconds
PUSH P,T2 ;Save minutes
MOVE T2,T1 ;Copy hours to T2
MOVE T1,CX ;Get output designator back from dangerous spot
MOVX T3,^D10 ;Radix 10
MOVEI T4,":" ;Load a colon for a seperator
SKIPE T2 ;Skip hours if zero
CALL OTIME1 ;(T1,T2,T3,T4/T1,T3) Output hours and a colon
POP P,T2 ;Get the minutes
SKIPE T2 ;Skip minutes if zero
CALL OTIME1 ;(T1,T2,T3,T4/T1,T3) Output minutes and colon
POP P,T2 ;Get the seconds
MOVEI T4,"." ;Seperator should be a dot
CALL OTIME1 ;(T1,T2,T3,T4/T1,T3) Output seconds and a dot
SETZ T4, ;No seperator now
POP P,T2 ;Load hundredths of seconds and fall through
OTIME1: NOUT% ;Output number
JSERR (<NOUT failed>) ;Owie
SKIPE T4 ;Any seperator character?
IDPB T4,T1 ;Yes, store it now
MOVX T3,NO%LFL!NO%ZRO!FLD(2,NO%COL)!FLD(^D10,NO%RDX) ;2 for the rest
RET ;Return to above
SUBTTL Subroutines -- Output Time in Internal Format
;Output time of day, "earliest", or "latest".
;Call with T1/ output pointer, T2/ time
;Returns +1 always, T1/ updated pointer.
OODTIM: IFE. T2 ;Is time zero?
HRROI T2,[ASCIZ/earliest/] ;Yes, load special string
CALLRET ISOUT ;(T1,T2/T1) Say this instead of 15-Nov-1858
ENDIF. ;OK, so the time wasn't zero
CAME T2,[.INFIN] ;Is it infinity?
IFSKP. ;Yes
HRROI T2,[ASCIZ/latest/] ;Say this
CALLRET ISOUT ;(T1,T2/T1) instead of 21-Sep-2217
ENDIF. ;So, it must be a normal date time
MOVX T3,OT%SCL ;Suppress columnation 9 days of the month
ODTIM% ;Zap it to terminal
JSERR (<ODTIM failed>) ;Hell is freezing over
RET ;Return
SUBTTL Subroutines -- Output Filenames and Usernames
;Small subroutine to get a filename appended to a string.
;Call with T1/ output pointer.
;Returns +1 always.
OJFNS: JUMPE T2,R ;File closed? Just return
MOVX T3,FLD(.JSSSD,JS%DEV)!FLD(.JSSSD,JS%DIR)!FLD(.JSAOF,JS%NAM)!FLD(.JSAOF,JS%TYP)!FLD(.JSAOF,JS%GEN)!JS%PAF
JFNS% ;JFN to String
JSERR(<JFNS error>) ;Owie
RET ;Return
;Routine to do a DIRST.
;Call with T1/ output designator, T2/ user or directory number (5B2+n)
;Returns +1 always, T1/ updated pointer
; T2/ user or directory number if legal,
; 0,,error if unknown or 0,,0 if not logged in
ODIRST: TRNE T2,-1 ;Not logged in?
IFSKP. ;If not logged in
HRROI T2,[ASCIZ/not-logged-in/] ;Indicate not logged in today
CALL ISOUT ;(T1,T2/T1) Send all of that to string and ret
SETZ T2, ;Indicate not logged in
RET ;Return with T1/ updated pointer and T2/ 0
ENDIF. ;End of not logged in case
MOVE T3,T1 ;Copy pointer in case error
DIRST% ;DIRectory number to STring
ERJMP .+2 ;Skip if error
RET ;Return to caller
EXCH T1,T3 ;Swap pointer with error code
HRROI T2,[ASCIZ/unknown/] ;Say something if failure
CALL ISOUT ;(T1,T2/T1) Return a string
MOVE T2,T3 ;Return error code in T2
RET ;Return pointer in T1
SUBTTL Subroutines -- Error Messages
;Subroutine to output error message
;Called from invocation of EMSG macro with CX/ address of text
;Returns +1 always.
EMSG1: HRROI T1,(CX) ;Point to the string itself
ESOUT% ;Send to terminal with question mark
RET ; and return
;Subroutine to handle JSYS errors
;Call with CX/address of ASCIZ string
;Returns +1 always, message, error, and trailing CRLF printed
JSERR1: HRROI T1,ERRBUF ;Point to text buffer
HRROI T2,(CX) ;Point to the string
CALL ISOUT ;(T1,T2/T1) Start off with that text
MOVX T2,<.FHSLF,,-1> ;This fork's last error
SETZ T3, ;No limit
ERSTR% ;Get string to error
CALL JSERR2 ;(T1/T1) Undefined error number
JFCL ;String size out of bounds or bad designator?
CALL OCRLF ;(T1/T1) Append a CRLF
CALLRET PERROR ;(/) Output error string and return
JSERR2: HRROI T2,[ASCIZ/Undefined error /] ;Output label for string
CALL GETERR ;(/T2) Get fork's last error
MOVEI T3,4+4 ;Radix 8
NOUT% ;Output that octal number
ERJMP .+1 ;Ignore error within error within error
RETSKP ;Return to finish the string
;Small routine to return this fork's last error in T2
;Returns +1 always, T2/ error number
GETERR: PUSH P,T1 ;Save T1
MOVEI T1,.FHSLF ;Load this fork
GETER% ;Get last error in T2
TLZ T2,-1 ;Zap junk in LH
POP P,T1 ;Restore T1
RET ;Return
;Small routine to display contents of error buffer.
;Returns +1 always
PERROR: HRROI T1,ERRBUF ;Point to error buffer
ESOUT% ;Output to terminal
RET ;Return to caller
SUBTTL End of ACJLOG
;Literals
LIT..: XLIST
LIT
LIST
END <EVLEN,,EV>