perm filename NETLIB.FAI[S,NET] blob sn#794284 filedate 1985-05-25 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00004 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	This is a library of network subroutines, to be linked together with
C00003 00003	TITLE EXPABR  FL A B C D P DSK TAB LF FF CR SPACE QUOTE QUO ABRFIL BUFSIZ OUTBFR OUTPTR LINBUF LINPTR ABBPTR EXPPTR INPTR ATPTR FILADR FILLNG FILPTR CCOUNT EXPABR GOTCOR SEARCH NXTLIN NOMORE RESTR IOPDLO NOINIT NOLOOK NOCORE FBEGIN ATSIGN ATSIG1 GETCHR CPOPJ1 CPOPJ GETLIN GETLI1 GETLI2 GETLI3 SPLIT ABBCHK ABBCH1 TOKEN TOKEN2 TOKEN3 DELIM0 DELIM COMPAR COMPA1 NEWSTR ATCOPY NOATSN NOATS1
C00019 00004	END
C00020 ENDMK
C⊗;
;This is a library of network subroutines, to be linked together with
;programs that need them.  It extends basic support in the NETWRK package,
;but differs in that these are separately compiled, independent routines.

;Contents:
;
;EXPABR - expands abbreviations using ABBREV.TXT files.

TITLE EXPABR ;⊗ FL A B C D P DSK TAB LF FF CR SPACE QUOTE QUO ABRFIL BUFSIZ OUTBFR OUTPTR LINBUF LINPTR ABBPTR EXPPTR INPTR ATPTR FILADR FILLNG FILPTR CCOUNT EXPABR GOTCOR SEARCH NXTLIN NOMORE RESTR IOPDLO NOINIT NOLOOK NOCORE FBEGIN ATSIGN ATSIG1 GETCHR CPOPJ1 CPOPJ GETLIN GETLI1 GETLI2 GETLI3 SPLIT ABBCHK ABBCH1 TOKEN TOKEN2 TOKEN3 DELIM0 DELIM COMPAR COMPA1 NEWSTR ATCOPY NOATSN NOATS1
	INTERN EXPABR

;EXPABR - Expand abbreviations using OPTION.TXT entries.
;
;Call:	MOVE 1,[<byte ptr to string to be expanded, or
;		addr of first word if 7-bit bytes>]
;	PUSHJ 17,EXPABR
;	 <error return: addr of error text in 1>
;	<normal return: byte ptr to expanded string in 1>
;
;All strings are assumed to be ASCIZ strings.  Saves and restores all ACs.

FL←0
A←1
B←2
C←3
D←4
P←17

DSK←←0

TAB←←11				;ASCII characters
LF←12
FF←14
CR←15
SPACE←40
QUOTE←42

;FL bits (right half)
QUO←←1				;Currently inside quotes

ABRFIL:	SIXBIT/ABBREV/
	SIXBIT/TXT/
	0
	0			;PPN to be filled in

BUFSIZ←←50			;Size of various buffers
OUTBFR:	BLOCK BUFSIZ		;Buffer to hold final output string
OUTPTR:	POINT 7,OUTBFR
LINBUF:	BLOCK BUFSIZ		;Buffer to hold input line
LINPTR:	POINT 7,LINBUF
ABBPTR:	0			;Pointer to abbreviation part of a line
EXPPTR:	0			;Pointer to expansion part of a line
INPTR:	0			;Pointer to current input string
ATPTR:	0			;Pointer to original string, if it had an @
FILADR:	0			;Address of start of file image
FILLNG:	0			;Length of file, in words
FILPTR:	0			;Pointer to current char in file
CCOUNT:	0			;Count of remaining chars
PASSCT:	0			;Number of passes over input file so far

EXPABR:	IOPUSH DSK,0		;Get a temporary I/O channel
	 JRST IOPDLO		;IOPUSH failed
	PUSH P,FL
	PUSH P,B
	PUSH P,C
	PUSH P,D
	PUSH P,JOBFF↑		;Save top of core ptr
	SETZM PASSCT
	TLNN A,-1		;Zero in left half?
	HRLI A,440700		;Yes, make 7-bit byte ptr
	MOVEM A,INPTR
	INIT DSK,17		;Dump mode
	 SIXBIT/DSK/
	 0
	 JRST NOINIT		;INIT failed
	GETPPN A,		;Always look on login area
	MOVEM A,ABRFIL+3
	LOOKUP DSK,ABRFIL
	 JRST NOLOOK		;LOOKUP failed, maybe file isn't there
	HRRZ A,JOBFF
	MOVEM A,FILADR		;Address where we'll read the file into
	MOVS B,ABRFIL+3
	MOVN B,B		;Word count of file
	MOVEM B,FILLNG
	ADDB B,JOBFF		;New core size
	CAMG B,JOBREL↑		;Skip if we need more core
	JRST GOTCOR		;Got enough already
	CORE B,
	 JRST NOCORE
GOTCOR:	HLL A,ABRFIL+3		;-count in left half
	SUBI A,1		;Form IOWD
	SETZ B,			;End IOWD list
	IN DSK,A		;Read the whole file into core
	 JRST SEARCH
	MOVEI A,[ASCIZ/Input error reading OPTION.TXT./]
	JRST RESTR

;Start searching at beginning of abbreviation file.
SEARCH:	PUSHJ P,FBEGIN		;Set up pointers to beginning of file
	PUSHJ P,ATSIGN		;Check for @ in input string
NXTLIN:	PUSHJ P,GETLIN		;Get a line from the abbreviation file
	 JRST NOMORE		;No more lines
	PUSHJ P,SPLIT		;Split line into abbreviation and expansion
	 JRST NXTLIN		;Not an ABBREV line or error, ignore line
	PUSHJ P,COMPAR		;Compare and skip if equal
	 JRST NXTLIN
	PUSHJ P,NEWSTR		;Construct new string in OUTBFR
;Now we go back and repeat the process.  You might think there is a problem
;since our input text is now in OUTBFR, and we'd be reading and writing it
;simultaneously after we find the next expansion.  But this is only there
;is an @ sign in it, and in that case, the text before the @ sign isn't
;altered, so it is unchanged by the copying.  (Lucky, aren't we!)
	MOVE A,OUTPTR		;Our output text
	MOVEM A,INPTR		;Is now the input
	AOS A,PASSCT		;Prevent infinite loops
	CAIGE A,=100
	JRST SEARCH		;Go and do it again
	MOVEI A,[ASCIZ/Probable infinite loop expanding abbreviations./]
	JRST RESTR

;Here after abbreviation file exhausted without having done any substitution.
NOMORE:	AOS -5(P)		;Set skip return
	SKIPN A,ATPTR		;Point to original INPTR if it's here
	MOVE A,INPTR		;Else it is still here
RESTR:	POP P,JOBFF		;Restore what we saved
	POP P,D
	POP P,C
	POP P,B
	POP P,FL
	IOPOP DSK,0		;And I/O channel
	 JRST IOPDLO		;This IOPOP can't fail
	POPJ P,

IOPDLO:	MOVEI A,[ASCIZ\IOPUSH/POP failed reading OPTION.TXT.\]
	POPJ P,

NOINIT:	MOVEI A,[ASCIZ/INIT failed reading OPTION.TXT./]
	JRST RESTR

NOLOOK:	HRRZ A,ABRFIL+1		;Get error code
	JUMPE A,NOMORE		;File doesn't exist, fine
	MOVEI A,[ASCIZ/LOOKUP failed reading OPTION.TXT./]
	JRST RESTR

NOCORE:	MOVEI A,[ASCIZ/Can't get core to read OPTION.TXT./]
	JRST RESTR

FBEGIN:	MOVE A,FILLNG
	IMULI A,5		;Compute char count
	MOVEM A,CCOUNT
	HRRZ A,FILADR
	HRLI A,440700		;Point to first char
	MOVEM A,FILPTR
	POPJ P,

;Check for @ in input string.  If found, adjust INPTR and ATPTR.
ATSIGN:	MOVE B,INPTR
	SETZM ATPTR		;No @ found yet
	TLZ FL,QUO
ATSIG1:	ILDB A,B		;Get next char
	JUMPE A,CPOPJ		;Return if done
	CAIN A,QUOTE		;Skip unless it's a quote
	TLC FL,QUO		;Quoting ↔ not quoting
	TLNN FL,QUO		;If quoting,
	CAIE A,"@"		;or not an atsign,
	JRST ATSIG1		;keep looking
	EXCH B,INPTR		;Store pointer to new beginning
	MOVEM B,ATPTR		;Remember old one
	POPJ P,

;Get next non-null character from input file into A.  Skips on success.
GETCHR:	SOSG CCOUNT
	POPJ P,			;End of file
	ILDB A,FILPTR
	JUMPE A,GETCHR		;Don't return nulls
CPOPJ1:	AOS (P)
CPOPJ:	POPJ P,

;Get a line from the input file.  Skips on success, line in LINBUF.
GETLIN:	MOVE B,LINPTR		;Place to store line
	MOVEI C,BUFSIZ*5-1	;Max count of chars to store
GETLI1:	PUSHJ P,GETCHR		;Get next character
	 JRST GETLI2		;No more
	CAIE A,CR		;Ignore <cr>
	CAIN A,FF		;Ignore <ff>
	JRST GETLI1
	CAIN A,LF		;End line at <lf>
	JRST GETLI3
	JUMPLE C,GETLI1		;If buffer full, skip to end of line
	IDPB A,B		;Save character
	SOJA C,GETLI1		;Decrement count and continue

;Here at end of file.
GETLI2:	CAIN C,BUFSIZ*5-1	;Did the luser omit the last <lf>?
	POPJ P,			;No, normal end of file
;Here at end of an input line.
GETLI3:	MOVEI A,0		;End with a null
	IDPB A,B
	JRST CPOPJ1

;Split input line into abbreviation and expansion parts.  Skips on success.
;ABBPTR is set to point to the abbreviation part of the line, EXPPTR to the
;expansion part.  The line is altered by depositing null bytes at the end
;of each of these two parts in LINBUF.
SPLIT:	MOVE B,LINPTR		;Point to beginning of line
	PUSHJ P,ABBCHK		;Skip if it's an "ABBREV:" line
	 POPJ P,		;Return if it's something else
	MOVEI D,"="		;Delimiter for abbreviation
	PUSHJ P,TOKEN		;Find the abbreviation
	 POPJ P,		;Pass back error return
	ADD C,[70000,,0]	;Back up the byte ptr for future ILDBs
	MOVEM C,ABBPTR
	MOVEI C,0		;Stick a null in to end the string
	DPB C,B
	;(Note: contents of A and D needed for call to DELIM.)
	PUSHJ P,DELIM		;Skip up to the delimiter
	 POPJ P,		;Something else was there!
	MOVEI D,0		;Use no delimiter for expansion
	PUSHJ P,TOKEN		;Find the expansion
	 POPJ P,		;Another chance for errors
	ADD C,[70000,,0]
	MOVEM C,EXPPTR
	MOVEI C,0
	DPB C,B
	JRST CPOPJ1

;ABBCHK checks for the string "ABBREV:" at the beginning of the line,
;and skips if it is found, with B updated to scan for the first token.

ABBCHK:	MOVE D,[POINT 7,[ASCII/ABBREV:/]]
ABBCH1:	ILDB A,B		;Char from line
	ILDB C,D		;Char from test string
	CAIL A,"a"		;Upper-casify
	CAILE A,"z"
	JRST .+2
	SUBI A,40
	CAIE A,(C)		;Skip if the same
	POPJ P,			;Fail if different
	CAIE A,":"		;Same, check if done
	JRST ABBCH1		;Not done, keep testing
	JRST CPOPJ1

;TOKEN takes an ILDB pointer to the potential first character of a token
;in B and a delimiter character in D (use 0 if no delimiter desired),
;and skip returns if it finds a legal token, with an LDB pointer to
;the actual first character in C, and an LDB pointer to the character
;following the token in B.  The direct return is taken on errors.

TOKEN:	ILDB A,B		;Start examining characters
	JUMPE A,CPOPJ		;Oops, can't be done yet!
	CAIE A,SPACE
	CAIN A,TAB
	JRST TOKEN		;Skip whitespace
	CAIN A,";"
	POPJ P,			;No token here, just a comment
	MOVE C,B		;Remember this position
;Now we search for the end of the token.
TOKEN2:	CAIN A,QUOTE		;Skip unless it's a quote
	TLC FL,QUO		;Quoting ↔ not quoting
	TLNE FL,QUO		;Quoting?
	JRST TOKEN3		;Yes, don't examine char
	CAIE A,";"		;Comment always ends token
	CAIN A,(D)		;So does delimiter if there is one
	JRST CPOPJ1
	CAIE A,SPACE		;Whitespace ends token also
	CAIN A,TAB
	JRST CPOPJ1
TOKEN3:	ILDB A,B
	JUMPN A,TOKEN2		;Get next char, jump unless end of line
	TLZN FL,QUO		;Still quoting at end of line?
	AOS (P)			;No, we're at end of token
	POPJ P,			;Error if we are

;Skip whitespace up to and including the delimiter, if not already there.
DELIM0:	ILDB A,B
DELIM:	CAIE A,SPACE		;Skip whitespace ...
	CAIN A,TAB
	JRST DELIM0
	CAIN A,(D)		;This better be the delimiter
	AOS (P)			;Yes, give skip return
	POPJ P,			;Else fail

;Compare input string with line from file.  Skip if they match.
COMPAR:	MOVE B,INPTR		;Compare the input string
	MOVE D,ABBPTR		;With the abbreviation
COMPA1:	ILDB A,B		;Get a char from each
	ILDB C,D
	CAIL A,"a"		;Map lower case to upper
	CAILE A,"z"
	JRST .+2
	SUBI A,40
	CAIL C,"a"
	CAILE C,"z"
	JRST .+2
	SUBI C,40
	CAIE A,(C)		;Skip if the same
	POPJ P,			;Different, fail
	JUMPN A,COMPA1		;Same, continue checking unless done
	JRST CPOPJ1		;Successful compare

;Construct the new string in OUTBFR, with the abbreviation replaced by
;the expansion.
NEWSTR:	MOVE C,OUTPTR
	SKIPN B,ATPTR		;Was there text before an @?
	JRST NOATSN		;No
ATCOPY:	ILDB A,B		;Yes, copy text up to @ sign
	IDPB A,C
	CAME B,INPTR		;This is where it ends
	JRST ATCOPY
NOATSN:	MOVE B,EXPPTR		;Now copy expansion text
NOATS1:	ILDB A,B
	IDPB A,C
	JUMPN A,NOATS1
	POPJ P,

	PRGEND
END