; -*-MIDAS-*-

TITLE TAGS

.INSRT RMS;MACROS

CH==,-1
CHIN==1				;INPUT CHANNEL
CHOUT==2			;OUTPUT CHANNEL
CHSRC==3			;SOURCE FILE INPUT CHANNEL

TFDEV:	0			;TAG FILE DEV, ETC.
TFFN1:	0
TFFN2:	0
TFSNM:	0

SFDEV:	0			;SOURCE FILE DEV, ETC.
SFFN1:	0
SFFN2:	0
SFSNM:	0
SFLANG:	0			;SOURCE FILE LANGUAGE IN SIXBIT.

MSNAME:	0			;DEFAULT SNAME.

SWDEF LPDL==40
PDL:	BLOCK LPDL+20

FORMF:	0	;-1 IF REMEMBERING A ^L WHICH WAS AT FRONT OF THIS SOURCE LINE.
FAILP:	0	;-1 => FAIL CODE, AS OPPOSED TO MIDAS CODE.
PALXP:	0	;-1 => PALX CODE, AS OPPOSED TO MIDAS CODE.
INFOP:	0	;-1 => THIS IS A INFO; FILE WHICH CONTAINS TEXT AND ITS OWN TAG TABLE.

RFNSWP:	0	;-1 => RFN SHOULD RECOGNIZE SWITCHES.
DEBUG:	0	;-1 => DON'T COMMIT SUICIDE.

SRCCPY:	0	;-1 => COPY OLD BUFFERS OF SOURCE FILE INTO THE OUTPUT FILE
EOFP:	0	;AT EOF IN SOURCE FILE, RESTORE P FROM HERE
EOFJ:	0	;AND JUMP INDIRECT THROUGH HERE.

FILMSG:	ASCII /
:/
	ASCII / Processing source file / 
PFNBUF:	BLOCK 8

BEG:	MOVE P,[-LPDL,,PDL]
	SETZM LINBUF
	MOVE A,[LINBUF,,LINBUF+1]
	BLT A,LINBFE		;PREPARE TO READ THE COMMAND STRING.
	MOVE A,[.BYTE 7 ? ^M]
	MOVEM A,LINBFE
	.SUSET [.ROPTIO,,A]
	TLNN A,OPTCMD
 	 .VALUE [ASCIZ /
:You must give a JCL command string.


:kill ¯]
	.BREAK 12,[..RJCL,,LINBUF]
	SETZM SFTOTC
	.SUSET [.RSNAM,,MSNAME]
	MOVE A,MSNAME
	MOVEM A,TFSNM		;SET UP DEFAULTS FOR TAG TABLE FILE NAME
	MOVSI A,'DSK
	MOVEM A,TFDEV
	MOVE D,[440700,,LINBUF]
	MOVEI B,TFDEV
	SETOM RFNSWP		;ALLOW SWITCHES.
	CALL RFN"RFN		;PARSE JCL FILENAME.
	MOVE A,[SIXBIT/TAGS/]
	SKIPE INFOP
	 MOVSI A,(SIXBIT/>/)
	SKIPN TFFN2
	 MOVEM A,TFFN2
	MOVE A,TFSNM		;ALLOW :TAGS FOO;
	SKIPN TFFN1
	 MOVEM A,TFFN1
;OPEN INPUT AND OUTPUT TAG TABLE FILES.
	SYSCAL OPEN,[[.UAI,,CHIN] ? TFDEV ? TFFN1 ? TFFN2 ? TFSNM]
	 .LOSE %LSFIL
	SYSCAL OPEN,[[.UAO,,CHOUT] ? TFDEV ? [SIXBIT /_TAGS_/] ? ['OUTPUT] ? TFSNM]
	 .LOSE %LSFIL
	SETZM TFCNT		;INIT BUFFERING OF INPUT TAG TABLE.
	MOVE A,[440700,,OUTBUF]
	MOVEM A,OUTPNT
	SETZM OUTTOT		;AND OUTPUT FILE.
	SKIPE INFOP
	 JRST MINFO		;A /I INFO; FILE IS BOTH SOURCE AND TAG TABLE.
SLOOP:	MOVEI N,TFREDC
	CALL RLIN		;READ A LINE OFF THE INPUT TAG FILE.
	SKIPN LINCNT
	 JRST DONE
	MOVE A,TFSNM		;DEFAULT SOURCE FILE DEV AND SNAME TO TAG FILE'S.
	MOVEM A,SFSNM
	MOVE A,TFDEV
	MOVEM A,SFDEV
	MOVE A,[SIXBIT/>/]
	MOVEM A,SFFN2
	MOVE D,LINPNT
	MOVEI B,SFDEV		;PARSE IT INTO SOURCE FILE NAME.
	SETZM RFNSWP		;NO SWITCHES ALLOWED IN FILENAMES IN THE TAG FILE.
	CALL RFN"RFN
SLOOP1:	CALL TFREDC
	CAIE I,^_
	 CAIN I,^C
	  JRST SLOOPL
	CAIN I,^M
	 JRST SLOOPL
	CAIE I,",		;SKIP PAST THE SIZE AND COMMA.
	 JRST SLOOP1
	MOVEI N,TFREDC
	CALL RSIX		;READ IN THE LANGUAGE.
	JUMPE A,SLOOPL
	MOVEM A,SFLANG
	CAIA			;RSIX'S TERMINATOR CAN BE THE CR OF THE CRLF BEFORE THE ^_.
SLOOP2:	 CALL TFREDC		;SKIP THE REST OF THE ENTRY.
	CAILE I,^_
	 JRST SLOOP2
SLOOP4:	CAIN I,^C		;EOF IS OK - USER PROBABLY LEFT OUT THE ^_ CRLF
	 JRST SLOOP3		;WHEN CREATING THE INITIAL LIST OF FILES.
	CAIE I,^M		;ASIDE FROM EOF, LOOK FOR A CR LF ^_.
	 JRST SLOOP2
	CALL TFREDC
	CAIE I,^J
	 JRST SLOOP4
	CALL TFREDC
	CAIE I,^_
	 JRST SLOOP4
	CALL TFREDC		;SKIP THE CRLF AFTER THE ^_.
	CAIE I,^M
	 JRST BADFRM
	CALL TFREDC
	CAIE I,^J
	 JRST BADFRM
SLOOP3:	CALL MAKNEW		;NOW WRITE THE NEW ENTRY.
	JRST SLOOP		;HACK THE NEXT SOURCE FILE.

SLOOPL:	CALL DELEWO
	.VALUE [ASCIZ /
:Language name not found when expected.


:kill ¯]

BADFRM:	CALL DELEWO
	.VALUE [ASCIZ /
:Bad format input tag table.  A ^_ is not followed by a CRLF.


:kill ¯]

;COMMON ROUTINE FOR ERROR MESSAGES.
;SAY WHICH SOURCE FILE WE ARE PROCESSING, AND FLUSH THE OUTPUT FILE.
DELEWO:	SKIPN SFDEV
	 JRST DELEW1
	MOVE D,[440700,,PFNBUF]	
	MOVEI B,SFDEV
	CALL RFN"PFN
	IRPC X,,[:

P]
	 MOVEI A,"X
	 IDPB A,D
	TERMIN
	.VALUE FILMSG
DELEW1:	SKIPE DEBUG
	 .VALUE
	SYSCAL DELEWO,[%CLIMM,,CHOUT]
	 JFCL
	RET

;HERE AFTER READING WHOLE INPUT TAG TABLE AND WRITING ENTRIES FOR ALL SOURCE FILES.
DONE:	MOVE A,[440700,,OUTBUF]	;NOW WRITE THE STUFF OUT.
	SYSCAL SIOT,[%CLIMM,,CHOUT ? A ? OUTTOT]
	 .LOSE %LSFIL
	SYSCAL RENMWO,[%CLIMM,,CHOUT ? TFFN1 ? TFFN2]
	 .LOSE %LSFIL
	.CLOSE CHOUT,
	SKIPE DEBUG
	 .VALUE
	.BREAK 16,140000

;READ A LINE FROM THE INPUT PATH IN N, INTO LINBUF.
;CLOBBERS H,I.  THE TERMINATION OF THE LINE IS NOT INCLUDED.
;A ^C MARKS THE END, IN LINBUF.
RLIN:	MOVE H,[440700,,LINBUF]	;BP -> START OF BUFFER.
	MOVEM H,LINPNT
	SETZM LINCNT	;0 CHARS READ SO FAR.
RLIN1:	CALL (N)	;READ NEXT CHAR.
	CAIG I,^M
	 JRST RLIN2
RLIN4:	CAMN H,[010700,,LINBUF+LINBSZ-1]
	 JRST RLIN1	;DON'T STORE IF BUFFER FULL.
	IDPB I,H	;ORDINARY CHAR, JUST PUT IN BUFFER.
	AOS LINCNT
	JRST RLIN1
	
RLIN2:	CAIN I,^M	;IGNORE CR.
	 JRST RLIN1
	CAIE I,^J	;LF ENDS LINE.
	CAIN I,^C	;^C ENDS LINE.
	 JRST RLIN3
	JUMPN I,RLIN4	;SAME FOR ^@.
RLIN3:	MOVEI I,^C	;LINE WAS TERMINATED, PUT ^C AT END OF BUFFER.
	IDPB I,H
	RET

SWDEF LINBSZ==100

LINPNT:	0
LINCNT:	0
LINBUF:	BLOCK LINBSZ
LINBFE:	-1

;; ASSEMBLE IN THE FILENAME READER AND PRINTER.

RFN"$$RFN==1
RFN"$$PFN==1
RFN"$$PFND==1

;; ACTIVATE THE "/" CHARACTER FOR READING SWITCHES, DEPENDING ON RFNSWP.
RFN"RSIXTP:
	CAIN A,"/
	 SKIPN RFNSWP
	  RET
	AOS (P)
RFN"PSIXTP:
	RET

;; WHEN "/" IS ACTIVATED, CALL HERE WITH THE CHAR AFTER THE "/" IN A.
RFN"$$SWITCH==1
RFN"SWITCH:
	CAIN A,"I
	 SETOM INFOP
	CAIN A,"I
	 RET
	SKIPE DEBUG
	 .VALUE
 	.VALUE [ASCIZ /
:Illegal switch


:kill ¯]

.INSRT SYSENG;RFN

;READ SIXBIT WORD INTO A FROM STREAM IN N.  CLOBBERS H.
;TERMINATING CHARACTER LEFT IN I.
RSIX:	MOVE H,[440600,,A]	;BP FOR STORING THE SIXBIT.
	SETZ A,		;NO CHARS SO .
RSIX0:	CALL (N)	;GET NEX CHAR, LOWER CASE TO UPPER.
	CAIL I,140
	 SUBI I,40
	CAIG I,40	;SPACE OR CTL CHAR => STOP.
	 RET
	SUBI I,40	;INSERT NORMAL CHAR IN THE 6BIT.
	TLNE H,77^4	;IGNORE CHARS AFTER THE FIRST 6.
	 IDPB I,H
	JRST RSIX0

;READ A CHAR INTO I OFF OF CHANNEL CHIN, BUFFERED.
TFREDC:	SOSG TFCNT
	 CALL TFRLD
	ILDB I,TFPNT
	RET

TFRLD:	SAVE A
	SAVE B
	MOVE A,[440700,,TFBFR]
	MOVEM A,TFPNT
	MOVEI B,TFBFSZ*5
	SYSCAL SIOT,[%CLIMM,,CHIN ? A ? B]
	 .LOSE %LSFIL
	MOVNS B
	ADDI B,TFBFSZ*5
	MOVEM B,TFCNT
	MOVEI B,^C
	IDPB B,A
POPBAJ:	REST B
	REST A
	RET

TFBFSZ==100

TFCNT:	0
TFPNT:	0
TFBFR:	BLOCK TFBFSZ
	0

;ROUTINES FOR READING THE SOURCE FILE, AND STORING INTO THE ENTRY (ACCUMULATED IN CORE).

DEFINE WRITEI CHAR
	MOVEI I,CHAR
	IDPB I,OUTPNT
	AOS OUTCNT
TERMIN

;SUBROUTINE TO OUTPUT CHAR IN I TO ENTRY.
OUTCHR:	IDPB I,OUTPNT
	AOS OUTCNT
	RET


;READ A CHAR INTO I OFF OF CHANNEL CHSRC, BUFFERED.
SFREDC:	ILDB I,SFPNT
	CAIN I,^C
	 CALL SFRLD
	AOS SFCHRS
	RET

;AFTER READING A ^C FROM SFBFR YOU MUST CALL SFRLD.
;IF THE ^C MEANT EOF, WE GO TO SRCEOF.  IF IT MEANT END OF BUFFER,
;WE REFILL THE BUFFER AND REPLACE THE ^C WITH THE REAL NEXT CHARACTER.
;IF SRCCPY IS SET, WHEN WE RELOAD THE BUFFER THE OLD STUFF IS WRITTEN TO CHOUT.
SFRLD:	SAVE A
	SAVE B
	MOVE A,SFPNT
	CAME A,SFEPT		;^C WASN'T AT END OF A SIOT =>
	 JRST POPBAJ		;IT WAS REALLY IN THE FILE.
	MOVE A,[440700,,SFBFR]	;ELSE BUFFER EMPTY, MUST READ MORE.
	SKIPN SRCCPY
	 JRST SFRLD1
	MOVEI B,SFBFSZ*5	;IF CALLER SPECIFIES, COPY THE DISCARDED BUFFER
	SYSCAL SIOT,[%CLIMM,,CHOUT ? A ? B]	;TO THE OUTPUT FILE.
	 .LOSE %LSFIL
SFRLD1:	MOVE A,[440700,,SFBFR]
	MOVEM A,SFPNT
	MOVEI B,SFBFSZ*5
	SYSCAL SIOT,[%CLIMM,,CHSRC ? A ? B]
	 .LOSE %LSFIL
	MOVNS B
	ADDI B,SFBFSZ*5		;HOW MUCH DID WE GET?
	JUMPE B,[ MOVE P,EOFP	;NOTHING => EOF, GO TO SRCEOF RESTORING P.
		  JRST @EOFJ]
	MOVEI B,^C
	IDPB B,A
	MOVEM A,SFEPT		;ELSE PUT ^C AFTER AND MAKE SRCEPT -> IT.
	ILDB I,SFPNT		;NOW GET THE FIRST CHAR JUST READ
	JRST POPBAJ

SFBFSZ==100

SFPNT:	0
SFEPT:	0			;-> THE ^C AFTER THE STUFF IN SFBFR.
SFBFR:	BLOCK SFBFSZ
	0
SFCHRS:	0			;# CHARS READ SO FAR FROM THIS SOURCE FILE.
SFTOTC:	0			;# CHARS IN ALL PREVIOUS SOURCE FILES.

;WRITE OUT AN ENTRY FOR ONE SOURCE FILE (NAMES IN SFDEV, ETC.)
MAKNEW:	SYSCAL OPEN,[[.UAI,,CHSRC] ? SFDEV ? SFFN1 ? SFFN2 ? SFSNM]
	 .LOSE %LSFIL
	MOVE A,[440700,,SFBFR]
	MOVEM A,SFPNT		;MARK BUFFER AS EMPTY (SFPNT ILDBS A ^C
	MOVEI B,^C		;WHICH SFEPT POINTS AT).
	IDPB B,A
	MOVEM A,SFEPT
	SETZM SFCHRS		;INIT CHAR POS IN SOURCE FILE TO 0.
	SETZM OUTCNT		;INIT SIZE OF ENTRY WRITTEN TO 0.
	MOVEI B,SFDEV
	MOVE D,[440700,,PFNBUF]
	CALL RFN"PFND		;PRINT FILENAMES INTO ENTRY.
	MOVEI A,PFNBUF
	CALL OUTASC
	WRITEI ^M
	WRITEI ^J
	MOVE A,OUTPNT
	MOVEM A,ONUMPT		;HERE IS WHERE SIZE WILL GO.  FOR NOW, STORE ZEROS.
REPEAT 5,WRITEI "0
	WRITEI [",]
	MOVEM P,EOFP		;SET UP PDL PTR TO RESTORE AT EOF.
	MOVEI A,SRCEOF
	MOVEM A,EOFJ
	SETZM SRCCPY

	MOVE A,SFLANG		;NOW PARSE SOURCE FILE ACCORDING TO ITS LANGUAGE
	CAMN A,[SIXBIT /MUDDLE/]
	 JRST MMUDDL
	CAMN A,[SIXBIT /TECO/]
	 JRST MTECO
	CAMN A,[SIXBIT /MIDAS/]	;NOTE:  THE FIRST THING EACH LANGUAGE MUST DO IS
	 JRST MMIDAS		;OUTPUT ITS FULL NAME AND A CRLF.
	CAMN A,[SIXBIT /XMIDAS/]
	 JRST XMIDAS
	CAMN A,[SIXBIT /FAIL/]
	 JRST MFAIL
	CAMN A,[SIXBIT /PALX/]
	 JRST MPALX
	CAMN A,[SIXBIT /LISP/]
	 JRST MLISP
	CAMN A,[SIXBIT /SCHEME/]
	 JRST MSCHEM
	CAMN A,[SIXBIT /R/]
	 JRST MR
	CAMN A,[SIXBIT /TJ6/]
	 JRST MTJ6
	CAMN A,[SIXBIT /TEX/]
	 JRST MTEX
	CAMN A,[SIXBIT /MACSYM/]
	 JRST MMACSY
	CAMN A,[SIXBIT /MICRO/]
	 JRST MMICRO
	CALL DELEWO
	.VALUE [ASCIZ / :A language not known to TAGS was specified.
The language must be MIDAS, PALX, FAIL, TECO, LISP, Scheme, MUDDLE,
R, TJ6, TeX or MACSYMA.


:kill ¯]

;HERE AT EOF IN SOURCE FILE, TO FINISH THE ENTRY.
SRCEOF:	MOVE A,SFCHRS		;COMPUTE TOTAL # CHARS IN SOURCE FILES.
	ADDM A,SFTOTC		;IN CASE SOMEONE IS INTERESTED.
	WRITEI ^_		;FIRST PUT THE ^_ CRLF AT THE END.
	WRITEI ^M
	WRITEI ^J
	MOVE A,OUTCNT		;NOW HACK THE ENTRY SIZE:  GET SIZE,
	ADDM A,OUTTOT
REPEAT 5,[
	IDIVI A,10.		;COMPUTE ITS DIGITS,
	SAVE B
]
	MOVE B,ONUMPT		;AND STORE THEM INTO RIGHT PLACE.
REPEAT 5,[
	REST A
	ADDI A,"0
	IDPB A,B
]
	RET

;SCAN A FILE OF MACSYMA CODE FOR FUNCTION DEFINITIONS.
MMACSY:
IRPC CH,,MACSYMA
	WRITEI "CH
TERMIN
	WRITEI ^M
	WRITEI ^J
MMACSL:	MOVE A,[440700,,LINBUF]
	MOVEI D,2
MMACS0:	CALL SFREDC		;MACSYMA TAG LINES MUST START WITH SQUOZE.
	SKIPN MACSLP(I)
	 JRST [	CAIE I,^L	;BUT WE DO ALLOW A ^L AT THE BEGINNING OF A LINE
		 JRST MMAIGN	;(THAT IS, A PAGE WITH NO CRLF AT THE FRONT).
		IDPB I,A
		AOJA D,MMACS0]	;SUCH A ^L MUST BE INCLUDED IN THE LINE IN THE TAGS FILE.
	IDPB I,A
MMACS1:	CALL SFREDC
	CAIL D,50.		;IF SYMBOL GETS TOO LONG, IGNORE IT.
	 JRST MMAIGN
	IDPB I,A		;SAVE ALL SQUOZE CHARS AT START OF LINE
	SKIPE MACSLP(I)		;IN LINBUF, AND THE FIRST NON-SQUOZE.
	 AOJA D,MMACS1		;D ENDS UP WITH # OF CHARS IN LINBUF.
	MOVE H,SFCHRS		;H HAS ADDRESS OF NEXT CHARACTER (POSITION OF DEFINITION).
	CALL MMACPS		;SKIP OVER SPACES.
	CAIN I,":
	 JRST MMACS3		;NAME ENDED BY COLON => THIS IS ASSIGNMENT.  COUNT IT.
	CAIE I,"(
	 CAIN I,"[		;]  IN ANY MACSYMA FUNCTION DEFINITION, THE FUNCTION NAME
	  CAIA			;MUST BE FOLLOWED BY A PAREN OR BRACKET.
	   JRST MMAIGN
MMACS4:	CALL SFREDC		;SO SKIP PAST THE MATCHING CLOSE.
	CAIN I,^J
	 JRST MMACSL
	CAIE I,"(		;DOUBLE NESTING OF PARENS OF BRACKETS =>
	 CAIN I,"[		;THIS IS NOT A FUNCTION DEFN, BUT SOMETHING RANDOM,
	  JRST MMAIGN		;SO IGNORE IT.
	CAIE I,")
	 CAIN I,"]		;WHEN WE REACH THE MATCHING CLOSE,
	  CAIA
	   JRST MMACS4
	CALL SFREDC		;IT CAN LEGITIMATELY BE FOLLOWED BY ANOTHER OPEN,
	CALL MMACPS
	CAIE I,"(		;IN WHICH CASE SKIP TO ITS MACTHING CLOSE.
	 CAIN I,"[		;]
	  JRST MMACS4
	CAIE I,":		;COLON FOLLOWS THE PARENS OR BRACKETS => FUNCTION DEFN.
	 JRST MMAIGN
MMACS3:	SAVE I			;IF IT'S A FUNCTION DEFINITION, OUTPUT IT.
	MOVE A,[440700,,LINBUF]	;NOT EVERYTHING UP TO THE COLON, JUST FIRST SYMBOL AND
	MOVEM A,LINPNT		;THE FOLLOWING DELIMITER.
	CALL OTAG		;TAG => OUTPUT IT.
	REST I
MMAIGN:	CALL IGNLIN
	JRST MMACSL

;SKIP 0 OR MORE CHARS UNTIL NON-SPACE.
MMACPS:	CAIE I,40
	 RET
	CALL SFREDC
	JRST MMACPS

;MACSLP+CH IS NONZERO IF CH IS AN ALPHANUMERIC CHARACTER.
MACSLP: REPEAT "%,0
	1			;%
	REPEAT "0-"%-1,0
	REPEAT "9-"0+1,1	;DIGITS
	REPEAT "A-"9-1,0
	REPEAT "Z-"A+1,1	;U.C. LETTERS
	REPEAT "A+40-"Z-1,0
	REPEAT "Z-"A+1,1	;L.C. LETTERS
	REPEAT 200-"Z-40-1,0
IFN .-MACSLP-200,.ERR TABLE LENGTH

;SCAN A FILE OF EMACS MACROS FOR TAGS.
MTECO:
IRPC CH,,TECO
	WRITEI "CH
TERMIN
	WRITEI ^M
	WRITEI ^J
MTECO0:	CALL SFREDC		;ONLY LINES STARTING WITH AN ! CAN HAVE TAGS.
	CAIE I,"!
	 JRST [	CALL IGNLIN
		JRST MTECO0]
	MOVEI N,SFREDC
	SAVE SFCHRS
	CALL RLIN		;READ IN THE REST OF THE LINE (MUST REMEMBER
	MOVE A,LINPNT		;TO PUT THE ! IN LATER IF THERE IS A TAG).
	SETZB C,D		;C HAS POS SCANNING AT, D HAS POS OF LAST :!.
	REST H			;H HAS POS IN FILE OF FRONT OF LINE.
MTECO1:	ILDB I,A
	AOS C
	CAIN I,^C
	 JRST MTECO3		;END OF LINE => IF FOUND TAG, STORE IT.
MTECO2:	CAIE I,":
	 JRST MTECO1
	ILDB I,A
	AOS C
	CAIN I,^C
	 JRST MTECO3
	CAIE I,"!
	 JRST MTECO2
	MOVE D,C		;REMEMBER WHERE THE LAST :! ON THE LINE ENDS.
	JRST MTECO1		;KEEP SEARCHING FOR ANOTHER SO FIND THE LAST.

MTECO3:	JUMPE D,MTECO0		;END OF LINE.  IF NO TAG, JUST SCAN NEXT LINE.
	ADD H,D		;THIS LINE HAS A TAG.  COMPUTE POS. OF TAG IN H.
	WRITEI "!		;WRITE THE "!" THAT WAS READ BEFORE CALLING RLIN.
	CALL OTAG		;OUTPUT THE REST OF THE LINE, AND THE POS.
	JRST MTECO0

;SCAN A FILE OF LISP CODE FOR FUNCTIONS, ETC.

DEFINE LTEST PREFIX,FTAG
	SETZ D,			;D HAS HOW MANY CHARS OF LINE WE HAVE READ.
	MOVE A,LINPNT
IRPC CH,,[PREFIX]
	ILDB I,A		;"(" MUST BE FOLLOWED BY AN ATOM.
	CAIE I,"CH
	 CAIN I,"CH+40		;WHICH STARTS WITH THE PREFIX.
	  AOSA D
	   JRST FTAG
TERMIN TERMIN

MLISP:
IRPC CH,,LISP
	WRITEI "CH
TERMIN
	WRITEI ^M
	WRITEI ^J
MLISPL:	SETZM FORMF
MLISP5:	CALL SFREDC		;DOES THIS LINE START WITH A "("?
	CAIN I,^L
	 JRST [	SETOM FORMF
		JRST MLISP5]	;ALLOW A ^L BEFORE THE "(".
	CAIE I,"(
	 JRST MLIGN
	SAVE SFCHRS
	MOVEI N,SFREDC
	CALL RLIN		;READ IN REST OF LINE.
	REST H			;H HAS POS. IN FILE OF START OF LINE.
	LTEST DEF,MLISP7	;SEE IF FUNCTION CALLED STARTS WITH "DEF".
	AOS D
	ILDB I,A
	CAIE I,"P
	 CAIN I,"P+40		;BUT IS NOT "DEFPROP"
	  JRST MLISP7
	JRST MLISP2

MLISP7:	LTEST MACRO,MLISP8	;SEE IF FUNCTION STARTS WITH "MACRO"
	JRST MLISP2

MLISP8:	LTEST ENDF,MLISPL	;SEE IF FUNCTION IS "ENDF"

;HERE IF FUNCTION BEING CALLED LOOKS GOOD (STARTS "DEF" OR "MACRO" OR "ENDF").
MLISP2:	CAIE I,^I
	 CAIN I,40		;NOW FIND THE SPACE ENDING THIS ATOM.
	  JRST MLISP1
	CAIN I,^C
	 JRST MLISPL		;(NO TAG HERE IF NOT ONE ON THIS LINE.)
	ILDB I,A
	AOJA D,MLISP2

MLISP1:	ILDB I,A		;THERE MUST BE ANOTHER ATOM AFTER THAT.
	AOS D
	CAIN I,^C
	 JRST MLISPL
	CAIE I,40
	 CAIN I,^I
	  JRST MLISP1
	CAIN I,"(		;ALLOW "(DEFUN (FOO BAR) ..." AND KEEP SCANNING TO ")" THEN.
	 JRST MLISPO
MLISP3:	CAIE I,40		;NOW FIND THE SPACE, TAB OR CR ENDING THIS ATOM.
	 CAIN I,^C
	  JRST MLISP4
	CAIN I,^I
	 JRST MLISP4
	CAIE I,"(
	 CAIN I,")
	  JRST MLISP4
	CAIE I,""
	 CAIN I,"|
	  JRST [		;STRING OR VBAR'D SYMBOL => SCAN OVER IT AND THEN TAG ENDS.
		CALL MLVBAR
		JRST MLISP4]
	CAIN I,"/
	 JRST [	ILDB I,A	;SLASH MAKES FOLLOWING SPACE NOT END ATOM.
		AOJA D,.+1]
	ILDB I,A
	AOJA D,MLISP3

;HERE FOR VERTICAL BAR OR DOUBLE-QUOTE SEEN IN FUNCTION BEING DEFINED.
MLVBAR:	PUSH P,I
MLVBA1:	ILDB I,A
	AOS D
	CAIN I,^C		;ABORT AT EOL INSIDE VBARS.
	 JRST MLVBA2
	CAME I,(P)
	 JRST MLVBA1
MLVBA2:	SUB P,[1,,1]
	RET

;HERE AFTER FINDING THE END OF THE NAME OF THE FUNCTION BEING DEFINED.  WE HAVE A TAG!
MLISP4:	CAIN I,^C
	 MOVEI I,^M		;EOL WAS REPRESENTED AS ^C BY RLIN.  TURN BACK TO ^M FOR FILE.
	DPB I,A
	ADD H,D			;COMPUTE IN H THE POS. OF THE TAG IN THE FILE.
	SKIPL FORMF
	 JRST MLISP6
	WRITEI ^L
MLISP6:	WRITEI "(		;WRITE THE "(" THAT WAS READ BEFORE RLIN.
	CALL OTAG		;WRITE THE REST OF THE TAG'S LINE.
	JRST MLISPL

;COME HERE IF WE FIND A "(" WHERE THE START OF THE FUNCTION NAME IS SUPPOSED TO BE.
MLISPO:	CAIE I,")		;SCAN TO MATCHING ")", BUT STOP AT END OF LINE.
	 CAIN I,^C		;WE ASSUME THAT THERE AREN'T ANY FURTHER PAREN LEVELS
	  JRST MLISP4		;INSIDE THE FUNCTION NAME, FOR SIMPLICITY.
	CAIE I,""
	 CAIN I,"|
	  JRST [
		CALL MLVBAR
		JRST MLISPO]
	CAIN I,"/
	 JRST [	ILDB I,A	;SLASH MAKES FOLLOWING CHAR NOT SPECIAL.
		AOJA D,.+1]
	CAIN I,^C		;ONLY END OF LINE STILL COUNTS IF SLASHIFIED.
	 JRST MLISP4
	ILDB I,A
	AOJA D,MLISPO

MLIGN:	CALL IGNLIN		;IGNORE REST OF THIS LINE OF LISP FILE.
	JRST MLISPL

; Scan a file of Scheme code.

mschem:
irpc ch,,Scheme
	writei "ch
termin
	writei ^m
	writei ^j
	jrst mscm0

mscm89:	movei i,^m
	dpb i,a
mscm90:	addi h,(d)
	call otag
mscm0:	save sfchrs
	movei n,sfredc
	call rlin
	rest h
	movei d,4		; Account for "(def"
	move a,linpnt
mscm20:	ildb i,a
	caie i,40
	 cain i,^i
	  aoja d,mscm20		; First, skip any leading whitespace
	caie i,"(
	 jrst mscm0
	ildb i,a
	caie i,"d
	 cain i,"D
	  caia
	   jrst mscm0
	ildb i,a
	caie i,"e
	 cain i,"E
	  caia
	   jrst mscm0
	ildb i,a
	caie i,"f
	 cain i,"F
	  caia
	   jrst mscm0
mscm30:	ildb i,a		; Find the end of the defmumble
	caie i,40
	 cain i,^i
	  aoja d,mscm40		; found whitespace after the defmumble
	cain i,^c
	 jrst mscm0		; end of line => no tag
	caie i,"(
	 cain i,"'
	  aoja d,mscm40
	aoja d,mscm30		; else keep looking

mscm40:	ildb i,a		; Find thing being defined
	caie i,40
	 cain i,^i
	  aoja d,mscm40		; skip more whitespace
	caie i,"(
	 cain i,"'
	  aoja d,mscm40
	cain i,^c
	 jrst mscm0		; end of line => no tag
	aoja d,mscm50		; go find space or end of line

mscm50:	ildb i,a		; Find space or end of line
	caie i,40
	 cain i,^i
	  aoja d,mscm90
	cain i,")
	 aoja d,mscm90
	cain i,^c
	 aoja d,mscm89
	caie i,"(
	 cain i,"'
	  aoja d,mscm90
	aoja d,mscm50		; keep looking

;SCAN A FILE OF R MACROS FOR TAGS.
MR:	WRITEI "R
	WRITEI ^M
	WRITEI ^J
MR0:	CALL SFREDC		;ONLY LINES STARTING WITH A . CAN HAVE TAGS.
	CAIE I,".
	 JRST MRIGN
	MOVEI N,SFREDC
	SAVE SFCHRS
	CALL RLIN		;READ IN THE REST OF THE LINE (MUST REMEMBER
	REST H			;H HAS POS IN FILE OF FRONT OF LINE.
	LTEST [RTAG]MR2	;LINES STARTING WITH "RTAG" ARE TAGS PUT IN JUST FOR :TAGS.
	JRST MR1A

MR2:	LTEST [AM]MR2A
	JRST MR1A

MR2A:	LTEST [DE]MR0		;DOES LINE START WITH "DE "?  IF SO, IT'S A TAG.
MR1A:	ILDB I,A		;SKIP TO THE NEXT SPACE, PAST THE 
	AOS D			;TAG-DEFINING OPERATION (".DE" OR ".DEFINE", ETC.)
	CAIE I,^I
	 CAIN I,40
	  JRST MR1B
	CAIN I,^C		;END OF LINE BEFORE SPACE MEANS THERE'S NO TAG NAME HERE.
	 JRST MR0
	JRST MR1A

MR1B:	ILDB I,A		;THEN SKIP ALL SPACES, IN CASE THERE ARE SEVERAL.
	AOS D
	CAIN I,^C
	 JRST MR0
	CAIE I,^I
	CAIN I,40		;WE LEAVE THIS LOOP ON SEEING THE START OF THE TAG NAME.
	 JRST MR1B
MR1:	ILDB I,A		;FIND END OF TAG NAME, COUNTING CHARS IN D.
	CAIE I,^I
	 CAIN I,40		;A SPACE ENDS IT, AND IS INCLUDED IN THE COUNT.
	  AOSA D
	   CAIN I,^C		;END OF LINE (^C) ENDS NAME AND IS NOT INCLUDED.
	    CAIA
	     AOJA D,MR1
	ADDI H,(D)		;THIS LINE HAS A TAG.  COMPUTE POS. OF TAG IN H.
	WRITEI ".		;WRITE THE "." THAT WAS READ BEFORE CALLING RLIN.
	CALL OTAG		;OUTPUT THE REST OF THE LINE, AND THE POS.
	JRST MR0

MRIGN:	CALL IGNLIN
	JRST MR0

;SCAN A FILE OF TJ6 INPUT FOR TAGS.
MTJ6:	WRITEI "T
	WRITEI "J
	WRITEI "6
	WRITEI ^M
	WRITEI ^J
MTJ0:	CALL SFREDC		;ONLY LINES STARTING WITH A . CAN HAVE TAGS.
	CAIE I,".
	 JRST MTJIGN
	MOVEI N,SFREDC
	SAVE SFCHRS
	CALL RLIN		;READ IN THE REST OF THE LINE (MUST REMEMBER
	REST H			;H HAS POS IN FILE OF FRONT OF LINE.
	LTEST [C TAG ]MTJ0	;A TAG IS A LINE STARTING WITH ".C TAG ".
MTJ1B:	ILDB I,A		;THEN SKIP ALL SPACES, IN CASE THERE ARE SEVERAL.
	AOS D
	CAIN I,^C
	 JRST MTJ0
	CAIE I,^I
	CAIN I,40		;WE LEAVE THIS LOOP ON SEEING THE START OF THE TAG NAME.
	 JRST MTJ1B
MTJ1:	ILDB I,A		;FIND END OF TAG NAME, COUNTING CHARS IN D.
	CAIE I,^I
	 CAIN I,40		;A SPACE ENDS IT, AND IS INCLUDED IN THE COUNT.
	  AOSA D
	   CAIN I,^C		;END OF LINE (^C) ENDS NAME AND IS NOT INCLUDED.
	    CAIA
	     AOJA D,MTJ1
	ADDI H,(D)		;THIS LINE HAS A TAG.  COMPUTE POS. OF TAG IN H.
	WRITEI ".		;WRITE THE "." THAT WAS READ BEFORE CALLING RLIN.
	CALL OTAG		;OUTPUT THE REST OF THE LINE, AND THE POS.
	JRST MTJ0

MTJIGN:	CALL IGNLIN
	JRST MTJ0

;Scan a file of TeX input for tags.
mtex:	writei "T
	writei "e
	writei "X
	writei ^M
	writei ^J
	jrst mtex0

mtxign:	call ignlin
mtex0:	call sfredc		;only lines starting with a \ can have tags.
	caie i,"\
	 jrst mtxign
	movei n,sfredc
	save sfchrs
	call rlin
	rest h
	ltest [TAG{]mtex0
mtexlp:	ildb i,a
	cain i,"}		;close brace ends tag and is included.
	 aoja d,mtextg
	caie i,^C		;end of line ends tag and is not included.
	 aoja d,mtexlp
mtextg:	addi h,(d)		;position of tag in H
	writei "\
	call otag
	jrst mtex0

;SCAN A FILE OF MUDDLE CODE FOR DEFINE AND DEFMAC.

MMUDDL:
IRPC CH,,MUDDLE
	WRITEI "CH
TERMIN
	WRITEI ^M
	WRITEI ^J
MMUDD0:	SETZM FORMF
MMUDD5:	CALL SFREDC		;DOES THIS LINE START WITH A "<"?
	CAIN I,^L
	 JRST [	SETOM FORMF
		JRST MMUDD5]	;ALLOW A ^L BEFORE THE "<".
	CAIE I,"<
	 JRST MMUDIGN
	SAVE SFCHRS
	MOVEI N,SFREDC
	CALL RLIN		;READ IN REST OF LINE.
	REST H
	MOVE A,LINBUF		;THE "<" MUST BE FOLLOWED BY EITHER
	MOVE D,LINBUF+1		;"DEFINE " OR "DEFMAC ".
	AND D,[.BYTE 7 ? 177 ? 177]
	CAMN A,[ASCII /DEFIN/]
	 CAME D,[ASCII /E /]
	  CAIA
	   JRST MMUDD2
	CAMN A,[ASCII /DEFMA/]
	 CAME D,[ASCII /C /]
	  JRST MMUDD0		;OTHERWISE, THERE IS NO TAG ON THIS LINE.
MMUDD2:	MOVE A,LINPNT
	ADDI A,1		;ADVANCE A PAST THE DEFINE/DEFMAC
  REPEAT 2,IBP A		;AND THE SPACE THAT FOLLOWS IT.
	MOVEI D,7		;D HAS HOW MANY CHARS OF LINE WE HAVE READ.
MMUDD1:	ILDB I,A		;THERE MUST BE ANOTHER ATOM AFTER THAT.
	AOS D
	CAIE I,^C
	CAIN I,"<
	 JRST MMUDD0
	CAIE I,".
	CAIN I,"(
	 JRST MMUDD0
	CAIN I,40
	 JRST MMUDD1
MMUDD3:	CAIN I,40		;NOW FIND THE SPACE ENDING THIS ATOM.
	 JRST MMUDD4
	CAIN I,^C
	 JRST MMUDD0		;(NO TAG HERE IF NOT ONE ON THIS LINE.)
	ILDB I,A
	AOJA D,MMUDD3
	
MMUDD4:	ADD H,D			;COMPUTE IN H THE POS. OF THE TAG IN THE FILE.
	SKIPL FORMF
	 JRST MMUDD6
	WRITEI ^L
MMUDD6:	WRITEI "<		;WRITE THE "<" THAT WAS READ BEFORE RLIN.
	CALL OTAG		;WRITE THE REST OF THE TAG'S LINE.
	JRST MMUDD0

MMUDIGN: CALL IGNLIN		;IGNORE REST OF THIS LINE OF MUDDLE FILE.
	JRST MMUDD0

;Scan a file of MICROcode

mmicro:	writei "M
	writei "I
	writei "C
	writei "R
	writei "O
	writei ^M
	writei ^J
	jrst mmicgo

mmiout:	move h,sfchrs		;Current position is end of tag.
	movei d,(c)		;RH(C) should contain length of tag.
	call otag		;Output tag.
mmigno:	call ignlin		;Flush rest of line.
mmicgo:	move a,[440700,,linbuf]	;A: Byte pointer to LINBUF.
	movsi c,-40.		;C: Length counter.
	setzi b,		;B: 0 => only digits and trash so far.
				; Else one plus number of first real char.
	call sfredc		;Check first character specially:
	caie i,40		;Space
	 cain i,^I		;or Tab?
	  jrst mmigno		;Ignore line.
	jrst mmic1

mmic0:	call sfredc
mmic1:	cain i,^J		;End of the line.
	 jrst mmicgo
	cain i,";		;Comment?
	 jrst mmigno
	aobjp c,mmigno		;Line got too long.
	idpb i,a
	cain i,""		;Macro definition?
	 jrst mmimac
	cain i,"/		;Field definition?
	 jrst mmidef
	cain i,":		;Label?
	 jrst mmilbl
	jumpn b,mmic0		;Already found first real char?
	caile i,40		;Trash?
	 cain i,177
	  jrst mmic0		;Yes.
;Allow numbers
;	cail i,"0		;Non-digit?
;	 caile i,"9
	  movei b,(c)		;Yes.
	jrst mmic0

mmidef:	call sfredc
	caie i,"=		;Really a definition?
	 jrst mmic1
	idpb i,a
	aoja c,mmiout

mmilbl:	jumpn b,mmiout		;Real chars?
	jrst mmigno

mmimac:	move a,[440700,,linbuf]
	ildb i,a		;Find first real char.
	sojg b,.-1
	caie i,".
	 jrst mmiout
	move b,a		;Remember that BP.
irpc ch,,[TOC]
	ildb i,a
	caie i,"ch
	 cain i,40+"ch
	  skipa
	   jrst mmmac1
termin
	jrst mmigno

mmmac1:	move a,b
irpc ch,,[TITLE]
	ildb i,a
	caie i,"ch
	 cain i,40+"ch
	  skipa
	   jrst mmiout
termin
	jrst mmigno

;SCAN A MIDAS OR FAIL OR PALX FILE FOR TAGS.

MFAIL:
IRPC CH,,FAIL
	WRITEI "CH
TERMIN
	SETOM FAILP
	JRST MMIDAF

MPALX:
IRPC CH,,PALX
	WRITEI "CH
TERMIN
	SETZM FAILP
	SETOM PALXP
	JRST MMIDAP

MMIDAS:
IRPC CH,,MIDAS
	WRITEI "CH
TERMIN
	SETZM FAILP
MMIDAF:	SETZM PALXP
MMIDAP:	WRITEI ^M		;MIDAS AND FAIL JOIN HERE.
	WRITEI ^J
MMIDAL:	MOVE A,[440700,,LINBUF]
	MOVEI D,2
MMIDA0:	CALL SFREDC		;MIDAS TAG LINES MUST START WITH SQUOZE.
	SKIPN SQUOZP(I)
	 JRST [	CAIE I,^L	;BUT WE DO ALLOW A ^L AT THE BEGINNING OF A LINE
		 JRST MMIGN1	;(THAT IS, A PAGE WITH NO CRLF AT THE FRONT).
		IDPB I,A
		AOJA D,MMIDA0]	;SUCH A ^L MUST BE INCLUDED IN THE LINE IN THE TAGS FILE.
	SETZ B,
	IDPB I,A
	CAIE I,".		;B GETS 0 IFF FIRST SQUOZE CHAR IS DOT.
MMIDA1:	 SETO B,		;B GETS -1 WHEN SECOND SQUOZE CHARACTER IS SEEN.
	CALL SFREDC
	CAIL D,15.		;IF LINE GETS TOO LONG, IGNORE IT.
	 JRST MMIGN
	IDPB I,A		;SAVE ALL SQUOZE CHARS AT START OF LINE
	SKIPE SQUOZP(I)		;IN LINBUF, AND THE FIRST NON-SQUOZE.
	 AOJA D,MMIDA1		;D ENDS UP WITH # OF CHARS IN LINBUF.
	JUMPE B,MMIGN		;IGNORE TAG IF ITS NAME IS ".".  ".=" IS NOT A TAG.
MMIDA3:	CAIE I,":
	 CAIN I,"=
	  CAIA
	   JRST MMIGN2		;IF 1ST NONSQUOZE ISN'T : OR =, NO TAG HERE.
MMIDA4:	SKIPN PALXP
	 JRST MMIDA5		;FOR PALX, DON'T MENTION TAGS SUCH AS "10$"
	MOVE B,[440700,,LINBUF]	;SINCE THEY ARE JUST LOCAL TAGS.
MMIDA6:	CAMN B,A
	 JRST MMIDA5
	ILDB C,B		;FIND THE FIRST CHARACTER AFTER THE ^L'S, IF ANY.
	CAIN C,^L
	 JRST MMIDA6
	CAIL C,"0
	 CAILE C,"9		;IF IT IS A DIGIT, THIS IS A LOCAL TAG.
	  JRST MMIDA5
	JRST MMIGN

MMIDA5:	SAVE I
	MOVE H,SFCHRS
	MOVE A,[440700,,LINBUF]
	MOVEM A,LINPNT
	CALL OTAG		;TAG => OUTPUT IT.
	REST I
MMIGN:	CALL IGNLIN
	JRST MMIDAL

;IN A FAIL PROGRAM, ALLOW ^ AND  AND ^ ^ AND ^A^A AT START OF LINE TO MODIFY A LABEL.
MMIGN1:	CAIE I,"^
	 CAIN I,^A
	  SKIPN FAILP
	   JRST MMIGN
	IDPB I,A
	AOJA D,MMIDA0		;IF WE HAVE ONE, IS NEXT CHAR SQUOZE?

MMIGN2:	SKIPN FAILP		;FAIL AND PALX ALLOW SPACES BEFORE COLONS AND ='S.
	 SKIPE PALXP
	  CAIA
	   JRST MMIGN
	CAIN I,"_		;IT ALSO MAKES _ EQUIVALENT TO =.
	 JRST MMIDA4
	CAIE I,40
	 JRST MMIGN
	CALL SFREDC
	JRST MMIDA3

;SQUOZP+CH IS NONZERO IF CH IS A SQUOZE CHARACTER.
; Value is CH in SIXBIT (sic).
SQUOZP:	REPEAT "$, 0
	'$ ? '%				;$ AND %
	REPEAT ".-"%-1, 0
	'.				;.
	REPEAT "0-".-1, 0
	REPEAT "9-"0+1, '0+.RPCNT	;DIGITS
	REPEAT "A-"9-1, 0
	REPEAT "Z-"A+1, 'A+.RPCNT	;U.C. LETTERS
	REPEAT "A+40-"Z-1, 0
	REPEAT "Z-"A+1, 'A+.RPCNT	;L.C. LETTERS
	REPEAT 200-"Z-40-1, 0
IFN .-SQUOZP-200,.ERR TABLE LENGTH

; XMIDAS is like MIDAS, except it is smarter.
xmidas:
irpc ch,,XMIDAS
	writei "ch
termin
	writei ^m
	writei ^j
	jrst xmidgo

xmidlb:	cain c,[sixbit /./]
	 jrst xmidig
	move h,sfchrs
xmidtg:	call otag
xmidig:	caie i,^j
	 call ignlin
xmidgo:	move a,[440700,,linbuf]
	setzi d,
	call sfredc
	caie i,40		; ignore lines starting with whitespace
	 cain i,^i
	  jrst xmidig
	jsp s,getsq1
xmidnx:	caie i,":
	 cain i,"=
	  jrst xmidlb
	came c,[sixbit /ENIFED/]	; DEF INE
	 camn c,[sixbit /OTCEV./]	; .VECTOR
	  jrst xmiddf
	came c,[sixbit /ALACS./]	; .SCALAR
	 camn c,[sixbit /SLAUQE/]	; EQUALS
	  jrst xmiddf
	camn c,[sixbit /TRSNI./]	; .INSRT
	 jrst xmidig
	jsp s,getsq2
	jrst xmidnx

xmiddf:	jsp s,getsq2
	cain i,""		; Ignore package prefix
	 jsp s,getsq
	soj d,
	move h,sfchrs
	soja h,xmidtg

; JSP S,GETSQ to find next squoze syllable on line.
; C contains reverse sixbit of syllable when you return (SIXBIT /ENIFED/ or
; SIXBIT /OTCEV./ or whatever).  Terminating character can be found in I.
getsq2:	soja d,getsq8		; .entry with char in I already in LINBUF
       
getsq:	call sfredc		; .entry
getsq1:	idpb i,a		; .entry with char in I
getsq8:	caie i,";
	 cain i,^j
	  jrst xmidig
	skipn b,squozp(i)
	 aoja d,getsq
	movei d,3(d)
	setzi c,
	lshc b,-6		; 1
	call sfredc
	idpb i,a
	skipn b,squozp(i)
	 soja d,(s)
	lshc b,-6		; 2
	call sfredc
	idpb i,a
	skipn b,squozp(i)
	 jrst (s)
	lshc b,-6		; 3
	call sfredc
	idpb i,a
	skipn b,squozp(i)
	 aoja d,(s)
	lshc b,-6		; 4
	call sfredc
	idpb i,a
	movei d,3(d)
	skipn b,squozp(i)
	 soja d,(s)
	lshc b,-6		; 5
	call sfredc
	idpb i,a
	skipn b,squozp(i)
	 jrst (s)
	lshc b,-6		; 6
getsq9:	call sfredc
	idpb i,a
	skipe squozp(i)
	 aoja d,getsq9
	aoja d,(s)

;Process an INFO file (/I), which contains its own tag table.
;We copy the input file into the output, while sending the tag table
;down outpnt.  When we come upon the string "Tag Table:" on the line after
;the end of a node, we write the tag table into the output file, ended by
;a ^_, and flush all of the input file to the next ^_.
;The rest of the input file is copied with no processing.
;The terminator (comma, tab or CR) of a node name is not included
;in its entry in the tag table;  the name is terminated directly by the rubout
;before the character address.  This is because we look for exact matches
;on a name, when selecting a node in INFO, rather than for substring matches.
;We can do it by searching for the node name and a rubout.
;If the actual terminator were present, since it could be either comma, tab or CR,
;we couldn't include it in the search command.
MINFO:	MOVE A,[440700,,SFBFR]
	MOVEM A,SFPNT		;MARK BUFFER AS EMPTY (SFPNT ILDBS A ^C
	MOVEI B,^C		;WHICH SFEPT POINTS AT).
	IDPB B,A
	MOVEM A,SFEPT
	SETZM SFCHRS		;INIT CHAR POS IN SOURCE FILE TO 0.
	SETZM OUTCNT		;INIT SIZE OF ENTRY WRITTEN TO 0.
	.IOPUS CHIN,		;MOVE INPUT FILE TO CHSRC SO THAT SFREDC WILL WORK ON IT.
	.IOPOP CHSRC,
	CALL SFREDC		;LOAD THE SOURCE BUFFER.  FROM NOW ON, WHEN WE
	MOVEM P,EOFP
	MOVEI A,MINFO9		;PREMATURE EOF IN SOURCE CAUSES AN ERROR.
	MOVEM A,EOFJ
	SETOM SRCCPY		;RELOAD THE BUFFER, THE OLD STUFF GETS COPIED OUT.
	CAIA
MINFOL:	 CALL SFREDC		;DOES THIS LINE START WITH A "^_"
	CAIE I,^_
	 JRST [	CALL IGNLIN
		JRST MINFOL]
	CALL IGNLIN		;SKIP IT;  LOOK AT THE NEXT ONE.
	MOVEI N,SFREDC
	SAVE SFCHRS
	CALL RLIN		;READ IN THE LINE THAT FOLLOWS THE ^_.
	REST H			;H HAS POS. IN FILE OF THE ^_.
	LTEST TAG TABLE,MINFO1	;IS THIS WHERE THE TAG TABLE GOES INTO THE FILE?
;WRITE THE TAG TABLE INTO THE FILE
	MOVE A,[440700,,SFBFR]
	SETZM SRCCPY		;STOP COPYING OUT OUR INPUT FILE, BUT FIRST DO COPY
MINFO4:	ILDB I,A		;THE REST OF WHAT WE HAVE READ SO FAR
	.IOT CHOUT,I
	CAME A,SFPNT		;(IE, UP TO END OF THIS LINE).
	 JRST MINFO4
MINFO5:	CALL SFREDC		;NOW READ IN AND THROW AWAY ALL OF THE FILE TILL THE
	CAIE I,^_		;NEXT LINE THAT STARTS WITH A ^_.
	 JRST [	CALL IGNLIN
		JRST MINFO5]
	MOVEI A,MINFOE
	MOVEM A,EOFJ
	MOVEM P,EOFP
MINFO6:	IDPB I,OUTPNT		;COPY THE ^_ AND ALL THE REST OF THE INPUT FILE
	AOS OUTCNT		;ONTO THE END OF THE TAG TABLE, WHICH WILL THEN
	CALL SFREDC		;BE OUTPUT, SO THAT THE TAG TABLE IS STUCK INTO
	JRST MINFO6		;THE INPUT FILE AT THIS POINT.

MINFOE:	MOVE A,OUTCNT		;AT EOF, COME HERE.  WRITE OUT TAG TABLE AND
	MOVEM A,OUTTOT		;TAIL OF SOURCE FILE, AND RENAME AND CLOSE.
	JRST DONE

;HERE ON A LINE WHICH IS A TAG.  THE TAG NAME IS PRECEDED BY "NODE: ".  FIND IT.
MINFO1:	SETZ D,			;D HAS HOW MANY CHARS OF LINE WE HAVE READ.
	MOVE A,LINPNT
MINFON:
IRPC CH,,[NODE: ]
	ILDB I,A
	AOS D
	CAIE I,"CH
	 CAIN I,"CH+40
	  CAIA
	   JRST MINFON
TERMIN
MINFO2:	ILDB I,A		;NOW FIND THE END OF THE TAG NAME,
	AOS D			;WHICH IS THE NEXT COMMA, TAB OR CR.
	CAIE I,",
	 CAIN I,^I
	  JRST MINFO3
	CAIE I,^M
	 JRST MINFO2
MINFO3:	SOS D			;DON'T INCLUDE TERMINATOR IN NAME OF TAG!
	ADD H,D			;NOW GET POS IN FILE OF TAG END IN H,
	CALL OTAG		;AND OUTPUT THE TAG.
	JRST MINFOL

MINFO9:	CALL DELEWO
	.VALUE [ASCIZ / :Source file does not give a place to insert Tag Table


:kill ¯]

;READ PAST THE NEXT ^J IN THE SOURCE FILE.
IGNLIN:	ILDB I,SFPNT
	AOS SFCHRS
	CAILE I,^J
	 JRST IGNLIN
	CAIN I,^C
	 CALL SFRLD
	CAIE I,^J
	 JRST IGNLIN
	RET

;OUTPUT THE FIRST C(D) NUMBERS IN LINBUF, THEN A RUBOUT, AND THE
;DECIMAL NUMBER IN H, THEN A CR.

OTAG:	MOVE B,LINPNT		;OUTPUT REST OF LINE UP TO END OF TAG.
OTAG1:	ILDB I,B
	IDPB I,OUTPNT
	AOS OUTCNT
	SOJG D,OTAG1
	WRITEI 177		;AND A RUBOUT
	CALL OUTDEC		;AND THE POSITION OF THE TAG.
	WRITEI ^M
	WRITEI ^J
	RET

;OUTPUT SIXBIT WORD IN A TO ENTRY BEING CONSTRUCTED.
OUTSIX:	JUMPE A,CPOPJ	;STOP IF ALL THE REST ARE SPACES.
	ROT A,6		;NEXT CHAR INTO LOW BYTE,
	LDB I,[600,,A]	;COPY JUST THAT CHAR INTO I,
	XORI A,(I)	;REMOVE IT FROM A.
	WRITEI 40(I)
	JRST OUTSIX

;OUTPUT DECIMAL NUMBER IN A TO ENTRY BEING GROWN.
OUTDEC:	IDIVI H,10.
	HRLM I,(P)
	SKIPE H
	CALL OUTDEC
	HLRZ I,(P)
OUTDGT: WRITEI "0(I)
CPOPJ:	RET

;OUTPUT ASCIZ STRING WHOSE ADDRESS IS IN A.
OUTASC:	HRLI A,440700
OUTAS1:	ILDB I,A
	JUMPE I,CPOPJ
	CALL OUTCHR
	JRST OUTAS1

PAT: PATCH:	BLOCK 100

SWDEF OUTBSZ==50.*2000

ONUMPT:	0	;BP TO PLACE IN OUTBUF TO STORE THE ENTRY SIZE IN CHARS, AS 5-DIGIT NUMBER.
OUTCNT:	0	;# CHARS WRITTEN IN THIS ENTRY.
OUTTOT:	0	;# CHARS WRITTEN IN ALL.
OUTPNT:	0	;BP FOR STORING IN OUTBUF.
OUTBUF:	BLOCK OUTBSZ
	1	;MAKE SURE DUMPING KNOWS THIS CORE MUST EXIST.
	END BEG
