2!		PROGRAM		: MAKSIL.BAS
5!		VERSION		: V10.1
6!		EDIT		: A
7!		EDIT DATE	: 10-MAY-91
10		EXTEND
11!	&
  !	&
  !********************************************************************* &
  !	&
  !			  C O P Y R I G H T &
  !	&
  !	&
  !		      Copyright (C) 1977, 1991 by &
  !	        Digital Equipment Corporation, Maynard, Mass. &
  !	&
  !	&
  !	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. &
  !	&
  !********************************************************************* &

20	! &
	! &
	!	M O D I F I C A T I O N   H I S T O R Y &
	! &

21	! VER/ED	EDIT DATE	REASON &
	! V9.5		11-Aug-87	(REG) Suppress "Illegal pointer..." &
	!				error for $FSTIN &
	! &
	&

100	! &
	! &
	!	P R O G R A M    D E S C R I P T I O N &
	! &

101!	MAKSIL CONVERTS THE OUTPUT OF THE RSX-BASED TASK BUILDER &
   !	(TKB.TSK) INTO A RSTS/E SIL FORMAT FILE.  IF DESIRED, THE &
   !	TASK'S SYMBOL TABLE (.STB) WILL BE INCLUDED IN THE &
   !	RSTS/E SIL FORMAT, THUS ALLOWING SYMBOLIC PATCHING OF &
   !	THE TASK IMAGE. &
   !	&
   !	IN ORDER TO CONVERT THE TASK IMAGE, SEVERAL CONDITIONS MUST &
   !	BE MET: &
   !	&
   !	   1.	THE STARTING ADDRESS OF THE TASK (THE LABEL REFERENCED &
   !		BY THE .END STATEMENT) MUST BE WITHIN THE LOWEST 1K &
   !		OF THE READ-ONLY PORTION OF THE TASK AND ALL &
   !		.PSECTS MUST BE READ-ONLY. &
   !	&
   !	   2.	THE HIGHEST VIRTUAL ADDRESS OF THE TASK MUST BE 177774. &
   !		THE WORD AT 177774 MUST CONTAIN A VALID, NON-ZERO O.SIZE &
   !		ENTRY.  THIS IS DESCRIBED IN THE COMMON.MAC LISTING. &
   !	&
   !	IN PRACTICE, THE SECOND CONDITION IS MET BY THE FOLLOWING &
   !	PROCEDURE: &
   !	&
   !	   1.	TASK-BUILD THE RUN-TIME SYSTEM AND RUN MAKSIL. &
   !		MAKSIL WILL PRINT AN ERROR MESSAGE (TASK MUST BE &
   !		EXTENDED BY XXXXXX BYTES). &
   !	&
   !	   2.	EDIT THE TKB CONTROL FILE TO EXTEND A DUMMY CONTROL &
   !		SECTION BY THE REQUIRED NUMBER OF BYTES AND RERUN &
   !		MAKSIL.  EVERYTHING SHOULD WORK OUT THIS TIME. &
   !		THE "EDIT" MODE OF MAKSIL MAY BE USED TO MODIFY &
   !		THE CONTROL FILE AUTOMATICALLY. &
   !	&
   !	MAKSIL MAY NOT WORK CORRECTLY IF THE TASK SIZES ARE WAY OUT &
   !	OF RANGE.  SOME INTELLEGENCE ON THE PART OF THE USER IS ASSUMED. &
   !	WHEN A RUN-TIME SYSTEM IS DEFINED, THE FOLLOWING TASK-BUILDER &
   !	PARAMETERS ARE USED TO SPECIFY THE VIRTUAL AND PHYSICAL &
   !	ADDRESS RANGE NEEDED: &
   !	&
   !		PAR		DEFINE VIRTUAL ADDRESS BASE AND RANGE. &
   !				PAR ALSO IMPLICITLY SPECIFIES THE &
   !				LARGEST PROGRAM (LOW-SEGMENT) AREA. &
   !	&
   !		STACK		THE PARTITION SIZE IS A MULTIPLE OF &
   !				4K-WORDS.  IF THE RUN-TIME SYSTEM IS, &
   !				SAY, ONLY 3K-WORDS, THE STACK PARAMETER &
   !				WOULD BE DEFINED AS "STACK=1024" TO &
   !				RESERVE AN ADDITIONAL 1K-WORDS.  IF THIS &
   !				IS DONE, THE RUN-TIME SYSTEM WILL ONLY &
   !				OCCUPY 3K-WORDS OF PHYSICAL MEMORY WHEN &
   !				IT IS LOADED. &
   !	&
   !		EXTSCT		RSTS/E REQUIRES THE TASK TO END AT &
   !				VIRTUAL ADDRESS 177774.  THE EXTSCT &
   !				EXTENDS A CONTROL SECTION (USUALLY &
   !				.99998) SO THAT THE VECTOR CONTROL &
   !				SECTION (.99999) ENDS CORRECTLY. &
   !	&

110!	&
   !	THE PAR AND STACK PARAMETERS ARE DEFINED AS FOLLOWS FOR &
   !	RUN-TIME SYSTEMS OF VARIOUS SIZES: &
   !	     SIZE &
   !	   1K -  4K			PAR=160000:020000 &
   !	   5K -  8K			PAR=140000:040000 &
   !	   9K - 12K			PAR=120000:060000 &
   !	  13K - 16K			PAR=100000:100000 &
   !	  17K - 20K			PAR=060000:120000 &
   !	  21K - 24K			PAR=040000:140000 &
   !	  25K - 28K			PAR=020000:160000 &
   !	&
   !	1K 5K  9K 13K 17K 21K 25K	STACK=3072 &
   !	2K 6K 10K 14K 18K 22K 26K	STACK=2048 &
   !	3K 7K 11K 15K 19K 23K 27K	STACK=1024 &
   !	4K 8K 12K 16K 20K 24K 28K	STACK=0000 &
   !	&
   !	&
   !	THE FOLLOWING EXAMPLE SHOWS A CONTROL FILE FOR A DUMMY RUN-TIME &
   !	SYSTEM: &
   !	&
   !		FOO/-HD,FOO,FOO=FOOBLD/MP &
   !		PAR=FOO:160000:020000 &
   !		STACK=0 &
   !		EXTSCT=.99998:0 &
   !		// &
   !	&
   !	AFTER TASK BUILDING FOO.TSK AND EXECUTING MAKSIL, THE COMMAND &
   !	FILE WOULD BE EDITED TO CHANGE THE PAR, STACK, AND EXTSCT &
   !	PARAMETERS TO APPROPRIATE VALUES.  THE TASK BUILDER IS &
   !	THEN RE-RUN TO CORRECTLY BUILD THE TASK. &
   !	&
   !	FINALLY, MAKSIL IS RERUN TO BUILD FOO.RTS. &
   !	&
   !	IN PRACTICE, RUN-TIME SYSTEMS ARE BUILT BY FIRST SPECIFING &
   !	THE SIZE (4K, 8K, ETC.) AND THEN TASK-BUILDING SO AS TO INCLUDE &
   !	AS MANY MODULES RESIDENT AS WILL FIT IN THE PARTITITON &
   !	(LEAVING SUFFICIENT PATCH SPACE, OF COURSE.)  THEN, MAKSIL &
   !	IS RUN TO DEFINE THE EXTSCT VALUE.  FINALLY, THE EXTENDED &
   !	TASK IS BUILT AND CONVERTED TO A RUN-TIME SYSTEM. &
   !	&
   !	&

120!	&
   !	OPERATING INSTRUCTIONS: &
   !	&
   !	   RUN MAKSIL &
   !	&
   !	AFTER PRINTING ITS HEADER LINE, MAKSIL ASKS: &
   !	&
   !	   Resident Library name (/UTILTY command)? FOO &
   !	&
   !	INPUT THE NAME OF THE RESIDENT LIBRARY (FOO IN THE &
   !	EXAMPLE) AND ANY UTILTY COMMANDS NEEDED.  THIS WILL BE USED &
   !	TO DEFINE DEFAULT FILENAMES AND TO SETUP THE COMMAND STRING &
   !	FOR $UTILTY.BAC.  A HIDDEN OPTION, /DEBUG, MAY BE USED TO &
   !	PRINT INTERNAL TABLES DURING THE BUILD.  ANOTHER HIDDEN &
   !	OPTION, /RTS, ALLOWS THE USER TO TURN MAKSIL INTO THE OLD &
   !	MAKRTS PROGRAM. &
   !	&
   !	   Task-built Resident Library input file <FOO.TSK>? <CR> &
   !	&
   !	INPUT THE NAME OF THE .TSK FILE, OR <CR> IF THE DEFAULT &
   !	IS ACCEPTABLE. &
   !	&
   !	AT THIS POINT, AND IF A RUN-TIME SYSTEM IS TO BE BUILT, &
   !	THE TASK IS CHECKED FOR CORRECT PARAMETERS. &
   !	THE PROGRAM THEN ASKS WHETHER IT IS TO RUN IN "EDIT MODE" &
   !	TO REDEFINE TASK-BUILDER PARAMTERS, OR IN "BUILD MODE" TO &
   !	CONSTRUCT THE RUN-TIME SYSTEM: &
   !	&
   !	  Edit mode (Yes/No) <Yes>? <CR> &
   !	&
   !	IF YOU TYPE <CR> OR "YES", THE NAME OF THE TASK-BUILDER &
   !	COMMAND FILE IS REQUESTED: &
   !	&
   !	  Task-builder command input file <FOO.CMD>? <CR> &
   !	&
   !	(IF THE TASK IS ACTUALLY CORRECT, THE PROGRAM DOES NOTHING &
   !	AND EXITS.  THIS PERMITS USING MAKSIL TWICE AS PART OF A &
   !	BATCH STREAM.) &
   !	&
   !	THE COMMAND FILE IS EDITED TO MODIFY THE "EXTSCT", &
   !	"STACK", AND "PAR" COMMANDS TO EXTEND THE TASK AS &
   !	NECESSARY.  THE PROGRAM THEN ASKS: &
   !	&
   !	  Corrected command file name <FOO.CMD>? <CR> &
   !	&
   !	IF YOU RESPOND WITH <CR>, THE OLD FILE WILL BE RENAMED &
   !	"FOO.BAK" (OR WHATEVER). &
   !	&
   !	THE PROGRAM THEN REMINDS YOU TO REBUILD THE TASK AND EXITS: &
   !	&
   !	  Please task-build again using FOO.CMD &
   !	&

130!	&
   !	IF YOU ANSWERED "NO" TO THE "EDIT MODE" QUESTION, THE &
   !	PROGRAM ABORTS IF THE TASK IS NOT CORRECTLY EXTENDED. &
   !	IF ALL GOES WELL, THE FOLLOWING QUESTIONS ARE ASKED: &
   !	&
   !	   Include symbol table (Yes/No) <Yes>? <CR> &
   !	&
   !	TYPE <CR> TO APPEND A SYMBOL TABLE (.STB) TO THE RUN-TIME SYSTEM. &
   !	THIS ALLOWS PATCHING THE .RTS VIA INIT OR THE ON-LINE PATCH &
   !	MECHANISM.  IF A SYMBOL TABLE IS REQUESTED, MAKSIL ASKS: &
   !	&
   !	   Symbol table input file <FOO.STB>? <CR> &
   !	&
   !	INPUT THE NAME OF THE .STB FILE OR <CR> IF THE DEFAULT &
   !	IS ACCEPTABLE. &
   !	&
   !	   Resident Library output file <SY:[0,1]FOO.LIB>? <CR> &
   !	&
   !	INPUT THE NAME OF THE .LIB FILE OR <CR> IF THE DEFAULT IS &
   !	ACCEPTABLE. &
   !	&
   !	FOO BUILDS THE RESIDENT LIBRARY (AND SYMBOL TABLE IF REQUESTED) &
   !	INTO THE OUTPUT FILE AND PRINTS (FOR EXAMPLE): &
   !	&
   !	   FOO built in 4K words, 123 symbols in the directory &
   !	   FOO.TSK renamed to FOO.TSK<40> &
   !	&
   !	THE TASK IMAGE FILE IS RENAMED SO THAT UNPRIVILEGED &
   !	USERS CAN ACCESS THE TASK IMAGE WITH THE "HISEG=" &
   !	SWITCH WHEN TASK-BUILDING THEIR PROGRAMS. &
   !	&
   !	IF THE RUN-TIME SYSTEM WAS WRITTEN TO [0,1], MAKSIL &
   !	CHAINS TO $UTILTY TO INSTALL THE RUN-TIME SYSTEM. &
   !	THIS PROVIDES AN ADDITIONAL CHECK ON THE CORRECTNESS &
   !	OF THE BUILD PROCEDURE. &
   !	&

140!	&
   !	THE FOLLOWING ERROR MESSAGES MAY BE PRINTED: &
   !	&
   !	   ?Odd base or transfer address &
   !	&
   !		THE .TSK FILE IS GARBAGE (NO START ADDRESS) &
   !	&
   !	   %Run-time system maximum job size (XX) &
   !				exceeds calculated maximum of (YY) &
   !	&
   !		THE MAXIMUM JOB SIZE (O.SIZE) AS DEFINED IN THE .TSK IS &
   !		IMPOSSIBLE GIVEN THE SIZE OF THE RUN-TIME SYSTEM. FOR EXAMPLE, &
   !		A RUN-TIME SYSTEM REQUIRING 16K WORDS HAS DEFINED A 28K &
   !		MAXIMUM JOB SIZE.  AS THE RSTS/E MONITOR ADJUSTS THE MAXIMUM &
   !		SIZE WHEN THE RUN-TIME SYSTEM IS ADDED, THE ERROR IS NON-FATAL. &
   !	&
   !	   Incorrect file size XX, computed = YY &
   !	&
   !		THE ACTUAL FILE SIZE IS LESS THAN THAT DEFINED BY THE &
   !		TASK PARAMETERS.  THIS IS FATAL AS WILL BE INDICATED BY &
   !		A SUBSEQUENT MESSAGE. &
   !	&
   !	   The run-time system is not aligned &
   !	   The run-time system is correctly aligned &
   !	&
   !		ONE OF THE ABOVE MESSAGES IS OUTPUT DEPENDING ON THE &
   !		OUTCOME OF THE TASK VERIFICATION PHASE. &
   !	&
   !	   %Multiple COMMAND: "FIRST COMMAND", "COMMAND LINE" &
   !	&
   !		A PAR, STACK, OR EXTSCT COMMAND APPEARS &
   !		MORE THAN ONCE.  ONLY THE FIRST IS USED. &
   !	&
   !	   ?Cannot build if extension still needed &
   !	&
   !		BUILD MODE WAS SELECTED WHEN THE TASK WAS NOT ALIGNED. &
   !	&
   !	   The command file is already correct.  Exiting. &
   !	&
   !		EDIT MODE WAS SELECTED EVEN THOUGH THE TASK IS CORRECT. &
   !		THIS MAY HAPPEN IF MAKSIL IS RUN FROM A BATCH STREAM. &
   !	&
   !	   The task-builder commands have been changed as follows &
   !		old PAR			new PAR &
   !		old STACK		new STACK &
   !		old EXTSCT		new EXTSCT &
   !	   FOO will load in a XX K-words partition using YY K-words physical memory. &
   !	   ZZ (octal) bytes may be used for expansion. &
   !	   Please task-build again using FOO.CMD &
   !	&
   !		THE ABOVE IS PRINTED TO LOG EDIT-MODE CHANGES. &
   !	&
   !	   Utilty ADD suppressed &
   !	&
   !		THIS MESSAGE IS PRINTED IF THE RUN-TIME SYSTEM WAS &
   !		NOT WRITTEN TO ACCOUNT [0,1]. &
   !	&

150!	&
   !	   ?Garbage when converting "NNNNN" in "COMMAND" -- TEXT &
   !	&
   !		SOME CONVERSION ERROR OCCURRED. &
   !	&
   !	   ?Couldn't find alignment point &
   !	&
   !		THE ALIGNMENT SCAN COULD NOT LOCATE THE COMMUNICATION &
   !		VECTOR.  IS THE TASK BUILD CORRECTLY? &
   !	&
   !	   ?Partition  or stack parameter incorrect for task &
   !	&
   !		YOU ARE TRYING TO EXTEND THE TASK TOO FAR. PLEASE &
   !		REBUILD THE TASK WITH CORRECT "PAR=" AND "STACK=" COMMANDS. &
   !	&
   !	   ?Task image XXXXX.TSK cannot be converted to run-time system YYYYY. &
   !	&
   !		CHECK THAT THE TASK IS DEFINED CORRECTLY.  COMMON PROBLEMS &
   !		INCLUDE A START ADDRESS THAT ISN'T IN THE FIRST 1K SEGMENT, &
   !		A MISSING VECTOR CONTROL SECTION (.99999), AND OVERALL &
   !		INCORRECT RUN-TIME SYSTEM DESIGN.  RUNNING MAKSIL USING &
   !		THE /DEBUG SWITCH (ON THE "Run-time system name" QUESTION) &
   !		WILL CAUSE A LIST OF INTERNAL SYMBOLS TO BE PRINTED. &
   !	&
   !	   ?Error reopening symbol table &
   !	&
   !		SOMEONE'S PLAYING GAMES. &
   !	&
   !	   ?Error when opening FILE.EXT -- TEXT &
   !	   ?Disk files only, please &
   !	&
   !		THE QUESTION IS NORMALLY ASKED AGAIN. &
   !	&
   !	   ?Illegal symbol table format &
   !	   ?Error getting a .GSD entry &
   !	   ?Long formatted-binary record &
   !	   ?Illegal formatted-binary record &
   !	   ?Illegal variable-length record &
   !	&
   !		THE PRECEEDING ERRORS INDICATE GARBAGE IN THE &
   !		SYMBOL TABLE (.STB) FILE.  THE SYMBOL-TABLE &
   !		WILL NOT BE BUILT.  (THE RUN-TIME SYSTEM WILL.) &
   !	&
   !	   ?Addressing outside of task limits &
   !	&
   !		THE TASK FILE CONTAINS GARBAGE (OR MAKSIL IS &
   !		FOULED UP).  THE PROGRAM WILL CRASH. &
   !	&
   !	   ?Error getting block XX -- TEXT &
   !	   ?Error putting block XX -- TEXT &
   !	   ?Error getting from XXXXX.STB -- TEXT &
   !	   ?Fatal error -- TEXT &
   !	&
   !		THE ABOVE ARE RSTS/E FATAL ERRORS.  SORRY. &
   !	&

900	! &
	! &
	!	D I M E N S I O N   S T A T E M E N T S &
	! &

920	  DIM S%(30%), WORD%(256%), AUTO.SEGMENT%(900%), AUTO.ENTRY%(900%) &
		! S%(30)		SYS FUNCTION BUFFER &
		! WORD%(256)		GSD RECORD BUFFER &
		! AUTO.SEGMENT%(900%)	AUTOLOAD VECTOR SEGMENT DESCRIPTOR &
		! AUTO.ENTRY%(900%)	AUTOLOAD VECTOR ENTRYPOINT ADDRESS &
	\ DIM SEG.BASE%(300%) &
		! SEG.BASE%(300%)	SEGMENT TABLE BASE ADDRESSES &
	&

1000	! &
	! &
	!	H E R E   W E   G O &
	! &

1010	VERSION$="V10.1-A" &
		! DEFINE EDIT DATA &

1020	ON ERROR GOTO 19000 &
	\ PRINT IF CCPOS(0%) &
	\ T$=FNERR$(0%) &
	\ PRINT "MAKSIL";CHR$(9%);VERSION$;CHR$(9%);T$ &

1025	IMAGE$="Resident Library" &
	\ SIL.EXT$=".LIB" &
	\ TSKFILE%=1%\ SILFILE%=2%\ GSDFILE%=3% &
	\ EDITIN%=3%\ EDITOUT%=4%\ NULL%=4% &

1030	PRINT IMAGE$;" name"; &
	\ INPUT LINE LIB$\ PRINT IF CCPOS(0%) &
	\ LIB$=CVT$$(LIB$,-2%) &
	\ GOTO 1030 IF LIB$="" &
	\ DEBUG%=INSTR(1%,LIB$,"/DEBUG") &
	\ DEBUG%,DEBUG.SEGMENT%=INSTR(1%,LIB$,"/DESEG") UNLESS DEBUG% &
	\ LIB$=LEFT(LIB$,DEBUG%-1%)+RIGHT(LIB$,DEBUG%+6%) IF DEBUG% &
	\ RTS%=INSTR(1%,LIB$,"/RTS") &
	\ LIB$=LEFT(LIB$,RTS%-1%)+RIGHT(LIB$,RTS%+4%) IF RTS% &
	\ IMAGE$="Run-Time System" IF RTS% &
	\ SIL.EXT$=".RTS" IF RTS% &
	\ UTILTYSTRING$="" &
	\ Q%=INSTR(1%,LIB$,"/") &
	\ IF Q% THEN &
		UTILTYSTRING$=RIGHT(LIB$,Q%) &
	\	LIB$=LEFT(LIB$,Q%-1%) &
		! GET THE RUN-TIME SYSTEM NAME &
		! EAT ANY UTILTY SWITCHES &
		! TSKFILE%	TASK-BUILT INPUT FILE UNIT NUMBER &
		! SILFILE%	SIL FORMAT OUTPUT FILE UNIT &
		! GSDFILE%	SYMBOL-TABLE INPUT FILE UNIT &
		! EDITIN%	TKB COMMAND FILE INPUT UNIT &
		! EDITOUT%	TKB COMMAND FILE OUTPUT UNIT &
		! NULL%		WORK AREA UNIT NUMBER &
		! LIB$		LIBRARY NAME &
		! UTILTYSTRING$	COMMANDS FOR $UTILTY IF ANY &

1040	GOTO 1030 IF FNFILE%("Task-built "+IMAGE$,LIB$,".TSK",TSKFILE%,0%) &
	\ INFILE$=FILE.NAME$\ SAVFILE$=DEVICE.PART$+PROJ.PROG$+NAME.PART$ &
		! OPEN THE TASK FILE, APPLYING DEFAULTS &
		! SAVE TASK INPUT FILE NAME AND DEFAULT NAME &
		! FOR SYMBOL TABLE AND TKB COMMAND FILES. &

1045	I%=INSTR(1%,LIB$,"(") &
	\ J%=INSTR(I%+1%,LIB$,")") &
	\ LIB$=LEFT(LIB$,I%-1%)+RIGHT(LIB$,J%+1%) IF (I%<>0%) AND (J%>I%) &
	\ I%=INSTR(1%,LIB$,":") &
	\ LIB$=RIGHT(LIB$,I%+1%) IF I% &
		! STRIP OFF ANY DEV:[P,PN] ON LIB/RTS NAME &

1050	TSK.BLOCK%=0% &
	\ CHANGE SYS(CHR$(12%)) TO S% &
	\ TSK.FILE.SIZE%=S%(13%)+SWAP%(S%(14%)) &
		! CLEAR "CURRENT TKB BLOCK" VARIABLE AND &
		! GET THE FILE SIZE IN BLOCKS &

1100	! &
	! &
	!	G E T   T A S K   P A R A M E T E R S &
	! &

1110	TSK.OFFSET%,LIB.OFFSET.VAL%=0% &
	\ L.BMXZ%=FNWORD%(8%) &
	\ L.BSYS%=SWAP%(FNWORD%(10%)) AND 255%		! GET SYSTEM ID BYTE &
	\ LIB.OFFSET.VAL%=112% IF L.BSYS%=4%		! IF M+ THEN 15 WINDOWS NOT 7 &
	\ L.BSA%=FNWORD%(4%) &
	\ L.BMXV%=FNWORD%(6%) &
	\ L.BXFR%=FNWORD%(116%+LIB.OFFSET.VAL%) &
	\ LOWCODE%=L.BMXZ% &
	\ TSK%=-1% UNLESS FNWORD%(12%) AND 16384% &
	\ HDR.BLOCKS%=3% IF TSK% &
	\ GO TO 1140 UNLESS RTS% &
	\ LOWCODE%=((-(L.BXFR% AND (-2047%))/2%) AND 32767%)/32% &
	\ IF (((L.BSA% OR L.BXFR%) AND 1%)=1%) THEN &
		PRINT "?Odd base or transfer address" &
	\	GOTO 1900 &
		! TSK.OFFSET%	DATA START FOR FNWORD% &
		! L.BMXZ%	MAX LOAD SIZE IN 64-BYTE BLOCKS &
		! L.BSYS%	SYSTEM ID STRING 4=M+ &
		! LIB.OFFSET.VAL% OFFSET ABOVE LIB BLOCKS FOR REST OF STUFF &
		! L.BSA%	BASE ADDRESS OF TASK &
		! L.BMXV%	HIGHEST VIRTUAL TASK ADDRESS &
		! L.BXFR%	TASK TRANSFER ADDRESS (CODE START) &
		! CHECK FOR FUNNY BUSINESS &

1140	BASE%=L.BMXZ%-LOWCODE% &
	\ TSK.BASE%=BASE% \ BASE%=0% IF BASE%<0% &
	\ TSK.OFFSET%=(BASE%*32%)+512%-(256%*(FNWORD% &
		(118%+LIB.OFFSET.VAL%)<>0%)) UNLESS TSK% &
	\ TOP%=((LOWCODE%+31%)/32%)*32% &
	\ KWORDS%=TOP%/32% &
	\ O.SIZE%=32%-(((KWORDS%+3%)/4%)*4%) &
	\ LIB.BLOCKS%=KWORDS%*4% &
	\ LIB.BLOCKS%=TSK.FILE.SIZE% IF TSK% &
	\ LOADAD%=(32%-KWORDS%)*2048% &
	\ HILOC%=(FNUNSIGNED(L.BMXV%-L.BSA%)/2%)-(BASE%*32%)	! USE THE UNSIGNED # &
	\ TOP.BLOCK%=(TOP%/8%) + 1% &

1150	IF DEBUG% THEN &
		Z%=FNPRT%("L.BMXZ%",L.BMXZ%) &
	\	Z%=FNPRT%("L.BSA%",L.BSA%) &
	\	Z%=FNPRT%("L.BSYS%",L.BSYS%)	! PRINT SYSTEM ID &
	\	Z%=FNPRT%("L.BMXV%",L.BMXV%) &
	\	Z%=FNPRT%("L.BXFR%",L.BXFR%) &
	\	Z%=FNPRT%("LOWCODE%",LOWCODE%) &
	\	Z%=FNPRT%("BASE%",BASE%) &
	\	Z%=FNPRT%("TSK.OFFSET%",TSK.OFFSET%) &
	\	Z%=FNPRT%("TOP%",TOP%) &
	\	Z%=FNPRT%("KWORDS%",KWORDS%) &
	\	Z%=FNPRT%("O.SIZE%",O.SIZE%) &
	\	Z%=FNPRT%("LIB.BLOCKS%",LIB.BLOCKS%) &
	\	Z%=FNPRT%("LOADAD%",LOADAD%) &
	\	Z%=FNPRT%("HILOC%",HILOC%) &
	\	Z%=FNPRT%("TOP.BLOCK%",TOP.BLOCK%) &
		! GET THE VALUES WE NEED FOR LOADING: &
		! LOWCODE%	1K BOUNDARY/100 WHERE CODE STARTS &
		! BASE%		FIRST WORD/100 IN TASK TO PUT IN SIL FILE &
		! TSK.OFFSET%	BASE OF TASK IMAGE IN TASK FILE &
		! TOP%		LOWCODE% ROUNDED UP TO A 1K BOUNDARY/100 &
		! KWORDS%	RUN-TIME SYSTEM SIZE IN K-WORDS &
		! O.SIZE%	MAXIMUM JOB SIZE FOR THIS LIB SIZE &
		! LIB.BLOCKS%	RUN-TIME SYSTEM SIZE IN DISK BLOCKS &
		! LOADAD%	LOAD ADDRESS &
		! HILOC% 	HIGH INDEX IN TASK ARRAY &
		! TOP.BLOCK%	HIGHEST BLOCK ADDRESSED BY THE TASK &

1155	IF TSK% THEN &
		L.BROB%=FNWORD%(122%+LIB.OFFSET.VAL%) &
	\	L.BROL%=FNWORD%(123%+LIB.OFFSET.VAL%) &
	\	GOTO 1160 UNLESS (L.BROB%>0%) AND (L.BROL%>0%) &
	\	MULTIUSER%=-1% &
	\	R.LSA% =FNWORD%(18%) &
	\	R.LHGV%=FNWORD%(19%) &
	\	R.LMXV%=FNWORD%(20%) &
	\	R.LMXV%=R.LHGV% UNLESS R.LMXV% &
	\	RO.BLOCKS%=(L.BROL%+7%)/8% &
	\	LIB.BLOCKS%=LIB.BLOCKS%-RO.BLOCKS% &
		! SIGNAL THAT WE'VE ENCOUNTERED A /MU TASK TO MAKE INTO .SIL &
		! MULTIUSER%	<>0% IF IT'S A MULTIUSER TSK &
		! L.BROB%	RELATIVE BLOCK NUMBER OF R/O IMAGE &
		! L.BROL%	R/O LOAD SIZE IN 32-WORD BLOCKS &
		! R.LSA%	BASE ADDRESS OF R/O LIBRARY &
		! R.LHGV%	HIGHEST ADDRESS OF WINDOW 0 &
		! R.HMXV%	HIGHEST VIRTUAL ADDRESS OF LIBRARY &
		! RO.BLOCKS%	SIZE OF THE RO CODE TO BE MADE INTO A .LIB &
		! LIB.BLOCKS%	TSK FILE SIZE MINUS RO CODE &

1160	GOTO 2010 UNLESS RTS% &

1200	! &
	! &
	!	C H E C K   B O U N D A R Y   C O N D I T I O N S &
	! &

1210	EXTRA%=0% \ PRINT IF CCPOS(0%) &
	\ IF HILOC%+1% = (TOP%*32%) &
	     AND TOP.BLOCK%+(BASE%/8%)+1% = TSK.FILE.SIZE% THEN &
		IF FNWORD%(HILOC%-1%) <= 32% &
		   AND FNWORD%(HILOC%-1%) > 0% &
		   AND FNWORD%(HILOC%-2%) <> 0% THEN &
		PRINT "%Run-time system maximum job size ("; &
			NUM1$(FNWORD%(HILOC%-1%)); &
			") exceeds calculated maximum of"; O.SIZE% &
				IF FNWORD%(HILOC%-1%) > O.SIZE% &
	\	GOTO 1300 &
		! VERIFY THE RUN-TIME SYSTEM. PRINT A WARNING IF &
		! THE MAXIMUM SIZE IS OFF.  THE TESTS ARE: &
		! 1.	THE CALCULATED AND ACTUAL TOP OF TASK &
		!	ADDRESSES MUST AGREE. &
		! 2.	THE TASK FILE MUST BE THE CORRECT SIZE. &
		! 3.	THE TOP TWO WORDS OF THE TASK MUST HAVE &
		!	THE CORRECT FORMAT. &

1220	Q%= TOP.BLOCK%+(TSK.BASE%/8%)+1% &
	\ IF TSK.FILE.SIZE% < Q% THEN &
		PRINT "Incorrect file size ";TSK.FILE.SIZE%;", computed ="; Q% &
!	\	GOTO 1300 &
		! MAKE SURE THE FILE SIZES ARE CORRECT BEFORE SCANNING &
		! FOR THE CORRECT RUN-TIME SYSTEM SIZE &

1230	FINAGLE%= -1% - L.BMXV% &
	\ FOR Q%=-1% TO 256% &
	\   IF FNWORD%(HILOC%-Q%-1%) > 0% &
		AND FNWORD%(HILOC%-Q%-1%) <= 32% &
		AND FNWORD%(HILOC%-Q%-2%) <> 0% THEN &
		 EXTRA%=(Q%*2%) + FINAGLE% &
	\	 GOTO 1250 &
		! TRY TO HELP THE POOR PROGRAMMER &

1240	NEXT Q% &
	\ PRINT "?Couldn't find alignment point" &
	\ GOTO 1900 &
		! DON'T TRY FOREVER &

1250	IF (EXTRA% AND -2048%) THEN &
		PRINT "?Partiton or stack parameter incorrect for task size" &
	\	GOTO 1900 &
		! MAKE SURE EXTRA% IS REASONABLE &

1300	! &
	! &
	!	P R O C E S S   " E D I T - M O D E " &
	! &

1310	IF EXTRA% THEN &
		PRINT "The run-time system is not aligned" &
	ELSE	PRINT "The run-time system is correctly aligned" &
		! A LITTLE INFORMATION &

1320	IF FNYES%("Edit mode") = 0% THEN &
		GOTO 2000 UNLESS EXTRA% &
	\	PRINT "?Cannot build if alignment still needed" &
	\	GOTO 1900 &
		! ASK IF EDIT MODE IS NEEDED.  MAKE REALLY SURE &
		! IT ISN'T NEEDED IF IT ISN'T WANTED. &

1330	IF EXTRA% = 0% THEN &
		PRINT "The command file is already correct."; &
	\ IF DEBUG% = 0% THEN &
		PRINT "  Exiting."\ GOTO 32767 &
		! DON'T EDIT IF WE DON'T HAVE TO. &

1340	GOTO 1340 IF FNFILE%("Task-builder command",SAVFILE$,".CMD",EDITIN%,0%) &
	\ CMDFILE$=FILE.NAME$\ CMDNAME$=DEVICE.PART$+PROJ.PROG$+NAME.PART$ &
	\ OPEN CMDNAME$+".TMP" FOR OUTPUT AS FILE EDITOUT% &
	\ PAR$, STACK$, EXTSCT$ = "" &
	\ ON ERROR GOTO 1400 &
		! OPEN EDIT INPUT AND OUTPUT FILES &
		! CMDFILE$	COMMAND INPUT FILE &
		! CMDNAME$	COMMAND INPUT FILE NAME PART &

1350	WHILE 1% &
	  \ INPUT LINE #EDITIN%, CMDLINE$ &
	  \ CMDLINE$=CVT$$(CMDLINE$,4%) &
	  \ PAR$   =FNCMDLINE$(PAR$,   "PAR=") &
	  \ STACK$ =FNCMDLINE$(STACK$, "STACK=") &
	  \ EXTSCT$=FNCMDLINE$(EXTSCT$,"EXTSCT=.99998") &
	  \ PRINT #EDITOUT%, CMDLINE$ IF CMDLINE$ <> "//" &
		! GET THE NEXT LINE: &
		! EXIT IF AT END OF FILE &
		! SAVE EXISTING PAR, STACK, AND EXTSCT. &
		! NOTE: WE ONLY NEED EXTSCT.  THE OTHERS ARE FOR SHOW. &
		! (IF THESE ARE FOUND, CMDLINE$ IS SET TO "//" &
		! SO IT ISN'T OUTPUT TWICE.) &

1360	NEXT &
		! KEEP ON GOING UNTIL END OF FILE SEEN &

1400	! &
	! &
	!	E D I T   C O M M A N D   F I L E &
	! &

1410	GOTO 19000 IF ERR <> 11% &
	\ RESUME 1420 &
		! HERE ON END OF FILE WHEN READING OLD COMMAND FILE &

1420	ON ERROR GOTO 19000 &
	\ NEWEXTSCT$=EXTSCT$ &
	\ NEWEXTSCT$="EXTSCT=.99998:0" UNLESS INSTR(1%,NEWEXTSCT$,":") &
	\ OLDEXTSCT%=0% &
	\ OLDEXTSCT%=OLDEXTSCT%*8% + VAL(MID(NEWEXTSCT$,Q%,1%)) &
			FOR Q%=INSTR(1%,NEWEXTSCT$,":")+1% TO LEN(NEWEXTSCT$) &
	\ REALEXTRA% = EXTRA% + OLDEXTSCT% &
	\ CODESIZE% = ((-1%) - L.BSA%) - REALEXTRA% &
			- ((L.BXFR% AND -2048%) - (L.BSA% AND -8192%)) &
	\ PARSIZE% = (CODESIZE% + 8191%) AND -8192% &
	\ PARBASE% = -PARSIZE% &
	\ STACK%   = ((PARSIZE%-CODESIZE%-REALEXTRA%) AND (2048%+4096%)) / 2% &
	\ EXTSCT%  = REALEXTRA% AND 2047% &
	\ NEWPAR$="PAR="+LIB$+":"+FNO$(PARBASE%)+":"+FNO$(PARSIZE%) &
	\ NEWSTACK$="STACK="+NUM1$(STACK%) &
	\ NEWEXTSCT$=LEFT(NEWEXTSCT$,INSTR(1%,NEWEXTSCT$,":"))+FNO$(EXTSCT%) &
	\ IF DEBUG% THEN &
		PRINT "EXTSCT$";TAB(16%);EXTSCT$ &
	\	Z%=FNPRT%("OLDEXTSCT%",OLDEXTSCT%) &
	\	Z%=FNPRT%("LOWCODE%",LOWCODE%) &
	\	Z%=FNPRT%("FINAGLE%",FINAGLE%) &
	\	Z%=FNPRT%("EXTRA%",EXTRA%) &
	\	Z%=FNPRT%("REALEXTRA%",REALEXTRA%) &
	\	Z%=FNPRT%("CODESIZE%",CODESIZE%) &
	\	Z%=FNPRT%("PARSIZE%",PARSIZE%) &
	\	Z%=FNPRT%("PARBASE%",PARBASE%) &
	\	Z%=FNPRT%("STACK%",STACK%) &
	\	Z%=FNPRT%("EXTSCT%",EXTSCT%) &
		! DO THE DIRTY WORK: &
		! EXTSCT$	THE TASK-BUILDER COMMAND &
		! OLDEXTSCT%	THE EXTSCT= VALUE FROM THE OLD COMMAND &
		! REALEXTRA%	EXTRA WE FOUND + EXTRA IN COMMAND FILE &
		! CODESIZE%	THE EXACT SIZE OF THE RUN-TIME SYSTEM &
		! PARSIZE%	THE PARTITION (VIRTUAL ADDRESS) SIZE &
		! PARBASE%	WHERE IT STARTS IN MEMORY &
		! STACK%	FILLS OUT UNNEEDED 1K LOW-CORE &
		! EXTSCT%	STRETCHES OUT THE RUN-TIME SYSTEM &

1500	! &
	! &
	!	F I X U P   A F T E R   E D I T I N G &
	! &

1510	 PRINT #EDITOUT%, NEWPAR$ &
	\ PRINT #EDITOUT%, NEWSTACK$ &
	\ PRINT #EDITOUT%, NEWEXTSCT$ &
	\ PRINT #EDITOUT%, "//" &
	\ PRINT "The task-builder commands have been changed as follows" &
	\ PRINT "  ";PAR$;TAB(32%);"  ";NEWPAR$ &
	\ PRINT "  ";STACK$;TAB(32%);"  ";NEWSTACK$ &
	\ PRINT "  ";EXTSCT$;TAB(32%);"  ";NEWEXTSCT$ &
	\ PRINT &
	\ PRINT LIB$;" will load in a"; FNUNSIGNED(PARSIZE%)/2048%; &
			"K-word partition using"; &
			FNUNSIGNED(PARSIZE%)/2048%-STACK%/1024%; &
			"K-words physical memory." &
	\ PRINT FNO$(EXTSCT%);" (octal) bytes may be used for expansion." &
	\ PRINT &
		! FINISH UP BY WRITING THE NEW COMMANDS &

1520	CLOSE TSKFILE%, EDITIN%, EDITOUT% &
	\ PRINT "Corrected command file name <"; CMDFILE$; ">"; &
	\ INPUT LINE CMDOUT$\ CMDOUT$=CVT$$(CMDOUT$,-2%) &
	\ CMDOUT$ = CMDFILE$ IF CMDOUT$ = "" &
	\ CMDOUT$ = CMDOUT$ + ".CMD" UNLESS INSTR(1%,CMDOUT$,".") &
	\ NAME CMDFILE$+"/SIZE:-1" AS CMDNAME$+".BAK" IF CMDFILE$ = CMDOUT$ &
	\ ON ERROR GOTO 1530 &
	\ OPEN CMDNAME$+".TMP" FOR INPUT AS FILE EDITIN%, MODE 8192% &
	\ OPEN CMDOUT$ FOR OUTPUT AS FILE EDITOUT% &
	\ WHILE 1% &
	\	INPUT LINE #EDITIN%, CMD$ &
	\	PRINT #EDITOUT%, CMD$; &
	\ NEXT &
!	\ NAME CMDNAME$+".TMP/SIZE:-1" AS CMDOUT$ &
		! CLOSE THE VARIOUS FILES &
		! DO THE RENAMING USING THE "FUNNY MODE" TO &
		! KILL ANY CURRENT COPY OF FOO.BAK FIRST &

1530	CLOSE EDITIN%, EDITOUT% &
	\ KILL CMDNAME$+".TMP" &
	\ PRINT "Please task build again using "; CMDOUT$ &
	\ RESUME 32767 &
		! NORMAL EXIT FROM EDIT MODE. &

1900	! &
	! &
	!	F A T A L   E X I T   F R O M   S E T U P   P H A S E &
	! &

1910	PRINT "?Task image ";INFILE$; &
	\ PRINT " cannot be converted to run-time system ";LIB$ &
	\ CLOSE TSKFILE%, EDITIN%, EDITOUT% &
	\ GOTO 32767 &
		! SORRY ABOUT THAT &

2000	! &
	! &
	!	S E T U P   G L O B A L   S Y M B O L   T A B L E &
	! &

2010	GSD.START%=LIB.BLOCKS%+1% &
	\ GSD.SYMBOLS%,GSD.BLOCKS%=0% &
	\ GOTO 3000 UNLESS FNYES%("Include symbol table") &
	\ GOTO 2010 IF FNFILE%("Symbol table",SAVFILE$,".STB",GSDFILE%,0%) &
	\ STBFILE$=FILE.NAME$ &
	\ LOW.VEC%,LOW.SEG%=32767%	! START REAL HIGH &
		! INITIALIZE TO NO .STB STUFF AND &
		! ASK WHAT THE USER WANTS TO DO. &
		! STBFILE$	THE NAME OF THE .STB FILE &

2020	CHANGE SYS(CHR$(6%)+CHR$(-25%)+CHR$(GSDFILE%)) TO S% &
	\ F.RTYP%=S%(5%)\ F.RATT%=S%(6%) &
	\ F.RSIZ%=S%(7%)+SWAP%(S%(8%)) &
	\ F.EFBK%=S%(15%)+SWAP%(S%(16%)) &
	\ F.FFBY%=S%(17%)+SWAP%(S%(18%)) &
	\ FB%=0%\ VAR%=2% &
	\ IF F.RTYP% <> FB% AND F.RTYP% <> VAR% THEN &
		PRINT "?Illegal .STB file format" &
	\	CLOSE GSDFILE%\ GOTO 3000 &
		! READ FILE ATTRIBUTES AND SETUP &
		! FILE PARAMETERS. &
		! MAKE SURE IT'S FORMATTED BINARY OR &
		! RSX VARIABLE-LENGTH &
		! FB%		FORMATTED-BINARY RECORD TYPE CODE &
		! VAR%		VARIABLE-LENGTH RECORD TYPE CODE &
		! F.RTYP%	RECORD TYPE &
		! F.RATT%	RECORD ATTRIBUTES (NOT USED) &
		! F.RSIZ%	RECORD SIZE (NOT USED) &
		! F.EFBK%	END-OF-FILE BLOCK &
		! F.FFBY%	FIRST FREE BYTE IN F.EFBK% &

2030	NULL%=4% &
	\ OPEN "_NL:" AS FILE NULL%, RECORDSIZE 512% IF F.RTYP% = VAR% &
	\ GOSUB 17500 &
		! GET A BUFFER FOR INPUT AND SETUP &
		! FOR THE FIRST READ &

2040	WHILE FNGSD.ENTRY%(4%) &
	\	GSD.SYMBOLS%=GSD.SYMBOLS%+1% &
	\	IF TSK% THEN		! THEN WE DO FUNNY STUFF &
			IF G.FLAG% AND 32% THEN		! RELOCATED &
				Q%=G.VALUE%/8%		! CALCULATE THE VECTOR # &
	\			LOW.VEC%=Q% IF Q%<LOW.VEC%	! STORE THE SMALLEST &

2045	NEXT &
	\ LOW.VEC%=0% IF LOW.VEC%<0% OR LOW.VEC%=32767% ! MAKE SURE IT'S LEGAL &
	\ GSD.BLOCKS%=(GSD.SYMBOLS%*4% + 255%)/256% &
		! SETUP FOR GLOBAL SYMBOL COLLECTION: &
		! FIND THE LOWEST AUTOLOAD VECTOR REFERENCED &
		!  AND ASSUME THE ONES BELOW THAT ARE OVERLAYED RES-LIB VECTORS &
		! GSD.SYMBOLS%	THE NUMBER OF SYMBOLS IF NON-ZERO &
		! GSD.BLOCKS%	THE NUMBER OF BLOCKS NEEDED &
		! NOTE THAT THE .STB FILE IS READ TWICE, &
		! ONCE TO DETERMINE THE NUMBER OF SYMBOLS &
		! AND ONCE (LATER) TO TRANSFER THEM TO THE SIL FILE &

2050	Q%=FNITEM% \ ENTRY%=NWORDS%+1% &
	\ GOTO 2090 IF (ITEM%=6%) OR (Q% AND 1%) &
	\ GOTO 2050 UNLESS (ITEM%=4%) AND (WORD%(2%)=7%) &
	\ PSECT$=RAD$(WORD%(3%))+RAD$(WORD%(4%)) &
		! GET THE NEXT ENTRY AFTER GLOBAL SYMBOLS. &
		! LOOP UNLESS WE HAVE A PSECT ENTRY. &
		! FINISHED WHEN END OF MODULE ENCOUNTERED OR ERROR OCCURRED. &

2060	GOTO 2070 UNLESS PSECT$="$$ALVC"	! QUIT IF NOT AUTOLOAD STUFF &
	\	Q%=FNITEM% \ ENTRY%=NWORDS%+1%	! SKIP THE TEXT ENTRY &
	\	GOTO 2070 UNLESS ITEM%=3% 	! EXIT IF WRONG TYPE &
	\	Q%=FNITEM% \ ENTRY%=NWORDS%+1% &
	\	GOTO 2070 UNLESS ITEM%=4%	! EXIT IF WRONG TYPE &
	\	IF WORD%(2%)=1541% THEN		! 3005(8) OLD AUTOLOAD &
			OFF.AUTO%=0%		! SET UP THE OFFSET &
		ELSE &
		IF WORD%(2%)=1540% THEN		! 3004(8) NEW AUTOLOAD &
			OFF.AUTO%=-1%		! GO 1 LOWER IN THIS CASE &
		ELSE &
			GOTO 2068		! SO JUST SKIP OVER IT &

2065	GOTO 2068 UNLESS WORD%(6%+OFF.AUTO%)=2061% ! Next record must be &
						! additive relocation &
\	GOTO 2050 IF WORD%(10%+OFF.AUTO%) = 2573% ! Skip .NAME sections &
\	GOTO 2068 UNLESS WORD%(10%+OFF.AUTO%) = 2576% ! Get out unless &
						! next type is reslib relocation &
\	AUTO.SEGMENT%(VINDX%)=WORD%(9%+OFF.AUTO%) &
\	AUTO.ENTRY%(VINDX%)=L.BSA%+WORD%(11%+OFF.AUTO%) &
\	VINDX%=VINDX%+1% &
\	GOTO 2050 &
		! GET TO AN AUTOLOAD VECTOR PSECT ENTRY &
		! SKIP THE TEXT PART &
		! GRAP THE UPDATED INFO FROM THE NEXT ENTRY &
		!  THE SEGMENT OFFSET AND ENTRY VALUE &
		! THEN LOOP &

2068	PRINT "%Unexpected type during ";PSECT$;" phase of symbol resolution." &
	\	GOTO 2080 &

2070	IF PSECT$="$$SGD1" THEN &
		Q%=FNITEM% \ ENTRY%=NWORDS%+1%		! SKIP THE TEXT ENTRY &
	\	IF ITEM%=3% THEN &
			PRINT "%Segment length changed" IF SEG.DESCRIP.LEN%<> &
				(NWORDS%-2%)*2% IF SEG.DESCRIP.LEN% &
	\		SEG.DESCRIP.LEN%=(NWORDS%-2%)*2% &
	\		SEG.NUMBER%=WORD%(2%)/SEG.DESCRIP.LEN% &
	\		LOW.SEG%=SEG.NUMBER% IF SEG.NUMBER%<LOW.SEG% &
	\		Q%=FNITEM% \ ENTRY%=NWORDS%+1%	! SKIP THE RELOCATION ENTRY &
	\	IF ITEM%=4% THEN &
			IF WORD%(2%)<>1552% THEN	! NOT 3020(8) THEN ERROR &
				GOTO 2068		! GIVE ERROR &
			ELSE				! DO IT &
				SEG.BASE%(OVL.DESCRIPTORS%)=L.BSA%+WORD%(3%) &
	\			OVL.DESCRIPTORS%=OVL.DESCRIPTORS%+1% &
		! GET TO THE SEGMENT DESCRIPTOR PSECT ENTRY &
		!  CALCULATE THE LENGTH OF THE SEGMENT DESCRIPTOR &
		!  AND REMEMBER THE LOWEST SEGMENT NUMBER FOUND. &
		!   THIS IS BECAUSE THE SEGMENTS DON'T START AT 0 &
		! SKIP RELOCATION PART BUT SAVE SEGMENT BASE ADDRESS &
		! AND COUNT UP NUMBER OF SEGMENT DESCRIPTORS &
		! THEN LOOP &

2080	GOTO 2050 &
		! UNKNOWN PSECT ENTRY &

2090	OVL.START%=LIB.BLOCKS%+GSD.BLOCKS%+1% IF OVL.DESCRIPTORS% &
	\ SEG.BLOCKS%=(OVL.DESCRIPTORS%*4% + 255%)/256% &
	\ CLOSE GSDFILE% &
	\ LOW.SEG%=0% IF LOW.SEG%<0% OR LOW.SEG%=32767% ! MAKE SURE ITS LEGAL &
	\ IF DEBUG.SEGMENT% THEN &
		Z%=FNPRT%("SEG LENGTH",SEG.DESCRIP.LEN%) &
	\	Z%=FNPRT%("$$ALVC ENTRIES",VINDX%) &
	\	Z%=FNPRT%("$$SGD1 ENTRIES",OVL.DESCRIPTORS%) &
	\	Z%=FNPRT%("LOW.VEC%",LOW.VEC%) &
	\	Z%=FNPRT%("LOW.SEG%",LOW.SEG%) &

3000	! &
	! &
	!	C O P Y    E V E R Y T H I N G   O U T &
	! &

3010	BLOCKS%=LIB.BLOCKS%+GSD.BLOCKS%+SEG.BLOCKS%+1% &
	\ SILFILE$=SAVFILE$ &
	\ SILFILE$="_SY:[0,1]"+LIB$ IF RTS% &
	\ IMAGE$="Task Image SIL" IF TSK% &
	\ SIL.EXT$=".SIL" IF TSK% &
	\ GOTO 1000 IF FNFILE%(IMAGE$,SILFILE$,SIL.EXT$,SILFILE%,BLOCKS%) &
	\ OUTFILE$=FILE.NAME$\ OUTNAME$=DEVICE.PART$+PROJ.PROG$+NAME.PART$ &
	\ OUTPUT.NEEDED%,CURRENT.BLOCK%,HIGHEST.BLOCK%=0% &
	\ OUT.BASE%=2% &
		! OPEN THE RUN-TIME SYSTEM FILE &
		! OUTFILE$	SIL OUTPUT FILE (TO CHECK FOR [0,1]) &
		! OUTNAME$	NAME OF OUTPUT FILE (FOR UTILTY ADD) &
		! OUTPUT.NEEDED% FLAG FOR FILE WRITER &
		! CURRENT.BLOCK% CURRENT BLOCK IN CORE FOR FILE WRITER &
		! HIGHEST.BLOCK% LAST BLOCK WRITTEN FOR FILE WRITER &
		! OUT.BASE%	FIRST BLOCK TO WRITE ON &

3020	B%=(TSK.OFFSET%/256%) &
	\ TSK.BLOCK%=(LOWCODE%+7%)/8% UNLESS TSK% &
	\ TSK.BLOCK%=LIB.BLOCKS% IF TSK% &
	\ Q%=OUT.BASE%-1% &
	\ FOR I%=1% TO TSK.BLOCK% &
	\ GET #TSKFILE%, RECORD B%+I% &
	\ PUT #SWAP%(TSKFILE%)+SILFILE%, RECORD Q%+I% &
	\ NEXT I% &
		! MOVE OVER .TSK CODE USING FOREIGN BUFFER I/O &

3030	GOTO 4000 UNLESS GSD.SYMBOLS% &
	\ ON ERROR GOTO 3160 &
	\ OPEN STBFILE$ FOR INPUT AS FILE GSDFILE%, MODE 8192% &
	\ ON ERROR GOTO 19000 &
	\ GOSUB 17500 &
	\ OUT.BASE%=LIB.BLOCKS%+2% &
	\ I%,PAR.BASE%,PAR.OFFSET%=0% &

3100	WHILE FNGSD.ENTRY%(0%) &
	\ G.TYPE%=SWAP%(G.FLAG%) AND 255% &
	\ GOTO 3105 IF G.TYPE%=4% &
	\ PSECT$=RAD$(G.NAME1%)+RAD$(G.NAME2%) &
	\ IDENT1%=G.NAME1% IF G.TYPE%=6% &
	\ IDENT2%=G.NAME2% IF G.TYPE%=6% &
	\ GOTO 3100 IF G.TYPE%<>5% &
	\ PAR.OFFSET%=0% IF PSECT$=". ABS." &
	\ PAR.BASE%=PAR.OFFSET% &
	\ PAR.OFFSET%=PAR.OFFSET%+G.VALUE% &
	\ AUTOLOAD%=(PSECT$="$$ALVC") &
	\ GOTO 3100 &
		! IF GLOBAL SYMBOL (G.TYPE=4) GO CHECK FOR RELOCATION &
		! IF GLOBAL PSECT (G.TYPE=5) THEN UPDATE BASE%, OFFSET% AND AUTOLOAD% &
		! IF PROGRAM VERSION (G.TYPE=6) THEN SAVE AWAY IN IDENT1%,IDENT2% &
		! ...IGNORE ANYTHING ELSE &

3105	RELATIVE.SYMBOL%=G.FLAG% AND 32% &
	\ G.FLAG%=0% &
	\ IF RELATIVE.SYMBOL% THEN &
		IF NOT (AUTOLOAD% OR TSK%) THEN &
			G.VALUE%=G.VALUE%+PAR.BASE% &
		ELSE	G.INDX%=G.VALUE%/8% &
	!	VECTOR # = OFFSET POINTER/LENGTH OF EACH VECTOR &
	\		G.INDX%=G.INDX%-LOW.VEC%	! CORRECT FOR OVERLAYED RES-LIBS &
	\	    IF G.INDX%<0% THEN &
			GOSUB 3300 	! PRINT INFORMATION &
			! PRINT "Illegal pointer from OVERLAYED LIB value - ";NUM1$(G.INDX%) &
		    ELSE &
			IF (G.INDX% < VINDX%) THEN &
				G.VALUE%=AUTO.ENTRY%(G.INDX%) &
	\			G.FLAG%=(AUTO.SEGMENT%(G.INDX%)/SEG.DESCRIP.LEN%)-LOW.SEG% &
	\			G.FLAG%=0% IF FNUNSIGNED(G.VALUE%)< &
					FNUNSIGNED(SEG.BASE%(G.FLAG%)) &
	\		IF DEBUG.SEGMENT% THEN &
				PRINT RAD$(G.NAME1%);RAD$(G.NAME2%);TAB(16%); &
				FNO$(G.VALUE%);"  - ";G.FLAG% &
		! IF A RELATIVE RELOCATION IS CALLED FOR THEN EITHER &
		! UPDATE VALUE FROM ACCUMULATED BASE OR USE THE &
		! AUTOLOAD VECTORS SAVED FROM PASS 1. IN THE CASE OF &
		! .TSK FILES ALWAYS USE AUTOLOAD VECTORS. &
		! IF THE BASE OF THE SEGMENT IS GREATER THAN AUTOLOAD ENTRY &
		! THEN TKB HAS MOVED THE CODE TO THE ROOT. &
		!  IF LESS THAN, THEN GET THE VALUE OF THE VARIABLE, AND CALCULATE &
		!   THE SEGMENT NUMBER FROM THE &
		!   ((OFFSET STORED)/LENGTH OF DESCRIPTOR)-LOWEST SEGMENT FOUND &

3110	Q%=FNSET%(I%,G.NAME1%) &
		+FNSET%(I%+1%,G.NAME2%) &
		+FNSET%(I%+2%,G.FLAG%) &
		+FNSET%(I%+3%,G.VALUE%) &
	\ I%=I%+4% &
	\ NEXT &
		! OUTPUT THE GLOBAL SYMBOLS (CORRECTED FOR RELOCATION) &

3120	GOTO 3125 UNLESS (I% AND 255%) &
	\ VINDX%=(I% AND -256%)+255% &
	\ Q%=FNSET%(I%,0%) FOR I%=I% TO VINDX% &
 		! COLLECT ALL SYMBOLS, STARTING &
  		! AT THE NEXT BLOCK PAST THE LIBRARY CODE &
		! ZERO OUT A PARTIAL LAST BLOCK &

3125	GOTO 4000 UNLESS OVL.DESCRIPTORS%	! THAT'S ALL THERE IS &
	\ OUT.BASE%=LIB.BLOCKS%+GSD.BLOCKS%+2% &
	\ I32768%=32767%+1% &
	\ I%=0% &

3130	Q%=FNITEM% \ ENTRY%=NWORDS%+1% &
	\ GOTO 3180 IF (ITEM%=6%) OR (Q% AND 1%) &
	\ GOTO 3130 UNLESS (ITEM%=4%) AND (WORD%(2%)=7%) &
	\ PSECT$=RAD$(WORD%(3%))+RAD$(WORD%(4%)) &
		! GET THE NEXT ENTRY AFTER GLOBAL SYMBOLS. &
		! FINISHED WHEN END OF MODULE ENCOUNTERED OR ERROR OCCURRED. &

3140	IF PSECT$="$$SGD1" THEN &
		Q%=FNITEM% \ ENTRY%=NWORDS%+1%	! GET THE DISK OFFSET AND SIZE &
	\	IF ITEM%=3% THEN &
			DISK.OFFSET%=((WORD%(3%)+(3%*(TSK%=0%))) AND 4095%)+1% &
	!	-3 FOR LIBRARIES, SINCE THEY DON'T HAVE THE 3 BLOCK HEADER &
	\		BYTE.OFFSET=DISK.OFFSET%*512. &
	\		HIGH.BYTE.OFFSET%=BYTE.OFFSET/65536. &
	\		MOD.OFFSET=(BYTE.OFFSET-(HIGH.BYTE.OFFSET%*65536.)) &
	\		LOW.BYTE.OFFSET%=0% &
	\		LOW.BYTE.OFFSET%=I32768% IF MOD.OFFSET>32767% &
	\		MOD.OFFSET=MOD.OFFSET+I32768% IF MOD.OFFSET>32767% &
	\		LOW.BYTE.OFFSET%=LOW.BYTE.OFFSET%+MOD.OFFSET &
	\		SEG.SIZE%=WORD%(5%) &
	\		SEG.NUMBER%=(WORD%(2%)/SEG.DESCRIP.LEN%)-LOW.SEG%	! THIS SEGMENTS NUMBER &
	\		Q%=FNITEM% \ ENTRY%=NWORDS%+1%	! GET THE BASE ADDRESS &
	\	IF ITEM%=4% THEN &
			SEG.BASE%=L.BSA%+WORD%(3%) IF WORD%(2%)=1552% &
	\	Q%=FNSET%(I%,SEG.BASE%) &
			+FNSET%(I%+1%,SEG.SIZE%) &
			+FNSET%(I%+2%,HIGH.BYTE.OFFSET%) &
			+FNSET%(I%+3%,LOW.BYTE.OFFSET%) &
	\	I%=I%+4% &
	\	IF DEBUG.SEGMENT% THEN &
			PRINT "SEGMENT NUMBER ";NUM1$(SEG.NUMBER%);" AT ";NUM1$(I%-4%) &
	\		Z%=FNPRT%("SEG.BASE%",SEG.BASE%) &
	\		Z%=FNPRT%("SEG.SIZE%",SEG.SIZE%) &
	\		Z%=FNPRT%("HIGH.~.OFFSET%",HIGH.BYTE.OFFSET%) &
	\		Z%=FNPRT%("LOW.~.OFFSET%",LOW.BYTE.OFFSET%) &
	\		Z%=FNPRT%("DISK.OFFSET%",DISK.OFFSET%) &

3150	GOTO 3130 &
		! UNRECOGNIZED PSECT ENTRY &

3160	GOTO 19000 IF ERL <> 3030 &
	\ T$=FNERR$(ERR) &
	\ PRINT "?Error reopening ";STBFILE$;" -- ";T$ &
	\ GSD.SYMBOLS%=0% &
	\ RESUME 3190 &
		! ERROR WHEN ACTUALLY COLLECTING &
		! .GSD STUFF.  OMIT COLLECTION &

3180	GOTO 3190 UNLESS (I% AND 255%) &
	\ VINDX%=(I% AND -256%)+255% &
	\ Q%=FNSET%(I%,0%) FOR I%=I% TO VINDX% &
		! ZERO OUT A PARTIAL LAST BLOCK &

3190	ON ERROR GOTO 19000 &
		! RESET ERROR HANDLER &

3195	GOTO 4000 &

3300	THIS.SYMBOL$=RAD$(G.NAME1%)+RAD$(G.NAME2%) &
	\ PRINT "Illegal pointer from OVERLAYED LIB: Value: ";NUM1$(G.INDX%);" - ";THIS.SYMBOL$ &
		UNLESS (THIS.SYMBOL$="$FSTIN") AND (DEBUG%=0%) &
	\ RETURN &
	! IF THE USER DID NOT REQUEST FAST MAPPING THEN TKB CHANGED THE VALUE &
	! OF $FSTIN ON THE FLY TO POINT TO A DUMMY ROUTINE INSTEAD OF TO AN &
	! AUTOLOAD VECTOR, BUT THE RELATIVE BIT (5) WAS NOT RESET, SO THIS IS &
	! NOT AN ERROR FOR $FSTIN. &
	&

4000	! &
	! &
	!	L O A D   . S I L   I N D E X &
	! &

4010	OUT.BASE%=1% &
	\ SIL.START%=1%+HDR.BLOCKS%	! ALLOW FOR A TSK HEADER &
	\ MODXFR%=1%			! DEFAULT TO NO TRANSFER ADDRESS &
	\ IF RTS% THEN &
		MODSIZE%=(TOP%*64%)-2%	! MODULE SIZE (BYTES) &
	  ELSE	LOADAD%=L.BSA%		! SUPPLY A POSSIBLE LOAD ADDRESS &
	\	MODSIZE%=(L.BMXV%+1%)-LOADAD% ! CALCULATE THE MODULE SIZE (BYTES) &
	\	LOADAD%=1% UNLESS L.BSA%! PIC LIBRARIES HAVE NO LOAD ADDRESS &
	\	DISKSIZE%=KWORDS%*4%	! FOR THOSE LIBRARIES >32K WORDS &
	\	IF TSK% THEN &
			MODXFR%=L.BXFR%	! SET ACTUAL TASK TRANSFER ADDRESS &
	\		LOADAD%=512%	! TASK'S ALWAYS START AT 1000(8) &
	\		DISKSIZE%=LIB.BLOCKS%-HDR.BLOCKS% &
					! DISKSIZE% INCLUDES OVERLAYS (IF ANY)
4015	Q%=FNSET%(0%,1%)		! NUMBER OF MODULES &
	  +FNSET%(1%,FNRAD%(LIB$,1%))	! SIL NAME (FIRST 3 BYTES) &
	  +FNSET%(2%,FNRAD%(LIB$,4%))	! SIL NAME (LAST  3 BYTES) &
	  +FNSET%(3%,IDENT1%)		! .IDENT   (FIRST 3 BYTES) &
	  +FNSET%(4%,IDENT2%)		! .IDENT   (LAST  3 BYTES) &
	  +FNSET%(5%,SIL.START%)	! SIL CODE START BLOCK &
	  +FNSET%(6%,GSD.START%)	! GLOBAL SYMBOL START BLOCK &
	  +FNSET%(7%,GSD.SYMBOLS%)	! NUMBER OF GLOBAL SYMBOLS &
	  +FNSET%(8%,LOADAD%)		! LOAD ADDRESS OF SIL &
	  +FNSET%(9%,MODSIZE%)		! MODULE SIZE (BYTES) &
	  +FNSET%(10%,MODXFR%)		! TRANSFER ADDRESS &
	  +FNSET%(11%,DISKSIZE%)	! MODULE SIZE (256 WORD DISK BLOCK) &
	  +FNSET%(12%,OVL.START%)	! OVERLAY DESCRIPTOR START BLOCK &
	  +FNSET%(13%,OVL.DESCRIPTORS%)	! NUMBER OF SEGMENT DESCRIPTORS &
		! SETUP SIL INDEX AREA &

4240	GOSUB 11000 &
	\ PRINT LIB$;" built in";KWORDS%;"K-words,"; &
	\ PRINT GSD.SYMBOLS%;"symbols in the directory" &
	\ TSKFILE$=INFILE$ &
	\ PROT$="<40>" &
	\ GOTO 4250 UNLESS TSK% &
	\ TSKFILE$=OUTFILE$ &
	\ PROT$="<104>" &
	\ CHANGE SYS(CHR$(6%)+CHR$(-25%)+CHR$(TSKFILE%)+CHR$(0%)) TO S% &
	\ S%(1%)=6% \ S%(2%)=-17% \ S%(3%)=SILFILE% &
	\ S%(I%)=S%(I%+23%) FOR I%=4% TO 7% &
	\ CHANGE S% TO S$ \ A$=SYS(S$) &
		! UPDATE "SIL" INDEX BLOCK. &

4245	S%(I%)=0% FOR I%=6% TO 30% &
	\ S%(0%)=30% &
	\ S%(1%)=6% &
	\ S%(2%)=-25% &
	\ S%(3%)=SILFILE% &
	\ S%(4%)=7% &
	\ S%(5%)=1% &
	\ S%(8%)=2% &
	\ S%(11%)=BLOCKS% &
	\ S%(12%)=SWAP%(S%(11%)) &
	\ S%(15%)=S%(11%)+1% &
	\ S%(16%)=SWAP%(S%(15%)) &
	\ CHANGE S% TO S$ \ A$=SYS(S$) &
	\ GOTO 4250 UNLESS MULTIUSER% &
		! WRITE FIXED FILE ATTRIBUTES FOR .SIL (.TSK IMAGE) &
		! SKIP NEXT STEP UNLESS A MULTI-USER TASK &
	\ OUT.BASE%=2% \ HIGHEST.BLOCK%=LIB.BLOCKS% &
	\ Q%=FNSET%(16%,FNRAD%(LIB$,1%)) &
	    +FNSET%(17%,FNRAD%(LIB$,4%)) &
	    +FNSET%(20%,R.LMXV%) &
	\ Q%=FNFORCE.OUT% &
	\ LIBFILE%=SILFILE% &
	\ SILFILE%=6% &
	\ RO.1KPAD%=((RO.BLOCKS%+3%)/4%)*4% &
	\ OPEN DEVICE.PART$+PROJ.PROG$+LIB$+".LIB" FOR OUTPUT AS FILE SILFILE%, &
			FILESIZE RO.1KPAD%+1%+GSD.BLOCKS%, MODE 64%+32% &
	\ B%=L.BROB%-1% &
	\ Q%=OUT.BASE%-1% &
	\ FOR I%=1% TO RO.BLOCKS% &
	\	GET #TSKFILE%, BLOCK B%+I% &
	\	PUT #SWAP%(TSKFILE%)+SILFILE%, BLOCK Q%+I% &
	\ NEXT I% &
		! MOVE OVER .TSK CODE USING FOREIGN BUFFER I/O. &
	\ B%=GSD.START% &
	\ Q%=RO.1KPAD%+1% &
	\ FOR I%=1% TO GSD.BLOCKS% &
	\	GET #LIBFILE%, BLOCK B%+I% &
	\	PUT #SWAP%(LIBFILE%)+SILFILE%, BLOCK Q%+I% &
	\ NEXT I% &
		! MOVE OVER .STB CODE USING FOREIGN BUFFER I/O. &
	\ CLOSE LIBFILE% &
		! FINISHED WITH THE .SIL, CLEAN UP .LIB &
	\ OUT.BASE%=1% \ HIGHEST.BLOCK%=RO.BLOCKS% &
	\ Q%=FNSET%(0%,1%)		! NUMBER OF MODULES &
	    +FNSET%(1%,FNRAD%(LIB$,1%))	! SIL NAME (FIRST 3 BYTES) &
	    +FNSET%(2%,FNRAD%(LIB$,4%))	! SIL NAME (LAST  3 BYTES) &
	    +FNSET%(3%,IDENT1%)		! .IDENT   (FIRST 3 BYTES) &
	    +FNSET%(4%,IDENT2%)		! .IDENT   (LAST  3 BYTES) &
	    +FNSET%(5%,1%)		! SIL CODE START BLOCK &
	    +FNSET%(6%,RO.1KPAD%+1%)	! GLOBAL SYMBOL START BLOCK &
	    +FNSET%(7%,GSD.SYMBOLS%)	! NUMBER OF GLOBAL SYMBOLS &
	    +FNSET%(8%,R.LSA%)		! LOAD ADDRESS OF SIL &
	    +FNSET%(9%,L.BROL%*64%)	! MODULE SIZE (BYTES) &
	    +FNSET%(10%,1%)		! TRANSFER ADDRESS &
	    +FNSET%(11%,RO.1KPAD%)	! MODULE SIZE (256 WORD DISK BLOCK) &
	    +FNSET%(12%,0%)		! OVERLAY DESCRIPTOR START BLOCK &
	    +FNSET%(13%,0%)		! NUMBER OF SEGMENT DESCRIPTORS &
		! SETUP "SIL" INDEX AREA. &
	&
	\ GOSUB 11000 &
		! UPDATE "SIL" INDEX BLOCK. &

4250	CLOSE TSKFILE%,SILFILE% &
	\ NAME TSKFILE$ AS TSKFILE$ + PROT$ &
	\ PRINT TSKFILE$; " renamed to "; TSKFILE$; PROT$ &

4255	GOTO 32767 IF (RTS%=0%) AND (LEN(UTILTYSTRING$)=0%) &
	\ IF (INSTR(1%,OUTFILE$,"[0,1]")=0%) AND RTS% THEN &
		PRINT "Utility ADD suppressed" &
	\	GOTO 32767 &
		! ADD IT ONLY IF IT'S IN [0,1] &
		! A BIT OF DOCUMENTATION &
		! ALL DONE &

4260	Q$=SYS(CHR$(8%)+"UTILTY ADD "+OUTNAME$+UTILTYSTRING$) &
	\ ON ERROR GOTO 0 &
	\ CHAIN "[1,2]UTILTY" LINE 30000 &
	\ GOTO 32767 &
		! PUT UTILTY COMMAND IN CORE-COMMON &
		! THAT'S ALL, FOLKS &

11000	Q%=FNSET%(I%,0%) FOR I%=14% TO 253% &
		! CLEAR OUT THE REMAINDER OF THE "SIL" INDEX. &
	\ C%=0% &
	\ FOR I%=0% TO 253% &
	\	FIELD #SILFILE%, I%*2% AS Q$, 2% AS Q$ &
	\	C%=C% XOR SWAP%(CVT$%(Q$)) &
	\ NEXT I% &
		! CALCULATE CHECKSUM OF FIRST 253 WORDS. &
	\ Q%=FNSET%(254%,C%) + FNSET%(255%,FNRAD%("SIL",1%)) &
		! LOAD CHECKSUM AND "SIL" FLAG. &
	\ Q%=FNFORCE.OUT% &
		! UPDATE "SIL" INDEX BLOCK. &

11020	RETURN &

15000	! &
	! &
	!	F U N C T I O N S &
	! &

15100	! &
	! &
	!	F N F I L E % ( P R O M P T $ , N A M E $ , E X T $ , &
	!			U N I T % , S I Z E % ) &
	! &
	! &

15110	DEF* FNFILE%(PROMPT$,FILNAME$,EXT$,CHANNEL%,FILE.SIZE%) &
		! &
		! INQUIRE AND OPEN A FILE: &
		! &
		! PROMPT$	WHAT TO ASK FOR &
		! FILNAME$	DEFAULT FILE NAME &
		! EXT$		DEFAULT EXTENSION &
		! CHANNEL%	CHANNEL ON WHICH TO OPEN &
		! FILE.SIZE%	FILE SIZE FOR OUTPUT, 0% FOR INPUT. &
		! &
		! NOTE: &
		!	INPUT FILES ARE OPENED READ-ONLY, &
		!	OUTPUT FILES ARE OPENED CONDITIONALLY CONTIGUOUS &
		!		FOR .TSK FILES, CONTIGUOUS OTHERWISE &
		!	THE FULL FILE NAME IS RETURNED IN FILE.NAME$ &
		!	THE FILE NAME (WITHOUT EXTENSION) IS RETURNED &
		!		IN NAME.PART$. &
		!	THE DEVICE NAME (IF SPECIFIED) IS RETURNED &
		!		IN DEVICE.PART$. &
		!	THE PROJ,PROG NUMBER (IF SPECIFIED) IS RETURNED &
		!		IN PROJ.PROG$. &
		! &

15120	ON ERROR GOTO 15150 &
	\ PRINT IF CCPOS(0%) &
	\ PRINT PROMPT$; " input"; UNLESS FILE.SIZE% &
	\ PRINT PROMPT$; " output"; IF FILE.SIZE% &
	\ PRINT " file <"; RIGHT(FILNAME$,INSTR(1%,FILNAME$,"_")+1%); EXT$; ">"; &
	\ INPUT LINE FILE.NAME$\ PRINT IF CCPOS(0%) &
	\ FILE.NAME$=CVT$$(FILE.NAME$,-2%) &
	\ FILE.NAME$=FILNAME$+EXT$ IF FILE.NAME$="" &
	\ FILE.NAME$=FILE.NAME$+EXT$ UNLESS INSTR(1%,FILE.NAME$,".") &
	\ CHANGE SYS(CHR$(6%)+CHR$(-10%)+FILE.NAME$) TO S% &
	\ NAME.PART$ = CVT$$(RAD$(S%(7%)+SWAP%(S%(8%))) &
			+ RAD$(S%(9%)+SWAP%(S%(10%))), -2%) &
	\ S%=S%(29%)+SWAP%(S%(30%)) &
	\ PROJ.PROG$ = "" &
	\ PROJ.PROG$ = "["+NUM1$(S%(6%))+","+NUM1$(S%(5%))+"]" IF (S% AND 128%) &
		! SCAN THE FILE NAME TO GET THE NAME PART ITSELF. &
		! IF NO PROJ,PROG NUMBER SPECIFIED, THEN GO ON. &
		! RECONSTRUCT THE PROJ,PROG NUMBER FROM S% &

15125	DEVICE.PART$ = "" &
	\ GOTO 15130 UNLESS (S% AND 4096%) &
	\ DEVICE.PART$ = CHR$(S%(23%))+CHR$(S%(24%)) &
	\ DEVICE.PART$ = DEVICE.PART$+NUM1$(S%(25%)) IF S%(26%) &
	\ DEVICE.PART$ = "_"+DEVICE.PART$ IF (S% AND 8192%) &
	\ DEVICE.PART$ = RAD$(S%(23%)+SWAP%(S%(24%)))+RAD$(S%(25%)+SWAP%(S%(26%))) IF S%<0% &
	\ DEVICE.PART$ = DEVICE.PART$+":" IF LEN(DEVICE.PART$) &
	\ IF S% >= 0% THEN &
		IF (STATUS AND 255%) THEN &
			PRINT "?Disk files only, please" &
	\		FNFILE%=6%\ GOTO 15180 &
		! IF NO DEVICE TYPE SPECIFIED, THEN GO ON. &
		! RECONSTRUCT THE DEVICE SPECIFIER FROM S% &
		! CHECK THAT, IF A DEVICE TYPE WAS SPECIFIED, IT &
		! IS INDEED A DISK. &

15130	IF FILE.SIZE% = 0% THEN &
		OPEN FILE.NAME$ FOR INPUT AS FILE CHANNEL%, MODE 8192% &
	ELSE	CONTIGUOUS.MODE%=64% &
	\	CONTIGUOUS.MODE%=16% UNLESS TSK% &
	\	OPEN FILE.NAME$ FOR OUTPUT AS FILE CHANNEL%, &
			FILESIZE FILE.SIZE%, MODE CONTIGUOUS.MODE%+32% &
		! OPEN IT UP IN CONTIGUOUS (CONDITIONALLY) AND TENATIVE &

15140	FNFILE%=0% &
	\ GOTO 15180 &
		! THAT'S ALL FOR NOW &

15150	IF ERL < 15120 OR ERL > 15130 THEN &
		GOTO 19000 &
	ELSE	IF ERR = 11% THEN RESUME 32767 &
	ELSE	T$=FNERR$(ERR) &
	\	PRINT '?Error when opening "';FILE.NAME$;'" -- ';T$ &
	\	FNFILE%=ERR &
	\	RESUME 15180 &
		! OPEN ERROR, TRY AGAIN &

15180	ON ERROR GOTO 19000 &

15190	FNEND &

15200	! &
	! &
	!	F N R A D % ( S T R I N G $ , S T A R T % ) &
	! &

15210	DEF* FNRAD%(VALUE$,START%) = &
			SWAP%(CVT$%(MID(SYS(CHR$(6%)+CHR$(-10%) &
			+ MID(VALUE$,START%,3%)),7%,2%))) &
		! &
		! CONVERT A THREE-CHARACTER STRING TO RAD50: &
		! &
		! VALUE$	WHAT TO CONVERT &
		! START%	THE FIRST BYTE TO CONVERT &
		! &

15300	! &
	! &
	!	F N E R R $ ( C O D E % ) &
	! &

15310	DEF* FNERR$(CODE%) = CVT$$(RIGHT( &
			SYS(CHR$(6%)+CHR$(9%)+CHR$(CODE%)),3%),4%) &
		! &
		! RETURN AN ERROR MESSAGE TEXT: &
		! &
		! CODE%		ERROR MESSAGE NUMBER &
		! &

15400	! &
	! &
	!	F N O $ ( V A L U E % ) &
	! &

15410	DEF* FNO$(VALUE%) &
		! &
		! CONVERT VALUE% TO AN OCTAL STRING &
		! &
		! &

15420	IF VALUE% >= 0% THEN &
		Q$="0" &
	ELSE	Q$="1"\ VALUE%=VALUE% AND 32767% &

15430	 Q$=Q$+CHR$(48% + ((VALUE%/8%^Q%) AND 7%)) &
			FOR Q%=4% TO 0% STEP -1% &
	\ FNO$=Q$ &
	&

15440	FNEND &

15450	! &
	!	F N P R T % ( S T R I N G $ , V A L U E % ) &
	! &
	! &

15460	DEF* FNPRT%(VALUE$,VALUE%) &
		! &
		! PRINT A STRING FOLLOWED BY THE OCTAL AND DECIMAL VALUES &
		! &

15470	PRINT VALUE$;TAB(16%);FNO$(VALUE%);" (";NUM1$(VALUE%);".)" &
	\ FNPRT%=0% &

15490	FNEND &

15500	! &
	! &
	!	F U N C T I O N S   F O R   . G S D   P R O C E S S I N G &
	! &

15510	! &
	! &
	!	F N G S D . E N T R Y % ( T Y P E % ) &
	! &

15520	DEF* FNGSD.ENTRY%(TYPE%) &
		! &
		! COMPILE A .GSD ENTRY &
		! &
		! RETURN: -1 IF ENTRY COMPILED, 0 IF DONE OR ERROR &
		! &
		! ON A SUCCESSFUL RETURN, THE .GSD INFORMATION IS &
		! STORED IN G.NAME1%, G.NAME2%, G.FLAG%, AND G.VALUE% &
		! NOTE:  THIS ROUTINE ONLY RETURNS GLOBAL SYMBOLS &
		! (TYPE = 4) IF TYPE<>0% AND ALL OTHERS ARE IGNORED. &
		! IF TYPE%=0% THEN ALL TYPES ARE RETURNED. &
		! &

15530	FNGSD.ENTRY%=0%\ Q%=FNITEM% &
	\ GOTO 15550 UNLESS Q% &
	\ GOTO 15580 IF Q% <> -2% &
	\ GOTO 15530 IF (ITEM% AND 255%) = 1% &
	\ GOTO 15590 IF (ITEM% AND 255%) = 2% &
	\ GOTO 15580 IF (ITEM% AND 255%) <> 5%	! ERROR IF NOT AN ISD &
	\	ENTRY%=NWORDS%+1%	! SKIP TO THE NEXT RECORD &
	\	GOTO 15530		! NOW, TRY AGAIN &
		! GET THE FIRST WORD AND CHECK RETURN CODE: &
		!  0	COMPILE THE DATUM &
		! -2	EXIT IF RECORD TYPE =2, GET DATA IF TYPE = 1 &
		! -1,-3	ERRORS, PRINT MESSAGE AND EXIT &
	&

15550	G.NAME1%=ITEM% &
	\ GOTO 15580 IF FNITEM%\ G.NAME2%=ITEM% &
	\ GOTO 15580 IF FNITEM%\ G.FLAG%=ITEM% &
	\ GOTO 15580 IF FNITEM%\ G.VALUE%=ITEM% &
		! COMPILE THE ENTRIES &

15560	GOTO 15530 IF (SWAP%(G.FLAG%) AND 255%) <> TYPE% IF TYPE% &
	\ FNGSD.ENTRY%=-1%\ GOTO 15590 &
		! IGNORE THIS ONE IF IT'S NOT A REAL SYMBOL &

15580	PRINT "?Error getting a .GSD entry. Return code = ";Q%; &
			", Return value = ";ITEM% &

15590	FNEND &

15600	! &
	! &
	!	F N I T E M % &
	! &

15610	DEF* FNITEM% &
		! &
		! GET THE NEXT WORD FROM GSDFILE%. &
		! THE DATUM IS RETURNED IN ITEM% &
		! FNITEM% RETURNS AN ERROR CODE: &
		!  0	NORMAL DATUM &
		! -1	END OF FILE ON INPUT DEVICE &
		! -2	RECORD HEADER READ, ITEM% HAS RECORD CODE &
		! -3	CHECKSUM ERROR ON FORMATTED BINARY READ &
		! &

15620	IF ENTRY% < 1% OR ENTRY% > NWORDS% THEN &
		GOSUB 15700 IF F.RTYP% = FB% &
	\	GOSUB 15800 IF F.RTYP% = VAR% &
	\	ITEM%=WORD%(1%)\ ENTRY%=2% &
	\	FNITEM%=-2% &
	\	FNITEM%=-3% IF F.RTYP% = FB% AND (CSUM% AND 255%) <> 0% &
	\	FNITEM%=-1% IF NWORDS%<1% OR FNEOF% &
	\	GOTO 15690 &
		! IF WE HAVE NOTHING LEFT IN THE &
		! RECORD, GET THE NEXT RECORD &
		! AND RETURN -2 (RECORD START) &
		! OR RETURN -3 ON CHECKSUM ERROR &
		! RETURN -1 ON END OF FILE &

15630	ITEM%=WORD%(ENTRY%)\ ENTRY%=ENTRY%+1% &
	\ FNITEM%=0% &
		! JUST GET THE NEXT WORD &

15690	FNEND &

15700	! &
	! &
	!	G E T   A   F B   R E C O R D &
	! &

15710	CSUM%=0%\ NEXTBYTE%=FNFBGETBYTE%\ RETURN IF FNEOF% &
	\ GOTO 15710 UNLESS NEXTBYTE% &
	\ GOTO 15790 IF NEXTBYTE% <> 1% &
	\ GOTO 15790 IF FNFBGETBYTE% &
	\ NEXTBYTE%=FNFBGETBYTE% &
	\ RECLEN%=NEXTBYTE%+SWAP%(FNFBGETBYTE%)-4% &
	\ IF RECLEN% > 512% THEN &
		PRINT "?Long formatted binary record" &
	\	GOTO 15790 &
		! READ THE HEADER AND GHECK FOR 0/1/0 FORMAT &
		! GET THE NUMBER OF DATA BYTES IN THE HEADER &

15720	GOTO 15790 IF RECLEN% AND 1% &
	\ NWORDS% = RECLEN%/2% &
	\ WORD%(WORD%)=FNFBGETBYTE%+SWAP%(FNFBGETBYTE%) FOR WORD%=1% TO NWORDS% &
	\ NEXTBYTE%=FNFBGETBYTE% &
		! MAKE SURE WE HAVE AN EVEN NUMBER OF BYTES &
		! GET THE RECORD AND THROW AWAY CHECKSUM &

15730	RETURN &

15790	PRINT "?Illegal formatted binary record" &
	\ ERROR%=-1% &
	\ RETURN &
		! PRINT A TROUBLE MESSAGE &

15800	! &
	! &
	!	G E T    A   V A R I A B L E   R E C O R D &
	! &

15810	GOSUB 17600\ RETURN IF FNEOF% &
		! GET A RECORD IF WE MUST &

15820	FIELD #GSDFILE%, INBYTE% AS JUNK$, 2% AS WORD$ &
	\ RECLEN%=SWAP%(CVT$%(WORD$)) &
	\ IF RECLEN%=-1% THEN &
		INBYTE%=512%\ GOTO 15810 &
		! GET THE LENGTH OF THE NEXT RECORD, &
		! LENGTH = -1 MEANS "NEXT BLOCK" &

15830	GOTO 15890 IF RECLEN% > 512% &
	\ INBYTE%=INBYTE%+2% &
	\ IF RECLEN% <= (512%-INBYTE%) THEN &
		FIELD #GSDFILE%, INBYTE% AS JUNK$,RECLEN% AS INPUT.RECORD$ &
	\	FIELD #NULL%, RECLEN% AS JUNK$ &
	\	LSET JUNK$=INPUT.RECORD$ &
	\	INBYTE%=INBYTE%+RECLEN% &
	\	GOTO 15850 &
		! IF THE RECORD IS COMPLETELY CONTAINED IN &
		! THIS BLOCK, JUST EXTRACT IT &
		! BUMP BYTE OFFSET TO NEXT RECORD &

15840	FIELD #GSDFILE%, INBYTE% AS JUNK$, 512%-INBYTE% AS PARTIAL$ &
	\ FIELD #NULL%, LEN(PARTIAL$) AS JUNK$ &
	\ LSET JUNK$=PARTIAL$ &
	\ INBYTE%=RECLEN%-(512%-INBYTE%) &
	\ GOSUB 17620\ FIELD #GSDFILE%, INBYTE% AS PARTIAL$ &
	\ FIELD #NULL%, LEN(JUNK$) AS JUNK$, INBYTE% AS Q$ &
	\ LSET Q$=PARTIAL$ &
		! GET THE FIRST PART OF THE RECORD FROM THIS BLOCK &
		! AND GET THE SECOND PART FROM THE NEXT BLOCK &

15850	INBYTE%=(INBYTE%+1%) AND -2% &
	\ GOTO 15890 IF RECLEN% AND 1% &
	\ NWORDS%=RECLEN%/2%\ Q%=0% &
	\ FOR WORD%=1% TO NWORDS% &
	\   FIELD #NULL%, Q% AS JUNK$, 2% AS JUNK$ &
	\   WORD%(WORD%)=SWAP%(CVT$%(JUNK$)) &
	\   Q%=Q%+2% &
	\ NEXT WORD% &
		! ROUND BYTE OFFSET TO NEXT WORD BOUNDARY &
		! CHECK FOR ODD RECORD AND CONVERT &
		! TO BINARY &

15860	RETURN &

15890	PRINT "?Illegal variable-length record" &
	\ ERROR%=-1% &
	\ RETURN &

15900	! &
	! &
	!	F N W O R D % ( A D D R E S S % ) &
	! &

15910	DEF* FNWORD%(A%) &
		! &
		! FNWORD%(A%)		GET A WORD FROM THE TASK &
		!			FILE AT WORD ADDRESS &
		!			(A%+TSK.OFFSET%) &
		! &

15920	A%=A%+TSK.OFFSET% &
	\ B%=(SWAP%(A%) AND 255%) + 1% &
	\ IF TSK.BLOCK% <> B% THEN &
		PRINT "?Addressing outside of task limits" &
			IF B% <= 0% OR B% > TSK.FILE.SIZE% &
	\	GET #TSKFILE%, RECORD B% &
	\	TSK.BLOCK%=B% &
		! MAKE SURE WE HAVE THE RIGHT BLOCK &

15930	FIELD #TSKFILE%, (A% AND 255%)*2% AS JUNK$, 2% AS JUNK$ &
	\ FNWORD%=SWAP%(CVT$%(JUNK$)) &
		! AND GET THE ACTUAL DATUM &

15990	FNEND &

16000	! &
	! &
	!	O U T P U T   F U N C T I O N S &
	! &
	! &
	! GLOBALS NEEDED BY THIS PACKAGE: &
	! OUT.BASE%		THE FIRST BLOCK OUTPUT BY FNSET% &
	!			MAY BE CHANGED AS DESIRED &
	! OUTPUT.NEEDED%	FLAG FOR OUTPUT ROUTINES. &
	!			INITIALLY SET TO 0 &
	! CURRENT.BLOCK%	WHAT IS IN MEMORY NOW &
	!			INITIALLY SET TO 0. &
	! HIGHEST.BLOCK%	THE HIGHEST BLOCK WRITTEN. &
	!			INITIALLY SET TO 0. &
	! &

16010	! &
	! &
	!	F N S E T % ( P O S I T I O N % , V A L U E % ) &
	! &

16020	DEF* FNSET%(POSITION%,VALUE%) &
		! &
		! OUTPUT ONE WORD TO THE FILE OPEN ON CHANNEL 2 &
		! THIS FUNCTION SIMULATES VIRTUAL MEMORY PROCESSING &
		! EXCEPT THAT A BASE BLOCK (THE POSITION OF ENTRY 0) &
		! MAY BE SPECIFIED. &
		! &
		! POSITION%	THE INDEX OF THE WORD TO CHANGE &
		! VALUE%	THE VALUE TO OUTPUT &
		! &

16030	Q%=SWAP%(POSITION%) AND 255% &
	\ FNSET%,Q%=FNGET.BLOCK%(OUT.BASE%+Q%) &
	\ IF Q% = 0% THEN &
		FIELD #SILFILE%, (POSITION% AND 255%)*2% AS Q$, 2% AS Q$ &
	\	LSET Q$=CVT%$(SWAP%(VALUE%)) &
	\	OUTPUT.NEEDED%=-1% &
		! MAKE SURE WE HAVE THE RIGHT BLOCK &
		! THEN -- ASSUMING NO ERRORS -- GET THE &
		! BUFFER PART TO CHANGE AND DO IT.  THEN, &
		! OUTPUT THE VALUE AND SET THE "STUFF IT" FLAG &

16040	FNEND &

16050	DEF* FNMODULO%(VVALUE,MODULO%)=VVALUE-(INT(VVALUE/MODULO%)*MODULO%) &

16100	! &
	! &
	!	F N G E T . B L O C K % ( W H I C H % ) &
	! &

16110	DEF* FNGET.BLOCK%(WHICH%) &
		! &
		! MAKE SURE WE HAVE BLOCK WHICH% IN &
		! MEMORY.  FORCE OUT THE CURRENT IF NECESSARY &
		! &

16120	FNGET.BLOCK%=0% &
	\ IF CURRENT.BLOCK% <> WHICH% THEN &
		FNGET.BLOCK%,Q%=FNFORCE.OUT% &
	\ IF Q% = 0% THEN &
		ON ERROR GOTO 16150 &
	\	GET #SILFILE%, RECORD WHICH% IF WHICH% < HIGHEST.BLOCK% &
	\	CURRENT.BLOCK%=WHICH% &
	\	HIGHEST.BLOCK%=WHICH% IF WHICH% > HIGHEST.BLOCK% &

16130	GOTO 16180 &
		! GOTCHA &

16150	GOTO 19000 IF ERL <> 16120 &
	\ T$=FNERR$(ERR) &
	\ PRINT "Error getting block";WHICH%;" -- ";T$ &
	\ FNGET.BLOCK%=ERR\ RESUME 16180 &
		! WE HAVE A PROBLEM &

16180	ON ERROR GOTO 19000 &

16190	FNEND &

16200	! &
	! &
	!	F N F O R C E . O U T % &
	! &

16210	DEF* FNFORCE.OUT% &
		! &
		! OUTPUT THE CURRENT BLOCK IF NEEDED &
		! &

16220	IF OUTPUT.NEEDED% THEN &
		ON ERROR GOTO 16250 &
	\	PUT #SILFILE%, RECORD CURRENT.BLOCK% &
		! OUTPUT THE CURRENT BLOCK IF NECESSARY &

16230	OUTPUT.NEEDED%,FNFORCE.OUT%=0% &
	\ CURRENT.BLOCK%=-1% &
	\ GOTO 16280 &
		! NO ERRORS, NO OUTPUT NEEDED, AND &
		! THERE IS NOTHING IN CORE NOW &

16250	GOTO 19000 IF ERL <> 16220 &
	\ T$=FNERR$(ERR) &
	\ PRINT "?Error putting block";CURRENT.BLOCK%;" -- ";T$ &
	\ FNFORCE.OUT%=ERR\ RESUME 16280 &
		! SORRY ABOUT THAT &

16280	ON ERROR GOTO 19000 &

16290	FNEND &

17000	! &
	! &
	!	G S D   I N P U T   F U N C T I O N S &
	! &

17100	! &
	! &
	!	F N F B G E T B Y T E % &
	! &

17110	DEF* FNFBGETBYTE% &
		! &
		! FNFBGETBYTE%	GET A BYTE FROM THE GSD FILE &
		! &

17120	GOSUB 17600 &
	\ FIELD #GSDFILE%, INBYTE% AS JUNK$, 1% AS JUNK$ &
	\ INBYTE%=INBYTE%+1%\ FNFBGETBYTE%=ASCII(JUNK$) &
	\ CSUM%=CSUM%+ASCII(JUNK$) &
		! GET A BLOCK IF NECESSARY, &
		! THEN EXTRACT THE DATUM AND UPDATE THE POINTER &
		! AND UPDATE THE FORMATED BINARY CHECKSUM &

17130	FNEND &

17200	! &
	! &
	!	E N D - F I L E   T E S T E R &
	! &

17210	DEF* FNEOF% &
		! &
		! FNEOF%	CHECK FOR END OF FILE &
		! &

17220	IF F.RTYP%=FB% THEN &
	IF ERROR% THEN &
		FNEOF%=-1% &
	ELSE	FNEOF% = 0% &

17320	IF F.RTYP%=VAR% THEN &
	IF ERROR% <> 0% THEN &
		FNEOF%=-1% &
	ELSE	IF INREC% < F.EFBK% &
		OR (INREC%=F.EFBK% AND INBYTE% < F.FFBY%) THEN &
			FNEOF%=0% &
		ELSE	FNEOF%=-1% &

17330	FNEND &

17500	! &
	! &
	!	I N I T I A L I Z E   G S D   F I L E &
	! &

17510	INREC%, ERROR%=0%\ INBYTE%=512% &
	\ GOSUB 17600 &
		! PRESET VARIABLES AND GET THE FIRST RECORD &

17520	RETURN &

17600	! &
	! &
	!	R E A D   A   B L O C K   I F   N E C E S S A R Y &
	! &

17610	RETURN IF INBYTE% < 512% &
	\ INBYTE%=0% &
		! RETURN IF WE'RE STILL WITHIN THE BLOCK, &
		! ELSE SETUP THE INPUT COUNTER &

17620	INREC%=INREC%+1% &
	\ ON ERROR GOTO 17650\ GET #GSDFILE% &
	\ GOTO 17680 &
		! WE MUST INPUT (GOSUB 117620) &

17650	ERROR%=ERR &
	\ IF ERROR% = 11% THEN &
		RESUME 17680 &
	  ELSE T$=FNERR$(ERROR%) &
	\	PRINT "?Error getting from ";STBFILE$;" -- ";T$ &
	\	RESUME 17680 &

17680	ON ERROR GOTO 19000 &

17690	RETURN &

18100	! &
	! &
	!	A N S W E R   Y E S   O R   N O &
	! &

18110	DEF* FNYES%(PROMPT$) &
		! &
		! PROMPT AND GET A YES/NO ANSWER &
		! &

18120	PRINT IF CCPOS(0%) &
	\ PRINT PROMPT$; " (Yes/No) <Yes>"; &
	\ INPUT LINE Q$\ PRINT IF CCPOS(0%) &
	\ Q$=CVT$$(Q$,-2%)\ Q$="Y" IF Q$ = "" &
	\ IF Q$ = LEFT("YES",LEN(Q$)) THEN &
		FNYES% = -1% &
	  ELSE	IF Q$ = LEFT("NO",LEN(Q$)) THEN &
			FNYES% = 0% &
		ELSE	PRINT "Please answer yes or no" &
	\		GOTO 18120 &
		! ALL WE WANT ARE THE FACTS &

18130	FNEND &

18200	! &
	! &
	!	S A V E   T K B   C O M M A N D S &
	! &

18210	DEF* FNCMDLINE$(CURRENT$,CMD$) &
		! &
		! RETURN CURRENT$ IF CMDLINE$ <> CMD$ &
		! OTHERWISE, RETURN CMDLINE$ AND SET CMDLINE$ TO "//" &
		! PRINT AN ERROR MESSAGE IF CMD$ APPEARS TWICE &
		! &

18220	FNCMDLINE$=CURRENT$ &
	\ IF LEFT(CVT$$(CMDLINE$,-2%),LEN(CMD$)) = CMD$ THEN &
		IF CURRENT$ <> "" THEN &
		PRINT '%Multiple "';CMD$;'": "';CURRENT$;'", "';CMDLINE$;'"' &
	  ELSE	FNCMDLINE$=CMDLINE$\ CMDLINE$="//" &
		! SUPER-PROGRAMMER STRIKES AGAIN &

18230	FNEND &

18400	DEF* FNUNSIGNED(X%)=32768.+(X% EQV 32767%) &
		! RETURN THE UNSIGNED MAGNITUDE OF AN INTEGER VALUE &

19000	! &
	! &
	!	F A T A L   E R R O R   T R A P &
	! &

19010	IF ERL = 1420 THEN &
		T$=FNERR$(ERR) &
	\	PRINT '?Garbage when converting "';Q$;'" in "';CMDLINE$;'" -- ';T$ &
	\	RESUME 1900 &
		! HERE ON REAL TROUBLE &

19015	RESUME 4255 IF ERL=4250 &

19020	E0%=ERR\ E1%=ERL\ RESUME 19030 &

19030	RESUME 19090 IF E0%=11% &
	\ PRINT "?MAKSIL	";VERSION$;" Fatal error";E0%;" at line";E1% &
	\ T$=FNERR$(E0%) &
	\ PRINT ,,T$
19090	GOTO 32767 &

32767	END
