(*********************************************************************** Name: MakeAbs.Pas Version: 1.0 This software has been placed into the public domain by Digital Equipment Corporation. DISCLAIMER: The information herein is subject to change without notice and should not be construed as a commitment by Digital Equipment Corporation. Digital Equipment Corporation assumes no responsibility for the use or reliability of this software. This software is provided "as is," without any warranty of any kind, express or implied. Digital Equipment Corporation will not be liable in any event for any damages including any loss of data, profit, or savings, claims against the user by any other party, or any other incidental or consequential damages arising out of the use of, or inability to use, this software, even if Digital Equipment Corporation is advised of the possibility of such damage. DEFECT REPORTING AND SUGGESTIONS: Please send reports of defects or suggestions for improvement directly to the author: Brian Hetrick Digital Equipment Corporation 110 Spit Brook Road ZKO1-3/J10 Nashua NH 03062-2698 Do NOT file a Software Performance Report on this software, call the Telephone Support Center regarding this software, contact your Digital Field Office regarding this software, or use any other mechanism provided for Digital's supported and warranted software. FACILITY: TURBO Pascal MS-DOS support routines ABSTRACT: Translates a relative path specification into an absolute path specification (one that does not depend upon current directories or relative directory specifiers) ENVIRONMENT: MS-DOS V2.0 or later, compiled with Borland International's TURBO Pascal V3.0 or later. AUTHOR: Brian Hetrick, CREATION DATE: 1 December 1986. MODIFIED BY: Brian Hetrick, 01-Dec-86: Version 1.0 000 - Original creation of module. ***********************************************************************) {.PA} (* * INCLUDE FILES: *) (* * LABEL DECLARATIONS: *) (* * CONSTANT DECLARATIONS: *) (* * TYPE DECLARATIONS: *) TYPE MakeAbsPath = STRING [255]; (* * OWN STORAGE: *) (* * TABLE OF CONTENTS: *) {.PA} PROCEDURE MakePathAbsolute (VAR RelativePath : MakeAbsPath); (*********************************************************************** FUNCTIONAL DESCRIPTION: Finds the absolute path specification for a given relative path specification. In the absolute path specification, the drive letter and a root-relative path specification name the file. In a relative path specification, the drive letter need not appear (it defaults to the current drive), and the path specification may be relative to the current path on the drive. FORMAL PARAMETERS: Path.mt.r - The possibly relative path specification which is set to be the corresponding absolute path specification. RETURN VALUE: None. IMPLICIT INPUTS: None. IMPLICIT OUTPUTS: None. SIDE EFFECTS: May obtain the current directory on the current drive, or the cur- rent directory on some other drive. For some reason, MS-DOS acces- es the drive when the current directory is requested, so this may generate an MS-DOS level error if the drive does not exist or if there is no volume in the drive. ***********************************************************************) VAR AbsolutePath : MakeAbsPath; DriveIndex : INTEGER; LastDeletePosition : INTEGER; ScanPtr : INTEGER; ThisChar : CHAR; BEGIN (* * Get drive index and current directory for drive *) IF (Length (RelativePath) >= 2) AND (RelativePath [2] = ':') THEN BEGIN DriveIndex := Ord (UpCase (RelativePath [1])) - 64; Delete (RelativePath, 1, 2) END ELSE DriveIndex := 0; GetDir (DriveIndex, AbsolutePath); (* * Construct the absolute path name *) IF Length (RelativePath) > 0 THEN BEGIN IF (RelativePath [1] = '/') OR (RelativePath [1] = '\') THEN Delete (AbsolutePath, 3, Length (AbsolutePath) - 2) ELSE IF (AbsolutePath [Length (AbsolutePath)] <> '\') AND (AbsolutePath [Length (AbsolutePath)] <> '/') THEN Insert ('\', AbsolutePath, Length (AbsolutePath) + 1) END; Insert (RelativePath, AbsolutePath, Length (AbsolutePath) + 1); (* * Fix lowercase and directory separators *) FOR ScanPtr := 1 TO Length (AbsolutePath) DO BEGIN ThisChar := UpCase (AbsolutePath [ScanPtr]); IF ThisChar = '/' THEN ThisChar := '\'; AbsolutePath [ScanPtr] := ThisChar END; (* * Fix up '.' and '..' references *) ScanPtr := 1; WHILE ScanPtr <= Length (AbsolutePath) DO BEGIN IF AbsolutePath [ScanPtr] = '\' THEN BEGIN (* * Check next character for '.' *) IF (Length (AbsolutePath) > ScanPtr) AND (AbsolutePath [ScanPtr + 1] = '.') THEN BEGIN (* * Check next character also for '..' *) IF (Length (AbsolutePath) > ScanPtr + 1) AND (AbsolutePath [ScanPtr + 2] = '.') THEN BEGIN (* * Have reference to parent directory. Delete both * '..' and previous directory *) LastDeletePosition := ScanPtr + 2; REPEAT ScanPtr := ScanPtr - 1 UNTIL (AbsolutePath [ScanPtr] = '\') OR (AbsolutePath [ScanPtr] = ':'); IF AbsolutePath [ScanPtr] = ':' THEN ScanPtr := ScanPtr + 1 END ELSE (* * Have reference to current directory. Delete '.' * only *) LastDeletePosition := ScanPtr + 1; (* * Delete directory references *) Delete (AbsolutePath, ScanPtr, LastDeletePosition - ScanPtr + 1) END ELSE (* * Next character is not '.' *) ScanPtr := ScanPtr + 1 END ELSE (* * Current character is not '\' *) ScanPtr := ScanPtr + 1 END; (* * Specification of the root directory through .. may leave only * the drive letter and colon *) IF Length (AbsolutePath) = 2 THEN Insert ('\', AbsolutePath, 3); (* * Return the absolute path *) RelativePath := AbsolutePath END;