1(* $Id: Path.Mod,v 1.5 2004/11/24 03:53:09 sgreenhill Exp $ *) 2MODULE OS:Path; 3(* Manipulation of file and directory names. 4 Copyright (C) 2000, 2001, 2003 Michael van Acken 5 6 This module is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public License 8 as published by the Free Software Foundation; either version 2 of 9 the License, or (at your option) any later version. 10 11 This module is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public 17 License along with OOC. If not, write to the Free Software Foundation, 18 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19*) 20 21IMPORT 22 Object, ADT:StringBuffer; 23 24CONST 25 sep = "/"; 26 27PROCEDURE DirName*(path: STRING): STRING; 28(**Calculates the directory name of pathname @oparam{path}. *) 29 VAR 30 i, j: LONGINT; 31 BEGIN 32 i := path.LastIndexOf(sep, path.length); 33 IF (i >= 0) THEN 34 (* if dirname is not composed exclusively of slashes, remove any 35 trailing "/" characters *) 36 j := i; 37 WHILE (j > 0) & (path.CharAt(j-1) = sep) DO 38 DEC(j); 39 END; 40 IF (j = 0) THEN (* include path separator at position `i' *) 41 INC(i); 42 ELSE (* discard all trailing separators *) 43 i := j; 44 END; 45 RETURN path.Substring(0, i); 46 ELSE (* plain file name, no directory part *) 47 RETURN ""; 48 END; 49 END DirName; 50 51PROCEDURE BaseName* (path: STRING): STRING; 52(**Calculates the basename of pathname @oparam{path}. The basename is the last 53 pathname component of @oparam{path}. It never contains a slash. If 54 @oparam{path} ends with a slash, then the basename is the empty string. If 55 path does not contain a slash, then the basename equals path. *) 56 VAR 57 i: LONGINT; 58 BEGIN 59 i := path.LastIndexOf(sep, path.length); 60 IF (i >= 0) THEN 61 RETURN path.Substring(i+1, path.length); 62 ELSE 63 RETURN path; 64 END; 65 END BaseName; 66 67PROCEDURE SplitExt* (path: STRING; VAR root, ext: STRING); 68(**Splits the pathname @oparam{path} into a pair @samp{(@oparam{root}, 69 @oparam{ext})} such that @samp{concat(@oparam{root},@oparam{ext}) = 70 @oparam{path}}. The extension @oparam{ext} is empty or begins with a period 71 and contains at most one period. The extension string does not contain a 72 slash character. *) 73 VAR 74 i: LONGINT; 75 BEGIN 76 i := path.LastIndexOf(".", path.length); 77 IF (i >= 0) & (path.IndexOf(sep, i) < 0) THEN 78 root := path.Substring(0, i); 79 ext := path.Substring(i, path.length); 80 ELSE 81 root := path; 82 ext := ""; 83 END; 84 END SplitExt; 85 86 87PROCEDURE Encode*(path: STRING): Object.CharsLatin1; 88(**Encode the file path or command @oparam{path} as a system-specific sequence 89 of bytes. 90 91 The default implementation returns a string with all character codes above 92 @samp{0FFX} replaced with the character @samp{_}. That is, non ISO Latin1 93 characters are discarded. For instances of @otype{Object.String8}, it is 94 the identity operation. *) 95 VAR 96 path8: Object.String8; 97 BEGIN 98 path8 := path.ToString8("_"); 99 RETURN path8.CharsLatin1(); 100 END Encode; 101 102PROCEDURE Decode*(path[NO_COPY]: ARRAY OF CHAR): STRING; 103(**Convert a system-specific sequence of bytes @oparam{path} representing a 104 file path into a string instance. This is the inverse of @oproc{Encode}. *) 105 BEGIN 106 RETURN Object.NewLatin1(path); 107 END Decode; 108 109PROCEDURE QuoteForShell* (path : STRING) : STRING; 110(**Convert a path to a form suitable for passing as a command-line argument to 111 a system command. Certain characters cannot be directly used in command-line 112 path arguments because the characters have special significance to the 113 system shell. For example, spaces are used to separate arguments in command 114 lines, so a path containing spaces must be quoted to cause the shell to 115 treat it as a literal. 116 117 This function determines if @oparam{path} needs to be quoted. If so, it 118 returns a quoted version. Otherwise, the original @oparam{path} is returned. 119 *) 120 121 CONST 122 escapeChar = "\"; 123 quoteChars = escapeChar + '"'; 124 125 PROCEDURE EscapeReservedChars(s, reserved : STRING; escape : CHAR) : STRING; 126 VAR 127 i : LONGINT; 128 sb : StringBuffer.StringBuffer; 129 c : UCS4CHAR; 130 needQuote : BOOLEAN; 131 BEGIN 132 needQuote := FALSE; 133 sb := StringBuffer.New('"'); 134 FOR i := 0 TO s.length - 1 DO 135 c := s.CharAt(i); 136 IF reserved.IndexOf(c, 0) >= 0 THEN 137 sb.AppendLatin1Char(escape); 138 needQuote := TRUE; 139 ELSIF c = ' ' THEN 140 needQuote := TRUE; 141 END; 142 sb.AppendChar(c); 143 END; 144 sb.AppendChar('"'); 145 IF needQuote THEN 146 RETURN sb.ToString(); 147 ELSE 148 RETURN s; 149 END; 150 END EscapeReservedChars; 151 152 BEGIN 153 RETURN EscapeReservedChars(path, quoteChars, escapeChar); 154 END QuoteForShell; 155 156END OS:Path. 157