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.