2!		PROGRAM		: PRELIN.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) 1981, 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.3-03	03-Mar-86	Change C81ODL.TSK from $ to C81$ &
	! V9.4-02	23-Feb-87	Add /I_D_SPACE qualifier &
    	! V9.7-04	19-Jan-89	Add RMS Supervisor Mode support &
    	! V10.0-E	02-Nov-89	Add /CC and /STACK= &
	! &

100	! &
	! &
	! &
	!	P R O G R A M   D E S C R I P T I O N &
	! &
	! &
	! &
	!     The PRELIN program implements the DCL LINK command &
	! by converting a LINK command line into the corresponding &
	! TKB command files. The command file (CMD) contains the names &
	! of output task file (.TSK; and .MAP if requested), the input &
	! overlay file, the appropriate task builder options, and &
	! the resident libraries required. PRELIN will create the &
	! appropriate overlay descriptor file (ODL) for the simple &
	! case of linking one or more files with no overlays, or when &
	! specifying a large overlay structure.  For each language, &
	! specific library and ODL files are included.  Both of these &
	! files are placed temporarily in the user account; &
	! CMD0nn.TMP, and ODL0nn.TMP where nn is the current job &
	! number.  A user could rename and modify these files if desired. &
	! &
	! &
	! The DCL Keyboard Monitor chains to PRELIN at line 30000. &
	! PRELIN  must be kept in _SY:[1,2] with a protection code of <232>. &
	! DCL passes PRELIN a valid command line in core common. &
	! The command line contains no extraneous spaces and no tabs. &
	! All keywords are three letters long. &
	! The command line has the form: &
	!	LINK/<qualifiers> [executable][,map]=input[,...] &
	! &
	! The qualifiers are: &
	!	/CC		'C' program &
	!	/DIBOL		DIBOL program &
	!	/DMS		DIBOL/DMS program &
	!	/ID		I&D Space program &
	!	/BP2		BASIC-PLUS-2 program &
	!	/C81		COBOL-81 program &
	!	/DES		The parameter is a description file &
	!			(TKB command file) &
	!	/F77		FORTRAN-77 program &
	!	/RSX11		RSX-11-based MACRO program &
	!	/FMS		Program needs FMS &
	!	/STR		PRELIN will prompt user for overlay &
	!			structure. The input files passed in &
	!			core common are the files to include &
	!			in the ROOT of the task. &
	!	/RMS		Defines RMS usage &
	! &
	! A line in core common cannot exceed 127 characters. &
	! The  KBM  verifies that a INFILE.OBJ does exist, and &
	! all of the qualifiers are  legal.  If /MAP is specified, &
	! both a map and executable file are created.  When /NOEXE is &
	! requested, /MAP must be present or an error will be generated. &
	! &
	!     PRELIN submits the created CMD file to the task builder &
	! which produces  an executable task file (TSK). &
	! &
	! COBOL will not allow the /STRUCTURE qualifier, and C81ODL.TSK must &
	! be installed in $ to get a COBOL executable task.   Also for &
	! COBOL,  ATPK must be located in the $ account.   C81ODL needs the &
	! .SKL file created by the compiler to create the CMD and ODL file. &
	! &
	! &

110	! &
	! &
	! &
	!    The following is the file LB:BP2.LNK which PRELIN uses to create &
	! the CMD and ODL files for BASIC-PLUS-2.  Each of the lines that &
	! begin with a dollar sign ($) are commands to be processed by the &
	! appropriate PRELIN subroutine. The lines without ($) are lines that &
	! go directly into the CMD or ODL files created by PRELIN (depending &
	! on the order that they occur in the .LNK file.) &
	! &
	! $; BP2.LNK &
	! $; &
	! $; Skeleton for DCL LINK command &
	! $; for BASIC-PLUS-2 T2.3 BL 2.3-00 &
	! $; under RSTS/E V9.0 &
	! $; &
	! $;		      Copyright (C) 1985, 1991 by &
	! $IF DEBUG &
	!  $RESLIB FMS FDVRDB &
	! $ELSE &
	!  $RESLIB FMS FDVLIB &
	! $ENDIF &
	! $RESLIB OTS BP2SML/NOCLUSTER &
	! $RESLIB RMS RMSRES &
	! $ &
	! $OPTION &
	! UNITS	=12 &
	! ASG	=SY:5:6:7:8:9:10:11:12 &
	! EXTTSK	=512 &
	! $ &
	! $ODL &
	! @LB:BP2IC7.ODL &
	! $IF RMS &
	!  $IF RMS:RESIDENT &
	! @LB:RMSRLX.ODL &
	!  $ELSE ;RMS:NORESIDENT &
	! @LB:RMS11X.ODL &
	!  $ENDIF &
	! $ELSE NORMS &
	! 	.NAME	RMSROT &
	! 	.NAME	RMSALL &
	! $ENDIF &
	! $ &
	! $IF NOFMS &
	! ROOT$$:	.FCTR	BASIC2-RMSROT &
	! LBR$$:	.FCTR	LB:BP2OTS.OLB/LB &
	! $ELSE ;FMS &
	!  $IF FMS:RESIDENT &
	! FMS$$:	.FCTR	LB:HLLDFN.OBJ-LB:HLLBP2.OBJ-LB:FDVDRS.OBJ &
	! ROOT$$:	.FCTR	BASIC2-RMSROT-FMS$$ &
	! LBR$$:	.FCTR	LB:BP2OTS.OLB/LB &
	!  $ELSE ;FMS:NORESIDENT &
	! FMS$$:	.FCTR	LB:HLLDFN.OBJ-LB:HLLBP2.OBJ &
	! ROOT$$:	.FCTR	BASIC2-RMSROT-FMS$$ &
	!   $IF DEBUG &
	! LBR$$:	.FCTR	LB:BP2OTS.OLB/LB-LB:FDVDBG.OLB/LB &
	!   $ELSE &
	! LBR$$:	.FCTR	LB:BP2OTS.OLB/LB-LB:FDVLIB.OLB/LB &
	!   $ENDIF &
	!  $ENDIF &
	! $ENDIF &
	! 	.ROOT	A0$,RMSALL &
	! &
	! &
	! The following is an example of a CMD and ODL file creatd by &
	! PRELIN. This is to show what lines are taken out of the .LNK &
	! file and used in the CMD and ODL file. &
	! The LINK command was LINK/BP2 BP2TST.  RMSRES and BP2SML resident &
	! libraries were present on the system. &
	! &
	! ;  TKB .CMD file created by DCL LINK  V10.1-A	14-Sep-82   10:17 AM &
	! SY:[9,254]BP2TST/FP,=ODL008.TMP/MP &
	! UNITS =12 &
	! ASG   =SY:5:6:7:8:9:10:11:12 &
	! EXTTSK=512 &
	! LIBR=RMSRES:RO &
	! LIBR=BP2SML:RO &
	! // &
	! &
	! ; TKB .ODL file created by DCL LINK  V10.1-A	14-Sep-82   10:17 AM &
	! @LB:BP2IC7.ODL &
	! @LB:RMSRLX.ODL &
	! ROOT$$:.FCTR	BASIC2-RMSROT &
	! LBR$$: .FCTR	LB:BP2OTS.OLB/LB &
	! 	 .ROOT	A0$,RMSALL &
	! A0$:	 .FCTR	SY:[9,254]BP2TST-ROOT$$-LBR$$ &
	! .END &

300	! &
	! &
	! &
	!	I / O    C H A N N E L S &
	! &
	! &
	! &
	!     CHANNEL #		USED FOR &
	! &
	!	1	USER INPUT KB: &
	!	2	INPUT FILE FOR EDITING THE TKB CMD FILE PRODUCED &
	!		BY C81ODL &
	!	3	CMD FILE FOR OUTPUT &
	!	4	OUTPUT FILE FOR BUILDING COBOL ODL AND CMD FILES &
	!	5	*.LNK FILE, OPEN READ ONLY. &
	!		THE *.LNK FILES MUST BE PLACED ON LB: &
	!	6	LB:FDVLIB.TSK - TO SEE IF IT CAN CLUSTER. &
	!	7	ODL FILE FOR OUTPUT &

400	! &
	! &
	!	V A R I A B L E   D E F I N I T I O N S &
	! &
	! &
	!     VARIABLE NAME	DEFINITION &
	! &
	!	AUTO.BEG%	POSITION OF AUTOLOAD INDICATOR IN ODL LINE &
	!	AUTO.LABEL$	LABEL GENERATED FOR AUTOLOAD INDICATOR &
	! 	AUTOLOAD$	"-*(label)" PART OF THE ODL LINE &
	!	BASE.ADDRESS%	BASE ADDRESS OF LIBRARY &
	!	BLD.STR$	BUILD THE STRING OF FILESPECS; &
	!			OR ENTIRE LINE FOR C81ODL &
	!			OR BUILD STRING OF PSECTS FOR ROOT &
	!	C%		CHARACTER OF PSECT NAME &
	!	C81CMD$		LINE FROM C81ODL CMD OR ODL FILE &
	!	C81ERR%		TRUE% IF ERROR FROM COBOL'S C81ODL UTILITY &
	!	CHILD%		LOOP COUNTER FOR PROCESSING FILES (CHILDREN) &
	!	CHILD.CNT%(I%)	NUMBER OF CHILDREN OF OVERLAY AT LEVEL I% &
	!	CHR.6$		CHR$(6%) &
	!	CLUSTER.LST$	LIST OF FILES FOR TKB TO CLUSTER &
	!	CMD$		USED IN FNC81CMD$, COMMAND TO BE TRANSLATED &
	!	CMD.FIL$	TEMP NAME + JOB # FOR CMD FILE &
	!	COLON.POS%	POSITION OF THE : ON THE LIBR=libnam:RO LINE &
	!	COMMAND$	COMMAND WORD FROM .LNK FILE (LIKE $ELSE) &
	!	COND%		CONDITION OF $IF STATEMENT IN .LNK FILE &
	!	CRLF$		CARRIAGE RETURN, LINE FEED CONSTANT. &
	!	CRNT.FCTR$	BUILDING CURRENT .FCTR LINE < 78 CHARS &
	!	DBG%		SET = TRUE% TO HALT CHAIN TO TKB, &
	!			FALSE% OTHERWISE &
	!	DEBUG.QUAL%	TRUE% IF USER SPECIFIED /DEBUG &
	!	DELIM$		DELIMITER SEPARATING FILESPECS &
	!	DELIM%		LOCATION OF DELIMITER SEPARATING FILESPECS &
	!	DESC.QUAL%	TRUE% IF USER SPECIFIED /DESCRIPTION. &
	!	DEV$		DEVICE SPECIFIED &
	!	E%		CODE FOR RSTS/E ERROR MESSAGE &
	!	ENTRY.TYP%	DIFFERENT ENTRY POINTS INTO THE PROGRAM &
	!	EXCLAIM%	SEARCHING COMMAND LINE FOR EXCLAMATION POINT &
	!	EXT.CTR%	EXTENSION COUNTER FOR LABELS &
	!	EXT.LBL$	EXTENSION LABEL FOR .FCTR LINE > 78 CHARS &
	!	FALSE%		CONSTANT LOGICAL FALSE = 0% &
	!	FCTR$		LIST OF FILE .FCTR OR AUTOLOAD .FCTR &
	!			SEPARATED BY "," OR "-" &
	!	FCTR.CMD$	STRING OF ":	.FCTR	"  FOR ODL FILE &
	!	FIL$		FILE EXTRACTED FROM C81ODL COMMAND LINE &
	!	FILCOUNT%	1%,2% OR 3% INDICATES PARSING TSKFIL,MAPFIL, &
	!			OR STBFIL IN LOOP. &
	!	FILE$		CURRENT FILESPEC TO PROCESS &
	!	FILE.LABEL$	LABEL FOR FILE .FCTR &
	!	FILELST$	LIST OF FILESPECS AND PSECTS SEPARATED BY "," &
	!			AND POSSIBLY AN AUTOLOAD INDICATOR &
	!	FILESPEC$	STRING OF A FILE SPECIFICATION &
	!	FILESPEC.BEG%	POSITION OF BEGINNING OF A FILESPEC &
	!	FILESPEC.END%	POSITION OF END OF A FILESPEC &
	!	FILESPEC.LEN%	LENGTH OF THE FILESPEC &
	!	FIRST.CHILD%	LABEL NUMB OF FIRST CHILD OF CURRENT OVERLAY &
	!	FMS.CLUSTER%	TRUE% IF FMS RESIDENT LIBRARY EXISTS AND IS &
	!			BUILT TO CLUSTER (AT APR 6). &
	!	FMS.QUAL%	TRUE% IF USER SPECIFIED /FMS QUALIFIER. &
	!	FMS.RESLIB$	NAME OF FMS RESIDENT LIBRARY;  NULL IF &
	!			LANGUAGE DOES NOT ALLOW FMS. &
	!	GOT.ERR%	TRUE% IF FATAL ERROR HAS OCCURRED.  PROGRAM &
	!			WILL EXIT WITHOUT TASK BUILD. &
	!	I%		LOOP COUNTER &
	!	ID%		TRUE% IF /ID SPECIFIED &
	!	IDENT.STG$	IDENTIFICATION STRING &
	!	IN.COB$		LINE FROM C81ODL CMD AND LOG FILE &
	!	IN.LNK$		LINE FROM LANGUAGE.LNK FILE TO PROCESS &
	!	INP$		INPUT FROM DCL PRE-PROCESSOR CORE COMMOM &
	!	JOB.NUM$	JOB NUMBER &
	!	JUNK$		JUNK &
	!	JUNK%		JUNK &
	!	LABEL$		LABEL FOR AN ODL LINE &
	!	LANG$		THE LANGUAGE SPECIFIED &
	!	LANGCNT%	NUMBER OF ACCEPTABLE LANGUAGES &
	!	LAST.CHILD%	LABEL NUMB OF LAST CHILD OF CURRENT OVERLAY &
	!	LAST.CHR$	OF OVERLAY INPUT, LOOKING FOR '+' OR ',' &
	!	LAST.DELIM%	POSITION OF LAST DELIMITER PARSED ON LINE &
	!	LBLNUM%		FOR GENERATING UNIQUE NUMERIC LABEL VALUES &
	!	LEVEL%		CURRENT OVERLAY LEVEL, WHERE 0% MEANS ROOT &
	!	LIBBLK%		ADDRESS OF RESIDENT LIBR DESCRIPTOR BLOCK &
	!			IN MONITOR &
	!	LIBNAME$	NAME OF LIBRARY &
	!	LIBNAME1%	FIRST WORD OF RESIDENT LIBRARY NAME &
	!	LIBNAME2%	SECOND WORD OF RESIDENT LIBRARY NAME &
	!	LIBTYPE$	"RMS", "FMS", OR "OTS" &
	!	M$		SET UP SYS() STRING TO LOOK UP FILE &
	!	MAPFIL$		FILESPEC OF MAP FILE THAT TKB WILL GENERATE &
	!	MAX.LEVEL%	MAXIMUM ALLOWABLE LEVELS &
	!	MAXODL.LEN%	MAXIMUM LENGTH OF ODL LINE = 78 CHARS &
	!	MSG$		AN ERROR OR WARNING MESSAGE &
	!	NEW.FILELST$	STARTING NEW LIST OF FILES AND LABELS &
	!			IF .FCTR LINE > 78 CHARS &
	!	NL$		CONSTANT NULL STRING &
	!	NOID%		TRUE% IF /NOID SPECIFIED &
	!	NULFIL%		FLAG INDICATING THAT WE ARE SUBSTITUTING A &
	!			NULL FILENAME &
	!	ODL$		LOCAL TO FNC81CMD$, NAME OF ODL0nn.TMP FILE &
	!	ODL.FIL$	TEMP NAME + JOB # FOR ODL FILE &
	!	ODLNAM$		FILESPEC OF ODL FILE FOR TKB TO GENERATE. &
	!	OTS.CLUSTER%	TRUE% IF OTS RESIDENT LIBRARY EXISTS AND &
	!			CAN CLUSTER. &
	!	OTS.RESLIB$	NAME OF OTS RESIDENT LIBRARY; NULL IF &
	!			LANGUAGE HAS NO OTS LIBRARY. &
	!	OTS.2.RESLIB$	NAME OF SECONDARY OTS RESIDENT LIBRARY; NULL &
	!			IF LANGUAGE HAS NO SECONDARY OTS LIBRARY. &
	!	OURPPN$		THE PPN WE ARE RUNNING UNDER &
	!	OUTFIL%		POSITION OF SPACE IN OUTPUT STRING &
	!	OUTFIL$		OUTPUT FILE(S) SPECIFIED; TSK AND MAP &
	!	OUTPUT.CHANNEL%	THE CHANNEL NUMBER THAT WE'RE CURRENTLY &
	!			WRITING TO - EITHER THE ODL OR THE CMD FILE. &
	!	OVERLAY$	USER INPUT OF OVERLAY FILES &
	!	PARM$		PARAMETER OF COMMAND IN .LNK FILE &
	!	PLUS%		TRUE% IF USER'S LINE ENDS WITH PLUS SIGN - &
	!			WE GO TO DEEPER LEVEL OF OVERLAYS. &
	!	PPN$		PPN FROM INPUT FILE SPECIFIED &
	!	PRESENT%	FLAG INDICATING THE PRESENCE OF A LIBRARY &
	!	PRG.NAM$	PROGRAM NAME - PRELIN &
	!	PRG.SPEC$	FULL FILE SPECIFICATION FOR PRELIN &
	!	PRIV.OFF$	TURN PRIVILEGES OFF &
	!	PRIV.ON$	TURN PRIVILEGE ON &
	!	PROMPT$		PROMPTING USER FOR INPUT &
	!	PSECT$		A PSECT NAME &
	!	PSECT.BEG%	POSITION OF BEGINNING OF PSECT NAME &
	!	PSECT.END%	POSITION OF END OF PSECT NAME &
	!	PSECT.LEN%	LENGTH OF PSECT NAME &
	!	PSECTLST$	LIST OF PSECTS USER WANTS TO FORCE TO ROOT &
	!	QUALS$		QUALIFIERS FROM USER'S COMMAND LINE. &
	!	RMS.QUAL%	TRUE% IF THE USER SPECIFIED /RMS, OR IF &
	!			/RMS IS THE DEFAULT. &
	!	RMS.RESLIB$	NAME OF RMS RESIDENT LIBRARY. &
	!	RTFIL$		INPUT ROOT FILES SPECIFIED &
	!	RTFIL%		POSITION OF "=" IN ROOT FILE STRING &
	!	RTSLST%		ADDRESS OF POINTER TO RUN TIME SYSTEM LIST &
	!	S1%		FLAG WORD 2 FROM FSS &
	!	SAM.QUAL%	TRUE% IF USER SPECIFIED /SAM (SORT, MERGE) &
	!	SAM.RESLIB$	SORT AND MERGE RESIDENT LIBRARY NAME &
	!	SEPAR$		SEPARATING CHARACTER (- OR ,) FOR .FCTR LINES &
	!			"-" FOR FILE .FCTR;  "," FOR AUTOLOAD .FCTR &
	!	SKIP%		TRUE% SKIP LINE IN LANG.LNK FILE, ELSE FALSE% &
	!	SKL.FILES$	LIST OF SKL FILES TO INPUT TO TKB &
	!	SPACECHR$	CONSTANT CHR$(32%) &
	!	STACK.SIZE%	Size of stack if /STACK specified, else zero &
	!	STBFIL$		FILESPEC OF STB FILE FOR TKB TO GENERATE. &
	!	STR%		TRUE% IF /STR SPECIFIED, ELSE FALSE% &
	!	SUBFIL$		NAME OF FILE TO SUBSTITUTE INTO TKB LINE &
	!	SYSHD$		SYSTEM HEADER &
	!	TABCHR$		TAB &
	!	TEMP$		TEMPORARY STRING &
	!	TEMP%		TEMPORARY INTEGER &
	!	TEMP2%		SECOND TEMPORARY INTEGER &
	! 	TEXT$		RANDOM TEXT STRINGS &
	!	TRUE%		CONSTANT -1% &
	!	TSKFIL$		FILESPEC OF TASK FILE FOR TKB TO GENERATE. &
	!	TXT.LIN$	USER INPUT FROM TERMINAL &
	!	TXT.STR$	USER INPUT STRING (AND CONTINUATION LINES) &
	!	USE.SAM.RES%	TRUE% IF WE'RE USING AN SAM RESIDENT LIBRARY. &
	!	USE.FMS.RES%	TRUE% IF WE'RE USING AN FMS RESIDENT LIBRARY. &
	!	USE.OTS.RES%	TRUE% IF WE'RE USING AN OTS RESIDENT LIBRARY. &
	!	USE.OTS.2.RES%	TRUE% IF WE'RE USING A SECONDARY OTS RES LIB. &
	!	USE.RMS.RES%	TRUE% IF WE'RE USING AN RMS RESIDENT LIBRARY. &
	!	USE.RMS.SUP%	TRUE% IF WE'RE USING AN RMS SUPERVISOR LIBRARY. &
	! &
	! &

800	! &
	! &
	! &
	! &
	!	F U N C T I O N S   A N D   S U B R O U T I N E S &
	! &
	! &
	! &
	!	PROGRAM DEFINED SUBROUTINES &
	! &
	!	TITLE	LINE RANGE	DESCRIPTION &
	! &
	! &
	!		10100		INITIALIZE .CMD FILE. &
	!				OPEN THE FILE, PRINT &
	!				COMMENT HEADER, COMMAND LINE, &
	! &
	!		10200		FINISH UP .CMD FILE. &
	!				INCLUDE OPTIONS FOR RESIDENT &
	!				LIBRARIES. &
	! &
	!	$IF	10300		TEST A CONDITION, USE FOLLOWING &
	!				LINES OF .LNK FILE IF TRUE. &
	! &
	!		10600		INITIALIZE ODL FILE. &
	! &
	!		10700-10740	THIS ROUTINE GETS AND TRANSLATES &
	!				PSECTS AND OVERLAYS IF /STRUCTURE WAS &
	!				SPECIFIED.  ALSO PROCESSES THE &
	!				BRANCHES OF THE ODL TREE AND PRINTS &
	!				THE ".FCTR" STATEMENTS THAT DESCRIBE &
	!				THE OVERLAY STRUCTURE IN THE ODL FILE &
	!				(FUNCTIONS DO THE REAL WORK) &
	! &
	!	COBOL	11000-11230	THE COBOL COMPILER SETS UP THE &
	!				OVERLAYS IN THE .SKL FILE --> THIS &
	!				INFORMATION IS NEEDED FOR THE ODL AND &
	!				CMD FILE.  C81ODL (COBOL UTILITY FOR &
	!				CREATING ODL AND CMD FILES FROM .SKL) &
	!				IS USED IN PRELIN BY CHAINING OFF &
	!				TO ATPK, RUNNING C81ODL, AND EDITING &
	!				THE CMD AND ODL FILE IF FMS SPECIFIC &
	!				FILE INFORMATION IS NEEDED.  THEN &
	!				PRELIN SUBMITS THE CMD FILE TO TKB TO &
	!				CREATE THE FINAL TASK. &
	! &

825	! &
	! &
	! &
	!		PROGRAM DEFINED FUNCTIONS &
	! &
	! &
	! &
	!	TITLE	LINE RANGE	DESCRIPTION &
	! &
	! &
	! &
	!      FNDO.LNK.FILE% &
	!      		14100-14199	PROCESS THE .LNK FILE &
	! &
	!      FNSKIP.LNK% 14200-14299	SKIP A LINE UNTIL MATCHING $ENDIF &
	!				IN THE .LNK FILE &
	! &
	!      FNTRANS$  15100-15120    FUNCTION FOR FILENAME STRING SCAN &
	!				THIS WILL TRANSLATE THE FILENAMES &
	!				THAT ARE SEPARATED BY "," TO "-" &
	!				IN THE ODL FILE. LOGICAL DEVICE NAMES &
	!				ARE TRANSLATED TO ACTUAL DEVICE &
	!				DEVICE NAMES AND PPNS.  THEY ARE NOT &
	!				STICKY &
	! &
	!	FNGET$	16000-16200	THIS FUNCTION IS FOR PROMPTING AND &
	!				GETTING AN INPUT LINE FROM THE USER. &
	!				CHECKING FOR AN EXCLAMATION POINT &
	!				AND IGNORING THAT AS A COMMENT. &
	!				TEST FOR "-" AND JUST CONCATENATE ON &
	! 				THE REST OF THE STRING  -- PROMPT FOR &
	!				MORE INPUT. &
	! &
	!	FNC81TRANS$ 16400-16499	THIS FUNCTION IS FOR TRANSLATING THE &
	!				COBOL INPUT FILES TO BE PASSED TO &
	! 				C81ODL.  THE DEVICE AND PPN ARE &
	! 				FORCED ON TO AVOID STICKINESS. &
	! &
	!	FNTRANS.PSECT$ &
	!		16500-16520	THIS ROUTINE TRANSLATES THE PSECT &
	!				LIST INTO ZERO OR MORE ".PSECT" LINES &
	!				IN THE ODL FILE, CONVERTS THE COMMAS &
	!				THAT SEPARATE THE PSECT NAMES INTO &
	!				HYPHENS, AND ADDS A TRAILING HYPHEN &
	! &
	!	FNFILESPEC$ 16600-16630 THIS FUNCTION EXPANDS A VALID &
	!				FILESPEC INTO ITS FULL FORM &
	! &
	!	FNGET.PSECT$ &
	!		16700-16790	THIS FUNCTION PROMPTS FOR AND GETS &
	!				A VALID LIST OF ZERO OR MORE PSECTS &
	!				FROM THE USER &
	! &
	!	FNGET.OVLY$ &
	!		16800-16890	THIS FUNCTION PROMPTS FOR AND GETS &
	!				A VALID OVERLAY LINE FROM THE USER. &
	!				THIS INCLUDES CHECKING THAT THE FILES &
	!				EXIST AND ARE ACCESSIBLE &
	! &
	!	FNC81CMD$ &
	!		16900-16950	THIS FUNCTION TRANSLATES THE C81 TKB &
	!				COMMAND LINE FROM THAT RETURNED BY &
	!				C81ODL.TSK TO THAT WHICH WE WILL PASS &
	!				TO TKB IN OUR COMMAND FILE. &
	! &
	!	FNPUT.FCTR% 17000-17070 THIS FUNCTION IS FOR CREATING THE &
	!				.FCTR LINES IN THE ODL FILE. &
	! &
	!	FNEXT.LBL$ 17100-17120	THIS FUNCTION IS CALLED BY &
	!				FNPUT.FCTR% TO CREATE THE LABEL FOR &
	! 				THE NEW LINE IN THE ODL FILE.  A NEW &
	!				LINE WILL NEED TO BE CREATED WHEN &
	!				THERE ARE TOO MANY FILES OR PSECTS. &
	! &
	!	FNPROC.BRANCH% &
	!		18000-18040	THIS FUNCTION PROCESSES A BRANCH OF &
	!				THE OVERLAY TREE -- PROMPTS THE USER &
	!				FOR OVERLAYS AND PRODUCES THE LINES &
	!				FOR THE ODL FILE. THIS FUNCTION CALLS &
	!				ITSELF RECURSIVELY UNTIL ALL BRANCHES &
	!				OF THE OVERLAY TREE ARE PROCESSED. &
	! &
	!	FNFILE.LABEL$ &
	!		18100-18110	THIS IS A FUNCTION FOR GENERATING THE &
	!				UNIQUE FILE LABEL FOR THE ODL LINE. &
	! &
	!	FNAUTO.LABEL$ &
	!		18200-18210	THIS IS A FUNCTION FOR GENERATING &
	!				THE UNIQUE AUTOLOAD VECTOR LABELS &
	!				FOR THE ODL FILE. &
	! &
	!	FNGET.ERR$ 18250-18260  THIS FUNCTION IS FOR GETTING THE &
	!				RSTS/E ERROR MESSAGES &
	! &
	!	FNPRT.MSG% 18300-18310	THIS FUNCTION DISPLAYS A MESSAGE. &
	!				FIRST IT CANCELS CTRL/O EFFECT AND &
	!				RETURNS CURSOR TO LEFT MARGIN IF &
	!				NECESSARY. &
	! &
	!	FNBAD.LNK.LINE%		THIS FUNCTION REPORTS A FATAL ERROR &
	!				IN THE .LNK FILE. &
	! &
	!	FNPROMPT% 18400-18410	THIS FUNCTION DISPLAYS A PROMPT. &
	! &
	!	FNLOOKUP.RESLIB% &
	!		18600-18690	THIS FUNCTION CHECKS WHETHER THE &
	!				RESIDENT LIBRARY IS INSTALLED. &
	! &

900	! &
	! &
	! &
	!	D I M E N S I O N    S T A T E M E N T S &
	! &
	! &
	! &
	!	PROGRAM DEFINED ARRAYS &
	! &
	!	CHILD.CNT%(I%)	NUMBER OF CHILDREN OF OVERLAY AT LEVEL I% &
	!	FILELST$(I%)	LIST OF FILES ASSOCIATED WITH OVERLAY &
	!			AT LEVEL I% &
	!	LANG$()		POSSIBLE LIST OF LANGUAGES &
	!	LBLNUM%(I%)	LAST NUMBER USED IN LABEL FOR OVERLAY &
	!			AT LEVEL I% &
	!	M%()		BYTES FROM SYSTEM CALLS &

910	DIM 	CHILD.CNT%(7%), &
		! CHILDCNT%(LEVEL%) IS THE NUMBER OF CHILDREN OF OVERLAY &
		! AT LEVEL% OF CURRENT PATH IN OVERLAY STRUCTURE &
	FILELST$(7%), &
		! FILELST$(LEVEL%) - LIST OF FILES ASSOCIATED WITH AN OVERLAY &
		! AT LEVEL% OF CURRENT PATH IN OVERLAY STRUCTURE &
	LANG$(7%), &
		! POSSIBLE LANGUAGES BP2,F77,DIBOL,C81,DMS (DIBOL VARIANT), &
		! RSX11, 'C' &
	LBLNUM%(7%), &
		! LBLNUM%(I%) - FOR EACH LEVEL I%, LBLNUM(I%) IS THE &
		! NUMBER OF THE LAST LABEL GENERATED AT LEVEL I% &
	M%(30%) &
		! BYTES RETURNED FROM SYSTEM CALLS &

999	! &
	! &
	! &
	!	S T A R T    O F    P R O G R A M &
	! &
	! &
	! &

1000	ON ERROR GOTO 19000 &
	\ CHR.6$ = CHR$(6%) &
	\ FALSE% = 0% &
	\ TRUE% = -1% &
	\ DBG% = FALSE% &
	\ PRIV.ON$ = CHR.6$ + CHR$(-21%) + CHR$(0%) &
	\ PRIV.OFF$ = CHR.6$ + CHR$(-21%) + CHR$(-1%) &
	\ JUNK$ = SYS(PRIV.OFF$) &
		! SET UP STANDARD ERROR TRAP. &
		! IF WE ARE DEBUGGING PRELIN, THEN SET "DBG% = TRUE%" HERE. &
		! IF WE ARE NOT DEBUGGING, THEN SET "DBG% = FALSE%" HERE. &
		! DROP TEMPORARY PRIVILEGES TEMPORARILY. &

1010	IDENT.STG$ = "V10.1-A" &
	\ PRG.NAM$ = "PRELIN" + CHR$(9%) &
	\ CHANGE SYS(CHR$(12%)) TO M% &
	\ PRG.SPEC$ = "[" + NUM1$(M%(6%)) + "," + NUM1$(M%(5%)) + "]" &
	\ PRG.SPEC$ = CHR$(M%(23%)) + CHR$(M%(24%)) + &
		NUM1$(M%(25%)) + ":" + PRG.SPEC$  IF M%(26%) AND 1% &
	\ PRG.SPEC$ = "_" + PRG.SPEC$ + &
		RAD$(M%(7%) + SWAP%(M%(8%))) + RAD$(M%(9%) + SWAP%(M%(10%))) &
		+ "." + RAD$(M%(11%) + SWAP%(M%(12%))) &
	\ IF M%(3%) + SWAP%(M%(4%)) <> 15% * 2% THEN &
		JUNK% = FNPRT.MSG%("?PRELIN must be compiled") &
	\ GOTO 32767 &
		! SET UP DEVICE AND ACCOUNT OF LAST FILE OPENED. &
		! SET UP OUR IDENTIFICATION STRING AND NAME. &

1030	SYSHD$ = SYS(CHR.6$+CHR$(9%)+CHR$(0%)) &
	\ JOB.NUM$ = RIGHT(NUM1$(100%+(ASCII(SYSHD$)/2%)),2%) &
	\ CHANGE SYS(CHR.6$ + CHR$(26%) + CHR$(0%) + CHR$(0%)) TO M% &
	\ OURPPN$ = "[" + NUM1$(M%(22%)) + "," + NUM1$(M%(21%)) + "]" &
	\ CMD.FIL$ = "CMD0" + JOB.NUM$ + ".TMP" &
	\ ODL.FIL$ = "ODL0" + JOB.NUM$ + ".TMP" &
	\ MAX.LEVEL% = 7% &
	\ MAXODL.LEN% = 78% &
	\ IF ENTRY.TYP% = 0% THEN &
		JUNK% = FNPRT.MSG%(IDENT.STG$+CHR$(9%)+RIGHT(SYSHD$,3%)) &
	\	JUNK% = FNPRT.MSG%("?Please use the DCL LINK command") &
	\	GOTO 32767 &
		! SET UP JOB NUMBER FOR FILE NAMES &
		! GET JOB STATISTICS AND THE PPN WE'RE RUNNING UNDER &
		! MAKE NAMES TO USE FOR TKB .CMD AND .ODL FILES &
		! DEFINE MAXIMUM LEVEL OF OVERLAYS &
		! SETS ENTRY POINT FOR ONLY CHAINING &
		! PRINT HEADER, ERROR MESSAGE, AND EXIT IF OTHER ENTRY &

1060	SKIP%, FMS.QUAL%, RMS.QUAL%, STR%, DEBUG.QUAL%, SAM.QUAL% = FALSE% &
	\ ID%, NOID% = FALSE% &
	\ GOT.ERR%, C81ERR% = FALSE% &
	\ TABCHR$ = CHR$(9%) &
	\ SPACECHR$ = CHR$(32%) &
	\ NL$ = "" &
	\ OTS.2.RESLIB$ = NL$ &
	\ CRLF$ = CHR$(13%) + CHR$(10%) &
	\ FCTR.CMD$ = ":" + TABCHR$ + ".FCTR" + TABCHR$ &
	\ JUNK$ = NL$ &
	\ JUNK% = 0% &
		! INITIALIZE PROGRAM VARIABLES. &
		! SET UP TAB, NULL, AND CARRIAGE RETURN CHARACTER STRING. &
		! SET SECONDARY OTS LIBRARY NAME TO THE NULL STRING &

1095	READ LANGCNT% &
	\ READ LANG$(I%) FOR I% = 1% TO LANGCNT% &
	\ DATA 7,BP2,C81,F77,DIBOL,DMS,RSX11,CC &
	&

1100	! &
	! &
	! &
	!	M A I N    L I N E    C O D E &
	! &
	! &

1105	OPEN "_KB:PRELIN.CMD" FOR INPUT AS FILE #1% &

1110	INP$ = CVT$$(SYS(CHR$(7%)),4%+8%+16%+32%+128%) &
	\ GOTO 11030 IF ENTRY.TYP%=2% &
	\ OUTFIL% = INSTR(1%,INP$,SPACECHR$) &
	\ RTFIL% = INSTR(1%,INP$,'=') &
	\ RTFIL$ = RIGHT(INP$,(RTFIL% +1%)) &
	\ OUTFIL$ = MID(INP$,OUTFIL%+1%,(RTFIL%-OUTFIL%-1%)) &
	\ TSKFIL$ = FNFILESPEC$(OUTFIL$) &
	\ MAPFIL$ = RIGHT(OUTFIL$,LEN(OUTFIL$)-RECOUNT+2%) &
	\ QUALS$ = LEFT(INP$,OUTFIL%-1%) &
	\ QUALS$ = RIGHT(QUALS$,INSTR(1%,QUALS$+"/","/")) &
		! GET INPUT LINE FROM CORE COMMON. &
		! CHECK IF WE'RE BACK FROM ATPK AFTER RUNNING C81ODL. &
		! IF SO, GO AND PROCESS REST OF COBOL FILES. &
		! STRIP OFF ALL BUT SPACES. SEARCH FOR SPACE. &
		! GET ROOT INPUT FILE(S) FROM = SIGN OVER. &
		! GET OUTPUT FILE(S) FROM " " TO "=". &
		! GET QUALIFIERS FROM FIRST SLASH (IF ANY) TO " ". &

1120	DESC.QUAL% = INSTR(1%,QUALS$,"/DES")<>0% &
	\ IF DESC.QUAL% THEN &
		CMD.FIL$ = RTFIL$ &
		\ GOTO 32700 &
		! IF USER SPECIFIED /DESCRIPTION QUALIFIER THEN &
		!	SET UP COMMAND FILESPEC FOR TKB. &
		!	GO RUN TKB. &

1125	FMS.QUAL% = INSTR(1%,QUALS$,"/FMS")<>0% &
	\ DEBUG.QUAL% = INSTR(1%,QUALS$,"/DEB")<>0% &
	\ SAM.QUAL% = INSTR(1%,QUALS$,"/SAM")<>0% &
	\ SAM.QUAL% = FALSE% IF INSTR(1%,QUALS$,"/SAM:NORES")<>0% &
	\ STR% = INSTR(1%,QUALS$,"/STR")<>0% &
	\ ID% = INSTR(1%,QUALS$,"/ID")<>0% &
	\ NOID% = INSTR(1%,QUALS$,"/NOID")<>0% &
	\ STACK.SIZE% = INSTR(1%,QUALS$,"/STACK:") &
	\ IF STACK.SIZE% &
	THEN	JUNK$ = RIGHT(QUALS$,STACK.SIZE%+7%) &
	\	JUNK% = INSTR(1%, JUNK$,"/") &
	\	JUNK$ = LEFT(JUNK$,JUNK%-1%) IF JUNK% &
	\	STACK.SIZE% = VAL(JUNK$) &

1127	GOTO 1130 IF INSTR(1%,QUALS$,"/"+LANG$(I%)) &
		FOR I% = 1% TO LANGCNT% &
	\ I% = 1% &
		! LOOK FOR /FMS, /SAM, /STR, AND LANGUAGE QUALIFIERS &
		! DEFAULT TO LANGUAGE SET UP BY SYSTEM MANAGER &

1130	LANG$ = LANG$(I%) &
	\ IF (LANG$="DMS") AND FMS.QUAL% THEN &
		JUNK% = FNPRT.MSG%("?Conflicting qualifiers - /DMS and /FMS") &
	\	GOTO 32750 &
		! NOTE - WE KNOW DCL PASSED US A LEGAL SET OF &
		!       QUALIFIERS, SO WE DON'T HAVE TO CHECK FOR &
		!	EXTRANEOUS QUALIFIERS &
		! IF USER SPECIFIED /DMS AND /FMS, GIVE ERROR AND EXIT &

1140	IF (LANG$="RSX11") OR (LANG$="CC")  THEN &
		RMS.QUAL% = INSTR(1%,QUALS$,"/RMS")<>0% &
	ELSE IF LANG$="DMS" THEN &
		RMS.QUAL% = FALSE% &
	ELSE &
		RMS.QUAL% = INSTR(1%,QUALS$,"/NORMS")=0% &
		! IF LANGUAGE IS RSX-11-BASED MACRO OR 'C' THEN &
		!	USE RMS ONLY IF USER EXPLICITLY REQUESTS IT. &
		! IF LANGUAGE IS DIBOL WITH DMS THEN &
		!	DON'T USE RMS, OBVIOUSLY. &
		! FOR OTHER RSX-11-BASED LANGUAGE, &
		!	USE RMS UNLESS USER EXPLICITLY SAYS /NORMS. &

2000	! &
	! &
	! PROCESS .LNK FILE. &
	! &
	! &
	OPEN "LB:"+LANG$+".LNK" FOR INPUT AS FILE #5% &
	\ USE.OTS.RES%, USE.RMS.SUP%, USE.RMS.RES%, USE.FMS.RES% = FALSE% &
	\ USE.OTS.2.RES%, OTS.CLUSTER%, FMS.CLUSTER% = FALSE% &
	\ GOSUB 10100 &
	\ GOSUB 10600 &
	\ JUNK% = FNDO.LNK.FILE% &
	\ GOTO 32750 IF GOT.ERR% &
	\ IF LANG$="C81" THEN &
		GOTO 11000 &
	ELSE &
		GOSUB 10200 &
	\	GOSUB 10700 &
	\	GOTO 32750 IF GOT.ERR% &
	\	PRINT #7%, ".END" &
	\	CLOSE #7% &
	\	GOTO 32700 &
		! GET READY TO READ LANGUAGE .LNK FILE READ-ONLY. &
		! PRESET THAT NO RESIDENT LIBRARIES ARE AVAILABLE. &
		! INITIALIZE THE CMD FILE. &
		! INITIALIZE THE ODL FILE. &
		! DO THE .LNK FILE. &
		! IF IT'S COBOL, GO RUN C81ODL TO CREATE ODL AND CMD FILE. &
		! FOR OTHER LANGUAGE, FINISH UP THE CMD FILE, &
		! CREATE THE OVERLAY TREE, AND FINISH UP THE ODL FILE. &

9000	! &
	! &
	! &
	!	P R O G R A M M E R    D E F I N E D &
	!		S U B R O U T I N E S &
	! &
	! &

9100	! &
	! &
	!	P R O C E S S   $ R E S L I B   S U B R O U T I N E &
	! &
	! &
	! INPUTS: &
	!	IN.LNK$ = $RESLIB LINE OF .LNK FILE. &
	!	PARM$ = PARAMETER FROM $RESLIB LINE OF .LNK FILE, &
	!		OF THE FORM: &
	!			LIBTYPE LIBNAME &
	!			OTS     LIBNAME/NOCLUSTER &
	!			OTS     LIBNAME,LIBNAME/[NO]CLUSTER &
	!		WHERE LIBTYPE IS FMS, RMS, OR OTS.  (MUST BE A &
	!		THREE-CHARACTER SYMBOL.) &
	!		SPACES ARE NOT SIGNIFICANT. &
	!		/[NO]CLUSTER IS ALLOWED ONLY WITH THE OTS. &
	!	RMS.QUAL%  INDICATES WHETHER WE'RE USING RMS OR NOT. &
	! &
	! OUTPUTS: &
	!	IF LIBTYPE IS FMS THEN &
	!		USE.FMS.RES% FLAGS WHETHER TO USE FMS RESLIB. &
	!		FMS.RESLIB$ = NAME OF FMS RESLIB. &
	!		OTS.CLUSTER% FLAGS WHETHER FMS IS BUILT TO CLUSTER &
	!		(IE PIC OR BUILT AGAINST APR 6). &
	!	IF LIBTYPE IS RMS THEN &
	!		USE.RMS.RES% FLAGS WHETHER TO USE RMS RESLIB USER MODE &
	!		USE.RMS.SUP% FLAGS WHETHER TO USE RMS RESLIB SUPR MODE &
	!		RMS.RESLIB$ = NAME OF RMS RESLIB. &
	!	IF LIBTYPE IS OTS THEN &
	!		USE.OTS.RES% FLAGS WHETHER TO USE OTS RESLIB. &
	!		USE.OTS.2.RES% FLAGS WHETHER TO USE 2NDARY OTS RESLIB. &
	!		OTS.RESLIB$ = NAME OF OTS RESLIB. &
	!		OTS.2.RESLIB$ = NAME OF SECOND OTS RESLIB. &
	!		OTS.2.RESLIB$ = NL$ IF LIST NOT SPECIFIED &
	!		OTS.CLUSTER% FLAGS WHETHER OTS RESLIB CAN CLUSTER. &
	!		USE.FMS.RES% MAY HAVE CHANGED TO FALSE% &
	!	IF LIBTYPE IS SAM (SORT_AND_MERGE) THEN &
	!		USE.SAM.RES% FLAGS WHTHER TO USE SORT AND MERGE RESLIB &
	&

9110	PARM$ = CVT$$(PARM$,-2%) &
	\ LIBTYPE$ = LEFT(PARM$,3%) &
	\ LIBNAME$ = RIGHT(PARM$,4%) &
	\ PRESENT% = FNLOOKUP.RESLIB%( LEFT(LIBNAME$,INSTR(1%, &
		LIBNAME$+"/","/")-1%) ) &
	\ GOTO 9120 UNLESS LIBTYPE$="RMS" &
	\ RMS.RESLIB$ = LIBNAME$ &
	\ IF NOT RMS.QUAL% THEN &
		USE.RMS.RES% = FALSE% &
	ELSE IF INSTR(1%,QUALS$,"/RMS:RES") THEN &
		USE.RMS.RES% = TRUE% &
	ELSE IF INSTR(1%,QUALS$,"/RMS:NORES") THEN &
		USE.RMS.RES% = FALSE% &
	ELSE IF INSTR(1%,QUALS$,"/RMS:SUP") THEN &
		USE.RMS.SUP% = TRUE% &
	ELSE &
		USE.RMS.RES% = PRESENT% &
		! EXTRACT LIBRARY NAME AND TYPE OF LIBRARY, &
		! ASSUMING LIB TYPE IS THREE CHARACTERS LONG. &
		! FIND OUT WHETHER THE LIBRARY IS PRESENT (ADDED) OR NOT. &
		! IF IT'S RMS, FLAG WHETHER TO USE RMS OR NOT. &

9115	GOTO 9199 &

9120	GOTO 9130 UNLESS LIBTYPE$="FMS" &
	\ FMS.RESLIB$ = LIBNAME$ &
	\ IF INSTR(1%,QUALS$,"/FMS:RES") THEN &
		USE.FMS.RES% = TRUE% &
	ELSE IF INSTR(1%,QUALS$,"/FMS:NORES") THEN &
		USE.FMS.RES% = FALSE% &
	ELSE &
		USE.FMS.RES% = PRESENT% AND FMS.QUAL% &
		! FLAG WHETHER OR NOT TO USE RESIDENT FMS. &

9125	GOTO 9199 UNLESS USE.FMS.RES% &
	\ OPEN "LB:"+FMS.RESLIB$+".TSK" FOR INPUT AS FILE #6% &
	\ GET #6% &
	\ FIELD #6%, 8% AS JUNK$, 2% AS TEMP$ &
	\ BASE.ADDRESS% = SWAP%(CVT$%(TEMP$)) &
	\ FMS.CLUSTER% = TRUE% &
	\ FMS.CLUSTER% = FALSE% IF BASE.ADDRESS%=-24576% &
	\ CLOSE #6% &
	\ USE.FMS.RES% = FALSE% IF &
		FMS.CLUSTER% AND USE.OTS.RES% AND (NOT OTS.CLUSTER%) &
	\ GOTO 9199 &
		! IF WE'RE USING THE FMS RESIDENT LIBRARY THEN &
		!	OPEN THE TSK FILE FOR THE FMS LIBRARY READ-ONLY. &
		!	//SHOULD TRAP ERROR.// &
		!	READ THE TASK HEADER, AND GET THE BASE ADDRESS OF THE &
		!	LIBRARY. &
		!	WE ASSUME THAT BASE ADDRESS IS EITHER &
		!	120000 OCTAL (NON-CLUSTERABLE) OR &
		!	140000 OCTAL (CLUSTERABLE), OR THE LIBRARY IS PIC. &
		!	IF BASE ADDRESS IS 120000 OCTAL (-24576 DECIMAL), &
		!	FLAG NON-CLUSTERABLE, ELSE CLUSTERABLE. &
		!	IF WE'VE ALREADY SEEN THE $RESLIB OTS COMMAND, &
		!	AND IF WE HAVE A NON-CLUSTERABLE OTS AND A &
		!	CLUSTERABLE FMS, THEN WE CAN'T USE FMS RESLIB. &

9130	GOTO 9137 UNLESS LIBTYPE$="OTS" &
	\ TEMP% = INSTR(1%,LIBNAME$,"/") &
	\ OTS.RESLIB$ = LIBNAME$ &
	\ OTS.RESLIB$ = LEFT(LIBNAME$,TEMP%-1%) IF TEMP%<>0% &
	\ GOTO 9133 IF TEMP%=0% &
	\ GOTO 9140 IF  (RIGHT(LIBNAME$,TEMP%)<>"/NOCLUSTER") AND &
			(RIGHT(LIBNAME$,TEMP%)<>"/CLUSTER") &
		! .LNK ERROR IF QUALIFIER IS NOT /CLUSTER OR /NOCLUSTER &

9133	OTS.CLUSTER% = (RIGHT(LIBNAME$,TEMP%)<>"/NOCLUSTER") &
	\ TEMP2% = INSTR(1%,OTS.RESLIB$,",") &
	\ OTS.2.RESLIB$ = RIGHT(OTS.RESLIB$,TEMP2%+1%) IF TEMP2%<>0% &
	\ OTS.RESLIB$ = LEFT(OTS.RESLIB$,TEMP2%-1%) IF TEMP2%<>0% &
	\ IF INSTR(1%,QUALS$,"/OTS:RES") THEN &
		USE.OTS.RES% = TRUE% &
	ELSE IF INSTR(1%,QUALS$,"/OTS:NORES") THEN &
		USE.OTS.RES% = FALSE% &
	ELSE &
		USE.OTS.RES% = FNLOOKUP.RESLIB%(OTS.RESLIB$) &
	\	USE.OTS.RES% = USE.OTS.RES% AND &
			FNLOOKUP.RESLIB%(OTS.2.RESLIB$) &
			IF LEN(OTS.2.RESLIB$) <> 0% &
		! WE CAN CLUSTER IF .LNK FILE SAYS TO CLUSTER &
		! FLAG WHETHER OR NOT TO USE RESIDENT OBJECT-TIME SYSTEM. &
		! FLAG WHETHER OTS RESLIB CAN CLUSTER OR NOT. &

9135	USE.OTS.2.RES% = USE.OTS.RES% AND (LEN(OTS.2.RESLIB$)<>0%) &
	\ OTS.2.RESLIB$ = NL$ UNLESS USE.OTS.2.RES% &
	\ USE.FMS.RES% = FALSE% IF &
		USE.FMS.RES% AND FMS.CLUSTER% AND &
		USE.OTS.RES% AND (NOT OTS.CLUSTER%) &
	\ GOTO 9199 &
		! USE THE SECONDARY OTS LIBRARY IF WERE USING THE OTS LIBRARY &
		!   AND A SECOND OTS LIBRARY WAS PRESENT ON THE $RESLIB LINE &
		!   SET IT BACK TO THE NULL STRING IF WE"RE NOT USING IT &
		! IF WE'VE ALREADY EXECUTED THE $RESLIB FMS LINE, &
		! AND IF WE HAVE A NON-CLUSTERABLE OTS AND A CLUSTERABLE &
		! FMS, THEN WE CAN'T USE FMS RESLIB. &

9137	GOTO 9140 UNLESS LIBTYPE$="SAM" &
	\ SAM.RESLIB$ = LIBNAME$ &
	\ USE.SAM.RES% = SAM.QUAL% &
	\ USE.RMS.RES% = TRUE% IF USE.SAM.RES% &
	\ GOTO 9199 &
		! IF RESLIB IS SAM, &
		! FLAG USE SORT AND MERGE LIBRARY IF HE WANTS IT &
		! FORCE USE RMS IF SORT IS BEING USED &

9140	JUNK% = FNBAD.LNK.LINE%(IN.LNK$) &
	\ GOT.ERR% = TRUE% &
		! ILLEGAL .LNK LINE. &

9199	RETURN &

10100	! &
	! &
	! &
	!	I N I T I A L I Z E   C M D   F I L E   S U B R O U T I N E &
	! &
	! &
	! THIS ROUTINE OPENS UP THE TKB CMD FILE AND PRINTS THE TKB &
	! COMMAND LINE FOO,FOO=BAR,BAR. &
	! &
	! INPUTS: &
	!	OUTFIL$ HAS THE FORM [OBJECT-FILESPEC][,MAP-FILESPEC] &
	!	TSKFIL$ IS THE OUTPUT FILESPEC &
	!	MAPFIL$ IS THE MAP FILESPEC (MAY BE NULL) &
	!	LANG$ = "RSX11" IF LANGUAGE IS /RSX11 (MACRO). &
	!	DEBUG.QUAL% FLAGS WHETHER /DEBUG SPECIFIED. &
	!	ID% = TRUE% IF /ID SPECIFIED, ELSE FALSE &
	!	NOID% = TRUE% IF /NOID SPECIFIED, ELSE FALSE &
	! &
	! OUTPUTS: &
	!	TKB CMD FILE OPEN ON CHANNEL 3. &
	!	COMMENT LINE AND FOO,FOO=FOO LINE PRINTED IN IT. &
	&
	OPEN CMD.FIL$ FOR OUTPUT AS FILE #3% &
	\ PRINT #3%, ';  TKB .CMD file created by DCL LINK  '; IDENT.STG$; &
			 TABCHR$; DATE$(0%); SPACE$(3%); TIME$(0%) &
	\ PRINT #3%, TSKFIL$; "/FP"; &
	\ PRINT #3%, "/DA"; IF &
		DEBUG.QUAL% AND ((LANG$="RSX11") OR (LANG$="F77") &
			OR (LANG$="CC")) &
	\ PRINT #3%, "/ID"; IF ID% &
	\ PRINT #3%, "/-ID"; IF NOID% &
	\ PRINT #3%, ","; MAPFIL$; IF LEN(MAPFIL$) &
	\ PRINT #3%, "="; ODL.FIL$; "/MP" &
		! OPEN THE CMD FILE AND PRINT THE COMMENT LINE. &
		! PRINT THE [objfile]/FP[/DA][/ID][,mapfile]=odlfile/MP LINE. &
		! INCLUDE /DA IF IT'S A MACRO OR F77 OR 'C' PROGRAM AND &
		! /DEBUG WAS SPECIFIED. THIS MEANS ODT FOR MACRO, AND FORTRAN &
		! INCLUDE /ID or /-ID IF [NO] I AND D SPACE REQUESTED &
		! DEBUGGER FOR FORTRAN. &

10199	RETURN &

10200	! &
	! &
	! &
	!	F I N I S H   U P   C M D   F I L E   S U B R O U T I N E &
	! &
	! &
	! &
	! INPUTS: &
	!	USE.FMS.RES%,\ &
	!	FMS.CLUSTER%, \ &
	!	USE.RMS.RES%,  \ &
	!	USE.RMS.SUP%,   +-- SET UP ALREADY BY $RESLIB COMMAND. &
	!	USE.OTS.RES%,  / &
	!	OTS.CLUSTER%  / &
	!	USE.SAM.RES% / &
	!	STACK.SIZE% - Stack size request, or zero for TKB default &
	!	CMD FILE OPEN ON CHANNEL 3. &
	! &
	! OUTPUTS: &
	!	APPROPRIATE LIBR= AND CLSTR= LINES PRINTED IN CMD FILE. &
	!	// COMMAND PRINTED, COMMAND FILE CLOSED. &
	! &
	! INTERNAL VARIABLES: &
	!	TEMP% = NUMBER OF RESLIBS TO CLUSTER &
	&
	GOTO 10240 IF USE.OTS.RES% AND (NOT OTS.CLUSTER%) &
	\ TEMP% = 0% &
	\ TEMP% = TEMP%+1% IF USE.RMS.RES% UNLESS USE.RMS.SUP% &
	\ TEMP% = TEMP%+1% IF USE.SAM.RES% &
	\ TEMP% = TEMP%+1% IF USE.OTS.RES% &
	\ TEMP% = TEMP%+1% IF USE.OTS.2.RES% &
	\ TEMP% = TEMP%+1% IF FMS.QUAL% AND USE.FMS.RES% AND FMS.CLUSTER% &
	\ GOTO 10240 IF TEMP%<2% &
	\ CLUSTER.LST$ = NL$ &
	\ CLUSTER.LST$ = "," + OTS.RESLIB$ IF USE.OTS.RES% AND OTS.CLUSTER% &
	\ CLUSTER.LST$ = CLUSTER.LST$ + "," + OTS.2.RESLIB$ IF &
		USE.OTS.2.RES% AND OTS.CLUSTER% &
	\ CLUSTER.LST$ = CLUSTER.LST$ + ","+ FMS.RESLIB$ IF &
		USE.FMS.RES% AND FMS.QUAL% AND FMS.CLUSTER% &
	\ CLUSTER.LST$ = CLUSTER.LST$ + "," + RMS.RESLIB$ IF USE.RMS.RES% &
		UNLESS USE.RMS.SUP% &
	\ CLUSTER.LST$ = CLUSTER.LST$ + "," + SAM.RESLIB$ IF USE.SAM.RES% &
		! WE CAN'T CLUSTER IF THE OTS RESLIB IS BEING USED AND ISN'T &
		! CLUSTERABLE. &
		! WE CAN'T CLUSTER UNLESS WE HAVE AT LEAST TWO CLUSTERABLE &
		! LIBRARIES. &
		! IF WE ARE CLUSTERING, BEGIN MAKING THE LIST OF LIBRARIES &
		! TO CLUSTER. &
		! OTS MUST GO FIRST IF IT'S BEING CLUSTERED. &
		! TACK FMS ONTO THE CLUSTER LIST IF WE'RE USING IT AND &
		! IT CLUSTERS. &
		! TACK RMS ONTO THE LIST IF WE'RE USING IT. &
		! TACK SAM RESIDENT LIBRARY NAME ONTO LIST IF WE'RE USING IT &

10220	PRINT    #3%, "CLSTR ="; RIGHT(CLUSTER.LST$,2%); ":RO" &
	\ PRINT  #3%, "LIBR  ="; FMS.RESLIB$; ":RO" IF &
		FMS.QUAL% AND USE.FMS.RES% AND (NOT FMS.CLUSTER%) &
	\ GOTO 10250 &
		! PRINT OUT THE CLUSTER LIST, BUT NOT THE FIRST COMMA &
		! IF FMS IS BEING USED BUT DOESN'T CLUSTER, THEN &
		! PUT OUT THE LIBR= LINE FOR IT. &

10240	PRINT #3%, "LIBR="; RMS.RESLIB$; ":RO" IF USE.RMS.RES% &
		UNLESS USE.RMS.SUP% &
	\ PRINT #3%, "LIBR="; FMS.RESLIB$; ":RO" &
		IF FMS.QUAL% AND USE.FMS.RES% &
	\ PRINT #3%, "LIBR="; OTS.RESLIB$; ":RO" IF USE.OTS.RES% &
	\ PRINT #3%, "LIBR="; OTS.2.RESLIB$; ":RO" IF USE.OTS.2.RES% &
		! WE'RE NOT CLUSTERING.  PRINT THE APPROPRIATE LIBR= &
		! LINES. &

10250	PRINT #3%, "RESSUP=RMS$:"; RMS.RESLIB$; "/SV:0" IF USE.RMS.SUP% &
	\ PRINT #3%, "STACK=";STACK.SIZE% IF STACK.SIZE% &

10299	PRINT #3%, "//" &
	\ CLOSE #3% &
	\ RETURN &

10300	! &
	! &
	! &
	!	P R O C E S S   $ I F    S U B R O U T I N E &
	! &
	! &
	! INPUTS: &
	!	PARM$ = CONDITION TO TEST.  ONE OF: &
	!		FMS &
	!		NOFMS &
	!		FMS:RESIDENT &
	!		FMS:NORESIDENT &
	!		OTS:RESIDENT &
	!		OTS:NORESIDENT &
	!		RMS &
	!		RMS:RESIDENT &
	!		RMS:NORESIDENT &
	!		NORMS &
	!		DEBUG &
	!		NODEBUG &
	!	SPACES ARE NOT SIGNIFICANT IN PARM$. &
	! &
	! OUTPUTS: &
	!	SKIP% = FALSE% IFF CONDITION IS TRUE. &
	!	GOT.ERR% = TRUE% IF FATAL ERROR IN .LNK FILE. &

10320	PARM$ = CVT$$(PARM$,-2%) &
	\ IF PARM$="FMS" THEN &
		COND% = FMS.QUAL% &
	ELSE IF PARM$ = "FMS:RESIDENT" THEN &
		COND% = FMS.QUAL% AND USE.FMS.RES% &
	ELSE IF PARM$ = "FMS:NORESIDENT" THEN &
		COND% = FMS.QUAL% AND (NOT USE.FMS.RES%) &
	ELSE IF PARM$ = "NOFMS" THEN &
		COND% = NOT FMS.QUAL% &
	ELSE IF PARM$ = "OTS:RESIDENT" THEN &
		COND% = USE.OTS.RES% &
	ELSE IF PARM$ = "OTS:NORESIDENT" THEN &
		COND% = NOT USE.OTS.RES% &
	ELSE IF PARM$ = "RMS" THEN &
		COND% = RMS.QUAL% &
	ELSE IF PARM$ = "RMS:SUPERVISOR" THEN &
		COND% = RMS.QUAL% AND USE.RMS.SUP% &
	ELSE IF PARM$ = "RMS:RESIDENT" THEN &
		COND% = RMS.QUAL% AND USE.RMS.RES% &
	ELSE IF PARM$ = "RMS:NORESIDENT" THEN &
		COND% = RMS.QUAL% AND (NOT (USE.RMS.RES% OR USE.RMS.SUP%)) &
	ELSE IF PARM$ = "NORMS" THEN &
		COND% = NOT RMS.QUAL% &
	ELSE IF PARM$ = "DEBUG" THEN &
		COND% = DEBUG.QUAL% &
	ELSE IF PARM$ = "NODEBUG" THEN &
		COND% = NOT DEBUG.QUAL% &
	ELSE &
		GOT.ERR% = TRUE% &

10340	SKIP% = NOT COND% &
	\ RETURN &

10600	! &
	! &
	! &
	!	I N I T I A L I Z E   O D L   F I L E   S U B R O U T I N E &
	! &
	! &
	OPEN ODL.FIL$ FOR OUTPUT AS FILE #7% &
	\ PRINT #7%, '; TKB .ODL file created by DCL LINK  '; IDENT.STG$; &
	\ PRINT #7%, TABCHR$; DATE$(0%); SPACE$(3%); TIME$(0%) &
	\ RETURN &
		! OPEN ODL FILE. &

10700	! &
	! &
	! &
	!	C R E A T E   T R E E    S U B R O U T I N E &
	! &
	! &
	! THIS ROUTINE PROMPTS THE USER FOR ROOT PSECTS AND OVERLAYS IF &
	! /STRUCTURE WAS SPECIFIED.  THIS ROUTINE PRINTS THE ".FCTR" &
	! STATEMENTS THAT DESCRIBE THE OVERLAY STRUCTURE IN THE ODL FILE &
	! &
	! INPUTS: &
	!	ODL FILE OPEN ON CHANNEL 3 &
	!	RTFIL$ = VALID LIST OF ROOT FILES (ONE OR MORE FILESPECS, &
	!	SEPARATED BY COMMAS) &
	!	STR% = TRUE% IF /STRUCTURE WAS SPECIFIED, FALSE% OTHERWISE. &
	!	FMS.QUAL% = TRUE% IF /FMS WAS SPECIFIED, FALSE% OTHERWISE. &
	! &
	! OUTPUTS: &
	!	A TREE OF ".FCTR" STATEMENTS HAS BEEN PRINTED IN THE ODL FILE. &
	!	THE ROOT OF THIS TREE IS "A0$".  THE TREE DESCRIBES THE &
	!	OVERLAY STRUCTURE SPECIFIED BY THE USER.  EACH OVERLAY &
	!	INCLUDES A REFERENCE TO LBR$$ (OBJECT LIBRARIES).  THE ROOT &
	!	(A0$) INCLUDES A REFERENCE TO ROOT$$ (OTS, RMS, AND FMS IS &
	!	/FMS WAS SPECIFIED). LBR$$ CONTAINS THE NEEDED LIBRARY .OLB. &
	! &
	! CONSIDER THE FOLLOWING DIALOG: &
	! &
	! $ LINK/STRUCTURE &
	! ROOT files: ROOT &
	! Root PSECTs: MYCMN &
	! Overlay: OVA+ &
	!   Overlay: OVA1 &
	!   Overlay: OVA2,OVA3 &
	!   Overlay: <RET> &
	! Overlay: OVB &
	! Overlay: OVC+ &
	!   Overlay: OVC1 &
	!   Overlay: OVC2 &
	!   Overlay: <RET> &
	! Overlay: <RET> &
	! &
	! THE FOLLOWING CHART SHOWS THIS OVERLAY STRUCTURE.  OVERLAYS ARE &
	! SHOWN IN RECTANGLES. THE STAR (*) REPRESENT AUTOLOAD INDICATORS. &
	! THE .FCTR LABELS USED IN THE ODL FILE ARE SHOWN, AND ALL END WITH $. &
	! &
	! +------+    +-----------+           +------+    +------+ &
	! | OVA1 |    | OVA2,OVA3 |           | OVC1 |    | OVC2 |     LEVEL 2 &
	! +------+    +-----------+           +------+    +------+ &
	!     | E0$         | E1$                 | E2$       | E3$ &
	!     ------   ------                     -----   ----- &
	!           \ /                                \ / &
	!           (*) D0$                            (*) D2$ &
	!            |                                  | &
	!         +-----+           +-----+          +-----+ &
	!         | OVA |           | OVB |          | OVC | 	     LEVEL 1 &
	!         +-----+           +-----+          +-----+ &
	!            | C0$             | C1$            | C2$ &
	!            ----------------- | ---------------- &
	!                             \|/ &
	!                             (*) B0$ &
	!                              | &
	!                          +------+ &
	!                          | ROOT | 			     LEVEL 0 &
	!                          +------+ &
	!                                A0$ &
	! &
	! THE FOLLOWING ARE THE ODL LINES THAT CORRESPOND TO THIS STRUCTURE. &
	! (ASSUME WE ARE IN [1,223].) NOTE THAT IT READS FROM BOTTOM TO TOP. &
	! &
	!	.PSECT	MYCMN &
	! E0$:	.FCTR	SY:[1,223]OVA1-LBR$$ &
	! E1$:	.FCTR	SY:[1,223]OVA2-SY:[1,223]OVA3-LBR$$ &
	! D0$:	.FCTR	E0$,E1$ &
	! C0$:	.FCTR	SY:[1,223]OVA-LBR$$-*(D0$) &
	! C1$:	.FCTR	SY:[1,223]OVB-LBR$$ &
	! E2$:	.FCTR	SY:[1,223]OVC1-LBR$$ &
	! E3$:	.FCTR	SY:[1,223]OVC2-LBR$$ &
	! D2$:	.FCTR	E2$,E3$ &
	! C2$:	.FCTR	SY:[1,223]OVC-LBR$$-*(D2$) &
	! B0$:	.FCTR	C0$,C1$,C2$ &
	! A0$:	.FCTR	SY:[1,223]ROOT-MYCMN-ROOT$$-LBR$$-*(B0$) &
	!	.ROOT	A0$,RMSALL &
	! &
	! &
	! THERE ARE TWO TYPES OF .FCTR STATEMENTS.  AN AUTOLOAD-FACTOR &
	! CONSISTS OF A LIST OF LABELS SEPARATED BY COMMAS (IE A SET OF THINGS &
	! THAT ARE OVERLAID AGAINST EACH OTHER).  A FILE-FACTOR CONSISTS OF &
	! A LIST OF ITEMS SEPARATED BY HYPHENS;  IT DESCRIBES THE ITEMS THAT &
	! LIVE IN A PARTICULAR OVERLAY; THE ITEMS SEPARATED BY HYPHENS ARE &
	! FILE SPECIFICATIONS, A REFERENCE TO LBR$$, AND PERHAPS A REFERENCE &
	! TO HIGHER-LEVEL OVERLAYS. A0$ IS SPECIAL BECAUSE IT INCLUDES A &
	! REFERENCE TO ROOT$$ AND MAY INCLUDE REFERENCES TO PSECTS TO BE &
	! FORCED TO THE ROOT. &
	! &
	! A FILE-FACTOR CAN HAVE AT MOST ONE CHILD, AND THE CHILD IS AN &
	! AUTOLOAD FACTOR.  THE CHILDREN OF AN AUTOLOAD-FACTOR ARE &
	! FILE-FACTORS.  THESE TWO KINDS OF FACTORS ALTERNATE FROM THE ROOT &
	! OF THE TREE TO THE LEAVES. &
	! &
	! THE LABEL OF A FILE-FACTOR CONSISTS OF A LETTER, A NUMBER, AND $. &
	! THE ODD LETTERS (IE A,C,E,G,I, ETC) ARE USED FOR FILE-FACTORS. &
	! THE LETTER DEPENDS ON THE LEVEL OF THE FACTOR IN THE TREE. &
	! THE NUMBERS ARE ASSIGNED HORIZONTALLY ACROSS THE TREE, STARTING &
	! AT 0. &
	! &
	! THE LABEL OF AN AUTOLOAD-FACTOR ALSO CONSISTS OF A LETTER, A NUMBER, &
	! AND $.  THE EVEN LETTERS (IE B,D,F,H,J, ETC) ARE USED FOR &
	! AUTOLOAD-FACTORS.  AN AUTOLOAD-FACTOR GETS THE SAME NUMBER AS ITS &
	! PARENT, AND THE NEXT LETTER IN THE ALPHABET AFTER ITS PARENT. &
	! FOR EXAMPLE, C2$ IS A FILE-FACTOR, AND ITS CHILD D2$ IS AN &
	! AUTOLOAD-FACTOR. &
	! &
	! IF A FACTOR LINE WOULD BE LONGER THAN 78 COLUMNS, IT IS SPLIT UP &
	! INTO SEVERAL LINES.  SEE COMMENTS ON FNPUT.FCTR% &

10710	IF LEN(RTFIL$) = 0% THEN &
		JUNK% = FNPRT.MSG%("?Program failure in " + &
			PRG.NAM$+IDENT.STG$) &
	\	JUNK% = FNPRT.MSG%("?No input files specified") &
	\	GOT.ERR% = TRUE% &
	\	GOTO 10750 &
		! IF TRANSLATED INPUT FILES ARE NOT FOUND &
		! ABORT NO TASK BUILD &

10720	PSECTLST$ = NL$ &
	\ IF STR% THEN &
		PSECTLST$ = FNGET.PSECT$ &
	\	PSECTLST$ = FNTRANS.PSECT$(PSECTLST$) &
			! IF /STRUCTURE, PROMPT USER FOR ROOT PSECTS. &
			! PUT .PSECT LINES IN ODL FILE AND KEEP A LIST &
			! OF THE PSECTS SPECIFIED FOR THE .ROOT LINE. &

10740	FILELST$(0%) = RTFIL$ &
	\ LBLNUM%(I%) = -1%   FOR I% = 0% TO MAX.LEVEL% &
	\ JUNK% = FNPROC.BRANCH%(0%,STR%) &
		! STORE ROOT FILES FROM DCL IN FIRST ENTRY OF FILELST &
		! FOR .ROOT LEVEL OF OVERLAY TREE. &
		! PROMPT THE USER FOR OVERLAYS AND BUILD THE OVERLAY &
		! DESCRIPTOR FILE. &

10750	RETURN &

11000	! &
	! &
	!	P R O C E S S   C O B O L  S U B R O U T I N E &
	! &
	! &
	! THE COBOL COMPILER SETS UP THE OVERLAYS IN THE .SKL &
	! FILE --> THIS INFORMATION IS NEEDED FOR THE ODL AND CMD FILE. &
	! PRELIN USES C81ODL.TSK (COBOL UTILITY FOR CREATING ODL &
	! AND CMD FILES FROM SKL).  PRELIN CHAINS OFF TO ATPK, WHO &
	! RUNS C81ODL AND THEN CHAINS BACK TO PRELIN. &
	! PRELIN THEN EDITS THE CMD AND ODL FILES, AND CHAINS TO &
	! TKB TO CREATE THE TASK. &
	! &
	! INPUTS: &
	!	USE.FMS.RES%,\ &
	!	FMS.CLUSTER%, \ &
	!	USE.RMS.RES%,  \ &
	!	USE.RMS.SUP%,   +-- SET UP ALREADY BY $RESLIB COMMAND. &
	!	USE.OTS.RES%,  / &
	!	USE.SAM.RES%  / &
	!	OTS.CLUSTER% / &

11005	CHANGE SYS(CHR$(6%)+CHR$(-10%)+"C81$:C81ODL.TSK") TO M% &
	\ M%(1%) = 6% &
	\ M%(2%) = 17% &
	\ M%(3%) = 255% &
	\ M%(4%) = 255% &
	\ M%(I%) = 0% FOR I%=13% TO 22% &
	\ M%(I%) = 0% FOR I%=27% TO 30% &
	\ CHANGE M% TO M$ &
	\ JUNK$ = SYS(M$) &
	! LOOK UP C81$:C81ODL.TSK TO BE SURE IT EXISTS. &
	! ON ERROR PRINT MESSAGE AND EXIT PROGRAM. &

11010	GOT.ERR% = FALSE% &
	\ TEMP$ = FNC81TRANS$(ODL.FIL$,RTFIL$) &
	\ GOTO 32750 IF GOT.ERR% &
	\ OPEN "C81C" + JOB.NUM$ + ".TMP" FOR OUTPUT AS FILE #4% &
	\ PRINT #4%, "!  LINK  is working..." &
	\ PRINT #4%, "$DISABLE KB LOG" &
	\ PRINT #4%, "$ALLOW FATAL ERRORS" &
	\ PRINT #4%, "RUN C81$:C81ODL.TSK" &
	\ PRINT #4%, TEMP$ &
	\ PRINT #4%, "^Z" &
	\ PRINT #4%, "RUN $PIP.SAV" &
	\ PRINT #4%, CMD.FIL$;"=ODL0";JOB.NUM$;".CMD/NOLOG" &
	\ PRINT #4%, "*=";ODL.FIL$;"/RMS/NOLOG" &
	\ PRINT #4%, "*=";CMD.FIL$;"/RMS/NOLOG" &
	\ PRINT #4%, "ODL0";JOB.NUM$;".CMD/DE/NOLOG" &
	\ PRINT #4%, "^Z" &
	\ CLOSE #4% &
		! CREATE TEMPORARY CMD FILE FOR ATPK TO PROCESS &
		! GIVE 'LINK WORKING' MESSAGE; NO LOG TO KB: &
		! C81ODL MUST BE INSTALLED ON $ TO LINK COBOL. &
		! THIS IS HOW C81ODL GETS THE CMD AND ODL FILE BUILT &
		! RENAME THE CMD FILE CREATED TO A TEMP FILE AND &
		! DELETE FIRST CMD FILE. &

11020	IF NOT FMS.QUAL% THEN &
		INP$ = "/NOFMS" &
	ELSE &
		INP$ = "/FMS:" &
		\ INP$ = INP$ + "NO" IF NOT USE.FMS.RES% &
		\ INP$ = INP$ + "RES" &
		\ INP$ = INP$ + "/CLU" IF FMS.CLUSTER% &
		! START BUILDING CORE-COMMON STRING FOR ATPK TO RETURN TO US. &
		! BUILD /NOFMS OR /FMS:[NO]RES QUALIFIER AND /CLU QUALIFIER. &

11025	INP$ = INP$ + "/SAM:" + SAM.RESLIB$ IF USE.SAM.RES% AND SAM.QUAL% &
	\ INP$ = INP$ + "/DEB" IF DEBUG.QUAL% &
	\ INP$ = INP$+SPACECHR$+OUTFIL$+";"+FMS.RESLIB$ &
	\ JUNK$ = SYS(CHR$(8%) + "ATPK C81L" + JOB.NUM$ + ".TMP=C81C" + &
		JOB.NUM$ + ".TMP/LOG" + "/CHA:" + PRG.SPEC$ + ";31000=\" + &
		INP$ + "\") &
	\ JUNK$ = SYS(PRIV.ON$) &
	\ CHAIN "_SY:$ATPK" LINE (30010% + 32767% + 1%) &
	\ STOP &
		! TACK OUTPUT FILESPECS ONTO CORE COMMON STRING FOR ATPK TO &
		! PASS BACK TO US. &
		! LOAD CORE COMMON WITH ATPK CMD LINE. &
		! GAIN PRIVILEGES FOR ATPK. &
		! CHAIN TO ATPK AT SPECIAL ENTRY POINT &
		!  (SET SIGN BIT FOR PRIVILEGES) &

11030	! &
	! &
	! &
	!	B A C K   F R O M   C 8 1 O D L &
	! &
	! &
	! &
	! WHEN WE HAVE REACHED HERE - WE HAVE GONE OFF TO C81ODL &
	! WHICH CREATED A CMD AND ODL FILE.  ATPK WAS INVOKED TO RUN &
	! C81ODL - NOW WE MUST DO SOME EDITING TO THE CMD AND ODL FILES. &
	! WE GOT HERE FROM LINE 1110. &
	! &
	! WE DO NOT HAVE PRIVILEGES ANYMORE WHEN WE ARE HERE &
	! BECAUSE WE HAVE CHAINED BACK FROM ATPK. &
	! INP$ CONTAINS THE CORE COMMON STRING OF THE FORM &
	! /SWITCHES<SPACE>[TASK-FILESPEC][,MAP-FILESPEC];[FMS-RESLIB] &
	! WHERE /SWITCHES ARE &
	!	/SAM:SAMRES	- SORT/MERGE + NAME OF RESLIB &
	!	/FMS:[NO]RES 	- EITHER /FMS OR /NOFMS WILL BE PRESENT ... &
	!	/NOFMS &
	!	/CLU		- FMS LIBRARY IS CLUSTERABLE. &
	!	/DEB		- /DEBUG WAS SPECIFIED. &
	! &
	! THE ODL FILE IS CALLED ODLnnn.TMP, AND THE COMMAND FILE IS &
	! CALLED CMDnnn.TMP, WHERE nnn IS OUR JOB NUMBER.  THE ATPK &
	! LOG FILE IS CALLED C81Lnn.TMP, AND MAY CONTAIN ERROR MESSAGES &
	! THAT WE WILL EXTRACT AND PASS TO THE USER. &
	! &
	! THE ODL AND CMD FILES SO FAR MAKE NO REFERENCE TO FMS, &
	! AND ALSO DO NOT CLUSTER RMS WITH THE OTS.  BUT WE'LL &
	! FIX THAT NOW. &
	! &
	! &
	TEMP% = INSTR(1%,INP$,";") &
	\ FMS.RESLIB$ = RIGHT(INP$,TEMP%+1%) &
	\ INP$ = LEFT(INP$,TEMP%-1%) &
	\ OUTFIL% = INSTR(1%,INP$,SPACECHR$) &
	\ OUTFIL$ = RIGHT(INP$,OUTFIL%+1%) &
	\ OUTFIL$ = CVT$$(OUTFIL$,4%) &
	\ TSKFIL$,STBFIL$ = FNFILESPEC$(OUTFIL$) &
	\ MAPFIL$ = RIGHT(OUTFIL$,LEN(OUTFIL$)-RECOUNT+2%) &
	\ TEMP% = INSTR(1%,STBFIL$,".") &
	\ STBFIL$ = LEFT(STBFIL$,TEMP%-1%) IF TEMP% &
	\ QUALS$ = LEFT(INP$,OUTFIL%-1%) &
	\ TEMP% = INSTR(1%,QUALS$,"/SAM") &
	\ SAM.QUAL% = TEMP%<>0% &
	\ USE.SAM.RES% = SAM.QUAL% &
	\ USE.RMS.RES% = TRUE% IF USE.SAM.RES% &
	\ SAM.RESLIB$ = NL$ &
	\ SAM.RESLIB$ = RIGHT(QUALS$,TEMP%+5%) IF SAM.QUAL% &
	\ SAM.RESLIB$ = LEFT(SAM.RESLIB$,INSTR(1%,SAM.RESLIB$+"/","/")) IF &
		SAM.QUAL% &
	\ FMS.QUAL% = INSTR(1%,QUALS$,"/FMS")<>0% &
	\ USE.FMS.RES% = INSTR(1%,QUALS$,"/FMS:RES")<>0% &
	\ FMS.CLUSTER% = INSTR(1%,QUALS$,"/CLU")<>0% &
	\ OPEN "C81L" + JOB.NUM$ + ".TMP" FOR INPUT AS FILE #4% &
		! HERE IF FINISHED PROCESSING C81ODL BY ATPK (FROM 1110). &
		! FIND SEMICOLON AND EXTRACT FMS RESLIB NAME. &
		! FIND SPACE AND EXTRACT OUTPUT FILES. &
		! EXTRACT QUALIFIERS. &
		! OPEN CMD FILE. &

11040	INPUT LINE #4%, IN.COB$ &
	\ IN.COB$ = CVT$$(IN.COB$,4%) &
	\ TEMP$ = CVT$$(IN.COB$,-2%) &
	\ GOTO 11045 IF LEFT(TEMP$,4%) = "BLD>" &
	\ GOTO 11050 IF (ASCII(IN.COB$) = ASCII("%")) AND &
		(MID(IN.COB$,2%,1%)<>SPACECHR$) AND &
		(MID(IN.COB$,2%,1%)<>TABCHR$) &
	\ GOTO 11050 IF (ASCII(IN.COB$) = ASCII("?")) AND &
		(MID(IN.COB$,2%,1%)<>SPACECHR$) AND &
		(MID(IN.COB$,2%,1%)<>TABCHR$) &
	\ GOTO 11040 &
		! READ ATPK LOG FILE &
		! SEARCH FOR 'BLD>' &
		! FIND '?' OR '%' PROCESS ERROR &
		! GET NEXT INPUT LINE &
		! SHOULD NOT HAVE END OF FILE HERE &

11045	INPUT LINE #4%, IN.COB$ &
	\ IN.COB$ = CVT$$(IN.COB$,4%) &
	\ TEMP$ = CVT$$(IN.COB$,-2%) &
	\ GOTO 11048 IF TEMP$ = "BLD>^Z" &
	\ GOTO 11045 IF LEN(TEMP$)=0% &
	\ GOTO 11045 IF LEFT(TEMP$,4%) = "BLD>" &
	\ JUNK% = FNPRT.MSG%("?" + IN.COB$) &
	\ C81ERR% = TRUE% &
	\ GOTO 11045 &
		! NOW WE HAVE FOUND FIRST BLD>. &
		! LOOK FOR C81ODL ERROR MESSAGES. &
		! IF FOUND FINAL BLD> - NO MORE ERROR MESSAGES. &
		! IF BLANK LINE - GOOD;	GET NEXT LINE. &
		! IF LINE BEGINS WITH BLD> - C81ODL IS PROMPTING &
		! FOR A CONTINUATION LINE. &
		! ELSE - C81ODL ERROR FOUND &
		!    PRINT "?" AND ERROR MESSAGE (STRIPPING OFF <CR><LF>) &
		! SET ERROR FOUND FLAG &

11048	GOTO 32750 IF C81ERR% &
	\ IN.COB$ = CVT$$(IN.COB$,4%) &
	\ INPUT LINE #4%, IN.COB$ &
	\ GOTO 11050 IF (ASCII(IN.COB$) = ASCII("%")) AND &
		(MID(IN.COB$,2%,1%)<>SPACECHR$) AND &
		(MID(IN.COB$,2%,1%)<>TABCHR$) &
	\ GOTO 11050 IF (ASCII(IN.COB$) = ASCII("?")) AND &
		(MID(IN.COB$,2%,1%)<>SPACECHR$) AND &
		(MID(IN.COB$,2%,1%)<>TABCHR$) &
	\ GOTO 11048 &
		! IF HERE, FOUND FINAL BLD> &
		! EXIT IF THERE WAS AN ERROR &
		! NO C81ODL ERRORS - LOOK THROUGH REST OF &
		!    LOG FILE FOR OTHER ERRORS &
		! RESUME 11060 AT END OF FILE &

11050	JUNK% = FNPRT.MSG%(IN.COB$) &
	\ GOTO 32750 &
		! PRINT ? OR % ERROR AND QUIT &

11060	OPEN "CMD0" + JOB.NUM$ + ".TMP" FOR INPUT AS FILE #2% &
	\ OPEN "CMD0" + JOB.NUM$ + ".TMP" FOR OUTPUT AS FILE #3% &
	\ ODLNAM$ = "ODL0" + JOB.NUM$ &
	\ OTS.RESLIB$, RMS.RESLIB$ = NL$ &
		! NO ERRORS FROM C81ODL. &
		! OPEN THE COMMAND FILE TWICE TO EDIT IT. &
		! BUILD TEMP ODL FILENAME USED IN CMD FILE (ODL0nn) &
		! C81ODL CREATED THIS CMD FILE. &

11070	INPUT LINE #2%, C81CMD$ &
	\ C81CMD$ = CVT$$(C81CMD$,4%) &
	\ GOTO 11200 IF C81CMD$ = "//" &
	\ GOTO 11080 IF LEFT(C81CMD$,5%) = "LIBR=" &
	\ C81CMD$ = FNC81CMD$(C81CMD$,ODLNAM$) &
		IF INSTR(1%,C81CMD$,"="+ODLNAM$) &
	\ PRINT #3%, C81CMD$ &
	\ GOTO 11070 &
		! READ NEXT LINE FROM COMMAND FILE &
		! ON TERMINATING LINE ("//") GOTO 11200. &
		! ON LIBRARY LINE ("LIBR=") GOTO 11080. &
		! LOOK FOR "=ODL0nn" (INDICATES TKB 'OUT=IN' CMD LINE) &
		! REPLACE OUTPUT FILENAME(S) &
		!	IF 'OUT=IN' CMD LINE &
		! COPY LINE TO OUTPUT FILE &
		! GO GET ANOTHER CMD LINE &

11080	COLON.POS% = INSTR(6%,C81CMD$,":") &
	\ LIBNAME$ = MID(C81CMD$,6%,COLON.POS%-6%) &
	\ IF LEFT(LIBNAME$,3%)="C81" THEN &
		OTS.RESLIB$ = LIBNAME$ &
	ELSE IF LEFT(LIBNAME$,3%)="RMS" THEN &
		RMS.RESLIB$ = LIBNAME$ &
	ELSE &
		PRINT #3%, C81CMD$ &
		! WE HAVE A LIBR= LINE. &
		! EXTRACT THE NAME OF THE RESIDENT LIBRARY. &
		! DECIDE IF IT'S THE OTS OR RMS LIBRARY. &
		! IF IT'S SOMETHING ELSE, WE'RE CONFUSED, BUT LET'S &
		! PLAY IT SAFE AND COPY THE LINE INTO THE OUTPUT FILE. &

11090	GOTO 11070 &

11200	OTS.CLUSTER% = TRUE% &
	\ USE.OTS.RES% = LEN(OTS.RESLIB$) <> 0% &
	\ USE.RMS.RES% = LEN(RMS.RESLIB$) <> 0% &
	\ GOSUB 10200 &
	\ CLOSE #2% &
	\ GOTO 32700 IF (NOT FMS.QUAL%) &
	\ OPEN "ODL0" + JOB.NUM$ + ".TMP" FOR INPUT AS FILE #2% &
	\ OPEN "ODL0" + JOB.NUM$ + ".TMP" FOR OUTPUT AS FILE #7% &
		! FINISH UP THE CMD FILE, WITH LIBR= OR CLSTR= LINES. &
		! IF NO FMS - DONE, GO AND TKB. &
		! OPEN ODL FILE TWICE FOR EDITING. &

11210	INPUT LINE #2%, C81CMD$ &
	\ C81CMD$ = CVT$$(C81CMD$,4%) &
	\ IF INSTR(1%,C81CMD$,"OBJRT$:")<>0% THEN &
		PRINT #7%, C81CMD$; "-FMS$$" &
	\	PRINT #7%, &
		"FMS$$:	.FCTR LB:HLLDFN.OBJ-LB:HLLCOB.OBJ-LB:FDVDRS.OBJ"; &
	\	PRINT #7%, "-LB:FDVLIB.OLB/LB"; IF (NOT DEBUG.QUAL%) AND &
			NOT USE.FMS.RES% &
	\	PRINT #7%, "-LB:FDVRDB.OLB/LB"; IF DEBUG.QUAL% AND &
			NOT USE.FMS.RES% &
	\	PRINT #7% &
	\	GOTO 11210 &
		! AT END OF FILE RESUME 32700 - TKB &
		! IF WE FIND OBJRT$: LINE, &
		!	ADD LINE FOR FMS AT END OF LIBRARY LINE. &
		!	MAKE A NEW LINE FOR FMS$$ AND THE &
		!	FMS .OBJ AND .OLB FILES THAT NEED TO BE BROUGHT IN. &

11220	PRINT #7%, C81CMD$ &
	\ GOTO 11210 &

14000	! &
	! &
	! &
	!	P R O G R A M M E R    D E F I N E D &
	!		F U N C T I O N S &
	! &
	! &

14100	DEF* FNDO.LNK.FILE% &
	! &
	! &
	!	F U N C T I O N   F N D O . L N K . F I L E % &
	! &
	! &
	! DO THE .LNK FILE. &
	! INPUTS: &
	!	.LNK FILE IS OPEN ON CHANNEL 3. &
	! &
	! OUTPUTS: &
	!	ODL AND CMD FILES HAVE BEEN PRODUCED, UNLESS ERROR OCCURRED. &
	!	GOT.ERR% = TRUE% IF ERROR OCCURRED. &
	!	COMMAND$ = LAST COMMAND READ FROM .LNK FILE. &
	!		(SHOULD BE *EOF*.) &
	!	PARM$ = PARAMETER OF LAST COMMAND READ FROM .LNK FILE. &
	! &
	! THIS IS A RECURSIVE FUNCTION TO ALLOW FOR NESTED $IF-$ELSE-$ENDIF &
	! CONSTRUCTS. &
	! THE FUNCTION EXECUTES THE LINES UP TO THE NEXT UNMATCHED &
	! $ELSE, $ENDIF, OR *EOF*.  THE FUNCTION &
	! LEAVES THE UNPROCESSED COMMAND IN COMMAND$ AND PARM$. &

14110	IN.LNK$ = FNGET.LNK.LINE$ &
	\ WHILE (COMMAND$<>"$ENDIF") AND (COMMAND$<>"$ELSE") AND &
		(COMMAND$<>"*EOF*") &
	\	GOTO 14130 IF COMMAND$<>"$IF" &
	\	GOSUB 10300 &
	\	GOTO 14180 IF GOT.ERR% &
	\	GOTO 14120 IF SKIP% &
	\	JUNK% = FNDO.LNK.FILE% &
	\	GOTO 14199 IF GOT.ERR% &
	\	JUNK% = FNSKIP.LNK% IF COMMAND$="$ELSE" &
	\	GOTO 14199 IF GOT.ERR% &
	\	GOTO 14180 IF COMMAND$<>"$ENDIF" &
	\	GOTO 14140 &
		! GET THE FIRST LINE, AND START TO LOOP UNTIL &
		! WE MEET A "*EOF*" OR UNMATCHED "$ENDIF" OR "$ELSE". &
		! IF THE COMMAND ISN'T "$IF" THEN GO DO IT. &
		! ELSE &
		!	EVALUATE THE CONDITION. &
		! 	IF THE CONDITION IS FALSE, GO SKIP. &
		!	ELSE EXECUTE UP TO MATCHING $ELSE OR $ENDIF. &
		!	IF IT'S A $ELSE, SKIP TO $ENDIF. &

14120		JUNK% = FNSKIP.LNK% &
	\	GOTO 14199 IF GOT.ERR% &
	\	JUNK% = FNDO.LNK.FILE% IF COMMAND$="$ELSE" &
	\	GOTO 14199 IF GOT.ERR% &
	\	GOTO 14180 IF COMMAND$<>"$ENDIF" &
	\	GOTO 14140 &
		!	CONDITION IS FALSE. &
		!	SKIP TO MATCHING $ELSE OR $ENDIF. &
		!	IF IT'S A $ELSE, EXECUTE UP TO MATCHING $ENDIF. &

14130		GOT.ERR% = FALSE% &
	\	IF COMMAND$=NL$ THEN &
			PRINT #OUTPUT.CHANNEL%, IN.LNK$ &
	\		GOTO 14140 &
		! IT'S NOT A $IF. &
		! IF IT'S NOT A COMMAND THEN &
		!	JUST COPY THE LINE TO THE .ODL OR .CMD FILE. &

14132		IF COMMAND$="$RESLIB" THEN &
			GOSUB 9100 &
	\		GOTO 14199 IF GOT.ERR% &
	\		GOTO 14140 &
		! IF IT'S A $RESLIB COMMAND, EXECUTE IT. &

14133		IF COMMAND$="$ERROR" THEN &
			JUNK% = FNPRT.MSG%("?"+PARM$) &
			\ GOT.ERR% = TRUE% &
			\ GOTO 14199 &
		! IF IT'S A $ERROR COMMAND THEN &
		!	PRINT THE MESSAGE AND EXIT PROGRAM. &

14134		IF COMMAND$="$OPTION" THEN &
			OUTPUT.CHANNEL% = 3% &
	\		GOTO 14140 &
		! IF IT'S A $OPTION COMMAND &
		!	SET UP THE PROPER OUTPUT CHANNEL TO USE. &

14136		IF COMMAND$="$ODL" THEN &
			OUTPUT.CHANNEL% = 7% &
	\		GOTO 14140 &
		! IF IT'S A $ODL COMMAND &
		!	SET UP THE PROPER OUTPUT CHANNEL TO USE. &

14138		GOTO 14180 &
		! IF IT'S AN ILLEGAL COMMAND THEN &
		!	GO PRINT ERROR MESSAGE AND ABORT. &

14140		IN.LNK$ = FNGET.LNK.LINE$ &
	\	NEXT &
	\ GOTO 14199 &
		! GET NEXT LINE FROM .LNK FILE, AND LOOP ONWARD. &
		! ON REACHING *EOF* OR UNMATCHED $ENDIF OR $ELSE, &
		! RETURN. &

14180	JUNK% = FNBAD.LNK.LINE% (IN.LNK$) &
	\ GOT.ERR% = TRUE% &

14199	FNDO.LNK.FILE% = JUNK% &
		! Meaningless return value. &
	\ FNEND &

14200	DEF* FNSKIP.LNK% &
	! &
	! &
	!	F U N C T I O N   F N S K I P . L N K % &
	! &
	! &
	! SKIP LINES OF .LNK FILE UP TO NEXT *EOF* OR UNMATCHED &
	! $ELSE OR $ENDIF COMMAND. &
	! &
	! INPUTS: &
	!	.LNK FILE IS OPEN ON CHANNEL 3. &
	! &
	! OUTPUTS: &
	!	GOT.ERR% = TRUE% IF ERROR OCCURRED. &
	!	COMMAND$ = LAST COMMAND READ FROM .LNK FILE. &
	!	PARM$ = PARAMETER OF LAST COMMAND READ FROM .LNK FILE. &
	! &
	! THIS IS A RECURSIVE FUNCTION TO ALLOW FOR NESTED $IF-$ELSE-$ENDIF &
	! CONSTRUCTS. &

14210	IN.LNK$ = FNGET.LNK.LINE$ &
	\ WHILE (COMMAND$<>"$ENDIF") AND (COMMAND$<>"$ELSE") AND &
		(COMMAND$<>"*EOF*") &
	\	IF COMMAND$="$IF" THEN &
			JUNK% = FNSKIP.LNK% &
	\		GOTO 14299 IF GOT.ERR% &
	\		JUNK% = FNSKIP.LNK% IF COMMAND$="$ELSE" &
	\		GOTO 14299 IF GOT.ERR% &
	\		GOTO 14280 IF COMMAND$<>"$ENDIF" &
		! REPEAT UNTIL WE FIND A "*END*" OR AN UNMATCHED "$ELSE" OR &
		! "$ENDIF". &
		! 	IF COMMAND IS "$IF" THEN &
		!		SKIP UNTIL MATCHING "$ELSE" OR "$ENDIF". &
		!		IF IT'S A "$ELSE" THEN SKIP UNTIL MATCHING &
		!		"$ENDIF". &
		!		ABORT IF IT'S A SECOND "$ELSE" OR A PREMATURE &
		!		"*EOF*". &

14220		IN.LNK$ = FNGET.LNK.LINE$ &
	\	NEXT &
	\ GOTO 14299 &
		! GET NEXT LINE OF .LNK FILE. &
		! LOOP ONWARD. &
		! ON EXITING LOOP, RETURN. &

14280	JUNK% = FNBAD.LNK.LINE%(IN.LNK$) &
	\ GOT.ERR% = TRUE% &

14299	FNSKIP.LNK% = JUNK% &
		! Meaningless return value. &
	\ FNEND &

15100	DEF* FNTRANS$(TEXT$) &
	! &
	! &
	!	F U N C T I O N   F N T R A N S $ &
	! &
	! &
	! THIS FUNCTION IS FOR TRANSLATING THE INPUT STRING. &
	! COMMAS THAT SEPARATE THE FILESPECS ARE REPLACED WITH "-". &
	! THE FILESPECS ARE EXPANDED TO FULL FORM TO OVERRIDE TKB'S &
	! STICKY DEFAULTS. &

15105	BLD.STR$, FILESPEC$ = NL$ &
		! TEXT IS THE INPUT FOR OVERLAY FILES &
		! INITIALIZE VARIABLES &

15110	IF LEN(TEXT$) <> 0% THEN &
		FILESPEC$ = FNFILESPEC$(TEXT$) &
	\ 	BLD.STR$ = BLD.STR$ + "-" IF LEN(BLD.STR$) &
	\	BLD.STR$ = BLD.STR$ + FILESPEC$ &
	\	TEXT$ = RIGHT(TEXT$,LEN(TEXT$)-RECOUNT+2%) &
	\	GOTO 15110 &
		! RETURN NULL STRING IF NO INPUT &
		! EXTRACT A FILESPEC AND EXPAND IT TO FULL FORM &
		! BUILD THE NEW STRING ADDING THE NEWEST FILESPEC &
		! RESET STRING TO EVERYTHING LEFT TO SCAN. &
		! (RECOUNT IS RETURNED BY FNFILESPEC$) &
		! GO AND GET MORE INPUT &

15120	FNTRANS$ = BLD.STR$ &
	\ FNEND &

16000	DEF* FNGET$(PROMPT$) &
	! &
	! &
	!  	F U N C T I O N    F N G E T $ &
	! &
	! &
	!  THIS FUNCTION IS FOR PROMPTING AND GETTING AN INPUT LINE FROM &
	! THE USER.  CHECKING FOR AN EXCLAMATION POINT AND IGNORING THAT AS A &
	! COMMENT.  TESTING FOR "-" AND JUST CONCATENATING &
	! THE REST OF THE STRING ON BY PROMPTING FOR MORE. &

16105	JUNK% = FNPROMPT%(PROMPT$) &
	\ TXT.STR$ = NL$ &
	\ EXCLAIM% = 0% &
		! DISPLAY THE PROMPT &
		! INITIALIZE VARIABLES &

16110	INPUT LINE #1%, TXT.LIN$ &
	\ PRINT #1% IF CCPOS(1%) &
	\ TXT.LIN$ = CVT$$(TXT.LIN$,2%+4%+32%) &
	\ GOTO 16130 IF LEN(XLATE(TXT.LIN$, SPACE$(32%))) <> 0% &
	\ EXCLAIM% = INSTR(1%,TXT.LIN$,"!") &
	\ TXT.LIN$ = LEFT(TXT.LIN$,EXCLAIM%-1%)  IF EXCLAIM% &
	\ LAST.CHR$ = RIGHT(TXT.LIN$,LEN(TXT.LIN$)) &
	\ GOTO 16120 IF LAST.CHR$ <> "-" &
	\ TXT.STR$ = TXT.STR$ + LEFT(TXT.LIN$,LEN(TXT.LIN$)-1%) &
	\ JUNK% = FNPROMPT%(SPACE$((LEVEL%-1%)*2%) + "Continue: ") &
	\ GOTO 16110 &
		! GET USER INPUT FROM TERMINAL (COMMAND LINE) &
		! STRIP OFF ALL EXCESS CHARACTERS &
		! IF ANY CONTROL CHARACTERS (< 32 ASCII) PRESENT, &
		! GO PRINT MESSAGE AND REPROMPT &
		! LOOK FOR EXCLAMATION POINT SIGNIFYING A COMMENT &
		! SET UP LAST CHARACTER VALUE &
		! IF LAST CHAR IS A "-" JUST BUILD THE STRING ON &
		! AND PROMPT FOR MORE &
		! GET NEXT INPUT LINE &

16120	GOTO 16200 IF LAST.CHR$ <> "," &
	\ TXT.STR$ = TXT.STR$ + TXT.LIN$ &
	\ JUNK% = FNPROMPT%(SPACE$((LEVEL%-1%)*2%) + "Continue: ") &
	\ GOTO 16110 &
		! TESTING FOR LAST CHAR TO BE A ",". &
		! BUILD THE COMMAND STRING, UNLESS INPUT WAS JUST A ",". &
		! PROMPT FOR MORE INPUT AND GET NEXT INPUT LINE. &

16130	JUNK% = FNPRT.MSG%("?Non-printable character") &
	\ GOTO 16105 &
		! CONTROL CHARS FOUND - PRINT MESSAGE AND GO REPROMPT &

16200	FNGET$ = TXT.STR$ + TXT.LIN$ &
	\ FNEND &
		! NO "-" OR "," FOR LAST CHAR &
		! JUST CONCATENATE STRING ON AND END &

16400	DEF* FNC81TRANS$(ODL.FIL$,SKL.FILES$) &
	! &
	! &
	!	F U N C T I O N   F N C 8 1 T R A N S $ &
	! &
	! &
	! THIS FUNCTION IS FOR TRANSLATING THE COBOL INPUT &
	! FILES TO BE PASSED TO C81ODL.  THE DEVICE AND PPN &
	! ARE FORCED ON TO AVOID STICKINESS. &
	! &
	! INPUTS: &
	!	ODL.FIL$ = filespec for ODL file to generate. &
	!	SKL.FILES$ = comma-separated list of one or more SKL input &
	!		files.  (.SKL is default filetype.) &
	!	USE.FMS.RES%, \ &
	!	FMS.CLUSTER%,  \ &
	!	USE.RMS.RES%,   +-- SET UP ALREADY BY $RESLIB COMMAND. &
	!	USE.OTS.RES%,  / &
	!	OTS.CLUSTER%  / &
	!	USE.SAM.RES% / &
	!	DEBUG.QUAL%	indicates whether user specified /DEBUG. &

16410	BLD.STR$, FILESPEC$ = NL$ &
		! INITIALIZE VARIABLES &

16420	IF LEN(SKL.FILES$) THEN &
		FILESPEC$ = FNFILESPEC$(SKL.FILES$) &
	\ 	BLD.STR$ = BLD.STR$ + ",-" + CRLF$ IF LEN(BLD.STR$) &
	\ 	BLD.STR$ = BLD.STR$ + FILESPEC$ &
	\ 	SKL.FILES$ = RIGHT(SKL.FILES$,LEN(SKL.FILES$)-RECOUNT+2%) &
	\	GOTO 16420 &
		! TRANSLATE FILESPEC TO GET EXPLICIT DEVICE AND PPN. &
		! BUILD THE STRING WITH A COMMA AND CONTINUATION CHARACTER &
		! AND <CR><LF>, AND PUT ON FILESPECS. &
		! GET THE REST OF THE STRING TO TRANSLATE. &
		! (RECOUNT IS RETURNED BY FNFILESPEC$) &

16430	BLD.STR$ = ODL.FIL$ + "=" + BLD.STR$ &
	\ BLD.STR$ = BLD.STR$+"/MAP" IF LEN(MAPFIL$) &
	\ BLD.STR$ = BLD.STR$+"/RES" IF USE.OTS.RES% &
	\ BLD.STR$ = BLD.STR$+"/IO:MEMRES:"+RMS.RESLIB$ IF USE.RMS.RES% &
	\ BLD.STR$ = BLD.STR$+"/DEB" IF DEBUG.QUAL% &
		! SPECIFY /MAP IF ANY MAP FILE SPECIFIED. &
		! SPECIFY RESIDENT OTS IF RESIDENT OTS BEING USED. &
		! SPECIFY RESIDENT RMS IF RMS RESLIB BEING USED. &
		! SPECIFY DEBUG IF REQUESTED. &

16450	IF LEN(BLD.STR$) > 160% THEN &
		JUNK% = FNPRT.MSG%("?Command too long") &
	\ GOT.ERR% = TRUE% &
		! THE COMMAND STRING MUST BE UNDER 160 CHARACTERS, &
		! COUNTING CONTINUATION LINES, ELSE ERROR AND NO TKB. &

16460	FNC81TRANS$ = BLD.STR$ &
	\ FNEND &

16500	DEF* FNTRANS.PSECT$(PSECTLST$) &
	! &
	! &
	!	F U N C T I O N   F N T R A N S . P S E C T $ &
	! &
	! &
	! THIS FUNCTION TRANSLATES THE PSECT LIST. &
	! INPUTS: &
	!	PSECTLST$	HAS THE FORM [psectname[,...]] &
	!			IE ZERO OR MORE PSECT NAMES SEPARATED &
	!			BY COMMAS &
	!	ODL FILE OPEN ON CHANNEL 3 &
	! OUTPUTS: &
	!	RETURN VALUE	HAS THE FORM [-psectname]... &
	!			IE THE SAME PSECT NAMES, BUT EACH PRECEEDED &
	!			BY A HYPHEN &
	!	FOR EACH PSECT NAME, A LINE HAVING THE FOLLOWING FORM &
	!	HAS BEEN PRINTED IN THE ODL FILE &
	!		.PSECT	psectname &
	! SIDE EFFECTS: &
	!	TEMP$, PSECT$, PSECT.BEG%, PSECT.END% ARE RANDOM &

16505	TEMP$ = NL$ &
	\ PSECT.BEG% = 1% &
	\ PSECT.END% = 0% &
	\ PSECTLST$ = PSECTLST$ + "," &
		! INITIALIZE VARIABLES &

16510	GOTO 16520 IF PSECT.BEG% >= LEN(PSECTLST$) &
	\ PSECT.END% = INSTR(PSECT.BEG%,PSECTLST$,",") &
	\ PSECT$ = MID(PSECTLST$,PSECT.BEG%,(PSECT.END%-PSECT.BEG%)) &
	\ PRINT #7%, TABCHR$; ".PSECT"; TABCHR$; PSECT$ &
	\ TEMP$ = TEMP$ + "-" + PSECT$ &
	\ PSECT.BEG% = PSECT.END% + 1% &
	\ GOTO 16510 &
		! IF NOTHING IN PSECTLST, SKIP OVER PRINTING &
		!  ANYTHING IN THE ODL FILE &
		! ADD A COMMA TO THE END OF PSECTLST TO KNOW WHEN TO END &
		! SEARCH FOR THE "," IN PSECTLST &
		! SET PSECT$ TO ONE PSECT NAME FOUND AT A TIME &
		! PRINT ".PSECT name" IN ODL FILE, SEPARATED BY "-" &
		! RESET PSECT.BEG TO THE NEXT PSECT NAME IN LIST &
		! GET NEXT PSECT NAME &

16520	FNTRANS.PSECT$ = TEMP$ &
	\ FNEND &
		! SET PSECT LIST TO THE NEWLY BUILT STRING &
		! THERE MAY BE NOTHING IN THE STRING &

16600	DEF* FNFILESPEC$(FILESPEC$) &
	! &
	! &
	!	F U N C T I O N   F N F I L E S P E C $ &
	! &
	! &
	! THIS FUNCTION EXPANDS A FILESPEC TO ITS FULL FORM WITH PHYSICAL &
	! DEVICE AND PPN.  THE INPUT FILESPEC MUST BE VALID OR WE BLOW UP. &
	! RECOUNT IS RETURNED AS THE NUMBER OF CHARACTERS NOT SCANNED. &
	! &
	! SIDE EFFECTS: &
	!	PPN$, DEV$, M%, S1% RANDOM &
	! &
	! ************************************************** &
	! ******************** N O T E ********************* &
	! ************************************************** &
	! *                                                * &
	! * THIS FUNCTION DOES NOT PUT AN UNDERSCORE IN    * &
	! * THE RETURNED FILESPEC BECAUSE TKB BARFS ON     * &
	! * UNDERSCORES.  THEREFORE, LOGICAL NAMES CAN     * &
	! * BE TRANSLATED TWICE.  TKB SHOULD BE FIXED.     * &
	! *                                                * &
	! ************************************************** &

16610	DEV$ = "SY:" &
	\ PPN$ = OURPPN$ &
	\ CHANGE SYS(CHR.6$+CHR$(-23%)+FILESPEC$) TO M% &
	\ S1% = M%(29%) + SWAP%(M%(30%)) &
	\ IF ((S1% AND 1%) = 0%) AND ((S1% AND 8192%) = 0%) THEN &
		FILESPEC$ = NL$ &
	\	GOTO 16630 &
		! SET DEFAULT DEVICE TO SY: &
		! SET DEFAULT PPN TO THE ONE WE'RE RUNNING UNDER &
		! DO FSS SYSTEM CALL &
		! IF NO FILE NAME OR DEVICE SPECIFIED &
		! 	RETURN NULL STRING &

16615	IF (S1% AND 8192%) <> 0% THEN &
		DEV$ = CHR$(M%(23%)) + CHR$(M%(24%)) &
	\	DEV$ = DEV$ + NUM1$(M%(25%))  IF M%(26%) &
	\	DEV$ = DEV$ + ":" &
		! GET THE DEVICE SPECIFIED &
		! (TKB WILL NOT ALLOW AN UNDERSCORE WITH DEVICE NAMES) &

16620	PPN$ = "[" + NUM1$(M%(6%)) + "," + NUM1$(M%(5%))+ "]" IF S1% AND 128% &
	\ FILESPEC$ = DEV$ + PPN$ &
	\ FILESPEC$ = FILESPEC$ + &
		 RAD$(M%(7%) + SWAP%(M%(8%))) + &
		 RAD$(M%(9%) + SWAP%(M%(10%))) 	IF (S1% AND 1%) &
	\ FILESPEC$=FILESPEC$+ "."+RAD$(M%(11%)+SWAP%(M%(12%))) IF S1% AND 8% &
	\ FILESPEC$ = CVT$$(FILESPEC$,2%) &
		! IF PPN WAS SPECIFIED, EXTRACT IT &
		! CREATE A STRING CONTAINING THE DEVICE, PPN AND FILE &
		! SPECIFICATION.  (STRIP OFF ALL TABS AND SPACES) &

16630	FNFILESPEC$ = FILESPEC$ &
	\ FNEND &

16700	DEF* FNGET.PSECT$ &
	! &
	! &
	!	F U N C T I O N   F N G E T . P S E C T $ &
	! &
	! &
	! THIS FUNCTION PROMPTS FOR AND GETS A VALID LIST OF PSECTS &
	! FROM THE USER.  IF THE USER TYPES AN INVALID LIST OF PSECTS, &
	! FNGET.PSECT$ PRINTS AN ERROR MESSAGE AND REPROMPTS. &
	! FNGET.PSECT$ RETURNS A STRING OF THE FORM &
	!	[psectname[,...]] &
	! SIDE EFFECTS: &
	!	TEXT$, BLD.STR$, I%, C%, PSECT.BEG%, PSECT.END% RANDOM &

16710	TEXT$ = FNGET$("Root COMMON areas: ") &
	\ PSECT.BEG% = 1% &
	\ BLD.STR$ = NL$ &
		! PROMPT FOR AND READ THE LIST OF PSECT NAMES &
		! START AT BEGINNING OF INPUT STRING &

16730	GOTO 16790  IF PSECT.BEG% > LEN(TEXT$) &
	\ PSECT.END% = INSTR(PSECT.BEG%,TEXT$,",") &
	\ PSECT.END% = LEN(TEXT$) + 1%  IF (PSECT.END% = 0%) &
	\ PSECT.LEN% = PSECT.END% - PSECT.BEG% &
	\ GOTO 16750  IF PSECT.LEN% = 0% &
	\ PSECT$ = MID(TEXT$,PSECT.BEG%,PSECT.LEN%) &
	\ FOR I% = 1% TO PSECT.LEN% &
	\	C% = ASCII(MID(PSECT$, I%, 1%)) &
	\	GOTO 16740  IF C% >= ASCII("0") AND C% <= ASCII("9") &
	\	GOTO 16740  IF C% >= ASCII("A") AND C% <= ASCII("Z") &
	\	GOTO 16740  IF C% = ASCII("$") &
	\	JUNK% = FNPRT.MSG%("?Illegal character - " + CHR$(C%)) &
	\	GOTO 16710 &
			! EXIT LOOP IF WE'VE PROCESSED WHOLE STRING &
			! FIND NEXT COMMA, OR END-OF-STRING &
			! GET LENGTH OF NEXT PSECT NAME &
			! IF ZERO LENGTH, GO PRINT MESSAGE AND REPROMPT &
			! GET THE PSECT NAME AND CHECK THAT &
			! ALL CHARACTERS ARE 0-9, A-Z, OR $ &
			! IF NOT, PRINT MESSAGE AND GO REPROMPT &

16740	NEXT I% &
	\ BLD.STR$ = BLD.STR$ + ","  IF LEN(BLD.STR$) <> 0% &
	\ BLD.STR$ = BLD.STR$ + LEFT(PSECT$, 6%) &
	\ PSECT.BEG% = PSECT.END% + 1% &
	\ GOTO 16730 &
		! LOOP FOR ALL CHARACTERS OF PSECT NAME &
		! TACK PSECT NAME ONTO END OF LIST, TRIMMING TO 6 CHARS &
		! FIND BEGINNING OF NEXT PSECT NAME &
		! LOOP FOR ALL PSECT NAMES &

16750	JUNK% = FNPRT.MSG%("?Null PSECT name") &
	\ GOTO 16710 &
		! PSECT NAME HAS ZERO LENGTH - PRINT MESSAGE AND GO REPROMPT &

16790	FNGET.PSECT$ = BLD.STR$ &
	\ FNEND &

16800	DEF* FNGET.OVLY$(LEVEL%) &
	! &
	! &
	!	F U N C T I O N   F N G E T . O V L Y $ &
	! &
	! &
	! THIS FUNCTION PROMPTS FOR AND GETS A VALID OVERLAY LINE &
	! FROM THE USER.  THIS INCLUDES CHECKING THAT THE FILES EXIST &
	! IF THE USER TYPES AN INVALID LINE,  FNGET.OVLY$ PRINTS AN &
	! ERROR MESSAGE AND REPROMPTS. &
	! &
	! INPUTS: &
	!	TERMINAL IS OPEN ON CHANNEL 1 &
	!	LEVEL% = CURRENT OVERLAY LEVEL, WHERE 0% MEANS ROOT &
	!	MAX.LEVEL% = MAXIMUM ALLOWABLE LEVEL &
	! &
	! OUTPUTS: &
	! 	RETURN VALUE HAS THE FORM [filespec[,...]] &
	!	PLUS% = 0 IF LINE DID NOT END WITH A PLUS SIGN, &
	!		-1 IF IT DID (AND PLUS SIGN HAS BEEN STRIPPED OFF) &
	!		(THIS WON'T OCCUR IF LEVEL% = MAX.LEVEL%) &
	! &
	! SIDE EFFECTS: &
	!	TEMP$, FILESPEC.BEG%, OVERLAY$ RANDOM &

16810	PLUS% = FALSE% &
	\ OVERLAY$ = FNGET$(SPACE$((LEVEL%-1%)*2%) + "Overlay:  ") &
	\ GOTO 16890 IF OVERLAY$ = NL$ &
		! INITALIZE VARIABLES; PLUS, FLAG FOR "+" &
		! PROMPT FOR OVERLAY STRUCTURE &
		! GET THE RESPONSE TO OVERLAY PROMPT, STRIP IT, &
		!  CHECK FOR EXCLAMATION POINT, "-", OR "," &
		! AND PROMPT FOR CONTINUATION. &
		! RETURN IMMEDIATELY IF NULL LINE &

16830	LAST.CHR$ = RIGHT(OVERLAY$,LEN(OVERLAY$)) &
	\ IF LAST.CHR$ = "+" AND LEN(OVERLAY$) <> 1% THEN &
		PLUS% = TRUE% &
	\	OVERLAY$ = LEFT(OVERLAY$,LEN(OVERLAY$)-1%) &
	\	IF LEVEL% >= MAX.LEVEL% THEN &
		      	JUNK% = FNPRT.MSG%("?Overlay tree has "+ &
				"too many levels") &
	\ 		GOTO 16810 &
		! IF LAST CHAR IS "+", SET FLAG, TAKE OFF "+" &
		! IF THIS WOULD CAUSE OVERLAYS TO NEST TOO DEEPLY, GIVE &
		! MESSAGE AND GO REPROMPT &

16835	IF INSTR(1%,OVERLAY$,"/") THEN &
		JUNK% = FNPRT.MSG%("?Illegal qualifier") &
	\	GOTO 16810 &
		! IF THERE ARE ANY SLASHES, GIVE ERROR MESSAGE AND REPROMPT &

16836	IF INSTR(1%,OVERLAY$,"(") THEN &
		JUNK% = FNPRT.MSG%("?Illegal character - (") &
	\	GOTO 16810 &
		! IF THERE IS A LEFT PARENTHESIS, GIVE ERROR MESSAGE AND &
		! REPROMPT &

16837	IF INSTR(1%,OVERLAY$,")") THEN &
	 	JUNK% = FNPRT.MSG%("?Illegal character - )") &
	\	GOTO 16810 &
		! IF THERE IS A RIGHT PARENTHESIS, GIVE ERROR MESSAGE &
		! AND REPROMPT &

16838	IF INSTR(1%,OVERLAY$,"+") THEN &
		JUNK% = FNPRT.MSG%("?Illegal character - +") &
	\	GOTO 16810 &
		! IF THERE IS A MISPLACED PLUS SIGN, GIVE ERROR MESSAGE &
		! AND REPROMPT &

16840	FILESPEC.BEG% = 1% &
		! FIRST FILESPEC BEGINS AT CHARACTER POSITION 1. &

16845	FILESPEC$ = RIGHT(OVERLAY$,FILESPEC.BEG%) &
	\ CHANGE SYS(CHR$(6%)+CHR$(-23%)+FILESPEC$) TO M% &
		! MAKE FIRST GUESS ABOUT THE NEXT FILESPEC &
		! FSS THE NEXT FILESPEC &
		! RESUME 16880 IF ERROR &

16848	FILESPEC.LEN% = LEN(FILESPEC$) - RECOUNT &
	\ FILESPEC$ = LEFT(FILESPEC$,FILESPEC.LEN%) &
	\ FILESPEC.END% = FILESPEC.BEG% + FILESPEC.LEN% &
	\ IF FILESPEC.END% <= LEN(OVERLAY$) THEN &
		DELIM$ = MID(OVERLAY$,FILESPEC.END%,1%) &
	\	IF DELIM$ <> "," THEN &
			JUNK% = FNPRT.MSG%("?Illegal character - " + DELIM$) &
	\		GOTO 16810 &
		! GET THE AMOUNT OF TEXT FSS ACTUALLY ATE &
		! PRUNE THE FILESPEC &
		! GET CHARACTER POSITION OF DELIMITER &
		! IF INVALID DELIMITER THEN PRINT MESSAGE AND &
		! GO REPROMPT &
		! (RECOUNT IS RETURNED BY FNFILESPEC$) &

16849	IF FILESPEC.LEN% = 0% THEN &
		JUNK% = FNPRT.MSG%("?Null file specification") &
	\	GOTO 16810 &
		! IF NULL FILESPEC, PRINT ERROR MESSAGE AND GO REPROMPT &

16850	S1% = M%(29%) + SWAP%(M%(30%)) &
	\ IF S1% < 0% THEN &
		JUNK% = FNPRT.MSG%(FNGET.ERR$(6%) + " - " + FILESPEC$) &
	\	GOTO 16810 &
		! GET THE DESCRIPTIVE FLAG WORD &
		! IF DEVICE NAME NOT TRANSLATED THEN SAY &
		! "?Not a valid device", GO REPROMPT &

16855	IF (S1% AND (2% OR 4% OR 32% OR 64% OR 256% OR 512%)) <> 0% THEN &
		JUNK% = FNPRT.MSG%("?Wildcards not allowed - " + FILESPEC$) &
	\	GOTO 16810 &
		! IF ANY WILDCARDS, GIVE MESSAGE, GO REPROMPT &

16858	IF ((S1% AND 4096%) <> 0%) AND NOT ((STATUS AND 255%) = 0%) THEN &
		JUNK% = FNPRT.MSG%("?Device must be disk - " + FILESPEC$) &
	\	GOTO 16810 &
		! IF DEVICE NAME WAS FOUND AND HANDLER INDEX IS NOT DISK, &
		! PRINT MESSAGE, GO REPROMPT &

16860	IF (S1% AND 1%) = 0% THEN &
		JUNK% = FNPRT.MSG%("?Missing file name - " + FILESPEC$) &
	\	GOTO 16810 &
		! IF NO FILE NAME GIVEN, GIVE MESSAGE &
		! AND GO REPROMPT &

16863	IF ((S1% AND 1024%) <> 0%) THEN &
	     JUNK% = FNPRT.MSG%("?Illegal file specification - " + FILESPEC$) &
	      \ GOTO 16810 &
		! IF A PROTECTION CODE IS FOUND, PRINT AN ERROR MESSAGE &
		! AND GO REPROMPT &

16865	FILESPEC$ = FILESPEC$ + ".OBJ" IF ((S1% AND 8%) = 0%) &
	\ CHANGE SYS(CHR.6$+CHR$(-10%)+FILESPEC$) TO M% &
	\ M%(1%) = 6% &
	\ M%(2%) = 17% &
	\ M%(3%) = 255% &
	\ M%(4%) = 255% &
	\ M%(I%) = 0% FOR I% = 13% TO 22% &
	\ M%(I%) = 0% FOR I% = 27% TO 30% &
	\ CHANGE M% TO M$ &
		! TACK ON .OBJ IF NO FILE TYPE GIVEN &
		! RE-SCAN &
		! SET UP SYS() STRING TO LOOK UP THE FILE &

16870	JUNK$ = SYS(M$) &
		! LOOK UP THE FILE, RESUME 16880 IF ERROR &

16875	FILESPEC.BEG% = FILESPEC.END% + 1% &
	\ GOTO 16845 IF FILESPEC.END% <= LEN(OVERLAY$) &
	\ GOTO 16890 &
		! ADVANCE TO END OF FILESPEC &
		! IF MORE FILESPECS TO CHECK, GO CHECK THEM &
		! ELSE RETURN &

16880	IF ERR = 2% THEN &
		JUNK% = FNPRT.MSG%("?Illegal file specification - " + &
			FILESPEC$) &
	\	GOTO 16810 &
		! CHANGE ?Illegal file name to ?Illegal file specification &
		! AND GO REPROMPT &

16885	JUNK% = FNPRT.MSG%(FNGET.ERR$(ERR) + " - " + FILESPEC$) &
	\ GOTO 16810 &
		! PRINT THE RSTS/E ERROR MESSAGE AND THE FILESPEC, &
		! AND GO REPROMPT &

16890	FNGET.OVLY$ = OVERLAY$ &
	\ FNEND &
		! RETURN &

16900	DEF* FNC81CMD$(CMD$,ODL$) &
	! &
	! &
	!	F U N C T I O N   F N C 8 1 C M D $ &
	! &
	! &
	! THIS FUNCTION IS FOR CREATING THE COBOL-81 TKB COMMAND LINE. &
	! IT SHOULD BE CALLED AT LINE 11070 WHEN YOU HAVE FOUND THE C81 &
	! COMMAND LINE WHICH CONTAINS THE STRING "=ODL0nn" IN THE FILE &
	! C81Cnn.TMP.  C81ODL.TSK PRODUCES C81Cnn.CMD WHICH WE MUST ALTER &
	! AND PUT INTO CMD0nn.TMP FOR TKB. &
	! &
	! C81ODL.TSK RETURNS AS MANY AS THREE FILES, WHICH WE MUST CHANGE &
	! FROM THE NAME PRELIN GAVE THEM TO THEIR REAL NAME.  C81ODL.TSK &
	! ALSO CAN PASS SWITCHES SUCH AS "/FU" TELLING TKB TO USE FULL &
	! LIBRARY SEARCHES, AND "/-SP" INFORMING TKB TO NOT AUTOMATICALLY &
	! SPOOL THE MAP FILE FOR PRINTING.  IN ORDER TO PASS THE CORRECT &
	! FILENAMES TO TKB, THEY MUST BE CHANGED USING THIS ROUTINE. &
	! &
	! INPUTS: &
	! 	CMD$ = 	THE ENTIRE LINE WHICH CONTAINS THE STRING "=ODL0nn". &
	!		ALL OF THE FILE NAMES ON THAT STRING SHOULD BE ODL$ &
	! 		NONE OF THE FILESPECS ON THE ORIGINAL COMMAND LINE &
	!		SHOULD HAVE DEVs OR PPNs. OF COURSE WE ARE AT THE &
	!		MERCY OF C81ODL.TSK HERE.  IF THEY CHANGE, WE FAIL. &
	!	ODL$ =  ODL0nn, THE NAME PRELIN GAVE THE TEMPORARY ODL FILE. &
	!		IF A FILE ON CMD$ IS DIFFERENT THAN ODL$, THEN THAT &
	!		FILENAME IS NOT CHANGED. &
	! &
	! OUTPUTS: &
	!	CMD$ =	THE STRING WITH THE NAME OF THE TASK FILE TO PRODUCE, &
	!		IF ONE WAS SPECIFIED (WHICH MAY HAVE BEEN CHANGED VIA &
	!		THE DCL /EXECUTABLE SWITCH). ALSO REPLACED IS THE &
	! 		NAME OF THE OPTIONAL MAP FILE (WHOSE NAME MAY HAVE &
	!		BEEN CHANGED BY THE DCL /MAP QUALIFIER).  IF WE ARE &
	!		LINKING /DEBUG, THEN ALSO INCLUDED ON THE COMMAND &
	!		LINE IS THE FILENAME FOR THE SYMBOL TABLE.  THIS &
	!		FILE NAME IS REPLACED WITH THE APPROPRIATE SYMBOL &
	! 		TABLE FILE NAME.  THE STB FILENAME IS TAKEN FROM THE &
	!		NAME OF THE TASK FILE. &

16910	JUNK% = INSTR(1%,CMD$,"=") &
\	IF JUNK% = 0% THEN &
		FNC81CMD$ = CMD$ &
\		GOTO 16950 &
		! FIND EQUAL SIGN (OUT=IN) &
		! IF NOT FOUND, THEN &
		!	RETURN STRING UNCHANGED &
		!	EXIT FUNCTION &

16920	OUT$ = LEFT(CMD$,JUNK%-1%) &
\	CMD$ = RIGHT(CMD$,JUNK%) &
\	TEMP$ = NL$ &
\	LASTDELIM%,FILCOUNT% = 0% &
\	WHILE LASTDELIM% < LEN(OUT$) &
\		DELIM% = INSTR(LASTDELIM%+1%,OUT$+",",",") &
\		JUNK% =  INSTR(LASTDELIM%+1%,OUT$+"/","/") &
\		DELIM% = JUNK% &
			IF JUNK% < DELIM% &
\		FILCOUNT% = FILCOUNT% + 1% &
\		FIL$ = MID(OUT$,LASTDELIM%+1%,DELIM%-LASTDELIM%-1%) &
\		SUBFIL$ = NL$ &
\		IF FIL$ <> ODL$ THEN &
			SUBFIL$ = FIL$ &
		ELSE	SUBFIL$ = TSKFIL$ &
				IF FILCOUNT% = 1% &
\			SUBFIL$ = MAPFIL$ &
				IF FILCOUNT% = 2% &
\			SUBFIL$ = STBFIL$ &
				IF FILCOUNT% = 3% &
		! STORE OUTPUT FILE(S) IN OUT$ &
		! SAVE REST OF CMD LINE (=IN) IN CMD$ &
		! INIT TEMP STRING TO CREATE NEW OUTPUT FILES &
		! INIT 'LAST DELIMITER' POSITION & FILE COUNTER &
		! DO WHILE MORE FILES TO PARSE: &
		!	LOCATE NEXT COMMA DELIMITER &
		!	LOCATE NEXT SLASH DELIMITER &
		!	SAVE ONE THAT OCCURS FIRST &
		!	INCREMENT FILE COUNTER &
		!	EXTRACT THE FILESPEC STRING &
		!	IF STRING DOESN'T MATCH FILENAME TO REPLACE, &
		!		COPY IT UNCHANGED TO TEMP STRING &
		!	ELSE	(REPLACE THE FILESPEC) &
		!		COPY .TSK FILE TO TEMP STRING &
		!			IF FIRST FILE FOUND &
		!		COPY .MAP FILE TO TEMP STRING &
		!			IF SECOND FILE FOUND &
		!		COPY .STB  FILE TO TEMP STRING &
		!			IF THIRD FILE FOUND &

16930		TEMP$ = TEMP$ + SUBFIL$ &
\		NULFIL% = (LEN(SUBFIL$) = 0%) &
\		LASTDELIM% = DELIM% &
\		IF MID(OUT$,DELIM%,1%) = "/" THEN &
			LASTDELIM% = INSTR(DELIM%+1%,OUT$+",",",") &
\			TEMP$ = TEMP$ + MID(OUT$,DELIM%,LASTDELIM%-DELIM%) &
				UNLESS NULFIL% &
		!	SET NULL-FILE FLAG IF NULL FILE WAS COPIED &
		!	MAKE CURRENT DELIMITER THE LAST ONE &
		!	IF DELIMITER WAS A SLASH, &
		!		FIND NEXT COMMA DELIMITER &
		!		COPY SWITCH(ES) OVER TO TEMP STRING &

16940		TEMP$ = TEMP$ + MID(OUT$,LASTDELIM%,1%) &
\	NEXT &
\	FNC81CMD$ = TEMP$ + CMD$ &
		!	COPY THE DELIMITER ITSELF OVER TO TEMP STRING &
		! CONTINUE WHILE MORE FILES TO PARSE &
		! RETURN TEMP STRING PLUS REST OF CMD LINE &

16950	FNEND &

17000	DEF* FNPUT.FCTR%(LABEL$,FILELST$,SEPAR$) &
	! &
	! &
	!	F U N C T I O N   F N P U T . F C T R % &
	! &
	! &
	! THIS FUNCTION IS FOR CREATING THE .FCTR LINES IN THE ODL &
	! FILE.  THIS IS WHERE ALL OF THE CONSIDERATION IS FOR THE &
	! LENGTH OF THE LINE NOT EXCEEDING 78 CHARACTERS. &
	! LABEL$ IS THE LABEL FOR THE MAIN ODL LINE THAT WE WILL GENERATE. &
	! FILELST$ IS A LIST OF FILE SPECS AND PSECTS SEPARATED BY HYPHENS. &
	! THERE MAY ALSO BE AN AUTOLOAD INDICATOR AT THE END OF THE LIST &
	! OF THE FORM: -*(label).  SEPAR$ IS THE SEPARATOR CHARACTER &
	! ("-" OR ",") BEING USED FOR THIS FACTOR: HYPHEN FOR A FILE FACTOR, &
	! COMMA FOR AN AUTOLOAD  FACTOR. &

17020	EXT.CTR% = 0% &
	\ AUTOLOAD$ = NL$ &
	\ AUTO.BEG% = INSTR(1%,FILELST$,"*") &
	\ IF AUTO.BEG% THEN &
		AUTOLOAD$ = RIGHT(FILELST$,AUTO.BEG%-1%) &
	\	FILELST$ = LEFT(FILELST$,AUTO.BEG%-2%) &
			! FIND WHERE AND IF THERE IS AN AUTOLOAD INDICATOR &
			! PEEL OFF AUTOLOAD FROM FILE LIST AND PUT IT IN &
			! AUTOLOAD$ FOR LATER &

17030	GOTO 17070 IF LEN(FILELST$) + LEN(AUTOLOAD$) + 14% <= MAXODL.LEN% &
	\ NEW.FILELST$ = NL$ &
	\ FILESPEC.BEG% = 1% &
	\ CRNT.FCTR$ = NL$ &
		! WILL FILELST$ AND AUTOLOAD$ FIT ONTO ONE LINE? &
		! (MAXODL.LEN = 78 CHARACTERS BECAUSE THAT IS THE MAXIMUM &
		! NUMBER OF CHARACTERS THAT CAN BE IN AN ODL LINE.) &
		! (+14 CHARACTERS COMES FROM THE "LABEL:<TAB>.FCTR<TAB>") &
		! IF SO, GO PRINT THE LINE AND EXIT &
		! ELSE INITIALIZE VARIABLES &

17040	FILESPEC.END% = INSTR(FILESPEC.BEG%,FILELST$,SEPAR$) &
	\ FILESPEC.END% = LEN(FILELST$) + 1%  IF FILESPEC.END% = 0% &
	\ FILE$ = MID(FILELST$,FILESPEC.BEG%,FILESPEC.END%-FILESPEC.BEG%) &
	\ GOTO 17050  IF LEN(FILE$) + LEN(CRNT.FCTR$) + 1% + 14% > 78% &
	\ CRNT.FCTR$ = CRNT.FCTR$ + SEPAR$   IF LEN(CRNT.FCTR$) <> 0% &
	\ CRNT.FCTR$ = CRNT.FCTR$ + FILE$ &
	\ GOTO 17055 &
		! GET THE NEXT FILE SPEC &
	 	! CAN WE TACK IT ONTO &
		! THE CURRENT .FCTR LINE? (<78 CHARACTERS). &
		! IF SO, TACK IT ON AND GO GET NEXT FILE SPEC &

17050	EXT.LBL$ = FNEXT.LBL$(LABEL$,EXT.CTR%) &
	\ GOTO 32750  IF GOT.ERR% &
	\ PRINT #7%, EXT.LBL$; FCTR.CMD$; CRNT.FCTR$ &
	\ NEW.FILELST$ = NEW.FILELST$ + SEPAR$  IF LEN(NEW.FILELST$) <> 0% &
	\ NEW.FILELST$ = NEW.FILELST$ + EXT.LBL$ &
	\ EXT.CTR% = EXT.CTR% + 1% &
	\ CRNT.FCTR$ = FILE$ &
		! GET A NEW LABEL FOR .FCTR LINE &
		! PRINT THE CURRENT .FCTR LINE (ADD THE NEW LABEL &
		! ONTO NEW FILE LIST) &
		! RESET CURRENT .FCTR TO CONTAIN THE FILE THAT WAS &
		! LEFT OVER AND WOULDN'T FIT ON THE PREVIOUS ODL LINE. &

17055	FILESPEC.BEG% = FILESPEC.END% + 1% &
	\ GOTO 17040  IF FILESPEC.BEG% <= LEN(FILELST$) &
		! PROCESS THE REST OF THE FILES IN THE LIST &
		! RESET FILESPEC.BEG TO THE BEGINNING OF THE NEXT FILE &

17060	EXT.LBL$ = FNEXT.LBL$(LABEL$,EXT.CTR%) &
	\ PRINT #7%, EXT.LBL$; FCTR.CMD$; CRNT.FCTR$ &
	\ NEW.FILELST$ = NEW.FILELST$ + SEPAR$  IF LEN(NEW.FILELST$) <> 0% &
	\ NEW.FILELST$ = NEW.FILELST$ + EXT.LBL$ &
	\ EXT.CTR% = EXT.CTR% + 1% &
	\ FILELST$ = NEW.FILELST$ &
	\ GOTO 17030 &
		! PRINT OUT LAST LABEL AND .FCTR &
		! DON'T FORGET ABOUT THE SEPARATOR &
		! INCREMENT COUNTER FOR LABELS &
		! NOW GO MAKE AN ODL LINE TO REFERENCE ALL THE LABELS &
		! WE'VE GENERATED &

17070	PRINT #7%, LABEL$; FCTR.CMD$; FILELST$; AUTOLOAD$ &
		! PRINT LABEL, FILE LIST, AND AUTOLOAD INDICATOR &
	\ FNPUT.FCTR% = JUNK% &
		! MEANINGLESS RETURN VALUE. &
	\ FNEND &

17100	DEF* FNEXT.LBL$(LABEL$,EXT.CTR%) &
	! &
	! &
	!	 F U N C T I O N   F N E X T . L B L $ &
	! &
	! &
	! THIS FUNCTION IS CALLED BY FNPUT.FCTR% TO CREATE THE &
	! LABEL FOR THE NEW LINE IN THE ODL FILE.  A NEW LINE WILL &
	! NEED TO BE CREATED WHEN THERE ARE TOO MANY FILES OR PSECTS. &

17110	GOTO 17120  IF EXT.CTR% > 36% &
	\ IF EXT.CTR% <= 9% THEN &
		FNEXT.LBL$ = NUM1$(EXT.CTR%) + LABEL$ &
	ELSE &
		FNEXT.LBL$ = CHR$(ASCII("A") + EXT.CTR% -10%) + LABEL$ &
			! THE TEST OF 36 IS THE POSSIBLE 36 LEGAL CHARACTERS &
			! FOR THE NEW EXT.LBL.  (0-9,A-Z) &
			! IF THE LABEL EXCEED 0-9 THEN YOU MUST GENERATE &
			! AN ALPHABETIC CHARACTER FOR THE NEW LABEL &

17115	GOTO 17130 &

17120	JUNK% = FNPRT.MSG%("?Program failure in " + PRG.NAM$ + IDENT.STG$) &
	\ JUNK% = FNPRT.MSG%("?File list is too long at line 17110") &
	\ FNEXT.LBL$ = NL$ &
	\ GOT.ERR% = TRUE% &
		! PRINT OUT ERROR MESSAGES AND EXIT NO TKB &

17130	FNEND &

18000	DEF* FNPROC.BRANCH%(LEVEL%,PLUS%) &
	! &
	! &
	!	F U N C T I O N  F N P R O C . B R A N C H % &
	! &
	! &
	! THIS FUNCTION PROCESSES A BRANCH OF THE OVERLAY TREE -- &
	! PROMPTS THE USER FOR OVERLAYS AND PRODUCES THE LINES FOR THE &
	! ODL FILE. &
	! THIS FUNCTION CALLS ITSELF RECURSIVELY UNTIL ALL BRANCHES OF THE &
	! OVERLAY TREE ARE PROCESSED. &
	!	INPUTS: &
	!		LEVEL% - LEVEL OF CURRENT OVERLAY &
	!		FILELST$(LEVEL%) - LIST OF 1 OR MORE FILES OF &
	!			THE CURRENT OVERLAY (SEPARATED BY COMMAS) &
	!		PLUS% = TRUE% IF THIS OVERLAY HAS CHILDREN &
	!			(USER TYPED PLUS TO INCREASE OVERLAY LEVEL) &
	!		      = 0 OTHERWISE &
	!		LBLNUM%(I%) - FOR EACH LEVEL I%, LBLNUM(I%) IS THE &
	!      		       NUMBER OF THE LAST LABEL GENERATED AT LEVEL I% &
	! &
	! FCTR$ - THE LIST OF LABELS FOR THE CHILDREN OF THE CURRENT OVERLAY &
	!	SEPARATED BY ","   (THE AUTOLOAD .FCTR) &
	!  OR &
	!	- THE LIST OF FILESPECS, PSECTS, ROOT$$, LBR$$ AND AUTOLOAD &
	!	INDICATOR  SEPARATED BY "-"   (THE FILE .FCTR) &

18010	LBLNUM%(LEVEL%) = LBLNUM%(LEVEL%) + 1% &
	\ CHILD.CNT%(LEVEL%) = 0% &
	\ GOTO 18030  IF NOT PLUS% &
		! CHILD.CNT%(LEVEL%) INITIALIZED &
		! IF USER DIDN'T TYPE "+" DON'T PROMPT FOR MORE CHILDREN &

18020	FILELST$(LEVEL%+1%), TEMP$ = FNGET.OVLY$(LEVEL%+1%) &
	\ IF LEN(TEMP$) <> 0% THEN &
		CHILD.CNT%(LEVEL%) = CHILD.CNT%(LEVEL%) + 1% &
	\	JUNK% = FNPROC.BRANCH%(LEVEL%+1%,PLUS%) &
	\ GOTO 18020 &
		! PROMPT FOR OVERLAY FILES - IF SOMETHING INPUT, CURRENT &
		! OVERLAY HAS ONE MORE CHILD. &
		! NOW PROCESS THE CHILDS BRANCH OF THE OVERLAY TREE &
		! LOOP UNTIL THE USER TYPES <RETURN> &

18030	GOTO 18040   IF CHILD.CNT%(LEVEL%) = 0% &
	\ AUTO.LABEL$ = FNAUTO.LABEL$(LEVEL%,LBLNUM%(LEVEL%)) &
	\ LAST.CHILD% = LBLNUM%(LEVEL%+1%) &
	\ FIRST.CHILD% = LAST.CHILD% - CHILD.CNT%(LEVEL%) + 1% &
	\ FCTR$ = FNFILE.LABEL$(LEVEL%+1%,FIRST.CHILD%) &
	\ FOR CHILD% = (FIRST.CHILD% + 1%) TO LAST.CHILD% &
	\	FCTR$ = FCTR$ + "," + FNFILE.LABEL$(LEVEL%+1%,CHILD%) &
	\ NEXT CHILD% &
	\ JUNK% = FNPUT.FCTR%(AUTO.LABEL$,FCTR$,",") &
		! IF NO CHILDREN DON'T GENERATE AUTOLOAD .FCTR &
		! SET UP NEW AUTOLOAD LABEL &
		! LAST.CHILD% IS THE LABEL NUMBER OF THE LAST CHILD OF &
		!  THE CURRENT OVERLAY &
		! FIRST.CHILD% IS THE LABEL NUMBER OF THE FIRST CHILD OF &
		!  THE CURRENT OVERLAY &
		! FCTR$ IS THE LIST OF LABELS FOR CHILDREN SEPARATED BY "," &
		! PRINT THE .FCTR LINE(S) IN THE ODL FILE &

18040	FILE.LABEL$ = FNFILE.LABEL$(LEVEL%,LBLNUM%(LEVEL%)) &
	\ FCTR$ = FNTRANS$(FILELST$(LEVEL%)) &
	\ FCTR$ = FCTR$ + PSECTLST$  IF LEVEL% = 0% &
	\ FCTR$ = FCTR$ + "-ROOT$$"  IF LEVEL% = 0% &
	\ FCTR$ = FCTR$ + "-LBR$$" &
	\ FCTR$ = FCTR$ + "-*(" + AUTO.LABEL$ +")" IF CHILD.CNT%(LEVEL%) > 0% &
	\ JUNK% = FNPUT.FCTR%(FILE.LABEL$,FCTR$,"-") &
	\ FNPROC.BRANCH% = JUNK% &
	\ FNEND &
		! CREATE THE LABEL FOR THE FILE .FCTR &
		! FCTR$ IS THE LIST OF FILESPECS, (PSECTS, ROOT$$, IF ROOT &
		! LEVEL) LBR$$ AND POSSIBLY AN AUTOLOAD INDICATOR. &
		! PRINT THE .FCTR LINE(S) IN THE ODL FILE. &
		! MEANINGLESS RETURN VALUE. &

18100	! &
	! &
	!	F U N C T I O N  F N F I L E . L A B E L $ &
	! &
	! &
	!  THIS FUNCTION IS FOR GENERATING THE UNIQUE LABELS &
	! FOR THE FILES IN THE ODL FILE. &

18110	DEF* FNFILE.LABEL$(LEVEL%,LBLNUM%) = &
		CHR$((LEVEL%*2%) + ASCII("A")) + NUM1$(LBLNUM%) + "$" &

18200	! &
	! &
	!	F U N C T I O N   F N A U T O . L A B E L $ &
	! &
	! &
	!  THIS FUNCTION IS FOR GENERATING THE UNIQUE &
	! AUTOLOAD VECTOR LABELS FOR THE ODL FILE. &

18210	DEF* FNAUTO.LABEL$(LEVEL%,LBLNUM%) = &
		CHR$((LEVEL%*2%) + ASCII("B")) + NUM1$(LBLNUM%) + "$" &

18250	! &
	! &
	! &
	! &
	!	F U N C T I O N   F N G E T . E R R $ &
	! &
	! &
	! &
	! &
	! THIS FUNCTION IS FOR GETTING THE RSTS/E ERROR MESSAGE &

18260	DEF* FNGET.ERR$(E%) = &
		CVT$$(RIGHT(SYS(CHR.6$+CHR$(9%)+CHR$(E%)),3%),4%) &

18270	DEF* FNBAD.LNK.LINE% (IN.LNK$) &
	! &
	! &
	! &
	!	F U N C T I O N   F N B A D . L N K . L I N E % &
	! &
	! &
	! &
	\ JUNK% = FNPRT.MSG%("?Program failure in " + PRG.NAM$ + IDENT.STG$) &
	\ JUNK% = FNPRT.MSG%("?Error in .LNK file - " + IN.LNK$) &
	\ GOT.ERR% = TRUE% &
	\ FNBAD.LNK.LINE% = JUNK% &
	\ FNEND &

18300	DEF* FNPRT.MSG%(MSG$) &
	! &
	! &
	!	F U N C T I O N   F N P R T . M S G % &
	! &
	! &
	! THIS FUNCTION DISPLAYS A MESSAGE.  FIRST IT CANCELS CTRL/O &
	! EFFECT AND RETURNS CURSOR TO LEFT MARGIN IF NECESSARY. &
	! THIS FUNCTION IS FOR AN ERROR MESSAGE OR &
	! WARNING MESSAGE (NOT FOR AN INFORMATIONAL MESSAGE). &

18310	JUNK$ = SYS(CHR$(0%) + CHR$(0%)) &
		IF (ASCII(MSG$)=ASCII("?")) OR (ASCII(MSG$)=ASCII("%")) &
	\ PRINT IF CCPOS(0%) &
  	\ PRINT MSG$ &
	\ FNPRT.MSG% = JUNK% &
 	\ FNEND &
		! CANCEL CTRL/O ON CHANNEL 0. &
		! BRING CURSOR TO LEFT MARGIN. &
		! PRINT THE MESSAGE. &

18400	DEF* FNPROMPT%(PROMPT$) &
	! &
	! &
	!	F U N C T I O N   F N P R O M P T % &
	! &
	! &
	! &
	! THIS FUNCTION DISPLAYS A PROMPT.  FIRST IT CANCELS CTRL/O &
	! EFFECT AND RETURNS CURSOR TO LEFT MARGIN IF NECESSARY. &

18410	JUNK$ = SYS(CHR$(0%) + CHR$(1%)) &
	\ PRINT #1% IF CCPOS(1%) &
	\ PRINT #1%, PROMPT$; &
	\ FNPROMPT% = JUNK% &
 	\ FNEND &
		! CANCEL CTRL/O ON CHANNEL 1 &
		! BRING CURSOR TO LEFT MARGIN &
		! PRINT THE MESSAGE &

18500	DEF* FNGET.LNK.LINE$ &
	! &
	! &
	!	F U N C T I O N   F N G E T . L N K . L I N E % &
	! &
	! &
	! THIS FUNCTION GETS AND DECODES THE NEXT LINE OF THE &
	! .LNK FILE OPEN ON CHANNEL 5. &
	! &
	! INPUTS: &
	! &
	! OUTPUTS: &
	!	COMMAND$ = COMMAND NAME IN UPPER CASE, &
	!		OR *EOF* IF END-OF-FILE ENCOUNTERED, &
	!		OR NULL STRING IF LINE IS NOT A COMMAND. &
	!	PARM$ = PARAMETER (IF ANY) FROM .LNK FILE, IF LINE IS A &
	!		COMMAND. (MIXED CASE.) &
	!	RETURN VALUE = LINE FROM .LNK FILE. &
	&

18510	GOT.ERR% = FALSE% &
	\ INPUT LINE #5%, IN.LNK$ &
	\ FNGET.LNK.LINE$ = CVT$$(IN.LNK$,4%) &
	\ IN.LNK$ = CVT$$(IN.LNK$,4% OR 8% OR 16% OR 128%) &
	\ COMMAND$ = NL$ &
	\ GOTO 18590 IF ASCII(IN.LNK$) <> ASCII("$") &
		! GET INPUT LINE, STRIP <RET> AND LEADING SPACES. &
		! ON EOF RESUME 18530. &
		! STRIP <CR><LF> AND EXCESS SPACES. &
		! IF FIRST CHAR NOT '$', IT'S NOT A COMMAND. &

18520	TEMP% = INSTR(1%, IN.LNK$, "!") &
	\ IN.LNK$ = LEFT(IN.LNK$,TEMP%-1%) IF TEMP%<>0% &
	\ GOTO 18510 IF IN.LNK$="$" &
	\ TEMP% = INSTR(1%,IN.LNK$+SPACECHR$, SPACECHR$) &
	\ COMMAND$ = CVT$$(LEFT(IN.LNK$,TEMP%-1%),32%) &
	\ PARM$ = RIGHT(IN.LNK$,TEMP%+1%) &
	\ GOTO 18590 &
		! STRIP OFF COMMENT. &
		! IF COMMAND IS NULL, GO GET ANOTHER LINE. &
		! GET THE COMMAND NAME AND THE PARAMETER STRING. &
		! RETURN. &

18530	COMMAND$ = "*EOF*" &
	\ PARM$ = NL$ &
	\ FNGET.LNK.LINE$ = "*EOF*" &
		! WE'VE REACHED END-OF-FILE.  RETURN THE "*EOF*" SYMBOL. &

18590	FNEND &

18600	DEF* FNLOOKUP.RESLIB% (LIBNAME$) &
	! &
	! &
	! F U N C T I O N   F N L O O K U P . R E S L I B % &
	! &
	! &
	! Returns TRUE% if the library is installed (ADDed), FALSE% if not. &

18610	CHANGE SYS(CHR.6$+CHR$(-23%)+LIBNAME$) TO M% &
	\ LIBNAME1% = M%(7%) + SWAP%(M%(8%)) &
	\ LIBNAME2% = M%(9%) + SWAP%(M%(10%)) &
	\ CHANGE SYS(CHR.6$+CHR$(-12%)+STRING$(28%,0%)) TO M% &
	\ RTSLST% = M%(15%) + SWAP%(M%(16%)) &
	\ LIBBLK% = RTSLST% + 2% &
	\ JUNK$ = SYS(PRIV.ON$) &
		! DO AN FSS OF THE LIBRARY NAME. &
		! GET FIRST AND SECOND WORD OF RAD50 OF LIBRARY NAME. &
		! LOOK UP PART II OF MONITOR TABLES. &
		! GET ADDRESS OF POINTER TO RTS LIST. &
		! GET ADDRESS OF FIRST RESIDENT LIBRARY DESCRIPTOR BLOCK. &
		! GAIN TEMPORARY PRIVILEGE. &

18620	LIBBLK% = PEEK(LIBBLK%) &
	\ IF LIBBLK%<>0% THEN &
		IF (PEEK(LIBBLK%+2%) = LIBNAME1%) &
		  AND (PEEK(LIBBLK%+4%) = LIBNAME2%) THEN &
			GOTO 18640 &
		ELSE &
			GOTO 18620 &
		! GET NEXT LIB DESCRIPTOR BLOCK IN LIB LIST. &
		! IF NOT AT END OF LIB LIST THEN &
		!	IF WE'VE FOUND THE LIBRARY THEN GO RETURN. &
		!	ELSE LOOP ONWARD. &

18630	FNLOOKUP.RESLIB% = FALSE% &
	\ GOTO 18650 &

18640	FNLOOKUP.RESLIB% = TRUE% &

18650	JUNK$ = SYS(PRIV.OFF$) &
	\ FNEND &

19000	! &
	! &
	! &
	!	E R R O R    T R A P    H A N D L I N G    R O U T I N E &
	! &
	! &
	! &

19010	IF ERL = 16870% THEN RESUME 16880 &
	ELSE IF ERL = 16845% THEN RESUME 16880 &
		! IF ERROR CHECKING OUT FILESPECS TYPED BY USER, &
		! GO REPORT IT &

19020	IF ERR=11% THEN &
		IF ERL = 16110% THEN RESUME 32750 &
		ELSE IF ERL=18510 THEN RESUME 18530 &
		ELSE IF ERL = 11048% THEN RESUME 11060 &
		ELSE IF ERL = 11210% THEN RESUME 32700 &
		! IF ^Z TO ANY PROMPT, EXIT NO TKB &
		! CHECKING ATPK LOG FILE FOR ERRORS &
		! IF NO ERRORS, GOTO TKB AND BUILD TASK &

19030	IF ERL=32710 THEN RESUME 32720 &
	ELSE IF (ERL=2000%) THEN &
		JUNK% = FNPRT.MSG%("?Command not installed") &
	\	JUNK% = FNPRT.MSG%(FNGET.ERR$(ERR) + " - LB:" + LANG$+".LNK") &
	\ 	RESUME 32750 &
		! IF ERROR CHAINING TO TKB, GO REPORT IT &
		! LANGUAGE FILES NOT FOUND IN PROPER PLACE &
		! SAY ?message - LB:lang.LNK &
		! END PROGRAM NO TASK BUILD &

19040	IF ERL=11005 THEN &
		JUNK% = FNPRT.MSG%("?Command not installed") &
	\	JUNK% = FNPRT.MSG%(FNGET.ERR$(ERR) + " - C81$:C81ODL.TSK") &
	\	RESUME 32750 &
		! IF C81$:C81ODL.TSK DOESN'T EXIST THEN &
		! SAY ?message - C81$:C81ODL.TSK &
		! END PROGRAM NO TASK BUILD &

19050	IF ERL = 9125% THEN &
		JUNK% = FNPRT.MSG%("?Error accessing FMS resident library") &
	\	JUNK% = FNPRT.MSG%(FNGET.ERR$(ERR) + " - LB:" + FMS.RESLIB$+".TSK") &
	\	RESUME 32750 &
		! IF ERROR OPENING RESIDENT LIBRARY &
		! GO REPORT IT &
		! END PROGRAM NO TASK BUILD &

19090	JUNK% = FNPRT.MSG%("?Program failure in " + PRG.NAM$ + IDENT.STG$) &
	\ ON ERROR GOTO 0 &
	\ STOP &
		! SAY ?Program failure in PRELIN V10.1-A &
		! SAY THE MESSAGE &
		! EXIT &

29000	! &
	! &
	! &
	!	J O B    S P A W N    E N T R Y &
	! &
	! &
	! &

29010	ENTRY.TYP% = 8% &
	\ GOTO 1000 &
		! SET ENTRY TYPE FOR SPAWNED ENTRY AND GOTO PROGRAM START. &

30000	! &
	! &
	! &
	!	C C L    E N T R Y &
	! &
	! &
	! &

30010	ENTRY.TYP% = 1% &
	\ GOTO 1000 &

31000	! &
	! &
	! &
	!	C H A I N    E N T R Y &
	! &
	! &
	! ATPK CHAINS BACK TO HERE FOR LINK/C81. &

31010	ENTRY.TYP% = 2% &
	\ GOTO 1000 &
		! SET ENTRY.TYP% FOR CHAIN ENTRY AND GOTO PROGRAM START. &

32000	! &
	! &
	! &
	!	L O G G E D - O U T    E N T R Y &
	! &
	! &
	! &

32010	ENTRY.TYP% = 4% &
	\ GOTO 1000 &
		! SET ENTRY.TYP% FOR LOGGED-OUT ENTRY AND GOTO PROGRAM START. &

32700	! &
	! &
	! &
	!	P R O G R A M    C O M P L E T I O N &
	! &
	! &
	! &

32710	CLOSE I% FOR I% = 1% TO 12% &
	\ GOTO 32767 IF DBG% &
	\ JUNK$ = SYS(CHR$(8%)+"TKB @"+CMD.FIL$) &
	\ CHAIN "_SY:$TKB.TSK" LINE 30000 &
	\ STOP &
		! CLOSE ALL FILES AND GET INFORMATION FOR &
		! IF WE ARE DEBUGGING PRELIN, THEN END. FILES ALREADY CLOSED. &
		! CORE COMMON TO CALL THE TASK BUILDER. &
		! CHAIN TO TKB &
		! ON ERROR RESUME 32720 &

32720	JUNK% = FNPRT.MSG%(FNGET.ERR$(ERR)+" - $TKB.TSK") &
		! TELL HIM WE DIDN'T FIND TKB &

32750	CLOSE I% FOR I% = 1% TO 12% &

32767	END
