(***********************************************************************

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;
