File: ACB.PG of Tape: Sources/Other/new-19
(Source file text) 

	FILE	A C B  --  ACID Documentation program
	TITLE	END-OF-LINE code processing
/
/	Here when an end of line code has been found. First we must
/	check to see if it is followed by a character other than a
/	space or another LF code. If not, the LF code is just treated
/	like a normal space code.
/
EOL	TAD	NEXTC		Peek ahead at next character
	TAD	=-' 		Check for an indent
	SZA			Skip if indent present
	TAD	=' -LF		Else check for multiple blank lines
	SZA CLA			Skip if multiple blank lines here
	JMP	BLANK2		Single LF code -- treat just like a space
/
/	Here we have a LF code that is followed either by a blank or
/	another LF code.
/
	JMS	OVERSET		Test for line already overset
	JMS	EOLCK		Process indent/multiple lines after LF code
/
/	Merge here from other places to close off the current line
/	and dump it out.
/
LNDUMP	JMS	IFLINE		Print out current line (if not null)
	JMP	NEWLN		Off to start a new line now
/
/	Subroutine IFLINE prints out the current line if it is not completely
/	null. If null, it prints nothing.
/
IFLINE	SUB
	LDI	-1		Close off the current line
	DCAI	LXR		...
	LDI	-1		and mark there is NO spillover
	DCAI	LXR		...
/
/	Test now for a completely null line (i.e. only sentinels present)
/
	TAD	LXR		Get pointer into the line buffer
	TAD	=-(LINEB+1)	Test for null line
	SZA CLA			Skip if nothing on this line
	JMS	DUMPLN		Else dump the current line (not justified)
	RET	IFLINE		Return to call now
	EJECT
/
/	The EOLCK subroutine checks for multiple extra lines and/or an
/	indent after a LF code. The LF code should be in CHAR, with
/	NEXTC containing the character immediately after the LF code
/
EOLCK	SUB
	TAD	NEXTC		Peek ahead at the next character
	TAD	=-' 		Test for a blank (start of a new indent)
	SNA
	JMP	DOIND		Yes - off to process an indent here
	TAD	=' -LF		Else test for multiple blank lines here
	SZA CLA			Skip if so
	RET	EOLCK		Something else - so return to caller now
/
/	Here to handle multiple blank lines in the output stream. Only job
/	here is to set the cell EXTRAL to the count of extra lines we find.
/	When the next line is dumped, these extra lines will be generated
/	after that line.
/
	LDI	1		Mark we have found one line already
	DCA	EXTRAL		...
/
/	Loop here counting all the extra blank lines we find.
/
0H	JMS	GETC		Get the next character to NEXTC
	CLA			Ignore the current character (we know it's LF9
	TAD	NEXTC		Peek ahead at next character
	TAD	=-LF		Is this a LF code too?
	SZA CLA			Skip if so
	JMP	EOLCK+1		Else loop back now to test for an indent
	INC	EXTRAL		Count the extra line
	JMP	0B		Loop back
/
/	Here to handle a space code after a LF code. This means that we are
/	setting a new indent for the line we are about to read. Read this
/	indent and set the value in NXINDENT for use on that line.
/
DOIND	DCA	NXINDENT	Initialize the indent to zero
	LDI	-1		Reset column count (since 1st blank ignored)
	TAD	COLUMN		...
	DCA	COLUMN		...
	LDI	-1		Set flag to ignore first blank on tab
	DCA	TABFLAG		...
/
1H	JMS	GETC		Read next character to NEXTC
	CLA			Ignore CHAR (we know it's a space)
	TAD	NEXTC		Peek ahead at the next character
	TAD	=-' 		Is this a blank too?
	SZA CLA			Skip if so
	RET	EOLCK		Else quit -- we have the indent set now
	INC	NXINDENT	Count the indent
	JMP	1B		And loop back
	EJECT
	TITLE	Process a Justification blank
/
/	Come here when we found a single LF code, must first set CHAR
/	to a normal blank and then process the LF code as if it was
/	a normal blank.
/
BLANK2	TAD	=' 		Set CHAR to a blank code
	DCA	CHAR		...
/
/	Here to handle a normal blank which can be used during justification
/	Must check to see if the current line is now overset.
/
BLANK	JMS	OVERSET		Check for an overset line now
	TAD	HYPHO		Get hyphenation flag
	AND	=020		Remove possible [h] flag, leave /H flag alone
	DCA	HYPHO		...
	TAD	=01001		Mark character now as justification blank
	DCA	CHAR		...
/
/	Check for 2 or more consecutive blanks. Such blanks are NOT treated
/	as justification blanks.
/
	TAD	NEXTC		Peek ahead at next character
	TAD	=-' 		Do we have 2 or more blanks in a row
	SNA CLA			Skip if not
	JMP	3F		Yes - this is a special case
/
/	Here to handle normal justification blank when line has not
/	overset.
/
	TAD	THISW		Get width of this word
	TAD	CURW		Add to current width on this line
	DCA	CURW		Store new line width
	DCA	THISW		Set word width back to zero
	JMP	NORMAL		Return justification blank now
/
/	Here when we have 2 or more blanks in a row. Must store fixed
/	blanks for each one that we find. Must also set new indent
/	up to this position.
/
3H	LDI	2		Account for 2 blanks already found
	TAD	CURW		Add in current width on this line
	TAD	THISW		Add in width of previous word (if any)
	TAD	INDENT		Add in indent already present on this line
	DCA	NXINDENT	Set new indent for next line
/
	TAD	=' 		First store a fixed blank
	JMS	STAC		...
	JMS	OVERSET		And test for overset line
/
2H	TAD	=' 		Now store a blank for the one just found
	JMS	STAC		...
	JMS	OVERSET		Is the line now overset?
	JMS	GETC		Get the next character
	CLA			Ignore for now
	TAD	NEXTC		Examine the following character
	TAD	=-' 		Test for another blank
	SZA CLA			Skip if so
	JMP	MLOOP		All done here -- off for next character
/
	INC	NXINDENT	Count the extra blank for next line indent
	JMP	2B		Loop back for next
/
/	Subroutine to check for an overset line:
/
/		JMS	OVERSET
/		<return>		still room on this line
/
/	When overset, this routine does NOT return
/
	CLA			Here for normal return
OVERSET	SUB			Entry & exit point
	TAD	CURW		Get current line width
	TAD	THISW		Add to current word width
	TAD	INDENT		Add in current indent on this line
	TAD	MAXW		Subtract maximum allowed width on line
	SPA SNA			Skip if we are overset now
	JMP	OVERSET-2	Not overset here - return
/
/	At this point, we have the overset
/	amount in the AC to process the overset line.
/
	DCA	TEMP		Save amount we were overset by
	TAD	CHAR		and store the character which overset us
	JMS	STAC		...
/
	LDI	-1		Close off the current line now
	DCAI	LXR		...
	LDI	-1		...
	DCAI	LXR		...
/
/	Here we are overset -- the normal case
/	Scan back now to previous justification blank, normal blank, hyphen
/	or discretionary hyphen.
/
	LDI	-3		Decrement the pointer now
	TAD	LXR		...
	JMP	*+3		Jump into loop below
/
/	Loop here looking for one of the above characters
/
4H	LDI	-1		Decrement the pointer again
	TAD	PTR		...
	DCA	PTR		...
/
	TADI	PTR		Test character at this position
	SNA			Pre-sentinel on buffer is an error
	JMP	NOSPAC		ERROR - Line has no places for justification
/
	RTL			Shift possible justification space bit to AC0
	SPA			Skip if not justification space
	JMP	6F		Handle justification space
	RTR			Restore character
	TAD	=-' 		Look for fixed space
	SNA			Skip if not
	JMP	6F		OK - fixed space found
	TAD	=' -'-		Normal hyphen here?
	SNA			Skip if not
	JMP	5F		Handle normal hyphen
	TAD	=('-)-(DHYPHEN-0200)	Test for discretionary hyphen
	SZA CLA			Skip if so
	JMP	4B		Something else -- keep looking
/
/	Here to handle discretionary hyphen. Note that the line must have
/	fitted at this point earlier on (since we called OVERSET then)
/
	INC	CURW		+1 to current width (account for real hyphen)
	TAD	='-		Install real hyphen now into buffer
	DCAI	PTR		...
/
/	Merge here to handle normal hyphen
/
5H	INC	PTR		Step over the hyphen (to get at DELETE code)
/
6H	CLA			Remove sentinel code from AC
	TAD	PTR		Save position now into line buffer
	DCA	SAVEP		...
	TADI	PTR		and save the character at that position
	DCA	SAVEC		...
/
	LDI	-1		install sentinel now at that point on the line
	DCAI	PTR		...
/
/	Check now to see if we are going to justify this line
/
	TAD	JFLAG		Justifying this line?
	SZA CLA			Skip if so
	JMP	ALLDONE		NO we are not justifying lines here
/
/	We are justifying. First job is find out how many positions we are
/	short on the line.
/
	TAD	CURW		Get current width of this line
	TAD	INDENT		Add in the indent at start of line
	TAD	MAXW		subtract maximum width of this line
	DCA	SPACES		Save count of spaces we need to add to line
/
/	Now find the earliest position on the line where we can start
/	justifying. This will be after the last fixed blank on the line
/
/	First zero out the address table of where justification spaces
/	are on the line. This table is used to randomize the insertion
/	of blanks into the line and to give priority to adding extra
/	blanks to a justification blank that immediately follows some
/	form of punctuation.
/
	TAD	=SPTABLE-1	Set pointer to space address table
	DCA	XR		...
	TAD	=-40		40 locations to clear in table
	DCA	CNTR		...
/
6H	DCAI	XR		Zero a word
	LOOP	6B		Loop till all cleared out
	TAD	=LINEB		Set pointer to table for randomizing
	DCA	XR2		function
/
/	We start by scanning to the previous fixed blank (if any) and
/	then counting the number of available spaces for doing the
/	justification.
/
	DCA	SPACNT		Zero count of available spaces on line
/
7H	LDI	-1		Decrement pointer into line buffer
	TAD	PTR		...
	DCA	PTR		...
	TADI	PTR		Load the character at that position
	SNA			Test for pre-sentinel of 0 on line buffer
	JMP	9F		All done here on pre-sentinel
	RTL			Test for justification blank
	SPA			Skip if not
	JMP	8F		OK - justification blank found here
	RTR			Else restore the character
	TAD	=-' 		Test for fixed blank
	SZA CLA			Skip if fixed blank was found
	JMP	7B		Something else -- keep scanning then
/
/	Now compare number of space positions we found with the
/	number of spaces we have to add to the line to get it
/	properly justified.
/
9H	TAD	SPACNT		Get count of space positions available
SLASHT	CLL RAR			#NOP# unless /T option chosen
	TAD	SPACES		Subtract number of space positions needed
	SPA CLA			Skip if line would not be underset
	JMP	HYPHNAT		Line is UNDERSET -- try & hyphenate a word
	JMP	JUSTIFY		Off to justify this line now
/
/	Here when a justification space has been found. First we count
/	this as an available position. Then we look to see if the previous
/	character was some punctuation character. If so, we note the fact
/	that we can insert an extra blank at this position. Also, if it
/	was a punctuation character, we want to install this address with
/	priority in SPTABLE, to ensure that any spaces we add to the line
/	are added at that point first.
/
8H	INC	SPACNT		Count room for this space
/
/	Check now to see if previous character was a punctuation character
/
	LDI	-1		Decrement pointer to get at previous character
	TAD	PTR		...
	DCA	TEMP		Save pointer to this character
	TAD	=PUNCTAB-1	Set pointer to punctuation table
	DCA	XR		...
	LDI	-3		Avoid unlikely but possible infinite loop
	DCA	RPTR		below (-3 in case inserting twice into table)
/
/	Loop here looking for a match in the punctuation table
/
0H	TADI	XR		Get the next character
	SNA			Check for sentinel on punctuation table
	JMP	1F		SENTINEL - not a punctuation character here
	TADI	TEMP		Compare with previous character
	SZA CLA			Skip if in the table
	JMP	0B		Else look for sentinel on the table
/
	INC	SPACNT		Allow another space here
	LDI	-2		Set to insert this address twice
	DCA	GCNTR		(since it will look better there)
	TADI	TEMP		Reget the character that got us here
	TAD	=-'.		Test for period
	SNA CLA			Skip if not
	LDI	-2		PERIOD -- always give HIGHEST priority
	TAD	=-6		Something else - slightly lower priority
	DCA	SAVE		Remember priority level for 2nd insertion
	TAD	SAVE		...
	JMP	2F		Set to insert at top of table
/
/	Here on non-punctuation. Randomize the position for table
/	insertion to avoid rivers in the text. The randomization
/	algorithm is somewhat(!) primitive but it should be more
/	than adequate for these purposes. We simply take the character
/	codes of consecutive groups of four characters and use this
/	modulo 32 as a position key into the table
/
/	priority 1	Insert in top 4 locations in table if possible
/	priority 2	Insert in next 4 positions if possible
/	priority 3	Insert in 9-40th positions in table
/
1H	TAD	=-4		Set loop counter
	DCA	CNTR		...
	LDI	-1		Set to insert this only once
	DCA	GCNTR		...
/
0H	TADI	XR2		Get next character on the line
	LOOP	0B		Loop for the 4 characters
	AND	=037		Truncate to range of table
/
/	Also merge back here to set pointer at slot #8 in table (after we
/	reached the end of the table during search for free slot)
/
2H	TAD	=SPTABLE+8	Index table of spaces
	DCA	TEMP		Save pointer
/
/	Merge back here to see if the new slot is still used
/
4H	TADI	TEMP		Look for free slot in the table
	SNA CLA			Skip if slot not free
	JMP	3F		Ok we have a free slot here
/
/	Current slot is already occupied. Move pointer forward until
/	we find a free slot.
/
	TAD	TEMP		Must first check for end of table
	TAD	=-(SPTABLE+39)	Compare with last slot
	SZA CLA			Skip if at end of table
	JMP	*+4		Not at end -- continue
	LOOP	2B,RPTR		Loop back to start of table now
	JMP	JUSTIFY		SPTABLE overflowed? better justify now
/
/	Here when not at the end of the table
/
	INC	TEMP		Not at end -- step pointer
	JMP	4B		Try this slot now
/
/	Here when the current slot is free. Insert the address
/
3H	TAD	PTR		Get position of justification space
	DCAI	TEMP		Insert into the table
	ISZ	GCNTR		Test for inserting twice
	JMP	*+2		Yes - must insert again
	JMP	7B		No - so done here
/
	LDI	4		Insert at lower priority than last time
	TAD	SAVE		(Old priority level)
	JMP	2B		Off to do it
/
/	Here when line has no spaces. Had better remove indent, otherwise
/	we can get stuck in a nasty loop of printing out error messages
/
NOSPAC	DCA	NXINDENT	Remove indent for next line
	JMS	E3		Issue error now
	PART
	TITLE	Line Justification section
/
/	Here to justify the line. Method here is to scan SPTABLE
/	for places at which spaces can be inserted into the line.
/	Note that justification spaces have a value of 01000 where
/	the low 6-bits of the word have the count of the number of
/	unit spaces to generate (this is handled by the DUMPLN routine)
/
JUSTIFY	TAD	SPACNT		Must find at least one space on the line
	SNA CLA			Test for this now
	JMP	NOSPAC		ERROR - Line has no spaces in it
/
4H	TAD	SPACES		Test for a perfect fit on this line
	SNA CLA			Skip if not (most likely case)
	JMP	ALLDONE		Perfect fit -- nothing to do then
/
	TAD	=SPTABLE-1	Reset pointer to the space address table
	DCA	XR1		...
	TAD	=-40		Set count for # of slots in the table
	DCA	CNTR		...
/
/	Loop here looking for the next available slot in the table
/
0H	TADI	XR1		Get next entry in the table
	SNA			Skip if we have an address here
	JMP	2F		This slot has nothing in it -- jump ahead
/
	DCA	TEMP		Save address of justification space
	INCI	TEMP		Up count of spaces to add at that point
	ISZ	SPACES		Have we generated all the spaces we need yet?
	JMP	2F		NO - so keep going
	JMP	ALLDONE		YES - so we are all done here
/
2H	LOOP	0B		Loop back if not at end of SPTABLE
	JMP	4B		At end - reset pointers/count and continue
/
/	Here when the line is all justified. Merge here from several places
/
ALLDONE	CLA			(AC may be non-zero on some merges here)
	JMS	DUMPLN		Dump this line out now
	JMP	NEWLN		and start the next one
	TITLE	End action processing
/
/	Here when we have come to the end of all the input files
/	It is now time to start the second pass of the program.
/
EOF	JMS	OVERSET		Must first check for overset line
/
/	Here when line is not overset
/
	LDI	-1		First close off the last line
	DCAI	LXR		...
	JMS	DUMPLN		Dump out the last line
/
/	Now save the total number of pages in the output file
/	in case we have a [t] command in the title
/
	LDI	-1		Total pages is one less than PAGENUM
	TAD	PAGENUM		...
	DCA	TOTALPG		Save total number of pages in file
	LDI	04000		Ensure extra lines packed up
	DCA	PAKIT		...
	TAD	LEFT		Force GENCR routine to end of page
	JMS	GENCR		Generate that number of lines now
	JMS	DUMPF		Dump out page buffer if /D option in effect
	DCA	PAKIT		Ensure remaining lines go directly now
	LDI	1024		Prevent GENCR from stopping on LEFT = 0
	DCA	LEFT		So set temporary value here
	TAD	BOTTOM		If zero, we have forms control
	SNA			Skip if no forms control
	JMP	2F		Ok, we have forms control here
	JMS	GENCR		Generate those extra lines
	JMP	1F		All done here
/
2H	TAD	=FF		For device with forms control, send form feed
	JMS	OUTC		...
/
/	Now reset the pointers to the symbol table after saving the new top
/	address and memory field of the symbol table
/
1H	TAD	SYMPTR		Save top of symbol table now
	DCA	SYMTOP		...
	TAD	SYMCDF+1	Save CDF to top of symbol table too
	DCA	CDFTOP		...
/
	TAD	=06211		Reset symbol table pointers now
	DCA	SYMCDF+1	...
	TAD	SYSTART		...
	DCA	SYMPTR		...
	TAD	OLDW		If not set, use MAXW to set it now
	SNA			Skip if we have a value already
	TAD	MAXW		else set value now
	DCA	OLDW
/
/	Now test to see which pass we are on
/
	TAD	PASS		Which pass are we on
	INC	PASS		Step pass number now
	SNA CLA			Skip if pass 2 finished
	JMP	PASS2		Else off for pass 2 now
/
	TAD	PAKUPR		Set to output in pass 3
	DCA	OUTCHAR		...
	LDI	-3		Test now in case we have finished pass 3
	TAD	PASS		...
	SZA CLA			Skip if we have finished pass 3
	JMP	1F		Else off for pass 3 now
/
/	Here we have finished pass 3, so it is time to finish up
/
SLASHZ	JMP	*+3		#NOP# if /Z not set, if set, no CONTROL/Z
/
	TAD	=CTLZ		Pack up ASCII end of file code
	JMS	PAKUP		...
/
	JMS	DUMPF		Dump remaining text in page buffer (if /D)
	JMS	BWR		Ensure last buffer-load is written out
	JMSX	CLOSE		Close out the output file
	JMP	$07600		Return to OS/8 monitor
/
1H	LDI	4		Set to isolate /V bit
	ANDX	SWITCH2		Test for /V option enabled
	SNA CLA			Skip if set
	JMP	PASS2		Off for pass 3 now
	TAD	=CR		Do CR/LF to flush out last line on LPT
	IOT	LPT,6		Output character
	IOS	LPT,1		Wait for flag
	JMP	*-1
	CLA			Since some LPT interfaces don't clear
	TAD	=LF		and do LF
	IOT	LPT,6		Output
	CLA
	JMP	PASS2		All done, off for pass 2
	TITLE	Hyphenation circuit
/
/	Here to hyphenate the word which is located just after
/	the address stored in SAVEP.  We want to
/	remember the hyphenation of this word in pass 2 so we
/	do not have to ask again for the hyphenation in pass 3.
/	(This is for the manual hyphenator)
/
/	Note that no hyphenation is performed during pass 1
/
HYPHNAT	TAD	HYPHO		Did we try to hyphenate before and fail?
	SZA CLA			Skip if not
	JMP	JUSTIFY		Yes we did -- so we will not try again
/
/	Do not attempt hyphenation if this is the last line on a page.
/	We don't want to hyphenate a word onto the next page.
/
	LDI	-1		Test for just one line remaining
	TAD	LEFT		...
	SNA CLA			Skip if not on last line of page
	JMP	JUSTIFY		Last line: don't hyphenate here
/
	TAD	PASS		Which pass are we on
	SNA CLA			Skip if not pass 1
SLASHM2	JMP	JUSTIFY		#NOP# if /M not set. If set no manual in pass 1
/
SLASHM	JMP	*+3		#NOP# if /M option not set. If set, no AUTOHYPH
	JMPX	AUTOHY		Jump off to autohyphenator
	LDI	-1		Test pass again
	TAD	PASS		...
	SZA CLA			Skip if pass 2
	JMP	HYPHEN2		Pass 3-- we know hyphen point
/
	TAD	SAVEP		Get address of where the word is
	DCA	KXR		and save it
	JMS	CRLF		Do CR/LF sequence on console
	TAD	=0207		Ring bell twice on the console
	JMS	TYPE		...
	TAD	=0207		...
	JMS	TYPE		...
/
/	Test the width now to see where the last point in this word is
/	that we can hyphenate up to.
/
	LDI	2		Account for hyphen and blank before this word
	TAD	CURW		Get the current line width
	TAD	INDENT		Add in the current line indent
	TAD	MAXW		Subtract the maximum allowed width
	DCA	SPACNT		Save count of positions left on line
/
/	Loop here to print out this word on the console. When we find
/	the last position that we can hyphenate at, we will print
/	a quote: viz  INTEREST'ING.
/
0H	TAD	KXR		Copy pointer
	IAC			+1 to examine next character
	DCA	XR1		...
	TADI	XR1		Test for sentinel on next character
	SPA CLA			Test for sentinel
	JMP	1F		All done when sentinel found
	TADI	KXR		Get the next character of the word
	JMS	FOLD		Fold over to upper case
	JMS	TYPE		Type it out on the console
	ISZ	SPACNT		Was this the last position to hyphenate at?
	JMP	0B		No -- so keep going
/
	TAD	=''		Yes -- output the quote now
	JMS	TYPE		...
	JMP	0B		and loop back for next character
/
/	Here when done printing out the word
/
1H	IOT	3,2		Clear keyboard flag now
	JMS	CRLF		New line on console
	TAD	SAVEP		Reset pointer to the word being hyphenated
	DCA	PTR		...
	EJECT
/
/	Now read characters from the console to find out where we are
/	going to hyphenate this word. Characters to test for are:
/
/	CR	means we can not hyphenate this word and should justify the
/		line without it.
/
/	DELETE	means that the operator wants the word printed out again
/		(presumably since the proper hyphenation point was skipped
/		by mistake).
/
/	-	means that we should hyphenate this word after the last
/		character that was echoed on the console.
/
/	Any other character means that we should search the word looking for
/	a match on the indicated character and echo each character on the
/	console as the search is done (somewhat similar to the 'S' search
/	in the EDIT and ICE text editor programs)
/
2H	JMS	READ		Read keyboard silently
	JMS	FOLD		Fold over to upper case (may be lower case)
	TAD	=-CR		Look for carriage return
	SNA
	JMP	5F		Not hyphenating if CR found
	TAD	=CR-'-		Look for hyphen
	SNA
	JMP	6F		Ok we know where we will hyphenate now
	TAD	=('-)-(DELETE-040)  Test for DELETE (already folded!)
	SNA
	JMP	HYPHNAT		DELETE -- so start over again at the beginning
	TAD	=(DELETE-040)	Restore the original character
	CMA IAC			Negate and save it
	DCA	TEMP		...
/
/	Loop here searching the word to hyphenate, echoing all the characters
/	on the console that do not match.
/
4H	INC	PTR		Step pointer to next character in word
	TAD	PTR		Set to examine character after this one
	DCA	XR1		...
	TADI	XR1		Peek ahead at next character
	SPA CLA			Test for sentinel on the word
	JMP	3F		All done at the end of the word
	TADI	PTR		Load the next character
	JMS	FOLD		Fold to upper case now for printing
	JMS	TYPE		Echo the character now on the console
	TADI	PTR		Reget the character
	JMS	FOLD		Fold again to upper case for testing
	TAD	TEMP		Compare with character we are searching for
	SNA CLA			Skip if no match
	JMP	2B		Match found, return now to see what to do
	JMP	4B		No match -- back to continue the search
/
/	Here in pass 2 when we already have the hyphen point in HPOINTS
/	table. Just load the next half-word in the table and get
/	the position of where the hyphen goes. A value of zero means
/	that hyphenation was rejected in pass 1.
/	Note that we set the HYPHO flag in order to avoid coming back here
/	if the line is still badly underset after we have hyphenated.
/
HYPHEN2	INC	HYPHO		Ensure we don't come here again.
	JMS	GETHALF		Get next half-word from the table
	SNA			If zero, we don't hyphenate
	JMP	JUSTIFY		Ok - not hyphenating here
/
	TAD	SAVEP		Index across characters of word
	DCA	PTR		Save pointer to character just before hyphen
	LDI	02000		Set discretionary hyphen point
	TADI	PTR		...
	DCAI	PTR		...
	JMP	REHYPH		Off to hyphenate it now
/
/	Here when the hyphenation point has been found. All we do is set the
/	02000 bit on the character that precedes the hyphenation point.
/	When we re-read this word, the GETC routine will then return a
/	discretionary hyphen at that point and the line will get hyphenated
/	there.
/
6H	LDI	02000		Get the discretionary hyphen point flag
	TADI	PTR		Merge with current character preceding hyphen
	DCAI	PTR		And store it back
	TAD	='-		Print hyphen now on console
	JMS	TYPE		...
	INC	HYPHO		Set flag to show we found a hyphenation point
/
/	Since we are in pass 1, we must store this hyphenation point into the
/	table for use in pass 2.
/
	TAD	SAVEP		Get position of start of word
	CMA IAC			Negate and subtract from position
	TAD	PTR		of the hyphenation point
	JMS	STHALF		Store in hyphen point half-word table
/
/	Merge here when CR was found to just print out the word again
/
5H	LDI	1		''impossible'' character forces printout
	JMP	4B-1		back to search for impossible character
/
/	Here at the end of this word. Check to see whether we found a
/	hyphenation point in it.
/
3H	JMS	CRLF		Newline on console
	TAD	HYPHO		Were we able to hyphenate this word?
	SZA CLA			Skip if not
	JMP	REHYPH		Ok we hyphenated this word then
/
/	Check now in case we were searching for a character that does not
/	exist
/
	LDI	-1		If +1 in TEMP, we either had CR or hyphen point
	TAD	TEMP		Check this now
	SZA CLA			Skip if we handle this all right
	JMP	HYPHNAT		Searching for non-existent character--go again
/
	JMS	STHALF		Store half-word of zero to show not hyphenated
	JMP	JUSTIFY		Off to justify now
/
/	Yes we can hyphenate this word. We must now set up the GETC
/	routine so we will re-read this word with the discretionary
/	hyphen point in it.
/
/	Must first restore THISW to account for character being restored.
/	However, it may be a delete code (after hyphen) in which case
/	we must not increment THISW
/
REHYPH	TAD	SAVEC		Get the character we saved
	TAD	=-DELETE	Test for delete code
	SZA CLA			Skip if restoring a delete code (no width)
	LDI	1		Else account for width of restored character
	DCA	THISW		...
	TAD	=RECAP		Set co-routine linkage to re-read word
	DCA	GETCX+0		...
/
/	Now copy over the word into the WORD buffer. We cannot read directly
/	From LINEB because the pointers can overlap each other.
/
	TAD	SAVEP		Set pointer to word to save
	DCA	XR1		...
	TAD	=-40		Maximum of 40 characters to copy over
	DCA	CNTR		...
	TAD	=WORD-1		Set pointer to where to save the word
	DCA	XR2		...
/
/	Loop here to copy the word over
/
1H	TADI	XR1		Word from LINEB save area
	SPA			Test for sentinel
	JMP	2F		All done here on sentinel
	DCAI	XR2		Else store into buffer
	LOOP	1B		Loop for next character, check overflow
2H	DCAI	XR2		Insert sentinel on the WORD buffer
	TAD	=WORD-1		Set pointer for RECAP section of GETC routine
	DCA	KXR		...
/
	JMS	GETC		Prime NEXTC by first call
	CLA			(Ignore old NEXTC now in CHAR)
	TAD	SAVEP		Restore the address into the line buffer
	DCA	PTR		...
	TAD	SAVEC		Restore the character we removed
	DCAI	PTR		...
	TAD	SAVEP		Now restore the line buffer pointer
	DCA	LXR		...
	JMP	MLOOP		Back to main loop to re-read this word
	EJECT
/
/	Here to store a half-word into the HPOINTS table for use in
/	determining hyphenation point in pass 2.
/
STHALF	SUB
	DCA	TEMP		Save half-word to store
	TAD	HYPHP		Check for table overflow
	TAD	=-(HPOINTS+128)	...
	SZA CLA			Skip if table overflowed
	JMP	*+3		All ok here
	INC	FATAL		Mark - fatal error
	JMS	E9		Print error and quit now
/
	LDI	04000		Invert the LH/RH store flag
	TAD	HYPHF		...
	DCA	HYPHF		...
/
	TAD	TEMP		Reget half-word to store
	SNL			Skip if storing right
	INC	HYPHP		Storing left, advance pointer now
	CDF	%HPOINTS	To field of hyphenation table
	SZL			Skip if storing left
	JMP	*+5		Storing right - no shift
/
	CLL RTL			Shift to RH of AC
	RTL			...
	RTL			...
	JMP	*+2		Skip to zero right byte
	TADI	HYPHP		Merge in the old left half
	DCAI	HYPHP		And store it back
	CDF	%*		Restore current field for exit
	RET	STHALF		Return now to caller
/
/	Subroutine to get the next half word from the HPOINTS table. This
/	routine is called in pass 2 only.
/
GETHALF	SUB
	LDI	04000		Invert the LH/RH flag
	TAD	HYPHF		...
	DCA	HYPHF		...
	SNL			Skip if load from right half
	INC	HYPHP		Loading from left, so step pointer first
	CDF	%HPOINTS	To field of hyphenation table
	TADI	HYPHP		Load the full word
	CDF	%*		Reset current field
	SZL			Skip if getting the left half
	JMP	*+4		Else getting the right half (no shift)
	RTR			Shift down to right half
	RTR			...
	RTR			...
	AND	=077		Isolate the half-word now
	RET	GETHALF		And return to caller
	EJECT
	EJECT
/
/	Subroutine to type a character on the console
/	Character to type is in the AC on entry here
/	NOTE: no temporary cells must be disturbed by TYPE routine
/
TYPE	SUB
	IOT	4,6		Type the character out
	IOS	4,1		Wait for flag to become available
	JMP	*-1		...
	CLA
	JMS	ABORTCK		Check for abort on ^C
	RET	TYPE		Return with AC clear
/
/	Subroutine to type a CR/LF on the console
/
CRLF	SUB
	TAD	=CR		Print CR
	JMS	TYPE		...
	TAD	=LF		Print LF
	JMS	TYPE		...
	RET	CRLF
/
/	Here for call to TYPE from field 1
/
	CIF	1		Always return to field 1
XTYPE	SUB			...
	JMS	TYPE		type out character
	JMP	XTYPE-2		Return to field 1
/
/	Subroutine to read a character from the keyboard
/
READ	SUB
	IOS	3,1		Wait for flag to come up
	JMP	*-1		...
	TAD	=0200		Set to turn parity bit on
	IOT	3,4		Read keyboard (don't clear flag yet)
	TAD	=-0203		Test for ^C on keyboard
	SNA			Skip if not
	JMP	$07600		Return to monitor if flag is up
	TAD	=0203		Reget the character
	DCA	TEMP		Save it
	IOT	3,2		Clear the keyboard flag now
	TAD	TEMP		Reget the character
	RET	READ
/
	TITLE	Justified line output
/
/	Here to dump the justified line to the output routines.
/
DUMPLN	SUB
	LDI	04000		(Ac maybe non-zero but ok)
	DCA	PAKIT		4000 to pack into page buffer if /D set
/
/	Display count of lines set in MQ -- just a nice frill
/
	ISZ	DISPLAY		Up the display counter
	TAD	DISPLAY		Get the count (yields 0 if ISZ skips anyway!)
	DI	07421		MQL instruction (if the MQ exists)
	CLA			(in case there is no MQ, must clear AC then)
/
/	Before dumping this line out, check to see if we are starting
/	a new page. If so, we must print the title line.
/
	ISZ	EJFLAG		Skip if forcing page eject
	JMP	0F		Ok, not forcing here
/
	TAD	LEFT		Get the number of lines left on page
	JMS	GENCR		Generate that number of lines
	JMS	DUMPF		Dump out the page buffer now
/
0H	DCA	EJFLAG		Ensure EJFLAG cleared out now
	TAD	LEFT		How many lines left on this page?
	SMA SZA CLA		Skip if none left
	JMP	5F		Still have room left -- continue
	JMS	DUMPF		Dump out the page buffer now in case /D set
/
/	No room left on this page. Must do bottom margin, dump new title
/	and do drop from top margin.
/
7H	LDI	1024		Avoid premature cutoff by GENCR routine
	DCA	LEFT		...
	DCA	PAKIT		Remaining text is output directly now
/
	LDI	-1		Are we starting the first page?
	TAD	PAGENUM		...
	SNA CLA			Skip if not
	JMP	8F		YES -- no drop then from prior bottom of page
/
	TAD	BOTTOM		Get the bottom margin depth
	SNA			If zero, means do form feed
	JMP	6F		zero -- off to do form feed then
/
	JMS	GENCR		Output that number of lines on console
	JMP	8F		Merge below
/
6H	TAD	=FF		Here when BOTTOM was zero, do form feed
	JMS	OUTC		...
/
/	Now process the title line.
/
8H	TAD	FINDENT		Generate possible floating indent before title
	JMS	GENSP		...
	TAD	=TITLE-1	Set pointer to the TITLE line
	DCA	DXR		...
/
/	Loop here to process title. Must check for special 02000 flag which
/	indicates the page number is to be printed out.
/
1H	CDF	%TITLE		To field of title buffer
	TADI	DXR		Get the next character out of the buffer
	CDF	%*		Reset current field
	SNA			Test for sentinel on TITLE buffer
	JMP	3F		SENTINEL -- all done here
	CLL RTL			Test for insertion of page number
	SZL			Skip if not encoded [p] command
	JMP	2F		Ok - do the page number here
	SPA			Test for encoded [t] command
	JMP	7F		Ok - do total pages in file
	CLL RAL			Test for encoded [w] command
	SPA			Skip if not
	JMP	PW		Off to process [w] command in title
	RAR			Restore original character
	RTR			...
	JMS	OUTC		Output it now
	JMP	1B		Loop back for next
/
/	Here when the 01000 flag has been found. We should dump the total
/	number of pages in the output file.
/
7H	CLA			Remove code from AC
	TAD	TOTALPG		Get the total number of pages in the file
	JMP	*+2		Merge with [p] command below
/
/	Here when the 02000 flag has been found. We should dump the page
/	number here
/
2H	TAD	PAGENUM		Get the current page number in binary
	JMS	BINDEC		Convert to decimal ASCII
	TAD	HIGH		Get the high order part
	SNA			Skip if not leading zero
	TAD	=' 		Change leading zero to blank
	JMS	OUTC		Else output
	TAD	MID		Get middle digit
	SNA			Skip if not a leading zero
	TAD	=' 		Else change leading zero to a blank
	JMS	OUTC		...
	TAD	LOW		Do the low order digit
	JMS	OUTC		...
	JMP	1B		Loop back for the next character
/
/	Here to process the [w] command in the title.
/
PW	CLA			Remove flag value from the AC
	TAD	OLDW		Get value of title width
	TAD	TWIDTH		Subtract from width of title
	SPA			If line overflow, don't complement
	CMA IAC			Else make positive value
	JMS	GENSP		Generate appropriate number of spaces
	JMP	1B		Loop back now for next character
/
/	Here when done with the title, increment the page number
/
3H	INC	PAGENUM		Increment the page number by 1
	TAD	DROP		Do the drop from the top of the page
	JMS	GENCR		...
	TAD	LINES		Reset the number of lines on the page
	DCA	LEFT		...
	EJECT
	EJECT
/
/	Test now for the /P option. If set, we want to print out the file/page
/	section number in the left-hand margin.
/
5H	LDI	04000		Remaining text is packed up (if /D option)
	DCA	PAKIT		...
NOFIN	TAD	FINDENT		#NOP# if /D set. Else get floating indent
	JMS	GENSP		...
	TADX	SWITCH2		Get COMMAND DECODER switch with /P bit
	AND	=0400		isolate the /P bit
	TAD	ERFLAG		Add in error flag in case error found
	SNA CLA			Skip if /P set
	JMP	9F		Not set -- continue
/
/	/P or error flag was set so print out the file/page/line number buffer
/
	TAD	=NHYPH-1	Set pointer to that buffer
	JMS	OUTLN		Output that line
	TAD	=' 		Now reset the correction flag area back.
	DCA	PSECT		...
	TAD	=' 		...
	DCA	PSECT+1		...
/
/	First job, now, is to do the indent on the line
/
9H	TAD	INDENT		Get the number of spaces for indent
	JMS	GENSP		Generate that number of spaces
/
	TAD	=LINEB-1	Set pointer to the line buffer
	DCA	LXR		...
/
/	Loop here to print out the contents of the line buffer
/
0H	TADI	LXR		Get next character in the line buffer
	SPA			Test for sentinel on the buffer
	JMP	4F		All done here on sentinel
	RTL			Test for justification space
	SPA			Skip if not
	JMP	3F		Off to handle justification space now
	SZL			Test for leadering out the line
	JMP	LEADER		Off to handle leadering condition
	RTR			Restore the original character
	TAD	=-DELETE	Test for DELETE code (not printed)
	SZA			Skip if DELETE code
	TAD	=DELETE-(DHYPHEN-0200)	Test for unused discretionary hyphen
	SNA			Skip if neither
	JMP	0B		Ignore DELETE and unused hyphen codes
/
	TAD	=(DHYPHEN-0200)	Restore original character
	JMS	OUTC		Print that character
	JMP	0B		Loop back for next
/
/	Here to handle leadering of a character. Count is in the low
/	order 9 bits and the character to leader with is in WCHAR
/
LEADER	RTR			Restore the count field
	AND	=0777		Remove the flag field
	CMA			Set 1's comp. in case perfect fit
	DCA	GCNTR		...
	JMP	*+3		Jump into loop below
/
8H	TAD	WCHAR		Get character to leader with
	JMS	OUTC		Output it
	LOOP	8B,GCNTR	Loop till all generated
	JMP	0B		Return for next character
/
/	Here to handle a justification space. The count of the number
/	of spaces to be produced is located in the low half of the word
/
3H	RTR			Restore the original code
	AND	=077		Isolate the space count
	JMS	GENSP		Generate that number of spaces
	JMP	0B		Loop back for the next character
/
/	Here when the sentinel has been found.
/
4H	LDI	1		Output a single CR/LF code now
	TAD	EXTRAL		Add in extra blank lines to be generated
	JMS	GENCR		Generate extra lines now
	DCA	EXTRAL		Clear the counter now
	RET	DUMPLN		Return now
/
	PART
	EJECT
/
/	Subroutine to output a message whose address (minus 1) is
/	in the AC on entry. Message is terminated with a sentinel of 0
/
OUTLN	SUB
	DCA	LXR		Save pointer to the message
	TADI	LXR		Get the next character in the message
	SNA			Test for sentinel on message
	RET	OUTLN		SENTINEL -- return to caller
	JMS	OUTC		Output the character
	JMP	OUTLN+2		Loop back for next
/
/	Subroutine to generate the number of spaces indicated in the
/	AC on entry. A count of 0 is permitted (in which case nothing
/	is generated).
/
GENSP	SUB
	CMA			Set up loop count for number of spaces
	DCA	GCNTR		...
	JMP	*+3		Jump into middle of loop (in case 0)
/
0H	TAD	=' 		Generate a blank
	JMS	OUTC		...
	LOOP	0B,GCNTR	Loop till all spaces generated
	RET	GENSP		Then return
/
/	Subroutine to generate the number of CR/LF sequences indicated
/	by count in AC. As with GENSP, a count of 0 is valid.
/	If we reach the bottom of the page, however, we stop printing
/
GENCR	SUB
	CMA			Set loop counter
	DCA	GCNTR		...
	JMP	2F		Jump into loop below (in case 0 count)
/
1H	TAD	=CR		Generate CR
	JMS	OUTC		...
	TAD	=LF		Generate LF
	JMS	OUTC		...
	LDI	-1		Decrement count of lines left on page
	TAD	LEFT		...
	DCA	LEFT		...
/
2H	TAD	LEFT		Get the number of lines left
	SPA SNA CLA		Skip if still room left on this page
	RET	GENCR		Quit now
	LOOP	1B,GCNTR	Loop till all generated
	RET	GENCR		and then return
	EJECT
/
/	Subroutine to increment an ASCII number. Calling sequence
/	provides the address of the last digit of the number to
/	increment. ASCII number is stored one character per word.
/
INCNUM	SUB
	DCA	TEMP		Save address of last digit
	TADI	TEMP		Get the digit
	TAD	=-' 		Test for possible space
	SZA CLA			Skip if so
	JMP	*+3		Else continue now
/
	TAD	='0		Change space now to a digit zero
	DCAI	TEMP		...
/
	INCI	TEMP		Increment that digit
	TADI	TEMP		Reget the digit
	TAD	=-('9+1)	Check for going too far
	SZA CLA			Skip if gone too far
	RET	INCNUM		Else return (all ok)
/
/	Gone too far, must reset digit to 0 and increment previous digit
/
	TAD	='0		Reset digit back to zero
	DCAI	TEMP		...
	LDI	-1		Move back to prior digit
	TAD	TEMP		...
	JMP	INCNUM+1	Loop back to increment it
/
/	Here is the first level of handling the output of characters.
/	Only job here is to supress all output in pass 1 and in pass 2
/	In pass 3, we send characters to the PAKUP routine and
/	check the /F flag to see if u/l case is to be folded on output.
/
NULL	DC	0		Dummy subroutine entry point
	CLA			Ignore character (we are in pass 1 or 2 here)
OUTC	SUB			Exit and entry point here
	JMS	FOLD		Set to NOP if /F option NOT chosen
	JMSI	OUTCHAR		Output char via NULL or PAKUP depending on pass
	RET	OUTC		Else return now
/
/	Little routine to pass character over to FPAK if depending upon
/	whether this character is to be packed into page buffer or not.
/
PAKF	DC	0		Dummy return address
	TAD	PAKIT		#NOP# if /D not set. Else put flag into AC 0
	SMA			Skip if packing up
	JMP	2F		Not packing up
	JMSX	FPAK		Off to pack it up
	RET	OUTC		Done
/
2H	JMS	PAKUP		Just pack directly
	RET	OUTC		Return.
	TITLE	Binary to Decimal number conversion
/
/	This subroutine takes a binary number in the AC and stores it as
/	1-3 ASCII digits in HIGH, MID and LOW. Leading zeroes are
/	supressed by inserting a binary zero to represent a leading zero
/
BINDEC	SUB
	DCA	NUMBER		Save number to go out
	DCA	HIGH		Zero counter to count subtractions
/
	TAD	NUMBER		Divide number by 100
	TAD	=-100		...
	SPA			Skip if more to go
	JMP	*+3		Else all done
	INC	HIGH		Count the subtractions that succeeded
	JMP	*-4		And loop back
/
	TAD	=100		Restore the number
	DCA	NUMBER		And save for moment
	TAD	HIGH		Get number divided by 100
	SNA			If 0, supress completely
	JMP	*+3		Zero -- suppress
/
	TAD	='0		Else store ASCII digit
	DCA	HIGH		...
/
	TAD	NUMBER		Get number now in range 0-99
	JMS	BINASC		Do remainder of conversion
/
/	Must be careful now on leading zero supression. If first digit
/	was not zero, we cannot suppress the 2nd zero!
/
	DCA	MID		Save 2nd digit
	TAD	HIGH		Did we suppress the first digit?
	SNA CLA			Skip if not
	RET	BINDEC		Yes - so allow MID to be supressed too
/
	TAD	MID		NO - so change binary zero to ASCII zero
	SNA			Skip if not binary zero
	TAD	='0		Else change to ASCII zero now
	DCA	MID		...
	RET	BINDEC		All done here
	EJECT
	TITLE	Error processing routines
/
/	Here when an error was detected.
/
	ROOM	14		All INC ERROR must be contiguous
E11	INC	ERROR		11-- Duplicate labels on symbolic reference
E10	INC	ERROR		10-- Section header overflowed
E9	INC	ERROR		9 -- Hyphenation table overflow in pass 1
E8	INC	ERROR		8 -- [-] type reference not found
E7	INC	ERROR		7 -- Symbol table overflow for sections
E6	INC	ERROR		6 -- Syntax error in numeric part of command
E5	INC	ERROR		5 -- Output buffer is full
E4	INC	ERROR		4 -- [D] command no OS/8 date entered
E3	INC	ERROR		3 -- Line to justify has no blanks in it
E2	INC	ERROR		2 -- No ] at end of command
E1	INC	ERROR		1 -- Undefined command in []
E0	INC	ERROR		0 -- line buffer has overflowed (no blanks?)
	ERM			E0-Enn entries must be protected here
/
	CLA			AC maybe non-zero on entry
	CDF	%*		Ensure current field is set
/
	TAD	ERROR		Get the number of the error we found
	CMA IAC			Negate and
	TAD	=E0		Subtract from last address in chain
	DCA	TEMP		Save address of call
	TADI	TEMP		Get the calling address
	DCA	ERCALL		and save it for later use
/
	TAD	=ERROR+02000	Reset INC instruction back in INC chain
	DCAI	TEMP		...
/
/	Now print out the file/page/line number and an error message
/
	TAD	=PSECT-1	Get address of file/page/line number
	DCA	XR		Save pointer to message
/
	TADI	XR		Get next character in the message
	SNA			Test for sentinel
	JMP	*+3		All done on sentinel
	JMS	TYPE		Else type this character
	JMP	*-4		And loop back for the next one
/
	TAD	=ERMESS		Print out ' ERROR - '
	JMS	MESSAGE		...
/
/	Now use the number in error to find out which message to print out
/
	TAD	ERROR		Get the error number
	TAD	=MBASE		Index table of message address
	DCA	TEMP		Save address
	TADI	TEMP		Get the address of the appropriate message
	CDF	%E0MS		To field of message
	JMS	MESSAGE		Print out that message
	CDF	%*		Reset current field now
	JMS	CRLF		Print CR/LF sequence
/
	DCA	ERROR		Clear out the error cell for next time
	TAD	FATAL		Was this a fatal error here?
	SZA CLA			Skip if not
	JMP	$07600		FATAL ERROR - Return to OS/8 monitor
/
/	We do not print the line with the error because it may be drastically
/	wrong.
/
	LDI	-1		Install sentinels to flush out current line
	DCA	LINEB		...
	LDI	-1		...
	DCA	LINEB+1		...
	INC	ERFLAG		Set flag to force file/page/line number out
	JMS	DUMPLN		Dump out blank line now
	DCA	ERFLAG		Clear the error flag
	JMP	NEWLN		Now try and recover by starting a new line
/
/	Subroutine to print out a message on the console. Message address
/	should be in the AC on entry. Message has 2 characters per word
/	packed in 6-bit ASCII.
/
/	following characters are treated specially:
/
/	%	marks end of the message
/	+	generates a CR/LF sequence
/	@	always ignored
/
/	Data field is not disturbed by this routine (and should not be
/	since HELP message is in field 1)
/
MESSAGE	SUB
	DCA	TEMP		Save address of message
	TADI	TEMP		Do the left half of this word
	RTR			Move the left half down to right half of AC
	RTR			...
	RTR			...
	JMS	HALF		...
	TADI	TEMP		Now do the right half of this word
	JMS	HALF		...
	INC	TEMP		Step to next location
	JMS	ABORTCK		Check for abort from console
	JMP	MESSAGE+2	And loop for the next one
/
/	Little subroutine to output the right half of the AC as a
/	8-bit character on the console
/
HALF	SUB
	AND	=077		Extract the right half of the AC
	SNA			Test for null
	RET	HALF		Always ignore binary null
	TAD	=-"@%		Test for end of message
	SNA
	RET	MESSAGE		% found -- all done here
	TAD	="@%-"@+	Test for encoded CR/LF
	SNA
	JMP	1F		Off to do CR/LF
	TAD	="@+-040	Restore and test for range of character
	SPA			Skip if character code is in range 240-277
	TAD	=0100		Was 00-37 so set for range 300-337
	TAD	=0240		Restore character to full 8-bit code
	JMS	TYPE		Type it out
	RET	HALF		And return
/
/	Here for encoded CR/LF
/
1H	JMS	CRLF		Do CR/LF now
	RET	HALF		And return to call
	TITLE	Index of contents processing
/
/	Here to process the index of contents. We do this in both passes
/	since in pass 1 there is no output, and the symbol table is empty
/	anyway. In pass 2, we do the index so we know how many pages there
/	are in the index.
/
/	First check that we are not suppressing the index of contents table
/
INDEX	SUB
	TAD	IFLAG		Load suppression flag
	TAD	NFLAG		If /N set, cannot generate index anyway
	SZA CLA			Skip if not suppressing the index
	RET	INDEX		We are supressing -- so return now
	TAD	OLDW		Get minus current maximum title width
	CLL CMA IAC RAR		Divide by 2 for centering
	TAD	=-(17/2)+01000	Account for width of TABLE OF CONTENTS
	DCA	LINEB		...
	TAD	=INMSG-1	Set pointer to 'TABLE OF CONTENTS' message
	DCA	XR1		...
	TAD	=LINEB		Set pointer to LINEB buffer
	DCA	XR2		...
/
/	Loop here to copy over the message into the LINEB buffer
/
0H	TADI	XR1		Get character from message
	SNA			Test for sentinel
	JMP	*+3		All done here on sentinel
	DCAI	XR2		Else copy over to buffer
	JMP	0B		And loop back for next
/
	LDI	-1		Install line sentinel on LINEB buffer
	DCAI	XR2		...
	JMS	DUMPLN		Dump out the line now
	LDI	2		Generate two blank lines
	JMS	GENCR		...
/
/	Now initialize pointers for dumping out the index
/
	LDI	-1		Set pointer to start of symbol table
	TAD	SYSTART		...
	DCA	SYMPTR2		...
	TAD	=06211		Initialize the starting CDF instruction
	DCA	SYMCDF2+1	...
/
/	Loop here to dump out a new entry
/
1H	JMS	INCSYM2		Step to start of new entry
	TAD	SYMCDF2+1	First compare CDF instructions
	CMA IAC			...
	TAD	CDFTOP		To see if we are in same field
	SZA CLA			Skip if so
	JMP	7F		Definitely more to do here
/
	TAD	SYMPTR2		If these pointers match now, we are done
	CMA IAC			...
	TAD	SYMTOP		...
	SNA CLA			skip if no match
	JMP	XDONE		Ok - done with the index now
/
/	Prepare to dump out the section number for this entry
/
7H	TAD	=LINEB-1	Set LINEB pointer
	DCA	LXR		...
	DCA	INDENT		Counts number of sections for indention
	TAD	=NLEVEL-1	Set pointer to save area for LEVEL field
	DCA	XR1		...
	JMS	SYMCDF2		To field of symbol table
	TADI	SYMPTR2		Get the first word (page number)
	CDF	%*		Reset current field
	DCA	SAVE		And save it for later use
/
/	Loop here to read the LEVEL field and copy to the NLEVEL buffer
/
2H	JMS	INCSYM2		Step pointer to next word in buffer
	JMS	SYMCDF2		Set to field of tables
	TADI	SYMPTR2		Load next pair of characters
	CDF	%*		Reset current field
	SNA			Test for sentinel on level field
	JMP	3F		All done with level field now
	INC	INDENT		Count the number of levels used here
	DCAI	XR1		Store into NLEVEL buffer
	JMP	2B		Loop back for next
/
/	Here when we have finished with the section number. Dump the section
/	number and then process text field of entry
/
3H	DCAI	XR1		Install sentinel on the buffer
	TAD	=NLEVEL		Dump out the level number now
	JMS	DOLEVEL,STAC	...
/
/	Now we have to tabulate over to the indent for this section
/	tab stop is at: 4 + 2*(level)
/
	LDI	8/2		Set for 8 blanks after section number
	TAD	INDENT		Get the number of levels here
	CLL RAL			Multiply by 2
	CMA IAC			Reverse signs for a moment
	TAD	LXR		Subtract positions already set on line
	TAD	=-(LINEB-1)		...
	DCA	GCNTR		To get to the correct tabulation stop
/
6H	TAD	=' 		Install a blank
	DCAI	LXR		...
	LOOP	6B,GCNTR	Loop till all inserted
/
/	Now process the label field on this entry
/
4H	JMS	INCSYM2		Step to next position in the TEXT field
	JMS	SYMCDF2		To field of table
	TADI	SYMPTR2		Load next pair of characters
	CDF	%*		Reset current field
	SNA			Test for sentinel on TEXT field
	JMP	5F		All done on sentinel
/
	DCA	PTR		Save the 2 characters
	TAD	PTR		Reget now
	CLL RTR			Shift the right half down
	RTR			...
	RTR			...
	JMS	OHALF		Output right half of AC
	TAD	PTR		Reget the two characters again
	JMS	OHALF		Output the right half of the AC
	JMP	4B		Loop back for next
/
/	Here when done. Tab over now to the right-hand margin to insert
/	the page number.
/
5H	LDI	6		Account for 6 spaces in page number
	TAD	LXR		Get address into the line buffer
	TAD	=-LINEB		Subtract the base address to get position
	TAD	OLDW		Subtract maximum title width (in case /D)
	STL RAR			Divide by 2 and use as loop counter
	DCA	GCNTR		Set it
/
/	Now store alternating blanks and periods till we get to the
/	right-hand margin.
/
6H	TAD	=' 		Store a blank
	DCAI	LXR		...
	TAD	='.		Then store a period
	DCAI	LXR		...
	LOOP	6B,GCNTR	Loop till all stored
/
/	Now dump out the page number in fixed form, changing leading
/	zeroes to blanks.
/
	TAD	SAVE		Get the saved page number
	JMS	BINDEC		Convert to ASCII decimal number
	TAD	=' 		Install extra blank before page number
	DCAI	LXR		...
	TAD	=STAC		Set to output via the STAC routine
	JMS	STAPG		Store the page number
/
/	Here when all done, set to print out this line on the output device
/
	LDI	-1		Install sentinel on the line
	DCAI	LXR		...
	DCA	INDENT		Remove indent setting now
	JMS	DUMPLN		Dump out this line now
/
/	If /D option in effect, we are only using the left-hand column
/	since we want the table of contents to extend across the entire page
/
	TAD	LEFT		Get number of lines left
	CLL CMA IAC RAL		Negate and multiply by 2
	TAD	LINES		Compare with total number of lines
	SPA CLA			Skip if starting right column next time (if /D)
	JMP	1B		Else loop for next entry now
	LDI	-1		In case /D, Force new page now
SLASHD5	DCA	EJFLAG		#CLA# if /D not set.
	JMP	1B		Loop back now for next line
/
/	Here when all done with the index
/
XDONE	LDI	-1		Set for new page after index of contents
	DCA	EJFLAG		...
	DCA	DISPLAY		Reset the display counter
	RET	INDEX		All done here
/
/	Subroutine called by INDEX to output the right half of the AC
/	as a full 8-bit code. Routine also checks for overflowing
/	the line, and will not store characters if there is no more room
/
OHALF	SUB
	AND	=077		Truncate down to a 6-bit byte
	SNA			Test for '@' on alignment to word boundary
	JMP	*+4 		If so, change it to a blank now
/
	TAD	=-040		Test for range 0-37
	SPA			Skip if in range 40-77
	TAD	=0100		Was 0-37 so expand to 300-337
/
	TAD	=040+0200	Restore code now
	DCA	TEMP		Save for a moment
/
/	Check for more room in the line buffer
/
	TAD	LXR		Get current address into line buffer
	TAD	=-LINEB+7	Subtract starting address (+ extra room needed)
	TAD	OLDW		Subtract maximum width for this line
	SMA CLA			Skip if we still have room
	RET	OHALF		No more room - so don't store the character
/
	TAD	TEMP		More room -- get the character
	DCAI	LXR		Install into the LINEB buffer
	RET	OHALF		return.