Description of the unit EXTFN 1. Introduction. In utilities like NSWEEP and in ZCPR, one can address files in any user area by including the user area number in the file name. Such file names are called extended file names, as they (may) contain the user area number between the drive name and the colon. For CP/M diehards using Turbo Pascal 3.0, a package of procedures in EXTFN.UNT are made available, which provide the possibility to specify extended file names, like 'A9:FILE.BOO', in a TP program. All the necessary definitions are gathered into one file. The structure of this file resembles a UNIT as introduced in TP 4.0, with an interface section and an implementation section, but despite this comment it is an ordinary include file. 2. Functional description. The function of the package is to enable the pascal programmer to access files in any user area, in the understanding that each of the (open) files can be located in different user areas. Moreover, this function must be independent of the file type, thus it should work for text files, typed files as well as untyped files. An implementation requirement was that all the standard pascal i/o procedures and functions would still be working when using this function. This requirement is met. If a file with an extended name is to be used, two actions are needed prior to actual using the file: the file name must be put into a special data structure (FILEDESCRIPTORS) and the file must be registered. Only when a file is registered, the required user area will be selected when accessing the file. Once registered, the normal Pascal i/o procedures, like assign, reset, rewrite, (block)read, (block)write and close, can be invoked. The (pseudo) unit EXTFN.UNT consists 4 type definitions, 5 procedures and 2 functions. 2.1. Type definitions. The type FILETYPES enumerates the two possible file types supported by TP: DISKFILE for a disk file and DEVICE for a logical device. The type FILENAMETYPES enumerates the possible formats of a disk file name: DUNE_FORMAT for a name including disk and user area, DNE_FORMAT for a name without the user area and NE_FORMAT for a name without disk and without user area. The DNE_FORMAT is equivalent with the standard full name of CP/M. The type FULLFILENAMES specifies the string to save a maximum sized extended file name. The type FILEDESCRIPTORS specifies a record in which the separate fields of a file name are stored. - 1 - Description of the unit EXTFN 2.2. Procedures and functions The syntax of the procedures and functions within EXTFN.UNT are summarised in the table below. They are given in alphabetical order. function ExpandFileName( var FileDesc : FileDescriptors ; NameType : FileNameTypes ) : FullFileNames ; procedure InitFileNameUnit ; procedure RegisterFile ( var FileDesc : FileDescriptors ; var SomeFile ) ; function SameName ( var FileDesc1: FileDescriptors ; var FileDesc2: FileDescriptors , NameType : FileNameTypes ) : Boolean ; procedure SplitFileName ( var FileDesc : FileDescriptors ; FileName : FullFileNames ) ; procedure UnInitFileNameUnit ; procedure UnRegisterFile( var SomeFile ) ; 2.2.1. ExpandFileName Function ExpandFileName builds from the filedescriptor a string with the file name. The name is formatted according to the specified FileNameType. A 'current' value of the drive will be replaced by its actual value and also a 'current' value of the user area will be replaced by its current actual value. The result may contain the '?' wildcard character. This function is needed to assign a TP file to a CP/M file (or device). Typically a program will contain the following fragment: RegisterFile( MyFileName, MyFile ) ; Assign( MyFile, ExpandFileName(MyFileName,DNE_Format) ) ; 2.2.2. InitFileNameUnit Procedure InitFileNameUnit should be invoked once, before any of the other procedures and functions in EXTFN.UNT is invoked. It initialises some of the internal variables and it installs an extension to BDos by modifying the BDos vector. 2.2.3. RegisterFile Procedure RegisterFile registers which files are assigned extended names. It builds an internal table, specifying the files and the user area in which they are located. Note that the user area to use is fixed at the time procedure RegisterFile is invoked: any change in the file name after the invokation does not affect the user area to be used. If the user area in the extended file name specifies the 'current' user area, the actual user area is substituted. Procedure RegisterFile effectivly invokes UnRegisterFile to ensure that one file occurs at most once in the internal table. This behaviour can be used to modify the registered user area in case it might have been changed. However, it is not allowed to invoke RegisterFile while the file is open! 2.2.4. SameName Boolean function SameName compares two extended file names and returns a TRUE value if they match and a FALSE value if they don't match. Through - 2 - Description of the unit EXTFN the specification of the NameType one can select whether the drive name and/or the user area number should be included in the comparison. Two names match if for every position in each of the fields the characters of the two names are either equal or at least one of them is the '?' wildcard character. In the comparison the '?' wildcard matches also a non-existing character. 2.2.5. SplitFileName Procedure SplitFileName takes an extended file name in a string as an argument and it builds a variable of type FILEDESCRIPTORS. The procedure recognises both extended disk file names and the logical device names. The procedure is liberal with regard to erroneous specifications: it does not report errors and it tries to make the best of it. If the drive designator is not specified in the file name string, the drive is set to 'current'. At the invokation of either ExpandFileName or SameName, the 'current' indication is substituted by the actual current drive designator. The user area number is handled in the same way: if it is not specified it is set to 'current' and replaced by the actual value whenever necessary. The '*' wildcard character is replaced by a number of '?' wildcard characters, enough to fill up the entire field. Any characters between the '*' wildcard and the next field terminator, like '.', are lost. 2.2.6. UnInitFileNameUnit Procedure UnInitFileNameUnit restores the original BDos vector, which was modified by InitFileNameUnit. See section 'Usage' for more comments on this procedure. 2.2.7. UnRegisterFile Procedure UnRegisterFile removes a file from the list of registered files, thereby disabling the feature to select a user area for that file. This procedure must not be called while the file is open! 3. Usage. Typically, a program using extended file names will contain the following program fragments: Program UseExtendedFileNames ; {$IEXTFN.UNT} { Include unit } ... var ExtFileName : FileDescriptors ; { Extended name of ExtFile } ExtFile : File of Something ; { Some file } NameString : FullFileNames ; { String with extended file name } ... begin { of main program } InitFileNameUnit ; ... ReadLn( NameString ) ; { Retrieve file name } SplitFileName( ExtFileName, NameString ) ; { Crack file name } - 3 - Description of the unit EXTFN RegisterFile ( ExtFileName, ExtFile ) ; { Register file } Assign( ExtFile, ExpandFileName(ExtFileName,DNE_Format) ) ; ... ... { Do I/O on file ExtFile } ... Close( ExtFile ) ; UnInitFileNameUnit ; end. Note the invokation of UnInitFileNameUnit at the end: it restores the original BDos vector in low memory. If the program is compiled to disk and the program is started 'from the CP/M prompt', the BDos vector will be restored also at the warm boot, which occurs when the program terminates. However, if the program is run from within TP, the BDos vector MUST be restored prior to returning to TP. Thus for normal program termination, UnInitFileNameUnit should be called at the end of the program. In order to catch the premature terminations due to run-time errors, it is advisable to use your own error processor, which invokes UnInitFileNameUnit. 4. Short technical description. To implement extended file names, a small shell is put on top of BDos. This shell is the procedure OwnBDos in EXTFN.UNT. Each call to OwnBDos from TP which references a file with an extended name, is replaced by four BDos calls. The first call retrieves the currently selected user area, the second call selects the user area for that specific file, the third call is the original, intercepted BDos call and the fourth and last BDos call reselects the original user area. The return code received by the TP runtime routines, is the return code of the file I/O BDos call. The procedure InitFileNameUnit modifies the vector in low memory to jump to OwnBDos in stead of BDos. At the time the program terminates, the vector must be restored: if not, the first invokation of BDos after program termination will have unpredictable results and most probably the computer will 'hang'. 5. Remarks. Any remarks, comments, bug reports, bug fixes and ideas for improvement are welcome, in either Dutch or English. E-mail is preferred. Wim Nelis Rozenhof 4 8316 CX Marknesse The Netherlands (0) 5273 - 3172 NELIS@NLR.NL (Internet) - 4 -