Loader Interface

KEY Note 1. Loader search order. When the loader is asked to find an entry point, the search is done in the following order: 1. System entries i.e. subsystem and Director system call list 2. Privately loaded entries 3. Current active directory 4. Subsystem base directory 5. Privately nominated directories i.e. SEARCHDIR list The subsystem base directory contains pointers to heavily used software such as the standard compilers and mathematical libraries, MAIL, VIEW, SETMODE etc. Object files found via the subsystem base directory are always added to the 'permanently loaded' loader table and remain loaded until the end of the current session or a call of RESETLOADER. Searching is always linear down the search list, never circular.
Note 2. Searching for entries at command level. If the loader is asked to load a particular command and it could not be found after a full search then the following action is taken. The loader assumes that the command name is really a file name and tries to connect it. If the connect fails or it succeeds but the file is neither an object file nor a character file then the load has failed and the message 'Load fails - ENTRY not found' is output. If the file is an object file then it is examined for a main entry point. If found then the object file is run otherwise the load fails. If the file is a character file, then a call is made to OBEYJOB to obey the contents of the file on the assumption that it contains a series of commands. Note that for an object file with a main entry then Command: PROGY Command: RUN(PROGY) Command: EXECUTE(PROGY) have identical effects at command level.
Note 3. Return code from non-trappable events in user programs. Just before the loader passes control to a piece of user software, it sets a trap to catch catastrophic failures in that software such as 'unassigned variable', 'address error', etc. If indeed some such contingency does occur in the user program then control passes to the trap. Almost the first thing the loader does is check the return code. If this is still zero, i.e. 'success' - which is quite likely since the failure was presumably unexpected - then the loader itself will set a standard return code of 103050709 before calling the diagnostics package and returning to whatever initiated the unsuccessful call. In many cases the initiating software will be the subsystem itself i.e. a user command typed at command level, but some other routines/commands available in the subsystem and callable from within user programs, themselves set up loader traps. Examples of these are RUN, CALL, EXECUTE (all described below), EMASFC, FCALL and PCALL. If a user program calls on one of these utilities then control will return to the program even after a catastrophic failure. If the program always checks the return code after calling one of these utilities then at least it can detect that a non-trappable failure has occurred and take appropriate action.
Note 4. Reserved filenames The files T#CODE, T#GLA and T#LOAD are reserved for use by the loader; their use for any other purpose is NOT recommended.

User Interface

KEY This section contains details of the commands used to control and interrogate the loader. It also contains details of the procedures CALL and USEFOR, commonly used by user programs.

LOADPARM

This command allows loader run-time options to be set. It is the loader equivalent of PARM (which sets compiler options). The default is FULL, which requests full cascade loading. Failure is reported if any unsatisfied references remain. LOADPARM(MIN) suppresses cascade loading and the loader will only load the file which contains the entry point being looked for. Any common areas required are created and all unsatisfied references are made dynamic. LOADPARM(LET) makes unsatisfied references 'unresolved' after a full cascade load so that execution can begin. IF LOADPARMs MIN and LET are both set, then unsatisfied references will always be made dynamic. Although it might appear that under these circumstances LET is ignored, it does affect the handling of mismatching lengths for a data entry and its references (see the "Errors and warnings associated with loading" section for further details). LOADPARM(MIN) is set.
If LOADPARM(ZERO) is requested then any common areas created by the loader will be zeroed otherwise they are filled with the unassigned pattern. Example: LOADPARM(LET,ZERO)

DATASPACE

This command allows the user to set up a data area in a file and use it to satisfy data references which occur during loading. The file can be a data file created by NEWSMFILE or a character file. DATASPACE permits the caller to add data entries to the 'permanent entries' loader table. Each entry is associated with a specific area within a file. Two entries are not allowed to overlap and any entry must be wholly contained within the file in which it occurs. The command takes 5 parameters of which 2 are optional: ENTRY - name of the new data entry FILE - name of the file which contains the area of store to be used by ENTRY. LENGTH - length of data area in BYTES OFFSET [optional] - offset of the start of ENTRY from the start of the file in BYTES. This parameter defaults to 0 i.e. the first available byte in the file is the first byte of the data area. ACCESS [optional] - Type of access required to the data area. The permitted values are: R - Read and Read Shared W - Unshared Write WS - Write Shared The default is W for a file, R for a pdfile member. Indeed pdfile members can ONLY be used in R access mode. This is to prevent problems arising when object files and DATASPACE areas are members of the same pd file. The loader connects object files in R mode to load them so if an object file which was a pd file member was loaded then the whole pd file would be connected in this mode regardless of any previous use of the pd file or any of its members. Whatever the access type requested, the appropriate permission must have been given. W and WS permissions are allowed on another user's file. Write shared access can be tricky, e.g. what if two of you are trying to write to the same area at the same time, and should not be used unless you are sure you know what you are doing. This command will be particularly useful to users of programming languages other than IMP since it allows the powerful EMAS facility of store mapping to be used from any language. The only requirement is that the language implementation allows external data areas. IMP defines %external variables which have this property, while in FORTRAN the equivalent is the common area. Normally the loader will create common areas at load time by assigning space from the user's gla file. DATASPACE allows the user to set up the data area independently of the loader in a location of his own choosing. When the loader encounters the data reference it will find that there is a data entry of the correct name and type already loaded and use it to satisfy the reference. By using common areas for input and output all conventional (and expensive) READ and WRITE operations can be avoided. There is the further advantage that more of the user's gla file is available for programs and the 'user gla full' error will occur less often. Note. This is not a language provided facility but a system supplied one and users should bear this in mind when making use of it. DATASPACE definitions remain in force until the end of the current session or an explicit call of RESETLOADER (q.v.). WARNING ------- IMP programmers should not use SMADDR on a file which has active DATASPACE definitions. This is because SMADDR can change the access mode to a file without the loader knowing about it. For example a file with DATASPACE entries connected in READ access mode could have this switched to WRITE mode by a call of SMADDR with consequences best left to the imagination! If you must access a file currently in use by DATASPACE then you should seek advice.

Example of the use of DATASPACE

KEY Consider the following two programs: %BEGIN COMMON /STAR/ISTAR(10) %EXTRINSICINTEGERARRAY STAR(1:10) DO 100 I=1,10 %INTEGER I ISTAR(I)=ISTAR(I)+I %FOR I=1,1,10 %CYCLE 100 CONTINUE STAR(I)=STAR(I)+I WRITE(6,600)ISTAR WRITE(STAR(I),6) 600 FORMAT(1H ,10I7) %REPEAT STOP %ENDOFPROGRAM END Both refer to an external data area called STAR, 40 bytes long, which is to be regarded as 10 integers. In the IMP program the extrinsic array STAR generates the data reference whereas in the FORTRAN program, the array ISTAR is contained in the common block STAR. Both programs increment each array element by the array subscript before outputting the value of each element.
Each program requires access in W mode to a data area 40 bytes long and we can provide this using the command DATASPACE. First the file to hold the area is created by, say, NEWSMFILE(DAREA,80) This command creates a zeroed file 80 bytes long called DAREA and we assign the first 40 bytes of it to a data entry called STAR by the command: DATASPACE(STAR,DAREA,40) If either program is run then when the loader tries to satisfy the data reference to STAR then it will find an entry of the correct name, type and length already loaded. Running either program would give the result 1 2 3 4 5 6 7 8 9 10 STAR remains loaded after the run so a second run would give the result 2 4 6 8 10 12 14 16 18 20 and so on. The final values are always preserved between calls and the definition of STAR will remain in force until log off or a call of RESETLOADER. DAREA can support as many other DATASPACE definitions as we wish provided that the areas defined are wholly within the file, no two areas overlap and there is no conflict in access mode. For example if we have STAR set up as above then the following attempts to set up another DATASPACE area would fail:
DATASPACE(PLANET,DAREA,40,60) => Not wholly contained in DAREA DATASPACE(ASTEROID,DAREA,40,20) => Overlaps STAR DATASPACE(COMET,DAREA,40,40,R) => DAREA already connected in W mode for STAR whereas DATASPACE(RIGEL,DAREA,20,40) would set up a new data entry 20 bytes long from byte 41 to 60 in DAREA while DATASPACE(CASTOR,DAREA,10,60) and DATASPACE(POLLUX,DAREA,10,70) would assign the remaining 20 bytes in the file to data entries CASTOR and POLLUX each 10 bytes long. The important point to remember is that the DATASPACE area length is always given in BYTES.

ALIASENTRY

This command allows a user to add an alias to a system or permanently loaded entry point directly to the loader tables for the duration of the session or the next call on RESETLOADER(q.v.). The alias is added to the 'permanent entries' loader table with a copy of the type and descriptor of the original name. The command takes two parameters: ENTRY - Name of a currently loaded entry point ALIAS - Name to be added to the permanently loaded entry table This method of aliasing differs in several ways from the command ALIAS. ALIAS works by adding an entry of the form ALIAS=ENTRY to the current active directory. For example ALIAS(ANALYSE,A) would enter A=ANALYSE in the active directory. The alias is permanent and can only be removed by another call on ALIAS. A call on A would cause the loader to search the currently loaded material. An entry called A would not be found so the loader would now search the active directory where it would find A=ANALYSE. The loader would remember that it started off looking for A in case this branch proves fruitless then start to look for ANALYSE. ANALYSE would be found among the currently loaded entries and the loader would return the descriptor to enter the command. If the alias had been set up using ALIASENTRY then a call on A would have found A among the currently loaded entries and returned the descriptor immediately. ALIASENTRY is more efficient than alias but ALIASENTRY definitions only remain in force for the current session or the next call on RESETLOADER. Example: ALIAS(FILES,F)

RUN

This command is used for running a compiled program. The only parameter is the name of the object file which contains the program. Note that the first action is to increment the loadlevel before starting any loading operations. After the RUN has terminated then everything loaded at the new loadlevel is unloaded and the loadlevel decremented before proceeding. By implication, anything loaded by a call on RUN will be unloaded again after the RUN. A routine which calls RUN will not have access to any temporarily loaded code or any temporary data area created by the RUN. If RUN is called from within a program and the file RUN fails catastrophically then a standard return code of 103050709 will be set unless the file itself had already set a non-zero return code. At command level RUN and EXECUTE have identical effects. Example: RUN(PROGY)

EXECUTE

This command operates in the same way as RUN (q.v.) except that the loadlevel is unaltered. Any code loaded or data area created by the call of EXECUTE can be used by the routine or program calling EXECUTE. Unlike RUN, EXECUTE does not unload. If EXECUTE is called from within a program and the file EXECUTEd fails catastrophically then a standard return code of 103050709 will be set unless the file itself had already set a non-zero return code. At command level EXECUTE and RUN have identical effects. Example: EXECUTE(PROGY)

CALL

%externalroutinespec call(%string(31) command, %string(255) param) This routine is as described in the EMAS 2900 User's Guide with the difference that if the load fails then CALL will set a return code and return to the routine which called it, rather than returning directly to command level. Note that the remarks pertaining to loadlevel and loading/unloading made in the description of RUN also apply to CALL (and its FORTRAN user's equivalents EMASFC and FCALL). If the code CALLed fails catastrophically then a standard return code of 103050709 will be set by the loader unless a non zero return code has already been set.

USEFOR

%systemintegerfunctionspec usefor(%routinename myname, %string(31) externalname) This function can be used to call any external routine or function from within a program where the routine or function need not be specified until run time. The nearest equivalent is CALL, but USEFOR is a much more powerful tool than CALL since it is not restricted to commands with a single %STRING(255) parameter. Code loaded via the USEFOR mechanism is not unloaded after it has been run, unlike the CALL mechanism. This is particularly useful in situations where constant loading and unloading could cause inefficiency e.g. CALL inside a loop. To use USEFOR you must first declare a dummy dynamic routine or function which has the same specification as the target routine(s) or function(s). A call to USEFOR at run time will then make a call to the dummy routine or function equivalent to a call on the desired code. USEFOR takes two parameters: MYNAME - the name of the dummy dynamic routine or function, and EXTERNALNAME - the name of the external routine or function which you actually want to call at run-time, and will return a result of zero if successful. The one restriction on USEFOR is that it can only be used with one dummy routine or function per program. Technically, what USEFOR does is to work its way back from its own stack to the location in the gla which contains the escape descriptor corresponding to the dummy routine. An attempt is then made to load EXTERNALNAME and if this is successful the escape descriptor in the gla is overwritten by the descriptor to EXTERNALNAME. A call on the dummy routine in the user program is then equivalent to a call on EXTERNALNAME. If we want to call EXTERNALNAME many times then we only have to load it once. If desired then we can give the program different EXTERNALNAMEs in the same run.

Example of the use of USEFOR

KEY Here is an extract from a program showing how USEFOR could be used in place of CALL: %BEGIN %DYNAMICROUTINESPEC ANYTHING(%STRING(255) S) %SYSTEMINTEGERFNSPEC USEFOR(%ROUTINENAME DUM(%STRING(255) S), %STRING(31) NEX) %ROUTINESPEC QUERY(%STRING(31) PROMPT,%STRINGNAME ANSWER) . . . %CYCLE ! Get next command QUERY("Next command: ",NCOM) %EXIT IF NCOM=".END" FLAG=USEFOR(ANYTHING,NCOM); !Make call on ANYTHING into call !on NCOM %RETURN %IF FLAG#0; ! USEFOR failed for some reason. ! What params do we want to give NCOM? QUERY("Param? ", PARM) ! Now call NCOM by calling ANYTHING ANYTHING(PARM) ! Check return code %IF RETURN CODE#0 %THEN %START . . %FINISH . . . %REPEAT . . %ENDOFPROGRAM
By contrast, here is another program fragment which shows USEFOR being used to allow different integer functions to be selected: %BEGIN %DYNAMICINTEGERFNSPEC ANYTHING(%INTEGERNAME I,J,K) %SYSTEMINTEGERFNSPEC USEFOR(%INTEGERFNNAME DUM(%INTEGERNAME I,J,K), %STRING(31) EXTERNALNAME) %ROUTINESPEC QUERY(%STRING(31) PROMPT,%STRINGNAME ANSWER) . . . . Solve loop %CYCLE ! Get name of next solve function QUERY("Solve function? ", NEXTFN) %RETURN %IF NEXTFN=".END" FLAG=USEFOR(ANYTHING,NEXTFN); ! Make call on ANYTHING into call on NEXTFN %RETURN %IF FLAG#0; ! Abandon if error TESTFLAG=0 I=NEXTPRIME J=I*2 %WHILE TESTFLAG=0 %CYCLE TESTFLAG=ANYTHING(I,J,K) %EXIT %IF K<0 I=K//2 J=K*2 %REPEAT %IF TESTFLAG#0 %THEN PRINTSTRING(NEXTFN." is diverging") PRINTSTRING("Final values are: ") WRITE(I,8) WRITE(J,8) WRITE(K,8) NEWLINE %REPEAT . . . %ENDOFPROGRAM
USEFOR will fail if a) MYNAME is not declared as dynamic b) MYNAME had been satisfied before USEFOR was first called e.g. %DYNAMICROUTINESPEC FILES(%STRING(255) S) would be satisfied by the subsystem command FILES at load time. c) the load of EXTERNALNAME failed. Note that in the spec of USEFOR given above, which is how it appears in the code of the loader, the %ROUTINENAME MYNAME parameter is simply a pointer to a code item external to the loader. The loader knows nothing about the spec of the external object. It could be a routine, a function, have many or few parameters; it doesn't matter because USEFOR does not call it. In the program or routine which calls USEFOR, however, the MYNAME spec must be identical to the spec of the dummy routine or function as the above examples illustrate. Once this has been done then any routine or function with the same spec as the dummy can be called.

Important note

KEY Care must be taken when using USEFOR over the problem of serial re-entrancy. This is discussed at greater length in the 'PRELOADing object files' subsection of the 'Efficient loading' section but in essence the problem is that global variables and common areas are only initialised by the loader when a file is loaded. USEFOR can call a routine or function many times but it is only loaded once. The nth call of the routine has as its starting values for global variables the n-1th final values. Not all routines have global variables or common blocks and in these there is no ambiguity but even in files which are not serially re-entrant the fact that global variables and common block values are preserved between runs can be turned to advantage but initially it is vital to be aware of the potential problems.

PRELOAD

This command causes object file FILE to be 'permanently loaded' i.e. until the end of the current session or an explicit call on RESETLOADER (q.v.). Any references which remain unsatisfied after the file is loaded are made dynamic. Note that this includes ALL data references except common areas. Common areas are set up by claiming space from the base gla. Preloading is generally used to 'permanently load' files which are going to be frequently used during a session. Loading overheads are only incurred once.

Important note

KEY PRELOAD should not be used until the 'PRELOADing object files' subsection of 'Efficient loading' has been read. In particular the implications of loading an object file once but running it several times must be understood if the command is to be used safely.

RESETLOADER

This command will unload any user files which are currently loaded. Any DATASPACE or ALIASENTRY definitions will also be lost. This command can ONLY be issued at command level; attempts to call it from a program will fail.

Current load status - LOADEDENTRIES, LOADEDFILES, CURRENTREFS

KEY LOADEDENTRIES,LOADEDFILES,CURRENTREFS LOADEDENTRIES prints a list of entries which have been loaded by the caller i.e. no subsystem or system call table entries. LOADEDFILES prints a list of currently loaded files. CURRENTREFS prints out a list of currently active references. An active reference is one which will trigger off a loader search if encountered during a load (unsatisfied reference) or program execution (dynamic reference).

System Interface

KEY This description of the system interface is accurate at the time of writing, however, the ERCC reserves the right to alter this interface as necessary. Intending users of any of the routines below do so at their own risk and should ensure that the specifications given here are still extant. Note 1. Loader Constants. The following constants are used in the description of the loader interface to categorise the various types of entry understood by the loader: FNAMETYPE(filename type) 0 DATA 1 CODE 2 MACRO 4
Note 2. Supplying loadlevel values to system routines. Many of the routines described in the system interface request a 'local loadlevel', (usually LOCLL). The loader is the only software which is allowed to alter the overall value of the loadlevel of the process, so the programmer should not attempt it. What the programmer can do is to decide whether a file is to be permanently or temporarily loaded. If the former is required then the caller should supply a LOCLL of 0. This causes a temporary, localised switch in loadlevel for the duration of the load of that file. The global value of loadlevel is unaltered. If, however, the file is only to be temporarily loaded then the current value of the global loadlevel should be supplied. This can be obtained by calling the integer function CURRENTLL (q.v.). If a value of LOCLL is supplied such that 0#LOCLL#global loadlevel, then the result is undefined but assuredly catastrophic.

Searching


LOOKLOADED

%systemlongintegerfunctionspec lookloaded(%string(31) entry, %integername type) This function looks for the occurrence of ENTRY in the caller's currently loaded material (i.e. subsystem entries and caller's privately loaded entries) TYPE can be FNAMETYPE or any combination of CODE,DATA or MACRO (e.g. CODE!MACRO). If TYPE is a multiple then if the search is successful the value of TYPE returned will be the type actually found.
The function always returns a result of 0 if the search fails. Successful searches give the following longinteger results: Returned TYPE Result ======== ==== ====== FNAMETYPE 1 i.e. the file is already loaded DATA A pseudo descriptor with the first word giving the length of the data entry in bytes and the second its address, but with no 'descriptor type' information. CODE A descriptor to ENTRY MACRO Not yet implemented

SEARCH

%systemintegerfunctionspec search(%string(31) entry, %longintegername desc,%stringname file,actualepname, %integername type,locll) This is the loader's main searching routine for the current EMAS subsystem. Searching is done in the order: 1. Subsystem entries 2. Privately loaded entries 3. Active directory 4. Subsystem base directory 5. Privately nominated directories

Input required

ENTRY Entry name to be searched for TYPE Any combination of CODE,DATA or MACRO LOCLL Supply value of global loadlevel (i.e. from CURRENTLL).

Possible results

%RESULT < 0 ----------- This means that ENTRY was found and is already loaded. Output given ------------ DESC Descriptor to CODE or DATA or MACRO item found ACTUALEPNAME If ENTRY was an alias or the leader of a chain of aliases then ACTUALEPNAME is the name of the entry point at the end of the alias chain, otherwise ACTUALEPNAME=ENTRY. TYPE Type of entry point found
%RESULT = 0 ----------- This means that ENTRY was found but is not currently loaded. Output given ------------ FILE The name of the file which contains ACTUALEPNAME. ACTUALEPNAME ENTRY, or if ENTRY was an alias then the entry point name eventually found. TYPE Type of entry point found. LOCLL Loadlevel value input or, or if the file was found in the subsystem base directory then 0 (so that FILE will be 'permanently' loaded).
%RESULT > 0 ----------- ENTRY was not found after a complete search(%RESULT=289) or an error condition was encountered.

Loading and searching


LOADEP

%systemlongintegerfunctionspec loadep(%string(31) entry, %integername type,flag, %integer locll) This longinteger function is used to effect a complete load based on a starting search for ENTRY. TYPE can be any combination of CODE, DATA or MACRO although in most cases CODE or CODE!MACRO would be the likely choices. If the load succeeds then the actual type found is returned through TYPE. FLAG indicates the success or failure of the load - a zero flag means successful. LOCLL is the value of the loadlevel supplied to the function in accordance with Note 2 above. It is therefore either the current loadlevel (from CURRENTLL) or 0 if all the loading is to be 'permanent'. If the call is successful then the result of the function is a descriptor to ENTRY otherwise the result is 0. Note that only in the case of ENTRY being of type CODE is a true 2900 descriptor returned.
The function first looks for ENTRY. If ENTRY is already loaded then the result is returned immediately. If not then routine SEARCH is called. If a suitable file to load is found then this is loaded by a call on LOADFILE2. If unsatisfied references remain then the load continues by calling CASCADELOAD (q.v.) by default, or MINLOAD (q.v.) if LOADPARM MIN is set. Should the load fail at some point, then everything that has been loaded by the call on LOADEP will be unloaded (by a call on UNLOAD2 (q.v.)).

LOADENTITY

%systemlongintegerfunctionspec loadentity(%string(31) entry, %integername type,flag,%integer locll) This function takes the same parameters as LOADEP and behaves exactly the same as LOADEP except where the initial call on SEARCH to find ENTRY returns a 'not found' condition. In these circumstances LOADENTITY will try to connect ENTRY on the assumption that it is a file. If the connect fails, or if it succeeds but the file is neither an object file nor a character file, then the function terminates. If ENTRY is an object file then it is inspected for a main entry and if one is found then the file is loaded as in LOADEP with the entry descriptor returned as the result, otherwise the function terminates. If ENTRY is a character file then the result -1 is returned. In the standard subsystem this is taken as an indication to attempt an OBEYJOB on the file.

CASCADELOAD

%systemroutinespec cascadeload(%integername flag,%integer locll) Used in conjunction with LOADFILE2 (q.v.) to effect a complete load (see LOADEP and LOADENTITY). While there are unsatisfied references (COMREG(7)>0), the routine attempts to satisfy them by searching for, and loading, files which contain any of the outstanding reference names as entry points. Common areas are created where appropriate. The routine terminates on encountering the first failure of any kind and will return a non zero flag. The routine requires the value of the local loadlevel as input. (LOCLL). If everything is to be 'permanently loaded' then LOCLL should be 0 otherwise the overall load level (from CURRENTLL (q.v.)) should be supplied (See Note 2 above).

Important note

KEY UNLOAD2 (q.v.) should be used to tidy up after any failure of CASCADELOAD.

MINLOAD

%systemroutinespec minload(%integer locll,makedynamic, %integername flag) Used in conjunction with LOADFILE2 (q.v.) to allow a single file to begin executing by fixing up unsatisfied references to be dynamic or unresolved as specified (See also LOADEP and LOADENTITY). The routine goes through the list of unsatisfied references and changes their type to dynamic if MAKEDYNAMIC=1 or unresolved if MAKEDYNAMIC=0. No further loading occurs although any outstanding common areas will be created. Note that in some circumstances calling MINLOAD may result in the creation of dynamic data references (q.v.). The routine returns a flag and requires the local loadlevel as input exactly as described in CASCADELOAD.

Important note

KEY UNLOAD2 (q.v.) should be used to tidy up after any failure.

Loading - LOADFILE2

KEY LOADFILE2 %systemroutinespec loadfile2(%string(31) file,%integername flag, %integer locll) This routine causes file FILE to be loaded at loadlevel LOCLL with the result returned via FLAG. A flag of 0 indicates success. LOADFILE2 copes with standard and bound object files. If the CODE area crosses a segment boundary or is marked as unshareable then the CODE and SST areas are copied into a file called T#CODEnn where nn is a unique suffix chosen by the system. In addition to performing basic loading operations, LOADFILE2 carries out any linking operations which are possible with already loaded material and will satisfy any outstanding references to entry points contained in FILE.

Unloading - UNLOAD2

KEY UNLOAD2 %systemroutinespec unload2(%integer locll,fail) This routine causes everything loaded with a loadlevel>=LOCLL to be unloaded. When the unload occurs at the end of normal processing then FAIL should be set to 0. However when the call to UNLOAD2 occurs as the result of a failed load then FAIL should be set to 1. This will ensure that any item 'permanently' loaded during the failed load will be unloaded. Note that if there are any references at loadlevels<LOCLL which have been satisfied by entries which are about to be unloaded then these references will be unfixed and made dynamic. A warning will be given when this is done.

Entering code - ENTER

KEY ENTER %systemroutinespec enter(%integer mode,dr0,dr1,%string(255) param) This routine is used to enter the code pointed at by the descriptor held in DR0 and DR1. This code may have either no parameters or a single %STRING(255) parameter contained in PARAM. MODE is a bit significant quantity: 2**0 - If set then request an explicit stack switch (i.e. from base stack to user stack). 2**1 - If set then parameter supplied. Note that the rules for executing a stack switch are as follows: Switch stacks if a) you are presently on the base stack and b) you are not privileged and c) you are calling something outside the basefile or c') you explicitly request a stack switch

Rebuilding loader search list - BDIRLIST

KEY BDIRLIST %systemroutinespec bdirlist Instructs the loader to rebuild its list of directories which must be searched when looking for entries. This routine must be called by software which changes the information on directories in the options file to ensure that the loader updates its own table.

General information routines


CURRENTLL

%systemintegerfunctionspec currentll Returns the current global value of loadlevel for the process.

CURSTACK

%systemintegerfunctionspec curstack Returns 0 if running on the base stack, otherwise 1.

Utility routine - FILLPATTN

KEY FILLPATTN %systemroutinespec fillpattn(%integer ncopies,n,from,to) Moves NCOPIES of N bytes from address FROM to address TO.

Dumping routine - LOADDUMP

KEY LOADDUMP %externalroutinespec loaddump(%string(255) s) This routine takes a single parameter to control which particular part of the loader tables are to be dumped. Valid parameters are: 0 - T#LOAD file header 1 - References table 2 - Permanent entries table 3 - Temporary entries table A null parameter or any other than those specified above will dump the whole T#LOAD file. Additional information on the current state of the SSLOADTAB, LLINFO and DUFFGLA record arrays is always printed.