Trailing-Edge
-
PDP-10 Archives
-
SRI_NIC_PERM_SRC_3_19910112
-
utilities/peruse.mac
There are no other files named peruse.mac in the archive.
;ACCT:<SU-UTILITIES>PERUSE.MAC.18, 18-May-83 20:38:27, Edit by F.FMF
;Add top-level FIRST and LAST commands
;ACCT:<SU-UTILITIES>PERUSE.MAC.17, 18-Apr-83 16:52:01, Edit by F.FMF
;Flush CFIBF% to allow typeahead
;ACCT:<SU-UTILITIES>PERUSE.MAC.16, 30-Mar-83 15:18:23, Edit by F.FMF
;Add PREVIOUS command
TITLE PERUSE - A FILE PERUSER
SUBTTL DEFINITIONS
;WRITTEN JANUARY 1980 BY KIRK LOUGHEED
;CODE FOR STRING SEARCH ALGORITHM BY MAN CHOR KO
SEARCH MONSYM, MACSYM
.REQUIRE SYS:MACREL.REL
ASUPPRESS
XALL
;ASSEMBLY SWITCHES
;THE REGISTERS
T1=1
T2=2
T3=3
T4=4
CHAR=5 ;CURRENT CHARACTER
FILBYT=6 ;FOR INDEXING INTO BP TO ACCESS BYTES IN FILE
FILWRD=7 ;CURRENT WORD IN FILE
TEMP=10 ;USED ONLY IN FSRCH
PAGE1=11 ;FIRST PAGE OF CURRENT RANGE
PAGE2=12 ;LAST PAGE OF CURRENT RANGE
FPOS=13 ;POSITION IN FIND ARRAY
P=17 ;STACK POINTER
OPDEF SKPA [TRNA]
;PARAMETERS
PAGE==30 ;PAGE USED BY PMAP
STKLEN==50 ;STACK LENGTH
BUFLEN==50 ;BUFFER LENGTH FOR VARIOUS BUFFERS
BUFCHR==BUFLEN*5-1 ;NUMBER OF CHARS IN A BUFFER OF LENGTH BUFLEN
BPTBSZ==276 ;SIZE OF INDEXING BYTE POINTER TABLE
ALPHSZ==^D128 ;SIZE OF THE ALPHABET
MXPATL==^D97 ;MAXIMUM SEARCH PATTERN LENGTH
PTBUFL==MXPATL/5+1 ;PATTERN BUFFER LENGTH
BIG=1750 ;THIS WILL CAUSE DELTA1 TO INCREMENT BIG
MAXFP=2000 ;LARGE ARRAY FOR PAGE RANGES FOUND
INFLG== GJ%OLD!GJ%DEL!GJ%IFG ;FLAGS FOR AN INPUT FILE SPEC
SUBTTL MACRO DEFINITIONS
;MACSYM-TYPE CHARACTER DEFINITIONS
.CHDQT==42 ;DOUBLE QUOTE
.CHSQT==47 ;SINGLE QUOTE
CM%HPP==CM%HPP!CM%SDH ;WITH OWN HELP, SUPPRESS NORMAL HELP
CM%FIX==0 ;This feature may go away, so work without it.
;MACRO TO PRINT A CRLF ON THE SCREEN
DEFINE OCRLF <
CALL [ TMSG <
> ;OUTPUT A CRLF
RET ]
>
;MACRO TO CALL COMMAND JSYS SUBROUTINE
DEFINE PARSE (TYPE) <
MOVEI T2,TYPE ;THE OBVIOUS WAY
CALL PARSER ;DOES A COMND
>
;FIELD DESCRIPTOR BLOCK MACRO (A SHUFFLED VERSION OF FLDDB.)
DEFINE FIELD (FUNCTION,DATA,NEXT,HELP,FLAGS) <
..XX==CM%FIX ;ALWAYS FIX UP IF AVAILABLE
IFNB <FLAGS>,<..XX==FLAGS!CM%FIX> ;THROW IN FLAGS IF ANY
FLDDB. FUNCTION,\..XX,<DATA>,<HELP>,,<NEXT>
>
;SPECIAL PARSE MACROS
DEFINE NOISE (STRING) <PARSE <[FIELD .CMNOI,<-1,,[ASCIZ STRING]>]>>
DEFINE CONFRM <
CALL [ MOVEI T2,JUSTCR ;SLIGHTLY BETTER SEQUENCE FOR
CALLRET PARSER ] ;FREQUENTLY USED CALL
>
;MACRO USED IN BUILDING KEYWORD TABLES
DEFINE X (STRING,ADDRESS,FLAGS) <
[IFNB <FLAGS>,<FLAGS!CM%FW!CM%INV>
ASCIZ STRING],,ADDRESS
>
SUBTTL COMMAND LOOP
;THINGS TO PARSE
SETUP: FIELD .CMINI
COMAND: FIELD .CMKEY,COMTAB
FILSPC: FIELD .CMFIL
JUSTCR: FIELD .CMCFM,,,<press RETURN>
;THE COMMAND TABLE
COMTAB: COMLEN,,COMLEN
X (ADVANCE,ADVANC)
X (COPY,COPY)
X (EXIT,EXIT)
X (F,FNDCMD,CM%ABR) ;ABBREV FOR FIND
X (FI,FIRCMD,CM%ABR) ;ABBREV FOR FIRST
FNDCMD: X (FIND,FIND)
FIRCMD: X (FIRST,FIRST)
X (GET,GET)
X (HELP,HELP)
X (L,LASCMD,CM%ABR) ;ABBREV FOR LAST
LASCMD: X (LAST,LAST)
X (LIST,LISTIT)
X (N,NEXCMD,CM%ABR) ;ABBREV FOR NEXT
NEXCMD: X (NEXT,NEXTPG)
X (NO-PAUSE,TENPAU)
X (P,PRVCMD,CM%ABR) ;ABBREV FOR PREVIOUS
X (PAUSE,TEPAU)
PRVCMD: X (PREVIOUS,PREVPG)
X (QUIT,QUIT)
X (SHOW,SHOW)
X (TYPE,TYPE)
COMLEN==.-COMTAB-1
START: RESET% ;INITIALIZE WORLD
MOVE P,[IOWD STKLEN, STACK] ;SET UP THE STACK
SETZM STRBUF ;NO SEARCH STRING YET
SETZM JFN ;NO FILE YET
CALL SETINT ;SET UP INTERRUPT HANDLER
CALL CHKSCN ;CHECK RESCAN BUFFER
NEWCOM: PARSE SETUP ;INITIALIZE COMMAND STATE BLOCK
HRRZ T1,CSTATE ;SHOULD BE JUMP TO RPARSE, BUT OK IF NOT
JRST (T1)
RPARSE: MOVE P,[IOWD STKLEN, STACK] ;IN CASE OF REPARSE
SETOM OKINT ;PERMIT CTRL/O INTERRUPTS
PARSE COMAND
HRRZ T2,(T2) ;GET SUBROUTINE ADDRESS
CALL (T2) ;TRANSFER TO CORRECT SUBROUTINE
JRST NEWCOM ;CALL(T2) INSTEAD OF JRST(T2) PAYS DIVIDENDS
SUBTTL EXIT AND HELP COMMANDS
EXIT: CONFRM
RESET%
SETZM JFN
SETZM TJFN
SKPA
QUIT: CONFRM
HALTF%
RET
;HERE ON THE HELP COMMAND
HELP: CONFRM
HRROI T1,HLPMSG
PSOUT% ;PRINT THE HELP MESSAGE
RET ;RETURN TO COMMAND LOOP
XLIST ;DON'T CREF THIS LITERAL
HLPMSG: ASCIZ\
PERUSE is a general purpose file perusal program. To get a file, type GET and
the file name to the PERUSE> prompt. You may also use the rescan buffer,
i.e., by typing "peruse myfile.txt" to the EXEC you will enter PERUSE with
that file. Wildcards (* and %) are permitted in the file specification, e.g.,
PERUSE> GET myfile.txt
PERUSE> GET *.pgo
Below is a summary of the commands. Note that a page refers to a disk page.
GET Get the first file of the file group specified. A file group is
obtained by using a wildcard such as '*' in the file specification,
e.g. <s.smith>*.pgo is the file group consisting of all files with
the 'pgo' extension in the directory <s.smith>.
ADVANCE Advance to the next file in the file group.
TYPE Type a page or range of pages in the current file. You may specify
only one page, a range of pages, the next page, the previous page, the
first page, the last page, or all pages. If no page is specified,
then the current page is used. You may also specify NEXT without
first saying TYPE. Below are some examples.
PERUSE> TYPE (PAGE) 1
PERUSE> TYPE (PAGE) 3 (TO PAGE) 10
PERUSE> TYPE (PAGE) NEXT
PERUSE> TYPE (PAGE) PREVIOUS
PERUSE> TYPE (PAGE) FIRST
PERUSE> TYPE (PAGE) LAST
PERUSE> TYPE (PAGE) ALL
PERUSE> NEXT (PAGE)
CTRL/O will abort the typeout of the current page.
FIND Search the entire file for a string, reporting the pages on which it
occurs, if any. Once a search string is specified, the FIND command
will default to that string until a new search string is given. The
search string is remembered from file to file.
PERUSE> FIND (STRING) Foo Bar
"FOO BAR" occurs on page(s) 3,4,10
PERUSE> ADVANCE (TO NEXT FILE IN GROUP)
PERUSE> FIND
"FOO BAR" occurs on page(s) 1,3
SHOW Display information on the current file, including the file group
specification, the current file specification, the file length, and
the current page. The current page is what is typed if you do not
give an argument to the TYPE command.
COPY Copy a range of pages into another file. This command can be used to
break up extremely large files into smaller components.
PERUSE> COPY (INTO FILE) myfile.out (PAGE) 45 (TO PAGE) 63
LIST List a range of pages on the lineprinter.
PERUSE> LIST (PAGE) 45 (TO PAGE) 50
PAUSE When your screen fills up, terminal output will pause until you type
^Q (hold down CTRL and press Q). This is the normal case, and you
need do nothing in order to get this mode.
NO-PAUSE Terminal output will not pause when your screen fills up, but you
may still type ^S (hold down CTRL and press S) to make the output
pause. As usual, type ^Q to resume the output.
QUIT Leave PERUSE.
EXIT Flush current file and group, then leave PERUSE.
\
LIST ;RESUME CREFFING
SUBTTL RESCAN BUFFER ROUTINE
;HERE TO CHECK RESCAN BUFFER FOR A FILE SPEC.
;RETURNS +1 ALWAYS
CHKSCN: STKVAR <<RSCBUF,20>>
MOVEI T1,.RSINI ;READ FROM RESCAN BUFFER
RSCAN% ;DO IT
ERJMP CHKX ;BOMBED, RETURN NOW
JUMPE T1,R ;NOTHING IN RESCAN BUFFER, JUST RETURN
CHKSN1: MOVNM T1,T3 ;PUT -COUNT INTO C
MOVEI T1,.PRIIN
HRROI T2,RSCBUF ;PUT IT IN THIS BUFFER
SIN% ;GET THE INPUT
MOVE T2,[POINT 7,RSCBUF]
DO.
ILDB T1,T2 ;GET A BYTE
CAIN T1,.CHLFD ;A LINE FEED?
RET ;GO BACK NOW
CAIE T1," " ;A SPACE?
CAIN T1,.CHTAB ;OR A TAB?
SKPA
LOOP. ;IF NEITHER, THEN LOOKS LIKE WE NEED MORE
ENDDO.
DO.
MOVEM T2,T3 ;SAVE POINTER
ILDB T1,T2 ;GET A CHAR
CAIN T1," " ;A SPACE?
LOOP. ;YES, GET ANOTHER
ENDDO.
MOVE T2,T3 ;NO, RESTORE POINTER
DO.
ILDB T1,T3 ;GET A CHAR
CAIE T1,.CHLFD ;A LF?
CAIN T1,.CHCRT ;OR A CR?
EXIT. ;EITHER, GO OUT
LOOP. ;OTHERWISE LOOP
ENDDO.
SETZ T1, ;GET A NULL
DPB T1,T3 ;DROP END OF FILE SPEC WITH NULL
MOVX T1,INFLG!GJ%SHT ;WANT SHORT FORM FOR INPUT FILESPEC
GETJFN: GTJFN%
ERJMP CHKX ;BOMBED
USEJFN: MOVEM T1,JFN ;WE'RE COMMITTED TO THIS JFN
CALL MAKSTR ;STORE TEXT FORM OF JFN
CALL OPEN ;TRY TO OPEN FILE
JRST GETX ;GO SEE IF ANY WILDCARDS
FILLEN: CALL FILE ;PRINT FILE NAME
CALLRET LENGTH ;AND SIZE, AND RETURN
;HERE ON VARIOUS JSYS ERRORS
CHKX: CALL WARN ;WHAT HAPPENED
ZJFN: HRRZ T1,JFN ;RELEASE JFN, IF ANY
RLJFN%
NOP ;IGNORE ERROR
SETZM JFN ;SIGNAL NO FILE
RET
;HERE ON OPEN FAILURE, TRY NEXT FILE IN GROUP
GETX: MOVE T1,JFN ;GET THE OFFENDING JFN
TLNE T1,(GJ%DEV!GJ%DIR!GJ%NAM!GJ%EXT!GJ%VER) ;WILDCARDS?
JRST ADV1 ;YES, TRY NEXT FILE IN GROUP
JRST ZJFN ;SET NO JFN FLAG AND RETURN TO COMMAND LOOP
SUBTTL GET A FILE
;HERE TO GET A NEW FILE
GET: NOISE (FILES IN GROUP)
CALL IFILE ;PARSE INPUT FILE
CONFRM
CALL CLOSE ;DISPOSE OF THE OLD ONE
MOVE T1,TJFN ;NEW JFN
JRST USEJFN ;SET UP FILE GROUP AND RETURN TO COMMAND
COMMENT \
;TOP (OF FILE GROUP) COMMAND
TOP: CALL CHKFIL ;WANT TO BE ABLE TO ASSUME REALLY HAVE ONE
RET ;GO HOME IF NONE YET
NOISE (OF FILE GROUP)
CONFRM
CALL CLOSE ;DISPOSE OF OLD ONE
MOVSI T1,(INFLG!GJ%SHT) ;SHORT FORM ON IN-CORE STRING
HRROI T2,JFNSTR
\
;HERE ON THE ADVANCE COMMAND
ADVANC: CALL CHKFIL ;SKIP IF WE HAVE A FILE
RET ;NO FILE SPEC GIVEN YET
NOISE (TO NEXT FILE IN GROUP)
CONFRM
ADV1: MOVSI T1,(CO%NRJ) ;SET RETAIN JFN BIT
HRR T1,JFN ;DON'T CLOBBER THAT BIT
CLOSF% ;CLOSE THE FILE
NOP ;NOT INTERESTED IN FAILURE HERE
ADV2: MOVE T1,JFN ;USE FULL JFN
GNJFN% ;GET NEXT FILE
ERJMP ADVDON ;LOOKS LIKE WE'RE DONE
CALL OPEN ;NOW TRY TO OPEN
JRST ADV2 ;FAILED, SO LOOK AT NEXT FILE
JRST FILLEN ;DISPLAY FILE NAME AND ITS LENGTH
ADVDON: CALL NEWLIN
TMSG <No more files in this group
> ;SAY WHAT PROBABLY HAPPENED
JRST ZJFN ;FLAG NOT CURRENT JFN AND RETURN
SUBTTL TYPE, LIST, AND COPY COMMANDS
;HERE ON THE TYPE COMMAND
TYPE: CALL RANGE ;GET OUR RANGE
RET ;ILLEGAL RANGE
TYPO: MOVEI T2,.PRIOU ;OUTPUT JFN
MOVEM T2,TJFN
CALL COPPAG ;COPY THE RANGE OF PAGES TO THE SCREEN
OCRLF ;A PARTING CRLF
RET ;RETURN TO COMMAND LEVEL
NEXTPG: CALL CHKFIL ;DO WE HAVE AN INPUT FILE?
RET ;NO FILE
NOISE (PAGE)
CONFRM
CALL RNGNXT ;CALCULATE NEXT PAGE
CAMLE T2,SIZE ;CHECK IT
CALLRET RNGOVR
MOVE T1,T2 ;DUPLICATE IT
DMOVEM T1,PAGE1 ;SET IT
JRST TYPO ;DO IT
PREVPG: CALL CHKFIL ;DO WE HAVE AN INPUT FILE?
RET ;NO FILE
NOISE (PAGE)
CONFRM
CALL RNGPRV ;CALCULATE PREVIOUS PAGE
SKIPG T1,T2 ;DO WE HAVE A VALID PAGE NUMBER?
CALLRET RNGUND
DMOVEM T1,PAGE1 ;SET IT
JRST TYPO ;DO IT
FIRST: CALL CHKFIL ;DO WE HAVE AN INPUT FILE?
RET ;NO FILE
NOISE (PAGE) ;GUIDE WORD
CONFRM
MOVEI PAGE1,1 ;FIRST PAGE IS PAGE 1
MOVEI PAGE2,1 ;AND LAST PAGE IN RANGE
JRST TYPO ;TYPE IT OUT
LAST: CALL CHKFIL ;DO WE HAVE AN INPUT FILE?
RET ;NO
NOISE (PAGE)
CONFRM
MOVE PAGE1,SIZE ;GET THE LAST PAGE AS FIRST PAGE IN RANGE
MOVE PAGE2,SIZE ;AND LAST PAGE IN RANGE
JRST TYPO ;TYPE IT OUT
;HERE ON THE LIST COMMAND
LISTIT: CALL RANGE ;GET A RANGE
RET ;ILLEGAL RANGE
CALL CHKEXT ;ILLEGAL FILE?
RET ;BAG IT
MOVSI T1,(GJ%SHT) ;SHORT GTJFN
HRROI T2,[ASCIZ/LPT:/] ;THE LINE PRINTER
GTJFN% ;GET A JFN
ERJMP FAIL ;BOMBED
MOVEM T1,TJFN ;STORE JFN
JRST COPYIT ;SUCCESS, GO JOIN THE COPY CODE
;HERE ON THE COPY COMMAND
COPY: CALL CHKFIL ;DO WE HAVE A FILE?
RET ;NO...
NOISE (INTO FILE) ;NOISE
CALL OFILE ;PARSE OUTPUT FILE
CALL RANGE ;READ PAGE RANGE
JRST NEWCOM ;ABORT
COPYIT: CALL TJOPEN ;OPEN IT
CALL COPPAG ;COPY PAGES
CLOSET: HRRZ T1,TJFN ;GET THE JFN OF THE TEMPORARY FILE
CLOSF% ;CLOSE IT
ERJMP WARN ;MAKE NOISE IF SOMETHING BOMBED
RET ;RETURN TO COMMAND LEVEL
SUBTTL TERMINAL PAUSE COMMANDS
TEPAU: SKIPA T1,[.MOONX] ;TERMINAL PAUSE (ON) END-OF-PAGE
TENPAU: MOVEI T1,.MOOFF ;TERMINAL NO PAUSE (ON) END-OF-PAGE
PUSH P,T1 ;SAVE MODE OF CHOICE
NOISE (ON END OF PAGE)
CONFRM
POP P,T3 ;GET BACK MODE
MOVEI T1,.PRIOU ;USER'S TTY
MOVEI T2,.MOXOF ;XON/XOFF FLAG (THAT'S THE PAGE PAUSE FEATURE)
MTOPR% ;PRETEND TTY IS A MAGTAPE (OH WELL!)
RET
;HERE TO CHECK IF THE EXTENSION INDICATES A POSSIBLE BINARY FILE
;SKIPS IF THE FILE IS PROBABLY GOOD
CHKEXT: SETZM TMPBLK ;CLEAR THE FIRST WORD OF THE TEMP BUFFER
HRROI T1,TMPBLK ;DUMP THE STRING HERE
HRRZ T2,JFN ;THE FILE JFN
MOVE T3,[1B11] ;WANT ONLY THE FILE EXTENSION
JFNS% ;WRITE THE STRING
MOVSI T2,-BADNUM ;NUMBER OF BAD EXTENSIONS
MOVE T1,TMPBLK ;OPTIMIZE LOOP
CHKGOD: CAMN T1,BADEXT(T2) ;SKIP IF IT DOESN'T MATCH OUR EXTENSION
JRST CHKBAD ;LOOKS LIKE A BADDIE
AOBJN T2,CHKGOD ;LOOP UNTIL DONE
RETSKP ;PROBABLY A GOOD FILE, SKIP RETURN
CHKBAD: CALL NEWLIN
TMSG <%Ignoring possible binary file - >
MOVEI T1,.PRIOU ;SEND TO THE TTY
HRRZ T2,JFN ;THE GUILTY JFN
MOVE T3,[1B2+1B5+1B8+1B11+1B14+1B35] ;FORMAT FLAGS
JFNS% ;WRITE THE FILE SPEC
OCRLF
RET ;AND MAKE AN ERROR RETURN
;THIS IS THE LIST OF SUSPICIOUS FILE EXTENSIONS
BADEXT: ASCII/REL/
ASCII/EXE/
ASCII/BIN/
ASCII/FUN/
ASCII/UNV/
ASCII/SAV/
ASCII/FAS/
BADNUM==.-BADEXT
SUBTTL SHOW COMMAND
SHOW: CALL CHKFIL ;SKIP IF WE HAVE A FILE
RET
NOISE (INFORMATION ON CURRENT FILE)
CONFRM
CALL GROUP ;FILE GROUP
CALL FILE ;CURRENT FILE
CALL LENGTH ;NUMBER OF DISK PAGES
CALL CURPAG ;CURRENT VALUE OF PAGE1
CALLRET STRING ;CURRENT SEARCH STRING AND RETURN
;HERE TO OUTPUT THE FILE GROUP
GROUP: TMSG <Group: >
HRROI T1,JFNSTR
PSOUT% ;SEND THE GROUP STRING
OCRLF
RET
;HERE TO OUTPUT THE CURRENT FILE
FILE: TMSG <File: >
MOVE T1,FDBBLK+.FBCTL
TLNN T1,(FB%DEL) ;DELETED?
JRST FILE1 ;NO, SKIP THE MESSAGE
TMSG <%File is deleted - >
FILE1: MOVEI T1,.PRIOU
HRRZ T2,JFN
SETZ T3,0
JFNS% ;WRITE OUT CURRENT FILE SPEC.
OCRLF
RET
;HERE TO SAY HOW LONG THE FILE IS
LENGTH: TMSG <Length: >
MOVEI T1,.PRIOU
HRRZ T2,SIZE
MOVEI T3,12
NOUT%
ERCAL WARN
TMSG < disk page(s)
>
RET
;HERE TO PRINT THE CURRENT PAGE
CURPAG: TMSG <Page: >
MOVEI T1,.PRIOU
MOVE T2,PAGE1
MOVEI T3,12
NOUT%
ERCAL WARN
OCRLF
RET
;HERE TO PRINT THE CURRENT SEARCH STRING
STRING: TMSG <String: ">
HRROI T1,STRBUF
PSOUT%
TMSG <"
>
RET
SUBTTL THE FIND COMMAND
;PARSE FIELDS
QUOTE: FIELD .CMQST,,REFIND,<string pattern to find>
REFIND: FIELD .CMCFM,,TEXT,<press RETURN to repeat last search>
TEXT: FIELD .CMTXT,,,,CM%SDH
FIND: CALL CHKFIL ;SKIP IF WE HAVE A FILE
RET ;RETURN TO COMMAND LOOP
NOISE (STRING)
PARSE QUOTE ;PARSE TEXT STRING WITHOUT QUOTES
HRRZS T3 ;CLEAR FLAGS ON LEFT
CAIN T3,REFIND ;TYPED A CRLF?
JRST FNDDEF ;YES, USE THE DEFAULT, IF ANY
CONFRM ;WAIT FOR CONFIRMATION
CALL INISTR ;INITIALIZE SEARCH STRING
FIND1: SETZM OKINT ;DON'T INTERRUPT US
SETZM NOSRCH ;ASSUME SEARCH NEED DID NOT COMPLETE
SETZM DIDONE ;WE HAVE NOT PRINTED HEADER OR NUMBER
SETZM LOPG ;LOW PAGE IN FILE
SETZM FLASTP ;HAVE NOT SEEN END OF FILE
SETZM SPAGE ;NO FIRST FIRST PAGE IN PAGE TABLE
SETZM EPAGE
MOVSI FPOS,-MAXFP ;POSITION AT FIRST ENTRY IN PAGE TABLE
FINDLP: CALL FMAP ;MAP IN SOME PAGES
MOVNI FILBYT,BPTBSZ+1
MOVEI FILWRD,PAGE*1000 ;ADDRESS OF FIRST WORD IN FILE
SLOOP: CALL FSRCH ;DO A FAST SEARCH
JRST FNDMOR ;YES
CAMN T1,EPAGE(FPOS) ;NO, FOUND SOMETHING. IS IT NEW?
JRST SLOOP ;NOT NEW, LOOK FOR MORE
SKIPN SPAGE(FPOS) ;ANY RANGE CURRENT?
JRST FSET ;NO RANGE START, VERY FIRST SET
AOS EPAGE(FPOS) ;CHECK IF EXACTLY 1 GREATER THAN END OF RANGE
CAMN T1,EPAGE(FPOS)
JRST SLOOP ;YES, WE DONE GOOD
SOS EPAGE(FPOS) ;NO, MAKE PAGE CORRECT AGAIN
AOBJN FPOS,FSET ;GET A NEW FPOS AND DO BOUNDS CHECK
SUBI FPOS,1 ;EXCEEDED BOUNDS, DUMP PAGE TABLE THEN ENTER
PUSH P,T1
CALL FNDOUT
POP P,T1
MOVSI FPOS,-MAXFP ;ENTER THE PAGE AT BEGINNING OF TABLE
FSET: MOVEM T1,SPAGE(FPOS) ;START A NEW RANGE
MOVEM T1,EPAGE(FPOS)
JRST SLOOP ;AND KEEP UP THE GOOD WORK
FNDMOR: SKIPE FLASTP ;DONE?
JRST FNDEND
MOVEI T3,764-PAGE ;ONE-PAGE OVERLAP
ADDM T3,LOPG
JRST FINDLP
;HERE TO REPORT THE RESULTS
FNDEND: CALL UNMAP ;UNMAP THE FILE
SETOM OKINT ;REALLOW CTRL/O
SETOM NOSRCH ;ASSUME NOT DIDONE AND SO NO NEED TO RE-SEARCH
FNDOUT: SKIPN DIDONE ;IF ON, ALREADY PRINTED LEADER
JRST FNDND1
SETZM NOSRCH ;AND THAT MEANS WE NEED TO RE-SEARCH
JRST FNDOU2
FNDND1: MOVEI T1,42 ;SEND A DOUBLE QUOTE
PBOUT%
HRROI T1,STRBUF ;PRINT THE STRING
PSOUT%
SKIPE SPAGE
JRST FNDOU1
TMSG <" does not occur in this file>
RET
FNDOU1: TMSG <" occurs on page(s) >
FNDOU2: MOVNI T4,1(FPOS) ;MAKE LOOP POINTER INTO FILE RANGE
MOVSI T4,(T4)
MOVEI T1,.PRIOU
MOVEI T2,","
SKIPE DIDONE ;IF NOT DIDONE, SUPPRESS COMMA
FOUTLP: BOUT%
MOVE T2,SPAGE(T4) ;GET FIRST PAGE
MOVEI T3,12 ;DECIMAL
NOUT%
ERCAL WARN
CAMN T2,EPAGE(T4) ;START AND END THE SAME?
JRST FOUNXT ;YES, GO ON TO NEXT
MOVEI T2,":" ;NO, THEY ARE DIFFERENT
BOUT%
MOVE T2,EPAGE(T4)
NOUT%
ERCAL WARN
FOUNXT: MOVEI T2,"," ;GET A COMMA FOR NEXT ARGUMENT
AOBJN T4,FOUTLP ;AND LOOP FOR ANY MORE
SETOM DIDONE ;FLAG THAT WE DID (AT LEAST) ONE
RET
;HERE IF NO STRING WAS SPECIFIED
FNDDEF: SKIPN STRBUF ;SKIP IF WE HAVE A DEFAULT
JRST FNDDFX ;NO DEFAULT SEARCH STRING
SETZM DIDONE ;HAVEN'T PRINTED FIRST THING YET
SKIPE NOSRCH ;SKIP IF WE HAVE TO SEARCH
JRST FNDND1 ;ALREADY SEARCHED, JUST READ RESULTS
JRST FIND1 ;NEW FILE, MUST RESEARCH
FNDDFX: CALL NEWLIN
TMSG <?No default search string>
RET ;RETURN TO COMMAND LOOP
FMAP: MOVE T3,SIZE ;CAN WE FIT ALL THAT'S LEFT INTO CORE?
SUB T3,LOPG
CAIG T3,765-PAGE ;COMPARE TO CORE SPACE
JRST FMAP1
MOVEI T3,765-PAGE ;NO, SO USE ALL OF CORE
MOVEI T2,765001 ;THIS IS THE MAXWRD WE WANT TO USE
JRST FMAP0
FMAP1: SETOM FLASTP ;FITS, MARK AS LAST PAGE SEEN
MOVE T1,LOPG ;FIGURE MAXWRD = MMAXWD - (LOPG - PAGE)*1000
SUBI T1,PAGE
IMULI T1,1000
MOVE T2,MMAXWD
SUB T2,T1
FMAP0: MOVEM T2,MAXWRD ;SAVE MAXWRD
SETZM (T2)
MOVE T1,LOPG ;JFN,,FILE PAGE
HRL T1,JFN
MOVE T2,[.FHSLF,,PAGE] ;PROCESS,,PROCESS PAGE
HRLI T3,(PM%CNT!PM%PLD!PM%RD!PM%CPY) ;FLAGS,,NUMBER OF PAGES
PMAP%
ERJMP FAIL
RET
;HERE TO UNMAP THE FILE
UNMAP: SETO T1,-1 ;UNMAPPING
MOVE T2,[.FHSLF,,PAGE] ;PROCESS,,PAGE
MOVE T3,SIZE ;NUMBER OF PAGES MAPPED
ADDI T3,1
CAILE T3,766-PAGE ;WE MAPPED ALL THIS IN MAYBE?
MOVEI T3,766-PAGE
HRLI T3,(PM%CNT)
PMAP%
ERCAL WARN
RET
;HERE IS THE ACTUAL SEARCHING CODE
FSRCH: ADD FILBYT,PATLEN
FAST: LDB CHAR,BP(FILBYT)
MOVE CHAR,UPPER(CHAR) ;FORCE UPPER CASE
FAST1: ADD FILBYT,DELTA1(CHAR)
FAST2: JUMPL FILBYT,FAST
CAILE FILBYT,764
JRST SLOW
SUBI FILBYT,BPTBSZ
ADDI FILWRD,BPTBSZ/5
CAMG FILWRD,MAXWRD
JRST FAST
RET ;RETURN +1 FOR FAILURE
SLOW: SUBI FILBYT,BIG
MOVEI T1,2
CHKWIN: CAMLE T1,PATLEN
JRST WIN
SUBI FILBYT,1
CAMGE FILBYT,[-BPTBSZ]
JRST BACKUP
SLOWLP: LDB CHAR,BP(FILBYT)
MOVE CHAR,UPPER(CHAR) ;FORCE UPPERCASE
CAMN CHAR,PAT-1(T1)
AOJA T1,CHKWIN
MOVE T2,DELTA1(CHAR)
CAIN T2,BIG
JRST USED2
CAML T2,DELTA2-1(T1)
JRST FAST1
USED2: ADD FILBYT,DELTA2-1(T1)
JRST FAST2
BACKUP: ADDI FILBYT,BPTBSZ
SUBI FILWRD,46
JRST SLOWLP
WIN: MOVE T1,FILWRD ;CURRENT WORD IN FILE
ADD T1,BP(FILBYT)
HRRZS T1
LSH T1,-^D9 ;MAKE IT A PAGE NUMBER
SUBI T1,PAGE-1 ;SUBTRACT THE PAGE OFFSET
ADD T1,LOPG ;MAKE IT A FILE PAGE
RETSKP ;RETURN +2 FOR SUCCESS
;HERE TO MOVE STRING FROM ATOM BUFFER TO STRING BUFFER
;CHARACTERS ARE COUNTED AND UPPERCASE IS FORCED
;THE STRING IS ALSO STORED IN REVERSE ORDER IN PAT
INISTR: MOVE T1,[POINT 7,ATMBUF] ;COPY ATMBUF TO STRBUF
MOVE T2,[POINT 7,STRBUF] ;NOW COPY IT BACKWARDS
MOVSI T3,-MXPATL ;SET COUNT TO 0
INIST1: ILDB T4,T1 ;GET A CHAR FROM ATOM BUFFER
MOVE T4,UPPER(T4) ;FORCE UPPERCASE
IDPB T4,T2 ;TRANSFER IT
CAIE T4,0 ;STOP ON ZEROBYTE
AOBJN T3,INIST1 ;COUNT UP ANOTHER ONE
HRRZS T3 ;NULL SEARCH FAILS
JUMPE T3,R
MOVEM T3,PATLEN ;SAVE COUNT
MOVE T1,[POINT 7,STRBUF] ;NOW COPY IT BACKWARDS
INIST2: ILDB T2,T1 ;GET A BYTE
MOVEM T2,PAT-1(T3) ;STORE THE BYTE IN REVERSE ORDER
SOJG T3,INIST2 ;LOOP UNTIL DONE
;fallin CALL IDLTA1
;fallin CALLRET IDLTA2
;INITIALIZE DELTA1 TABLE
IDLTA1: MOVE T1,PATLEN
MOVEM T1,DELTA1
MOVE T1,[DELTA1,,DELTA1+1]
BLT T1,DELTA1+ALPHSZ-1 ;NOW EVERY ENTRY = PATLEN
MOVE T1,PATLEN
SUBI T1,1
SETDT1: HRR CHAR,PAT(T1) ;SCAN PAT LEFT TO RIGHT
HRRM T1,DELTA1(CHAR) ;PUT POSITION INTO TABLE
SOJGE T1,SETDT1
HRR CHAR,PAT ;TERMINAL CHARACTER
MOVEI T2,BIG ;THIS IS THE BIG HACK
HRRM T2,DELTA1(CHAR) ;THIS WILL CAUSE EXIT FROM FAST
;fallin CALLRET IDLTA2
;INITIALIZE DELTA2 TABLE
; THIS IS THE 'RIGHTMOST PLAUSIBLE REOCCURENCE' TABLE.
; ONE ENTRY FOR EACH POSITION IN PAT.
;AC DEFINITIONS USED ONLY IN IDLTA2
STRBEG==2
STREND==3
PATEND==4
J==14
K==15
IDLTA2: DMOVE STRBEG,[ REPEAT 2,<1> ]
MOVEI PATEND,1
STD2LP: CAMN PATEND,PATLEN ;DONE?
RET
CAML STREND,PATLEN ;FALL OFF THE LEFT END?
AOJA STREND,FINDPT
MOVE CHAR,PAT(STREND)
CAMN CHAR,PAT-1(PATEND)
JRST FINDPT
FINDBG: ADDI STRBEG,1
MOVE K,STRBEG ;K INDEX FOR POSSIBLY RPR
MOVEI J,1 ;J IND FOR TERMINAL SUBPAT
MATCH: CAMLE J,PATEND ;NOTE: EVEN WHEN J=PATEND ALL WE KNOW
; IS THAT WE HAVE AN 'OCCURENCE' WE
; STILL HAVE TO CHECK FOR PLAUSIBILITY
JRST FOUND
CAMLE K,PATLEN ;CASE OF RPR FALLING OFF THE LEFT END?
JRST FOUND ;YES - NO PRECEDING CHARACTER THEN.
MOVE CHAR,PAT-1(J) ;NO -
CAME CHAR,PAT-1(K)
JRST FINDBG ;LOOK FOR TERMINAL CHAR
ADDI J,1 ;FOUND TERM CH,DOES NEXT CH MATCHES TOO?
AOJA K,MATCH
FOUND: MOVE STREND,PATEND ;LENGTH OF SUBPAT
ADD STREND,STRBEG ;POSITION OF RIGHT MOST CH OF RPR
SUBI STREND,1 ;THIS IS K
FINDPT: MOVEM STREND,DELTA2(PATEND)
AOJA PATEND,STD2LP
SUBTTL RANGE PARSER
;+1 IF ILLEGAL RANGE
;+2 SUCCESS
PAGEN1: FIELD .CMKEY,RNGTB1,NUMBER
PAGEN2: FIELD .CMKEY,RNGTB2,NUMBER
NUMBER: FIELD .CMNUM,^D10,JUSTCR
RNGTB1: RNGLN1,,RNGLN1
X (ALL,RNGALL)
X (CURRENT,THIS1)
X (FIRST,RNGFIR)
X (LAST,RNGLAS)
X (NEXT,RNGNXT)
X (PREVIOUS,RNGPRV)
RNGLN1==.-RNGTB1-1
RNGTB2: RNGLN2,,RNGLN2
X (CURRENT,THIS1)
X (FIRST,RNGFIR)
X (LAST,RNGLAS)
X (NEXT,RNGNXT)
X (PREVIOUS,RNGPRV)
RNGLN2==.-RNGTB2-1
RANGE: CALL CHKFIL ;DO WE HAVE AN INPUT FILE?
RET ;NO FILE
NOISE (PAGE)
PARSE PAGEN1 ;PARSE FIRST PAGE
HRRZS T3 ;CLEAR FLAGS ON LEFT
CAIN T3,JUSTCR ;PARSED A CRLF?
RETSKP ;YES, USE CURRENT PAGE
CAIN T3,NUMBER ;PARSED A NUMBER?
JRST RNG1 ;YES
HRRZ T2,(T2) ;GET SUBROUTINE ADDRESS
CALL (T2) ;EVALUATE KEYWORD TO PAGE
RNG1: PUSH P,T2 ;STORE PAGE NUMBER
NOISE (TO PAGE)
PARSE PAGEN2 ;SECOND PAGE
HRRZS T3
CAIN T3,JUSTCR ;TYPED A CRLF?
JRST RNGONE ;YES
CAIN T3,NUMBER
JRST RNG2
HRRZ T2,(T2) ;EVALUATE KEYWORD TO PAGE
CALL (T2)
RNG2: PUSH P,T2 ;STORE SECOND PAGE NUMBER
CONFRM
POP P,T2 ;GET BACK SECOND PAGE NUMBER
POP P,T1 ;GET BACK FIRST PAGE NUMBER
RNGCHK: JUMPLE T1,RNGUND ;CANNOT BE ZERO OR LESS
JUMPLE T2,RNGUND
CAMG T1,SIZE ;CANNOT BE LARGER THAN FILE
CAMLE T2,SIZE
JRST RNGOVR
CAMLE T1,T2 ;PAGES CANNOT BE OUT OF ORDER
JRST RNGX
DMOVEM T1,PAGE1 ;CHECKS OUT, SAVE THEM
RETSKP ;SKIP RETURN, ALL IS OKAY
;HERE TO HANDLE ILLEGAL RANGE SPEC
RNGUND: CALL NEWLIN
TMSG <?Page number specified is zero or less>
RET
RNGOVR: CALL NEWLIN
TMSG <?Page number specified is beyond last page of file>
RET
RNGX: CALL NEWLIN
TMSG <?Page numbers specified are out of order>
RET
;HERE TO DECODE NAMED PAGES
THIS1: MOVE T2,PAGE1 ;THIS VERY PAGE
RET
RNGFIR: MOVEI T2,1 ;FIRST PAGE
RET
RNGLAS: MOVE T2,SIZE ;LAST PAGE
RET
RNGNXT: MOVE T2,PAGE1 ;NEXT PAGE
ADDI T2,1
RET
RNGPRV: MOVE T2,PAGE1 ;PREVIOUS PAGE
SUBI T2,1
RET
;HERE IF "ALL" WAS TYPED
RNGALL: CONFRM
MOVEI PAGE1,1 ;THIS IS THE RANGE
MOVE PAGE2,SIZE
POP P,(P) ;DON'T USE RET ADDR
RETSKP
;HERE IF ONLY ONE PAGE WAS SPECIFIED
RNGONE: POP P,T1 ;GET THAT PAGE
MOVE T2,T1 ;DUPLICATE IT
JRST RNGCHK
SUBTTL PAGE COPYING ROUTINE
;CALLED BY THE TYPE, COPY, AND LIST COMMANDS
;PAGE1, PAGE2 - RANGE OF PAGES TO BE COPIED
;RETURNS +1 IF JSYS FAILURE
; +2 ON SUCCESS
COPPAG: SKIPG SIZE ;JUST GO HOME IF ZERO (OR FEWER!) PAGES
RET
CAMLE PAGE1,PAGE2 ;REDUNDANT CONSISTENCY CHECK
JRST [DMOVE PAGE1,[REPEAT 2,<1>] ;RESET PAGES TO 1
JRST RNGX] ;RETURN ERROR
MOVEI T4,1000*5 ;NUMBER OF CHARS TO SEND ON OTHER PAGES
COPLOP: CAML PAGE1,SIZE ;IS IT LAST PAGE?
MOVE T4,BYTREM ;IF SO SEND ONLY THIS MANY BYTES
MOVEI T1,-1(PAGE1) ;ADJUST PAGE NUMBER FOR PMAP
HRL T1,JFN ;JFN OF INPUT FILE
MOVE T2,[.FHSLF,,PAGE] ;MAP TO THIS PROCESS AND PAGE
MOVSI T3,(PM%PLD!PM%RD) ;READ ACCESS BITS
PMAP% ;MAP THE PAGE
ERJMP WARN ;RETURN ON ERROR
HRRZ T1,TJFN ;OUTPUT JFN
HRROI T2,PAGE*1000 ;BEGINNING OF THE PAGE
MOVN T3,T4 ;SEND EXACTLY THIS MANY CHARS
SOUT%
ERJMP WARN ;ERROR PROBABLY IS EOF
SETO T1,-1 ;WE ARE UNMAPPING
MOVE T2,[.FHSLF,,PAGE] ;PROCESS HANDLE AND PAGE
MOVEI T3,0 ;NO PAGE COUNT
PMAP% ;UNMAP THE PAGE
ERJMP WARN ;RETURN ON ERROR
CAME PAGE1,PAGE2 ;REACHED PAGE2?
AOJA PAGE1,COPLOP ;NO, DO IT AGAIN
RET ;DONE
SUBTTL FILE OPENING ROUTINE
;HERE TO OPEN AN INPUT FILE AND RECORD ITS LENGTH IN PAGES AND BYTES
;+1 ON FAILURE WITH ERROR MESSAGE PRINTED ON SCREEN
;+2 ON SUCCESS
OPEN: HRRZ T1,JFN ;THE JFN
MOVE T2,[7B5+OF%RD!OF%PDT] ;MODE FLAGS
OPENF% ;OPEN THE FILE
ERCAL OPX ;CAN'T
HRRZ T1,JFN ;THE JFN
HRLZI T2,.FBLEN ;LENGTH OF FDB AND OFFSET
MOVEI T3,FDBBLK ;ADDRESS OF FDB STORAGE BLOCK
GTFDB% ;GET THE FILE DESCRIPTOR BLOCK
HRRZ T1,FDBBLK+.FBBYV ;PAGE COUNT TO T1
HRRZM T1,SIZE ;SAVE IT
LDB T2,[POINT 6,FDBBLK+.FBBYV,11] ;BYTE SIZE TO T2
MOVE T3,FDBBLK+.FBSIZ ;BYTE COUNT TO T3
CAIN T2,7 ;7-BIT BYTES?
JRST BS7
MOVEI T2,-1(T1) ;SECOND TO LAST PAGE
IMULI T2,1000 ;WORDS NOT INCLUDING LAST PAGE
CAMGE T2,T3 ;IS IT STILL BIGGER THAN WORD COUNT?
SKIPA T2,T3 ;NO, USE WORD COUNT AS IS
ADDI T2,1000 ;YES, COUNT TOO SMALL, USE 1000*SIZE
MOVEM T2,MMAXWD ;STORE AS HIGHEST FILE WORD
IDIVI T2,1000 ;NUMBER OF WORDS ON LAST PAGE
SKIPN T3 ;ZERO?
SKIPA T3,[5000] ;YES, SHOULD BE 5000
IMULI T3,5 ;NO, CONVERT WORDS TO BYTES
MOVEM T3,BYTREM ;SAVE THIS AS NUMBER BYTES ON LAST PAGE
OP1: SETZM NOSRCH ;MUST SEARCH FILE FOR ANY STRING
DMOVE PAGE1,[ REPEAT 2,<1> ] ;SET BOTH PAGES TO 1
RETSKP
BS7: MOVEI T2,-1(T1) ;SECOND TO LAST PAGE
IMULI T2,5000 ;BYTES NOT INCLUDING LAST PAGE
CAMGE T2,T3 ;IS IT STILL BIGGER THAN BYTE COUNT?
SKIPA T2,T3 ;NO, USE BYTE COUNT AS IS
ADDI T2,5000 ;YES, COUNT TOO SMALL, USE 5000*SIZE
MOVE T3,T2 ;BYTE COUNT
IDIVI T3,5000 ;NUMBER OF BYTES ON LAST PAGE
SKIPN T4 ;IF ZERO, SHOULD BE 5000
MOVEI T4,5000
MOVEM T4,BYTREM ;SAVE THIS AS NUMBER BYTES ON LAST PAGE
ADDI T2,4 ;CONVERT BYTES TO WORDS, ROUNDED UP
IDIVI T2,5
MOVEM T2,MMAXWD ;STORE AS HIGHEST FILE WORD
JRST OP1 ;FINISH UP
OPX: HRRZ T1,JFN ;GET THE JFN BACK
TRO T2,OF%THW ;TRY FOR THAWED ACCESS THIS TIME
OPENF%
JRST OPX1 ;STILL NO GO
RET ;GOT IT!
OPX1: POP P,(P) ;DON'T NEED THIS RETURN ADDRESS ANY MORE
CALL NEWLIN
TMSG <%Could not open >
MOVEI T1,.PRIOU
HRRZ T2,JFN
SETZ T3,0
JFNS% ;PRINT OUT FILE NAME
TMSG < - >
CALL ERRHAN
OCRLF
RET ;SINGLE RETURN TO CALLER
SUBTTL ASSORTED UTILITY ROUTINES
;HERE IS THE ERSTR PRINTING ROUTINE
ERRHAN: MOVEI T1,.PRIOU ;TO THE TTY
HRLOI T2,.FHSLF ;THIS PROCESS,,LAST ERROR
SETZ T3,0 ;LONG MSGS
ERSTR% ;PRINT THE ERROR MSG
ERJMP WHA ;CAN'T EVEN SAY WHAT HAPPENED.
ERJMP FAIL
RET
WHA: CALL NEWLIN ;GET TO CLEAR LINE
TMSG <%There was an undefined error within an error! Watch out!>
RET
;MAKE SURE ON A NEW LINE
NEWLIN: MOVEI T1,.PRIOU ;CURSOR POSITION AS VERT,,HORIZ
RFPOS%
TRNE T2,-1 ;OK ONLY IF ALL RH BITS 0
OCRLF ;FLUNKED, FORCE FRESH LINE
RET
;HERE FOR A WARNING MESSAGE ON A JSYS ERROR
WARN: CALL NEWLIN ;WANT FRESH LINE
TMSG <%Warning - >
CALL ERRHAN
OCRLF
RET
;HERE TO RETURN TO COMMAND LOOP ON JSYS ERROR
FAIL: CALL NEWLIN ;WANT FRESH LINE
TMSG <%Failure - >
CALL ERRHAN
JRST NEWCOM
;HERE TO CHECK FOR JFN, SKIP RETURN IF ALL OKAY
CHKFIL: SKIPE JFN ;ZERO JFN MEANS NO FILE
RETSKP
CALL NEWLIN ;MAKE SURE OF A FRESH LINE
TMSG <?You must GET a file or file group first>
RET ;ERROR RETURN
;HERE TO EXECUTE THE COMND JSYS
;THIS NONSENSE WOULD NOT BE NECESSARY IF DEC USED CM%FIX
;AT LEAST, NOT THE EXTRA JUNK -- THE SUBROUTINE DOES HAVE A RAISON D'ETRE
PARSER: MOVEI T1,CSTATE ;ADDRESS OF COMMAND STATE BLOCK
COMND% ;PARSE A FIELD
IFN CM%FIX, <
RET ;RETURN RIGHT NOW
> ;IFN CM%FIX
IFE CM%FIX, <
TXNN T1,CM%NOP ;COULD WE PARSE IT?
RET ;YES, RETURN TO CALLER
CALL NEWLIN ;MAKE SURE OF A NEW LINE
TMSG <?Unrecognized command - >
CALL ERRHAN ;GIVE SYSTEM HELPFUL ERROR DIAGNOSIS
LDB T1,[POINT 7,ATMBUF,6] ;DON'T PRINT NULL ATOM
JUMPE T1,PRSX1
TMSG < - "> ;PRINT OFFENDING TEXT IF WE CAN
HRROI T1,ATMBUF
PSOUT%
MOVEI T1,.CHDQT
PBOUT%
PRSX1: TMSG <
(Hint: For help type BACKSPACE and a question mark.)>
JRST NEWCOM ;RETURN FOR A REPARSE
> ;IFE CM%FIX
;HERE TO WRITE A JFN STRING INTO JFNSTR
MAKSTR: HRROI T1,JFNSTR ;DESTINATION OF STRING
MOVE T2,JFN ;THE JFN
MOVE T3,[1B2+1B5+1B8+1B11+1B14+1B35] ;FORMAT FLAGS
JFNS% ;WRITE THE STRING
MOVE T1,[POINT 7,JFNSTR]
MOVE T2,[POINT 7,IDEV]
MOVEM T2,IJFNBK+.GJDEV
MOVEI T3,":"
CALL CPYFLD
IBP T1
MOVE T2,[POINT 7,IDIR]
MOVEM T2,IJFNBK+.GJDIR
MOVEI T3,">"
CALL CPYFLD
MOVE T2,[POINT 7,INAM]
MOVEI T3,"."
CALL CPYFLD
MOVE T2,[POINT 7,IEXT]
CALL CPYFLD
RET
CPYFLD: ILDB 0,T1
CAMN 0,T3
JRST CPYFL1
IDPB 0,T2
JRST CPYFLD
CPYFL1: SETZ 0,
IDPB 0,T2
RET
;HERE TO PARSE AN OUTPUT FILE NAME USING COMND JSYS
IFILE: SKIPA T1,[IJFNBK] ;TO PARSE INPUT FILE
OFILE: MOVEI T1,OJFNBK ;TO PARSE OUTPUT FILE
MOVEM T1,CSTATE+.CMGJB
PARSE FILSPC ;GET JFN ON FILE
MOVEM T2,TJFN ;SAVE IT
MOVEI T1,UNJFN ;CHANGE REPARSE ADDRESS
MOVEM T1,CSTATE
RET
;HERE TO OPEN THE TEMPORARY JFN
TJOPEN: MOVE T1,TJFN ;GET OUTPUT FILE JFN
MOVE T2,[7B5+OF%WR] ;SET ACCESS MODE
OPENF% ;OPEN THE FILE
ERJMP TJOPX ;BOMBED, SKIP TO ERROR ROUTINE
RET ;SUCCESS RETURN
TJOPX: CALL WARN ;SAY WHAT WENT WRONG
JRST NEWCOM ;GO REINITIALIZE
UNJFN: MOVE T1,TJFN ;RELEASE THE TEMPORARY JFN
RLJFN%
NOP ;IGNORE ERRORS
SETZM TJFN ;NO TEMP JFN TO RELEASE
MOVEI T1,RPARSE ;SET CORRECT REPARSE ADDRESS
MOVEM T1,CSTATE
JRST RPARSE
;HERE TO CLOSE THE JFN
CLOSE: HRRZ T1,JFN ;HERE WE HAVE IT
CLOSF% ;BYE BYE
NOP ;WHAT COULD GO WRONG?
RET
SUBTTL INTERRUPT HANDLING
;HERE TO SET UP OUR INTERRUPT SYSTEM
SETINT: MOVEI T1,.FHSLF ;CURRENT PROCESS
MOVE T2,[LEVTAB,,CHNTAB] ;INTERRUPT TABLES
SIR% ;SET INTERRUPTS
EIR% ;ENABLE INTERRUPTS
MOVE T2,[1B0+1B16] ;ACTIVATE CHANNELS 0 AND 16
AIC%
MOVE T1,[.TICCO,,0] ;CONTROL-O ASSIGNED TO CHANNEL 0
ATI%
RET
;HERE IS THE ROUTINE TO FAKE A CONTROL-O
SHUTOF: AOSE OKINT ;SKIP IF ALLOWING INTERRUPTS
DEBRK%
MOVEI T1,.PRIOU ;OUR OUTPUT FILE
CFOBF% ;ZAP IT
TMSG <^O...
>
SHUT: SETO T1,-1
MOVE T2,[.FHSLF,,PAGE]
MOVEI T3,0
PMAP% ;UNMAP THE SPECIAL PAGE
ERCAL WARN
MOVEI T1,NEWCOM ;DEBREAK TO COMMAND LOOP
MOVEM T1,PCSAVE
SETOM OKINT ;ALLOW INTERRUPTS
DEBRK% ;RETURN FROM INTERRUPT
;HERE ON ILLEGAL MEMORY READ
MEMX: CALL NEWLIN ;MAKE SURE ON NEW LINE
MOVEI T1,"%"
PBOUT%
CALL ERRHAN ;PRINT OUT ERROR MESSAGE
TMSG < - probably pages after end of file
>
JRST SHUT ;GO UNMAP AND DEBREAK TO COMMAND LOOP
;INTERRUPT TABLES
CHNTAB: 1,,SHUTOF ;CHANNEL 0 FOR CTRL-O
BLOCK 17
1,,MEMX ;CHANNEL 16 IS ILLEGAL MEMORY READ
BLOCK 23
SUBTTL STORAGE (PURE AND IMPURE)
;STORE THE LITERALS HERE, JUST BEFORE THE IMPURE STORAGE
;DON'T SEND THEM TO THE CREF LISTING
XLIST
LIT
LIST
;UPPERCASING TABLE
UPPER: XXZ==0
REPEAT <"a">,<XXZ
XXZ==XXZ+1> ;UPPERCASE ALREADY OR IRRELEVANT, NO CHANGE
REPEAT <"z"-"a"+1>,<XXZ-40
XXZ==XXZ+1> ;LOWERCASE, RAISE
REPEAT <177-"z">,<XXZ
XXZ==XXZ+1> ;IRRELEVANT, NO CHANGE
;LEVEL TABLE FOR THE INTERRUPT SYSTEM
LEVTAB: PCSAVE
BLOCK 2
;THE COMMAND STATE BLOCK
CSTATE: 0,,RPARSE ;THE REPARSE ADDRESS
.PRIIN,,.PRIOU ;I/O JFNS
-1,,[ASCIZ/PERUSE> /] ;CONTROL-R BUFFER
-1,,COMBUF ;CAN'T EDIT PAST THIS POINT
-1,,COMBUF ;POINTER TO NEXT FIELD
BUFCHR ;REMAINING SPACE IN COMMAND BUFFER
0 ;REMAINING UNPARSED CHARACTERS
-1,,ATMBUF ;LAST FIELD PARSED
BUFCHR ;SIZE OF ATOM BUFFER
IJFNBK ;ADDRESS OF JFN BLOCK
;THE ARGUMENT BLOCK FOR THE LONG FORM GTJFN
IJFNBK: INFLG!GJ%XTN+.GJALL ;0 - .GJGEN
.PRIIN,,.PRIOU ;1 - .GJSRC
0 ;2 - .GJDEV
0 ;3 - .GJDIR
-1,,INAM ;4 - .GJNAM
-1,,IEXT ;5 - .GJEXT
0 ;6 - .GJPRO
0 ;7 - .GJACT
0 ;10 - .GJJFN
G1%IIN ;11 - .GJF2
BLOCK IJFNBK+.GJATR+1-.
OJFNBK: GJ%FOU!GJ%XTN+.GJDEF
BLOCK OJFNBK+.GJATR+1-.
;VARIABLES
JFN: BLOCK 1 ;CURRENT JFN
TJFN: BLOCK 1 ;JFN OF COPY FILE
IDEV: BLOCK 8
IDIR: BLOCK 8
INAM: ASCIZ "*"
BLOCK INAM+8-.
IEXT: ASCIZ "*"
BLOCK IEXT+8-.
PCSAVE: BLOCK 1 ;SAVE PC HERE ON CTRL/O
OKINT: BLOCK 1 ;^O INTERRUPT-PERMITTED SEMAPHORE
SIZE: BLOCK 1 ;NUMBER OF PAGES IN CURRENT FILE
LOPG: BLOCK 1 ;LOW PAGE NUMBER USED BY FIND
NOSRCH: BLOCK 1 ;FLAG USED BY FIND COMMAND
PATLEN: BLOCK 1 ;NUMBER OF CHARACTERS IN SEARCH STRING
MMAXWD: BLOCK 1 ;ADDRESS OF LAST WORD IN THE FILE
MAXWRD: BLOCK 1 ;ADDRESS OF LAST WORD TO SEARCH
FLASTP: BLOCK 1 ;FLAG TO SIGNAL EOF SEARCHED
DIDONE: BLOCK 1 ;FLAG USED TO DETERMINE WHETHER COMMA NEEDED
;LARGE BUFFERS
STACK: BLOCK STKLEN ;SUBROUTINE STACK
COMBUF: BLOCK BUFLEN ;COMMAND BUFFER
ATMBUF: BLOCK BUFLEN ;ATOM BUFFER
STRBUF: BLOCK BUFLEN ;STRING BUFFER
JFNSTR: BLOCK BUFLEN ;STRING ASSOCIATED WITH FIRST JFN
TMPBLK: BLOCK BUFLEN ;TEMPORARY STORAGE
SPAGE: BLOCK MAXFP ;STARTING PAGES FOR FIND
EPAGE: BLOCK MAXFP ;ENDING PAGES FOR FIND
PATBUF: BLOCK PTBUFL ;PATTERN BUFFER
BP00:
I==0
REPEAT 46,<
X==0
REPEAT 5,<
POINT 7,I(FILWRD),7*X+6
X==X+1>
I==I+1>
BP==.
DELTA1: BLOCK ALPHSZ ;ONE ENTRY FOR EACH ALPHABET
PAT: BLOCK MXPATL ;ARRAY FOR UNPACKING OUR PATTERN TO BE MATCHED
DELTA2: BLOCK MXPATL
FDBBLK: BLOCK .FBLEN ;STORE CURRENT FILE'S FDB HERE
BYTREM: BLOCK 1 ;NUMBER OF BYTES IN FILE'S LAST PAGE
END START