perm filename HOST.FAI[S,NET]7 blob sn#796096 filedate 1985-06-13 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00009 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00003 00002	 A B C X Y P PDLEN HSTSID HSTFN1 HSTVRS HSTDIR HSTDEV HSTWHO HSTDAT HSTTIM NAMPTR SITPTR NETPTR NTNPTR HDRLEN NETNUM NTLNAM NTRTAB NETLEN ADDADR ADLSIT ADRCDR ADLXXX ADRSVC SVLCNT SVRCDR SVLFLG SVRNAM SVCARG ADDLEN STLNAM STRADR STLSYS STRMCH STLFLG STFSRV STFGWY SITLEN NMLSIT NMRNAM NAMLEN NNLNET NNRNAM NTNLEN NT$NUM NE%UNT NE%STR NN%IP NW%ARP NW%SI NW%SU HSTFIL HSTPPN
C00015 00003	 START FLSINP HSTCOM CMDSCN PROMPT DOCMD HSTLUP GOTHST GETNUM GETNU1 GETNU2 GETNU3 GETNU4 GETNU5 GETNU6 NOTIPH HSTLUZ ALPHST CNTCHR
C00021 00004	 SEARCH SRCNXW SRCWIN OFFNAM NXTHST PRINT NAMLP NAMDUN MCHTYP ENDNIC
C00026 00005	 MAPHST
C00027 00006	 HSTNUM HSTNU0 HSTNUS HSTNU1 HSTNU2 HSTNU3 HSTNUD
C00029 00007	 SWINIR SWINR1 SWINR2 SWINIP CPOPJ1 CPOPJ SWINP1 PRHNUM PRHNIP PRDECP PRDEC PROCT PRLOOP PDL MONCMP HSTADR HSTTOP HSTEXT CRLF
C00034 00008	Host table printer  H TBL D hostab hostb1 htbunm netprt nhashs skpntp
C00038 00009	 onenet foo3 hstprt hsterr outcnt outcn1 outcn2
C00042 ENDMK
C⊗;
;⊗ A B C X Y P PDLEN HSTSID HSTFN1 HSTVRS HSTDIR HSTDEV HSTWHO HSTDAT HSTTIM NAMPTR SITPTR NETPTR NTNPTR HDRLEN NETNUM NTLNAM NTRTAB NETLEN ADDADR ADLSIT ADRCDR ADLXXX ADRSVC SVLCNT SVRCDR SVLFLG SVRNAM SVCARG ADDLEN STLNAM STRADR STLSYS STRMCH STLFLG STFSRV STFGWY SITLEN NMLSIT NMRNAM NAMLEN NNLNET NNRNAM NTNLEN NT$NUM NE%UNT NE%STR NN%IP NW%ARP NW%SI NW%SU HSTFIL HSTPPN

	TITLE HOST

;This program is adapted from the old HOST.MID, which read the HOSTS1.BIN
;file, and from various code in NETWRK.FAI.  NETWRK isn't inserted directly,
;because we want to do slightly different things in searching for host names.

A←12				;Our AC's don't interfere with NETWRK's
B←13
C←14
X←15
Y←16
P←17

PDLEN←←20

;The format of the host table binary file is:

HSTSID←←0	; wd 0	SIXBIT /HOSTS3/
HSTFN1←←1	; wd 1	SIXBIT FN1 of source file (eg HOSTS)
HSTVRS←←2	; wd 2	SIXBIT FN2 of source file (TNX: version #)
HSTDIR←←3	; wd 3  SIXBIT directory name of source file (eg SYSENG)
HSTDEV←←4	; wd 4  SIXBIT device name of source file (eg AI)
HSTWHO←←5	; wd 5	SIXBIT login name of person who compiled this
HSTDAT←←6	; wd 6  SIXBIT Date of compilation as YYMMDD
HSTTIM←←7	; wd 7	SIXBIT Time of compilation as HHMMSS
NAMPTR←←10	; wd 10 Fileaddress of NAME table.
SITPTR←←11	; wd 11	Fileaddress of SITE table.
NETPTR←←12	; wd 12 Fileaddress of NETWORK table.
NTNPTR←←13	; wd 13 Fileaddress of NETNAME table.
		;....expandable....
  HDRLEN←←14	; length of header

; NETWORK table
;	wd 0	Number of entries in table.
;	wd 1	Number of words per entry. (2)
; This table contains one entry for each known network.
; It is sorted by network number.
; Each entry contains:

NETNUM←←0	; wd 0 network number (full netaddr)
NTLNAM←←1	; wd 1 LH - fileaddr of ASCIZ name of network
NTRTAB←←1	; wd 1 RH - fileaddr of network's ADDRESS table
 NETLEN←←2

; ADDRESS table(s)
;	wd 0	Number of entries in table.
;	wd 1	Number of words per entry. (3)
; There is one of these tables for each network.  It contains entries
; for each site attached to that network, sorted by network address.
; These tables are used to convert a numeric address into a host name.
; Also, the list of network addresses and services for a site is stored
; within these tables.
; Each entry contains:

ADDADR←←0	; wd 0	Network address of this entry, in HOSTS3 fmt.
ADLSIT←←1	; wd 1 LH - fileaddr of SITE table entry
ADRCDR←←1	; wd 1 RH - fileaddr of next ADDRESS entry for this site
		;	 0 = end of list
ADLXXX←←2	; wd 2 LH - unused
ADRSVC←←2	; wd 2 RH - fileaddr of services list for this address
		;	0 = none, else points to SERVICE node of format:
	SVLCNT←←0	;		<# wds>,,<fileaddr of next, or 0>
	SVRCDR←←0
	SVLFLG←←1	;		<flags>,,<fileaddr of svc name>
	SVRNAM←←1
	SVCARG←←2	;		<param1> ? <param2> ? ...
 ADDLEN←←3

; SITE table
;	wd 0	Number of entries in table.
;	wd 1	Number of words per entry. (3)
; This table contains entries for each network site,
; not sorted by anything in particular. A site can have more
; than one network address, usually on different networks.
; This is the main, central table.
; Each entry looks like:

STLNAM←←0	; wd 0 LH - fileaddr of official host name
STRADR←←0	; wd 0 RH - fileaddr of first ADDRESS table entry for this
		;		site.  Successive entries are threaded
		;		together through ADRCDR.
STLSYS←←1	; wd 1 LH - fileaddr of system name (ITS, TIP, TENEX, etc.)
		;		May be 0 → not known.
STRMCH←←1	; wd 1 RH - fileaddr of machine name (PDP10, etc.)
		;		May be 0 → not known.
STLFLG←←2	; wd 2 LH - flags:
STFSRV←←400000	;	4.9 1 → server site (has FTP or TELNET)
STFGWY←←200000	;	4.8 1 → Internet Gateway site (HOSTS3 only)
 SITLEN←←3

; NAMES table:
;	wd 0	Number of entries
;	wd 1	Number of words per entry. (1)
; This table is used to convert host names into network addresses.  It
; contains entries sorted alphabetically by host name.

NMLSIT←←0	; wd 0 LH - fileaddr of SITE table entry for this host.
NMRNAM←←0	; wd 0 RH - fileaddr of host name
		; This name is official if NMRNAM = STLNAM of NMLSIT.
 NAMLEN←←1

; NETNAME table:
;	wd 0	Number of entries
;	wd 1	Number of words per entry. (1)
; This table is used to convert network names into network numbers.  It
; contains entries sorted alphabetically by network name, exactly as
; for the NAMES table.  Although the symbols below are different (in order
; to make semantic distinctions), programs can depend on the fact
; that the NETNAME table format is identical to that of the NAMES table.

NNLNET←←0	; wd 0 LH - fileaddr of NETWORK table entry for this host.
NNRNAM←←0	; wd 0 RH - fileaddr of network name
 NTNLEN←←1

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;		HOSTS3 Network Address Format           ;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

comment |
HOSTS3 network address format:

   4.9-4.6 - 4 bits of format type, which specify interpretation of
		the remaining 32 bits.
IN	0000 - Internet address (handles ARPA, RCC, LCS)
		4.5-1.1 - 32 bits of IN address.
UN	0001 - Unternet address.  Same format, but not part of Internet.
		4.5-3.7 - HOSTS3-defined network number (1st 8-bit byte)
		3.6-1.1 - address value in next 24 bits.
			This handles CHAOS and any local nets.  The network
			numbers are unique within the HOSTS3 table but
			don't necessarily mean anything globally, as do
			Internet network numbers.
	0011 - String address.
		4.5-3.7 - HOSTS3-defined network number (1st 8-bit byte)
		3.6-3.1 - 0
		2.9-1.1 - address of ASCIZ string in file/process space

Note that the "network number" for all of these formats is located in
the same place.  However, for fast deciphering of the entire range of
possibilities, one could simply consider all of the high 12 bits as the
network number.  Beware of the Internet class A, B, and C formats, though;
the only truly general way to compare network numbers is to use their
masked 36-bit values, although simpler checks are OK for specific nets.
For this reason (among others) network numbers are represented by
full 36-bit values with the "local address" portion zero.

The 4-bit "String address" value is much more tentative than the IN or UN
values.  Bit 4.9, the sign bit, is being reserved as usual for the possible
advent of a truly spectacular incompatible format.
|

NT$NUM←←301400		;Byte pointer to network number (high 12 bits)
NE%UNT←←<040000,,0>	;Escape bit indicating "Unternet" type address
NE%STR←←<100000,,0>	;Escape bit indicating "string" type address
NN%IP←←<740000,,0>	;host number bits that are off for all IP addresses
NW%ARP←←<12⊗=24>	;HOSTS3 uses full word network # values
NW%SI←←44⊗=24		;Internet address of SU-NET-TEMP
NW%SU←←NE%UNT+NW%SI	;"Unternet" used for Stanford Ethernet


DEFINE GETNET(AC,ADDR)<
IFDIF <ADDR><><MOVE AC,ADDR>
	TLNN AC,(17⊗=32)	; Check for non-Internet type addrs
	 TLNN AC,(1⊗=31)	;  Internet address, see if class A net
	  TDZA AC,[77,,-1]	;   Unternet or class A, zap low 3 octets
	TLNN AC,(1⊗=30)		; Class B or C, see which.
	 TRZA AC,177777		;  Class B network, zap low 2 octets
	  TRZ AC,377		;   Class C net, only zap 1 low octet
>;GETNET

HSTFIL:	SIXBIT/HOSTS3/		;filename and extension of binary file
	SIXBIT/BIN/
HSTPPN:	SIXBIT/HSTNET/		;PPN of binary file
;⊗ START FLSINP HSTCOM CMDSCN PROMPT DOCMD HSTLUP GOTHST GETNUM GETNU1 GETNU2 GETNU3 GETNU4 GETNU5 GETNU6 NOTIPH HSTLUZ ALPHST CNTCHR

START:	CAI
	RESET
	SETZM MONCMP
	MOVE P,[IOWD PDLEN,PDL]
	PUSHJ P,MAPHST		;Map host table in core
	RESCAN A
	JUMPE A,PROMPT
	INCHRS X
	 JRST PROMPT
	CAIE X,"H"		;Check for HOST command
	 CAIN X,"h"
	  JRST HSTCOM
FLSINP:	INCHRS X
	 JRST PROMPT
	CAIE X,175
	 CAIN X,12
	  JRST PROMPT
	JRST FLSINP

HSTCOM:	OUTSTR CRLF
CMDSCN:	INCHRS X
	 JRST GOTHST
	CAIE X,175
	 CAIN X,12
	  JRST GOTHST		;No command argument
	CAIE X," "
	 JRST CMDSCN
	SETOM MONCMP
	JRST DOCMD

PROMPT:	SKIPE MONCMP
	 EXIT 1,
	OUTSTR [ASCIZ/
Host name or number: /]
DOCMD:	SETZM HSTEXT
	MOVE Y,[POINT 7,HSTEXT]
HSTLUP:	INCHWL X
	ANDI X,177
	CAIN X,15
	 INCHWL X
	CAIE X,175
	 CAIN X,12
	  JRST GOTHST
	IDPB X,Y
	JRST HSTLUP

GOTHST:	SKIPN HSTEXT
	 JRST HOSTAB		;Print whole table
	SETZ X,
	IDPB X,Y
;Here with input text string in HSTEXT.
	MOVE Y,[POINT 7,HSTEXT]	;Start at beginning of text
	ILDB X,Y		;Now see if we got a name or a number
	CAIL X,"0"
	 CAILE X,"9"
	  JRST ALPHST		;Alphabetic host specification
	PUSHJ P,SWINIP		;Get host number
	 JRST NOTIPH		;Not an IP host number
	JUMPN X,HSTLUZ
	MOVE 0,B		;Set up for HSTNUM
GETNUM:	PUSHJ P,HSTNUM		;Look up the number
	 JRST GETNU2		;Not found
GETNU1:	HLRZ 6,STLNAM(7)	;Get official name
	ADD 6,HSTADR
	OUTSTR (6)
	PUSHJ P,PRINT
	JRST PROMPT

GETNU2:	HLRZ 0,B		;Get LH of host number
	ANDI 0,777700		;Just class-A network part
	CAIN 0,(NW%SU)		;Stanford PUP address?
	JRST GETNU4		;Yes, convert to IP
	CAIN 0,(NW%SI)		;Or Stanford IP?
	JRST GETNU5		;Yes, convert to PUP
GETNU3:	OUTSTR [ASCIZ/Unknown host
/]
	JRST PROMPT

GETNU4:	LDB 0,[POINT 8,B,27]	;Subnet number from PUP address
	LSH 0,=8		;Position for IP address
	JRST GETNU6

GETNU5:	LDB 0,[POINT 8,B,19]	;Subnet number from IP address
GETNU6:	DPB 0,[POINT 16,B,27]	;Store 2nd and 3 bytes
	TLC B,(NW%SU≠NW%SI)	;Change to the other network
	MOVE 0,B
	PUSHJ P,HSTNUM		;And look that up
	 JRST GETNU3		;Not there either
	JRST GETNU1		;Matched, sort of, so tell the user

;Here with a non-IP host number in A (octal) and B (decimal).
NOTIPH:	JUMPE X,[OUTSTR [ASCIZ/Incomplete host number specification
/]
		JRST PROMPT]
	CAIN X,"/"		;BBN style number?
	 JRST [	CAILE B,377
		 SETO B,
		PUSH P,B
		ILDB X,Y	;Check numericness
		CAIL X,"0"
		 CAILE X,"9"
		  JRST HSTLUZ
		PUSHJ P,SWINIR
		SKIPN B
		 SETZM (P)
		POP P,A		;A←host, B←IMP
		JUMPN X,HSTLUZ
		LSH A,=16
		ADDI A,(B)
		TLO A,(NW%ARP)	;Set network
		MOVE 0,A
		JRST GETNUM]
	CAIN X,"#"		;XEROX style number
	 JRST [	SKIPLE A
		CAILE A,377
		 JRST HSTLUZ
		PUSH P,A
		ILDB X,Y	;Check numericness
		CAIL X,"0"
		 CAILE X,"9"
		  JRST HSTLUZ
		PUSHJ P,SWINIR
		POP P,B		;B←subnet, A←host
		JUMPN X,HSTLUZ
		SKIPLE A
		CAILE A,377
		 JRST HSTLUZ
		LSH B,=8
		ADDI B,(A)
		TLO B,(NW%SU)	;Set network
		MOVE 0,B
		JRST GETNUM]
HSTLUZ:	OUTSTR [ASCIZ/Bad host number format
/]
	JRST PROMPT

;Here with an alphabetic host name.
ALPHST:	SETOM NOHOST#		;Indicate no host found so far
	MOVEI 0,HSTEXT

;  Set up various AC's for hairy search below.  0 has a pointer to the input
; host, 1 has the host table pointer, 2 has the character count.

	MOVE 1,HSTADR			; base host address
	MOVE 2,NAMPTR(1)
	ADD 2,HSTADR			; address of NAMES table
	HRLO 1,(2)			; # of entries,,-1
	EQVI 1,1(2)			; -<1+# of entries>,,table-1
	ADJSP 1,1			; now have AOJBN pointer to table
	MOVE 3,
	HRLI 3,440700			; make byte pointer
	SETZ 2,				; character count

; Compute character count in AC 2

CNTCHR:	ILDB 4,3
	JUMPE 4,[	SETZB 3,4	; init pointers
			JRST SEARCH]
	CAIL 4,"a"			; lowercase?
	 SUBI 4,"a"-"A"
	DPB 4,3
	AOJA 2,CNTCHR
;⊗ SEARCH SRCNXW SRCWIN OFFNAM NXTHST PRINT NAMLP NAMDUN MCHTYP ENDNIC

;Host name search

SEARCH:	JUMPE 2,SRCWIN
	SETOM PASS1#		;First pass of 2-pass search
	PUSH P,1		;Save for second pass
SRCH1:	MOVEI 5,(2)			; copy of count
	MOVE 6,0			; copy of source pointer
	HRRZ 7,(1)
	ADD 7,HSTADR			; pointer for this entry
SRCNXW:	MOVE 10,(7)
	MOVE 11,(6)
	ANDCMI 11,1			; 1.1 is a loser
	CAIL 5,=5			; account for this word
	 JRST [	CAME 10,11		; match for this word?
		 JRST NXTHST
		SUBI 5,=5		; match, account for this word
		ADDI 7,1
		AOJA 6,SRCNXW]		; still more to go
	AND 11,[BYTE (7)000,000,000,000,000
		BYTE (7)177,000,000,000,000
		BYTE (7)177,177,000,000,000
		BYTE (7)177,177,177,000,000
		BYTE (7)177,177,177,177,000](5)
	SETOM EXACT#
	CAMN 10,11			; exact match?
	 JRST SRCWIN			; stop the presses!
	SETZM EXACT
	SOJL 5,SRCWIN			; this string ends on word boundry
	AND 10,[BYTE (7)177,000,000,000,000
		BYTE (7)177,177,000,000,000
		BYTE (7)177,177,177,000,000
		BYTE (7)177,177,177,177,000](5)
	CAME 10,11			; match for partial word?
	 JRST NXTHST
SRCWIN:	HRRZ 5,NMRNAM(1)
	ADD 5,HSTADR
	HLRZ 7,NMLSIT(1)
	ADD 7,HSTADR
	HLRZ 6,STLNAM(7)
	ADD 6,HSTADR
	SKIPN PASS1
	 JRST SRCWI1		;Not pass 1, any match OK
	SKIPN EXACT		;Was it an exact match?
	CAIN 5,(6)		;Or is it an official name?
	CAIA			;Yes, then show in pass 1
	JRST NXTHST
SRCWI1:	MOVSI 10,1		;Pseudo-flag
	TDNE 10,STLFLG(7)	;Have we shown it already?
	 JRST NXTHST		;yes
	IORM 10,STLFLG(7)	;Set pseudo-flag when we show a site
	OUTSTR (5)
	CAIN 5,(6)
	 JRST OFFNAM		;Official name
	OUTSTR [ASCIZ/ is a nickname for /]
	OUTSTR (6)
	OUTSTR [ASCIZ/, which/]
OFFNAM:	PUSHJ P,PRINT
NXTHST:	AOBJN 1,SRCH1
	AOSN PASS1		;Skip unless finishing pass 1
	 JRST [	POP P,1		;Restore AOBJN pointer
		JRST SRCH1]	;Go do pass 2
	SKIPE NOHOST		;Did we print anything?
	 OUTSTR [ASCIZ/Unknown host name
/]
	JRST PROMPT

;Here to print information for a host.  Call with site table entry address in 7.

PRINT:	SETZM NOHOST		;We now have found a match
	OUTSTR [ASCIZ/ is number /]
	HRRZ 6,STRADR(7)
NAMLP:	ADD 6,HSTADR
	MOVE X,ADDADR(6)
	PUSHJ P,PRHNUM
	HRRZ 6,ADRCDR(6)
	JUMPE 6,NAMDUN
	OUTSTR [ASCIZ/, /]
	JRST NAMLP
NAMDUN:	OUTSTR [ASCIZ/,
a /]
	SKIPL STLFLG(7)
	 SKIPA 10,[[ASCIZ/user /]]
	  MOVEI 10,[ASCIZ/server /]
	OUTSTR (10)
	HRRZ 6,STRMCH(7)
	JUMPE 6,[	OUTSTR [ASCIZ/unknown/]
			JRST MCHTYP]
	ADD 6,HSTADR
	OUTSTR (6)
MCHTYP:	OUTSTR [ASCIZ/ machine running /]
	HLRZ 6,STLSYS(7)
	JUMPE 6,[	OUTSTR [ASCIZ/an unknown operating system.

/]
			POPJ P,]
	ADD 6,HSTADR
	OUTSTR (6)
ENDNIC:	OUTSTR [ASCIZ/.

/]
	POPJ P,
;⊗ MAPHST

; MAPHST -- Map host table into core
; Call:	PUSHJ 17,MAPHST
;	<return>
; Smashes 0, 1, 2, and 3.

↑MAPHST:OPEN 0,[17 ↔ 'DSK   ' ↔ 0]
	 JRST 4,.-1
	DMOVE 0,HSTFIL
	MOVE 3,HSTPPN
	LOOKUP 0,
	 JRST 4,.-1
	MOVE 2,JOBFF↑
	MOVS 0,3 ↔ MOVN 0,0 ↔ ADDB 0, JOBFF↑	; get address of highest addr we need
	MOVEM 0,HSTTOP
	CORE 0,				; get more core from system maybe
	 JRST 4.,-1
	MOVE 0,3 ↔ HRRI 0,-1(2)		; compute IOWD to read host table in
	SETZ 1,
	INPUT 0,
	MOVE 0,(2)			; get first word of host table
	CAME 0,HSTFIL
	 JRST 4,.-1
	MOVEM 2,HSTADR			; remember where host table begins
	RELEAS 0,
	POPJ 17,
;⊗ HSTNUM HSTNU0 HSTNUS HSTNU1 HSTNU2 HSTNU3 HSTNUD

; HSTNUM -- Return descriptor block for a host
; Call:	MOVEI <host number>
;	PUSHJ 17,HSTNUM
;	<error return--no such host>
;	<return--absolute NAMNUM in 0, NUMSYS,,NUMNAM in 1, NUMBTS,,NUMMCH in 2>
; Smashes 0, 1, 2, 3, and 4.

HSTNUM:	GETNET 4,0			; get network number
	SKIPN 4
	 TLO 0,(NW%ARP)			; if none given, assume ARPANet
	MOVE 1,HSTADR
	MOVE 1,NETPTR(1)
	PUSHJ 17,HSTNUS			; lookup network number
	  POPJ 17,
	MOVE 1,NTRTAB(1)		; get address table for network
	MOVEM 4				; thing to search for
	PUSHJ 17,HSTNUS			; lookup address
	  POPJ 17,
	HLRZ 7,ADLSIT(1)		; get site table entry
	ADD 7,HSTADR
	JRST CPOPJ1

HSTNUS:	ADD 1,HSTADR			; relocate table
	MOVE 2,(1)			; get # of entries
	MOVE 3,1(1)			; and entry size
	ADDI 1,2			; point at first entry
HSTNU1:	CAMN 4,(1)			; found it?
	  JRST CPOPJ1			;   yes, skip return for success
	ADD 1,3				; point at next entry
	SOJG 2,HSTNU1			; keep on searching
	POPJ P,				; failed
;⊗ SWINIR SWINR1 SWINR2 SWINIP CPOPJ1 CPOPJ SWINP1 PRHNUM PRHNIP PRDECP PRDEC PROCT PRLOOP PDL MONCMP HSTADR HSTTOP HSTEXT CRLF

;Some of these subroutines adapted from TELNET.MID[S,NET].

;  Super winning numeric input routine.  Numbers are parsed as both octal and
; decimal, unless either (a) an 8 or 9 appears in the number, or (b) the number
; is followed by a decimal point.

SWINIR:	SETZB A,B			; A ← octal number, B ← decimal
SWINR1:	CAIL X,"8"			; if can't be octal, A ← -1
	 SETO A,
	JUMPL A,SWINR2
	LSH A,3
	ADDI A,-"0"(X)			; bring in next octal digit
SWINR2:	IMULI B,=10
	ADDI B,-"0"(X)			; bring in next decimal digit
	ILDB X,Y
	CAIN X,"."			; decimal point ends spec and forces decimal
	 JRST [	SETO A,
		ILDB X,Y
		POPJ P,]
	CAIL X,"0"
	 CAILE X,"9"
	  POPJ P,			; non-numeric, return
	JRST SWINR1

;Super winning IP host number parser.  If an IP host number is seen, then it will
;be returned in B and SWINIP will skip return.  Otherwise, just like SWINIR.

SWINIP:	PUSHJ P,SWINIR		;Parse a number
	CAIL X,"0"		;Check the next character
	CAILE X,"9"
	POPJ P,			;Not a digit, so not an IP host number
	PUSH P,B		;Save 1st byte
	PUSHJ P,SWINP1		;Get rest of IP host number left-adj in B
	POP P,A			;Restore 1st byte
	LSHC A,-=12		;Right-adjust entire number in B
CPOPJ1:	AOS (P)			;Skip to show IP host number
CPOPJ:	POPJ P,

;Subroutine to return an IP host number left-adjusted in B.

SWINP1:	PUSHJ P,SWINIR		;Get a number
	PUSH P,B		;Save it
	CAIL X,"0"		;See if a digit follows
	CAILE X,"9"
	TDZA B,B		;No.  Zero B and skip
	PUSHJ P,SWINP1		;Yes, get rest of IP host in B
	POP P,A			;Get back current byte
	LSHC A,-=8		;Shift into rest of number
	POPJ P,

;Routine to print a host number, either in SU Ethernet or IP format.  Takes
;host number in X.
PRHNUM:	TLNE X,740000		;Non-Internet?
	 JRST PRHNIP		;Yes, print non-IP
	LDB A,[POINT 8,X,11]
	PUSHJ P,PRDEC		;Print first byte
	LDB A,[POINT 8,X,19]
	PUSHJ P,PRDECP		;Print period and second byte
	LDB A,[POINT 8,X,27]
	PUSHJ P,PRDECP		;Print period and third byte
	LDB A,[POINT 8,X,35]
	PUSHJ P,PRDECP		;Print period and fourth byte
	POPJ P,

PRHNIP:	HLRZ A,X		;Get left half of addr
	CAIE A,(NW%SU)		;SU-Net?
	 POPJ P,		;No, return quietly
	OUTSTR [ASCIZ/SU /]
	LDB A,[POINT 8,X,27]
	PUSHJ P,PROCT		;Print first byte
	OUTCHR ["#"]
	LDB A,[POINT 8,X,35]
	PUSHJ P,PROCT		;Print second byte
	POPJ P,

PRDECP:	OUTCHR ["."]
PRDEC:	SKIPA C,[=10]
PROCT:	MOVEI C,10
PRLOOP:	IDIV A,C
	PUSH P,B
	SKIPE A
	 PUSHJ P,PRLOOP
	POP P,A
	ADDI A,"0"
	OUTCHR A
	POPJ P,

PDL:	BLOCK PDLEN

MONCMP:	BLOCK 1				; -1 → got a monitor command

HSTADR:	BLOCK 1
HSTTOP:	BLOCK 1
HSTEXT:	BLOCK 25

CRLF:	BYTE (7)15,12
;Host table printer ;⊗ H TBL D hostab hostb1 htbunm netprt nhashs skpntp

BEGIN HOSTAB

;Formerly a separate program, this is run when you give a null argument to HOST.

	GLOBAL A,B,X,Y,P
H←←7				;AC containing host table address
TBL←←10				;Other ACs
D←←11

↑hostab:getppn a,
	came a,['100100']
	jrst hostb1
	outstr [asciz/Sorry, you must be logged in to print the whole host table.
/]
	exit

hostb1:	move h,hstadr
	outstr [asciz/Host table generated by /]
	skipn x,hstwho(h)	;get UNAME of creator
	 move x,['??????']	;null UNAME?
htbunm:	setz y,			;zap where character will go
	rotc x,6		;gobble a character
	addi y,40		;ASCIIify
	outchr y
	jumpn x,htbunm		;continue if more
	outstr [asciz/ on /]
	skipn x,hstdat(h)	;get compilation date
	 move x,['??????']	;null creation date?
	rot x,=12		;put year last
repeat 2,<
 repeat 2,<
	  setz y,		;zap character
	  rotc x,6		;gobble a character
	  addi y,40		;ASCIIify
	  outchr y
 >;repeat 2
	  outchr ["/"]
>;repeat 2
 repeat 2,<
	  setz y,		;zap character
	  rotc x,6		;gobble a character
	  addi y,40		;ASCIIify
	  outchr y
 >;repeat 2
	  outchr [" "]
	skipn x,hsttim(h)	;get compilation time
	 move x,['??????']	;null compilation time?
repeat 2,<
 repeat 2,<
	  setz y,		;zap character
	  rotc x,6		;gobble a character
	  addi y,40		;ASCIIify
	  outchr y
 >;repeat 2
	  outchr [":"]
>;repeat 2
 repeat 2,<
	  setz y,		;zap character
	  rotc x,6		;gobble a character
	  addi y,40		;ASCIIify
	  outchr y
 >;repeat 2
	outstr crlf

;Now, for each network print the name of the network
;and print a host map driven off its ADDRESS table.
	move a,netptr(h)
	addi a,(h)
	move b,(a)			;Number of networks
	movem b,netcnt#
	move b,1(a)			;Words per entry
	movem b,netsiz#
	addi a,2			;Address of first network
	movem a,netloc#
netprt:	sosge netcnt
	 exit				;No more networks
	outstr crlf
	hlrz x,ntlnam(a)
	addi x,(h)
	outstr (x)
	outstr [asciz/ Network:/]
	hrrz tbl,ntrtab(a)
	jumpn tbl,nhashs
	outstr [asciz/  no hosts/]
nhashs:	outstr crlf
	jumpe tbl,skpntp
	addi tbl,(h)
	pushj p,onenet
skpntp:	move a,netsiz
	addb a,netloc
	jrst netprt
;⊗ onenet foo3 hstprt hsterr outcnt outcn1 outcn2

;Print info for net whose ADDRESS table is pointed to by tbl

onenet:
repeat 0,<
	ldb b,[nw$byt,,2+addadr(tbl)]	; Get network number
	cain b,nw%dln			; Dialnet is strange
	 jrst [	type [Phone #		]
		jrst foo3]
>;repeat 0
	outstr [asciz/Host number	/]
foo3:	outstr [asciz/Official Name	Machine		System

/]
	skipge d,(tbl)		;load number of entries
	 jrst hsterr		;invalid number of entries?
	jumpe d,cpopj		;no hosts this net
	skipg 1(tbl)		;test number of words/entry
	 jrst hsterr		;invalid number of words?
	movei a,2(tbl)
;A has absolute address of next ADDRESS table entry to print
hstprt:	hlrz b,adlsit(a)	;Get SITE entry
	addi b,(h)		;Convert to absolute address
	movei x,"*"		;assume a server
	skipl stlflg(b)		;but is it really?
	 movei x," "		;nope, a user
	outchr x		;initial heading
	skipn x,addadr(a)	;get number of host
	 jrst hsterr		;funny host number?
	push p,a
	push p,b
	pushj p,prhnum		;print host number
	pop p,b
	pop p,a
	outchr [11]		;go to next field
	hlrz x,stlnam(b)	;get name of host
	jumpe x,hsterr		;null host pointer?
	addi x,(h)		;convert to absolute address
	pushj p,outcnt		;Output and count length of string
	caige x,=8		;more than one field length?
	 outchr [11]
	outchr [11]
	hrrz x,strmch(b)	;get machine host is
	jumpe x,[movei x,[asciz/UNKNOWN/] ;unknown name
		 jrst .+2]	;and continue
	addi x,(h)		;convert to absolute address
	pushj p,outcnt		;and output it
	caige x,=8		;more than one field length?
	 outchr [11]
	outchr [11]
	hlrz x,stlsys(b)	;get system host has
	jumpe x,[movei x,[asciz/UNKNOWN/] ;unknown system
		 jrst .+2]	;and continue
	addi x,(h)		;convert to absolute address
	outstr (x)		;and output it
	outstr crlf
	add a,1(tbl)		;go to next entry in the table
	sojg d,hstprt		;loop for next entry
	outstr [asciz/
* means this site is a server
/]
	popj p,			;Done this network

hsterr:	outstr [asciz/
Error in host table format.  Please report this via GRIPE NETWORK.
/]
	exit

;Here to print ASCIZ string whose address is in X, and return its
;length in X.
outcnt:	outstr (x)		;Print string
	hrli x,440700		;Make byte ptr
	push p,x
	movei x,0
outcn1:	ildb y,(p)		;Get a char
	jumpe y,outcn2		;Jump if all done
	aoja x,outcn1		;Else count and continue
outcn2:	adjsp p,-1		;Flush byte ptr on stack
	popj p,
	
BEND HOSTAB

	END START