Google
 

Trailing-Edge - PDP-10 Archives - bb-kl11m-bm - t20src/checkd.mac
There are 35 other files named checkd.mac in the archive. Click here to see a list.
; Edit= 39 to CHECKD.MAC on 10-Oct-88 by GSCOTT
;Ask if user wants structure dismounted if lost pages file not written, fix
;several confusing error messages, use TTMSG for dismounting structure message
;to prevent jumbling with monitor's TTMSG, output "undefined error n" if ERSTR
;gives +1 return.
; Edit= 38 to CHECKD.MAC on 12-May-88 by RASPUZZI
;If we crash with an illegal instruction, give the user the option to CONTINUE
;and have the structure currently being worked on dismounted.
; Edit= 37 to CHECKD.MAC on 5-May-88 by RASPUZZI
;Be more informative when the GTJFN% fails for a directory file.
; Edit= 36 to CHECKD.MAC on 25-Mar-88 by LOMARTIRE
;Bump edit number for 7.0 Autopatch 
; UPD ID= 49, RIP:<7.UTILITIES>CHECKD.MAC.4,  19-Feb-88 17:50:36 by GSCOTT
;TCO 7.1236 - edit 26, update copyright notice.
; UPD ID= 30, RIP:<7.UTILITIES>CHECKD.MAC.3,  14-Dec-87 09:15:35 by BROOKS
;Increment version number for 7.0 ft1
; UPD ID= 23, RIP:<7.UTILITIES>CHECKD.MAC.2,   4-Nov-87 15:47:22 by MCCOLLUM
;TCO 7.1112 - Add ENABLE/DISABLE/SHOW LOGIN STRUCTURE commands.
; *** Edit 4 to CHECKD.MAC by RASPUZZI on 7-Jan-87, for SPR #21493
; Increase the amount of lost pages that CHECKD can handle from 1/3 of an RP06
; to about 1/3 of an RA81
; *** Edit 3 to CHECKD.MAC by MCCOLLUM on 18-Nov-86
; Print last directory seen if RCDIR fails in NXTDIR
; *** Edit 2 to CHECKD.MAC by GRANT on 26-Mar-86
; Allow multiple CHECKDs to simultaneously mount structures 
; UPD ID= 120, SNARK:<6.1.UTILITIES>CHECKD.MAC.64,   1-May-85 16:45:08 by LEACHE
;MORE OF PREVIOUS
; UPD ID= 114, SNARK:<6.1.UTILITIES>CHECKD.MAC.63,  14-Apr-85 15:59:33 by LEACHE
;TCO 6.1.1321 Add ENABLE BOOT-PARAMETERS
; UPD ID= 92, SNARK:<6.1.UTILITIES>CHECKD.MAC.62,   6-Mar-85 10:10:26 by HAUDEL
;TCO 6.1.1235 - Use Sixbit DONOCA for the DON'T CARE option.
; UPD ID= 78, SNARK:<6.1.UTILITIES>CHECKD.MAC.61,  13-Feb-85 15:33:10 by HAUDEL
;TCO 6.1.1199 - Remove the SET DRIVE SERIAL NUMBER command.
; UPD ID= 70, SNARK:<6.1.UTILITIES>CHECKD.MAC.60,  24-Jan-85 09:27:22 by HAUDEL
;TCO 6.1.1135 - Change an error message.
; UPD ID= 60, SNARK:<6.1.UTILITIES>CHECKD.MAC.59,  18-Dec-84 13:58:34 by TBOYLE
;TCO 6.1.1094 - Fix DISABLE AUTOMATIC-STARTUP At .AUTOS+6.
; UPD ID= 54, SNARK:<6.1.UTILITIES>CHECKD.MAC.58,   4-Dec-84 09:33:49 by TBOYLE
;TCO 6.1.1069 (QAR 706325) Put a space between filename and "is new" &vers 6.1
; UPD ID= 625, SNARK:<6.UTILITIES>CHECKD.MAC.57,  31-Oct-84 15:29:03 by TBOYLE
;More TCO 6.2116 - Ask for decimal serial number 
; UPD ID= 603, SNARK:<6.UTILITIES>CHECKD.MAC.56,   7-Oct-84 04:51:26 by TBOYLE
;More TCO 6.2116 - RP20 serial number by channel/kontroller/unit number.
; UPD ID= 602, SNARK:<6.UTILITIES>CHECKD.MAC.55,   6-Oct-84 02:33:06 by TBOYLE
;TCO 6.2237 (QAR 706247) Use SECPAG for BAT pairs. Also fix unit bit mask.
; UPD ID= 595, SNARK:<6.UTILITIES>CHECKD.MAC.54,  17-Sep-84 14:32:26 by PURRETTA
;Up edit level for previous edit.
; UPD ID= 590, SNARK:<6.UTILITIES>CHECKD.MAC.53,  10-Sep-84 14:04:09 by TBOYLE
;Use true sector size 1000 when writing RP20 serial number.
; UPD ID= 558, SNARK:<6.UTILITIES>CHECKD.MAC.52,   2-Jul-84 15:42:28 by TBOYLE
;Channel/Controller/Unit number on input and output now in decimal.
; UPD ID= 557, SNARK:<6.UTILITIES>CHECKD.MAC.51,   2-Jul-84 14:38:40 by TBOYLE
;TCO 6.2115 and 6.2116 - don't care disks and RP20 serial numbers.
; UPD ID= 551, SNARK:<6.UTILITIES>CHECKD.MAC.50,  18-Jun-84 17:04:12 by TBOYLE
;Fix a bug in 6.2067... At BATWRT use TRECPP/SECPAG to normalize
; UPD ID= 549, SNARK:<6.UTILITIES>CHECKD.MAC.49,  12-Jun-84 15:53:51 by TBOYLE
;TCO 6.2067 - Use DOP%PS at BATWRT, HOMIN, and BATIN.
; UPD ID= 402, SNARK:<6.UTILITIES>CHECKD.MAC.48,  14-Dec-83 11:38:34 by TSANG
;TCO 6.1871 Allow wildcard for input filespec.
; UPD ID= 400, SNARK:<6.UTILITIES>CHECKD.MAC.47,  13-Dec-83 16:14:26 by TBOYLE
;More TCO 6.1903 Changed to use TRANSL in HOMEIN, PSCHK, START0..
; UPD ID= 398, SNARK:<6.UTILITIES>CHECKD.MAC.46,  12-Dec-83 14:14:55 by TBOYLE
;TCO 6.1903 and 6.1905 Use real PS: name, and put in DOBE's and <returns>
; UPD ID= 396, SNARK:<6.UTILITIES>CHECKD.MAC.45,   7-Dec-83 14:58:31 by TBOYLE
;TCO 6.1898 Make VERIFY command use GTASTS and fix GETCK2. (5.1 ed. 54)
; UPD ID= 395, SNARK:<6.UTILITIES>CHECKD.MAC.44,   7-Dec-83 13:00:43 by TBOYLE
;TCO 6.1897 Make .BATEX update BAT BLOCKS after VERIFY. (5.1 ed. 76) Now ed. 46
; UPD ID= 394, SNARK:<6.UTILITIES>CHECKD.MAC.43,   6-Dec-83 17:26:10 by TBOYLE
;TCO 6.1895 Fix wrong serial # being loaded in HOM on ENA AUTO. (5.1 ed. 74)
; UPD ID= 393, SNARK:<6.UTILITIES>CHECKD.MAC.42,   6-Dec-83 16:30:36 by TBOYLE
;TCO 6.1894 Allow 14 chars on owner id for created structure. (5.1 Edit 31)
; UPD ID= 392, SNARK:<6.UTILITIES>CHECKD.MAC.41,   6-Dec-83 16:21:10 by TBOYLE
;TCO 6.1893 Be paranoid about directory names (5.1 Edit 32)
; UPD ID= 390, SNARK:<6.UTILITIES>CHECKD.MAC.40,   5-Dec-83 17:07:33 by TBOYLE
;TCO 6.1890 Move new SEEADR routine to development sources.
; UPD ID= 389, SNARK:<6.UTILITIES>CHECKD.MAC.39,   5-Dec-83 13:52:52 by TBOYLE
;More TCO 6.1869 use new MSTR to pick up LPPCYL of TCO 6.1876
; UPD ID= 376, SNARK:<6.UTILITIES>CHECKD.MAC.38,  21-Nov-83 17:43:21 by TBOYLE
;Fix last edit. Make GTASTS different from GTUSTS.
;TCO 6.1869 - Make CHECKD use MSTR% to obtain disk drive info.
; UPD ID= 344, SNARK:<6.UTILITIES>CHECKD.MAC.35,  17-Aug-83 10:06:14 by WEETON
;TCO 6.1776 - Fix arguments to DSKTAB for RA81s.
; UPD ID= 340, SNARK:<6.UTILITIES>CHECKD.MAC.34,   8-Aug-83 09:49:41 by WEETON
;TCO 6.1759 - Increase space for code in CHECKD.
; UPD ID= 336, SNARK:<6.UTILITIES>CHECKD.MAC.33,   2-Aug-83 15:53:02 by WEETON
;Make edit number ^D37
; UPD ID= 335, SNARK:<6.UTILITIES>CHECKD.MAC.32,   2-Aug-83 15:06:40 by WEETON
;TCO 6.1613 - Incorporate D1%INI function of DSKAS JSYS.
; UPD ID= 334, SNARK:<6.UTILITIES>CHECKD.MAC.31,   2-Aug-83 14:18:11 by WEETON
;TCO 6.1590 and 6.1591 - Wait for confirmation before adding APR serial number
;on new structure
; UPD ID= 333, SNARK:<6.UTILITIES>CHECKD.MAC.30,   2-Aug-83 14:06:55 by WEETON
;TCO 6.1582 - Make ADD command include APR serial number, and drive/con/kon no.
; UPD ID= 332, SNARK:<6.UTILITIES>CHECKD.MAC.29,   2-Aug-83 13:55:52 by WEETON
;TCO 6.1584 - Don't trash Multipack structure BAT blocks (supercedes TCO 6.1574
;; and TCO 6.1575)
; UPD ID= 331, SNARK:<6.UTILITIES>CHECKD.MAC.28,   2-Aug-83 13:45:42 by WEETON
;TCO 6.1573 - Can't add pages greater than largest already in BAT BLOCK
; UPD ID= 330, SNARK:<6.UTILITIES>CHECKD.MAC.27,   2-Aug-83 13:43:01 by WEETON
;TCO 6.1572 - Make Edit number decimal
; UPD ID= 327, SNARK:<6.UTILITIES>CHECKD.MAC.26,  28-Jul-83 11:33:42 by WEETON
;TCO 6.1738 - Report correct disk address on multiply assigned page
; UPD ID= 319, SNARK:<6.UTILITIES>CHECKD.MAC.25,  18-Jul-83 14:08:22 by WEETON
;TCO 6.1735 - Make RAxx disk types page mode.
; UPD ID= 239, SNARK:<6.UTILITIES>CHECKD.MAC.24,  23-Mar-83 14:24:34 by WEETON
;Yet more of TCO 6.1547 - Always run in section 1 and make PNTFIL read from
; section 2
; UPD ID= 237, SNARK:<6.UTILITIES>CHECKD.MAC.23,  21-Mar-83 08:59:55 by WEETON
;TCO 6.1548 - Increase lost pages buffer back to V5 size.
; UPD ID= 236, SNARK:<6.UTILITIES>CHECKD.MAC.22,  20-Mar-83 11:50:44 by WEETON
;More of TCO 6.1547 - Make XSIR% work right.
; UPD ID= 235, SNARK:<6.UTILITIES>CHECKD.MAC.21,  18-Mar-83 18:20:08 by WEETON
; UPD ID= 234, SNARK:<6.UTILITIES>CHECKD.MAC.20,  18-Mar-83 17:09:14 by WEETON
;TCO 6.1556 - If disk address is too big when deassigning page, quit.
; UPD ID= 233, SNARK:<6.UTILITIES>CHECKD.MAC.19,  18-Mar-83 16:33:46 by WEETON
;TCO 6.1553 - Write names of "new" files.
; UPD ID= 232, SNARK:<6.UTILITIES>CHECKD.MAC.18,  18-Mar-83 16:16:05 by WEETON
;TCO 6.1555 - Don' allow system to come up under some conditions.
; UPD ID= 231, SNARK:<6.UTILITIES>CHECKD.MAC.17,  18-Mar-83 16:09:42 by WEETON
;TCO 6.1552 - Check for invisible and deleted files when FIXCNTing of pages
; UPD ID= 230, SNARK:<6.UTILITIES>CHECKD.MAC.16,  18-Mar-83 15:58:17 by WEETON
;TCO 6.1550 - Notify users when CHECKD is going to run at system startup
; UPD ID= 225, SNARK:<6.UTILITIES>CHECKD.MAC.15,  15-Mar-83 14:52:42 by COBB
;TCO 6.1545 - Change major/minor version numbers
; UPD ID= 224, SNARK:<6.UTILITIES>CHECKD.MAC.14,  15-Mar-83 13:58:59 by COBB
;More TCO 6.1496 - Use T1, not T2 in HOMEIN:
; UPD ID= 203, SNARK:<6.UTILITIES>CHECKD.MAC.13,   4-Feb-83 05:10:56 by WACHS
;TCO 6.1496 - Add def'ns for RA80, RA81, RA60. Alllow controller 0 - 17
; UPD ID= 170, SNARK:<6.UTILITIES>CHECKD.MAC.12,  17-Nov-82 13:20:41 by LEACHE
;More TCO 6.1247
; UPD ID= 168, SNARK:<6.UTILITIES>CHECKD.MAC.11,  15-Nov-82 10:00:32 by DONAHUE
;TCO 6.1356 - Put ERJMP after first instruction that references FDB
; UPD ID= 163, SNARK:<6.UTILITIES>CHECKD.MAC.10,  26-Oct-82 13:44:25 by WEETON
;TCO 6.1329 - Check for old LOST-PAGES.BIN
; UPD ID= 162, SNARK:<6.UTILITIES>CHECKD.MAC.9,  26-Oct-82 09:37:31 by WEETON
;TCO 6.1328 - Don't default structure names
; UPD ID= 161, SNARK:<6.UTILITIES>CHECKD.MAC.8,  14-Oct-82 11:08:34 by WEETON
;TCO 6.1304 - After unsuccessful dismount of structure,return to CHECKD> prompt
; UPD ID= 160, SNARK:<6.UTILITIES>CHECKD.MAC.7,  14-Oct-82 11:05:17 by WEETON
;TCO 6.1303 - Read various definations from PROLOG
; UPD ID= 159, SNARK:<6.UTILITIES>CHECKD.MAC.6,  14-Oct-82 10:45:53 by WEETON
; UPD ID= 158, SNARK:<6.UTILITIES>CHECKD.MAC.5,  14-Oct-82 10:41:44 by WEETON
; UPD ID= 157, SNARK:<6.UTILITIES>CHECKD.MAC.4,  14-Oct-82 10:36:37 by WEETON
;TCO 6.1301 - Increase size of directory buffer to match larger directories
; UPD ID= 125, SNARK:<6.UTILITIES>CHECKD.MAC.3,   3-Sep-82 11:06:32 by LEACHE
;TCO 6.1247 Add ENABLE PASSWORD ENCRYPTION
; UPD ID= 120, SNARK:<6.UTILITIES>CHECKD.MAC.2,  19-Aug-82 15:24:35 by LEACHE
;TCO 6.1231 - Protect against user files with extension .DIRECTORY
; UPD ID= 84, SNARK:<5.UTILITIES>CHECKD.MAC.13,  24-Feb-82 14:36:12 by PAETZOLD
;TCO 5.1736 - Correct sense of PAGNN and MR%DIR tests in MRKBTB
; UPD ID= 80, SNARK:<5.UTILITIES>CHECKD.MAC.12,  18-Feb-82 17:56:35 by MURPHY
;TCO 5.1732 - Construct numeric string for default number pages in COMND call.
; UPD ID= 78, SNARK:<5.UTILITIES>CHECKD.MAC.11,   1-Feb-82 16:45:42 by PAETZOLD
;TCO 5.1713 - Use ^V's on characters of file name and type in FIXCNT
; UPD ID= 60, SNARK:<5.UTILITIES>CHECKD.MAC.10,  24-Nov-81 10:56:41 by DONAHUE
;TCO 5.1573 - Don't charge directory pages to superior
; UPD ID= 30, SNARK:<5.UTILITIES>CHECKD.MAC.9,   9-Sep-81 15:58:07 by DONAHUE
;TCO 5.1495 - Rewrite Bat block logic to account for lost pages
; UPD ID= 12, SNARK:<5.UTILITIES>CHECKD.MAC.8,  28-Jul-81 15:05:48 by LYONS
; fix some bugs in the last edits
; UPD ID= 11, SNARK:<5.UTILITIES>CHECKD.MAC.7,  27-Jul-81 14:31:13 by LYONS
;TCO 5.1297 - Add error return for SCANDI in QDONE
;ADD MORE OF THE VERIFY CODE (AGAIN) AND TCO 5.1280
; UPD ID= 1543, SNARK:<5.UTILITIES>CHECKD.MAC.5,   9-Feb-81 13:39:51 by LYONS
;ADD MORE OF THE VERIFY CODE
; UPD ID= 992, SNARK:<5.UTILITIES>CHECKD.MAC.4,   5-Sep-80 16:54:05 by LYONS
;GENERAL CLEANUP, ADD SOME CODE TO .VERIFY
; UPD ID= 750, SNARK:<5.UTILITIES>CHECKD.MAC.3,  10-Jul-80 20:42:34 by LYONS
;ADD WRITE VERIFICATION CONTROLS FOR SYSTEM
;ADD ENABLE AND DISABLE COMMANDS
;PUT CPU SERIAL NUMBER INTO HOME BLOCK FOR STRUCTURES WHICH BOOT SYSTEM
; UPD ID= 376, SNARK:<4.1.UTILITIES>CHECKD.MAC.2,  26-Mar-80 14:13:47 by DBELL
;TCO 4.1.1124 - ADD RP20 SUPPORT
;<4.UTILITIES>CHECKD.MAC.29, 11-Oct-79 15:24:06, EDIT BY GRADY
;<4.UTILITIES>CHECKD.MAC.28, 11-Oct-79 14:57:55, EDIT BY GRADY
;TCO 4.2496 - DELETE ALL GENERATIONS OF THE LOST PAGES FILE IN RLSPG2
;<4.UTILITIES>CHECKD.MAC.27,  8-Aug-79 11:33:07, EDIT BY GRANT
;TCO 4.2379 - CHANGE LF TO CRLF TO CLEAN UP SOME OUTPUT FORMATS
;<4.UTILITIES>CHECKD.MAC.26, 17-Apr-79 16:28:55, EDIT BY DBELL
;TCO 4.2232 - AT NXTPR ROUND DOWN BAT BLOCK ENTRIES TO PAGE BOUNDARIES
; SO THAT 3/4 OF THE PAGES WITH A BAD SECTOR WILL NOT BE MISSED.
;<4.UTILITIES>CHECKD.MAC.25, 10-Mar-79 13:39:25, EDIT BY KONEN
;UPDATE COPYRIGHT FOR RELEASE 4
;<4.UTILITIES>CHECKD.MAC.24,  8-Mar-79 13:25:35, EDIT BY R.ACE
;TAKE OUT TAPE-INIT FUNCTIONS
;<4.UTILITIES>CHECKD.MAC.23, 19-Feb-79 11:54:59, Edit by KONEN
;INCREMENT MOUNT COUNT AFTER MOUNTING A STRUCTURE
;<4.UTILITIES>CHECKD.MAC.22, 12-Feb-79 13:12:50, EDIT BY R.ACE
;CHANGE CKMNT TO ACCOMMODATE NEW GALAXY TEXT MESSAGE FORMAT
;<4.UTILITIES>CHECKD.MAC.21, 10-Jan-79 10:32:00, EDIT BY R.ACE
;RELEASE PID IN QUIT CODE
;<4.UTILITIES>CHECKD.MAC.20, 12-Dec-78 10:48:23, EDIT BY DBELL
;TCO 4.2119 - FIX BUG IN RELEASING MORE THAN 12K LOST PAGES
;<4.UTILITIES>CHECKD.MAC.19,  8-Dec-78 14:39:41, EDIT BY DBELL
;TCO 4.2115 - MOVE LOCATION HFLAGS TO PREVENT BAT LOGIC ERRORS
;<4.UTILITIES>CHECKD.MAC.18,  8-Dec-78 11:10:21, EDIT BY DBELL
;TCO 4.2114 - FIX BAT LOGIC AT NXTPR TO USE FULL 27 BIT ADDRESSES
;<4.UTILITIES>CHECKD.MAC.17, 27-Nov-78 10:31:31, Edit by LCAMPBELL
; Add QUIT as a synonym for EXIT
;<4.UTILITIES>CHECKD.MAC.16, 12-Nov-78 13:53:58, EDIT BY R.ACE
;CHANGE VOLID PARSING TO USE ^V INSTEAD OF QUOTED STRINGS
;<4.UTILITIES>CHECKD.MAC.15,  6-Nov-78 07:47:29, EDIT BY R.ACE
;TCO 4.2079 - ADD TAPE-INITIALIZATION FUNCTIONS
;PERFORM GENERAL CLEAN-UP
;<4.UTILITIES>CHECKD.MAC.14, 31-Aug-78 17:16:39, Edit by MCLEAN
;MAKE CYLUN2 HAVE 558 CYLINDERS PER UNIT FOR DIAGNOSTICS
;<4.UTILITIES>CHECKD.MAC.13, 24-Jul-78 07:38:08, EDIT BY MILLER
;CHANGE DEFINITION OF DSKMSK TO INCLUDE DSKNB
;<4.UTILITIES>CHECKD.MAC.12, 19-Jun-78 13:27:15, Edit by MCLEAN
;<1MCLEAN>CHECKD.MAC.6,  6-May-78 23:39:32, Edit by MCLEAN
;ADD RP07

;	COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1976, 1988.
;	ALL RIGHTS RESERVED.
;
;	THIS SOFTWARE IS FURNISHED UNDER A  LICENSE AND MAY BE USED AND  COPIED
;	ONLY IN  ACCORDANCE  WITH  THE  TERMS OF  SUCH  LICENSE  AND  WITH  THE
;	INCLUSION OF THE ABOVE  COPYRIGHT NOTICE.  THIS  SOFTWARE OR ANY  OTHER
;	COPIES THEREOF MAY NOT BE PROVIDED  OR OTHERWISE MADE AVAILABLE TO  ANY
;	OTHER PERSON.  NO  TITLE TO  AND OWNERSHIP  OF THE  SOFTWARE IS  HEREBY
;	TRANSFERRED.
;
;	THE INFORMATION IN THIS  SOFTWARE IS SUBJECT  TO CHANGE WITHOUT  NOTICE
;	AND SHOULD  NOT  BE CONSTRUED  AS  A COMMITMENT  BY  DIGITAL  EQUIPMENT
;	CORPORATION.
;
;	DIGITAL ASSUMES NO  RESPONSIBILITY FOR  THE USE OR  RELIABILITY OF  ITS
;	SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY DIGITAL.
	TITLE CHECKD	CHECK/RECONSTRUCT CONSISTENCY OF FILE STRUCTURE
	SEARCH MONSYM,MACSYM,PROLOG
	.CPYRT <<1976, 1988>>

	.REQUIRE SYS:MACREL
	EXTERN .JBSA		;LH/ FIRST FREE LOC IN CHECKD
	SALL
	.DIRECTIVE FLBLST

;ENTRY VECTOR

PRGCST==0			;CUSTOMER ID
PRGVER==7			;[7.1112]VERSION NUMBER
PRGMIN==0			;[7.1112]MINOR VERSION
PRGEDT==^D39			;Edit number

ENTVEC:	JRST START		;MAIN START
	JRST START		;REENTER
	BYTE (3)PRGCST (9)PRGVER (6)PRGMIN (18)PRGEDT+VI%DEC
	JRST REBST		;REBUILD THE BIT TABLE


;CHECKD OPERATES ACCORDING TO HOW IT WAS CALLED:
;
;1. CALLED BY MONITOR JOB 0 (AT SYSTEM STARTUP - MEXEC MODULE)
;	ENTRY VECTOR LOCATION 0 - CHECK PS: FILE CONSISTENCY
;	ENTRY VECTOR LOCATION 3 - INITIALIZE PS: BITTABLE
;
;2. RUN BY ENABLED WHEEL OR OPERATOR
;	ENTRY VECTOR LOCATIONS 0 AND 1 - ACCEPT COMMANDS FROM TTY
	Subttl	Table of Contents

;		     Table of Contents for CHECKD
;
;				  Section		      Page
;
;
;    1. Definitions  . . . . . . . . . . . . . . . . . . . . .   4
;    2. Initialization . . . . . . . . . . . . . . . . . . . .  25
;    3. Job 0 Startup  . . . . . . . . . . . . . . . . . . . .  31
;    4. Utility Routines . . . . . . . . . . . . . . . . . . .  32
;    5. Structure Utility Routines . . . . . . . . . . . . . .  33
;    6. Create Command . . . . . . . . . . . . . . . . . . . .  54
;    7. Check Command  . . . . . . . . . . . . . . . . . . . .  63
;    8. Edit Command . . . . . . . . . . . . . . . . . . . . .  66
;    9. Enable/Disable Commands  . . . . . . . . . . . . . . .  67
;   10. Exit Command . . . . . . . . . . . . . . . . . . . . .  79
;   11. File-DDT Command . . . . . . . . . . . . . . . . . . .  80
;   12. Push Command . . . . . . . . . . . . . . . . . . . . .  82
;   13. Help Command . . . . . . . . . . . . . . . . . . . . .  83
;   14. Rebuild Command  . . . . . . . . . . . . . . . . . . .  84
;   15. Reconstruct Command  . . . . . . . . . . . . . . . . .  85
;   16. Release Command  . . . . . . . . . . . . . . . . . . .  88
;   17. Scan Command . . . . . . . . . . . . . . . . . . . . .  91
;   18. Show Command . . . . . . . . . . . . . . . . . . . . .  94
;   19. Verify Command . . . . . . . . . . . . . . . . . . . .  99
;   20. BAT Block Editor . . . . . . . . . . . . . . . . . . . 104
;   21. Directory Scan Code  . . . . . . . . . . . . . . . . . 132
;   22. Interrupt System
;       22.1    Control-A Interrupt  . . . . . . . . . . . . . 184
;       22.2    Unexpected Interrupt . . . . . . . . . . . . . 187
;       22.3    Control-C Interrupt  . . . . . . . . . . . . . 188
;       22.4    Panic Interrupt  . . . . . . . . . . . . . . . 189
;   23. End of CHECKD  . . . . . . . . . . . . . . . . . . . . 190
	SUBTTL Definitions

; AC'S

F=0
T1=1
T2=2
T3=3
T4=4
Q1=5
Q2=6
Q3=7
P1=10
P2=11
P3=12
S1=13
S2=14
S3=15
CX=16
P=17

;MISCELLANEOUS DEFINITIONS

NWSEC==200			;WORDS/SECTOR ON THE DISK
PGSIZ==1000			;PAGE SIZE
PGSFT==11			;SHIFT FOR CONVERTING ADDRESS TO PAGE
SUMBYT==.TICCA			;SUMMARY BYTE DURING SCANS
;SIZE OF BIT TABLE FILE IF WRITTEN BY PRE-RELEASE-2 MONITOR

OLDTOP=3100			;SIZE OF TOP HALF OF BIT TABLE
OLDBOT=11300			;SIZE OF BOTTOM HALF OF BIT TABLE

DEFP4S==^D10000			;DEFAULT PAGES FOR SWAPPING
DEFPFS==^D950			;DEFAULT PAGES FOR FRONT END

; Macro to change what section we are currently running in.
; Calling sequence
; SEC	SECNUM,ADDR
;  Where SECNUM is the section number
;  And   ADDR   is the address in the section
;   Defaults:
;	SECNUM = 0
;	ADDR   = PC + 1 (in new section)
DEFINE SEC(SECNUM<0>,ADDR<.+1>),<
	XJRSTF	[0
		SECNUM,,ADDR]
>

;MACRO TO CONVERT SYMBOL TO NUMBER IN STRING
;(SHOULD BE IN MACSYM NOW)

DEFINE FORS. (NUM,ARGS,STRING,%MN1)<
   DEFINE %MN1(ARGS)<STRING>
	..FORN==NUM
	.FORN1(%MN1)>
;INFORMATION ABOUT THE STRUCTURE BEING WORKED ON

BTBTOP:	BLOCK 1			;SIZE OF TOP HALF OF BIT TABLE
BTBBOT:	BLOCK 1			;SIZE OF BOTTOM HALF OF BIT TABLE
BTBPGS:	BLOCK 1			;NUMBER OF PAGES IN BIT TABLE
NSSUN:	BLOCK 1			;NUMBER OF SECTORS IN SWAPPING SPACE
FSSUN:	BLOCK 1			;FIRST SECTOR IN SWAPPING SPACE
NPACKS:	BLOCK 1			;NUMBER OF PACKS IN STRUCTURE
HITRK:	BLOCK 1			;LAST CYLINDER IN STRUCTURE
LOTRK:	BLOCK 1			;FIRST CYLINDER IN STRUCTURE

;INFORMATION ABOUT THE SIZE OF THE STRUCTURE BASED ON THE TYPE OF DISK
;THIS BLOCK IS FILLED IN BY A BLT FROM OTHER TABLES, SO DO NOT CHANGE
;THE ORDER OF THESE WORDS.

SECPAG:	BLOCK 1			;SECTORS PER PAGE
SECCYL:	BLOCK 1			;SECTORS PER CYLINDER
PAGCYL:	BLOCK 1			;PAGES PER CYLINDER
CYLUNT:	BLOCK 1			;CYLINDERS PER UNIT
SECUNT:	BLOCK 1			;SECTORS PER UNIT
BTWCYL:	BLOCK 1			;BIT WORDS IN BIT TABLE PER CYLINDER
LPPCYL:	BLOCK 1			;LOST SECTORS PER CYL
TRECPP: BLOCK 1			;TRUE SECTORS PER PAGE
TRCUNT: BLOCK 1			;TRUE SECTORS PER UNIT

; THE ORDER OF THE FOLLOWING WORDS ARE NOT CRITICAL

DRRST:	BLOCK 1			;RETURNED SOFTWARE STATUS
;HOME BLOCKS.  EACH NUMBER IS A SECTOR NUMBER RELATIVE TO THE START
;OF A UNIT.  EVERY UNIT IN A STRUCTURE HAS THESE BLOCKS ASSIGNED.

HOME::	0			;BOOT STRAP FOR THE 11
	1			;HOME BLOCK
	2			;BAT BLOCK
	3			;RESERVED
	4			;RESERVED
	5			;RESERVED
	6			;RESERVED
	7			;RESERVED
	10			;RESERVED
	11			;RESERVED
	12			;SECONDARY HOME BLOCK
	13			;SECONDARY BAT BLOCK
NHOME==:.-HOME
;ERROR BITS RETURNED FROM DSKASA

ER%IDA==1B0			;ILLEGAL DISK ADDRESS
ER%MDA==1B1			;MULTIPLY ASSIGNED DISK ADDRESS
ER%BAT==1B2			;BAD ADDRESS MARKED IN BAT BLOCKS

;FLAG BITS FOR MRKBTB TO KNOW WHAT KIND OF ADDRESS IT HAS

MR%PT==1B0			;PAGE TABLE
MR%PTT==1B1			;PAGE TABLE TABLE
MR%SWP==1B2			;SWAPPING SPACE
MR%SPC==1B3			;HOME BLOCKS, BAT BLOCKS, ETC.
MR%DIR==1B4			;THIS IS A DIRECTORY

;MISCELLANEOUS BITS

FILNB==1B3			;NEW FILE BIT
DSKMSK==-1B15			;MASK TO SELECT ONLY DISK ADDRESS FIELD
ADRMSK==-1B13			;MASK FOR COMPLETE STORAGE ADDRESS
ADDERS==<-ADRMSK>-1		;MASK OF THE ADDRESS BITS
;BAT BLOCK DEFINITIONS

;THE BAT BLOCK IS ONE SECTOR IN LENGTH.  IT CONSISTS OF 4 WORDS OF
;HEADER, FOLLOWED BY DATA, TWO WORDS PER ENTRY, INDICATING WHERE THE
;BAD SPOTS ON THE DISK ARE.  WORD ^D126 CONTAINS A SPECIAL CODE, AND
;WORD ^D127 CONTAINS THE SECTOR NUMBER OF THE BAT BLOCK

MAXBFR==172			;MAX FREE SPACE IN A BAT BLOCK
MAXPAR==MAXBFR/2		;MAX PAIRS IN A BAT BLOCK
MNPAKS==4			;MAXIMUM NO. OF PACKS IN A STRUCTURE
MAXPR==MAXBFR*MNPAKS		;SIZE OF BAT PAIR ARRAY
BPRBLK:	BLOCK MAXPR*2+1		;BAT PAIRS PLUS THE ORIGINAL WORDS
BATBUF:	BLOCK 200		;BUFFER FOR BAT BLOCK

BATBL1==2			;SECTOR NO. OF FIRST BAT BLOCK
BATBL2==13			;SECTOR NO. OF SECOND BAT BLOCK

;DATA PAIRS

DEFSTR BTUNM,0,17,8		;BIT MASK FOR UNIT 1B17=0,1B16=1,1B15=2..


;SPECIAL WORDS AT END OF BAT BLOCK

CODE=606060			;THE CODE

BT%FND==1B1			;FLAG INDICATES BAT BLOCK PAIR KNOWN, BUT NOT
				;RECORDED IN THE BAT BLOCKS
BT%MAP==1B2			;BAT ENTRY MADE BY MAPPER
BT%WBM==1B3			; WRITTEN BY MONITOR
BT%ANG==1B4			;ANYONE'S GUESS WHY THIS WAS ADDED
;LOCATIONS WHERE THINGS ARE MAPPED

;0 - 40000 ARE RESERVED FOR THE PROGRAM

FSTPAG==40000			;FIRST PAGE USED FOR STORAGE

; USED BY CREATE TO BUILD HELP TEXT FOR AVAILABLE UNITS

HBUF=FSTPAG			;HELP BUFFER
NHBUFP==2			;LENGTH OF HELP BUFFER

; USED BY SCAN, CHECK, REBUILD, AND RECONSTRUCT

;******  PT, PTT AND HBUF ALL OVERLAP ******

PT=HBUF				;WHERE TO MAP THE PAGE TABLE
PTT=PT+1000			;WHERE TO MAP THE PAGE TABLE TABLE

; USED BY CHECK

LOSBUF=PTT+1000			;WHERE TO SAVE LOST PAGES
MAXLOS==405000			;[04] NUMBER OF LOST PAGES THAT CAN BE ACCOUNTED FOR

; USED BY SCAN, CHECK, RECONSTRUCT, REBUILD, AND VERIFY
	; VERIFY USES SYSBTB TO KEEP THE BAT PAIRS FROM ITS
	; OWN SCAN OF THE DISK.

SYSBTB=LOSBUF+MAXLOS		;PLACE TO MAP THE BIT TABLE
BTBMAX==100000			;MAX SIZE OF THE BIT TABLE

; USED BY SCAN, CHECK, REBUILD, AND RECONSTRUCT

LOCBTB=SYSBTB+BTBMAX		;LOCAL COPY OF THE BIT TABLE

	; VERIFY USES DIRORG AS A SCRATCH AREA TO READ THE DISK INTO

DIRORG=2M			;START OF MAP AREA FOR DIRECTORY,Section 2
NDIRPG==DRMXSZ			;MAX SIZE OF DIR IN PAGES

LSTPPG==LOCBTB+BTBMAX		;END OF PAGE AREA

IF2,<IFL <770000-LSTPPG>,<PRINTX MAPPED PAGE AREA OVERLAPS DDT AREA>>
;JFN'S

BTBJFN:	BLOCK 1			;JFN FOR BIT TABLE FILE
INJFN:	BLOCK 1			;JFN FOR INPUT FILE FOR RELEASE COMMAND
OUTJFN:	BLOCK 1			;JFN FOR OUTPUT FILE FOR LOST-PAGES.BIN
DAJFN:	BLOCK 1			;JFN OF FILE BEING READ BY SCAN COMMAND
FDJFN:	BLOCK 1			;JFN OF DIRECTORY BEING CHECKED
RUNJFN:	BLOCK 1			;JFN OF PROGRAM WE ARE GOING TO RUN
HANDLE:	BLOCK 1			; HANDLE OF FORK WE ARE RUNNING THE PROGRAM IN

;FLAGS - SET ACCORDING TO COMMAND TYPED

BATFLG:	BLOCK 1			;ALLOW BAT BLOCK DELETION AS WELL AS
				; INSERTION ON DISK VERIFY PASS
SOFTFL:	BLOCK 1			; 0==> MARK HARD ERRORS OR ECC ERRORS ONLY,
				;  1==> MARK SOFT ERRORS AS WELL AS ECC ERRORS
ECCFLG: EXP 1	; DEFAULT ON	; 0==> MARK ONLY HARD ERRORS
				;  1==> MARK ECC ERRORS
REBLDF:	BLOCK 1			;REBUILD BITTAB IF NON-0
CHKFLF:	BLOCK 1			;CHECK FILES IF NON-0, ELSE DIRECTORIES ONLY
ENAFLG: BLOCK 1			;nonzero for ENABLE, zero for DISABLE
SETFLG: BLOCK 1			;nonzero for SET, zero for CLEAR
BEMFLG: BLOCK 1			; set to indicate that the editor was called
				; without a verify pass in front of it.
BATTYF: BLOCK 1			;FLAG THAT HEADERS HAVE BEEN DUMPED DURING
				;BAT BLOCK OUTPUT
;COUNTS OF ERRORS FOUND BY BUILD
;ZSTART THRU ZEND ARE ZEROED BY BUILD

ZSTART:
NBAD:	BLOCK 1			;ALL ERRORS
NDE:	BLOCK 1			;BAD PAGE TABLE ADDRESSES IN FDB'S
NPTTE:	BLOCK 1			;BAD PAGE TABLE TABLE ADDRESSES IN FDB'S
NBPT:	BLOCK 1			;FAILURES TO READ PAGE TABLES
NBPTT:	BLOCK 1			;FAILURES TO READ PAGE TABLE TABLES
NBPTE:	BLOCK 1			;BAD ADDRESSES IN PAGE TABLES
NBPTTE:	BLOCK 1			;BAD ADDRESSES IN PAGE TABLE TABLES
NIDA:	BLOCK 1			;ILLEGAL ADDRESSES
NMDA:	BLOCK 1			;MULTIPLY ASSIGNED ADDRESSES
NSDA:	BLOCK 1			;SEARCHED-FOR ADDRESSES FOUND
NDSKER:	BLOCK 1			;DISK READ ERRORS
NNBT:	BLOCK 1			;ADDRESSES NOT IN BIT TABLE
				; (BELONGING TO A FILE, BUT NOT ASSIGNED)
NABAT:	BLOCK 1			;ASSIGNED PAGES THAT ARE MARKED AS BAD
ZEND=.-1
;MISCELLANEOUS STORAGE

DIRORA:	DIRORG			;POINTER TO BASE OF MAPPED DIR
HFLAGS:	BLOCK 1			;FLAGS FROM HOME BLOCK
LOSTOT:	BLOCK 1			;NUMBER LOST PAGES
NLINB==^D100/5			;SIZE OF INPUT LINE BUFFER
LINBUF:	BLOCK NLINB
PAGNN:	BLOCK 1			;CURRENT OFFSET IN INDEX BLOCK (PAGE NO. IN FILE)
DALIST:	BLOCK 1			;AOBJN POINTER TO DATAB
DASIZ==2000
TMPBUF:				;TEMPORARY STRING BUFFER
DATAB:	BLOCK DASIZ		;LIST OF DISK ADDRESSES BEING LOOKED FOR VIA SCAN COMMAND
PDLEN==100
PDL:	BLOCK PDLEN		;STACK
DIRNAM:	BLOCK 21		;NAME OF CURRENT DIRECTORY
DIRNUM:	BLOCK 1			;NUMBER OF CURRENT DIRECTORY
STRNAM:	BLOCK 10		;STRUCTURE NAME STRING
PSNAME: BLOCK 10		;ACTUAL NAME OF PS: (IF ANY)
STRHOM:	BLOCK 10		;STR NAME ACTUALLY IN HOME BLOCK
ALINAM:	BLOCK 2			;[2] ALIAS NAME
JOBNO:	BLOCK 1			;NUMBER OF THIS JOB
ZUSED:	BLOCK 1			;NO. PAGES USED BEFORE CHECKD RAN
WRTLPF:	BLOCK 1			;WRITE LOST-PAGES.BIN IF .NE. 0
LPFHED:	BLOCK 5			;HEADER ON LOST-PAGES FILE
SYMTOP:	BLOCK 1			;ADDRESS OF END OF SYMBOL TABLE
STRDEV:	BLOCK 1			;CURRENT STR (DEVICE DESIGNATOR)
OVERHD:	BLOCK 1			;COUNT OF USED PAGES NOT ASSIGNED TO FILES
BATCNT:	BLOCK 1			;COUNT OF BAD PAGES (DECREMENTED WHEN
				; THE PAGE IS USED BY A FILE)
BATLST: BLOCK 1			;LAST BLOCK WE PROCESSED LOOKING FOR BAT BLOCKS
BATMRK: BLOCK 1			;NUMBER OF BLOCKS MARKED BAD
FSTSEC: BLOCK 1			;THE FISRT PAGE TO READ WHILE DOING A SCAN
LSTSEC:	BLOCK 1			;THE LAST PAGE WE WILL LOOK AT WHEN DOING A BAT
				;BLOCK SCAN + 1
PAGCNT:	BLOCK 1 		;COUNT OF FILE PAGES FOR THE CURRENT FILE
TOTPGS:	BLOCK 1			;TOTAL FILE PAGES IN USE
NAMBUF:	BLOCK 10		;BUFFER FOR STR NAME STRINGS
IDZB:!				;BEGIN OF ID ZERO AREA
UNITID:	BLOCK 4			;UNIT ID BUFFER
OWNRID:	BLOCK 4			;OWNER ID BUFFER
IDZZ==.-1			;END OF ID ZERO AREA
NPG4SW:	BLOCK 1			;NUMBER OF PAGES FOR SWAPPING
NPGFES: BLOCK 1			;NUMBER OF PAGES FOR FRONT-END
MNTBLK:	BLOCK 50		;STORAGE FOR MOUNTING STRS
HOMARG:	BLOCK 4			;ARG BLOCK FOR MODIFYING HOME BLOCK
RNUBLK:	BLOCK .MSRLN		;BLOCK FOR .MSRNU FCN
STRMNT:	BLOCK 1			;DEVICE DESIGNATOR OF MOUNTED STR.
FCNBLK:	BLOCK 4			;FUNCTION BLOCK FOR COMND
SAVREP:	BLOCK 1			;REPARSE PDL POINTER
SAVRET:	BLOCK 1			;REPARSE RETURN ADDRS
OKFLG:	BLOCK 1			;FLAG FOR FNDSTR
PSFLG:	BLOCK 1			;-1 IF THIS IS REALLY PS:
CPUSER:	BLOCK 1			;SERIAL # OF CPU IF BOOTED FROM THIS STRUCTURE
MAXRED:	BLOCK 1			;MAX PAGES TO READ ON A VERIFY READ
THSUNI: BLOCK 1			;UNIT NUMBER WE ARE WORKING ON
;THE FOLLOWING LOCATIONS ARE USED IN DIRECTORY SCANNING (GTFILE) TO CONVERT
;DIRECTORY NUMBER TO FILE NAME

ROOTDR:	BLOCK 20		;PLACE FOR STR:<ROOT-DIRECTORY>
ROOTPT:	BLOCK 1			;POINTER TO END OF ABOVE STRING
FILNAM:	BLOCK 25		;PLACE FOR STR:<DIRECTORY>SUBDIR.DIRECTORY
DOTPTR:	BLOCK 1			;POINTER TO LAST DOT
BRKPTR:	BLOCK 1			;POINTER TO LEFT BRACKET


;OVERHEAD IS ALL PAGES USED AS FOLLOWS:
;	HOME BLOCKS
;	SWAPPING SPACE
;	PAGE TABLE TABLE
;	PAGE TABLE
;	MARKED AS BAD AND NOT USED BY ANY OF THE ABOVE OR AS A FILE PAGE

;PAGNN SERVES AS A COUNTER INTO A FILE.  IT IS USED IN MRKBTB TO
;TELL WHAT PAGE AN ERROR IS IN.
;IF THE FILE IS LONG, THE PAGE NUMBER IS INCREMENTED ONCE FOR EVERY
;ENTRY IN A PAGE TABLE AND 1000 FOR EVERY ENTRY IN THE PAGE TABLE TABLE
;THAT IS ZERO.  THUS WITH A SPARSE FILE, PAGNN HAS THE SAME VALUE AS IF
;IT WERE NOT SPARSE. PAGNN IS -1 WHEN MRKBTB IS CALLED FOR ANY OTHER
;PAGE (PAGE TABLE, SWAPPING SPACE)


;VALUES FOR FILE CURRENTLY BEING SCANNED
;KEEP THESE IN ORDER

DEFVER:	BLOCK 1			;VERSION
DEFNAM:	BLOCK 1			;NAME
DEFEXT:	BLOCK 1			;EXTENSION
	BLOCK 4
;INTERRUPT LOCATIONS

RET1:	BLOCK 2			;flags and PC saved here
RET2:	BLOCK 2
RET3:	BLOCK 2

LEVTAB:	RET1			; [LOCATION WHERE PC STORED BY LEVEL]
	RET2
	RET3

;[39] Macro to grow entry in the channel table

	DEFINE ASSCHN(LEV,CHN,ADR),< ;Level, channel number, routine address
	ONCHNS==ONCHNS!1B<^O<CHN>> ;Count this channel as one to enable
	CHAN'CHN==<LEV>B5+ADR	;Construct this symbol for later use
>				;End of DEFINE ASSCHN

;[39] Set up channels to all go to BADINT

	ONCHNS==0		;Start with nothin on
	XX==0			;Starting with channel 0
	REPEAT ^D36,<		;For each of the channels
	ASSCHN(2,\XX,DSPINT+XX) ;Assign to bad interrupt location
	XX==XX+1>		;Count to next channel
	ONCHNS==0		;Reset channels to enable, start with none

;[39] Assign channels as needed.

	ASSCHN(1,1,CONTC)	;Control-C to Control-C handler
	ASSCHN(3,2,SUMINT)	;Control-A to summary handler
	ASSCHN(3,3,APUSH)	;Control-P to push to exec
	ASSCHN(1,\.ICPOV,PANIC)	;PDL overflows to PANIC
	ASSCHN(1,\.ICDAE,PANIC)	;Data errors to PANIC
	ASSCHN(1,\.ICQTA,PANIC)	;Disk full to PANIC
	ASSCHN(1,\.ICILI,PANIC)	;Ill inst to PANIC
	ASSCHN(1,\.ICIRD,PANIC)	;Ill mem read to PANIC
	ASSCHN(1,\.ICIWR,PANIC)	;Ill mem write to PANIC
	ASSCHN(1,\.ICMSE,PANIC)	;Sys resources exhausted to PANIC

;[39] Grow the channel table from the above definitions.

	XX==0			;Starting at channel 0
	DEFINE PLANTC(NUM),<EXP CHAN'NUM> ;Plant one channel table entry

CHNTAB:	REPEAT ^D36,<		;For each channel
	 XLIST			;Stop listing
	 PLANTC (\XX)		;Plant a channel
	 LIST			;Resume listing
	XX==XX+1>		;Ratchet the channel number
DEFINE SAVEQ<
	JSP CX,SAVQ>

SAVQ::	PUSH P,Q1		;SAVE Q1-Q3
	PUSH P,Q2
	PUSH P,Q3
	PUSHJ P,0(CX)		;CONTINUE ROUTINE, EXIT VIA .+1
RESTQ::	 SKIPA			;NON-SKIP RETURN
	AOS -3(P)		;SKIP RETURN
	POP P,Q3
	POP P,Q2
	POP P,Q1
	RET

DEFINE SAVET<
	JSP CX,SAVT>

SAVT::	PUSH P,T1		;SAVE T1-T4
	PUSH P,T2
	PUSH P,T3
	PUSH P,T4
	PUSHJ P,0(CX)		;CONTINUE ROUTINE, RETURN VIA .+1
RESTT:	SKIPA			;NO-SKIP RETURN
	AOS -4(P)		;PASS ALONG SKIP RETURN
	POP P,T4
	POP P,T3
	POP P,T2
	POP P,T1
	RET
;Macro to print an error message and transfer.  If the "MSG" field is
;specified, it is printed.  If FILFLG is non-blank, the filespec pointed to by
;DIRNAM, DEFNAM, etc., if printed at the end of the message.  A call to JSERRO
;is done to get the last error printed.  If an address is specified, a JRST to
;it is genererated.  Note that this code is not skippable.

	DEFINE PNTERR (MSG,ADDR,FILFLG)<
	IFNB <MSG>,<
	HRROI T1,[ASCIZ/
? CHECKD: MSG /]
	PSOUT			;PRINT THE MESSAGE IF ANY
	IFNB <FILFLG>,<CALL PNTFIL>> ;PRINT THE FILE NAME IF REQUESTED
	CALL JSERRO		;[39] Output error string
	IFNB <ADDR>,<JRST ADDR>	;JRST TO SPECIFIED ADDRESS IF ANY
	>

	DEFINE RETERR (MSG)<
	 JRST [	TMSG <
? CHECKD: MSG
>
		RET]
>

;ERROR - MACRO TO PRINT ERROR AND GO TO SPECIFIED LOCATION
;USED IN PARSING CODE WHEN COMND RETURNS CM%NOP

	DEFINE ERROR (ADDR,MSG)<
	JRST [	HRROI T1,[ASCIZ/ MSG/]
		CALL ERRDRV	;;CALL DRIVER ROUTINE
		JRST ADDR]>
;BITS+N CONTAINS A WORD WITH A 1 IN BIT N

XX==0
BITS::	REPEAT ^D36,<EXP 1B<XX>
		XX=XX+1>
;DIRECTORY RELATED DEFSTR'S
;COPIED FROM PROLOG.MAC

;DIRECTORY HEADER (FOR PAGE 0; FIRST 3 WORDS ARE REPEATED ON
;SUBSEQUENT PAGES)
;FDB DEFINITIONS

DEFSTR FBBK3,.FBBK3,35,36	;BACKUP WORD 3
DEFSTR FBBK4,.FBBK4,35,36	;BACKUP WORD 4
;HOME BLOCK DEFINITIONS - COPIED FROM <5.MONITOR>DSKALC.MAC

CODHOM==:707070			;HOME BLOCK SPECIAL CODE
HBLEN==:200			;LENGTH OF HOME BLOCK
HM1BLK==:1			;BLOCK # OF FIRST HOME BLOCK
HM2BLK==:^D10			;BLOCK # OF SECOND HOME BLOCK

HOMNAM==:0			;SIXBIT /HOM/
HOMID==:1			;SIXBIT /ID/
HOMPHY==:2			;PHYSICAL ADR'S OF HOME BLOCKS
HOMSNM==:3			;SIXBIT /STRUCTURE NAME/
HOMLUN==:4			;XWD TOTAL PACKS, LOGICAL PACK #
HOMHOM==:5			;BLOCK # OF HOME BLK,, BLK # OF OTHER HB
HOMP4S==:6			;# OF PAGES FOR SWAPPING ON EACH UNIT
HOMFST==:7			;FIRST SWAPPING TRACK ON EACH UNIT
HOMRXB==:10			;ADR OF INDEX BLOCK OF ROOT DIRECTORY
HOMBXB==:11			;INDEX BLOCK ADR OF BACKUP FILE
HOMFLG==:12			;FLAGS
HOMSIZ==:13			;SIZE OF A UNIT IN SECTORS (BLOCKS)
HOMBTB==:14			;SIZE OF TOP HALF OF BIT TABLE (NUMBER OF TRACKS)
HOMMID==:15			;MEDIA IDENTIFICATION (UNIQUE)
HOMDCF==:16			;DON'T CARE DISK FLAG (FILE SYSTEM PROTECTION
				;FOR FILE STRUCTURE IGNORED)
HOMBTF==17			;BOOT PARAMETER FLAGS

HOMFE0==:61			;FE FILE SYSTEM WORD ONE (SECTOR #)
HOMFE1==:62			;FE FILE SYSTEM WORD TWO (# OF SECTORS)

HOMFE2==:101			;BOOTSTRAP.BIN WORD 1 (SECTOR #)
HOMFE3==:102			;BOOTSTRAP.BIN WORD 2 (# OF SECTOR)

HOMLS1==:160			;[7.1112]Serial numbers of CPUs that
HOMLS2==:161			;[7.1112] can use this structure as a
HOMLS3==:162			;[7.1112] Login Structure
HOMLS4==:163			;[7.1112]
LGSLEN==4			;[7.1112]Number of consecutive words above

HOMSER==:164			;SERIAL # OF CPU THAT BOOTS FROM THIS STRUCTURE
HOMUID==:165			;UNIT ID
HOMOID==:170			;OWNER ID
HOMFSN==:173			;FILE SYSTEM TYPE
HOMCOD==:176			;0 ,, CODHOM
HOMSLF==:177			;THIS HOME BLOCK #
;DATA AND MACROS FOR COMMAND PARSER (USES COMND JSYS)

;TB - MACRO TO SET UP COMMAND TABLE

	DEFINE TB (DAT,TXT,CONBTS<0>)<
	IFE CONBTS,<XWD [ASCIZ /TXT/],DAT>
	IFN CONBTS,<XWD [CONBTS!CM%FW
			ASCIZ /TXT/],DAT>
>
	DEFINE TF (DAT,TXT)<
	[ASCIZ/TXT/],,[DAT]
>
;ADDRESSES FOR HANDLING EACH COMMAND

CMDTAB:	CMDSIZ,,CMDMAX		;NUMBER COMMANDS, MAXIMUM NUMBER
	TB (.CHECK,CHECK)	;CHECK (BITTABLE/DIRECTORY)
	TB (.CREAT,CREATE)	;CREATE NEW FILE SYSTEM
	TB (.DSABL,DISABLE)	;DISABLE AUTOMATIC STARTUP
	TB (.EDIT,EDIT)		; THE BAT BLOCKS
	TB (.ENABL,ENABLE)	;ENABLE AUTOMATIC STARTUP
	TB (.EXIT,EXIT)		;EXIT FROM CHECKD TO MONITOR
	TB (.FILDT,FILE-DDT)	;PUSH TO THE FILE DDT PROGRAM
	TB (.HELP,HELP)		;PRINT HELP TEXT
	TB (.PUSH,PUSH)		;PUSH TO A NEW EXEC
	TB (.REBLD,REBUILD)	;REBUILD BIT TABLE
	TB (.RECNS,RECONSTRUCT)	;RECONSTRUCT ROOT-DIRECTORY
	TB (.RLEAS,RELEASE)	;RELEASE LOST PAGES
	TB (.SCAN,SCAN)		;SCAN FILE FOR PAGE NUMBERS
	TB (.SHOW,SHOW)		;SHOW COMMAND
	TB (.STATU,STATUS)	;TYPE THE SETTINGS OF THE KNOWN SWITCHES
	TB (.VERIF,VERIFY)	;VERIFY DISK FOR ERRORS

CMDSIZ==.-CMDTAB-1
CMDMAX==CMDSIZ			;MAXIMUM NUMBER OF COMMANDS
NCHPW==5			;NUMBER OF CHARACTERS PER WORD
PROMPT:	ASCIZ /CHECKD>/		;PROMPT
CMDBLK:	BLOCK .CMGJB+5		;COMMAND STATE BLOCK (LEAVE ROOM FOR GROWTH)
GJFSIZ==.GJBFP+2
GTJBLK:	BLOCK GJFSIZ		;GTJFN BLOCK (USED BY COMND)

BUFSIZ==150
BUFFER:	BLOCK BUFSIZ		;BUFFER USER TYPES COMMAND INTO
ATMSIZ==BUFSIZ
ATMBUF:	BLOCK ATMSIZ		;BUFFER THAT COMND STORES LAST FIELD INTO

DEFSTR (CMFNC,.CMFNP,8,9)	;FUNCTION CODE
DEFSTR (CMFFL,.CMFNP,17,9)	;FUNCTION FLAGS
DEFSTR (CMLST,.CMFNP,35,18)	;LIST POINTER TO NEXT FUNCTION BLOCK
DEFSTR (CMDAT,.CMDAT,35,36)	;FUNCTION SPECIFIC DATA
DEFSTR (CMHLP,.CMHLP,35,36)	;POINTER TO HELP TEXT STRING
DEFSTR (CMDEF,.CMDEF,35,36)	;POINTER TO DEFAULT STRING

;CONFIRMATION OR COMMA
FDCC:	FLDDB.(.CMCMA,,,,,FDCO)
FDCO:	FLDDB.(.CMCFM)
;GTJFN BLOCK FOR LOST-PAGES.BIN (RELEASE COMMAND)

RLSGTJ:	GJ%OLD!GJ%PHY		;OLD FILE ONLY
	.PRIIN,,.PRIOU		;INPUT/OUTPUT JFN
	-1,,STRNAM		;DEFAULT STRUCTURE
	0			;NO DEFAULT DIRECTORY
	-1,,DIRNAM		;DEFAULT FILENAME
	-1,,[ASCIZ/BIN/]	;DEFAULT EXTENSION
	0			;NO DEFAULT PROTECTION
	0			;NO DEFAULT ACCOUNT NUMBER
	0			;NO JFN SPECIFIED
;FORMAT OF LOST-PAGES.BIN FILE

.LPFLG==0			;FLAG WORD
  .LPMJK==<252525,,'LPF'>	;MAJIK CONSTANT IN FLAG WORD
.LPTAD==1			;DATE-TIME STAMP
.LPSTR==2			;ASCIZ STR NAME
.LPCNT==4			;NUMBER OF ENTRIES
.LPDTA==5			;BEGINNING OF DATA
	SUBTTL Initialization

;ALL COMMANDS RETURN HERE TO RE-START CHECKD AND DISMOUNT
; ANY PREVIOUSLY MOUNTED STRUCTURE.

RESTRT:	SKIPN JOBNO		;ARE WE JOB 0
	JRST QUIT		;YES - JUST EXIT

	CALL DISMNT		;DISMOUNT IF NECESSARY
	CALL RESET		;RESET STORAGE
	MOVEI T1,.TICCP
	DTI
	MOVEI T1,SUMBYT		;TURN OFF PSI CHANNELS
	DTI
	MOVEI T1,.TICCC		;FOR ^C
	DTI
	TMSG <
>
	JRST START		;GO RESTART PROGRAM

;SPECIAL ENTRY IF REBUILDING BIT TABLE AUTOMATICALLY

REBST:	SETOM REBLDF		;INDICATE REBUILD REQUESTED
	JRST START0		;COMMON ENTRY
;NORMAL ENTRY

START:	HLRZ T1,.JBSA		;GET ADDR OF 1ST LOCATION AFTER CHECKD
	CAIL T1,FSTPAG		;OVERLAPPING?
	JRST [	TMSG <?CHECKD program overlaps FSTPAG> ;YES
		HALTF]

;IF YOU GET THE ABOVE MESSAGE, YOU HAVE A LOT OF WORK TO DO

	SETZM REBLDF		;DEFAULT IS NO REBUILD BITTAB

;To get more space, the directory's have been mapped into section 2,
;and Sections 0 and 1 are mapped together.  Also, a macro (SEC)
;has been added to make it easy to change what section we are running in.

START0:
	MOVX T1,<.FHSLF,,0>	;[39] Source is section 0
	MOVX T2,<.FHSLF,,1>	;destination is section 1
	MOVX T3,<SM%RD+SM%WR+SM%EX+SM%IND+1> ;map same as section 0,, one section only
	SMAP%			;map a new section
	 ERJMP JSHALT		;[39] This should not happen
	SETZM T1		;new section
	MOVE T2,[.FHSLF,,2]	;section 2
	MOVE T3,[SM%RD+SM%WR+1] ;read/write access to new section
	SMAP%			;map a new section
	 ERJMP JSHALT		;[39] This should not happen
	SEC 1			;enter section 1 for all time
	MOVE P,[IOWD PDLEN,PDL]
	MOVE T1,[ASCII "PS"]	;SET STRNAM TO PS: IN CASE THIS IS JOB 0
	MOVEM T1,STRNAM
	CALL TRANSL		;BUT FIRST, GET THE REAL PS: NAME, IF ANY.
	HRROI T1,PSNAME		
	HRROI T2,STRNAM
	MOVEI T3,0
	SOUT			;COPY TO PSNAME FOR FUTURE REFERENCE
	CALL RESET
	SETOM CHKFLF		;DEFAULT IS CHECK FILES
	SETZM DIRNUM		;INITIALIZE DIRECTORY NUMBER
	SETZM BATLST		;INITIALIZE BAT BLOCK COUNTER
	SETZM TOTPGS		;INITIALIZE TOTAL FILE PAGES
	SETZM ZUSED		;CLEAR INFO ABOUT STG
	SETOM WRTLPF		;DEFAULT IS WRITE LOST PAGES FILE
	SETZM STRMNT		;NO STRUCTURE MOUNTED YET
	SETZM BEMFLG		;DEFAULT IS DO VERIFY FIRST
;Create a string for structure alias named "CHKnnn" where "nnn" is the job,

	GJINF
	MOVEM T3,JOBNO
	HRROI T1,ALINAM		;[2] BP TO ALIAS NAME LOCATION
	HRROI T2,[ASCII/CHK/]	;[2] BP TO FIRST PART OF ALIAS
	MOVNI T3,3		;[2] IT'S 3 CHARACTERS LONG
	SOUT%			;[2] MAKE BEGINNING OF ALIAS
	 ERJMP .+1		;[2] 
	MOVE T2,JOBNO		;[2] GET OUR JOB NUMBER
	MOVE T3,[FLD(1,NO%LFL)!FLD(1,NO%ZRO)!FLD(3,NO%COL)!FLD(<^D10>,NO%RDX)] ;[2] LEADING ZEROS, 3 COLUMNS, DECIMAL
	NOUT%			;[2] FINISH THE ALIAS STRING
	 ERJMP .+1		;[2] 
;Enable caps if running under job 0

	MOVEI T1,.FHSLF
	RPCAP
	SKIPE JOBNO		;SKIP IF JOB 0
	JRST STRT1
	MOVX T3,SC%WHL!SC%OPR	;ENABLE CAPS
	EPCAP
	JRST STRT2

STRT1:	TXNN T3,SC%WHL!SC%OPR	;CHECK ENABLED CAPS
	JRST [	TMSG <?WHEEL or OPERATOR capability required
>
		JRST QUIT]
	TXNN T2,SC%CTC		;CHECK FOR ^C CAP
	JRST [	TMSG <? ^C capability not enabled
>
		HALTF
		JRST START]	;MAKE CONTINUE RESTART
	MOVX T3,SC%CTC!SC%WHL!SC%OPR
	EPCAP			;ENABLE ^C CAP ALSO
STRT2:	SETZM DALIST		; NO DISC ADDRESS LIST
	MOVEI T1,.FHSLF		;T1/FORK HANDLE
	CIS			;CLEAR THE INTERRUPT SYSTEM
	EIR			;ENABLE INTERRUPTS
	MOVEI T2,[3
		1,,LEVTAB
		1,,CHNTAB]		;DECLARE LEVTAB AND CHNTAB
	XSIR%
	SETO T2,		;DISABLE ALL CHANNELS
	DIC			;DEACTIVATE ALL CHANNELS
	MOVX T2,ONCHNS		;[39] Load channels to activate
	AIC			;ACTIVATE CHANNELS FOR TERM INTS
	MOVE T1,[XWD .TICCP,3]	;^P ON CHAN 3
	ATI
	MOVE T1,[XWD SUMBYT,2]	;CONTROL-Y ON CHANNEL 2 FOR STATUS REPORT
	ATI			;ASSIGN ^Y TO CHANNEL 2
	SKIPN JOBNO		;IF JOB 0,
	JRST DOJOB0		; DO SPECIAL ROUTINE
	MOVE T1,[XWD .TICCC,1]	;ASSIGN ^C TO CHANNEL 1
	ATI
	CALL PARSEI		; CALL COMMON ROUTINE TO DO WORK
PARSE1:	MOVE P,[IOWD PDLEN,PDL]	;RESET STACK
	HRROI T1,PROMPT		;POINTER TO PROMPT STRING
	CALL CMDINI		;INIT COMND (SETUP REPARSE)
	MOVE T1,[CZ%NCL+.FHSLF]
	CLZFF		;RELEASE ALL JFNS
	MOVEI T1,[FLDDB.(.CMKEY,,CMDTAB)] ;T1/ADDRESS OF FDB
	CALL COMNDX		;LOOK FOR A KEYWORD
	 ERROR PARSE1,<Not a CHECKD command> ;NO. START OVER
	HRRZ T1,(T2)		;YES. GO PROCESS IT
	JRST (T1)
;HERE TO SET UP THE PARSE STATE BLOCK

PARSEI:	MOVEI T2,CMDBLK		;POINT TO START OF COMMAND STATE BLOCK
	MOVE T1,[.PRIIN,,.PRIOU] ;JFN'S FOR USER INPUT AND OUTPUT
	MOVEM T1,.CMIOJ(T2)
	HRROI T1,BUFFER		;POINTER TO START OF USER INPUT
	MOVEM T1,.CMBFP(T2)
	MOVEM T1,.CMPTR(T2)	;POINTER TO NEXT FIELD
	MOVEI T1,BUFSIZ*NCHPW	;SPACE REMAINING IN BUFFER
	MOVEM T1,.CMCNT(T2)
	SETZM .CMINC(T2)	;NUMBER OF UNPARSED CHARACTERS
	HRROI T1,ATMBUF		;POINTER TO ATOM BUFFER
	MOVEM T1,.CMABP(T2)
	MOVEI T1,ATMSIZ*NCHPW	;NUMBER CHARACTERS IN ATOM BUFFER
	MOVEM T1,.CMABC(T2)
	MOVEI T1,GTJBLK		;ADDRESS OF GTJFN BLOCK
	MOVEM T1,.CMGJB(T2)
	RET
	SUBTTL Job 0 Startup

;SPECIAL JOB 0 ENTRY POINT TO CALL ROUTINES NECESSARY
;ACCORDING TO AUTOMATIC STARTUP

DOJOB0:
	MOVEI T1,.PRIOU		;WAIT FOR OUTPUT TO END.
	DOBE
	SETOM T1		;to everyone
	HRROI T2,[ASCIZ/ Checking system structure.
/]				;message
	TTMSG			;send message
	 ERJMP .+1		;don't care about errors.
	SETOM PSFLG		;SAY REALLY DOING PS:
	CALL SETSTR		;SET UP DEVICE DESIGNATOR
	CALL CLRCDE		;CLEAR MONITOR FLAGS
				;BEFORE STARTING
	SETOM WRTLPF		;TURN ON LOST PAGES FILE
	SKIPE REBLDF		;REBUILDING?
	CALL BTBINI		;YES - INIT BITTABLE
	CALL QDONE		;SCAN DIRECTORIES
	MOVX T1,.SFCDE		;SETUP IN CASE OF ERRORS
	MOVEI T2,1
	SKIPN WRTLPF		;WAS THIS TURNED OFF?
	SMON			;YES - SET FLAG THEN
	SETOM T1		;to everyone
	HRROI T2,[ASCIZ/ Check of system structure completed.
/]				;message
	TTMSG			;send it
	 ERJMP .+1		;don't care about errors
	MOVEI T1,.PRIOU
	DOBE			;WAIT FOR OUTPUT TO END.
	JRST QUIT		;THROUGH - EXIT
	SUBTTL Utility Routines

;ROUTINE TO CLEAR SF%CDE AND SF%BTE FLAGS

CLRCDE:	MOVX T1,.SFCDE		;FLAG TO CLEAR
	MOVEI T2,0
	SMON			;CLEAR IT
	MOVX T1,.SFBTE		;OTHER FLAG
	SMON
	RET			;DONE - RETURN

;DRIVER FOR "ERROR" MACRO - T1/ POINTER TO ASCIZ ERROR MESSAGE

ERRDRV:	ESOUT			;OUTPUT ERROR STRING TO TTY
	CALL CRLF		;OUTPUT CRLF
	MOVE T1,[CZ%NCL+.FHSLF]	;DUMP ALL CLOSED JFN'S
	CLZFF
	RET

;ROUTINE TO OUTPUT # SPACES IN T3

SPACN:	MOVEI T2,40		;SPACE
	IDPB T2,T1
	SOJG T3,.-1
	RET

;Here to quickly/cheaply copy ASCIZ string, insures null at end of string.
;Call with T1/ destination byte pointer, T2/ source byte pointer
;Returns +1 always, string copied, T1 and T2 updated

ISOUT:	TLC T1,-1		;Complement left half
	TLCN T1,-1		;Was the neft half -1?
	HRLI T1,(Point 7)	;Yes, make it a byte pointer
	TLC T2,-1		;Complement left half
	TLCN T2,-1		;Was the neft half -1?
	HRLI T2,(Point 7)	;Yes, make it a byte pointer

ISOUT1:	ILDB CX,T2		;Load a byte
	IDPB CX,T1		;Store it
	JUMPN CX,ISOUT1		;Jump if not done
	MOVNI CX,1		;Back up the byte pointer
	ADJBP CX,T1		; by one and
	MOVEM CX,T1		;  store back the byte pointer
	RET			;Return
	SUBTTL Structure Utility Routines

;ROUTINE TO SETUP MOUNTED STRUCTURE DEVICE DESIGNATOR
;USES MNTBLK TO GET CORRECT STRING

SETMNT:	SKIPN T1,MNTBLK+.MSTAL	;ALIAS IF PRESENT
	MOVE T1,MNTBLK+.MSTNM	;ELSE USE NAME STRING
	STDEV			;GET DEVICE DESIGNATOR
	 ERJMP JSHALT		;[39] Cannot happen (we just mounted it)
	MOVEM T2,STRMNT		;SAVE IT
	MOVE T2,MNTBLK+.MSTNM	;SAVE ACTUAL STR NAME
	HRROI T1,STRHOM
	MOVEI T3,0
	SOUT
	TMSG <
[>
	MOVE T1,MNTBLK+.MSTNM	;ACTUAL NAME
	PSOUT
	TMSG <: Mounted>
	SKIPN MNTBLK+.MSTAL	;SEE IF ALIAS
	JRST STMNT1		;NO - CONTINUE
	TMSG < as >
	MOVE T1,MNTBLK+.MSTAL
	PSOUT			;PRINT IT
	MOVEI T1,":"
	PBOUT
	HRROI T1,STRNAM		;COPY TO STRNAM
	MOVE T2,MNTBLK+.MSTAL	; THE ACTUAL STR NAME NOW
	MOVEI T3,0		; IN USE BY THE SYSTEM
	SOUT
STMNT1:	TMSG <]
>
	RET
;ROUTINE TO DISMOUNT ANY STRUCTURE MOUNTED BY CHECKD

DISMNT:	SKIPN T2,STRMNT		;DEVICE DESIGNATOR OF STR MNTED
	RET			;NONE - RETURN
	MOVEM T2,MNTBLK		;SAVE FOR MSTR
	SETZM STRMNT		;SAY NO LONGER MOUNTED

;[39] Give a message about the dismount using TTMSG so output doesn't get
;mixed with MSTR's TTMSG when the dismount completes.
	
	HRROI T1,TMPBUF		;[39] Point to temp buffer area
	HRROI T2,[ASCIZ/
[Dismounting structure /]	;[39] Point to first part of message
	CALL ISOUT		;[39] (T1,T2/T1) Copy string
	HRROI T2,STRHOM		;[39] Publish name next
	CALL ISOUT		;[39] (T1,T2/T1) Copy string
	HRROI T2,[ASCIZ/:]
/]				;[39] ending string
	CALL ISOUT		;[39] (T1,T2/T1) Copy string
	GJINF%			;[39] Get my terminal number in T4
	MOVEI T1,.TTDES(T4)	;[39] Get my terminal designator
	HRROI T2,TMPBUF		;[39] Point to temp buffer
	TTMSG%			;[39] Send that to my terminal
	 ERJMP .+1		;[39] Ignore errors

DISMN1:	MOVE T1,[1,,.MSDIS]	;FUNCTION TO DISMOUNT STR
	MOVEI T2,MNTBLK		;ADDRS OF ARGS
	MSTR			;DO FUNCTION
	 ERJMPR DISMN2		;[39] Something went wrong, get T1/ error code
	RET			;RETURN (DONE)

;Here to attempt to abort initialization of BITTABLE

DISMN2:	CAIN T1,MSTX43		;[39] Can't dismount while INIing?
	JRST JSHALT		;[39] Nope, something else serious, halt
	MOVX T1,DA%AIN		;set abort bit
	MOVE T2,STRDEV		;get structure's device designator
	DSKAS			;abort initialization
	 ERCAL JSERRO		;[39] Output error and then
	JRST DISMN1		;try to dismount again.
;SETSTR - ROUTINE TO SET UP WORKING STRUCTURE INFO
;STSTRN - AS ABOVE, WITHOUT DISPLAY OF STSRUCTURE NAME

STSTRN:	SETZM T3
	SKIPA
SETSTR:	SETOM T3
	STKVAR <TYPSTR>
	MOVEM T3,TYPSTR		;SAVE ENTRY TYPE
	SKIPE T2,STRMNT		;MOUNTED A STR?
	JRST STSTR1		;YES - ALREADY HAVE DEVICE DESIG
	HRROI T1,STRHOM		;COPY NAME FOR LATER INFO
	HRROI T2,STRNAM
	MOVEI T3,0
	SOUT			;...
	HRROI T1,STRNAM		;NO - GET STRING TYPED
	STDEV			;CONVERT TO DEVICE DESIGNATOR
	 JRST [	JSERR		;REPORT ERROR
		JRST RESTRT]
STSTR1:	MOVEM T2,STRDEV		;SAVE
	SKIPN TYPSTR		;WANT STR NAME TYPED?
	JRST AFTTYP		;NO
	TMSG <
[Working on structure >		;[39]
	HRROI T1,STRHOM		;PRINT STR NAME
	PSOUT
	TMSG <:]
>
AFTTYP:	SKIPE ZUSED		;CHECK IF HERE YET
	RET			;YES - RETURN
	MOVE T1,STRDEV		;GET DEVICE DESIGNATOR
	GDSKC			;GET DISK SPACE
	MOVEM T1,ZUSED
	RET			;RETURN

;GDNAM - ROUTINE TO WRITE CURRENT DIRECTORY NAME INTO DIRNAM

;RETURNS +1: FAILURE,
;		T1/ERROR CODE
;	  +2: SUCCESS

;WRITES STRUCTURE:<DIRECTORY> IN DIRNAM
;REQUIRES DIRNUM TO HAVE THE 36-BIT DIRECTORY NUMBER

GDNAM:	HRROI T1,DIRNAM		;GET THE NAME OF THIS DIRECTORY
	MOVE T2,DIRNUM		;T2/ DIRECTORY NUMBER
	DIRST			;WRITE ITS NAME
	 RET			;FAILED. RETURN FAILURE
	RETSKP			;SUCCEEDED
;FRSDIR - GET FIRST DIRECTORY ON THE STRUCTURE

;	CALL FRSDIR

;RETURNS +1: FAILURE
;	 +2: SUCCESS

;RETURNS WITH DIRNUM SET UP

FRSDIR:	HRROI T2,[ASCIZ/<*>/]	;ASK FOR ALL DIRECTORIES
	CALL ADDSTR		;ADD STRUCTURE STRING
	MOVX T1,RC%AWL!RC%EMO	;T1/ ALLOW WILD CARD, NO RECOGNITION
	RCDIR			;GET FIRST DIRECTORY NUMBER
	 ERJMP [ PNTERR(<Unable to reference directory files>)
		JSERR
		RET]
	TXNE T1,RC%AMB!RC%NOM!RC%NMD ;ANY ERRORS?
	JRST [	PNTERR(<Unable to reference directory files>)
		RET]
	MOVEM T3,DIRNUM		;NO. SAVE DIRECTORY NUMBER
	RETSKP
;NXTDIR - GET NEXT DIRECTORY

;	CALL NXTDIR

;RETURNS +1: FAILURE OR DONE
;	 +2: SUCCESS

;RETURNS WITH DIRNUM SET UP

NXTDIR:	MOVX T1,RC%EMO!RC%AWL!RC%STP ;T1/ NO RECOGNITION, ALLOW WILD CARDS, STEP
	HRROI T2,ATMBUF		;POINT TO STR:<*>
	MOVE T3,DIRNUM		;T3/ DIRECTORY WE GOT BEFORE
	RCDIR			;GET THE NEXT DIRECTORY
	IFJER.			;[3]IF A JSYS ERROR OCCURS
	 PNTERR(<Failed to get next directory>)	;[3]
	 HRROI T1,[ASCIZ/? CHECKD: Last directory seen was /] ;[3]TELL HIM WHERE WE WERE
	 PSOUT%			;[3]OUTPUT TO THE TTY:
	 MOVEI T1,.PRIOU	;[3]OUTPUT TO TTY:
	 MOVE T2,DIRNUM		;[3]GET THE LAST DIRECTORY NUMBER
	 DIRST%			;[3]PRINT IT OUT
	  ERJMP .+1		;[3]AT LEAST WE TRIED
	 TMSG <
>				;[3]FINISH OFF THE MESSAGE
	 SETZ T1,		;[3]CLEAR FLAGS FOR ERROR
	 SETZM DIRNUM		;[3]
	 RET			;[3]
	ENDIF.			;[3]
	TXNE T1,RC%NOM!RC%AMB	;DID WE GET A STRANGE ERROR?
	JRST [	PNTERR(<Failed to get next directory>)
		SETZM DIRNUM
		RET]
	TXNE T1,RC%NMD		;NO MORE DIRECTORIES?
	JRST  [	SETZM DIRNUM
		RET]
	MOVEM T3,DIRNUM		;NO. SAVE DIRECTORY NUMBER
	RETSKP
;CKDIR - ROUTINE TO DO DIRECTORY CONSISTENCY CHECK AND REBUILD
;IF THERE ARE ANY ERRORS
; DIRECTORY NUMBER IS IN "DIRNUM"

CKDIR:	MOVE T2,DIRNUM		;GET DIRECTORY NUMBER
	MOVX T1,DD%CHK		;CHECK ONLY
	DELDF
	 ERJMP CKDIR1		;ERROR - INFORM WORLD
	RET			;OK - RETURN

CKDIR1:	TMSG <% Rebuilding symbol table for >
	HRROI T1,DIRNAM		;PRINT NAME
	PSOUT
	MOVE T2,DIRNUM		;GET NUMBER AGAIN
	MOVX T1,DD%RST		;REBUILD FCN
	DELDF			;TRY IT
	 ERJMP CKDIR2		;CAN'T REBUILD
	TMSG < [OK]
>
	RET			;SAY OK AND RETURN

CKDIR2:	TMSG < [FAILED]
>
	RET			;RETURN
;ROUTINE TO GET CONNECTED STRUCTURE STRING INTO STRNAM

GETCON:	GJINF			;GET CONNECTED STR ID
	HLRZS T2		;STRUCTURE UNIQUE CODE
	HRLI T2,.DVDES		;MAKE INTO DEVICE DESIGNATOR
	HRROI T1,STRNAM
	DEVST			;CONVERT TO STRING
	 JRST GETCN1		;NOT CONNECTED - FIX
	RET			;RETURN

GETCN1:	SETO T1,		;SAY THIS JOB
	HRROI T2,T4		;ONE WORD INTO T4
	MOVX T3,.JILNO		;LOGGED IN DIR #
	GETJI
	 ERJMP JSHALT		;[39] Should never happen
	MOVEM T4,FCNBLK		;SAVE IT
	SETZM FCNBLK+1		;NO PASSWORD
	SETOM FCNBLK+2		;THIS JOB
	MOVE T1,[AC%CON+3]
	MOVEI T2,FCNBLK		;ADDRS OF ARGS
	ACCES			;CONNECT TO LOGGED IN DIR
	 ERJMP JSHALT		;[39] Should never happen
	JRST GETCON		;LOOP BACK AND TRY AGAIN

;ROUTINE TO TRANSLATE STRNAM FROM PS: TO ITS REAL NAME, IF ANY.

TRANSL:	HRROI T1,STRNAM
	STDEV			;GET INTERNAL REPRESENTATION
	 ERJMP R		;IF FAIL, RETURN, ITS NOT EVEN MOUNTED
	HRROI T1,STRNAM		;PUT IT HERE, PAL.
	DEVST			;GET THE REAL NAME
	 ERJMP JSERR0		;ERROR, REPORT, AND RETURN
	RET
;ROUTINE TO DO CONFIRMATION AND GET STRUCTURE NAME STRING

FCNFRM:	HRROI T1,[ASCIZ /FOR/]
	CALL CMDNOI		;XTRA GUIDE WORD
CONFRM:	SETZM	T1		;no default for structure name
	CALL CMDSTR		;GET STRUCTURE STRING
	HRROI T1,STRNAM		;PLACE TO STORE STRUCTURE NAME
	HRROI T2,ATMBUF		;COPY STRING TYPED BY USER
	MOVEI T3,0
	SOUT			;SLOW
	CALL CMDEOL		;PARSE TO EOL
	 JRST PARSE1		;ERROR
	RET

;ROUTINES TO PARSE STRUCTURE NAME STRING (DEFALUT IN T1)
;ENTRY:  PRSSTR		PARSE EXISTING STRUCTURE
;	 CMDSTR		PARSE NON-EXISTENT STRUCTURE

PRSSTR:	MOVX T2,<FLD(.CMDEV,CM%FNC)+<CM%SDH!CM%HPP!CM%DPP>>
	SKIPA
CMDSTR:	MOVX T2,<FLD(.CMFLD,CM%FNC)+<CM%SDH!CM%HPP!CM%DPP>>
	MOVEM T1,FCNBLK+.CMDEF	;SAVE DEFAULT
	MOVEM T2,FCNBLK		;SETUP FUNCTION
	HRROI T1,[ASCIZ "STRUCTURE NAME"]
	MOVEM T1,FCNBLK+.CMHLP	;SETUP HELP TEXT
	SETZM FCNBLK+.CMDAT	;NO XTRA DATA
	MOVEI T1,FCNBLK		;FUNCTION BLOCK
	CALL COMNDX
	 ERROR PARSE1,<Invalid structure name>
	SKIPN CMDBLK+.CMINC	;ANY REMAINING CHARACTERS?
	RET			;NO - OK RETURN
	MOVE T3,CMDBLK+.CMPTR	;YES - GET POINTER
	ILDB T2,T3		;GET NEXT CHARACTER
	CAIE T2,":"		;SEE IF A COLON?
	RET			;NO - OK RETURN
	MOVEM T3,CMDBLK+.CMPTR	;SKIP OVER CHARACTER
	SOS CMDBLK+.CMINC
	RET			;AND RETURN


	;ROUTINE TO GET STRUCTURE NAME
GETSTR:	SETZM T1		;No default
	CALL PRSSTR		;Get the structure
	HRROI T1,STRNAM		;PLACE TO STORE STRUCTURE NAME
	HRROI T2,ATMBUF		;COPY STRING TYPED BY USER
	MOVEI T3,0
	SOUT			;
	RET
;GENERAL COMND UTILITIES

;SET UP AND EXECUTE COMND JSYS
; T1/ ADDRESS OF FUNCTION DESCRIPTOR BLOCK
;RETURNS +1: PARSE FAILED (ITRAP OR CM%NOP SET)
;	 +2: PARSE SUCCEEDED, T1,T2,T3 AS RETURNED BY COMND JSYS

COMNDX:	MOVE T2,T1		;MOVE FDB ADDRESS TO T2
	MOVEI T1,CMDBLK		;GET COMND STATE BLOCK ADDR IN T1
	COMND			;THE ONLY COMND JSYS IN CHECKD
	 ERJMP R
	TXNE T1,CM%NOP		;PARSE OK?
	RET			;NO
	RETSKP			;YES

; COMNDE - PRINT ERROR MESSAGE FOR COMND
;  T2/ ERROR CODE (RETURNED BY COMND)
; RETURNS +1: ALWAYS

COMNDE:	HRROI T1,[ASCIZ/ /]
	ESOUT			;SET UP BEGINNING OF ERROR MESSAGE
CMNDE1:	MOVEI T1,.PRIOU		;[37] Entry point for other places
	HRLI T2,.FHSLF
	SETZ T3,
	ERSTR			;PRINT ERROR MESSAGE
	 JFCL
	 JFCL
CRLF:	TMSG <
>
	RET

;INIT COMND AND SETUP REPARSE TO BE THE RETURN ADDRS
;OF THE CALLER. C(T1) := POINTER TO PROMPT STRING

CMDINI:	MOVEM T1,CMDBLK+.CMRTY	;SETUP PROMPT
	POP P,SAVRET		; AND RETURN ADDRS
	MOVEM P,SAVREP		;SAVE PDL FOR REPARSE
	MOVEI T1,REPARS		;SETUP REPARSE ADDRS
	MOVEM T1,CMDBLK+.CMFLG
	MOVEI T1,[FLDDB.(.CMINI)] ;INIT FUNCTION
	CALL COMNDX
	 JFCL
	JRST @SAVRET		;RETURN

REPARS:	MOVE P,SAVREP		;RESET PDL
	JRST @SAVRET		; RETURN TO CALLER OF CMDINI
;NOISE PARSE ROUTINE
; C(T1) := GUIDE WORD STRING

CMDNOI:	MOVEM T1,FCNBLK+.CMDAT	;SAVE TEXT STRING
	MOVX T1,<FLD(.CMNOI,CM%FNC)>
	MOVEM T1,FCNBLK		;SET UP FUNCTION
	MOVEI T1,FCNBLK		;FUNCTION
	CALL COMNDX
	 JRST [	CALL COMNDE	;ERROR, TYPE MESSAGE
		JRST PARSE1]
	RET			;RETURN

;CHECK FOR EOL (RETURN +1 IF NONE)

CMDEOL:	MOVEI T1,[FLDDB.(.CMCFM)]
	CALL COMNDX		;CHECK CONFIRMATION
	 JRST COMNDE		;ERROR, TYPE MESSAGE AND RETURN
	RETSKP			;YES - SKIP RETURN
;ROUTINE TO WRITE A HEADER FOR THE LOST-PAGES FILE

LPFWRT:	SETZM LPFHED+.LPSTR	;CLEAR STR NAME
	SETZM LPFHED+.LPSTR+1
	MOVE T1,[.LPMJK]		;MAJIK CONSTANT
	MOVEM T1,LPFHED+.LPFLG
	GTAD			;GET CURRENT DATE & TIME
	MOVEM T1,LPFHED+.LPTAD
	HRROI T1,LPFHED+.LPSTR	;POINT TO STR NAME
	HRROI T2,STRHOM		;POINT TO NAME STRING
	MOVEI T3,0		;OUTPUT TILL NULL
	SOUT
	MOVE T1,LOSTOT		;LOST PAGES COUNT
	MOVEM T1,LPFHED+.LPCNT
	MOVE T1,OUTJFN
	MOVE T2,[POINT 36,LPFHED]
	MOVNI T3,.LPDTA		;HEADER SIZE
	SOUT
	RET			;DUMP AND RETURN
;ROUTINE TO CHECK LOST-PAGE FILE HEADER

LPFCHK:	SETZM DIRNAM		;CLEAR STR NAME AREA
	SETZM DIRNAM+1
	MOVE T1,INJFN		;INPUT JFN
	MOVE T2,[POINT 36,LPFHED]
	MOVNI T3,.LPDTA		;SIZE OF RECORD
	SIN			;READ IT
	 ERJMP JSHALT		;[39] Should never happen
	MOVE T1,LPFHED+.LPFLG	;GET FLAG WORD
	CAME T1,[.LPMJK]	;CHECK CONSTANT
	JRST [	TMSG <?File not in correct format>
		JRST LPFCHE]
	HRROI T1,STRHOM		;CHECK MATCH OF STR
	HRROI T2,LPFHED+.LPSTR
	STCMP
	JUMPN T1,[TMSG <?File is for structure >
		 HRROI T1,LPFHED+.LPSTR
		 PSOUT
		 JRST LPFCHV]
LPFCH1:	TMSG <File written on: >
	MOVEI T1,.PRIOU
	MOVE T2,LPFHED+.LPTAD	;FILE DATE AND TIME
	MOVEI T3,0		;USE DEFAULT
	ODTIM
	TMSG < , contains >
	MOVEI T1,.PRIOU
	MOVE T2,LPFHED+.LPCNT
	MOVEI T3,^D10		;DECIMAL NUMBER
	NOUT
	 JFCL
	TMSG < entries.
>
	RETSKP			;GOOD RETURN

LPFCHE:	TMSG < , Aborting...
>
	RET			;ERROR RETURN

LPFCHV:	TMSG <
>
	HRROI T1,[ASCIZ "Do you want to proceed anyway? "]
	CALL YESNO		;GET CONFIRMATION
	JUMPL T1,LPFCH1		;YES - USE THIS FILE
	RET			;NO - TERMINATE
;ROUTINE TO ADD STRUCTURE NAME TO BEGINNING OF STRING

;ACCEPTS:
;	T2/ POINTER TO EXISTING STRING

;	CALL ADDSTR

;RETURNS +1: ALWAYS,
;		T2/ POINTER TO STRING WITH STRUCTURE IN FRONT

ADDSTR:	STKVAR <GJSTR>
	MOVEM T2,GJSTR		;SAVE POINTER TO STRING
	HRROI T1,ATMBUF		;BUILD FILESPEC HERE
	HRROI T2,STRNAM		;STRUCTURE NAME STRING
	MOVEI T3,0
	SOUT			;COPY STRUCTURE NAME
	MOVEI T2,":"		;APPEND COLON TO DEVICE NAME
	IDPB T2,T1
	MOVE T2,GJSTR
	SOUT			;COPY REMAINDER OF NAME
	HRROI T2,ATMBUF		;COMPLETE NAME
	RET			;RETURN WITH CORRECT POINTER

;ROUTINE TO CHECK FOR PS:

PSCHK:	CALL TRANSL		;GET REAL PS: NAME, IF ANY.
	SETZM PSFLG		;NOT PS: YET
	HRROI T1,STRNAM		;NAME OF STRUCTURE
	HRROI T2,PSNAME
	STCMP			;COMPARE STRINGS
	JUMPN T1,R		;NOT PS - NON SKIP
	SETZM OKFLG		;FLAG FOR FNDSTR
	CALL FNDSTR		;SEE IF THERE IS A DISMOUNTED
	 SETO T1,		;CANT HAPPEN (ASSUME PS)
	JUMPE T1,R		;NEED TO MOUNT THIS PS
	SETOM PSFLG		;THIS IS THE REAL PS:
	MOVE T1,[SIXBIT /DBUGSW/];SEE IF WE ARE TIMESHARING, AND ONLY
	SYSGT			; ALLOW WORKING ON PS IF NOT
	SKIPE T2		;DID WE GET THE ENTRY?
	JUMPE T1,R		;YES, WE DID, BUT WE ARE TIMESHARING
	RETSKP			;SKIP RETURN
;ROUTINE TO SCAN ALL DISK DRIVES LOOKING FOR STRUCTURE
;NAMED IN STRNAM AND CHECKING TO SEE IF IT IS DISMOUNTED
; RETURNS +1 IF ERROR
; RETURNS +2 C(T1) := -1 IF STR ALREADY MOUNTED
;	     C(T2) := 0 IF NEED TO MOUNT STR (MNTBLK SETUP)

FNDSTR:	STKVAR <NUNITS,DEVSAV>
FNDST0:	SETOM RNUBLK+.MSRCH	;INIT FOR FIRST UNIT
	SETOM RNUBLK+.MSRCT
	SETOM RNUBLK+.MSRUN
	SETOM MNTBLK+.MSTNU	;INIT # OF UNITS IN STR
	SETZM NUNITS		;INIT NUMBER OF UNITS FOUND
FNDST1:	CALL GTUSTS		;GET UNIT STATUS
	 JRST FNDST3		;NO MORE UNITS
	CALL STRMAT		;MATCH STRUCTURE WANTED
	 JRST FNDST1		;NO - TRY NEXT
	SKIPL MNTBLK+.MSTNU	;FIRST TIME HERE
	JRST FNDST2		;NO - JUST SETUP UNIT
	HRRZ T1,RNUBLK+.MSRNS	;YES - GET # OF UNITS IN STR
	CAILE T1,10		;MAX NUMBER WE CAN HANDLE
	RETERR <More than 8. units in structure>
	MOVEM T1,MNTBLK+.MSTNU
	SETOM MNTBLK+.MSTUI	;INIT MOUNT TABLE TO -1
	MOVE T1,[MNTBLK+.MSTUI,,MNTBLK+.MSTUI+1]
	BLT T1,MNTBLK+.MSTUI+.MSTNO*10-1
				;CLEAR TABLE
FNDST2:	HRRZ T1,RNUBLK+.MSRNS	;GET # OF UNITS
	CAME T1,MNTBLK+.MSTNU	;SAME AS BEFORE?
	RETERR <Ambiguous number of units found>
	HLRZ T1,RNUBLK+.MSRNS	;GET LOGICAL UNIT NUMBER
	IMULI T1,.MSTNO		;CALC OFFSET INTO TABLE
	ADDI T1,MNTBLK+.MSTUI
	SKIPL .MSTCH(T1)	;UNIT PREVIOUSLY NOT FOUND?
	RETERR <Multiple logical units found>
	HRLI T1,RNUBLK+.MSRCH	;SET UP XFER WORD
	MOVEI T2,.MSTUN(T1)
	BLT T1,0(T2)		;XFER DISK ADDRESS
	AOS NUNITS		;INCR NUMBER OF PACKS SO FAR
	JRST FNDST1		;GET MORE
;HERE WHEN NO MORE UNITS FOUND

FNDST3:	SKIPE T1,NUNITS		;FOUND ANYTHING?
	JRST FNDST8		;YES - GO ON
	HRROI T1,STRNAM		;SEE IF ALREADY ON-LINE
	STDEV
	 RETERR <Structure not found>
	MOVEM T2,DEVSAV		;SAVE DEVICE DESIG FOR DISMOUNT
	SKIPN OKFLG		;WANT TO WARN USER
	JRST [	SETO T1,	;DON'T MOUNT ANYTHING
		RETSKP]		;GOOD RETURN
	HRROI T1,[ASCIZ "% Structure already mounted. Forcibly dismount and proceed? "]
	CALL YESNO
	JUMPE T1,R		;DON'T PROCEDE
	HRROI T1,STRHOM		;COPY NAME TO HERE
	HRROI T2,STRNAM		; FOR DISMOUNT MSG
	MOVEI T3,0
	SOUT
	MOVE T1,DEVSAV		;SETUP DEVICE DESIGNATOR
	MOVEM T1,STRMNT
	MOVEM T1,MNTBLK		;SETUP FOR GET STR STATUS
	HRROI T1,STRNAM		;PUT STRUCTURE-ID HERE
	MOVEM T1,MNTBLK+.MSGSI
	MOVE T1,[.MSGLN,,.MSGSS]
	MOVEI T2,MNTBLK		;FUNCTION BLOCK
	MSTR			;GET STR ID
	 ERJMP JSHALT		;[39] Should never happen
	CALL DISMNT		;DISMOUNT STR
	JRST FNDST0		;AND START OVER

FNDST8:	CAME T1,MNTBLK+.MSTNU	;FOUND CORRECT NUMBER
	RETERR <Structure missing one or more units>
	HRROI T1,STRNAM		;SET NAME INTO BLOCK
	MOVEM T1,MNTBLK+.MSTNM
	SETZM MNTBLK+.MSTAL	;NO ALIAS
	SETZ T1,		;SAY NEED TO MOUNT
	RETSKP			;GIVE GOOD RETURN
;ROUTINE TO READ-NEXT-UNIT STATUS

GTASTS:				;GET STATUS OF ALIAS ID.
	HRROI T1,NAMBUF		;PLACE FOR STRUCTURE NAME
	MOVEM T1,RNUBLK+.MSRSA	;GET ALIAS NAME
	SETZM RNUBLK+.MSRSN	;DON'T CARE ABOUT ACTUAL STRUCTURE NAME
	JRST GTUST1;		;GO INLINE
	
GTUSTS:				;GET STATUS OF PHYSICAL ID.
	HRROI T1,NAMBUF		;PLACE FOR STRUCTURE NAME
	MOVEM T1,RNUBLK+.MSRSN	;ALWAYS GET ACTUAL STRUCTURE NAME
	SETZM RNUBLK+.MSRSA	;DONT CARE ABOUT ALIAS NAME
GTUST1:	MOVE T1,[.MSRLN,,.MSRNU] ; LEN,,FCN
	MOVEI T2,RNUBLK		;ADDRS OF ARGS
	MSTR			;GET STATUS
	 ERJMP [MOVEI T1,.FHSLF	;OURSELVES
		GETER
		HRRZ T1,T2
		CAIE T1,MSTX18	;NO MORE UNITS?
		JSERR		;ERROR
		RET]		;NO - RETURN
	RETSKP			;GOOD RETURN
;ROUTINE WHICH SKIPS IFF CURRENT UNIT IS PART OF STRUCTURE WE
;WANT.

STRMAX:	TDZA T3,T3		; FLAG THAT WE DONT CARE ABOUT MOUNTED
STRMAT:	SETO T3,
	MOVE T1,RNUBLK+.MSRST	;GET UNIT STATUS
	TXNE T1,MS%HBB		;VALID HOME BLOCKS?
	JRST STMAT1		;GIVE WARNING
	TXNE T1,MS%OFL!MS%DIA
	RET			;OFF-LINE, OR DIAG
	SKIPE T3		;ARE WE LOOKING FOR MOUNTED UNITS?
	JRST [	TXNE T1,MS%MNT	;MOUNTED?
		RET
		JRST .+1]	;NO, IT OK
	HRROI T1,NAMBUF		;CONSIDER THIS NAME
	HRROI T2,STRNAM		;REQUESTED STRUCTURE
	STCMP			;MATCH STRINGS
	JUMPN T1,R		;RETURN IF NO MATCH
	RETSKP			;SKIP IF MATCH

STMAT1:	TMSG <% Unit >
	MOVE T2,RNUBLK+.MSRUN
	MOVEI T3,^D10		;DECIMAL OUTPUT
	CALL TTNOUT		;PRINT UNIT #
	SKIPGE RNUBLK+.MSRCT	;ANY CONTROLLER?
	JRST STMAT2		;NO, SKIP SOME OUTPUT
	TMSG < on controller >	;YES, TYPE SOME
	MOVE T2,RNUBLK+.MSRCT	;GET CONTROLLER NUMBER
	CALL TTNOUT		;TYPE IT
STMAT2:	TMSG < on channel >
	MOVE T2,RNUBLK+.MSRCH
	CALL TTNOUT		;AND CHANNEL
	TMSG < does not have valid home blocks - ignored.
>
	RET			;RETURN ERROR
;ROUTINE TO INITIALIZE A STRUCTURE FROM INFORMATION GIVEN
;BY THE USER. C(T1) := FLAGS,,FCN

STRINI:	HLLM T1,MNTBLK+.MSINU	;STORE FLAGS AND FUNCTION
	HRRZ T2,MNTBLK+.MSINU	;GET NUMBER OF UNITS
	SOS T2			; -1
	IMULI T2,.MSINO		;WORDS / UNIT
	SETZM MNTBLK+.MSIST(T2)	;CLEAR STATUS WORD
	HRROI T1,STRNAM		;SET UP NAME STRING
	MOVEM T1,MNTBLK+.MSINM
	MOVE T1,NPG4SW		;# PAGES FOR SWAPPING
	MOVEM T1,MNTBLK+.MSISW(T2)
	MOVE T1,NPGFES		;# PAGES FOR FRONT-END
	MOVEM T1,MNTBLK+.MSIFE(T2)
	MOVE T1,CPUSER		;CPU SERIAL NUMBER OF BOOTABLE STRUCTURE
	MOVEM T1,MNTBLK+.MSISN(T2)
	MOVEI T1,MNTBLK+.MSIUI(T2)
	HRLI T1,UNITID		;UNIT ID STRING
	BLT T1,MNTBLK+.MSIUI+2(T2) ;MOVE STRING (12 CHARS)
	MOVEI T1,MNTBLK+.MSIOI(T2)
	HRLI T1,OWNRID		;OWNER ID STRING
	BLT T1,MNTBLK+.MSIOI+2(T2) ;MOVE IT
	HRLZI T1,.MSISN+1(T2)	;SIZE OF ARG LIST
	HRRI T1,.MSINI		; SIZE ,, FUNCTION
	MOVEI T2,MNTBLK		;POINT TO ARG BLOCK
	MSTR			;TRY TO MOUNT , ETC.
	 ERJMP [JSERR		;REPORT FAILURE
		RET]
	CALL SETMNT		;SET MOUNTED STR
	RETSKP			;GOOD RETURN

;INIT STRUCTURE PARAMETERS (SET DEFAULTS)

STRDEF:	SETZM NPG4SW		;ASSUME NO SWAPPING
	SETZM NPGFES		;AND NO FRONT-END FILE SYSTEM
	SETZM IDZB		;CLEAR ID FIELDS
	MOVE T1,[IDZB,,IDZB+1]
	BLT T1,IDZZ		;...
	RET			;RETURN
;ROUTINE TO MOUNT STRUCTURE FOR EXCLUSIVE USE

XMNTA:	TDZA T1,T1		;OK IF MOUNTED ENTRY
XMNT:	SETO T1,		;MUST FIND OFF-LINE
	MOVEM T1,OKFLG		;SAVE FLAG FOR FNDSTR
	CALL FNDSTR		;FIND STUCTURE
	 JRST RESTRT		; PROBLEM - START OVER
	JUMPL T1,R		;RETURN IF ALREADY MOUNTED
	HRROI T1,ALINAM		;[2] GET STRUCTURE ALIAS
	MOVEM T1,MNTBLK+.MSTAL	;SETUP ALIAS FOR CHECKD
	MOVX T1,MS%XCL!MS%IGN	;EXCLUSIVE USE, IGNORE ERRORS
	HLLM T1,MNTBLK+.MSTNU	;SET FLAGS
	HRRZ T1,MNTBLK+.MSTNU	;CALC SIZE OF BLOCK
	IMULI T1,.MSTNO
	ADDI T1,.MSTUI		; PLUS CONSTANT SIZE
	HRLZS T1		;MOVE TO LHS
	HRRI T1,.MSMNT		;MOUNT FUNCTION
	MOVEI T2,MNTBLK		;POINT TO ARG BLOCK
	MSTR
	 ERJMP [JSERR		;REPORT LOSAGE
		JRST RESTRT]	;START OVER
	CALL SETMNT		;SET STRUCTURE MOUNTED
	HRROI T1,ALINAM		;[2] GET STRUCTURE ALIAS
	MOVEM T1,MNTBLK+.MSDEV	;SET UP ALIAS NAME
	MOVE T1,[1,,.MSIMC]	;INCREMENT MOUNT COUNT FOR THIS STR
	MOVEI T2,MNTBLK		;POINT TO ARG BLOCK
	MSTR
	 ERJMP [JSERR		;REPORT LOSAGE
		JRST RESTRT]	;START OVER
	RET			;RETURN
 REPEAT 0, <
;SET COMMAND

.SET:	MOVEI T1,[FLDDB.(.CMKEY,,SETTAB)]	;SECONDARY KEYTABLE
	CALL COMNDX
	 ERROR PARSE1,<Not a CHECKD command>
	HRRZ T1,(T2)		;GET DISPATCH
	JRST (T1)		;PROCESS

;SET KEYWORD TABLE

SETTAB:	XWD SETSIZ,SETMAX
	TB (.DRVSNO,DRIVE-SERIAL-NUMBER)	;DRIVE SERIAL # FOR RP20
SETSIZ=.-SETTAB-1
SETMAX=SETSIZ
	;SET DRIVE-SERIAL-NUMBER
.DRVSNO: TRVAR <SERNO>
	HRROI T1,[ASCIZ /FOR RP20/]
	CALL CMDNOI		;NOISE WORDS
	CALL CMDEOL		;PARSE END OF LINE
	 JRST PARSE1		;ERROR RETURN
	CALL CNFINF		;GET CONFIGURATION INFORMATION
	MOVEI Q1,RNUBLK+.MSRCH	;CHANNEL,UNIT,CTL FOR .MSRUS MSTR FUNCTION
	CALL GETUNT		;GET UNIT INFO FOR ONE UNIT
	MOVE T1,[.MSRLN,,.MSRUS]
	XMOVEI T2,RNUBLK
	MSTR
	 ERJMP 	[JSERR
		JRST PARSE1]
	LOAD T1,MS%TYP,RNUBLK+.MSRST
	CAIE T1,.MSR20
	 ERROR PARSE1,<Drive is not an RP20>
SETDV1:	HRROI T1,[ASCIZ /Enter decimal serial number: /]
	CALL CMDINI
	MOVEI T1,[FLDDB.(.CMNUM,,^D10)]
	CALL COMNDX
	 ERROR SETDV1,<Invalid decimal number>
	MOVEM T2,SERNO
	MOVE T1,RNUBLK+.MSRCH
	STOR T1,DOP%C2,T4	;CHANNEL
	MOVE T1,RNUBLK+.MSRCT
	STOR T1,DOP%K2,T4	;CONTROLLER
	MOVE T1,RNUBLK+.MSRUN
	STOR T1,DOP%U2,T4	;UNIT
	MOVEI T1,3		;SECTOR THREE IS FOR THE SERIAL NUMBER
	TXO T1,<FLD .DOPPU,DOP%AT> ;RELATIVE ADDRESSES
	MOVEI T2,1000		;LENGTH OF BLOCK
	TXO T2,DOP%PS+DOP%NF	;TRUE PHYSICAL SECTORS, CHAN/CTL/UNIT
	MOVEI T3,BATBUF
	DSKOP
	 JUMPN T1,[JSERR
		JRST RESTRT]
	MOVEI T1,.MSR20
	IORI T1,400		;128 SERIES DRIVE AS IN PHYUBB-2
	LSH T1,20	
	MOVEM T1,BATBUF+0	;SAVE HIGH ORDER SERIAL NUMBER
	MOVE T1,SERNO
	MOVEM T1,BATBUF+1	;SAVE LOW ORDER SERIAL NUMBER
	MOVEI T1,3		;BACK TO SECTOR 3
	TXO T1,<FLD .DOPPU,DOP%AT> ;RELATIVE ADDRESSES
	TXO T2,DOP%WR		;WRITE
	DSKOP			;WRITE IT BACK
	 JUMPN T1,[JSERR
		JRST RESTRT]
	JRST RESTRT	
>				;END REPEAT 0
	SUBTTL Create Command

;CREATE NEW FILE SYSTEM

;ACCEPT FILE STRUCTURE DESCRIPTION AND BUILD A NEW STRUCTURE
;ON THE SPECIFIED UNITS. (.MSINI FUNCTION)

.CREAT:	HRROI T1,[ASCIZ /NEW FILE SYSTEM FOR/]
	CALL CMDNOI		;PRINT GUIDE WORDS
	CALL CONFRM		;GET STR NAME AND CONFIRM
	CALL STRDEF		;SET DEFAULTS
	HRROI T1,[ASCIZ /Enter alias: /]
	CALL CMDINI		;INIT AND PROMPT
	HRROI T1,[ASCIZ /CHECKD/]
	CALL CMDSTR		;PARSE STRUCTURE NAME
	HRROI T1,DIRNAM		;PLACE TO STORE ALIAS
	HRROI T2,ATMBUF		;WHAT HE TYPED
	MOVEI T3,0
	SOUT
	CALL CMDEOL		;PARSE TO EOL
	 JRST PARSE1		; ERROR
CREAT1:	HRROI T1,[ASCIZ /How many units in this structure? /]
	CALL CMDINI		;PRINT PROMPT
	MOVEI T1,[FLDDB.(.CMNUM,,^D10)]
	CALL COMNDX		;GET DECIMAL NUMBER
	 ERROR CREAT1,<Invalid decimal number>
	CAIG T2,8		;AND IN RANGE
	CAIGE T2,1
	ERROR CREAT1,<Number not in range 1-8>
	MOVEM T2,MNTBLK+.MSINU	;SAVE NUMBER OF UNITS
	CALL CMDEOL		;GET <CR>
	 JRST CREAT1		;TRY AGAIN
	CALL CNFINF		;GET CONFIG INFO
	MOVEI Q1,MNTBLK+.MSISU	;BEGINNING OF UNIT INFO
	HRRZ Q2,MNTBLK+.MSINU	;COUNT OF UNITS
CREAT2:	CALL GETUNI		;GET UNIT INFO
	ADDI Q1,.MSINO		;STEP TO NEXT
	SOJG Q2,CREAT2		;LOOP TILL DONE
	SETZM HBUF		;CLEAR THE HELP BUFFER
	MOVE T1,[HBUF,,HBUF+1]
	BLT T1,HBUF+<NHBUFP*1000>-1
CREAT3:	HRROI T1,[ASCIZ /Number of pages to allocate for swapping? /]
	CALL CMDINI		;PRINT PROMPT
	RADIX 10
	FORS. (DEFP4S,<NUMSWP>,<
		MOVEI T1,[FLDDB.(.CMNUM,CM%SDH,^D10,<0 for no swapping space or
   a decimal number between 2000 and 40000>,NUMSWP)]>)
	RADIX 8
	CALL COMNDX
	 SKIPA			;GIVE ERROR IF PARSE FAILED
	SKIPGE T2		; AND IN RANGE
	ERROR CREAT3,<Invalid decimal number>
	JUMPE T2,CRT3A		;ZERO IS OK
	CAIG T2,^D40000		;VALIDATE RANGE
	CAIGE T2,^D2000
	ERROR CREAT3,<Swapping space value not in range 2000. to 40000.>
CRT3A:	MOVEM T2,NPG4SW		;SAVE FOR LATER
	CALL CMDEOL
	 JRST CREAT3
CREAT4:	HRROI T1,[ASCIZ /Number of pages to allocate for the Front End File System? /]
	CALL CMDINI		;PRINT PROMPT
	RADIX 10
	FORS. (DEFPFS,<NUMFES>,<
		MOVEI T1,[FLDDB.(.CMNUM,CM%SDH,^D10,<0 for no front end file system or
   a decimal number between 250 and 10000>,NUMFES)]>)
	RADIX 8
	CALL COMNDX
	 SKIPA			;GIVE ERROR IF PARSE FAILED
	SKIPGE T2
	ERROR CREAT4,<Invalid decimal number>
	JUMPE T2,CRT4A		;ZERO IS OK
	CAIG T2,^D10000		;CHECK RANGE
	CAIGE T2,^D250
	ERROR CREAT4,<Value not in range 250. to 10000.>
CRT4A:	MOVEM T2,NPGFES		;SAVE NUMBER
	CALL CMDEOL
	 JRST CREAT4		;TRY AGAIN
	GJINF			;GET USER NAME
	MOVE T2,T1
	HRROI T1,NAMBUF
	MOVEM T1,FCNBLK+.CMDEF	;SET UP DEFAULT POINTER
	DIRST			; INTO NAMBUF
	 ERJMP JSHALT		;[39] Should never happen
	MOVX T1,<FLD(.CMFLD,CM%FNC)+<CM%SDH!CM%HPP!CM%DPP>>
	MOVEM T1,FCNBLK		;SETUP FCN
	SETZM FCNBLK+.CMDAT	;NO XTRA DATA
	HRROI T1,[ASCIZ "Name of user owning structure"] ;[39]
	MOVEM T1,FCNBLK+.CMHLP	;SETUP HELP TEXT
CREAT5:	HRROI T1,[ASCIZ "Owner name? "]
	CALL CMDINI		;PROMPT
	MOVEI T1,FCNBLK		;SETUP SPECIAL FUCNTION BLOCK
	CALL COMNDX		;GET RESPONSE
	 ERROR CREAT5,<Invalid owner name string>
	HRROI T2,ATMBUF		;RESPONSE
	HRROI T1,OWNRID		;COPY TO OWNER ID
	MOVEI T3,^D14		;MAX CHARS
	MOVEI T4,0		;OR NULL (WHICHEVER COMES FIRST)
	SOUT
	SKIPN T3
	ERROR CREAT5,<Name string greater than 12. characters>
	CALL CMDEOL		;GRNTEE EOL
	 JRST CREAT5
CREAT6:	HRROI T1,[ASCIZ /Is this a system structure for startup? /]
	CALL YESNO
	JUMPE T1,[SETZ T2,	;NO, DON'T NEED CPU SERIAL NUMBER
		  JRST CRT6A]
CREAT7:	HRROI T1,[ASCIZ /Serial number of CPU started from this structure? /]
	CALL CMDINI		;PRINT PROMPT
	MOVEI T1,[FLDDB.(.CMNUM,CM%SDH,^D10,<Serial number of CPU or carriage return for this CPU>,0)]
	CALL COMNDX
	 ERROR CREAT6,<Invalid decimal number>
	MOVEM T2,CPUSER		;save serial number
	CALL CMDEOL		;confirmed?
	 JRST CREAT7		;no, try again
	SKIPGE CPUSER		;non negitive number given?
	 JRST [	TMSG <?Serial number must be non-negitive> ;no, write a message
		JRST CREAT7]	;try again
	SKIPE CPUSER		;yes, was a serial number given?
	 JRST CRT6A		;yes, have serial number, don't get this APR
	MOVEI T1,.APRID		;want APR serial number
	GETAB			;get it
	 ERROR RESTRT,<Couldn't get APR serial number>
	MOVEM T1,CPUSER		;store serial number

;NOW TRY TO INIT/MOUNT THE STRUCTURE

CRT6A:	HRROI T1,UNITID		;SETUP UNIT ID STRING
	HRROI T2,STRNAM		;TO BE STRUCTURE NAME
	MOVEI T3,0
	SOUT			;...
	HRROI T1,DIRNAM		;ALIAS TEXT STRING
	MOVEM T1,MNTBLK+.MSIAL	;SET UP ALIAS
	MOVX T1,<FLD(.MSCRE,MS%FCN)+MS%XCL>
	CALL STRINI		;INIT STRUCTURE
	 JRST PARSE1		;FAILED
	JRST RESTRT		;OK - GET NEXT COMMAND
;ROUTINE TO GET CHANNEL, CONTROLLER, AND UNIT NUMBERS FOR A DRIVE.
; C(Q1) := POINTER TO 3-WORD DRIVE INFO BLOCK
; C(Q2) := NUMBER OF UNITS

GETUNT:	HRROI T2,[ASCIZ /DECIMAL Channel, Controller, and Unit number: /]
	HRROI T1,TMPBUF
	MOVEI T3,0
	SOUT
	MOVEI Q2,1		;ONE UNIT
	JRST GETUN1		;JOIN COMMON CODE

GETUNI:	HRROI T2,[ASCIZ /DECIMAL Channel, Controller, and Unit numbers for logical unit /]
	HRROI T1,TMPBUF		;TEMP BUFFER
	MOVEI T3,0
	SOUT
	HRRZ T2,MNTBLK+.MSINU	;CALC UNIT #
	SUB T2,Q2
	MOVEI T3,^D10		;DECIMAL
	NOUT
	 JFCL
	HRROI T2,[ASCIZ /: /]
	MOVEI T3,0
	SOUT
GETUN1:	HRROI T1,TMPBUF		;POINT TO GENERATED PROMPT
	CALL CMDINI		;PRINT PROMPT
	CALL SPCNUM		;SPECIAL NUMBER ROUTINE
	 JRST GETUN1		;ERROR RETURN
	CAIG T2,7		;CHECK RANGE
	CAIGE T2,0
	 ERROR GETUN1,<Channel number not in range 0-7>
	MOVEM T2,.MSICH(Q1)	;STORE IN PROPER PLACE
	MOVEI T1,[FLDDB.(.CMCMA)]
	CALL COMNDX
	 ERROR GETUN1,<Comma expected between channel and controller numbers>
	CALL SPCNUM		;GET CONTROLLER NUMBER
	 JRST GETUN1		;INVALID
	CAML T2,[-1]		;VERIFY NOT TOO SMALL
	CAILE T2,17		;OR TOO LARGE
	 ERROR GETUN1,<Controller number not in range -1 to 15>
	MOVEM T2,.MSICT(Q1)	;STORE IT
	MOVEI T1,[FLDDB.(.CMCMA)]	;WANT ANOTHER COMMA
	CALL COMNDX		;GET IT
	 ERROR GETUN1,<Comma expected between controller and unit numbers>
	CALL SPCNUM		;GET UNIT NUMBER
	 JRST GETUN1		;INVALID NUMBER
	SKIPL T2		;VERIFY RANGE
	CAILE T2,377		;TO BE REASONABLE
	 ERROR GETUN1,<Unit number not in range 0-255>
	MOVEM T2,.MSIUN(Q1)	;STORE IT
	CALL CMDEOL		;GRNTEE EOL
	 JRST GETUN1		;ERROR
	RET			;OK - RETURN
;SPECIAL NUMBER ROUTINE WITH VERY LONG HELP TEXT

SPCNUM:	MOVX T1,<FLD(.CMNUM,CM%FNC)+CM%HPP!CM%SDH>
	MOVEM T1,FCNBLK		;SETUP FUNCTION
	HRROI T1,HBUF		;POINT TO HELP TEXT
	MOVEM T1,FCNBLK+.CMHLP
	MOVEI T1,^D10		;SETUP RADIX
	MOVEM T1,FCNBLK+.CMDAT
	SETZM FCNBLK+.CMDEF	;NO DEFAULT
	MOVEI T1,FCNBLK		;T2/ FUNCTION BLOCK
	CALL COMNDX
	 SKIPA			;FAILED
	RETSKP			;GOOD RETURN
	TMSG <
?Invalid decimal number
>
	RET			;ERROR RETURN
;ROUTINE TO SETUP STRING CONTAINING AVAILABLE UNIT INFO

CNFINF:	SAVEQ			;SAVE Q1-Q3
	HRROI Q1,HBUF		;POINT TO BUFFER BEG
	MOVE T1,Q1		;GET FIRST STRING
	HRROI T2,HHDR		;POINT TO HEADER
	MOVEI T3,0
	SOUT
	MOVEM T1,Q1		;SAVE PNTR SO FAR

	SETOM RNUBLK+.MSRCH	;INIT FOR FIRST UNIT
	SETOM RNUBLK+.MSRCT
	SETOM RNUBLK+.MSRUN
CNFIN1:	CALL GTUSTS		;GET UNIT STATUS
	 JRST CNFIN3		;NO MORE - DONE
	MOVE Q2,RNUBLK+.MSRST	;GET STATUS
	TXNE Q2,MS%MNT		;MOUNTED STR?
	JRST CNFIN1		;YES IGNORE
	MOVSI T1,-UNTYTN	;GET READY FOR SEARCH
	LDB T2,[POINTR (Q2,MS%TYP)]	;GET THIS UNIT'S TYPE
CNFIN4:	HLRZ T3,UNTYTB(T1)	;GET NEXT TABLE ENTRY
	CAME T2,T3		;FOUND THE UNIT TYPE YET?
	AOBJN T1,CNFIN4		;NO, KEEP LOOKING
	HRRO T2,UNTYTB(T1)	;CREATE POINTER TO TYPE STRING
	MOVE T1,Q1		;GET OUTPUT POINTER
	MOVEI T3,0
	SOUT			;DUMP IT
	MOVE T2,RNUBLK+.MSRCH	;GET CHANNEL NUMBER
	MOVE T3,[NO%LFL+<6,,^D10>] ;DECIMAL OUTPUT FILLED IN 6 COLUMNS
	NOUT			;CONVERT TO NUMBER
	 JFCL
	MOVE T2,RNUBLK+.MSRCT	;GET CONTROLLER NUMBER
	MOVE T3,[NO%LFL+<^D11,,^D10>] ;DECIMAL FILLED IN 11 COLUMNS
	NOUT			;TYPE IT
	 JFCL
	MOVE T2,RNUBLK+.MSRUN	;GET UNIT NUMBER
	MOVE T3,[NO%LFL+<^D9,,^D10>] ;DECIMAL FILLED IN 9 COLUMNS
	NOUT
	 JFCL
	MOVEI T3,4
	CALL SPACN		;MOVE OVER
	HRROI T2,NAMBUF		;ASSUME STR NAME
	TXNE Q2,MS%HBB		;VALID HOME BLOCKS?
	HRROI T2,[ASCIZ "Bad home blocks"]
	TXNE Q2,MS%DIA		;MAINT MODE?
	HRROI T2,[ASCIZ "Maintenance mode"]
	TXNE Q2,MS%OFL		;OFF-LINE
	HRROI T2,[ASCIZ "Off-line"]
	MOVEI T3,^D20		;MAX CHARS
	MOVEI T4,0		;TERMINATOR
	SOUT			;DUMP STRING SO FAR

; NEXT PAGE .....
; ....
	MOVNI T2,1		;BACKUP OVER NULL
	ADJBP T2,T1
	MOVE T1,T2		;RESTORE BP
	AOS T3			;ACCOUNT FOR IT
	CALL SPACN		;T3 HAS CHARS REMAINING
	TXNE Q2,MS%DIA!MS%OFL!MS%HBB
	JRST CNFIN2		;NO MORE INFO
	HLRZ T2,RNUBLK+.MSRNS	;GET LOGICAL UNIT #
	MOVEI T3,12		;DECIMAL
	NOUT
	 JFCL
	MOVEI T2," "
	IDPB T2,T1		;PUT IN SPACE
	MOVEI T2,"("
	IDPB T2,T1		;AND PAREN
	HLRZ T2,RNUBLK+.MSRNS	;GET UNIT # AGAIN
	AOS T2			;CHANGE TO ORDINAL
	NOUT			;DUMP IT
	 JFCL
	HRROI T2,[ASCIZ " of "]
	MOVEI T3,0
	SOUT
	HRRZ T2,RNUBLK+.MSRNS	;GET # OF UNITS IN STR
	MOVEI T3,^D10
	NOUT			;DUMP IT
	 JFCL
	MOVEI T2,")"		;CLOSE PAREN
	IDPB T2,T1
CNFIN2:	MOVEI T2,15		;CR
	IDPB T2,T1		;OUTPUT
	MOVEI T2,12		;LF
	IDPB T2,T1
	MOVEM T1,Q1		;SAVE PNTR
	JRST CNFIN1		;GET NEXT

CNFIN3:	MOVEI T2,15		;XTRA CRLF
	IDPB T2,Q1
	MOVEI T2,12
	IDPB T2,Q1		;...
	MOVEI T2,0		;TIE OFF STRING
	IDPB T2,Q1
	RET			;RETURN
;UNIT INFO TABLES

UNTYTB:	1,,[ASCIZ/RP04/]	;1 - RP04
	5,,[ASCIZ/RP05/]	;5 - RP05
	6,,[ASCIZ/RP06/]	;6 - RP06
	7,,[ASCIZ/RP07/]	;7 - RP07
	11,,[ASCIZ/RM03/]	;11 - RM03
	24,,[ASCIZ/RP20/]	;24 - RP20
	27,,[ASCIZ/RA80/]	;27 - RA80
	30,,[ASCIZ/RA81/]	;30 - RA81
	31,,[ASCIZ/RA60/]	;31 - RA60
	0,,[ASCIZ/UNK /]	;LAST ENTRY IS CATCH-ALL FOR UNKNOWNS

	UNTYTN==.-UNTYTB-1	;NUMBER OF REAL ENTRIES

;HELP MESSAGE HEADER

HHDR:	ASCIZ "

Triple of decimal numbers from one of the following:

Type  Channel  Controller  Unit  Structure name      Logical unit
----  -------  ----------  ----  --------------      ------------

"
	SUBTTL Check Command 

;COMMON ROUTINE FOR CHECK COMMAND

.CHECK:	MOVEI T1,[FLDDB.(.CMKEY,,CKTAB)]	;SECONDARY KEYTABLE
	CALL COMNDX
	 ERROR PARSE1,<Not a CHECKD command>
	HRRZ T1,(T2)		;GET DISPATCH
	JRST (T1)		;PROCESS

;CHECK COMMAND KEYWORD TABLE

CKTAB:	XWD CKSIZ,CKMAX
	TB (.BITAB,BITTABLE)	;CHECK BITTABLE CONSISTENCY
	TB (.DIREC,DIRECTORY)	;CHECK DIRECTORY CONSISTENCY

CKSIZ=.-CKTAB-1
CKMAX=CKSIZ
;CHECK (CONSISTENCY OF) BITTABLE

;USER WANTS TO CHECK BIT TABLE.
;  THIS IS THE STANDARD OPTION WHEN RUNNING FROM JOB 0.
;GET CONFIRMATION.  USE DEFAULT FLAG SETTINGS.

.BITAB:	HRROI T1,[ASCIZ /CONSISTENCY OF/]
	CALL CMDNOI		;NOISE WORDS
	CALL CONFRM		;GET STR AND CONFIRM
	CALL PSCHK		;SEE IF THIS IS PS:
	 CALL XMNT		;NO - MOUNT FOR EXCLUSIVE ACCESS
	CALL SETSTR		;SET CURRENT STR ETC.
	SETOM WRTLPF		;TURN ON LOST-PAGES FILE
	CALL QDONE		;SCAN DIRECTORIES
	SKIPN PSFLG		;WAS THIS THE REAL PS:
	 JRST RESTRT		;NO - RESTART CHECKD
	SKIPE WRTLPF		;STILL FOUND ERRORS?
	CALL CLRCDE		;PS IS OK - CLEAR MONITOR FLAGS
	JRST RESTRT		; AND RESTART
;CHECK (CONSISTENCY OF) DIRECTORY

;USER WANTS TO CHECK DIRECTORY CONSISTENCY.  GET CONFIRMATION

.DIREC:	HRROI T1,[ASCIZ /CONSISTENCY OF/]
	CALL CMDNOI		;GUIDE WORDS
	CALL CONFRM		;GET STR AND CONFIRM
	CALL PSCHK		;SEE IF THE PS:
	 CALL XMNTA		;NO - CHECK MOUNTED
	CALL SETSTR		;SET CURRENT STR

;GET THE FIRST DIRECTORY NUMBER AND STORE IT IN DIRNUM

	CALL FRSDIR		;GET FIRST DIRECTORY
	 JRST RESTRT		;FAILED.

;HAVE A DIRECTORY NUMBER. CHECK DIRECTORY'S CONSISTENCY

.DIRLP:	CALL GDNAM		;GET THE DIRECTORY NAME
	 JRST .DIRL1		;SKIP IF ERROR
	CALL CKDIR		;CHECK AND REBUILD IF NECESSARY
.DIRL1:
	CALL NXTDIR		;GET THE NEXT DIRECTORY
	 JRST RESTRT		;FAILED OR DONE. START OVER
	JRST .DIRLP
	SUBTTL Edit Command

;BAT BLOCK EDITOR

.EDIT:	HRROI T1,[ASCIZ /BAT BLOCKS FOR/]
	CALL CMDNOI		;TYPE THE NOISE
	CALL CONFRM		;GET THE STRUCTURE
	CALL PSCHK		;SEE IF IT WAS PS
	 CALL XMNT		; EXCLUSIVE MOUNT IT
	CALL SETSTR		;SET UP INFO WE NEED
	CALL HOMEIN		;READ HOME BLOCKS
	 JRST RESTRT		; ONLY ON AN ERROR
	CALL BATIN		;READ USEFUL BAT BLOCK INFO
	SETOM BEMFLG		;INDICATE WE ARE HERE
	JRST BATWRK		;EDIT THE BAT BLOCKS, PLEASE
	SUBTTL Enable/Disable Commands

;ENABLE / DISABLE

.DSABL:	SETZM ENAFLG		;INDICATE THIS IS A DISABLE
	JRST ENABL1

.ENABL:	SETOM ENAFLG		;INDICATE THIS IS AN ENABLE

ENABL1:	MOVEI T1,[FLDDB.(.CMKEY,,ENTAB)]	;SECONDARY KEYTABLE
	CALL COMNDX
	 ERROR PARSE1,<Not a CHECKD command>
	HRRZ T1,(T2)		;GET DISPATCH
	JRST (T1)		;PROCESS

;ENABLE COMMAND KEYWORD TABLE

ENTAB:	XWD ENASIZ,ENAMAX
	TB (.AUTOS,AUTOMATIC-STARTUP) ;ENABLE SYSTEM STRUCTURE
	TB (.BATUP,BAT-BLOCK-DELETE)
	TB (.BOOTP,BOOT-PARAMETERS)
	TB (.DCARE,DON'T-CARE,CM%INV)
	TB (.ECC,ECC-ERROR-MARKING)
	TB (.UNLMT,LARGE-DIRECTORIES)
	TB (.LGSTR,LOGIN-STRUCTURE) ;[7.1112]
	TB (.PSENC,PASSWORD-ENCRYPTION)
	TB (.SOFT,SOFT-ERROR-MARKING)
	TB (.WRITE,WRITE-VERIFICATION)
ENASIZ=.-ENTAB-1
ENAMAX=ENASIZ
;ENABLE STRUCTURE FOR AUTOMATIC STARTUP BY SETTING CPU SERIAL NUMBER INTO
; THE HOME BLOCK(S)

.AUTOS:	HRROI T1,[ASCIZ /FROM STRUCTURE/]
	CALL CMDNOI		;NOISE WORDS
	CALL CONFRM		;GET STRUCTURE AND CONFIRM
	CALL SETSTR		;SET UP WORKING STRUCTURE INFO
	CALL HOMEIN		;READ HOME BLOCKS OF FIRST PACK
	 JRST RESTRT		;BAD BLOCKS
	SKIPN T2,ENAFLG		;IS THIS DISABLE?
	JRST AUTOS2		;YES, DON'T ASK FOR CPU SERIAL NUMBER
AUTOS1:	HRROI T1,[ASCIZ /Serial number of CPU to startup? /]
	CALL CMDINI		;PRINT PROMPT
	MOVEI T1,[FLDDB.(.CMNUM,CM%SDH,^D10,<Serial number of CPU or carriage return for this CPU>,0)]
	CALL COMNDX
	 ERROR AUTOS1,<Invalid decimal number>
	JUMPN T2,AUTOS2		;HAVE SERIAL NUMBER
	MOVE T1,[SIXBIT /APRID/]
	SYSGT			;GET CPU SERIAL NUMBER
	MOVE T2,T1		;USE T2 SINCE JUMPN ABOVE USES T2
AUTOS2:	MOVEM T2,HOMARG+.MSHVL	;STORE SERIAL NUMBER
	HRROI T1,STRNAM		;GET POINTER TO STRUCTURE NAME
	MOVEM T1,HOMARG+.MSHNM	;STORE STRUCTURE BEING MODIFIED
	MOVEI T1,HOMSER		;WORD WE WANT TO MODIFY
	MOVEM T1,HOMARG+.MSHOF
	SETOM HOMARG+.MSHMK	;CHANGING ENTIRE WORD
	DMOVE T1,[EXP <4,,.MSHOM>,HOMARG]
	MSTR			;MODIFY HOME BLOCK
	 ERCAL JSERR0		;FAILED. PRINT REASON
	JRST RESTRT		;RESTART
;SET/CLEAR BATBLOCK ENTRY DELETE FLAG

.BATUP:	HRROI T1,[ASCIZ /ON DISK VERIFICATION/]
	CALL CMDNOI		;NOISE WORDS
	MOVEI T1,[FLDDB.(.CMCFM)];CONFIRMATION ONLY
	CALL COMNDX
	 ERROR PARSE1,<Invalid command confirmation>
	MOVE T1,ENAFLG		;GET ENABLE/DISABLE FLAG
	MOVEM T1,BATFLG		;SAVE THE STATUS
	JRST RESTRT
;Enable/Disable BOOT parameters


BPTAB:	XWD BPSIZ,BPSIZ
	TF (BT%HOD,HALT-ON-DUMP-ERRORS)
	TF (BT%RPM,READ-PARAMETERS)
	BPSIZ=.-BPTAB-1
	;Flags for parameters


.BOOTP:	HRROI T1,[ASCIZ /FOR STRUCTURE/]
	CALL CMDNOI		;NOISE WORDS
	CALL GETSTR		;GET STRUCTURE NAME
	CALL STSTRN		;SETUP STRUCTURE DATA
	SETZM P6		;ZERO MASK WORD
	HRROI T1,[ASCIZ/PARAMETER/]
	CALL CMDNOI		;NOISE WORDS
PARMLP:	MOVEI T1,[FLDDB.(.CMKEY,,BPTAB,,,FDCC)]
	CALL COMNDX
	 ERROR PARSE1,<Not a valid parameter>
	HRRZS T3		;Get right-half only
	LOAD T3,CMFNC,0(T3)	;Good parse, get our function code
	CAIE T3,.CMKEY		;Was it a keyword?
	JRST NOTKEY		;No, try for something else
	HRRZ T2,(T2)		;Get pointer to the bit
	TDO P6,(T2)		;Set the bit
	JRST PARMLP		;Back for more
NOTKEY:	CAIN T3,.CMCMA		;Comma?
	JRST PARMLP		;Yes, back for more
	CAIE T3,.CMCFM		;Did he confirm?
	 ERROR PARSE1,<Not a valid parameter>


BPSTOR:	CALL HOMEIN		;READ HOME BLOCKS OF FIRST PACK
	 JRST RESTRT		;BAD BLOCKS
	MOVE T1,BATBUF+HOMBTF	;Get existing bits
	TDO T1,P6		;Assume we are setting
	SKIPN ENAFLG		;Are we setting?
	TDZ T1,P6		;No, so clear
	MOVEM T1,HOMARG+.MSHVL	;Store bits
	HRROI T1,STRNAM		;GET POINTER TO STRUCTURE NAME
	MOVEM T1,HOMARG+.MSHNM	;STORE STRUCTURE BEING MODIFIED
	MOVEI T1,HOMBTF		;WORD WE WANT TO MODIFY
	MOVEM T1,HOMARG+.MSHOF
	SETOM HOMARG+.MSHMK	;CHANGING ENTIRE WORD
	DMOVE T1,[EXP <4,,.MSHOM>,HOMARG]
	MSTR			;MODIFY HOME BLOCK
	 ERCAL JSERR0		;FAILED. PRINT REASON
	JRST RESTRT		;RESTART
;LIMIT/UNLIMIT (NUMBER OF FILES PER DIRECTORY ON STRUCTURE

.UNLMT:	MOVX T1,MS%LIM		;GET THE BIT TO ASSUME DISABLE (LIMIT)
	SKIPE ENAFLG		;WAS IT ENABLE
	SETZ T1,		;YES, CLEAR THE BIT INSTEAD
	STKVAR <NEWVAL>
	MOVEM T1,NEWVAL
	HRROI T1,[ASCIZ /ON STRUCTURE/]
	CALL CMDNOI		;NOISE WORDS
	CALL CONFRM		;GET STR AND CONFIRM
	CALL SETSTR		;SET CURRENT STR
	CALL HOMEIN		;READ HOME BLOCKS (OF FIRST PACK)
	 JRST RESTRT		;GIVE UP IF CAN'T
	MOVE T2,HFLAGS	;GET OLD VALUE OF LIMIT BIT
	HRROI T1,[ASCIZ /[Large directories were allowed]
/]
	TXNE T2,MS%LIM		;ANNOUNCE OLD VALUE
	HRROI T1,[ASCIZ /[Large directories were not allowed]
/]
	PSOUT
	HRROI T1,STRNAM		;GET POINTER TO STRUCTURE NAME
	MOVEM T1,HOMARG+.MSHNM	;STORE STRUCTURE BEING MODIFIED
	MOVEI T2,HOMFLG		;WORD WE WANT TO MODIFY
	MOVE T3,NEWVAL		;GET NEW VALUE FOR MS%LIM BIT
	MOVX T4,MS%LIM		;SPECIFY WHICH BIT TO MODIFY
	DMOVEM T1,HOMARG	;STORE ARGS IN ARG BLOCK
	DMOVEM T3,HOMARG+.MSHVL
	DMOVE T1,[EXP <4,,.MSHOM>,HOMARG]
	MSTR			;MODIFY HOME BLOCK
	 ERCAL JSERR0		;FAILED, PRINT REASON
	JRST RESTRT		;RESTART
;SET/CLEAR SOFT ERROR DURING VERIFY PHASE MARKING

.SOFT:	CALL SFTECC		;DO THE WORK
	MOVEM T1,SOFTFL		;SAVE THE STATUS
	JRST RESTRT

;HERE TO ENABLE /DISABLE ECC ERROR COUNTING

.ECC:	CALL SFTECC		;DO THE WORK
	MOVEM T1,ECCFLG		;SAVE THE STATUS
	JRST RESTRT

SFTECC:	HRROI T1,[ASCIZ /DURING VERIFICATION OF DISK SURFACE/]
	CALL CMDNOI
	MOVEI T1,[FLDDB.(.CMCFM)]
	CALL COMNDX
	 ERROR PARSE1,<Invalid command confirmation>
	MOVE T1,ENAFLG		;GET ENABLE/DISABLE FLAG
	RET
;ENABLE/DISABLE WRITE VERIFICATION ON DISK

;CHOICES ARE ENABLE/DISABLE WRITE OF SWAP/DATA/BOTH/NONE ON STR FOO

.WRITE:	STKVAR <BITMSK,BITVAL>	;MASK OF BITS TO CHANGE, NEWVALUE
	HRROI T1,[ASCIZ /OF/]
	CALL CMDNOI		;NOISE WORDS
	MOVEI T1,[FLDDB. (.CMKEY,,WRTTAB)] ;GET KEYWORD TABLE
	CALL COMNDX		;PARSE THE NEXT KEYWORD
	 ERROR PARSE1,<Not a CHECKD command>
	HRRZ T1,(T2)		;GET DISPATCH
	JRST (T1)		;AND GO THERE

WRTTAB:	XWD WRTSIZ,WRTSIZ
	TB (.DATA,DATA)		;DATA SPACE
	TB (.SWAP,SWAPPING)	;SWAP SPACE
WRTSIZ=.-WRTTAB-1		;SIZE OF THE TABLE

.SWAP:	MOVX T1,MS%RWS		;READ AFTER WRITE FOR SWAP
	SKIPA			;INTO COMMON CODE
.DATA:	MOVX T1,MS%RWD		;READ AFTER WRITE FOR DATA
	MOVEM T1,BITMSK		;SAVE FOR LATER
	AND T1,ENAFLG		;SEE IF WE ARE SETTING FUNCTIONALITY
	MOVEM T1,BITVAL		;REMEMBER ENABLE/DISABLE
	HRROI T1,[ASCIZ /ON STRUCTURE/]
	CALL CMDNOI		;NOISE WORDS
	CALL CONFRM		;GET STRUCTURE AND CONFIRM
	CALL SETSTR		;SET UP STRUCTURE
	CALL HOMEIN		;READ HOME BLOCKS OF STR
	 JRST RESTRT		;ON AN ERROR, GO BACK TO PROMPT
	MOVE T1,BITMSK		;MASK OF BIT TO CHANGE
	MOVEM T1,HOMARG+.MSHMK	;ONLY THIS BIT ALLOWED
	MOVE T1,BITVAL		;GET STATE OF BIT
	MOVEM T1,HOMARG+.MSHVL	;VALUE TO USE FOR FLAG
	HRROI T1,STRNAM		;POINTER TO STRUCTURE NAME
	MOVEM T1,HOMARG+.MSHNM
	MOVEI T1,HOMFLG		;WORD TO MODIFY
	MOVEM T1,HOMARG+.MSHOF
	DMOVE T1,[ XWD 4,.MSHOM
		   HOMARG]	;SET UP HEADER
	MSTR			;MODIFY THE HOME BLOCKS
	 ERCAL JSERR0		;REASON FOR FAILURE
	JRST RESTRT		;ALL DONE WITH THIS
;ENABLE/DISABLE STRUCTURE FOR DON'T CARE IF DISK PORTED TO UNKNOWN SYSTEM


.DCARE:	STKVAR <BITMSK,BITVAL>	;MASK OF BITS TO CHANGE, NEWVALUE
	SETOM BITMSK		;THE WHOLE WORD IS USED
	MOVE T1,[SIXBIT/DONOCA/];GET THE NAME TO USE
	AND T1,ENAFLG		;SEE IF WE ARE SETTING THE FUNCTION
	MOVEM T1,BITVAL		;REMEMBER ENABLE/DIABLE
	HRROI T1,[ASCIZ /IF PORTED TO UNKNOWN SYSTEM ON STRUCTURE/]
	CALL CMDNOI		;NOISE WORDS
	CALL CONFRM		;GET STRUCTURE AND CONFIRM
	CALL SETSTR		;SET UP STRUCTURE
	CALL HOMEIN		;READ HOME BLOCKS OF STR
	 JRST RESTRT		;ON AN ERROR, GO BACK TO PROMPT
	MOVE T1,BITMSK		;MASK OF BIT TO CHANGE
	MOVEM T1,HOMARG+.MSHMK	;ONLY THIS BIT ALLOWED
	MOVE T1,BITVAL		;GET STATE OF BIT
	MOVEM T1,HOMARG+.MSHVL	;VALUE TO USE FOR FLAG
	HRROI T1,STRNAM		;POINTER TO STRUCTURE NAME
	MOVEM T1,HOMARG+.MSHNM
	MOVEI T1,HOMDCF		;WORD TO MODIFY
	MOVEM T1,HOMARG+.MSHOF
	DMOVE T1,[ XWD 4,.MSHOM
		   HOMARG]	;SET UP HEADER
	MSTR			;MODIFY THE HOME BLOCKS
	 ERCAL JSERR0		;REASON FOR FAILURE
	JRST RESTRT		;ALL DONE WITH THIS
;.[7.1112]
;
; .LGSTR:
;
; This routine implements the ENABLE/DISABLE LOGIN-STRUCTURE command.
; It either enters a CPU serial number into, or removes a serial
; number from words HOMLS1, HOMLS2. HOMLS3, or HOMLS4 of a given
; structure's home blocks.
; Call:
;	JRST .LGSTR
; with:
;	ENAFLG/   0 to remove a serial number, -1 to add
; Returns:
;	To lable RESTRT, always
;
MINAPR==^D1025			;Minimum CPU serial number
MAXAPR==^D4095			;Maximum CPU serial number
.LGSTR:	STKVAR <CPUNUM>		;For saving serial number
	HRROI T1,[ASCIZ /FOR STRUCTURE/]
	CALL CMDNOI		;Noise words
	CALL GETSTR		;Get the structure name
	HRROI T1,[ASCIZ/FOR CPU/]
	CALL CMDNOI		;Parse guide words
	MOVEI T1,[FLDDB.(.CMNUM,CM%SDH,^D10,<CPU serial	number>,,[FLDDB.(.CMCFM,CM%SDH,,<or carriage for local CPU>,,)])]
	CALL COMNDX
	 ERROR AUTOS1,<Invalid decimal number>
	HRRZS T3		;Get FDB used
	LDB T1,[POINT 9,.CMFNP(T3),8] ;Get function code
	CAIE T1,.CMCFM		;Just confirmed?
	IFSKP.			;Yes...
	  HRRZI T1,.APRID	;Get processor serial number
	  GETAB%		; from system tables
	   JSERR		;Failed?
	  MOVEM T1,CPUNUM	;Save serial number
	ELSE.			;Got a decimal number
	  MOVEM T2,CPUNUM	;Save CPU serial number
	  CALL CMDEOL		;Confirm command
	   JRST PARSE1		;Failed
	  MOVE T2,CPUNUM	;Fetch serial number'
	  CAIL T2,MINAPR	;Too small?
	  CAILE T2,MAXAPR	;Or too large?
	  IFNSK.		;Yes...
	    ERROR (RESTRT,<CHECKD: CPU serial number must be between 1025 and 4095>)
	  ENDIF.
	ENDIF.			;Join common code
	CALL STSTRN		;()Set up structure info
	CALL HOMEIN		;()Read home block into
	 JRST RESTRT		;Failed. Do next command
	MOVSI T4,-LGSLEN	;Number of home block words
	HRRI T4,BATBUF+HOMLS1	;Address of first word to check
;
; If we are enabling, scan through the Login Structure words in the Home
; Block and see if the given serial number is already there.
;
	SKIPN ENAFLG		;Enabling?
	IFSKP.			;If yes...
	  MOVE T1,T4		;Get AOBJN pointer
ENALOP:	  HLRZ T2,(T1)		;Get LH of word
	  HRRZ T3,(T1)		;And right half of word
	  CAME T2,CPUNUM	;Is this the requested number
	  CAMN T3,CPUNUM	;Or is this?
	  JRST RESTRT		;Yes. Then it's been done!
	  AOBJN T1,ENALOP	;Check all words
	ENDIF.			;
;
; Do the actual DISABLE or ENABLE
;
LGSLOP:	MOVE T1,(T4)		;Get home block word to check
	HLRZ T2,T1		;Get LH of word T2
	HRRZ T3,T1		;And RH in T3
	SKIPN ENAFLG		;Are we enabling?
	IFSKP.			;If yes...
	  SKIPE T2		;Is LH available?
	  IFSKP.		;If so, then use it
	    MOVE T2,CPUNUM	;Get number to store
	    HRL T1,T2		;Make new word
	    JRST LGSHOM		;Go place in home blocks
	  ENDIF.		;
	  SKIPE T3		;Is RH available
	  IFSKP.		;If so, then use it
	    MOVE T3,CPUNUM	;Get CPU to use
	    HRR T1,T3		;Make new home block word
	    JRST LGSHOM		;Go stick it in
	  ENDIF.		;
	ELSE.			;If disabling...
	  CAME T2,CPUNUM	;Does LH match CPU number?
	  IFSKP.		;If so, clear out LH
	    HRRZS T1		;Zero LH of home block word
	    JRST LGSHOM		;Go write new word
	  ENDIF.		;
	  CAME T3,CPUNUM	;Does RH match CPU number?
	  IFSKP.		;If so, clear out RH
	    HLLZS T1		;Zero RH of home block word
	    JRST LGSHOM		;Go write new word
	  ENDIF.		;
	ENDIF.			;
	AOBJN T4,LGSLOP		;Loop through all home block words
	SKIPE ENAFLG		;Are we enabling
	ERROR (RESTRT,<CHECKD: No space in Home Block for serial number>) ;Enabling
	ERROR (RESTRT,<CHECKD: Serial number not found in Home Block>) ;Disabling
;
; T4 contains the home block word to change, T1 contains the new
; contents of that word.
;

LGSHOM:	MOVEM T1,HOMARG+.MSHVL	;Store new word in MSTR% argument block
	HRRZS T4		;Get address of home block word
	SUBI T4,BATBUF		;Get offset into home blocks
	MOVEM T4,HOMARG+.MSHOF	;Save in MSTR% block
	SETOM HOMARG+.MSHMK	;Mask of bits to change in word
	MOVE T1,STRDEV		;Get device designator of structure
	MOVEM T1,HOMARG+.MSHNM	;Stick in MSTR% argument block
	MOVE T1,[4,,.MSHOM]	;Length of arg block,,MSTR% function code
	MOVEI T2,HOMARG		;Address of arg block
	MSTR%			;Write the new home block word
	 ERCAL JSERR0		;Failed. Print error
	JRST RESTRT		;Finsihed
;ENABLE/DISABLE PASSWORD ENCRYPTION


.PSENC:	STKVAR <BITMSK,BITVAL>	;MASK OF BITS TO CHANGE, NEWVALUE
	MOVX T1,MS%CRY		;GET PASSWORD ENCRYPTION BIT
	MOVEM T1,BITMSK		;SAVE FOR LATER
	AND T1,ENAFLG		;SEE IF WE ARE SETTING FUNCTIONALITY
	MOVEM T1,BITVAL		;REMEMBER ENABLE/DISABLE
	HRROI T1,[ASCIZ /ON STRUCTURE/]
	CALL CMDNOI		;NOISE WORDS
	CALL CONFRM		;GET STRUCTURE AND CONFIRM
	CALL SETSTR		;SET UP STRUCTURE
	CALL HOMEIN		;READ HOME BLOCKS OF STR
	 JRST RESTRT		;ON AN ERROR, GO BACK TO PROMPT
	MOVE T1,BITMSK		;MASK OF BIT TO CHANGE
	MOVEM T1,HOMARG+.MSHMK	;ONLY THIS BIT ALLOWED
	MOVE T1,BITVAL		;GET STATE OF BIT
	MOVEM T1,HOMARG+.MSHVL	;VALUE TO USE FOR FLAG
	HRROI T1,STRNAM		;POINTER TO STRUCTURE NAME
	MOVEM T1,HOMARG+.MSHNM
	MOVEI T1,HOMFLG		;WORD TO MODIFY
	MOVEM T1,HOMARG+.MSHOF
	DMOVE T1,[ XWD 4,.MSHOM
		   HOMARG]	;SET UP HEADER
	MSTR			;MODIFY THE HOME BLOCKS
	 ERCAL JSERR0		;REASON FOR FAILURE
	JRST RESTRT		;ALL DONE WITH THIS
	SUBTTL Exit Command

;EXIT (TO MONITOR)

;USER WANTS TO QUIT.  GET CONFIRMATION AND EXIT

.EXIT:	HRROI T1,[ASCIZ /TO MONITOR/]
	CALL CMDNOI
	MOVEI T1,[FLDDB. (.CMCFM)] ;T1/ADDRESS OF FUNCTION DESCRIPTOR BLOCK
	CALL COMNDX		;GET CONFIRMATION
	 ERROR PARSE1,<Invalid command confirmation> ;NO
	CALL RESET
	JRST QUIT
	SUBTTL File-DDT Command

;FILE-DDT

;USER WISHES TO GET INTO THE ABSOLUTE DISK EDITOR, AND DO SOME MUNGING

.FILDT:	CALL FILDTX		;CALL THE REAL ROUTINE
	 JFCL			; IGNORE ANY ERRORS
	JRST PARSE1		; AND ON WITH THE WORK

FILDTX:	HRROI T1,[ASCIZ /THE DISKS/] ;NOISE WORDS
	CALL CMDNOI
	MOVEI T1,[FLDDB. (.CMCFM)]
	CALL COMNDX		; GET THE END OF LINE CONFIRM
	 ERROR R,<Invalid command confirmation>
	MOVX T1,GJ%OLD!GJ%SHT	; SHORT FORM JFN, OLD FILE
	HRROI T2,[ASCIZ /SYS:FILDDT.EXE/]
	CALL GETFRK
FILDTE:	 ERROR R,<Run of FILDDT failed>
	CALL RUNFRK
	 JRST FILDTE
	RETSKP
RUNFRK: MOVE T1,HANDLE		;GET THE FORK NUMBER
	SETZ T2,		;START AT NORMAL ADDRESS
	SFRKV			;DO IT.
	 ERJMP R
	WFORK			;WAIT FOR IT TO STOP
	 ERJMP R
	RFSTS			;GET STATUS AND PC OF FORK
	LDB T1,[POINTR (T1,RF%STS)]; STATUS CODE
	CAIE T1,3		;FORCED TERMINATION?
	JRST RUNFIN		;NO, OK
	TMSG <
?Error at PC >
	ANDI T2,-1		;PC ONLY
	MOVX T3,NO%LFL!NO%ZRO!<6,,10>
	CALL TTNOUT		;TYPE THE NUMBER AS A PC
	TMSG <: >
	MOVEI T1,.PRIOU
	HRLO T2,HANDLE
	SETZ T3,
	ERSTR			;DO IT
	 RET
	 RET
	TMSG <
>
	RETSKP

RUNFIN:	MOVE T1,HANDLE
	KFORK
	 ERJMP .+1
	SETZM HANDLE		;DONE
	RETSKP

GETFRK:	GTJFN			;GET A JFN ON THE FILE
	 ERJMP R
	MOVEM T1,RUNJFN		;SAVE FOR LATER
	MOVX T1,CR%CAP		;SET UP BITS TO KEEP CAPABILITIES
	CFORK			;CREATE AN INFERIOR
	 ERJMP R
	MOVEM T1,HANDLE		;SAVE THE HANDLE

	MOVS T1,T1		;PUT IN LEFT HALF
	HRR T1,RUNJFN		;GET JFN OF THE FILE
	GET			;READ IN THE PROG INTO THE FORK
	 ERJMP R
	SETZM RUNJFN		;CLEAR JFN SINCE NO LONGER OURS
	RETSKP			;RETURN
	SUBTTL Push Command

;PUSH (JUST LIKE FILDDT, BUT TO THE EXEC

.PUSH:	CALL PUSHX
	 JFCL
	JRST PARSE1

PUSHX:	HRROI T1,[ASCIZ /TO EXEC LEVEL/]
	CALL CMDNOI
	MOVEI T1,[FLDDB. (.CMCFM)] ;T1/ ADDRESS OF FDB
	CALL COMNDX
	 ERROR R,<Invalid command confirmation> ;NO. PRINT ERROR
PUSHEN:	MOVX T1,GJ%OLD!GJ%SHT
	HRROI T2,[ASCIZ /SYSTEM:EXEC.EXE/]
	CALL GETFRK
PUSHER:	 ERROR R,<Push to a new EXEC failed>
	CALL RUNFRK		; RUN IT
	 JRST PUSHER
	RETSKP

;HERE FOR AUTO PUSH

APUSH:	CALL DOPUSH		;DO THE REAL WORK
	DEBRK			;AND RETURN

DOPUSH:	SAVET			;SAVE THE TEMP AC'S
	TMSG <
[Pushing to a new EXEC]
>
	CALL PUSHEN		;PUSH TO EXEC NOW
	 RET			;RETURN TO CALLER, IGNORE ANY ERRORS
	RET
	SUBTTL Help Command

;HELP

;USER WANTS AN EXPLANATION.  GET CONFIRMATION AND PRINT HELP TEXT

.HELP:	MOVEI T1,[FLDDB. (.CMCFM)] ;T1/ ADDRESS OF FDB
	CALL COMNDX		;GET CONFIRMATION
	 ERROR PARSE1,<Invalid command confirmation> ;NO. PRINT ERROR
	MOVX T1,GJ%OLD!GJ%SHT!GJ%IFG	;[79]GET A JFN FOR THE HELP FILE
	HRROI T2,[ASCIZ /HLP:CHECKD.HLP/]
	GTJFN
	 JRST [	PNTERR (<GTJFN for the help file failed>)
		JRST PARSE1]
	MOVEM T1,INJFN		;SAVE THE JFN NUMBER
	HRRZ T1,T1		;[79]
	MOVE T2,[7B5!OF%RD]	;READ THE FILE 7 BITS AT A TIME
	OPENF
	 JRST [	PNTERR (<OPENF for the help file (HLP:CHECKD.HLP) failed>)
		JRST PARSE1]
HELP1:	HRRZ T1,INJFN		;[79] GET JFN FOR INPUT
	BIN			;READ THE BYTE
	 ERJMP HELP2		; DONE, GO CLEAN UP
	MOVE T1,T2		;MOVE THE BYTE TO ANOTHER AC
	PBOUT			; SO WE CAN OUTPUT IT.
	JRST HELP1		;AND LOOP TILL THE END OF THE FILE

HELP2:	MOVE T1,INJFN
	CLOSF
	 JRST [	PNTERR (<CLOSF for the help file failed>)
		JRST PARSE1]
	JRST PARSE1
	SUBTTL Rebuild Command

;REBUILD (BIT TABLE).

;USER WANTS TO REBUILD THE BIT TABLE.  GET CONFIRMATION AND SET FLAG

.REBLD:	HRROI T1,[ASCIZ /BIT TABLE OF/]
	CALL CMDNOI		;NOISE WORDS
	CALL CONFRM		;GET STR AND CONFIRM
	CALL PSCHK		;CHECK FOR PS:
	 CALL XMNT		;NOT PS - MUST MOUNT IT
	CALL SETSTR		;SET CURRENT STR
	SETOM REBLDF		;YES. SET FLAG FOR QDONE CODE
	CALL BTBINI		;INIT BITTABLE
	CALL QDONE
	SKIPN PSFLG		;WAS THIS THE PS:?
	 JRST RESTRT		;NO - RESTART WHEN DONE
	CALL CLRCDE		;YES - CLEAR MONITOR FLAG
	JRST RESTRT		;AND RESTART

;ROUTINE TO INIT STRUCTURE BITTABLE

BTBINI:	MOVX T1,DA%INI		;T1/INITIALIZE BIT TABLE
	MOVE T2,STRDEV		;T2/STRUCTURE NUMBER
	DSKAS			;INITIALIZE A PRIVATE COPY OF THE BIT TABLE
	 JRST [	TMSG<
?Failed to initialize bit table
>
		JSERR
		SETZM WRTLPF	;don't allow system to come up
		JRST RESTRT]
	RET			;RETURN
	SUBTTL Reconstruct Command

;RECONSTRUCT (ROOT-DIRECTORY)

;USER WANTS TO TRY TO RECOVER A LOST FILE SYSTEM. FIRST COPY THE
;BACKUP COPY OF THE ROOT-DIRECTORY AND THEN REBUILD THE BITTABLE.

.RECNS:	MOVEI T1,[FLDDB.(.CMKEY,,RECTAB)] ;SECONDARY KEYTABLE
	CALL COMNDX
	 ERROR PARSE1,<Not a valid RECONSTRUCT option>
	HRRZ T1,(T2)		;GET DISPATCH
	JRST (T1)		;PROCESS

; TABLE OF OPTIONS FOR RECONSTRUCTION

RECTAB:	2,,2
	TB (.RECIT,INDEX-TABLE)
	TB (.RECRD,ROOT-DIRECTORY)
; RECONSTRUCT ROOT-DIRECTORY

.RECRD:	HRROI T1,[ASCIZ /OF/]
	CALL CMDNOI		;PRINT GUIDE WORDS
	CALL CONFRM		;GET STRUCTURE AND CONFIRM
	CALL PSCHK		;IS THIS THE PRIMARY PUBLIC STR
	 SKIPA			;NO - MUST GET EXCLUSIVE ACCESS
	ERROR PARSE1,<Cannot reconstruct PS: during time-sharing>
	SETZM OKFLG		;OK IF ON-LINE (MSG LATER)
	CALL FNDSTR		;FIND STRUCTURE (SET UP MNTBLK)
	 JRST PARSE1		;REASON ALREADY GIVEN
	JUMPL T1,[ERROR PARSE1,<Cannot reconstruct mounted structure>]
	CALL STRDEF		;SET UP DEFAULTS
	HRROI T1,ALINAM		;[2] GET STRUCTURE ALIAS
	MOVEM T1,MNTBLK+.MSIAL	;SET UP ALIAS
	MOVX T1,MS%XCL+<FLD(.MSRRD,MS%FCN)> ;FCN FOR RECONSTRUCT
	CALL STRINI		;INIT STRUCTURE
	 JRST PARSE1		;FAILURE
	TMSG <[Reconstruction phase 1 complete]
>
	CALL SETSTR		;SET CURRENT STRUCTURE
	SETOM REBLDF		;FLAG FOR QDONE REBUILD
	CALL BTBINI		;INIT BITTABLE
	CALL QDONE		;SCAN DIRECTORIES
	JRST RESTRT		;RESTART PROGRAM
; RECONSTRUCT INDEX-TABLE

.RECIT:	HRROI T1,[ASCIZ /OF/]
	CALL CMDNOI		;PRINT GUIDE WORDS
	CALL CONFRM		;GET STRUCTURE AND CONFIRM
	CALL PSCHK		;IS THIS THE PRIMARY PUBLIC STR
	 SKIPA			;NO - MUST GET EXCLUSIVE ACCESS
	ERROR PARSE1,<Cannot reconstruct PS: during time-sharing>
	SETOM OKFLG		;ASK ABOUT DISMOUNTING IF NOW MOUNTED
	CALL FNDSTR		;FIND STRUCTURE (SET UP MNTBLK)
	 JRST PARSE1		;REASON ALREADY GIVEN
	JUMPL T1,[ERROR PARSE1,<Cannot reconstruct mounted structure>]
	CALL STRDEF		;SET UP DEFAULTS
	HRROI T1,ALINAM		;[2] GET STRUCTURE ALIAS
	MOVEM T1,MNTBLK+.MSIAL	;SET UP ALIAS
	MOVX T1,MS%XCL+<FLD(.MSRIX,MS%FCN)> ;FCN FOR RECONSTRUCT
	CALL STRINI		;INIT STRUCTURE
	 JRST PARSE1		;FAILURE
	TMSG <[Reconstruction complete]
>
	JRST RESTRT		;DONE
	SUBTTL Release Command

;RELEASE (LOST PAGES)

;USER WANTS TO RELEASE LOST PAGES.  THESE ARE PAGES MARKED IN THE BIT
;TABLE AS USED AND NOT POINTED TO BY ANY FILE.  A PREVIOUS CALL TO
;CHECKD HAS PRODUCED A FILE OF THESE PAGES.  GET CONFIRMATION AND SET
;FLAGS AS NEEDED

.RLEAS:	STKVAR<DSKAD2,SAVCHN>
	HRROI T1,[ASCIZ /LOST PAGES FROM/]
	CALL CMDNOI		;PRINT NOISE WORDS

	MOVE T1,[RLSGTJ,,GTJBLK]	;COPY SPECIAL JFN BLOCK TO COMND'S JFN
	BLT T1,GTJBLK+.GJJFN-1	; BLOCK TO SPECIFY DEFAULT FILE
	CALL GETCON		;SET UP CONNECTED STR
	HRROI T1,DIRNAM		;BUILD DEFAULT FILESPEC
	HRROI T2,STRNAM
	MOVEI T3,0
	SOUT
	MOVEI T2,"-"
	IDPB T2,T1
	HRROI T2,[ASCIZ "LOST-PAGES"]
	SOUT			;STR:STR-LOST-PAGES.BIN
	MOVEI T1,[FLDDB.(.CMFIL)] ;T1/ADDRESS OF FUNCTION DESCRIPTOR BLOCK
	CALL COMNDX		;GET INPUT FILE SPEC, DEFAULTING TO LOST-PAGES.BIN
	 JRST [	CALL COMNDE	;ERROR, TYPE MESSAGE
		JRST PARSE1]
	HRRZM T2,INJFN		;YES. SAVE THE FILE'S JFN
	CALL FCNFRM		;(FOR) STR: & CONFIRM
	CALL PSCHK		;OK IF PS
	 CALL XMNTA		;MOUNT IF NOT ON LINE
	CALL SETSTR		;SET CURRENT STRUCTURE
	MOVE	T1,INJFN	;get JFN of x-LOST-PAGES.BIN
	MOVEI	T2,T4		;want to put date in T4
	MOVEI	T3,1		;only want internal write date
	RFTAD			;get file's write date
	 ERJMP	[ PNTERR(<Failed to get last write date>)
		  MOVE	T1,INJFN ;get the JFN back
		  RLJFN		;release it
		   JFCL		;don't care about errors
		  JRST	PARSE1]	;return
	GTAD			;get current date and time
	CAMN	T1,[-1]		;system date and time set?
	 JRST	[ HRROI	T1,[ASCIZ/% System date and time not set.  Do you want to continue anyway? /] ;no, build a prompt
		  CALL	YESNO	;get either a YES or a NO
		  JUMPE	T1,PARSE1 ;if "NO", return
		  JRST	RLEAS1]	;if "YES", go ahead and do stuff anyway
	SUBI	T1,2*25253	;subtract 2 hours
	CAMG	T1,T4		;within range?
	JRST	RLEAS1		;yes, go ahead and do stuff
	HRROI	T1,[ASCIZ/% File is more than 2 hours old, do you want to continue anyway? /] ;build a new prompt
	CALL	YESNO		;get either a YES or a NO
	JUMPE	T1,PARSE1	;if "NO", go back to CHECKD>
				;if "YES", fall thru...
RLEAS1:	MOVE T1,INJFN		;T1/JFN FOR INPUT FILE
	MOVE T2,[44B5+1B19]
	OPENF			;OPEN THE INPUT FILE
	 JRST [	PNTERR(<Failed to open lost pages file>)
		MOVE T1,INJFN	;T1/JFN OF INPUT FILE
		RLJFN		;RELEASE THE JFN
		 JFCL		;IGNORE FAILURE
		JRST PARSE1]	;GO START PARSE AGAIN
	CALL LPFCHK		;CHECK FILE FORMAT
	 JRST [	MOVE T1,INJFN	;INPUT JFN
		RLJFN		;FLUSH IT
		 JFCL
		JRST RESTRT]	;FORGET IT
	SETZM LOSTOT		;CLEAR COUNT
;READ DISK ADDRESSES FROM FILE.   EACH ADDRESS IS A SECTOR NUMBER RELATIVE
;TO START OF STRUCTURE.  DEASSIGN VIA DSKAS JSYS.

RLSPG1:	MOVE T1,INJFN		;T1/JFN OF INPUT FILE
	BIN			;READ ONE ADDRESS
	 ERJMP RLSPG2		;ERROR OR EOF
	JUMPE T2,[TMSG <% Zero word -- ignored
>
		 JRST RLSPG1]
	MOVE T1,T2		;T1/SECTOR NUMBER
	MOVEM T1,DSKAD2
	TXO T1,DA%DEA
	MOVE T2,STRDEV		;T2/STRUCTURE NUMBER
	DSKAS
	 JRST [	TMSG <%Failed to deassign lost page at disk address >
		MOVE T2,DSKAD2	;T2/FAILING ADDRESS
		MOVEI T3,10	;T3/OCTAL RADIX
		CALL TTNOUT	;PRINT THE ADDRESS THAT FAILED
		MOVEI T1,.FHSLF	;this process
		GETER		;get last error
		 ERJMP .+1	;shouldn't happen
		HRRZS	T2	;error number only
		CAIE	T2,DSKX06 ;Invalid disk address?
		JRST RLSPG1	;no, ignore the failure
		JSERR		;yes, write why we failed
		JRST	RLSPG2]	;quit before we totally destroy the pack
	AOS LOSTOT		;COUNT SUCCESS
	JRST RLSPG1		;LOOP UNTIL EOF
;COME HERE ON ERROR OR END OF FILE - CHECK WHICH

RLSPG2:	MOVE T1,INJFN
	GTSTS			;GET FILE STATUS
	TXNN T2,GS%EOF
	JRST [	TMSG <?Error while reading >
		MOVEI T1,.PRIOU
		MOVE T2,INJFN
		MOVEI T3,0
		JFNS		;PRINT FILE NAME
		TMSG < , Aborting...
>
		JRST .+1]
	TMSG < Released >
	MOVEI T1,.PRIOU
	MOVE T2,LOSTOT
	MOVEI T3,^D10
	NOUT			;TELL HOW MANY
	 JFCL
	TMSG < pages
>
	HRRZ T1,INJFN		;GET JFN BACK
	SETZM T2		;DELETE ALL GENERATIONS OF
	DELNF			; THE LOST PAGES FILE
	 JSERR
	HRRZ T1,INJFN
	CLOSF
	 JFCL
	JRST RESTRT		;DONE - RESTART
	SUBTTL Scan Command

;SCAN (FOR DISK ADDRESSES FROM FILE) FILE-SPECIFICATION

;USER WANTS TO SEARCH A FILE CONTAINING DISK ADDRESSES THAT ARE ASSIGNED
;TO MORE THAN ONE FILE.  EACH TIME A FILE IS FOUND TO POINT TO ONE OF THESE
;ADDRESSES A MESSAGE WILL BE PRINTED.  GET THE NAME OF THE FILE TO BE
;READ AND CONFIRMATION. SET FLAGS AS NEEDED.

.SCAN:	HRROI T1,[ASCIZ /FOR DISK ADDRESSES IN/]
	CALL CMDNOI		;PRINT NOISE WORDS
	MOVEI T1,[FLDDB.(.CMIFI)] ;T1/ADDRESS OF FDB
	CALL COMNDX		;GET FILE TO SCAN
	 JRST [	CALL COMNDE	;ERROR, REPORT AND START OVER
		JRST PARSE1]
	HRRZM T2,DAJFN		;YES. SAVE THE JFN
	CALL FCNFRM		;GET STR AND CONFIRM
	CALL PSCHK		;OK IF PS:
	 CALL XMNTA		;MOUNT IF NOT ONLINE
	CALL SETSTR		;SET CURRENT STR
	SETOM CHKFLF		;YES. SET FLAG FOR QDONE CODE
	MOVE T1,DAJFN		;T1/JFN
	MOVE T2,[XWD 70000,200000]
	OPENF
	 JRST [	PNTERR(<Failed to open specified file>)
		MOVE T1,DAJFN
		RLJFN
		 JFCL
		JRST PARSE1]
	MOVSI P1,-DASIZ
;READ EACH ADDRESS AND STORE 2 WORDS PER ADDRESS:
;1)	SOFTWARE ADDRESS
;2)	GIVEN ADDRESS

RDDALP:	MOVE T1,DAJFN
	CALL RDLIN		;READ ONE ADDRESS
	MOVE T1,[POINT 7,LINBUF]
	SETZ Q1,			;ASSUME SOFTWARE ADDRESS
RDDL1:	ILDB T2,T1
	CAIN T2," "		;FLUSH SPACES
	JRST RDDL1
	CAIE T2,"Z"-100		;EOF?
	CAIN T2,0
	JRST RDDAW		;YES, DONE
	CAIN T2,"H"		;HARDWARE ADDRESS?
	JRST [	SETO Q1,		;YES
		JRST RDDL1]
	CAIN T2,"S"		;SOFTWARE ADDRESS?
	JRST [	SETZ Q1,		;YES
		JRST RDDL1]
	CAIL T2,"0"		;OCTAL DIGIT?
	CAILE T2,"7"
	JRST [	TMSG <?Octal number required.
>
		JRST RDDALP]	;TRY AGAIN
	BKJFN			;BACKUP THE POINTER OVER FIRST DIGIT
	 JFCL
	MOVEI T3,^D8		;READ NUMBER IN OCTAL
	NIN
	 JRST [	JSERR
		TMSG <?Octal number required.
>
		JRST RDDALP]
	MOVE T1,T2
	MOVEM T1,DATAB+1(P1)	;STORE GIVEN ADDRESS
	SKIPE Q1			;USE GAVE SOFTWARE ADDRESS?
	JRST [	TXO T1,DA%CNV+DA%HWA
		MOVE T2,STRDEV	;T2/STRUCTURE NUMBER
		DSKAS		;NO, CONVERT
		 JSERR
		JRST .+1]
	MOVEM T1,DATAB(P1)	;STORE SOFTWARE ADDRESS
	AOBJN P1,.+1
	AOBJN P1,RDDALP
	TMSG <?Table full.
>
;REACHED END OF FILE.  EACH ADDRESS HAS BEEN WRITTEN IN 2 FORMS IN THE
;DATAB ARRAY.  STORE AOBJN POINTER TO DATAB IN DALIST.

RDDAW:	HLRES P1		;NEGATIVE OF SPACE REMAINING
	MOVNS P1		;SPACE REMAINING
	SUBI P1,DASIZ		;NEGATIVE OF SPACE USED
	HRLZM P1,DALIST		;(-SPACE USET4,,0)
	MOVE T1,DAJFN		;T1/JFN FOR INPUT FILE
	CLOSF			;CLOSE THE FILE
	 JFCL			;IGNORE FAILURE
	CALL QDONE		;NO MORE QUESTIONS
	JRST RESTRT		;DONE - RESTART
	SUBTTL Show Command

;SHOW COMMAND


;SHOW KEYWORD TABLE

SHWTAB:	XWD SHWSIZ,SHWMAX
	TB (.SHWBP,BOOT-PARAMETERS)
	TB (.SHWLG,LOGIN-SERIAL-NUMBERS) ;[7.1112]
SHWSIZ=.-SHWTAB-1
SHWMAX=SHWSIZ


.SHOW:	HRROI T1,[ASCIZ/INFORMATION FOR/]
	CALL CMDNOI
	MOVEI T1,[FLDDB.(.CMKEY,,SHWTAB,,,)]
	CALL COMNDX
	 ERROR PARSE1,<Not a valid topic>
	HRRZ T1,(T2)		;GET DISPATCH
	JRST (T1)		;PROCESS
	;SHOW BOOT-PARAMETERS

ON:	ASCIZ/ON /
OFF:	ASCIZ/OFF/

.SHWBP:	HRROI T1,[ASCIZ /FOR STRUCTURE/]
	CALL CMDNOI		;NOISE WORDS
	CALL CONFRM		;Get structure name and confirm
	CALL STSTRN		;SETUP STRUCTURE DATA
	CALL HOMEIN		;READ HOME BLOCKS OF FIRST PACK
	 JRST RESTRT		;BAD BLOCKS
	MOVE P6,BATBUF+HOMBTF	;Get existing bits
	HRROI T1,[ASCIZ/
  BOOT will /]
	PSOUT
	HRROI T1,[ASCIZ/READ parameters

/]
	TXNN P6,BT%RPM		;Are parameters to be read?
	HRROI T1,[ASCIZ/IGNORE parameters

/]
	PSOUT
	HRROI T1,[ASCIZ/      BOOT PARAMETERS:

/]
	PSOUT
	HRROI T1,[ASCIZ/      PROCEED on dump errors

/]
	TXNE P6,BT%HOD
	HRROI T1,[ASCIZ/      HALT on dump errors

/]
	PSOUT
	JRST RESTRT

;[7.1112]
;
; .SHWLG:
;
; This routine is called to display all the CPUs which can use a given
; structure as a Login Structure. It does this by scanning the Home
; Block words HOMLS1 through HOMLS4. CPU numbers are entered in these
; words by halfwords.
; Call:
;	JRST .SHWLG
; Returns:
;	To label RESTRT, always
;
.SHWLG:	HRROI T1,[ASCIZ /FOR STRUCTURE/]
	CALL CMDNOI		;Noise words
	CALL CONFRM		;Get structure name and confirm
	CALL STSTRN		;Setup structure data
	CALL HOMEIN		;Read Home Block of first pack
	 JRST RESTRT		;Bad blocks
	MOVSI T4,-LGSLEN	;Get length of serial number block
	HRRI T4,BATBUF+HOMLS1	;Make AOBJN pointer to list
	MOVE T1,T4		;Get pointer
SHWLG1:	SKIPE (T1)		;Is a serial number present?
	JRST SHWLG2		;Yes. Go do list
	AOBJN T1,SHWLG1		;Scan entire block
;
; There are no serial numbers in the Home Block. Inform user
;
	TMSG <
>				;<crlf>
	HRROI T1,STRHOM		;Point to name
	PSOUT%			;Primary output
	 ERJMP RESTRT		;Failed
	TMSG <: is not a Login Structure
>				;Finish message
	JRST RESTRT		;Done
;
; Here to display a list of 1 to 8 CPU serial numbers from words
; HOMLS1 through HOMLS4 of the Home Block
;
SHWLG2:	TMSG <
>				;<crlf>
	HRROI T1,STRHOM		;Point to to structure name
	PSOUT%			;Print it
	 ERJMP RESTRT		;Failed
	TMSG  <: is a Login Structure for CPUs:
>
SHWLG3:	HLRZ T2,(T4)		;Get CPU number from LH
	JUMPE T2,SHWLG4		;No number here
	TMSG <	>		;<tab>
	MOVEI T3,^D10		;Decimal
	CALL TTNOUT		;Display it
SHWLG4:	HRRZ T2,(T4)		;Get RH CPU number
	JUMPE T2,SHWLG5		;None here
	TMSG <	>		;<tab>
	MOVEI T3,^D10		;Decimal
	CALL TTNOUT		;Display it
SHWLG5:	AOBJN T4,SHWLG3		;Show entire list
	TMSG <
>				;Finish with <crlf>
	JRST RESTRT		;Done
;HERE TO DISPLAY THE STATUS OF THE KNOWN SWITCHES

.STATU:	HRROI T1,[ASCIZ /OF CHECKD SWITCHES/]
	CALL CMDNOI		;TYPE THE NOISE ON THE USER
	MOVEI T1,[FLDDB. (.CMCFM)]
	CALL COMNDX		;GET A CONFIRMATION
	 ERROR PARSE1,<Invalid command confirmation> ;NO. PRINT ERROR
	TMSG <
CHECKD switch settings at >
	MOVEI T1,.PRIOU		;ON THE TTY
	SETO T2,		;CURRENT DATE AND TIME
	MOVX T3,OT%DAY!OT%FDY!OT%FMN!OT%4YR!OT%DAM!OT%SPA!OT%NSC!OT%12H!OT%TMZ!OT%SCL
	ODTIM
	TMSG <

>
	HRROI T1,[ASCIZ /BAT block entry deletion/]
	MOVE Q1,BATFLG
	CALL STATIT		; OUTPUT THE STATUS
	HRROI T1,[ASCIZ /Soft disk read error inclusion/]
	MOVE Q1,SOFTFL
	CALL STATIT
	HRROI T1,[ASCIZ /ECC disk read error inclusion/]
	MOVE Q1,ECCFLG
	CALL STATIT
	JRST PARSE1

STATIT:	PSOUT
	SKIPE Q1
	JRST [	TMSG < is enabled.
>
		RET]
	TMSG < is disabled.
>
	RET
	SUBTTL Verify Command

;HERE TO VERIFY THE SWAP SPACE ON A DISK, OR THE ENTIRE DISK.
;USE THE VALUE OF BATFLG TO DECEIDE IF WE SHOULD ALLOW DELETION
;OF ENTRIES IN THE BAT BLOCKS, BUT ALWAYS ASK ABOUT ADDING THEM.

;DURING THE BAT BLOCK SCAN, SYSBTB IS USED AS A ORDERED PAIR
;LIST OF ALL THE BAT BLOCKS WE HAVE SEEN.

.VERIF:	STKVAR <VDSKFL>
	HRROI T1,[ASCIZ /DISK SURFACE FOR/]
	CALL CMDNOI		;OUT THE NOISE WORDS
	MOVEI T1,[FLDDB.(.CMKEY,,VETAB)]
	CALL COMNDX		;PARSE NEXT WORDS..
	 ERROR PARSE1,<not a CHECKD command>
	HRRZ T1,(T2)		;GET TABLE ADDR
	JRST (T1)		;DISPATCH TO THE ROUTINE.

VETAB:	XWD VESIZ,VEMAX
	TB (.VEDSK,FILE-SYSTEM)	;VERIFY ALL OF DISK SURFACE
	TB (.VESWP,SWAPPING)	;VERIFY ALL OF SWAP SPACE

VESIZ=.-VETAB-1
VEMAX=VESIZ
.VEDSK:	TDZA T1,T1		; 0==> ALL OF DISK
.VESWP:	SETO T1,		; 1==> ONLY SWAP SPACE
	MOVEM T1,VDSKFL		;SAVE THE FLAG FOR LATER
	HRROI T1,[ASCIZ /ON STRUCTURE/]
	CALL CMDNOI		;OUT THE NOISE
	CALL CONFRM		;GET STR AND CONFIRM
	CALL PSCHK		;SEE IF WE ARE ON PS?
	 CALL XMNT		;EXCLUSIVE MOUNT OF STRUCTURE IF NOT PS
	CALL SETSTR		;SET UP THE STRUCTURE
	CALL HOMEIN		;READ HOME BLOCKS FOR FIRST PACK
	 JRST RESTRT		;ERROR, PUNT THIS COMMAND
	CALL BATIN		;READ THE BAT BLOCKS IN
	SETZM SYSBTB		;CLEAR TABLE FOR BAT BLOCKS
	MOVEI T1,BPRBLK		;POINT TO FIRST PAIR OF BAT BLOCK PAIRS
	MOVEI T3,MAXPR		;TOTAL NUMBER OF ENTRIES
	SETZ T2,		;CLEAR COUNTER
VERLO2:	MOVE Q1,0(T1)		;GET FIRST WORD OF PAIR
	TXZ Q1,ADRMSK
	JUMPE Q1,VERCO1		;IF 0, END OF THE LIST
	ADD T2,1(T1)		;ADD IN UPPER END OF RANGE
	SUB T2,Q1		;SUBTRACT LOWER BOUND, AND ADD 1 TO ADJUST FOR
	ADDI T2,1		;COUNT, RATHER THAN RANGE
	ADDI T1,4		;DO THE NEXT PAIR OF WORDS
	SOJG T3,VERLO2		;AND LOOP TILL WE HAVE DONE THEM ALL
VERCO1:	TMSG <There are >
	MOVEI T3,^D10
	CALL TTNOUT
	TMSG < sectors marked as bad in the BAT blocks.
>
	MOVE T1,PAGCYL		;NUMBER OF PAGES PER CYLINDER
	CAIGE T1,^D100		;IS IT LESS THAN THE AMOUNT WE ARE WILLING
	JRST .+3		;YES, THATS THE NUMBER WE WANT
	LSH T1,-1		;READ HALF AS MUCH
	JRST .-3		;SEE IF THIS FITS
	MOVEM T1,MAXRED		;SAVE NUMBER OF PAGES TO READ
	SKIPE VDSKFL		; ARE WE DOING THE ENTIRE DISK?
	JRST VERSWP		;NO, JUST THE SWAP SPACE
	JRST VERFIL		;YES, GO DO THE FILE SPACE
; HERE TO VERIFY AN ENTIRE STRUCTURE, AND REPORT ANY DIFFERENCES
; BETWEEN THE BAT BLOCK, AND WHAT WE FIND

VERFIL:	MOVE T1,NPACKS		;GET THE NUMBER OF PACKS
	IMUL T1,SECUNT		;CALCULATE THE NUMBER OF SECTORS IN STRUCTURE
	MOVEM T1,LSTSEC		;AND SAVE THE COUNT FOR LATER
	SETZM FSTSEC		;START AT SECTOR 0
	CALL VERSCN		;SCAN THE DISK

; HERE AFTER THE DISK OR SWAP SPACE HAS BEEN GONE OVER

VERCO3:	MOVEI T1,SYSBTB		;POINT TO FIRST PAIR OF BAT BLOCK PAIRS
	SETZ T2,		;CLEAR COUNTER
VERLO1:	MOVE T3,0(T1)		;GET FIRST WORD OF PAIR
	TXZ T3,ADRMSK
	JUMPE T3,VERCO2		;CONTINUE, WE ARE ALL DONE IF IT IS 0
	ADD T2,1(T1)		;ADD IN UPPER END OF RANGE
	SUB T2,T3		;SUBTRACT LOWER BOUND, AND ADD 1 TO ADJUST FOR
	ADDI T2,1		;COUNT, RATHER THAN RANGE
	ADDI T1,4		;DO THE NEXT PAIR OF WORDS
	SOJG T3,VERLO1		;AND LOOP TILL WE HAVE DONE THEM ALL
VERCO2:	TMSG <Disk scan found >
	MOVEI T3,^D10
	JUMPE T2,[TMSG <no>
		  JRST .+2]	; INIDICATE NO ERRORS
	CALL TTNOUT
	TMSG < bad sectors.
>
	JRST BATWRK		; GO TO THE EDITOR
;HERE TO SCAN A DISK LOOKING BETWEEN FSTSEC AND LSTSEC FOR A BAD PAGE

; FOR THE FUTURE, ADD CODE TO READ MORE THAN A PAGE AT A TIME (MAXRED),
; AND GO BACK AND SINGLE STEP PAGES IF THERE IS AN ERROR.

VERSCN: MOVE P1,FSTSEC		;SET THE STARTING LOCATION
VERLO3:	CALL READCK		;READ THE BLOCK, AND SEE IF IT IS GOOD
	 CALL MARKCK		;MARK THAT FACT
	ADD P1,SECPAG		;GO TO NEXT SECTOR, PLEASE
	MOVEM P1,BATLST		;SAVE LAST BLOCK WE LOOKED AT
	CAMGE P1,LSTSEC		; PAST THE END?
	JRST VERLO3		;NO, LOOP FOR MORE
	RET			;ALL DONE
; Here to verify the swap space for each unit in the structure.

; We have to go and get the home blocks on each unit, and verify that they all
; have the swap space.  In the normal case, each unit will have exactly the
; same amount of swap space, and it will start at the save relative position
; on each unit, but places like Stanford insist on building kludge types of
; PS's, with three units and swap space on the first two only.  So go and get
; the pages for each unit, and if they try to build funny disks, we will not
; step on them.

VERSWP:	MOVE Q3,NPACKS		; THE NUMBER OF UNITS THAT HAVE SWAP SPACE
	SETZ Q2,		; THE NUMBER OF THE UNIT WE ARE WORKING ON
VERSW1:	MOVE Q1,SECUNT		; GET SIZE OF EACH UNIT
	IMUL Q1,Q2		; AND GET THE START OF THIS UNIT
	MOVEI T1,1		; NUMBER OF THE FIRST HOME BLOCK
	ADD T1,Q1		; ADD IN THE OFFSET
	CALL GETHOM		; AND READ IT IN.
	 JRST [	MOVEI T1,12	; FAILURE, SO TRY FOR THE SECOND ONE
		ADD T1,Q1
		CALL GETHOM
		 ERROR PARSE1,<Could not read the home blocks>
		JRST .+1]	; BACK TO THE MAIN LINE OF CODE
	CALL HOMIN1		; ENTER THE HOME BLOCK VERIFICATION CODE AFTER
				;  WE HAVE SET UP THE HOME BLOCK ON UNIT X
	 ERROR PARSE1,<Home blocks appear to have garbage in them>
	ADD Q1,FSSUN		; ADD IN THE OFFSET OF THE SWAP SPACE
	MOVEM Q1,FSTSEC		; AND RECORD IT AS THE PLACE TO START
	ADD Q1,NSSUN		; ADD THE LENGTH OF THE SWAP SPACE
	MOVEM Q1,LSTSEC		; AND THAT IS THE PLACE TO STOP
	MOVEM Q2,THSUNI		; RECORD THE UNIT NUMBER FOR PRYING EYES
	CALL VERSCN		; AND SCAN THAT PART OF THE DISK
	AOS Q2			; ON TO THE NEXT UNIT
	SOJG Q3,VERSW1		; GO OVER ALL THE UNITS
	JRST VERCO3		; JOIN THE COMMON CODE
	SUBTTL BAT Block Editor

; HERE TO DO THE WORK OF EDITING THE BAT BLOCKS

BATWRK:	SETZM BATLST		; CLEAR THE SCAN INDICATOR
	CALL PARSEI
BATEDI:	HRROI T1,BATPRM		; GET THE PROMPT
	CALL CMDINI		; AND SAY HELLO
	MOVEI T1,[FLDDB.(.CMKEY,,BATTAB)]
	CALL COMNDX		; GETS THE COMMAND
	 ERROR BATEDI,<Not a BAT block edit command>
	HRRZ T1,(T2)		; GET DISPATCH ADDR
	JRST (T1)		; GO TO IT.

BATPRM:	ASCIZ /BAT-EDIT>/

BATTAB:	BATTAL,,BATTAL
	TB (.BATAD,ADD)		; ADD TO THE BAT BLOCK
	TB (.BATDE,DELETE)	; DELETE FROM THE BAT BLOCKS
	TB (.BATEX,EXIT)	; EXIT AND WRITE NEW BLOCKS
	TB (.EFILD,FILE-DDT)	; CALL THE DISK EDIT PROGRAM
	TB (.BATLI,LIST)	; LIST STATUS OF KNOWN PAGES
	TB (.EPUSH,PUSH)	; CALL THE EXEC FOR LATER
	TB (.BATQU,QUIT)	; GIVE UP, LEAVE BAT BLOCKS ALONE
BATTAL==.-BATTAB-1
; here to exit and update the bat blocks

.BATEX:	HRROI T1,[ASCIZ /TO CHECKD COMMAND LEVEL AFTER UPDATING THE BAT BLOCKS/]
	CALL CMDNOI		; BITCH AT THE LOSER
	MOVEI T1,[FLDDB. (.CMCFM)]
	CALL COMNDX		; GET THE END OF THE LINE
	 ERROR BATEDI,<Invalid command confirmation>
	SETZ P1,		; FIRST SECTOR TO START AT
	MOVE P2,SECUNT		; SIZE OF FIRST PACK IN DISK
	MOVE P3,NPACKS		; NUMBER OF PACKS TO GO OVER
BATEX1:	CALL BATBLD		; BUILD BAT BLOCK FOR THIS UNIT
	 JRST [	TMSG <%Error, bat blocks not written; too many entries to add.>
		JRST BATEDI]
	ADD P1,SECUNT		; START AT BEGINNING OF NEXT PACK
	ADD P2,SECUNT
	SOJG P3,BATEX1		; LOOP OVER ALL PACKS

; HERE, AND WE CAN WRITE THE BLOCKS, BECAUSE WE KNOW THE WILL FIT

	SETZ P1,		; SAME AS LAST TIME
	MOVE P2,SECUNT
	MOVE P3,NPACKS
BATEX2:	CALL BATBLD		; BUILD THE BLOCKS
	 JRST [	TMSG <?Error on second pass of building bat blocks>
		JRST BATEDI]
	CALL BATWRT		; AND WRITE THEM IN BOTH PLACES
	 JRST [	TMSG <?Error writing bat blocks to disk, write is aborted.
%The bat blocks may be inconsistent at this time.
>
		JRST BATEDI]
	ADD P1,SECUNT
	ADD P2,SECUNT
	SOJG P3,BATEX2		; LOOP OVER ALL PACKS
	SETZM SYSBTB		; Never allow EXIT to copy old BAT entries.
	JRST RESTRT		; DONE, BACK FOR MORE
; HERE TO BUILD THE BAT BLOCK FOR A GIVIN DISK

; (P1) = LOWER BOUND
; (P2)-1 = UPPER BOUND
; (NPACKS)-(P3) = UNIT NUMBER

; BLOCKS ARE BUILT IN PT

BATBLD:	SETZM PT		; CLEAR AREA TO BUILD BLOCK IN
	MOVE T1,[PT,,PT+1]
	BLT T1,PT+777		; CLEAR THE DISK AREA
	MOVSI T1,(SIXBIT /BAT/)
	MOVEM T1,PT+BATNAM	; SET THE NAME (SIXBIT BAT IN FIRST WORD)
	MOVE T1,[CODE]
	MOVEM T1,PT+BATCOD	; SET SPECIAL CODE TO LOOK FOR
	MOVEI T1,BPRBLK		; POINT TO THE FIRST WORD
	MOVEI T2,PT+4		; START OF ENTRIES TO BUILD
	SETZ Q2,		; CLEAR COUNT OF NUMBER FOUND
	SKIPA
BATBL9:	ADDI T1,4		; POINT TO NEXT ENTRY
	SKIPN Q1,(T1)		; GET THE FIRST ADDRESS
	JRST BATBL3		; IT WILL BE 0 AT END OF THE LIST
	TXNN Q1,BT%MAP		; WAS IT DONE BY THE MAPPER?
	JRST BATBL9		; NO, LOOP FOR MORE
	TXZ Q1,ADRMSK		; CLEAR ANY FLAG BITS WE DON'T NEED
	CAML Q1,P1		; LESS THAN LOWER BOUND?
	CAML Q1,P2		; NO, IS IT LESS THAN UPPER BOUND?
	JRST BATBL9		; FAILS, LOOP FOR THE NEXT ONE
	DMOVE T3,2(T1)		; GET THE REAL WORDS
	DMOVEM T3,(T2)		; AND WRITE THE PAIR
	AOS Q2			; COUNT THE NEW ENTRY
	ADDI T2,2		; UPDATE THE POINTER
	JRST BATBL9		; AND GET THE NEXT ONE
; HERE AFTER WE ARE DONE ADDING THE HARDWARE TYPE ENTRIES, SO SEE IF WE
;  HAVE TOO MANY OR WHAT...

BATBL3:	CAILE Q2,MAXPAR		; DID WE GET TOO MANY?
	RET			; YES, ERROR RETURN
	MOVEI T3,PT		; BASE OF TABLE
	STOR Q2,BTHCT,(T3)	; SAVE THE NUMBER WE ADDED
	MOVEI T1,BPRBLK		; POINT TO THE FIRST WORD
	SETZ Q3,		; CLEAR COUNT OF NUMBER FOUND
	SKIPA
BATBL4:	ADDI T1,4		; POINT TO NEXT ENTRY
	SKIPN Q1,(T1)		; GET THE FIRST ADDRESS
	JRST BATBL5		; IT WILL BE 0 AT END OF THE LIST
	TXNN Q1,BT%ANG!BT%WBM!BT%FND ; DID WE GET IT THERE
	JRST BATBL4		; NO, LOOP FOR MORE
	TXZ Q1,ADRMSK		; CLEAR ANY FLAG BITS WE DON'T NEED
	CAML Q1,P1		; LESS THAN LOWER BOUND?
	CAML Q1,P2		; NO, IS IT LESS THAN UPPER BOUND?
	JRST BATBL4		; FAILS, LOOP FOR THE NEXT ONE
	DMOVE T3,2(T1)		; GET THE REAL WORDS
	DMOVEM T3,(T2)		; AND WRITE THE PAIR
	AOS Q3			; COUNT THE NEW ENTRY
	ADDI T2,2		; UPDATE THE POINTER
	JRST BATBL4		; AND GET THE NEXT ONE
; HERE AND Q2= MAPPER COUNT, Q3= WRITTEN BY MONITOR COUNT

BATBL5:	ADD Q2,Q3		;GET TOTAL OF BLOCKS
	CAILE Q2,MAXPAR		;OVER THE TOP ?
	RET			;YES, HANG IT UP
	SUB Q2,Q3		;No, assume SOFTFL is on
	SKIPN SOFTFL		;SOFT FLAG ON?
	JRST BATBL7		;NO, DON'T WRITE THE ADDRESSES TO BAT BLOCK
	MOVEI T1,SYSBTB		;POINT TO THE FIRST WORD
	SKIPA			;
BATBL6:	ADDI T1,4		;POINT TO NEXT ENTRY
	SKIPN Q1,(T1)		;GET THE FIRST ADDRESS
	JRST BATBL7		;IT WILL BE 0 AT END OF THE LIST
	TXNN Q1,BT%ANG!BT%WBM!BT%FND ;DID WE GET IT THERE
	JRST BATBL6		;NO, LOOP FOR MORE
	TXZ Q1,ADRMSK		;CLEAR ANY FLAG BITS WE DON'T NEED
	CAML Q1,P1		;LESS THAN LOWER BOUND?
	CAML Q1,P2		;NO, IS IT LESS THAN UPPER BOUND?
	JRST BATBL6		;FAILS, LOOP FOR THE NEXT ONE
	DMOVE T3,2(T1)		;GET THE REAL WORDS
	PUSH P,T1		;save table address
	MOVE T1,Q1		;put current address in T1
	CALL SEEADR		;AND LOOK FOR THIS ENTRY
	 JRST BATB10		;yes it's there, don't add it again
	DMOVEM T3,(T2)		;address not found, WRITE THE PAIR
	AOS Q3			;COUNT THE NEW ENTRY
	ADDI T2,2		;UPDATE THE POINTER
BATB10:	POP P,T1		;restore table address
	JRST BATBL6		;AND GET THE NEXT ONE

BATBL7:	MOVEI T3,PT		;GET BASE AGAIN
	STOR Q3,BTMCT,(T3)	; SAVE THIS FOR LATER
	ADD Q2,Q3		; GET TOTAL OF BLOCKS
	CAILE Q2,MAXPAR		; OVER THE TOP ?
	RET			; YES, HANG IT UP
	MOVEI Q3,MAXPAR		; GET TOTAL ALLOWED
	SUB Q3,Q2		; AND CALCULATE NUMBER FREE
	STOR Q3,BATFR,(T3)	; AND SAVE IT IN THE BLOCK
	RETSKP			; AND WE WIN FOR THIS BLOCK
; HERE TO WRITE THE BAT BLOCKS TO THE DISK

BATWRT:	MOVEI	T1,BATBL1	;get address of sector where BAT block goes
	MOVEM	T1,PT+BATBLK	;save it in BAT block
	MOVE 	T2,P1		;number of sectors to get on Nth unit
	IMUL	T2,TRECPP	;TRECPP/SECPAG = true sectors/sector
	IDIV	T2,SECPAG	;convert to true sectors
	ADD	T1,T2		;add number of sectors to get on Nth unit
	TXO	T1,<<FLD .DOPSR,DOP%AT>+DOP%SN> ;get flags
	MOVEI	T2,PGSIZ	;get page size
	IDIV	T2,TRECPP	;compute number or words to write
	TXO	T2,DOP%WR+DOP%PS ;write the data and use true physical sectors
	MOVEI	T3,PT		;address of data
	MOVE	T4,STRDEV	;get structure device number
	DSKOP			;write data to disk
	SKIPE T1		;any errors?
	RET			;yes, error, as AC1 .NE. 0
	MOVEI	T1,BATBL2	;get address of sector where BAT block goes
	MOVEM	T1,PT+BATBLK	;save it in BAT block
	MOVE	T2,P1		;get number of sectors to get on Nth unit
	IMUL	T2,TRECPP	;TRECPP/SECPAG = true sectors/sector
	IDIV	T2,SECPAG	;convert to true physical secotrs
	ADD	T1,T2		;add number of sectors to get on Nth unit
	TXO	T1,<<FLD .DOPSR,DOP%AT>!DOP%SN> ;get flags
	MOVEI	T2,PGSIZ	;get page size
	IDIV	T2,TRECPP	;compute number or words to write
	TXO	T2,DOP%WR+DOP%PS ;write the data and use true physical sectors
	MOVEI	T3,PT		;address of data
	MOVE	T4,STRDEV	;get structure device number
	DSKOP			;write data to disk
	SKIPE T1		;any errors?
	RET			;yes, error, as AC1 .NE. 0
	RETSKP			;done!
;HERE TO PUSH TO A NEW EXEC

.EPUSH:	CALL PUSHX		; CALL THE REAL ROUTINE
	 JFCL			; IGNORE ANE ERROR
	JRST BATEDI		; BACK TO WORK, PLEASE

;HERE TO CALL FILDDT

.EFILD:	CALL FILDTX		;CALL THE REAL ROUTINE
	 JFCL			; IGNORE ANY ERRORS
	JRST BATEDI		; AND ON WITH THE WORK
;HERE TO ADD AN ENTRY TO THE BAT BLOCKS

.BATAD:	HRROI T1,[ASCIZ /PAGE NUMBER/]
	CALL CMDNOI
	MOVEI T1,[FLDDB.(.CMNUM,CM%SDH,10,<Octal number of page to add to BAT block>,0)]
	CALL COMNDX
	 ERROR BATEDI,<Invalid octal number>
	MOVE P1,T2
	CALL CMDEOL
	 JRST BATEDI
	IMUL P1,SECPAG		; CONVERT TO A SECTOR
	SKIPG P1
	JRST [	TMSG <%The page number must be greater than 0.
>
		JRST BATEDI]	; GET COMMAND AGAIN
	MOVE T3,NPACKS
	IMUL T3,SECUNT		; GET TOTAL SIZE
	CAML P1,T3		; IS IT SMALL
	JRST [	TMSG <%The page number cannot be larger than >
		MOVE P1,T3
		SUBI P1,1
		CALL TYPEP1
		TMSG <.
>
		JRST BATEDI]	; BACK FOR MORE INPUT

; HERE, AND WE THINK THE NUMBER PASS THE RANGE CHECK
; T2 HAS THE SECTOR NUMBER IN IT

	MOVEI T1,BPRBLK		; ADDRESS OF TABLE TO LOOK THRU
	CALL BTTBSE		; SEARCH TABLE
	 JRST BATAD1		; NO MATCH, OK
	TMSG <
%Page >
	CALL TYPEP1
	TMSG < is already marked in the BAT blocks.
>
	JRST BATEDI		; AND GO BACK FOR MORE
;HERE TO DO THE REAL WORK OF ADDING A PAGE ENTRY

BATAD1:	MOVEI T1,BPRBLK		; POINT TO THE TABLE, PLEASE
	MOVNI T2,MAXPR/2	; TOTAL NUMBER OF ENTRIES WE ALLOW
	CALL BTTBAD		; ADD THIS ENTRY
	 JRST BATEDI
	MOVE Q2,T1		; KEEP A POINTER TO THIS ENTRY
	MOVEI T1,SYSBTB		; LOOK FOR THIS ENTRY IN OUR LIST
	MOVX Q1,BT%FND		; ASSUME WE FOUND IT OURSELF
	CALL BTTBSE		; SEE IF IT IS THERE
	 MOVX Q1,BT%ANG		; IF NOT THERE, ANYONES GUESS WHERE ITS FROM
	IORM Q1,(Q2)		; FLAG THAT IT IS OURS
	TXNE Q1,BT%FND		; CHECK WHICH WAY WE SET IT
	JRST [	DMOVE T2,2(T1)	; GET THE CKU FIELDS
		JRST .+2]
	SETZB T2,T3		; CLEAR THE CKU IF IT WAS BT%ANG
	DMOVEM T2,2(Q2)		; UPDATE THE CKU
	MOVEI Q1,2(Q2)		; POINT TO THE CKU FIELD
	LOAD T2,ADD27,(Q1)	; GET THE ADDRESS
	SKIPE T2		; SKIP IF IT IS ZERO, AND WE NEED TO FIX IT
	JRST BATEDI		; BACK TO THE MAIN LOOP
	MOVE T3,SECPAG		; GET PROPER NUMBER OF SECTORS
	SUBI T3,1		; LESS ONE, PER FORMAT OF BAT BLOCKS
	STOR T3,BATNB,(Q1)	; SAVE THE LENGTH
	SETO T3,		; SET FLAG BITS
	STOR T3,BADT,(Q1)	; INDICATE THIS IS THE NEW TYPE OF ENTRY
	MOVE T3,P1		; GET THIS SECTOR NUMBER
	IDIV T3,SECUNT		; GET OFFSET FOR THIS UNIT
	STOR T4,ADD27,(Q1)	; AND SAVE IN THE WORDS
	MOVEI T1,.APRID		;want system serial number
	GETAB			;get it
	 ERJMP .+1		;shouldn't happen
	STOR T1,APRNM,(Q1)	;save it
;	T1/ sector number adjusted for unit (used to check unit no)
;	T2/ address of units CHANnel, KONtroller, and UNIT block in MNTBLK
;	T3/ unit number sector is located on in structure
	MOVE T1,P1		;get a working copy of the sector number
	MOVEI T2,MNTBLK+.MSTUI	;address of first word of CHAN,KON,UNIT block
	MOVEI T3,1		;assume unit 1
BATAD3:	SUB T1,SECUNT		;subtract number of sectors/unit
	JUMPL T1,BATAD2		;found correct unit?
	ADDI T2,.MSTNO		;no, next address of next CHAN,KON,UNIT block
	AOS T3			;bump count of which pack we're on.
	CAMLE T3,NPACKS		;see if we're past end of structure
	 ERROR	BATEDI,<Sector too large for this structure>
				;error, shouldn't happen!
	JRST BATAD3		;go back and check again
BATAD2:	MOVE T1,.MSTCH(T2)	;get channel number
	STOR T1,BTKNM,(Q1)	;save channel number
	MOVE T1,.MSTUN(T2)	;get unit number
;CONVERT THE UNIT NUMBER TO A BIT PATTERN
	ANDI T1,7		;TRUNCATE UNIT NUMBER TO 3 BITS BECAUSE
				;RP20 AND HSC'S CAN HAVE HIGH NUMBERS
	MOVEI T2,1		;BEGIN WITH BIT FOR DRIVE 0
	LSH T2,(T1)		;SHIFT PROPER NUMBER OF BITS
	STOR T2,BTUNM,(Q1)	;BIT POSITIONING DONE, SAVE UNIT BIT PATTERN
	JRST BATEDI		; BACK TO THE MAIN LOOP
;HERE TO DELETE AN ENTRY FROM THE BAT BLOCKS

.BATDE:	HRROI T1,[ASCIZ /PAGE NUMBER/]
	CALL CMDNOI
	MOVEI T1,[FLDDB.(.CMNUM,CM%SDH,10,<Octal number of page to delete from the BAT block>,0)]
	CALL COMNDX
	 ERROR BATEDI,<Invalid octal number>
	MOVE P1,T2
	CALL CMDEOL
	 JRST BATEDI
	IMUL P1,SECPAG		; CONVERT TO A SECTOR
	SKIPG P1
	JRST [	TMSG <%The page number must be greater than 0.
>
		JRST BATEDI]	; GET COMMAND AGAIN
	MOVE T3,NPACKS
	IMUL T3,SECUNT		; GET TOTAL SIZE
	CAML P1,T3		; IS IT SMALL
	JRST [	TMSG <%The page number cannot be larger than >
		MOVE P1,T3
		SUBI P1,1
		CALL TYPEP1
		TMSG <.
>
		JRST BATEDI]	; BACK FOR MORE INPUT

; HERE, AND WE THINK THE NUMBER PASS THE RANGE CHECK
; T2 HAS THE SECTOR NUMBER IN IT

	SKIPN BATFLG
	 ERROR BATEDI,<BATBLOCK deletion has not been enabled>
	MOVEI T1,BPRBLK
	CALL BTTBDE		;DELETE THIS ENTRY IF IT IS THERE
	 JRST [	TMSG <%Page >
		CALL TYPEP1
		TMSG < is not marked in the bat blocks.
>
		JRST BATEDI]
	JRST BATEDI		; BACK FOR MORE INPUT
;HERE TO JUST QUIT THE BAT BLOCK EDITOR

.BATQU: HRROI T1,[ASCIZ /FROM THE EDITOR, DON'T UPDATE THE DISK/]
	CALL CMDNOI		; GIVE THE NOISE TO THE USERS
	MOVEI T1,[FLDDB.(.CMCFM)]
	CALL COMNDX		; GET THE CONFIRMATION
	 ERROR BATEDI,<Invalid command confirmation>
	JRST RESTRT		; RESTART THE WORLD.
;HERE TO LIST THE INFORMATION WE HAVE ABOUT BAT BLOCKS

.BATLI:	HRROI T1,[ASCIZ /BAT BLOCK INFORMATION/]
	CALL CMDNOI		; TYPE THE NOISE
	MOVEI T1,[FLDDB.(.CMCFM)]
	CALL COMNDX		; GET CONFORMATION
	 ERROR BATEDI,<Invalid command confirmation>
	TMSG <
The following pages are marked in the BAT blocks:
>
	MOVEI Q1,BPRBLK		; POINTER TO LIST
	SETZM BATTYF		; CLEAR HEADER FLAG
BATLI1:	SKIPN T1,(Q1)		; GET NEXT ENTRY IN LIST
	JRST BATLIR
	TXZ T1,ADRMSK		; BLANK OUT ANY EXTRA BITS
	JUMPE T1,BATLIR
	CALL BATTYP		; TYPE THIS BAT ENTRY
	ADDI Q1,4
	JRST BATLI1
BATLIR:	TMSG <
>
	SKIPE BEMFLG		;ONLY GO ON IF WE HAVE SOME GOOD INFO
	JRST BATEDI
	TMSG <The following pages are marked in the bat blocks, but were read
without errors.
>
	SETZM BATTYF		; CLEAR HEADER FLAG
	MOVEI Q1,BPRBLK		; GET THE REAL BAT BLOCK LIST
BATLI2:	SKIPN P1,(Q1)		; GET NEXT ENTRY, PLEASE
	JRST BATLIN		; END OF LIST, WE ARE DONE HERE
	TXZ P1,ADRMSK
	JUMPE P1,BATLIN
BATLI3:	MOVEI T1,SYSBTB		; POINT TO THE BAT LIST AGAIN
	CALL BTTBSE		; AND LOOK FOT THIS ENTRY
	 JRST [	PUSH P,T1	; SAVE THE T1 REG
		CALL BATTYP	; AND TYPE THE ENTRY, PLEASE
		POP P,T1	; PUT T1 BACK
		JRST .+1]	; AND RETURN
	ADD P1,SECPAG		; BUMP THE POINTER UP SOME
	CAMG P1,1(T1)		; SEE IF IT IS PAST THE END, PLEASE
	JRST BATLI3		; NO, SEE IF IT IS HIDDEN
	ADDI Q1,4		; GO TO THE NEXT ENTRY
	JRST BATLI2
BATLIN:	TMSG <
The following pages are not marked in the BAT blocks, and could not
be read.
	>
	SETZM BATTYF		; CLEAR HEADER FLAG
	MOVEI Q1,SYSBTB		; GET THE REAL BAT BLOCK LIST
BATLI4:	SKIPN P1,(Q1)		; GET NEXT ENTRY, PLEASE
	JRST BATWRK		; END OF LIST, WE ARE DONE HERE
	TXZ P1,ADRMSK
	JUMPE P1,BATWRK
BATLI5:	MOVEI T1,BPRBLK		; POINT TO THE BAT LIST AGAIN
	CALL BTTBSE		; AND LOOK FOT THIS ENTRY
	 JRST [	PUSH P,T1	; SAVE THE T1 REG
		CALL BATTYP	; AND TYPE THE ENTRY, PLEASE
		POP P,T1	; PUT T1 BACK
		JRST .+1]	; AND RETURN
	ADD P1,SECPAG		; BUMP THE POINTER UP SOME
	CAMG P1,1(T1)		; SEE IF IT IS PAST THE END, PLEASE
	JRST BATLI5		; NO, SEE IF IT IS HIDDEN
	ADDI Q1,4		; GO TO THE NEXT ENTRY
	JRST BATLI4
;HERE TO TYPE A SINGLE BAT BLOCK ENTRY
;
; Q1 POINTS THE 4 WORD ENTRY, AND BATTYF IS THE HEADER TYPE FLAG
;
BATTYP:	SKIPN BATTYF		; FLAG SET?
	JRST [	TMSG <
 Start    End    Type  Address  Length  APRID  Chan  Unit	Who
 (Pages     )          (Sectors      )

>
		SETOM BATTYF	; ONLY ONE HEADER
		JRST .+1]
	MOVE T2,(Q1)		; GET FIRST WORDS
	TXZ T2,ADRMSK		;CLEAR ALL BUT THE ADDRESS
	IDIV T2,SECPAG
	MOVE T3,[^D9,,10]
	CALL TTNOUT		; TYPE THE NUMBER (START)
	MOVE T2,1(Q1)
	IDIV T2,SECPAG
	MOVE T3,[^D9,,10]
	CALL TTNOUT		; TYPE THE NUMBER (END)
	PUSH P,Q1		; SAVE POINTER
	ADDI Q1,2		; SKIP OLD DATA
	LOAD T4,ADD27,(Q1)	; GET BIG ADDRESS
	LOAD T1,BADT,(Q1)	; GET TYPE FIELD
	SKIPN T1		; IS THIS AN OLD ONE?
	LOAD T4,ADD18,(Q1)	; YES, GET OLD ADDRESS
	SKIPN T1
	JRST [	TMSG <OLD  >
		JRST BATTY1]
	TMSG <NEW  >
BATTY1: MOVE T2,T4
	MOVE T3,[^D12,,10]	; 9 COL, DECIMAL
	CALL TTNOUT		; OUTPUT THE NUMBER (ADDRESS)
	LOAD T2,BATNB,(Q1)	; GET LENGTH
	ADDI T2,1		; FUDGE IT A LITTLE
	MOVE T3,[^D6,,^D10]
	CALL TTNOUT		; OUTPUT THE NUMBER (LENGTH)
	LOAD T2,APRNM,(Q1)	; GET APRID OF WRITER
	MOVE T3,[^D8,,^D10]
	CALL TTNOUT		; OUTPUT THE NUMBER (APRID)
	LOAD T2,BTKNM,(Q1)	; GET CONTROLER NUMBER
	MOVE T3,[^D5,,^D10]
	CALL TTNOUT
	LOAD T1,BTUNM,(Q1)	; GET UNIT NUMBERS FLAGS
	MOVE T3,[^D1,,^D10]
	JUMPE T1,BATTY2		; OUT OF HERE IF WE ARE ALL DONE
	SETO T2,
BATTY3:	AOS T2
	TRZE T1,1		; IS THE LOW ORDER BIT SET
	JRST [	PUSH P,T1	; SAVE OLD BIT MASK
		CALL TTNOUT	; TYPE THE UNIT NUMBER
		SKIPE (P)	; SEE IF THAT WAS THE LAST UNIT WE NEED TO TYPE
		CALL [	TMSG <,>
			RET]
		POP P,T1	; RESTORE FLAGS
		JRST .+1]	; AND CONTINUE
	LSH T1,-1		; SLIDE IT OVER A BIT
	JUMPN T1,BATTY3		; AND KEEP GOING IF THERE IS MORE
BATTY2:	TMSG <	>
	POP P,Q1
	MOVE T2,(Q1)		; GET THE FLAGS AND START SECTOR
	HRROI T1,[ASCIZ /   	Mapper
/]				; ASSUME THE MAPPER DID IT
	TXNE T2,BT%FND
	HRROI T1,[ASCIZ /   	CHECKD
/]				; WE FOUND IT IN OUR WANDERINDS
	TXNE T2,BT%WBM
	HRROI T1,[ASCIZ /   	Monitor
/]				; THE MONITOR (OR US SOME TIME IN THE PAST)
				; PLACED IT IN THE BAT BLOCK
	TXNE T2,BT%ANG
	HRROI T1,[ASCIZ /   	Unknown
/]				; IT JUST APPEARED FOR THE ETHIER
	PSOUT			; TELL THE LOSER
	RET
; HERE TO TRY TO READ A DISK PAGE, AND SEE IF WE CAN GET IT.  IN NO CASE,
; WILL WE ALLOW IT TO FIND ITS WAY INTO THE BAT BLOCKS
; CALL WITH P1 = THE SECTOR TO READ
; RETURN +1 IF ERROR
; RETURN +2 IF OK

; THIS CODE, THE BAT BLOCK ADD ROUTINE, THE SCAN ROUTINE (VERSCN), AND
; EVERYTHING THAT HAS ANYTHING TO DO WITH THIS CODE **KNOWS** WHAT AC'S
; ARE USABLE FOR WHAT.  IN GENERAL, ALL THE T'S ARE TRASHABLE, AS WELL
; AS Q1, (BUT WE USE IT AS A COUNTER), AND P1 *** MUST *** CONTAIN THE
; SECTOR NUMBER THAT WE ARE READING AT.

READCK:	MOVE T4,STRDEV		;SET DEVICE TO READ ON
	SETZ Q1,		;INDICATE WE HAVE DONE ANY READS YET
READ1:	MOVE T3,DIRORA		;READ INTO THE DIRECTORY AREA
	MOVE T1,P1		; LOAD THE PAGE ADDRESS
	TXO T1,<FLD .DOPSR,DOP%AT>
				; LINEAR ADDRESS, ALWAYS
	TXO T1,DOP%SN		;INDICATE A STRUCTURE REFERENCE
	MOVX T2,1000!DOP%IL!DOP%IR
				;1000 WORDS, AND SUPPRESS ERROR LOG,
				;  AND NO RETRY
	DSKOP			;READ THE PAGE
	 ERJMP	[JSERR		;write why we failed
		JRST	.+1]	;continue
	JUMPN T1,READE1		;READ ERROR
	SKIPE Q1		; FIRST TRY?
	JRST READE2		; NO, SEE WHATS UP
READR:	RETSKP			; NO ERROR, GOOD IN ANY CASE

; HERE IF WE WIN ON A SOFT ERROR AFTER THE FIRST TRY

READE2:	TMSG <Soft read error for page >

	; FALL INTO NEXT PAGE
; HERE TO TYPE PAGE NUMBER, AND IF WE ARE COUNTING SOFT ERRORS, RETURN A
; FAILED TO READ STATUS (NON SKIP RETURN)

READC:	CALL TYPEP1
	TMSG <.
>
	SKIPN SOFTFL		; SOFT ERRORS WANTED?
	JRST READR		; NO, RETURN

; HERE TO TELL USER PAGE IS COUNTED AS BAD, AND RETURN THE INFORMATION

READB:	TMSG <	The page will be considered bad.
>
	RET			; RETURN THE ERROR

; HERE IF WE HAD AN ERROR ON SOFT READS. TRY 8 TIMES BEFORE WE GIVE UP
; ON THIS SECTOR.

READE1: AOS Q1			; COUNT THE NUMBER OF TRYS
	CAIE Q1,10		; UP TO THE LIMIT YET
	JRST READ1		; NO, TRY AGAIN
	SETZ Q1,		; CLEAR OUT THE COUNT

;HERE FOR ECC READ RETRY

READ2:	MOVE T3,DIRORA
	MOVE T1,P1		; LOAD THE PAGE ADDRESS
	TXO T1,<FLD .DOPSR,DOP%AT>
				; LINEAR ADDRESS, ALWAYS
	TXO T1,DOP%SN		;INDICATE A STRUCTURE REFERENCE
	MOVX T2,1000!DOP%IL	;1000 WORDS, AND SUPPRESS ERROR LOG
	DSKOP			;READ THE PAGE
	JUMPN T1,READE3		;ECC ERROR, WE ARE DONE
	SKIPE Q1		;WAS THIS THE FIRST ATTEMPT?
	JRST READE4		;NO, SEE IF WE WANT SOFT OR ECC ERRORS

; HERE IF A "HARD" SOFT ERROR WAS RECOVREABLE ON THE FIRST ECC READ

	TMSG <Soft read error recovered by ECC for page >
	JRST READC		;TYPE PAGE NUMBER, AND COUNT IT IF WE ARE
				; LOOKING FOR SOFT ERRORS
;HERE ON FIRST THRU Nth ERR READ ERROR WITH ECC

READE3:	AOS Q1			;COUNT THIS ERROR
	CAIE Q1,10		;DID WE TRY 8 TIMES?
	JRST READ2		;NO, TRY FOR ALL 8

	TMSG <Hard error reading page >
	CALL TYPEP1
	TMSG <.
>
	JRST READB		;ALWAYS COUNT IT AS BAD

;HERE IF A RETRY WITH ECC AFTER THE FIRST ONE WINS

READE4:	TMSG <Recoverable ECC read error for page >
	CALL TYPEP1
	TMSG <.
>

; IF EITHER SOFTFL OR ECCFLG ARE SET, WE RETURN AN ERROR, ELSE IT IS OK

	SKIPE SOFTFL		;WANT SOFT ERRORS?
	JRST READB		; YES, INDICATE ERROR
	SKIPE ECCFLG		;WANT ECC ERRORS?
	JRST READB		; YES, ALSO INDICATE ERROR
	JRST READR		;RETURN, PLEASE, NO ERROR
; HERE TO MARK THE BIT TABLE WITH A BLOCK AS BEING BAD

MARKCK: MOVEI T1,SYSBTB		; POINT TO THE TABLE WE ADD TO
	MOVNI T2,<BTBMAX/4>-1	; LOTS OF ENTRIES
	CALL BTTBAD		; ADD IT TO THE TABLE
	 JFCL
	MOVX T2,BT%FND		; WE FOUNT IT, SO CLAIM IT
	IORM T2,(T1)
	CALLRET SETCKU		; SET THE CKU CORRECTLY
;HERE TO SET THE CKU OF THE PAIR POINTED TO BY T1

SETCKU:	PUSH P,T1		; SAVE ADDRESS OF THE BAT PAIR
	ADDI T1,2		; SKIP OUR STUFF
	MOVE T3,SECPAG		; GET PROPER LENGTH IN SECTORS
	SUBI T3,1		; LESS ONE PER FORMAT OF BAT BLOCKS
	STOR T3,BATNB,(T1)	; SAVE THE LENGTH
	SETO T3,		; SET FLAG BITS
	STOR T3,BADT,(T1)	; INDICATE THIS IS THE NEW TYPE OF ENTRY
	MOVE T3,P1		; GET THIS SECTOR NUMBER
	IDIV T3,SECUNT		; GET OFFSET FOR THIS UNIT
	STOR T4,ADD27,(T1)	; AND SAVE IN THE WORDS
	CALL GETCKU		; FIND THE CKU FOR THIS SECTOR
	POP P,Q2		; Q1,3 HAVE C, U, Q2= POINTER TO BLOCK
	ADDI Q2,2		; BUMP POINTERS TO THE REAL PAIRS.
	STOR Q1,BTKNM,(Q2)	; STASH THE CONTROLLER NUMBER
	LOAD Q1,BTUNM,(Q2)	; FETCH THE OLD UNIT FLAGS
	ANDI Q3,7		; TRUNCATE TO 3 BITS (FIX FOR HSC AND RP20'S)
	MOVN Q3,Q3		; NEGATE UNIT NUMBER
	IOR Q1,BITS+^D35(Q3)	; GET THE NEW UNIT BIT ADDED
	STOR Q1,BTUNM,(Q2)	; AND SAVE IT BACK AGAIN
	MOVE T1,[SIXBIT /APRID/]
	SYSGT			; GET OUR CPU NUMBER
	STOR T1,APRNM,(Q2)	; AND FILE THAT FOR THOSE WITH PEEKING EYES
	RET			; RETURN AND KEEP GOING
; HERE TO GET THE CKU FOR THE SECTOR IN P1

GETCKU:	SETOM RNUBLK+.MSRCH	;INIT FOR FIRST UNIT
	SETOM RNUBLK+.MSRCT
	SETOM RNUBLK+.MSRUN
	SETOM MNTBLK+.MSTNU	;INIT # OF UNITS IN STR
	MOVE Q1,P1		;THIS IS THE SECTOR NUMBER WE WANT
	IDIV Q1,SECUNT		;NOW WE HAVE THE UNIT NUMBER WE WANT
	ADDI Q1,1		;FOR SOME REASON, UNIT NUMBERS START AT 1
GETCK2: CALL GTASTS		;GET FIRST UNIT STATUS
	 JRST [	TMSG <
? Unit for page >
		CALL TYPEP1
		TMSG < not found.
>
		JRST GETCK1]
	CALL STRMAX		;IS THIS THE DISK WE ARE LOOKING FOR?
	 JRST GETCK2		; NO, LOOK FOR THE NEXT ONE
	HLRZ Q2,RNUBLK+.MSRNS	; GET THIS LOGICAL UNIT NUMBER
	AOS Q2			; UNIT NUMBERS START AT 1
	CAME Q2,Q1		; THE ONE WE ARE LOOKING FOR?
	 JRST GETCK2		; NO, LOOK YET AGAIN
	MOVE Q1,RNUBLK+.MSRCH	;CHANNEL
	MOVE Q2,RNUBLK+.MSRCT	;CONTROLLER
	MOVE Q3,RNUBLK+.MSRUN	;UNIT
	RET

;HERE ON AN ERROR, RETURN A CKU OF 0,0,0

GETCK1:	SETZB Q1,Q2
	SETZ Q3,
	RET
; HERE TO TYPE THE CONTENTS OF P1 AS A NUMBER BASE 8 , AND CONVERTED TO A
; PAGE NUMBER FROM A SECTOR NUMBER

TYPEP1:	MOVE T2,P1
	IDIV T2,SECPAG
	MOVEI T3,10		; OCTAL
	CALLRET TTNOUT
;BAT BLOCK TABLE SEARCH

;HERE TO SEE IF THERE IS AN OVERLAP BETWEEN THE PAGE POINTED TO BY P1,
;AND ANY ENTRY IN THE TABLE POINTED TO BY T1.
;
; SKIP RETURN ON A MATCH, NON SKIP RETURN ON NO OVERLAP

BTTBS1: ADDI T1,4
BTTBSE:	SKIPN T2,(T1)		; IS THE TABLE EXAUSTED?
	RET			; YES, WE ARE DONE
	TXZ T2,ADRMSK		; CLEAR ANY EXTRA BITS
	JUMPE T2,R		; RETURN IF ADDRESS IS ZERO
	CAML P1,T2		; SEE IF IT IS IN RANGE
	CAMLE P1,1(T1)		; IF NOT, THEN
	JRST BTTBS1		; LOOK FOR MORE
	RETSKP			; IN RANGE, A GOOD RETURN T1= ADDR OF ENTRY
;BAT BLOCK TABLE DELETE

;HERE TO DELETE A SET OF SECTORS FROM THE TABLE POINTED TO BY T1
;P1 HAS THE ENTRY TO DELETE.  A SKIP RETURN INDICATED OK, AN +1 RETURN
;IS FOR ERRORS (I.E. NOT FOUND)

BTTBDE:	TXZ P1,ADRMSK		; MAKE SURE WE HAVE NO EXTRA BITS
	SKIPN T2,(T1)		; END OF LIST?
	RET			; YES, AND WE HAVENT SEEN IT YET, SO ERROR
	TXZ T2,ADRMSK
	JUMPE T2,R		; RETURN IF THIS PART 0, TOO
	CAME P1,T2		; IS IT IN FORNT OF THE LIST?
	JRST [	ADDI T1,4	; GO FOR MORE
		JRST BTTBDE]	; TILL WE HAVE IT
	MOVE T2,T1		; FIND THE END OF THE LIST, PLEASE
	MOVE T3,(T2)
	TXNE T3,ADDERS
	AOJA T2,.-2		; IN A FAST LOOP
	HRLI T3,4(T1)		; SOURCE
	HRR T3,T1		; DESTINATION (FORWARD 4 WORDS)
	BLT T3,(T2)		; SO WHAT IF WE MOVE FOUR EXTRA WORDS
	RETSKP			; WE ARE DONE
;BAT BLOCK TABLE ADD

; HERE TO ADD A WORD PAIR TO A BAT TABLE.
; T1 POINTS TO THE TABLE, AND P1 HAS THE SECTOR TO ADD
; WE WILL ADD SECPAG NUMBERS. T1 WILL POINT TO THE ENTRY WHEN DONE
;

BTTBAD:	AOSLE T2		; BUMP COUNT, CHECK FOR OVERFLOW
	JRST [	TMSG < BATBLOCK table is full, some entries must be deleted to add more.
Error encountered on page >
		CALL TYPEP1	; TYPE THIS PAGE NUMBER
		TMSG <.
>
		RET]
	SKIPN (T1)		; GET NEXT ENTRY IN TABLE
	JRST BTTBA1		; NO, NEW ENTRY
	ADDI T1,4		; NEXT ENTRY
	JRST BTTBAD

BTTBA1:	MOVE T3,SECPAG		; GET NUMBER OF SECTORS PER PAGE
	TXZ P1,ADRMSK		; MAKE SURE WE HAVE NO EXTRA BITS
	ADD T3,P1		; NUMBER OF END + 1
	SUBI T3,1		; NUMBER OF END
	MOVEM P1,0(T1)		; SAVE THE START OF THIS ERROR REGION
	MOVEM T3,1(T1)		; UPDATE END POINTER
	SETZM 2(T1)		; CLEAR BAT BLOCK WORDS
	SETZM 3(T1)
	SETZM 4(T1)		; MAKE SURE WE CAN FIND THE END OF THE LIST
	RETSKP
	SUBTTL Directory Scan Code

;Here from job 0 startup or from SCAN, RECONSTRUCT ROOT-DIRECTORY, REBUILD (BIT
;TABLE), or CHECK BITTABLE commands.  Flags indicate what functions to perform.

QDONE:	CALL HOMEIN		;GO COMPUTE HOME BLOCK STUFF
	 JRST QDON1		;ERROR
	CALL BATIN		;GO GET THE BAT BLOCKS
	TMSG <
>
	CALL INIBTB		;INITIALIZE LOCAL COPY OF BIT TABLE
	CALL SCANDI		;GO SCAN ALL THE DIRECTORIES
	 JRST QDON1		;AN ERROR, CLEAN UP
	SKIPN DALIST		;SCANNING FOR DISK ADDRESSES?
	SKIPN CHKFLF		;NO. CHECKING FILES?
	JRST QDON1		;SCANNING OR NOT CHECKING FILES. DON'T DO
				; BIT TABLE STUFF
	CALL FINBTB		;YES, DO SUMMARY, ETC.
QDON1:	CALL RESET
	RET			;RETURN TO CALLER
;[39] Call JSERRO to output "? JSYS error: string", returns +1 always.
;[39] Call JSERR1 to just output the error

JSERRO:	HRROI T1,[ASCIZ/ JSYS error: /]	;Load initial string
	ESOUT%			;Output with a "?" and clear input buffer
	CALL JSERR1		;Output the error text
	TMSG <
>
	RET

JSERR1:	MOVEI T1,.PRIOU		;Point output at primary again
	MOVX T2,<.FHSLF,,-1>	;Output this fork's last error
	SETZ T3,		;No limit on that string
	ERSTR			;Send string to terminal
	 CALLRET JSERR2		;Undefined error number!
	 JFCL			;Shouldn't have a length problem
	RET			;Return

JSERR2:	TMSG <Undefined error number > ;Output label for string
	MOVEI T1,.FHSLF		;Load this fork
	GETER%			;Get last error in T2
	MOVEI T1,.PRIOU		;Send output to terminal
	ANDI T2,-1		;Get just the number please
	MOVEI T3,4+4		;Radix 8
	NOUT%			;Output that octal number
	 ERJMP .+1		;Ignore error within error within error
	RET			;Return
	
;[39] Here on a serious JSHLT type of error.

JSHALT:	CALL JSERRO		;Output JSYS error code
				;Fall through to QUIT routine

;Here to exit CHECKD.  Insure that terminal interrupt chars are off then halt.

QUIT:	CALL RESET		;[39] Insure that all files closed now
	MOVEI T1,.TICCP
	DTI
	MOVEI T1,SUMBYT		;T1/CODE FOR ^Y
	DTI			;DEASSIGN ^Y FROM CHANNEL 2
	SKIPN JOBNO		;CAME FROM JOB 0?
	HALTF			;YES. ^C WASN'T ASSIGNED
	MOVEI T1,.TICCC		;T1/CODE FOR ^C
	DTI			;DEASSIGN ^C FROM CHANNEL 1
	HALTF
	JRST .-1
;ROUTINE TO READ IN THE HOME BLOCKS AND SET NSSUN AND FSSUN

HOMEIN:	CALL TRANSL		;GET REAL PS: NAME, IF ANY.
	MOVEI T1,1		;READ IN FIRST HOME BLOCK
	CALL GETHOM
	 JRST HOMIN2		;FAILED, TRY SECOND HOME BLOCK
HOMIN1:
	SETOM RNUBLK+.MSRCH	;INIT FOR STRUCTURE SEARCH
	SETOM RNUBLK+.MSRCT	;ALSO INIT
	SETOM RNUBLK+.MSRUN	;ALSO INIT
	DO.
	 CALL GTASTS		;GET NEXT UNIT (ALIASES)
	 IFNSK.			;IF NO MORE THEN..
	  TMSG <		;TELL THE BAD NEWS
?Structure not found
>				;[39]
	  SETZM WRTLPF		;DON'T ALLOW SYSTEM TO COME UP.
	  RET			;BAD RETURN
	 ENDIF.
	 CALL STRMAX		;SEE IF THIS IS IT.
	 JRST TOP.		;NO, SEARCH NEXT
	ENDDO.
HOMIN3:	MOVE T1,[RNUBLK+.MSRSP,,SECPAG] ;FOUND IT, PREPARE FOR BLT
	BLT T1,BTWCYL		;COPY INFO OUT.
	MOVE T1,RNUBLK+.MSRLS	;GET LOST SECTORS/CYL.
	MOVEM T1,LPPCYL		;COPY INFO OUT.
	MOVE T1,RNUBLK+.MSTSP	;GET TRUE SECTORS/PAGE
	MOVEM T1,TRECPP		;COPY INFO OUT.
	IDIV T1,SECPAG		;FORM TRUE SECTORS/SECTOR
	IMUL T1,SECUNT		;COMPUTE TRUE SECTORS PER UNIT
	MOVEM T1,TRCUNT		;STASH IT
	MOVE T1,RNUBLK+.MSRST	;GET RETURNED SOFTWARE STATUS
	MOVEM T1,DRRST		;STASH IT
	MOVE T1,BATBUF+HOMFLG	;GET HOME BLOCK FLAGS
	MOVEM T1,HFLAGS		;REMEMBER THEM
	MOVE T1,BATBUF+HOMP4S	;GET # OF PAGES FOR SWAPPING PER UNIT
	IMUL T1,SECPAG		;GET # OF SWAPPING SECTORS
	MOVEM T1,NSSUN
	MOVE T1,BATBUF+HOMFST	;GET FIRST SWAPPING CYLINDER
	IMUL T1,SECCYL		;CONVERT TO SECTOR
	MOVEM T1,FSSUN		;SECTOR OFFSET FOR SWAPPING SPACE
	HLRZ T1,BATBUF+HOMLUN	;GET NUMBER OF PACKS IN SYSTEM STR
	MOVEM T1,NPACKS
	SETZM LOTRK		;FIRST CYLINDER IS ALWAYS 0
	IMUL T1,CYLUNT		;COMPUTE LAST CYLINDER
	MOVEM T1,HITRK		;HITRK = NTKUN*NPACKS
	SKIPN T1,BATBUF+HOMBTB	;SEE IF SIZE OF BIT TABLE IS DEFINED
	JRST [	MOVEI T1,OLDTOP	;NO. MUST HAVE BEEN BUILT BY OLD MONITOR
		MOVEM T1,BTBTOP	;SAVE OLD SIZE OF TOP HALF OF BIT TABLE
		MOVEI T1,OLDBOT	; AND OLD SIZE OF BOTTOM HALF
		MOVEM T1,BTBBOT
		JRST HOMIN4]
	MOVEM T1,BTBTOP		;BUILT BY RELEASE 2 OR LATER.  SAVE SIZE
				; OF TOP HALF OF BIT TABLE
	IMUL T1,BTWCYL		;COMPUTE NUMBER OF BIT WORDS IN BOTTOM
	MOVEM T1,BTBBOT		; AND SAVE IT
HOMIN4:	ADD T1,BTBTOP		;COMPUTE TOTAL SPACE IN FILE
	CAILE T1,BTBMAX		;WILL IT FIT IN ADDRESS SPACE?
	JRST [	TMSG<
?Bit table too large
>				;[39]
		SETZM WRTLPF	;don't allow system to come up
		RET]
	ADDI T1,<PGSIZ-1>	;ROUND UP TO NEXT PAGE
	IDIVI T1,PGSIZ		;COMPUTE NUMBER OF PAGES IN FILE
	MOVEM T1,BTBPGS		;SAVE SIZE OF BIT TABLE FILE
	RETSKP
HOMIN2:	MOVEI T1,12		;SECOND HOME BLOCK
	CALL GETHOM		;READ IT IN
	 JRST NOHOME		;FAILED
	JRST HOMIN1		;SUCCESS

NOHOME:	TMSG <Could not find a valid home block> ;[39]
	SETZM WRTLPF		;don't allow system to come up
	RET

GETHOM:	TXO T1,<FLD .DOPSR,DOP%AT> ;LOGICAL ADDRESS
	MOVE T4,STRDEV		;GET STRUCTURE NUMBER
	TXO T1,DOP%SN		;SET MASK TO ALL ONES
	MOVEI T2,NWSEC		;LENGTH OF BLOCK
	TXO T2,DOP%PS		;USE TRUE PHYSICAL SECTORS
	MOVEI T3,BATBUF		;ADR OF AREA TO READ INTO
	DSKOP
	JUMPN T1,R		;IF ERROR, RETURN
	MOVS T1,BATBUF+HOMNAM	;CHECK CONSISTENCY
	CAIE T1,'HOM'
	RET
	MOVE T1,BATBUF+HOMCOD	;AND SPECIAL CODE
	CAIE T1,CODHOM
	RET
	RETSKP			;HOME BLOCK OK
;ROUTINE TO READ IN ALL OF THE BAT BLOCKS AND SET UP THE
;ERROR PAIRS

BATIN:	SAVEQ
	STKVAR <LSXSEC,SAVWRK>
	MOVE T1,NPACKS		;# OF PACKS IN STRUCTURE
	IMUL T1,TRCUNT		;COMPUTE SECTORS IN STRUCTURE
	MOVEM T1,LSXSEC		;SAVE IT
	MOVEI Q1,2		;FIRST BAT ADDRESS
	MOVEM P1,SAVWRK		;SAVE PERMANENT REG
	MOVEI P1,BPRBLK		;START OF TABLE
	SETZM (P1)		;MARK TABLE AS EMPTY
GETBAT:	MOVE T1,Q1		;DISK ADDRESS
	TXO T1,<FLD .DOPSR,DOP%AT> ;LINEAR ADDRESS
	MOVE T4,STRDEV		;GET STRUCTURE NUMBER
	TXO T1,DOP%SN		;SET TO -1
	MOVEI T2,NWSEC		;SIZE OF A BLOCK
	TXO T2,DOP%PS		;USE TRUE PHYSICAL SECTORS
	MOVEI T3,BATBUF		;BUFFER FOR THE BAT BLOCK
	DSKOP			;GET THE BLOCK
	JUMPN T1,TRY2		;IF BAT4, TRY SECONDARY
	MOVS T1,BATBUF		;GET HEADER WORD
	CAIE T1,'BAT'		; A BAT BLOCK?
	JRST TRY2		;NO. TRY SECONDARY
	MOVE T1,BATBUF+BATCOD	;SEE IF UNIQUE CODE IS THERE
	CAIE T1,CODE		;IS IT?
	JRST TRY2		;NO. TRY SECONDARY THEN
GOTBAT:	MOVEI T4,BATBUF		;T4/ADDRESS OF START OF BAT BLOCK
	LOAD Q3,BTHCT,(T4)	;GET NUMBER OF PAIRS WRITTEN INITIALLY
	LOAD T3,BTMCT,(T4)	;GET NUMBER OF PAIRS MONITOR HAS WRITTEN
	MOVE Q2,Q3		;REMEMBER THE NUMBER WRITTEN BY THE MAPPER
	ADD Q3,T3		;TOTAL PAIRS WRITTEN
	CAILE Q3,MAXPAR		;DID BLOCK OVERFLOW?
	MOVEI Q3,MAXPAR		;YES. ONLY LOOK AT VALID PART THEN
	MOVEM Q3,OVERHD		;COUNT THESE AS OVERHEAD UNLESS THEY ARE
				; FOUND TO BE ASSIGNED LATER
	MOVEM Q3,BATCNT		;KEEP A SEPARATE COUNT, TOO
	JUMPE Q3,NONE		;IF NONQ1, GO TO NEXT UNIT
	MOVEI T3,BATBUF+4	;FIRST BAD PAIR IN BLOCK
	CALL NXTPR		;MOVE THE NEXT PAIR
	SOJG Q3,.-1		;DO ALL PAIRS
NONE:
	ADD Q1,TRCUNT		;NEXT PACK
	CAMGE Q1,LSXSEC		;OVER THE LAST PACK IN THE STRUCTURE?
	JRST GETBAT		;NO. GO DO IT
	MOVE P1,SAVWRK		;RESTORE PERMANENT REG
	RET			;AND DONE
; HERE TO MAVE A BAT BLOCK PAIR

; T3 POINTS TO THE PAIR WE ARE TO MOVE,
; Q1 HAS OFFSET OF DISK ADDRESS (I.E. 2 + (SECUNT*PACK))
; Q2 HAS NUMBER WRITTEN BY MAPPER, BUT LEFT TO BE PROCESSED
; Q3 HAS TOTAL NUMBER TO MOVE
; P1 POINTS TO WHERE THEY ARE GOING
; T1, T2, AND T4 ARE SCRATCH

NXTPR:	DMOVE T1,(T3)		; GET FIRST AND SECOND WORD
	DMOVEM T1,2(P1)		;SAVE ORIGINAL WORDS IN SECOND BLOCK HALF
	LOAD T4,ADD27,(T3)	;GET STARTING ADDRESS IF NEW FORMAT
	LOAD T1,BADT,(T3)	;GET TYPE FIELD
	SKIPN T1		;OLD FORMAT?
	LOAD T4,ADD18,(T3)	;YES, GET OLD STYLE ADDRESS INSTEAD
	ADD T4,Q1		;MAKE IT A LINEAR ADDRESS
	SUBI T4,2		;REMOVE BIAS FOR BAT BLOCK
	MOVE T1,T4		;COPY THE ADDRESS
	MOVE T2,SECCYL		;GET NUMBER OF SECTORS
	ADD T2,LPPCYL		;  PER CYLINDER
	IDIV T1,T2		;NUMBER OF CYLINDERS IN PHYSICAL ADDRESS
	IMUL T1,LPPCYL		;NUMBER OF LOST SECTORS IN PHYSICAL ADDRESS
	SUBB T4,T1		;TRANLSATE TO LOGICAL ADDRESS
	IDIV T1,SECPAG		;ROUND DOWN ADDRESS TO A PAGE BOUNDARY
	IMUL T1,SECPAG		;TO CATCH ERRORS IN MIDDLE OF A PAGE
	MOVEM T1,0(P1)		;SAVE AS FIRST ADDRESS OF REGION
	MOVE T1,0(T3)
	LSH T1,-^D27		;GET COUNT OF BAD BLOCKS
	ADDI T4,0(T1)		;CALCULATE LAST ONE
	MOVEM T4,1(P1)		;FINISH OFF PAIR
	SETZM 4(P1)		;FLAG END OF LIST
	MOVX T2,BT%MAP		;ASSUME IT WAS FROM THE MAPPER
	SOSGE Q2		;IF WE COUNT ALL THE MAPPER DID,
	MOVX T2,BT%WBM		;THE REST MUST BE BY THE MONITOR
	IORM T2,(P1)		;FLAG THE AUTHOR OF THIS ENTRY
	ADDI P1,4		;NEXT PAIR IN BUFFER
	ADDI T3,2		;NEXT PAIR IN BAT BLOCK
	RET
;PRIMARY BAT BLOCK WAS BAD. TRY THE SECONDARY

TRY2:	MOVE T1,Q1		;GET ADDRESS
	ADDI T1,11		;GET UP TO THE SECONDARY
	MOVE T4,STRDEV		;GET STRUCTURE NUMBER
	TXO T1,DOP%SN		;SET TO ONES
	TXO T1,<FLD .DOPSR,DOP%AT> ;LINEAR ADDRESS
	DSKOP			;READ IN THE SECONDARY
	JUMPN T1,NONE		;IF ERROR, NONE THERE
	MOVS T1,BATBUF
	CAIE T1,'BAT'		;A GOOD BAT BLOCK?
	JRST NONE		;NO. GIVE UP
	MOVE T1,BATBUF+BATCOD	;UNLIKELY CODE
	CAIE T1,CODE		;GOOD?
	JRST NONE		;NO. NO BAT BLOCKS
	JRST GOTBAT		;YES, USE THIS ONE
;INIBTB - INITIALIZE THE BIT TABLE

;ACCEPTS: NONE

;	CALL INIBTB

;RETURNS +1:ALWAYS

;THIS ROUTINE INITIALIZES THE LOCAL COPY OF THE BIT TABLE USING THE SAME CODE
;AS THE MONITOR USES IN DSKAL1.  FIRST IT INITIALIZES THE TABLE SO THAT ALL
;PAGES ARE FREE. THEN IT ASSIGNS THE SPECIAL SYSTEM BLOCKS ON EVERY PACK
;AND CALLS SWPASN TO ASSIGN THE SWAPPING SPACE

INIBTB:	SAVEQ
	STKVAR <LSTPAG>
	MOVE T1,PAGCYL		;GET NUMBER OF PAGES PER CYLINDER
	MOVN T2,BTBTOP		;GET SIZE OF TOP HALF OF BIT TABLE
	HRLZS T2		;T2/(-COUNT,,OFFSET IN TOP HALF)
INIBT2:	MOVEI T3,0(T2)		;GET OFFSET
	ADDI T3,LOCBTB		;ADDRESS OF CURRENT WORD
	MOVEM T1,0(T3)		;STORE FULL COUNT FOR EACH CYLINDER
	AOBJN T2,INIBT2		;GO TO NEXT WORD
	MOVE T2,BTBTOP		;START AT BEGINNING OF BIT PART OF BIT TABLE
	ADDI T2,LOCBTB		;COMPUTE ADDRESS OF FIRST BIT WORD
INIBT1:	SETOM 0(T2)		;INIT ONE BIT WORD
	SUBI T1,^D36		;REDUCE COUNT OF PAGES (1 BIT PER PAGE)
	CAILE T1,^D36		;LAST WORD?
	AOJA T2,INIBT1		;NO. GO INITIALIZE IT
	MOVN T1,BITS-1(T1)	;LAST WORD PARTIALLY FULL. SET ONLY VALID BITS
	MOVEM T1,1(T2)		;STORE LAST WORD FOR FIRST CYLINDER
	MOVEI T1,LOCBTB		;CONSTRUCT STARTING LOCATIONS FOR BLT
	HRLS T1			;(START OF TABLE,,START OF TABLE)
	MOVE T3,BTBTOP		;GET SIZE OF TOP HALF OF BIT TABLE
	HRLS T3			; IN BOTH HALVES
	ADD T1,T3		;(START OF BOTTOM HALF,,START OF BOTTOM HALF)
	ADD T1,BTWCYL		;(START OF BOTTOM HALF,,2ND GROUP OF WORDS)
	MOVEI T2,LOCBTB		;CONSTRUCT LIMIT FOR BLT
	ADD T2,BTBTOP		;POINT TO BOTTOM HALF OF BIT TABLE
	ADD T2,BTBBOT		;POINT JUST BEYOND END
	SUBI T2,1		;POINT TO LAST WORD FOR LIMIT OF BLT
	BLT T1,0(T2)		;COPY GROUPS OF BIT WORDS TO REST OF TABLE

	; FALL INTO NEXT PAGE
;ASSIGN THE HOME BLOCKS

	SETZM NBAD		;INITIALIZE COUNT OF ERRORS
	SETOM PAGNN		;INDICATE NOT A FILE PAGE
	MOVSI Q3,-NHOME		;Q3/(-COUNT,,OFFSET TO HOME TABLE)
	SETOM LSTPAG		;INITIALIZE LAST PAGE ASSIGNED

;LOOP OVER SPECIAL SECTORS IN HOME BLOCK TABLE

HOMAS1:	MOVE T1,HOME(Q3)	;GET SECTOR NUMBER WITHIN UNIT
	IDIV T1,SECPAG		;CONVERT TO PAGE
	CAMN T1,LSTPAG		;SAAME AS LAST PAGE ASSIGNED?
	JRST HOMAS3		;YES. DON'T ASSIGN IT AGAIN

;ASSIGN THIS PAGE FOR ALL UNITS

	MOVEM T1,LSTPAG		;SAVE LAST PAGE ASSIGNED
	MOVN Q2,NPACKS		;NO. GET NUMBER OF UNITS IN STRUCTURE
	HRLZS Q2		;Q2/(-COUNT,,UNIT NUMBER)
HOMAS2:	MOVEI T1,0(Q2)		;GET UNIT NUMBER
	IMUL T1,SECUNT		;COMPUTE FIRST SECTOR IN THIS UNIT
	ADD T1,HOME(Q3)		;T1/SECTOR TO ASSIGN
	MOVX F,MR%SPC		;INDICATE SPECIAL BLOCKS
	CALL MRKBTB		;ASSIGN PAGE
	 JFCL			;IGNORE FAILURE. ERROR HAS BEEN REPORTED
	AOBJN Q2,HOMAS2		;LOOP TO NEXT UNIT IN STRUCTURE
HOMAS3:	AOBJN Q3,HOMAS1		;LOOP TO NEXT SPECIAL SECTOR
	SKIPE NBAD		;DID WE GET ANY ERRORS?
	JRST [	TMSG <-  -  -  -  -  -  -  -
>				;YES. PRINT DIVIDER TO SEPARATE FROM FILE OUTPUT
		SETZM NBAD	;RESET COUNT
		JRST .+1]
	CALL SWPASN		;MARK THE SWAPPING PAGES
	RET
;DSKASA - ASSIGN PAGE IN LOCAL BIT TABLE

;ACCEPTS:
;	1/SECTOR NUMBER RELATIVE TO START OF STRUCTURE

;	CALL DSKASA

;RETURNS +1: ILLEGAL ADDRESS OR ADDRESS ALREADY ASSIGNED
;		T4/ERROR CODE
;	 +2: SUCCESS, PAGE ASSIGNED

;THIS ROUTINE ASSIGNS A PAGE IN THE LOCAL BIT TABLE USING THE SAME METHOD
;AS THE MONITOR USES IN DSKAL1.  IT ASSIGNS THE PAGE CONTAINING THE
;SPECIFIED SECTOR.  IF THE PAGE IS ALREADY ASSIGNED, IT TAKES THE ERROR
;RETURN.

DSKASA:	SAVEAC	<T1>		;save address we're working on
	SETZ T4,		;INITIALIZE ERROR FLAG
	IDIV T1,SECCYL		;T1/CYLINDER, T2/SECTOR WITHIN CYLINDER
	CAML T1,LOTRK		;NON-NEGATIVE CYLINDER NUMBER?
	CAML T1,HITRK		;WITHIN STRUCTURE'S LIMITS?
	JRST DSKAS1		;RETURN ILLEGAL ADDRESS
	CAML T1,BTBTOP		;WITHIN TOP HALF OF BIT TABLE?
	JRST DSKAS1		;NO. RETURN ILLEGAL ADDRESS
	MOVE T3,PAGCYL		;GET PAGES PER CYLINDER
	IMUL T3,SECPAG		;COMPUTE NUMBER SECTORS IN COMPLETE PAGES
	CAML T2,T3		;IS THIS SECTOR WITHIN A FULL PAGE (POSSIBLE
				; EXTRA SECTORS AT END OF CYLINDER)?
	JRST DSKAS1		;NO. RETURN ILLEGAL ADDRESS
	MOVE T4,T1		;4/CYLINDER NUMBER
	IDIV T2,SECPAG		;CONVERT SECTOR TO PAGE WITHIN CYLINDER
	JUMPN T3,DSKAS1		;MUST BE ON PAGE BOUNDARY
	IDIVI T2,^D36		;GET INDEX TO BIT WORD WITHIN CYLINDER
	IMUL T1,BTWCYL		;OFFSET IN BOTTOM FOR THIS CYLINDER
	ADD T1,T2		;OFFSET IN BOTTOM FOR THIS PAGE
	ADD T1,BTBTOP		;OFFSET IN BIT TABLE FOR BIT WORD
	MOVE T3,BITS(T3)	;BIT FOR THIS PAGE
	TDNN T3,LOCBTB(T1)	;IS PAGE ALREADY ASSIGNED?
	JRST DSKAS2		;YES. REPORT MULTIPLY ASSIGNED ADDRESS
	ANDCAM T3,LOCBTB(T1)	;NO. ASSIGN IT
	SOS LOCBTB(T4)		;REDUCE FREE COUNT
	RETSKP

DSKAS1:	MOVX T4,ER%IDA		;INDICATE ILLEGAL ADDRESS
	RET
DSKAS2:	MOVX T4,ER%MDA		;INDICATE MULTIPLY ASSIGNED
	RET
;ROUTINE TO ASSIGN THE SWAPPING BLOCKS
;	CALL SWPASN
;RETURNS +1:	ALWAYS

SWPASN:	MOVN P1,NPACKS		;SET UP AN AOBJN POINTER
	HRLZS P1		;FOR ALL PACKS IN SYSTEM
	SETZM NBAD		;INITIALIZE COUNT OF ERRORS
	SETOM PAGNN		;INDICATE NOT A FILE PAGE
SWPAS1:	MOVE P2,SECUNT		;GET # OF SECTORS PER UNIT
	IMULI P2,0(P1)		;GET LOGICAL ADR OF START OF THIS PACK
	ADD P2,FSSUN		;GET START OF SWAPPING SPACE ON UNIT
	MOVE P3,NSSUN		;GET # OF SWAPPING SECTORS PER UNIT
	ADD P3,SECPAG		;MAKE SURE TO EVEN UP TO FULL PAGE
	SUBI P3,1
	IDIV P3,SECPAG		;GET # OF PAGES FOR SWAPPING
	JUMPE P3,SWPAS3		;IF NO SWAPPING SKIP UNIT
SWPAS2:	MOVE T1,P2		;GET NEXT PAGE TO BE ASSIGNED
	MOVX F,MR%SWP		;INDICATE THIS IS SWAPPING SPACE
	CALL MRKBTB		;ASSIGN THE PAGE
	 JFCL			;IGNORE FAILURE.  ERROR HAS BEEN REPORTED
	ADD P2,SECPAG		;STEP TO THE NEXT PAGE
	SOJG P3,SWPAS2		;LOOP BACK FOR ALL PAGES ON UNIT
SWPAS3:	AOBJN P1,SWPAS1		;LOOP BACK FOR ALL UNITS
	SKIPE NBAD		;DID WE GET ANY ERRORS?
	 JRST [	TMSG <- - - - - - -
>				;PRINT DIVIDER TO SEPARATE FROM FILE OUTPUT
		SETZM NBAD	;RESET COUNT OF ERRORS
		JRST .+1]
	RET			;AND RETURN
;SCAN ALL DIRECTORIES. CALLS SCANFD WITH ONE DIRECTORY, LOOPS THROUGH ALL DIRECTORIES

SCANDI:

;SET UP STR:<ROOT-DIRECTORY> IN ROOTDR

	HRROI T1,ROOTDR		;T1/ DESTINATION  POINTER
	HRROI T2,STRNAM		;T2/ SOURCE IS STRUCTURE NAME
	SETZ T3,		;T3/ STOP ON NULL
	SOUT			;PUT STRUCTURE NAME IN ROOTDR
	MOVEI T2,":"		;T2/ A COLON
	IDPB T2,T1		;ADD A COLON AFTER STRUCTURE
	HRROI T2,[ASCIZ/<ROOT-DIRECTORY>/]
	SETZ T3,		;STOP ON NULL
	SOUT			;ADD <ROOT-DIRECTORY> TO STRUCTURE
	MOVEM T1,ROOTPT		;SAVE POINTER TO END
	CALL FRSDIR		;GET THE FIRST DIRECTORY
	 RET			;FAILED. QUIT
SCAND2:	CALL GDNAM		;GET NAME & NUMBER
	 JRST SCAND1		;SKIP IF ERROR
	CALL CKDIR		;CHECK AND REBUILD IF NECESSARY
	CALL SCANFD		;SCAN THIS DIRECTORY
SCAND1:	CALL NXTDIR		;GET NEXT DIRECTORY
	 JRST [	TXNN T1,RC%NMD	;NO MORE DIRECTORIES?
		RET		;NO, SOME OTHER ERROR, PASS IT DOWN
		RETSKP]		;YES, DONE, INDICATE SUCCESS
	JRST SCAND2		;GO CHECK THIS ONE
;SCAN ONE DIRECTORY. CALLS SCAN3 FOR A SYMBOL TABLE ENTRY, LOOPS THROUGH
;ALL SYMBOL TABLE ENTRIES

;DIRNUM/DIRECTORY NUMBER

SCANFD:	HRRZ T1,DIRNUM		;USE NUMBER ONLY (ON THIS STR)
	CALL SETFD		; MAP THE APPROPRIATE DIRECTORY
				;DIRORG IS STARTING LOCATION
	 RET			;FAILED TO MAP OR HEADER WAS BAD
	MOVE T1,[POINT 7,DIRNAM]
	MOVE T2,DIRORA
	LOAD T2,DRNUM,(T2)	; GET DIRECTORY NUMBER
	HRL T2,STRDEV		; ADD STR UNIQUE CODE
	DIRST			;PUT NAME OF DIRECTORY IN DIRNAM
	 JFCL
	MOVEI T2,0
	IDPB T2,T1		;TERMINATE WITH NULL
	MOVE T4,DIRORA
	LOAD T1,DRSTP,(T4)	;GET LAST WORD USED BY SYMBOL TABLE
	MOVEM T1,SYMTOP
	LOAD T4,DRSBT,(T4)	;GET ADDRESS OF START OF SYMBOL TABLE

;NOTE: ASSUMES HEADER IS 2 WORDS

SCAN1:	ADDI T4,.SYMLN		; STEP TO NEXT SYMBOL
	CAMGE T4,SYMTOP		; REACHED END OF SYMBOL TABLE?
	JRST SCAN2		; NO

;END OF SYMBOL TABLE. UNMAP THE DIRECTORY

	CALL UNMAPD		;UNMAP THE DIRECTORY
	RET

SCAN2:	MOVE T3,T4		; GET POINTER TO SYMBOL
	ADD T3,DIRORA		; GET ABS ADR OF SYMBOL
	LOAD T1,SYMET,(T3)	; GET ENTRY TYPE
	JUMPN T1,SCAN2A		; IF NOT A NAME, SKIP IT
	LOAD T1,SYMAD,(T3)	; GET ADDRESS OF FDB
	ADD T1,DIRORA		; GET ABS ADR OF FDB
	LOAD T2,FBNAM,(T1)	; GET POINTER TO NAME STRING
	 ERJMP [ TMSG <%Illegal address in symbol table> ;[39]
		 CALL BADBLK	;PRINT DIRECTORY NAME
		 JRST SCAN1]	;SKIP THIS ONE AND CONTINUE
	ADD T2,[DIRORG+1]	; GET ABS ADR OF START OF STRING
	MOVEM T2,DEFNAM
	PUSH P,T4		; SAVE POINTER TO SYMBOL TABLE
	LOAD T4,SYMAD,(T3)	; GET RELATIVE ADR OF FDB FROM SYMBOL TABLE
	CALL SCAN3		; GO DO NAME CHAIN
	POP P,T4		; GET BACK INDEX INTO SYMBOL TABLE
SCAN2A:	JRST SCAN1		; LOOP BACK FOR ALL SYMBOLS
;MAP ONE DIRECTORY INTO THIS FORK

;	T1/DIRECTORY NUMBER

SETFD:	PUSH P,T1		;SAVE DIRNUM
	CALL GTFILE		;GET JFN ON DIRECTORY FILE
	HRRZ T1,FDJFN		;OPEN THE DIRECTORY FILE
	MOVE T2,[440000,,OF%RD+OF%THW]
	OPENF
	 JRST [	TMSG <%OPENF failed on directory > ;[39]
		HRROI T1,DIRNAM	;T1/POINTER TO DIRECTORY NAME
		PSOUT		;PRINT DIRECTORY
		TMSG< - Skipped>
		JSERR		;OPEN FAILET4, GO TYPE OUT ERROR
		POP P,T1	;RESTORE DIRECTORY NUMBER
		RET]
	HRLZ T1,FDJFN		;NOW MAP IN DIRECTORY
	MOVE T2,[.FHSLF,,DIRORG/1000]
	MOVE T3,[PM%CNT+PM%RD+NDIRPG]
	PMAP
	POP P,T1		;GET BACK DIR #
	CALL DR0CHK		;CHECK CONSISTENCY OF HEADER
	 JRST [	CALL UNMAPD	;BAD HEADER. UNMAP THE DIRECTORY
	 	CALLRET BADBLK]	;HEADER IS BAD
	RETSKP

;ROUTINE TO UNMAP A DIRECTORY

UNMAPD:	SETO T1,			;PMAP -1 TO DIRORG
	MOVE T2,[.FHSLF,,DIRORG/1000]
	MOVE T3,[PM%CNT+PM%RD+NDIRPG]
	PMAP			;UNMAPPED!
	HRRZ T1,FDJFN		;T1/ JFN
	CLOSF			;CLOSE THIS FILE
	 JFCL
	RET			;AND EXIT
;GTFILE - GET FILE NAME FOR THIS DIRECTORY AND GET A JFN ON IT

;ASSUMES DIRNAM POINTS TO STR:<DIRECTORY>

;	CALL GTFILE

;RETURN +1: ALWAYS
;		FDJFN/ JFN FOR DIRECTORY FILE

GTFILE:	MOVE T1,[POINT 7,DIRNAM] ;POINT TO STR:<DIRECTORY>
	SETZM DOTPTR		;INDICATE DOT NOT FOUND YET
	SETZM BRKPTR		;INDICATE BRACKET NOT FOUND YET
GTFIL1:	ILDB T2,T1		;GET NEXT CHARACTER IN STRING
	CAIN T2,"<"		;LEFT BRACKET?
	JRST [	MOVEM T1,BRKPTR	;YES. SAVE ITS POINTER
		JRST GTFIL1]	;GO GET NEXT CHARACTER
	CAIN T2,"."		;IS IT A DOT?
	JRST [	MOVEM T1,DOTPTR	;YES. SAVE ITS POINTER
		JRST GTFIL1]	;GO GET NEXT CHARACTER
	CAIE T2,">"		;IS IT A RIGHT BRACKET?
	JRST GTFIL1		;NO. GO GET NEXT CHARACTER
	SKIPN DOTPTR		;FOUND RIGHT BRACKET. HAVE WE SEEN A DOT?
	JRST GTFIL2		;NO. MUST BE IN <ROOT-DIRECTORY>

;HERE WHEN THIS IS A SUBDIRECTORY.  ;WE HAVE STR:<DIRECTORY.SUBDIRECTORY>.
;CONVERT TO STR:<DIRECTORY>SUBDIRECTORY.DIRECTORY

	DPB T2,DOTPTR		;REPLACE DOT WITH RIGHT BRACKET
	MOVEI T2,"."		;GET A DOT
	DPB T2,T1		;REPLACE RIGHT BRACKET WITH DOT
	HRROI T2,[ASCIZ/DIRECTORY.1/] ;T2/ SOURCE IS THIS STRING
	SETZ T3,		;T3/ STOP ON NULL
	SOUT			;FORM STR:<DIR>SUBDIR.DIRECTORY
	HRROI T2,DIRNAM		;SET UP POINTER TO DIRECTORY
	JRST GTFIL3		;GO GET JFN
;HERE WHEN DIRECTORY IS IN ROOT-DIRECTORY. FORM STR:<ROOT-DIRECTORY>DIR.DIRECTORY

GTFIL2:	MOVE T1,ROOTPT		;POINT TO END OF STR:<ROOT-DIRECTORY>
	MOVE T2,BRKPTR		;POINT TO LEFT BRACKET
	MOVEI T3,^D40		;DIRECTORY NAME <=39 CHARACTERS
	MOVEI T4,">"		;STOP ON RIGHT BRACKET
	SOUT			;COPY DIRECTORY NAME
	SETOM T3		;BACK UP POINTER OVER THE BRACKET
	IBP T3,T1
	MOVEM T3,T1		;T1/ DESTINATION IS END OF DIRECTORY NAME
	HRROI T2,[ASCIZ/.DIRECTORY/] ;T2/ POINTER TO SOURCE
	SETZ T3,		;T3/ STOP ON NULL
	SOUT			;COPY ".DIRECTORY" TO END OF STRING
	HRROI T2,ROOTDR		;POINT TO START OF THIS STRING
	JRST GTFIL3		;GO GET JFN

;T2 POINTS TO FILE SPEC. GET A JFN ON THIS DIRECTORY FILE

GTFIL3:	MOVX T1,GJ%PHY!GJ%SHT!1	;PHYSICAL ONLY, SHORT BLOCK, GENERATION 1
	GTJFN%			;GET A JFN
	IFJER.			;[37] If error,
	  TMSG <
?Failed to get JFN for directory: >
	  MOVE T1,T2		;[37] Get directory string
	  PSOUT%		;[37] Display it
	  TMSG <
Because: >			;[37] Preface the JSYS error
	  CALL CMNDE1		;[37] (/) Now show JSYS error
	  HALTF%		;[37] Stop
	  JRST .-1		;[37] And can't continue (possible structure damage)
	ENDIF.			;[37]
	HRRZM T1,FDJFN		;SAVE JFN
	RET
;DO ONE NAME. STARTS WITH FDB FOR ONE NAME.  CALLS SCAN7 TO DO ALL GENERATIONS FOR
;ONE EXTENSION.  LOOPS THROUGH ALL EXTENSIONS FOR ONE NAME

;	T4/OFFSET IN DIRECTORY OF FDB

SCAN3:	SKIPN T4
	RET
	ADD T4,DIRORA		; GET ABS ADR OF FDB
	MOVE T1,T4

;NOTE: REPEATED BELOW

	CALL FDBCHK		; MAKE SURE THIS IS A GOOD FDB
	 CALLRET BADBLK		; IT IS NOT
	LOAD T1,FBEXT,(T4)	; GET ADR OF EXT STRING
	ADD T1,[DIRORG+1]
	MOVEM T1,DEFEXT
	PUSH P,T4
	SUB T4,DIRORA		; GET RELATIVE ADR OF FDB
	CALL SCAN7
	POP P,T4
	LOAD T4,FBEXL,(T4)	; STEP TO NEXT EXT
	JRST SCAN3

;DO ONE EXTENSION. CALLS BUILD FOR ONE FDB.  LOOPS THROUGH ALL VERSIONS.

;	T4/OFFSET IN DIRECTORY OF FDB

SCAN7:	SKIPN T4
	RET
	ADD T4,DIRORA		; GET ABS ADR OF FDB
	MOVE T1,T4
	CALL FDBCHK		; CHECK THE QUALITY OF THIS FDB
	 CALLRET BADBLK		; NO GOOD
	LOAD T1,FBGEN,(T4)	; GET VERSION #
	HRRM T1,DEFVER
	PUSH P,T4
	CALL BUILD		; DO ONE VERSION
	POP P,T4
	LOAD T4,FBGNL,(T4)	; STEP TO NEXT GENERATION FDB
	JRST SCAN7

;BADBLK - PRINT MESSAGE ABOUT BAD BLOCK IN DIRECTORY

BADBLK:	TMSG < in directory >
	HRROI T1,DIRNAM		;T1/POINTER TO DIRECTORY NAME
	PSOUT			;PRINT DIRECTORY NAME
	TMSG <
>
	RET
;ROUTINE CALLED FOR EACH FILE--FIND ALL ADDRESSES IN PT'S OF FILE

;	T4/ADDRESS OF FDB

BUILD:	STKVAR<DSKAD1,FDBCNT,PAGNO>
	SKIPN CHKFLF		;RETURN IMMED IF NOT CHECKING FILES
	RET
	SKIPN T1,.FBADR(T4)	;GET DISK ADDRESS OF INDEX BLOCK
	RET			;disc address
	TLNE T1,(FILNB)		;IS IT A NEW FILE?
	 JRST	[TMSG <%>	;warning
		CALL PNTFIL	;print file name
		TMSG < is a "new" file
>
		RET]		;new file, return.
	SETZM ZSTART		;CLEAR COUNTS OF ERRORS
	MOVE T2,[XWD ZSTART,ZSTART+1]
	BLT T2,ZEND
	SETZM PAGCNT		;INIT COUNT OF FILE PAGES FOR THIS FILE
	LOAD T3,FBNPG,(T4)	;GET COUNT IN FDB OF FILE PAGES
	MOVEM T3,FDBCNT		;SAVE IT FOR CHECKING LATER
	SETOM PAGNN		;INDICATE NOT IN FILE PAGE
	MOVE T3,.FBCTL(T4)	;GET FLAGS IN FDB
	TXNE T3,FB%LNG		;IS THIS A LONG FILE?
	JRST BUILNG		;YES. GO DO THE PAGE TABLE TABLE
	MOVX F,MR%PT		;INDICATE THIS IS PAGE TABLE
	CALL MRKBTB		;MARK BIT TABLE TO SHOW PAGE USED BY
				; INDEX BLOCK
	JRST [	AOS NDE		;FAILED. INDICATE BAD ADDRESS FOR PAGE TABLE
		JRST BUILD1]
	SETZM PAGNN		;INITIALIZE FILE PAGE NUMBER
	MOVE T3,.FBCTL(T4)	; GET FLAG BITS
	TXNE T3,FB%DIR		; IS THIS A DIRECTORY FILE?
	MOVX F,MR%DIR		; YES, SAY SO
	CALL MRKPT		;MARK BIT TABLE TO SHOW PAGES POINTED
				; TO BY THE PAGE TABLE
	JRST BUILD1		;GO PRINT ERRORS IF ANY
;SCAN LONG FILE
;	T1/DISK ADDRESS OF PAGE TABLE TABLE

BUILNG:	MOVEM T1,DSKAD1		;SAVE ADDRESS OF PAGE TABLE TABLE
	MOVX F,MR%PTT 		;INDICATE THIS IS A PAGE TABLE TABLE
	CALL MRKBTB		;MARK BIT TABLE TO SHOW PAGE USED BY
				; PAGE TABLE TABLE
	 JRST [	AOS NPTTE	;INDICATE BAD ADDRESS FOR PAGE TABLE TABLE
		JRST BUILD1]	;GIVE UP ON THIS FILE
	MOVEI T2,PTT		;T2/WHERE TO READ PAGE TABLE TABLE INTO
	CALL DSKRED		;READ THE PAGE TABLE TABLE
	JRST [	AOS NBPTT	;INDICATE PAGE TABLE TABLE UNREADABLE
		AOS NBAD	;INCREMENT COUNT OF ALL ERRORS
		JRST BUILD1]	;GIVE UP ON THIS FILE
	MOVEI T1,PTT		;T1/ADDRESS OF WHERE TO LOOK FOR PTT
	CALL CHKCSM		;CHECK/RESET CHECKSUM
	 JRST [	AOS NBPTT	;NO GOOD
		AOS NBAD
		JRST BUILD1]
	SETZM PAGNN		;INITIALIZE COUNT OF FILE PAGES
	MOVSI P1,-1000		;P1/(-COUNT,,OFFSET IN PAGE TABLE TABLE)


;LOOP THROUGH ENTRIES IN PAGE TABLE TABLE MARKING BIT TABLE FOR PAGE USED
;BY PAGE TABLE AND PAGES USED BY FILE AS INDICATED BY PAGE TABLE

BUILN1:	MOVE T1,PTT(P1)		;GET DISK ADDRESS OF NEXT PAGE TABLE
	TLZ T1,(ADRMSK)		;GET STORAGE ADR
	JUMPE T1,[MOVEI T1,1000	;INCREMENT COUNT OF PAGES BY
		ADDM T1,PAGNN	; SIZE OF PAGE TABLE
		JRST BUILN2]	;GO TO NEXT ENTRY IN PAGE TABLE TABLE
	MOVEM T1,PTT(P1)
	MOVE T2,PAGNN		;SAVE CURRENT FILE PAGE NUMBER
	MOVEM T2,PAGNO
	SETOM PAGNN		;INDICATE IN PAGE TABLE
	MOVX F,MR%PT		;INDICATE THIS IS A PAGE TABLE
	CALL MRKBTB		;MARK BIT TABLE TO SHOW PAGE USED BY PAGE TABLE
	JRST [	AOS NBPTTE	;INDICATE BAD ADDRESS IN PAGE TABLE TABLE
		MOVE T2,PAGNO	;RESTORE FILE PAGE NUMBER
		MOVEM T2,PAGNN
		JRST BUILN2]	;GO TO NEXT ENTRY IN PTT
	MOVE T2,PAGNO		;RESTORE FILE PAGE NUMBER
	MOVEM T2,PAGNN
	CALL MRKPT		;MARK BIT TABLE TO SHOW PAGES POINTED
				; TO BY PAGE TABLE
BUILN2:	SKIPN NIDA		;QUIT IMMED IF SEEN ILLEG ADDRESSES
	AOBJN P1,BUILN1		;GO TO NEXT ENTRY IN PAGE TABLE TABLE

;PAGE TABLE TABLE IS DONE

	JRST BUILD1
;HERE WHEN ALL PAGES FOR A FILE HAVE BEEN ASSIGNED AND ERROR COUNTS
;INCREMENTED.  FIX PAGE COUNT IF NEEDED AND REPORT SUMMARY OF ERRORS
;IF ANY.

BUILD1:	MOVE T2,PAGCNT		;GET LOCAL COUNT OF FILE PAGES
	ADDM T2,TOTPGS		;INCREMENT TOTAL FOR ALL FILES
	SKIPG T1,NBAD		;DID WE GET ANY ERRORS ON THIS FILE?
	JRST [	SKIPE DALIST	;NO. ARE WE SEARCHING?
		RET		;YES. DON'T FIX THE PAGE COUNT
		CAME T2,FDBCNT	;DOES LOCAL COUNT AGREE WITH THE FDB?
		CALL FIXCNT	;NO. FIX IT IN THE FDB
		RET]

;PRINT SUMMARY OF ERRORS FOR THIS FILE

	TMSG <Summary for file >
	CALL PNTFIL		;PRINT THE FILE SPEC

;THE COUNTS THAT ARE REPORTED HERE HAVE BEEN INCREMENTED BY MRKPT,
;MRKBTB AND BUILD.  THEY WERE CLEARED BY THE BLT IN BUILD AND THUS
;CONTAIN THE ERROR COUNTS FOR THE CURRENT FILE ONLY.

; NEXT PAGE ....
	HRROI T1,[ASCIZ /
Faulty page table addresses in FDB: /]
	SKIPE T2,NDE
	CALL BUILDE
	HRROI T1,[ASCIZ /
Faulty long file page table addresses in FDB: /]
	SKIPE T2,NPTTE
	CALL BUILDE
	HRROI T1,[ASCIZ /
Faulty addresses in page table: /]
	SKIPE T2,NBPTE
	CALL BUILDE
	HRROI T1,[ASCIZ /
Page tables unreadable: /]
	SKIPE T2,NBPT
	CALL BUILDE
	HRROI T1,[ASCIZ /
Faulty addresses in long file page table: /]
	SKIPE T2,NBPTTE
	CALL BUILDE
	HRROI T1,[ASCIZ /
Long file page tables unreadable: /]
	SKIPE T2,NBPTT
	CALL BUILDE
	HRROI T1,[ASCIZ /
Illegal addresses: /]
	SKIPE T2,NIDA
	CALL BUILDE
	HRROI T1,[ASCIZ /
Multiply assigned addresses: /]
	SKIPE T2,NMDA
	CALL BUILDE
	HRROI T1,[ASCIZ /
Search addresses found: /]
	SKIPE T2,NSDA
	CALL BUILDE
	HRROI T1,[ASCIZ /
Disk read errors: /]
	SKIPE T2,NDSKER		;DISK ERRORS?
	CALL BUILDE
	HRROI T1,[ASCIZ /
File addresses not in bit table: /]
	SKIPE T2,NNBT		;PAGES ASSIGNED TO FILES BUT NOT IN BIT TABLE?
	CALL BUILDE
	HRROI T1,[ASCIZ /
Assigned pages marked in BAT blocks: /]
	SKIPE T2,NABAT		;ANY ASSIGNED PAGES THAT ARE BAD?
	CALL BUILDE
	TMSG <
-  -  -  -  -  -  -  -
>
	RET
BUILDE:	PSOUT			; THE STRING POINTER TO BY T1
	MOVEI T3,^D10		; BASE 10 TYPEOUT
	CALLRET TTNOUT		; AND TYPE THE NUMBER

;PNTFIL - PRINT FILE SPEC

PNTFIL:	HRROI T1,DIRNAM
	PSOUT			;PRINT STR:<DIRECTORY>
	DMOVE	T1,[G2BPT 2,7,0]
	MOVE	T2,DEFNAM
	MOVE	T3,[POINT 7,TMPBUF]
	ILDB	T4,T1
	IDPB	T4,T3
	SKIPE	T4
	JRST	.-3
	HRROI	T1,TMPBUF
	PSOUT			;PRINT THE FILE NAME
	MOVEI T1,"."
	PBOUT
	DMOVE	T1,[G2BPT 2,7,0]
	MOVE	T2,DEFEXT
	MOVE	T3,[POINT 7,TMPBUF]
	ILDB	T4,T1
	IDPB	T4,T3
	SKIPE	T4
	JRST	.-3
	HRROI	T1,TMPBUF
	PSOUT			;PRINT EXTENSION
	MOVEI T1,"."
	PBOUT
	HRRZ T2,DEFVER
	MOVEI T1,.PRIOUT
	MOVEI T3,^D10
	NOUT			;PRINT VERSION
	 JFCL
	RET
;MRKPT - MARK THE BIT TABLE FOR ONE PAGE TABLE

;ACCEPTS:
;	T1/DISK ADDRESS OF INDEX BLOCK
;	F/MR%PT (PASSED TO MRKBTB)

;RETURNS +1:ALWAYS

;THIS ROUTINE IS CALLED DURING THE BITTABLE, REBUILD, AND SCAN FUNCTIONS.
;GIVEN THE DISK ADDRESS OF A PAGE TABLE (INDEX BLOCK), IT READS THE
;PAGE TABLE AND SCANS THE ADDRESSES IN IT.  FOR EACH NON-ZERO ADDRESS
;IT CALLS MRKBTB TO ASSIGN THE PAGE POINTED TO BY THE ADDRESS

MRKPT:	PUSH P,T1
	MOVEI T2,PT		;T2/STARTING ADDRESS TO READ INTO
	CALL DSKRED		;READ INDEX BLOCK
	JRST [	AOS NBPT	;INCREMENT COUNT OF UNREADABLE PAGE TABLES
		AOS NBAD	;INCREMENT TOTAL COUNT OF ERRORS
		POP P,T1	;RESTORE DISK ADDRESS
		RET]		;IGNORE THIS PAGE TABLE
	MOVEI T1,PT		;T1/ADDRESS OF PAGE TABLE
	CALL CHKCSM		;CHECK/RESET CHECKSUM
	 JRST [	AOS NBPT	;INCREMENT COUNT OF UNREADABLE PAGE TABLES
		AOS NBAD	;INCREMENT TOTAL COUNT OF ERRORS
		POP P,T1	;RESTORE DISK ADDRESS
		RET]		;IGNORE THIS PAGE TABLE

;LOOP THROUGH WORDS IN PAGE TABLE

	MOVSI P2,-1000		;P2/(-COUNT,,OFFSET INTO PT)
MRKPT1:	MOVE T1,PT(P2)		;GET NEXT ADDRESS FROM PAGE TABLE
	TLZ T1,(ADRMSK)		;GET STORAGE ADR
	JUMPE T1,MRKPT2		;SKIP IF ZERO
	MOVEM T1,PT(P2)		;SAVE ADDRESS OF PAGE IN FILE
	CALL MRKBTB		;ASSIGN PAGE IN BOTH BIT TABLES
	 AOS NBPTE		;FAILED. INCREMENT COUNT OF BAD ADDRESSES IN PT
MRKPT2:	AOS PAGNN		;POINT TO NEXT FILE  PAGE
	SKIPN NIDA		;QUIT IMMED IF SEEN ILLEG ADDRESSES
	AOBJN P2,MRKPT1		;GO TO NEXT ENTRY

;END OF PAGE TABLE

	POP P,T1		;RESTORE ADDRESS OF INDEX BLOCK
	RET
;MRKBTB - MARK THE BIT TABLE FOR ONE PAGE

;ACCEPTS:
;	T1/DISK ADDRESS TO MARK IN BIT TABLE
;	F/FLAG INDICATING WHAT CALLED THIS ROUTINE (MEANINGFUL ONLY IF
;	  PAGNN IS NEGATIVE)

;RETURNS +1:DISK ADDRESS BAD
;		1/DISK ADDRESS WITH BITS 0-14 TURNED OFF
;	  +2:DISK ADDRESS GOOD
;		1/DISK ADDRESS WITH BITS 0-14 TURNED OFF

;THIS ROUTINE IS CALLED DURING THE BITTABLE, REBUILD, AND SCAN FUNCTIONS
;WHEN A PAGE HAS BEEN IDENTIFIED AS IN USE (FILE PAGE, SWAP PAGE, ETC.)
;ACTION DEPENDS ON FUNCTION:
;SCAN - SEE IF THIS ADDRESS IS BEING SEARCHED FOR
;BITTABLE - ASSIGN PAGE IN LOCAL BIT TABLE
;REBUILD - ASSIGN PAGE IN LOCAL AND SYSTEM BIT TABLE
;THIS ROUTINE PRINTS ONE-LINE MESSAGES THAT CONTAIN THE DISK ADDRESS AND
;DESCRIPTION OF HOW THE PAGE IS USED

MRKBTB:	TLZ T1,(DSKMSK)
	SAVET
	STKVAR <ASAVE>
	MOVEM T1,ASAVE		;SAVE DISK ADDRESS
	TXNN F,MR%DIR		;IS THIS A DIRECTORY FILE?
	SKIPGE PAGNN		;FILE PAGE?
	JRST [	AOS OVERHD	;DIRECTORY PAGE OR OVERHEAD SO COUNT IT
		JRST MRKBT5]
	AOS PAGCNT		;YES. COUNT AS FILE PAGE
MRKBT5:	CALL SEEADR		;SEE IF ADDRESS IS MARKED IN BAT BLOCKS
	 JRST [	MOVX T4,ER%BAT	;INDICATE THIS IS A BAD BLOCK
		SOS OVERHD	;PREVIOUSLY COUNTED AS OVERHEAD. PAGE
				; IS IN USE
		SOS BATCNT	;DECREMENT COUNT OF UNUSED BAD PAGES
		JRST BATA]	;GO REPORT IT

MRKBT4:	SKIPN T2,DALIST		;AOBJN POINTER TO LIST OF ADDRESSES INPUT
				; VIA SCAN COMMAND
	 JRST MRKBT1		;NOT SCANNING FOR DISK ADDRESSES

;SCANNING FOR ADDRESSES CONTAINED IN DATAB LIST.  SEE IF THIS ADDRESS
;IS IN THE LIST.

	CAMN T1,DATAB(T2)
	 JRST SDA		; ADDRESS IS BEING SEARCHED
	AOBJN T2,.+1
	AOBJN T2,.-3
	RETSKP			;NOT IN THE LIST. DON'T TRY TO MARK BIT TABLE
;DOING BIT TABLE CONSISTENCY CHECK. ASSIGN THIS PAGE IN BOTH BIT TABLES
;T1/SECTOR NUMBER RELATIVE TO START OF STRUCTURE

MRKBT1:	CALL DSKASA		;ASSIGN IN LOCAL BIT TABLE
	 JRST [	TXNE T4,ER%IDA	;FAILED.  ILLEGAL ADDRESS?
		JRST IDA	;YES. GO REPORT ERROR
		TXNE T4,ER%MDA	;NO. PAGE NOT AVAILABLE?
		JRST MDA	;YES. GO REPORT ERROR
		TMSG <
% DSKASA returned unknown error
>
		JRST .+1]
	MOVE T1,ASAVE		;T1/SECTOR NUMBER
	MOVE T2,STRDEV		;T2/STRUCTURE 0
	DSKAS			;TRY TO ASSIGN THE PAGE
	 RETSKP			;FAILED. GOOD.

;TRIED TO ASSIGN PAGE IN SYSTEM BIT TABLE AND SUCCEEDED.  THIS IS AN
;ERROR  BECAUSE SYSTEM SHOULD HAVE KNOWN ABOUT THE FILE PAGE

	SKIPE REBLDF		;IF REBUILDING, BIT TABLE HAS BEEN INITIALIZED
	RETSKP			; SO IGNORE

;ERROR CONDITIONS.  T4 CONTAINS ERROR FLAG.  IF ERROR WAS ILLEGAL ADDRESS
;OR MULTIPLY ASSIGNED, TAKE NON-SKIP RETURN SO CALLER CAN INCREMENT COUNT
;OF FAULTY ADDRESSES.  IF ADDRESS IS MARKED IN BAT BLOCKS, CONTINUE
;AS IF NOTHING HAD HAPPENED.

;PAGE IS NOT ASSIGNED IN SYSTEM BIT TABLE

	TMSG <Disk address >
	MOVE T2,ASAVE		;T2/SECTOR NUMBER
	MOVEI T3,10		;T3/RADIX
	CALL TTNOUT		;PRINT THE SECTOR NUMBER
	TMSG < not in bit table >
	SETZ T4,		;INDICATE NOT AN ERROR TO AVOID FAILURE RETURN
	AOS NNBT		;INCREMENT COUNT OF NOT IN BT'S
	JRST MRKBTP

;DISK ADDRESS IS INVALID

IDA:	TMSG <Illegal disk address >
	AOS NIDA		;INCREMENT COUNT OF ILLEGAL ADDRESS
	JRST SDA1
;THIS ADDRESS IS BEING SEARCHED FOR VIA SCAN COMMAND.

SDA:	TMSG <Found disk address >
	SETZ T4,		;INDICATE NOT AN ERROR TO AVOID NON-SKIP RETURN
	AOSA NSDA		;INCREMENT THE COUNT OF ADDRESSES FOUND
SDA1:	SETZM WRTLPF		;SUPPRESS LOST-PAGES FILE, ETC.
	MOVE T2,DATAB+1(T2)
	MOVEI T3,10
	CALL TTNOUT
	JRST MRKBTP

;PAGE WAS ALREADY ASSIGNED.

MDA:	MOVEM T1,DATAB+1(T2)	;Save address of multiply assigned page
	TMSG <Multiply assigned disk address >
	AOS NMDA		;INCREMENT COUNT OF MULTIPLY ASSIGNED ADDRESSES
	JRST SDA1

;THIS DISK ADDRESS IS RECORDED IN THE BAT BLOCKS.

BATA:	TMSG <Disk address >
	MOVE T2,ASAVE		;GET SECTOR NUMBER
	MOVEI T3,10		;T3/OCTAL
	CALL TTNOUT		;PRINT THE ADDRESS
	TMSG < marked in BAT blocks>
	AOS NABAT		;INCREMENT COUNT OF BAD ADDRESSES
	JRST MRKBTP		;GO PRINT THE FILE PAGE
;PRINT FILE PAGE WHERE ERROR OCCURRED

MRKBTP:	AOS NBAD		;INCREMENT COUNT OF TOTAL ERRORS
	SKIPGE T2,PAGNN		;GET PAGE NUMBER
	JRST MRKBT2		;NEGATIVE MEANS NOT A FILE PAGE
	TMSG <: File page >
	MOVEI T3,10		;T3/RADIX
	CALL TTNOUT		;PRINT PAGE NUMBER
	JRST MRKBT3

;NOT A FILE PAGE. F INDICATES WHAT IT IS.

MRKBT2:	TXNE F,MR%PT		;IS THIS A PAGE TABLE?
	JRST [	TMSG <: Page table> ;PAGE TABLE
		JRST MRKBT3]
	TXNE F,MR%PTT		;NO. IS IT A PAGE TABLE TABLE?
	JRST [	TMSG <: Long file page table>
		JRST MRKBT3]	;PAGE TABLE TABLE
	TXNE F,MR%SWP		;NO. IS IT SWAPPING SPACE?
	JRST [	TMSG <: Swapping space>
		JRST MRKBT3]
	TXNE F,MR%SPC		;NO. IS IT A SPECIAL BLOCK?
	JRST [	TMSG <: Special system blocks>
		JRST MRKBT3]

MRKBT3:	TMSG <
>
	JUMPE T4,RSKP		;IF NOT REALLY AN ERROR, TAKE SKIP RETURN
	TXNN T4,ER%BAT		;WAS IT A BAD ADDRESS
	RET			;NO. TAKE ERROR RETURN
	MOVE T1,ASAVE		;RESTORE SECTOR NUMBER
	JRST MRKBT4		;GO CONTINUE
;FIXCNT - FIX THE COUNT OF FILE PAGES FOR ONE FILE

;ACCEPTS:
;	NOTHING IN AC'S, BUT DIRNAM,DEFNAM,DEFEXT,DEFVER MUST BE SET UP

;RETURNS +1:ALWAYS

;CALLED BY BUILD WHEN A FILE'S PAGE COUNT IN THE FDB DISAGREES WITH
;LOCAL COUNT OF DATA PAGES.  DOES OPENF AND CLOSF TO FORCE THE UPDATE.
;NOTE THAT THE COUNT WILL NOT BE UPDATED IF ANYONE ELSE HAS THE FILE OPEN
;UNTIL THE LAST CLOSE OCCURS.  IN THE CASE OF ROOT-DIRECTORY.DIRECTORY
;AND SOME OTHERS THAT ARE NEVER CLOSED, THE COUNT WILL NOT BE UPDATED

FXCNAM:	BLOCK	21
FXCEXT:	BLOCK	21
FIXCNT:	SAVEAC	<Q1,Q2>		;save some ACs
	STKVAR<JFN1>
	DMOVE T1,[G2BPT 2,7,0]
	MOVE T2,DEFNAM		;GET THE NAME POINTER
	DMOVE T3,[G2BPT 0,7,FXCNAM] ;GET THE NEW STRING POINTER
	CALL FIXCN2		;BUILD A NICE STRING FOR GTJFN
	DMOVE T1,[G2BPT 2,7,0]
	MOVE T2,DEFEXT		;GET POINTER TO EXTENSION
	DMOVE T3,[G2BPT 0,7,FXCEXT] ;GET THE NEW STRING POINTER
	CALL FIXCN2		;BUILD A NICE STRING FOR GTJFN
	MOVEI T1,GTJBLK		;T1/ ADDRESS OF GTJFN BLOCK
	MOVX T2,GJ%DEL!GJ%XTN!GJ%OLD!GJ%PHY ;OLD FILE,deleted,extended block
	HRR T2,DEFVER		;VERSION NUMBER OF THIS FILE
	MOVEM T2,.GJGEN(T1)	;(FLAGS,,VERSION NUMBER)
	MOVX T2,G1%IIN		;invisible files too
	MOVEM T2,.GJF2(T1)	;mark in extended flags
	MOVE T2,[.NULIO,,.NULIO] ;NULL DEVICE FOR INPUT AND OUTPUT
	MOVEM T2,.GJSRC(T1)	;(INPUT JFN,,OUTPUT JFN)
	SETZM .GJDEV(T1)		;NO DEFAULT DEVICE
	SETZM .GJDIR(T1)		;NO DEFAULT DIRECTORY
	MOVEI T2,FXCNAM		;POINTER TO CURRENT FILENAME
	MOVEM T2,.GJNAM(T1)	;MAKE THIS THE DEFAULT
	MOVEI T2,FXCEXT		;POINTER TO CURRENT EXTENSION
	MOVEM T2,.GJEXT(T1)	;MAKE THIS THE DEFAULT
	SETZM .GJPRO(T1)		;NO DEFAULT PROTECTION
	SETZM .GJACT(T1)		;NO DEFAULT ACCOUNT STRING
	SETZM .GJJFN(T1)		;NO SPECIFIC JFN
	HRROI T2,DIRNAM		;T2/ STR:<DIRECTORY>
	GTJFN			;GET A JFN ON THE CURRENT FILE
	 JRST [	PNTERR (<Unable to fix count for file>,FIXCN1,FILE)]
	HRRZS T1		;T1/JFN WITHOUT FLAGS
	MOVEM T1,JFN1		;SAVE IT
	MOVX T2,OF%RD!OF%PDT	;T2/READ ACCESS, DON'T CHANGE ACCESS DATE
	OPENF			;OPEN THE FILE
	 JRST [	MOVE T1,JFN1	;FAILED. T1/JFN
		TXO T2,OF%THW!OF%RD!OF%PDT ;T2/THAWED, READ, DON'T CHANGE DATE
		OPENF		;OPEN IT THAWED THIS TIME
		 JRST [	PNTERR (<Unable to fix count for file>,FIXCN1,FILE)]
		JRST .+1]	;SUCCEEDED
	MOVE T1,JFN1		;T1/JFN
	MOVEI T4,.FBBYV		;OFFSET TO BE CHANGED
	STOR T4,CF%DSP,T1	;SAVE IT IN T1
	MOVX T2,FB%PGC		;T2/MASK FOR PAGE COUNT FIELD
	MOVE T3,PAGCNT		;T3/NEW PAGE COUNT TO BE STORED
	CHFDB			;PUT CORRECT PAGE COUNT IN FDB
	 ERJMP [PNTERR (<Unable to fix count for file>,,FILE)
		JRST .+1]
	MOVE T1,JFN1		;T1/JFN
	CLOSF			;CLOSE THE FILE
	 JFCL			;IGNORE FAILURE
FIXCN1:	RET

FIXCN2:				;ROUTINE TO JACKET STRINGS WITH ^V'S
				;T1/ OLD STRING POINTER
				;T4/ NEW STRING POINTER
	MOVEI Q1,"V"-100	;GET A CONTROL V
FIXCN3:	ILDB Q2,T1		;GET A BYTE
	JUMPE Q2,FIXCN4		;NULL BYTE?
	IDPB Q1,T3		;NO SO PUT A CONTROL V
	IDPB Q2,T3		;AND THEN THE REAL CHARACTER
	JRST FIXCN3		;AND LOOP
FIXCN4:	IDPB Q2,T3		;APPEND A NULL
	RET			;RETURN TO CALLER
;CHECK CHECKSUM IF NEW FORMAT XB'S
; T1/ LOCATION OF XB

CHKCSM:	PUSH P,Q1
	PUSH P,T1		;SAVE XB LOCATION
	HRRZ T2,T1
	ADD T2,[XBCKSM]		;GET EXISTING CHECKSUM FROM XB
	MOVEI T1,Q1		;PUT IT INTO Q1
	CALL LDXBD
	MOVE T1,0(P)
	CALL DOCSM		;COMPUTE CHECKSUM
	SETCA Q1,		;SUBTRACT CHECKSUMS (1'S COMPL)
	ADD T1,Q1
	POP P,0(P)
	POP P,Q1
	CAME T1,[-1]		;0? (OR -0)
	JUMPN T1,[TMSG <	Checksum incorrect
>
		RET]
	JRST RSKP
;COMPUTE CHECKSUM
; T1/ ADDRESS OF PT

DOCSM:	MOVSI T4,-1000
	SETZ T3,			;COMPUTE CHECKSUM IN C
	JCRY0 .+1
DOCSM1:	MOVE T2,@T1
	TLZ T2,(ADRMSK)		;LOOK ONLY AT ADDRESS PART OF WORD
	SKIPN T2		;EMPTY?
	HRRZ T2,T4		;YES, USE INDEX IN CHECKSUM
	ADD T3,T2
	JCRY0 [AOJA T3,.+1]	;DO END-AROUND CARRY
	AOS T1			;next word
	AOBJN T4,DOCSM1
	MOVE T1,T3		;RETURN CHECKSUM IN T1
	RET
;LOAD/STORE DATA IN INDEX BLOCK.
;SINCE THE STORAGE ADDRESS IS ONLY 23 BITS, THE REMAINING PORTION
;OF EACH WORD CAN BE USED TO STORE USEFUL INFORMATION, E.G. A
;CHECKSUM OF THE INDEX BLOCK.  THESE ROUTINES PACK AND UNPACK
;THE DATA FROM THE XB USING B0-8 OF SUCCESSIVE WORDS.

; T1/ ADDRESS OF WORD(S)
; T2/ NUMBER OF XB WORDS,,XB ADDRESS + OFFSET
;	CALL STXBD/LDXBD
; RETURN +1 ALWAYS, DATA MOVED BETWEEN XB AND C(C(T1))

;STORE DATA INTO INDEX BLOCK

STXBD:	HRLI T1,(<POINT 9,0>)	;INIT PTR TO CALLERS DATA
STXBD1:	ILDB T3,T1		;GET BYTE FROM CALLER
	DPB T3,[POINT 9,0(T2),8]	;PUT IT IN XB
	AOBJN T2,STXBD1		;INCREMENT THROUGH XB
	RET

;LOAD FROM XB

LDXBD:	HRLI T1,(<POINT 9,0>)	;INIT PTR TO CALLERS STORAGE
LDXBD1:	LDB T3,[POINT 9,0(T2),8]	;GET BYTE FROM XB
	IDPB T3,T1		;PUT IT IN CALLERS STORAGE
	AOBJN T2,LDXBD1		;SCAN THROUGH XB
	RET

;ITEMS IN INDEX BLOCK VECTOR

XBCKSM==<-4,,0>			;CHECKSUM--4 WORDS BEGINNING AT 0
DSKRED:	PUSH P,T1
	MOVE T3,T2
	TLZ T1,(ADRMSK)
	MOVE T4,STRDEV		;GET STRUCTURE NUMBER
	TXO T1,DOP%SN		;SET TO ALL ONES
	TXO T1,<FLD .DOPSR,DOP%AT>
	MOVEI T2,1000		;WORD COUNT
	DSKOP
	SKIPE T1
	AOSA NDSKER		;DSK READ ERR
	AOS -1(P)
	POP P,T1
	MOVE T2,T3
	RET

DSKWRT:	PUSH P,T1
	MOVE T3,T2
	TLZ T1,(ADRMSK)
	TXO T1,<FLD .DOPSR,DOP%AT>
	MOVE T4,STRDEV		;GET STRUCTURE NUMBER
	TXO T1,DOP%SN		;SET TO -1
	MOVX T2,DOP%WR+1000
	DSKOP
	SKIPE T1
	JRST [	AOS NDSKER
		TMSG <Disk write error
>
		JRST .+1]
	POP P,T1
	MOVE T2,T3
	RET
;FINBTB - CALLED WHEN DONE.  PRINTS COUNTS OF FREE AND USED PAGES
;BEFORE AND AFTER THE ASSIGNMENTS

FINBTB:	TMSG <
Local count of file pages: >
	MOVE T2,TOTPGS		;GET COUNT OF FILE PAGES
	MOVEI T3,12		;DECIMAL RADIX
	CALL TTNOUT
	TMSG <
Local count of overhead pages: >
	MOVE T2,OVERHD		;GET COUNT OF OVERHEAD PAGES
	MOVEI T3,12		;DECIMAL RADIX
	CALL TTNOUT		;PRINT THE COUNT
	TMSG <
Local count of used pages: >
	MOVE P1,LOTRK
	SUB P1,HITRK
	HRLZS P1
	HRR P1,LOTRK		;LOTRK-HITRK ,, LOTRK
	SETZ T2,
	ADD T2,LOCBTB(P1)	;COUNT FREE PAGES FOR CYLINDER
	AOBJN P1,.-1
	MOVNS T2		;NEGATIVE OF TOTAL FREE
	MOVE T3,HITRK
	IMUL T3,PAGCYL		;GET TOTAL PAGES
	ADD T2,T3		;TOTAL USED
	ADD T2,BATCNT		;ADD PAGES THAT ARE MARKED BAD BUT NOT
				; USED BY A FILE
	MOVEI T3,12
	CALL TTNOUT		;PRINT LOCAL COUNT OF USED PAGES
	TMSG <
>
	SKIPE REBLDF		;REBUILDING BIT TABLE?
	JRST FINBT1		;YES. NEXT COUNT IS MEANINGLESS
	TMSG<
System count before CHECKD: >
	MOVE T2,ZUSED		;SYSTEM'S COUNT OF USED AT BEGINNING
	MOVEI T3,12
	CALL TTNOUT		;PRINT ORIGINAL COUNT

;NEXT PAGE ....
FINBT1:	TMSG <
System count after CHECKD: >
	MOVE T1,STRDEV		;DEVICE DESIGNATOR FOR STR
	GDSKC			;GET SYSTEM COUNTS
	MOVE T2,T1		;GET COUNT OF USED
	CALL TTNOUT		;PRINT CURRENT COUNT
	TMSG <

>
;GENERATE LOST PAGES LIST.  MAP SYSTEM BIT TABLE AND COMPARE WITH
;LOCALLY GENERATED VERSION.  OUTPUT DIFFERENCES.

	SKIPN REBLDF		;ARE WE REBUILDING THE BIT TABLE?
	JRST FNDLS8		;NO.
	MOVX T1,DA%WRT		;T1/WRITE THE BIT TABLE
	MOVE T2,STRDEV		;T2/STRUCTURE 0
	DSKAS			;COPY PRIVATE COPY OF BIT TABLE TO FILE
	 JRST [	PNTERR(<Failed to write bit table file>)
		JSERR
		RET]
	RET			;SUCCESS. DON'T DO THE REST
;HERE WHEN NOT REBUILDING THE BIT TABLE.  GET A JFN ON BIT TABLE FILE,
;OPEN IT AND MAP IT TO OUR ADDRESS SPACE

FNDLS8:	PUSH P,P1		;SAVE AC
	HRROI T2,[ASCIZ /<ROOT-DIRECTORY>DSKBTTBL/]
	CALL ADDSTR		;ADD STRUCTURE NAME
	MOVX T1,GJ%OLD!GJ%SHT!GJ%PHY
	GTJFN			;GET JFN ON BIT TABLE FILE
	 JRST [	PNTERR(<GTJFN failure for <ROOT-DIRECTORY>DSKBTTBL>)
		RET]
	MOVEM T1,BTBJFN		;SAVE THE JFN
	MOVEI T2,OF%RD+OF%THW	;T1/READ ACCESS, THAWED
	OPENF			;OPEN THE BIT TABLE FILE
	 JRST [	PNTERR(<OPENF failure for <ROOT-DIRECTORY>DSKBTTBL>)
		RET]
	HRLZ T1,BTBJFN		;SOURCE (PAGE 0 OF BIT TABLE FILE)
	MOVE T2,[.FHSLF,,SYSBTB/PGSIZ] ;DESTINATION (SYSBTB AREA OF THIS FORK)
	MOVE T3,BTBPGS		;NUMBER OF PAGES IN FILE
	TXO T3,PM%CNT+PM%RD+PM%CPY ;MAP WITH COPY-WRITE
	PMAP			;MAP BIT TABLE FILE TO CORE STARTING AT SYSFCT
	SETZM OUTJFN		;NO FILE YET
	SETZM LOSTOT		;INIT COUNT OF LOST PAGES
	MOVN P1,HITRK		;SETUP TO SCAN ALL TRACKS
	HRLZS P1

;LOOP THROUGH PAGES IN BIT TABLE, COMPARING WITH LOCAL COPY.  REPORT
;INCONSISTENCIES AND FIX WHERE NECESSARY

FNDLS1:	MOVE T1,LOCBTB(P1)	;GET OUR COUNT
	CAME T1,SYSBTB(P1)	;AGREES WITH SYSTEM?
	JRST [	CALL FNDLS2	;NO, FIGURE OUT DIFFERENCE
		JRST FNDLS1]	;TRY AGAIN
	AOBJN P1,FNDLS1		;DO ALL TRACKS
;ALL CYLINDERS HAVE BEEN CHECKED.  WRITE FILE OF LOST PAGES IF THERE
;ARE ANY.  NOTE THAT WRITING IS SUPPRESSED IF ERRORS HAVE OCCURRED.

	SKIPG LOSTOT		;ANY LOST PAGES?
	JRST [	TMSG <There are no lost pages.
>				;NO. DON'T CREATE LOST-PAGES FILE
		JRST FNDLSX]

;OPEN A FILE AND DUMP LOST PAGES LIST

	TMSG <There are >
	MOVE T2,LOSTOT
	MOVEI T3,^D10		;OUTPUT IT IN DECIMAL
	CALL TTNOUT
	TMSG < lost pages
>
	SKIPE WRTLPF		;[39] Write file?
	JRST FNDLS0		;[39] Yes

;[39] Here if we are suppressing writing the lost pages file.

	TMSG <%Suppressed writing of lost pages file, too many errors
>				;[39] Uh oh
	SKIPE JOBNO		;[39] Skip if job 0
	SKIPN STRMNT		;[39]  or no mounted str
	JRST FNDLSX		;[39] Yes, exit now please

	TMSG <
%WARNING: The structure is still mounted with exclusive access to this job so
that errors may be fixed.  This is to prevent other users from accessing the
structure until you have completely finished checking or repairing it.  After
repairing the structure, you may rerun CHECKD and try your command again using
structure name >		;[39] Helpful message part one
	HRROI T1,ALINAM		;[39] Point to alias name again
	PSOUT%			;[39] Send that to terminal
	TMSG <:.  You may also choose to dismount the structure now.

>				;[39] Finish helpful message
	HRROI T1,[ASCIZ/Dismount the structure now? /] ;[39] Get an answer
	CALL YESNO		;[39] (T1/T1) Get Yes (-1) or No (0) answer
	SKIPE T1		;[39] User want structure dismounted?
	CALL DISMNT		;[39] (/) Yes, please dismount the structure
	JRST FNDLSX		;[39] Punt the lost pages file and return
;Here to write the lost pages file.

FNDLS0:	HRROI T1,ATMBUF		;BUILD FILESPEC HERE
	HRROI T2,STRHOM		;START WITH STR NAME
	MOVEI T3,0
	SOUT
	MOVEI T2,"-"
	IDPB T2,T1
	HRROI T2,[ASCIZ /LOST-PAGES.BIN/]
	SOUT			;COMPLETE SPEC
	MOVX T1,GJ%FOU!GJ%SHT!GJ%PHY
	HRROI T2,ATMBUF		;FILESPEC TEXT PNTR
	GTJFN			;GET A JFN FOR LOST PAGES FILE
	 JRST [	PNTERR(<GTJFN failure for lost pages file>,FNDLS9)]
	MOVEM T1,OUTJFN		;SAVE JFN FOR LOST PAGES FILE
	MOVE T2,[44B5+OF%WR]	;T2/36-BIT BYTES, WRITE ACCESS
	OPENF			;OPEN IT
	 JRST [	PNTERR(<Failed to open lost pages file>,FNDLS9)]
	TMSG<
Addresses are in file >
	MOVEI T1,.PRIOU
	MOVE T2,OUTJFN		;HAVE OUTPUT FILE?
	MOVX T3,1B2+1B5+1B8+1B11+1B14+1B35
	JFNS			;PRINT NAME
	TMSG <
>
	CALL LPFWRT		;WRITE THE HEADER
	MOVE T1,OUTJFN		;THE DESTINATION
	MOVE T2,[POINT 36,LOSBUF] ;POINT TO LIST
	MOVE T3,LOSTOT		;GET NUMBER OF LOST PAGES
	CAILE T3,MAXLOS		;MORE THAN THE BUFFER SIZE?
	MOVEI T3,MAXLOS		;YES, DON'T WRITE MORE THAN WAS REMEMBERED
	MOVN T3,T3		;MAKE NEGATIVE
	SOUT			;WRITE THE FILE
	 ERJMP [PNTERR (<Output error or quota exceeded>,FNDLS9)]
	MOVE T1,OUTJFN
	CLOSF
	 JFCL
	JRST FNDLSX

FNDLS9:	TMSG <
?File was not written
>
;UNMAP THE BIT TABLE AND CLOSE THE FILE

FNDLSX:	SETO T1,
	MOVE T2,[.FHSLF,,SYSBTB/PGSIZ]
	MOVE T3,BTBPGS		;NUMBER OF PAGES
	TXO T3,PM%CNT
	PMAP			;UNMAP SYSTEM BIT TABLE PAGES
	MOVE T1,BTBJFN
	CLOSF
	 JFCL
	POP P,P1		;RESTORE AC
	RET
;FIND DIFFERENCE IN BITS, COMPUTE CORRESPONDING ADDRESS

FNDLS2:	HRRZ T4,P1		;GET TRACK NUMBER
	IMUL T4,BTWCYL		;COMPUTE INDEX TO BIT TABLE
	ADD T4,BTBTOP		;POINT INTO BOTTOM HALF
	MOVN T1,BTWCYL		;GET NUMBER OF BIT WORDS PER CYLINDER
	HRL T4,T1		;T4/(-COUNT,,T1DDRESS OF BIT WORD)
FNDLS4:	MOVE T1,LOCBTB(T4)	;GET OUR BIT WORD
	XOR T1,SYSBTB(T4)		;GET DIFFERENCE
	JFFO T1,FNDLS3		;JUMP IF HAVE A DIFFERENCE
	AOBJN T4,FNDLS4		;DIFFERENCE NOT IN THAT WORT4, TRY NEXT

;HERE WHEN THE LOCAL AND SYSTEM BIT TABLES DISAGREE IN FREE PAGE COUNT FOR
;A TRACK AND EITHER
;	1) ALL THE BIT WORDS FOR THAT CYLINDER AGREE
;		OR
;	2) ONE OR MORE PAGES ARE MARKED AS ASSIGNED IN THE LOCAL BIT AND
;	   FREE IN THE SYSTEM BIT TABLE
;NOTE THAT THE LATTER SHOULD NOT OCCUR SINCE IT SHOULD HAVE PRODUCED A
;'NOT IN BIT TABLE' MESSAGE EARLIER AND BEEN CORRECTED.
;IF PAGES ARE MARKED AS FREE IN THE LOCAL TABLE AND ASSIGNED IN THE SYSTEM
;TABLE, THEY WILL BE IDENTIFIED AS LOST PAGES

FNDLS7:	TMSG <?Bit tables inconsistent at cylinder >
	HRRZ T2,P1		;GET CYLINDER NUMBER
	MOVEI T3,10		;T3/OCTAL
	CALL TTNOUT		;PRINT THE CYLINDER NUMBER
	MOVE T1,LOCBTB(P1)	;COPY THE LOCAL (PRESUMED CORRECT) COUNT
	MOVEM T1,SYSBTB(P1)	; TO THE SYSTEM COUNT. NOTE: DOES NOT CHANGE
				; THE COPY ON THE DISK
	TMSG <
>
	RET
FNDLS3:	MOVSI T1,(1B0)		;GET BIT
	MOVN T3,T2
	LSH T1,0(T3)
	TDNE T1,SYSBTB(T4)	;BIT WAS OFF IN SYSTEM (PAGE ASSIGNED)?
	JRST FNDLS7		;NO. PAGE SHOULD HAVE BEEN ASSIGNED
	IORM T1,SYSBTB(T4)	;NOTE PAGE NOW NOT ASSIGNED
	AOS SYSBTB(P1)		;ADJUST COUNT
	HRRZ T1,P1		;GET TRACK NUMBER
	IMUL T1,SECCYL		;GET SECTOR COUNT
	HLRE T3,T4		;GET INDEX TO BIT TABLE
	ADD T3,BTWCYL
	IMULI T3,^D36		;COMPUTE PAGE WITHIN TRACK
	ADD T2,T3
	IMUL T2,SECPAG		;COMPUTE SECTOR WITHIN TRACK
	ADD T1,T2		;DSKADR = TRACK ADR + SEC WITHIN TRK
	CALL SEEADR		;SEE IF A BAT BLOCK
	 RET			;YES. DONT PUT IT IN LOST FILE
	AOS T2,LOSTOT		;COUNT IT
	CAILE T2,MAXLOS		;STILL ROOM?
	JRST [	HRROI T1,[ASCIZ /
?Lost pages buffer full, further lost pages will be ignored.
/]
		CAIN T2,MAXLOS+1	;FIRST TIME?
		PSOUT		;YES. TELL HIM
		RET]		;AND GIVE UP
	MOVEM T1,LOSBUF-1(T2)	;STORE LOST PAGE
	RET
;ROUTINE TO SEE IF A DISK ADDRESS IS A BAT BLOCK
; T1/ DISK ADDRESS
;
;RETURUNS +1: A BAT BLOCK
;	  +2: NOT A BAT BLOCK

SEEADR:	SAVET			;SAVE ALL OF THE "T" ACS
	MOVEI T3,BPRBLK		;START OF THE PAIRS
SEEIF:	SKIPN (T3)		;AT THE END?
	RETSKP			;YES, RETURN +2
	MOVE T2,0(T3)		;GET START RANGE
	TLZ T2,777000		;MASK OUT FLAGS
	MOVE T4,1(T3)		;GET END RANGE
	TLZ T4,777000		;MASK OUT FLAGS
	CAML T1,T2		;IN RANGE?
	CAMLE T1,T4		;IN RANGE?
	SKIPA			;NO, NEXT PAIR
	RET			;YES,RETURN
	ADDI T3,4		;NEXT PAIR
	JRST SEEIF		;GO SEE IF THE NEXT PAIR IN ONE
;OUTPUT NUMBER IN B TO TERMINAL

;	2/NUMBER
;	3/RADIX

TTNOUT:	MOVEI T1,101
	NOUT
	 JFCL
	RET


;READ LINE INTO LINE BUFFER
; T1/ JFN FROM WHICH TO READ

RDLIN:	PUSH P,Q1
	HRLZ T4,T1		;T4=INJFN,,OUTJFN
	HRRI T4,.PRIOU
	MOVEI T1,T2		;T1=ADR OF PARAMETER BLOCK
	MOVEI T2,4		;B=COUNT OF PARAMETERS
	MOVSI T3,(RD%BRK+RD%RAI+RD%BEL+RD%JFN) ;C=FLAGS, BREAK ON EOL AND USE JFNS
	HRROI Q1,LINBUF		;E=PTR TO LINE BUFFER
	MOVEI Q2,NLINB*5	;F=MAX BYTE COUNT
	TEXTI
	 ERJMP JSHALT		;[39] Should never happen
	TLNN T3,(RD%BTM)	;TERMINATED PROPERLY?
	JFCL			;NO, MUST BE END OF FILE
	MOVE T1,Q1		;RETURN UPDATED BFR PTR
	POP P,Q1
	RET
;GET YES/NO ANSWER FROM TERMINAL. C(T1) := PROMPT STRING

YESNO:	STKVAR <ANSWER,QUEST>
	MOVEM T1,QUEST		;SAVE FOR ERROR
YESNO1:	MOVE T1,QUEST		;GET PROMPT STRING
	CALL CMDINI		;INIT CMD AND PROMPT
	MOVEI T1,[FLDDB.(.CMKEY,,YESNOT)]
	CALL COMNDX		;GET RESPONSE
	 ERROR YESNO1,<Invalid response>
	MOVEM T2,ANSWER		;SAVE ANSWER
	CALL CMDEOL		;GRNTEE CR
	 JRST YESNO1		;ERROR
	MOVE T2,ANSWER		;PICKUP RESPONSE
	HRRE T1,0(T2)		;RETURN -1 FOR YES, 0 FOR NO
	RET

YESNOT:	2,,2			;COUNT OF ENTRIES
	TB (0,NO)
	TB (-1,YES)
;ROUTINES TO CHECK CONSISTENCY OF DIRECTORY AND FDB'S

;ROUTINE TO CHECK THE CONSISTENCY OF THE HEADER ON THE FIRST DIR PAGE
;ASSUMES DIR IS MAPPED
;ACCEPTS IN T1/	DIR NUMBER
;	CALL DR0CHK
;RETURNS +1:	HEADER IS SCREWED UP
;	 +2:	OK
;DOES NOT SAVE TEMPORARY ACS

DR0CHK:	MOVE T4,DIRORA		;GET BASE ADR OF MAPPED DIR AREA
	LOAD T2,DRNUM,(T4)	;GET DIR NUMBER
	ERJMP DR0CHB		;ERROR IF NON-EXISTENT PAGE
	CAME T1,T2		;DO THE DIRECTORY NUMBERS MATCH?
	JRST DR0CHB		;NO
	LOAD T2,DRTYP,(T4)	;GET BLOCK TYPE
	CAIE T2,.TYDIR		;IS BLOCK TYPE CORRECT?
	JRST DR0CHB		;NO
	LOAD T2,DRRPN,(T4)	;GET RELATIVE PAGE #
	JUMPN T2,DR0CHB		;MUST BE 0
	LOAD T2,DRSTP,(T4)	;GET TOP OF SYMBOL TABLE
	SOS T2			;GET LAST WORD USED
	LSH T2,-PGSFT		;TURN IT INTO PAGE #
	CAIL T2,NDIRPG		;WITHIN BOUNDS?
	JRST DR0CHB		;NO
	LOAD T2,DRFFB,(T4)	;GET ADR OF FIRST FREE BLOCK
	TRZ T2,777		;IT MUST POINT ONTO THIS PAGE
	JUMPN T2,DR0CHB
	LOAD T1,DRNAM,(T4)	;NOW CHECK NAME BLOCK
	JUMPE T1,DR0CH1		;DONT WORRY IF NO NAME
	CALL NAMCHK		;MAKE SURE THIS IS A NAME BLOCK
	 RET			;NO
DR0CH1:	LOAD T1,DRPSW,(T4)	;GET PASSWORD POINTER
	JUMPE T1,DR0CH2		;COULD BE 0
	CALL NAMCHK		;CHECK BLOCK TYPE
	 RET			;FAILED CHECK
DR0CH2:	RETSKP			;EVERYTHING IS IN ORDER

DR0CHB:	TMSG <%Illegal format for page 0> ;[39]
	RET
;FDBCHK - ROUTINE TO CHECK AN FDB
;ACCEPTS IN T1/	ABSOLUTE ADR OF FDB
;	CALL FDBCHK
;RETURNS +1:	BAD FDB
;	 +2:	FDB OK
;ALL ACS ARE SAVED AND RESTORED

FDBCHK:	SAVET			;SAVE ALL ACS USED
	STKVAR <FDBCHA,FDBCHF>
	MOVEM T1,FDBCHA		;SAVE ADR OF FDB
	CALL ADRCHK		;CHECK THIS ADDRESS
	 JRST FDBBAD		;NOT GOOD
	LOAD T2,FBTYP,(T1)	;GET BLOCK TYPE
	LOAD T3,FBLEN,(T1)	;GET LENGTH OF BLOCK
	CAIL T3,.FBLN0		;MUST BE GREATER THAN GROUND 0 LENGTH
	CAIE T2,.TYFDB		;BLOCK TYPE MUST BE "FDB"
	JRST FDBBAD		;BAD FDB
	LOAD T1,FBNAM,(T1)	;GET POINTER TO NAME STRING
	JUMPE T1,FDBBAD		;MUST ALWAYS BE SET UP
	CALL NAMCHK		;CHECK NAME
	 RET			;BAD
	MOVE T1,FDBCHA		;GET BACK FDB ADR
	LOAD T1,FBEXT,(T1)	;GET POINTER TO EXT STRING
	JUMPE T1,FDBCH2		;MIGHT NOT BE SET UP YET
	CALL EXTCHK		;CHECK EXT BLOCK
	 RET			;BAD
FDBCH2:	MOVE T1,FDBCHA		;GET FDB ADR AGAIN
	LOAD T1,FBACT,(T1)	;GET POINTER TO ACCOUNT STRING
	JUMPLE T1,FDBCH3		;SEE IF THERE IS AN ACCOUNT STRING
	CALL ACTCHK		;YES, CHECK ITS BLOCK TYPE
	 RET			;BAD
FDBCH3:	MOVE T1,FDBCHA		;GET BACK FDB ADDR
	LOAD T2,FBVER,(T1)	;GET VERSION #
	CAIGE T2,1		;VER #1 OR LATER?
	JRST FDBCH6		;OLDER - JUST EXIT
	LOAD T1,FBLWR,(T1)	;GET LAST WRITER STRING
	JUMPE T1,FDBCH5		;IGNORE OF NONE
	CALL UNSCHK		;CHECK ITS BLOCK TYPE
	 RET			;BAD
FDBCH5:	MOVE T1,FDBCHA		;FDB ADDRS AGAIN
	LOAD T1,FBAUT,(T1)	;GET AUTHOR STRING
	JUMPE T1,FDBCH6		;ALL DONE IF NONE
	CALL UNSCHK		;CHECK ITS BLOCK TYPE
	 RET			;BAD
FDBCH6:	RETSKP			;FDB LOOKS OK

FDBBAD:	TMSG <%Illegal format FDB> ;[39]
	RET
;ROUTINE TO CHECK A NAME BLOCK
;ACCEPTS IN T1/	RELATIVE ADR OF NAME BLOCK
;	CALL NAMCHK
;RETURNS +1:	BAD BLOCK TYPE
;	 +2:	OK
;ALL ACS SAVED AND RESTORED

NAMCHK:	SAVET			;SAVE ALL ACS
	ADD T1,DIRORA		;MAKE ADDRESS ABSOLUTE
	CALL ADRCHK		;CHECK THIS ADDRESS
	 JRST NAMBAD		;NO GOOD
	LOAD T2,NMTYP,(T1)	;GET BLOCK TYPE
	LOAD T3,NMLEN,(T1)	;GET LENGTH
	CAIL T3,2		;MUST BE AT LEAST 2 WORDS LONG
	CAIE T2,.TYNAM		;AND MUST BE A NAME BLOCK
	JRST NAMBAD		;LOSE
	RETSKP			;NAME BLOCK OK

NAMBAD:	TMSG <%Illegal format for name block> ;[39]
	RET
;ROUTINE TO CHECK AN EXTENSION BLOCK
;ACCEPTS IN T1/	RELATIVE ADR OF EXTENSION BLOCK
;	CALL EXTCHK
;RETURNS +1:	BAD BLOCK
;	 +2:	OK
;SAVES AND RESTORES ALL ACS

EXTCHK:	SAVET
	ADD T1,DIRORA		;MAKE ADDRESS ABSOLTE
	CALL ADRCHK		;SEE IF ADR IS GOOD
	 JRST EXTBAD		;NO GOOD
	LOAD T2,EXTYP,(T1)	;GET TYPE
	LOAD T3,EXLEN,(T1)	;AND LENGTH
	CAIL T3,2		;LENGTH MUST BE AT LEAST 2
	CAIE T2,.TYEXT		;EXTENSION TYPE OK?
	JRST EXTBAD		;NO GOOD
	RETSKP			;OK

EXTBAD:	TMSG <%Illegal format for extension block> ;[39]
	RET
;ROUTINE TO CHECK AN ACCOUNT STRING BLOCK
;ACCEPTS IN T1/	RELATIVE ADR OF ACCOUNT STRING BLOCK
;	CALL ACTCHK
;RETURNS +1:	BAD ACCOUNT BLOCK
;	 +2:	OK
;SAVES AND RESTORES ALL ACS

ACTCHK:	SAVET
	ADD T1,DIRORA		;GET ABS ADR
	CALL ADRCHK		;CHECK ADR
	 JRST ACTBAD		;BAD ADR
	LOAD T2,ACTYP,(T1)	;GET BLOCK TYPE
	LOAD T3,ACLEN,(T1)	;AND LENGTH
	CAIL T3,3		;MUST BE AT LEAST 3 WORDS LONG
	CAIE T2,.TYACT		;ACCOUNT BLOCK TYPE?
	JRST ACTBAD		;NO
	RETSKP			;OK

ACTBAD:	TMSG <%Illegal format for account block> ;[39]
	RET
;ROUTINE TO CHECK A USER NAME STRING BLOCK
;ACCEPTS IN T1/ RELATIVE ADR OF NAME STRING BLOCK
;	CALL UNSCHK
;RETURNS +1:	BAD USER NAME BLOCK
;	 +2:	OK
;SAVES AND RESTORES ALL ACS

UNSCHK:	SAVET
	ADD T1,DIRORA		;GET ABS ADDR
	CALL ADRCHK		;CHECK ADDR
	 JRST UNSBAD		;BAD ADDRS
	LOAD T2,UNTYP,(T1)	;GET BLOCK TYPE
	LOAD T3,UNLEN,(T1)	; AND LENGTH
	CAIL T3,3		;MUST BE AT LEAST 3
	CAIE T2,.TYUNS		;USER NAME BLOCK TYPE?
	JRST UNSBAD		;SOMETHING WRONG
	RETSKP			;GIVE GOOD RETURN

UNSBAD:	TMSG <%Illegal format for user name block> ;[39]
	RET
;ROUTINE TO CHECK THAT AN ADR IS WITHIN THE DIR BOUNDS
;ACCEPTS IN T1/	ABS ADR TO BE CHECKED
;	CALL ADRCHK
;RETURNS +1:	ILLEGAL ADR
;	 +2:	OK

ADRCHK:	MOVE T2,DIRORA		;GET UPPER BOUNDS
	ADD T2,[NDIRPG*PGSIZ]
	CAML T1,DIRORA		;ABOVE LOWER LIMIT?
	CAML T1,T2		;AND BELOW UPPER LIMIT?
	RET			;NO
	RETSKP			;YES, ADR IS OK
;CALLED AT STARTUP AND EXIT.   CLOSE ALL FILES, RELEASE ALL JFN'S, CLEAR
;DEFAULT FILESPEC

RESET:	MOVNI T1,1
	CLOSF			;CLOSE ALL OPEN FILES
	 JFCL
	MOVE T1,[CZ%NCL+.FHSLF]
	CLZFF		;RELEASE ALL JFNS
	SETZM DEFVER
	MOVE T1,[XWD DEFVER,DEFVER+1]
	BLT T1,DEFEXT+4
	SETZM PSFLG		;RESET PS FLAG
	RET
	SUBTTL Interrupt System -- Control-A Interrupt

;USER TYPED CTRL/A OR SOME OTHER INTERUPT BYTE

SUMINT:	PUSH P,T1
	PUSH P,T2
	PUSH P,T3
	SKIPN DIRNUM		;ONLY IF ACTUALLY DOING SOMWTHING
	JRST SUMBAT
	TMSG <Working on directory >
	MOVEI T1,101
	MOVE T2,DIRNUM
	DIRST
	JFCL
	TMSG <
>
DBK:	POP P,T3
	POP P,T2
	POP P,T1
	DEBRK
SUMBAT:	SKIPN BATLST		; ARE WE DOING A VERIFY PASS?
	JRST DBK		; NO, IGNORE THE INTERUPT
	TMSG <Working on page >
	MOVE T2,BATLST		; GET LAST SECTOR WE STARTED AT
	IDIV T2,SECPAG		; CONVERT TO A PAGE NUMBER
	MOVEI T3,^D8
	CALL TTNOUT		; TYPE NUMBER
	TMSG < out of >
	MOVE T2,LSTSEC		; GET THE END
	SUB T2,FSTSEC		; GET THE LENGTH
	IDIV T2,SECPAG		; CONVERT TO A PAGE NUMBER
	MOVEI T3,^D8
	CALL TTNOUT		; AND TYPE IT
	SKIPN T2,FSTSEC		; ARE WE GOING OVER THE WHOLE DISK
	JRST SUMBT2		; YES, JUST GET OUT AND GIVE THE PERCENTAGE
	TMSG < (>		; INDICATE RANGE START
	IDIV T2,SECPAG		; CONVERT TO A PAGE NUMBER
	MOVEI T3,^D8
	CALL TTNOUT		; GIVE THE NUMBER
	TMSG </>
	MOVE T2,LSTSEC
	IDIV T2,SECPAG		; CONVERT TO A PAGE NUMBER
	MOVEI T3,^D8
	CALL TTNOUT
	TMSG <)>		; CLOSE OFF RANGE
SUMBT2:	TMSG < pages. (>
	MOVE T1,LSTSEC		; THE END OF THE AREA
	SUB T1,FSTSEC		; GET LENGTH
	MOVE T2,BATLST		; GET THE ONE WE ARE ON
	SUB T2,FSTSEC		; AND GET THE OFFSET INTO THE AREA
	IMULI T2,^D100		; SAVE TWO DECIMAL PLACES
	IDIV T2,T1		; AND CALCULATE THE PERCENTAGE
	MOVEI T3,^D10
	CALL TTNOUT		; OUTPUT THE NUMBER
	TMSG <%>
	SKIPN FSTSEC		; DID WE START AT THE START OF THE STRUCTURE
	JRST SUMBT3		; YES, FORGET THIS STUFF
	TMSG < of unit >
	MOVE T2,THSUNI		; GET OUR UNIT NUMBER
	ADDI T2,1		; LOGICAL UNITS START AT 1, NOT ZERO
	MOVEI T3,^D10
	CALL TTNOUT
SUMBT3:	TMSG <)
>
	JRST DBK		; DONE WITH THE INTERUPT
	SUBTTL Interrupt System -- Unexpected Interrupt

;[39] All unused channels dispatch to DSPINT+n where n is the channel number.
;If we get here then there has been either a monitor problem or a CHECKD bug.

DSPINT:	REPEAT ^D36,<
	XLIST			;[39] Don't list each one
	CALL BADINT
	LIST>			;[39]

BADINT:	PUSH P,T1
	PUSH P,T2
	PUSH P,T3
	TMSG <
Unexpected interrupt, channel >
	HRRZ T2,-3(P)		;GET PC OF DISPATCH IN DSPINT
	SUBI T2,DSPINT+1		;MAKE RELATIVE
	MOVEI T1,.PRIOU
	MOVEI T3,^D8
	NOUT			;TYPE CHANNEL NUMBER
	 JFCL
	TMSG <
>
	POP P,T3
	POP P,T2
	POP P,T1
	POP P,0(P)
	DEBRK			;IGNORE IT
	SUBTTL Interrupt System -- Control-C Interrupt

;USER TYPED CTRL/C

CONTC:	SKIPE REBLDF		;REBUILDING BIT TABLE?
	JRST NOCNTC		;YES - SPECIAL WARNING
	CALL DISMNT		;NO - DISMOUNT STR IF ANY
	TMSG <^C
>
	JRST QUIT


NOCNTC:	PUSH P,T1		;SAVE AN AC
	TMSG <% Cannot interrupt bit table rebuild, ignored ...
>
	POP P,T1
	DEBRK
	SUBTTL Interrupt System -- Panic Interrupt

;[38]
;PANIC - Routine arrived through a panic channel interrupt. We'll
;give the user the option of whether or not he wants to dismount the
;structure.

PANIC:	HRROI T1,[ASCIZ /CHECKD: Panic interrupt at PC /]
	ESOUT%			;Make it a "?" error
	MOVEI T1,.CTTRM		;Put PC on terminal
	MOVE T2,LEVTAB		;Must get interrupt information (PC)
	MOVE T2,1(T2)		;Here's the PC
	TLZ T2,777700		;Only want section,,address
	MOVEI T3,^D8		;Display in octal
	NOUT%			;Show the PC
	 ERJMP .+1		;Let's not get recursive here
	TMSG <, >		;Now get ready for last error message
	CALL JSERR1		;[39] Output just the error string
	TMSG <

%WARNING: The structure is now left mounted exclusively to this job.  This is
to prevent other users from accessing the structure until you have completely
finished using it.  After repairing the structure, you may rerun CHECKD and try
your command again using structure name >
	HRROI T1,ALINAM		;[39] Point to alias name again
	PSOUT%			;[39] Send that to terminal
	TMSG <:.  If you would like to release
the structure and make it available for other users, please type CONTINUE and
the structure will be dismounted.
>				;[39]
	HALTF%			;Stop and wait for user response
	CALL DISMNT		;Now release the structure
	JRST QUIT		;Now stop and don't continue
	SUBTTL End of CHECKD
	END <4,,ENTVEC>