SystemTools.hxx.in 33.7 KB
Newer Older
1 2
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing#kwsys for details.  */
3 4 5
#ifndef @KWSYS_NAMESPACE@_SystemTools_hxx
#define @KWSYS_NAMESPACE@_SystemTools_hxx

6 7 8
#include <@KWSYS_NAMESPACE@/Configure.hxx>

#include <iosfwd>
9
#include <map>
Brad King's avatar
Brad King committed
10 11
#include <string>
#include <vector>
12

13
#include <@KWSYS_NAMESPACE@/String.hxx>
Brad King's avatar
Brad King committed
14

15
#include <sys/types.h>
16
#if !defined(_WIN32) || defined(__CYGWIN__)
17
#include <unistd.h> // For access permissions for use with access()
18
#endif
19 20

// Required for va_list
21
#include <stdarg.h>
22 23
// Required for FILE*
#include <stdio.h>
Brad King's avatar
Brad King committed
24
#if !defined(va_list)
25
// Some compilers move va_list into the std namespace and there is no way to
26 27 28 29
// tell that this has been done. Playing with things being included before or
// after stdarg.h does not solve things because we do not have control over
// what the user does. This hack solves this problem by moving va_list to our
// own namespace that is local for kwsys.
30 31 32 33 34
namespace std {
} // Required for platforms that do not have std namespace
namespace @KWSYS_NAMESPACE@_VA_LIST {
using namespace std;
typedef va_list hack_va_list;
35
}
36 37
namespace @KWSYS_NAMESPACE@ {
typedef @KWSYS_NAMESPACE@_VA_LIST::hack_va_list va_list;
38 39
}
#endif // va_list
40

41
namespace @KWSYS_NAMESPACE@ {
42

43
class SystemToolsTranslationMap;
44
class SystemToolsPathCaseMap;
45
class SystemToolsEnvMap;
46

47 48 49 50
/** \class SystemToolsManager
 * \brief Use to make sure SystemTools is initialized before it is used
 * and is the last static object destroyed
 */
51 52 53 54 55 56 57 58
class @KWSYS_NAMESPACE@_EXPORT SystemToolsManager
{
public:
  SystemToolsManager();
  ~SystemToolsManager();
};

// This instance will show up in any translation unit that uses
59
// SystemTools. It will make sure SystemTools is initialized
60 61
// before it is used and is the last static object destroyed.
static SystemToolsManager SystemToolsManagerInstance;
62

63 64 65 66 67
// Flags for use with TestFileAccess.  Use a typedef in case any operating
// system in the future needs a special type.  These are flags that may be
// combined using the | operator.
typedef int TestFilePermissions;
#if defined(_WIN32) && !defined(__CYGWIN__)
68 69 70 71 72
// On Windows (VC and Borland), no system header defines these constants...
static const TestFilePermissions TEST_FILE_OK = 0;
static const TestFilePermissions TEST_FILE_READ = 4;
static const TestFilePermissions TEST_FILE_WRITE = 2;
static const TestFilePermissions TEST_FILE_EXECUTE = 1;
73
#else
74 75 76 77 78
// Standard POSIX constants
static const TestFilePermissions TEST_FILE_OK = F_OK;
static const TestFilePermissions TEST_FILE_READ = R_OK;
static const TestFilePermissions TEST_FILE_WRITE = W_OK;
static const TestFilePermissions TEST_FILE_EXECUTE = X_OK;
79 80
#endif

81 82 83
/** \class SystemTools
 * \brief A collection of useful platform-independent system functions.
 */
Brad King's avatar
Brad King committed
84
class @KWSYS_NAMESPACE@_EXPORT SystemTools
85 86
{
public:
87 88 89 90 91
  /** -----------------------------------------------------------------
   *               String Manipulation Routines
   *  -----------------------------------------------------------------
   */

92 93 94 95 96 97 98
  /**
   * Replace symbols in str that are not valid in C identifiers as
   * defined by the 1999 standard, ie. anything except [A-Za-z0-9_].
   * They are replaced with `_' and if the first character is a digit
   * then an underscore is prepended.  Note that this can produce
   * identifiers that the standard reserves (_[A-Z].* and __.*).
   */
Brad King's avatar
Brad King committed
99
  static std::string MakeCidentifier(const std::string& s);
100

Brad King's avatar
Brad King committed
101
  static std::string MakeCindentifier(const std::string& s)
102 103 104 105
  {
    return MakeCidentifier(s);
  }

106
  /**
107
   * Replace replace all occurences of the string in the source string.
108
   */
109
  static void ReplaceString(std::string& source, const char* replace,
110
                            const char* with);
111
  static void ReplaceString(std::string& source, const std::string& replace,
Brad King's avatar
Brad King committed
112
                            const std::string& with);
113 114 115 116 117

  /**
   * Return a capitalized string (i.e the first letter is uppercased,
   * all other are lowercased).
   */
Brad King's avatar
Brad King committed
118
  static std::string Capitalized(const std::string&);
119

120
  /**
121 122
   * Return a 'capitalized words' string (i.e the first letter of each word
   * is uppercased all other are left untouched though).
123
   */
Brad King's avatar
Brad King committed
124
  static std::string CapitalizedWords(const std::string&);
125

126
  /**
127 128
   * Return a 'uncapitalized words' string (i.e the first letter of each word
   * is lowercased all other are left untouched though).
129
   */
Brad King's avatar
Brad King committed
130
  static std::string UnCapitalizedWords(const std::string&);
131

132 133 134
  /**
   * Return a lower case string
   */
Brad King's avatar
Brad King committed
135
  static std::string LowerCase(const std::string&);
136

137 138 139
  /**
   * Return a lower case string
   */
Brad King's avatar
Brad King committed
140
  static std::string UpperCase(const std::string&);
141

142 143 144 145
  /**
   * Count char in string
   */
  static size_t CountChar(const char* str, char c);
146

147 148 149 150
  /**
   * Remove some characters from a string.
   * Return a pointer to the new resulting string (allocated with 'new')
   */
151
  static char* RemoveChars(const char* str, const char* toremove);
152 153

  /**
154
   * Remove remove all but 0->9, A->F characters from a string.
155 156 157
   * Return a pointer to the new resulting string (allocated with 'new')
   */
  static char* RemoveCharsButUpperHex(const char* str);
158

159 160 161 162
  /**
   * Replace some characters by another character in a string (in-place)
   * Return a pointer to string
   */
163 164
  static char* ReplaceChars(char* str, const char* toreplace,
                            char replacement);
165

166
  /**
167
   * Returns true if str1 starts (respectively ends) with str2
168 169
   */
  static bool StringStartsWith(const char* str1, const char* str2);
Brad King's avatar
Brad King committed
170
  static bool StringStartsWith(const std::string& str1, const char* str2);
171
  static bool StringEndsWith(const char* str1, const char* str2);
Brad King's avatar
Brad King committed
172
  static bool StringEndsWith(const std::string& str1, const char* str2);
173

174 175 176 177
  /**
   * Returns a pointer to the last occurence of str2 in str1
   */
  static const char* FindLastString(const char* str1, const char* str2);
178

179 180 181 182 183 184
  /**
   * Make a duplicate of the string similar to the strdup C function
   * but use new to create the 'new' string, so one can use
   * 'delete' to remove it. Returns 0 if the input is empty.
   */
  static char* DuplicateString(const char* str);
185

186 187 188 189
  /**
   * Return the string cropped to a given length by removing chars in the
   * center of the string and replacing them with an ellipsis (...)
   */
190
  static std::string CropString(const std::string&, size_t max_len);
191

192 193 194 195
  /** split a path by separator into an array of strings, default is /.
      If isPath is true then the string is treated like a path and if
      s starts with a / then the first element of the returned array will
      be /, so /foo/bar will be [/, foo, bar]
196
  */
197 198 199
  static std::vector<String> SplitString(const std::string& s,
                                         char separator = '/',
                                         bool isPath = false);
200
  /**
201
   * Perform a case-independent string comparison
202
   */
203
  static int Strucmp(const char* s1, const char* s2);
204

205
  /**
206 207 208
   * Convert a string in __DATE__ or __TIMESTAMP__ format into a time_t.
   * Return false on error, true on success
   */
209 210
  static bool ConvertDateMacroString(const char* str, time_t* tmt);
  static bool ConvertTimeStampMacroString(const char* str, time_t* tmt);
211 212 213 214 215

  /**
   * Split a string on its newlines into multiple lines
   * Return false only if the last line stored had no newline
   */
Brad King's avatar
Brad King committed
216
  static bool Split(const std::string& s, std::vector<std::string>& l);
217 218
  static bool Split(const std::string& s, std::vector<std::string>& l,
                    char separator);
219 220

  /**
221
   * Return string with space added between capitalized words
222
   * (i.e. EatMyShorts becomes Eat My Shorts )
223
   * (note that IEatShorts becomes IEat Shorts)
224
   */
225
  static std::string AddSpaceBetweenCapitalizedWords(const std::string&);
226

227
  /**
228
   * Append two or more strings and produce new one.
229 230
   * Programmer must 'delete []' the resulting string, which was allocated
   * with 'new'.
231 232
   * Return 0 if inputs are empty or there was an error
   */
233 234 235
  static char* AppendStrings(const char* str1, const char* str2);
  static char* AppendStrings(const char* str1, const char* str2,
                             const char* str3);
236

237
  /**
238 239 240 241 242 243 244 245
   * Estimate the length of the string that will be produced
   * from printing the given format string and arguments.  The
   * returned length will always be at least as large as the string
   * that will result from printing.
   * WARNING: since va_arg is called to iterate of the argument list,
   * you will not be able to use this 'ap' anymore from the beginning.
   * It's up to you to call va_end though.
   */
246
  static int EstimateFormatLength(const char* format, va_list ap);
247

248 249 250
  /**
   * Escape specific characters in 'str'.
   */
251 252
  static std::string EscapeChars(const char* str, const char* chars_to_escape,
                                 char escape_char = '\\');
253

254 255 256 257 258
  /** -----------------------------------------------------------------
   *               Filename Manipulation Routines
   *  -----------------------------------------------------------------
   */

259 260 261
  /**
   * Replace Windows file system slashes with Unix-style slashes.
   */
Brad King's avatar
Brad King committed
262
  static void ConvertToUnixSlashes(std::string& path);
263 264 265 266 267 268 269 270 271

#ifdef _WIN32
  /**
   * Convert the path to an extended length path to avoid MAX_PATH length
   * limitations on Windows. If the input is a local path the result will be
   * prefixed with \\?\; if the input is instead a network path, the result
   * will be prefixed with \\?\UNC\. All output will also be converted to
   * absolute paths with Windows-style backslashes.
   **/
Brad King's avatar
Brad King committed
272
  static std::wstring ConvertToWindowsExtendedPath(const std::string&);
273 274
#endif

275
  /**
276
   * For windows this calls ConvertToWindowsOutputPath and for unix
277 278
   * it calls ConvertToUnixOutputPath
   */
Brad King's avatar
Brad King committed
279
  static std::string ConvertToOutputPath(const std::string&);
280

Ken Martin's avatar
Ken Martin committed
281 282 283 284
  /**
   * Convert the path to a string that can be used in a unix makefile.
   * double slashes are removed, and spaces are escaped.
   */
Brad King's avatar
Brad King committed
285
  static std::string ConvertToUnixOutputPath(const std::string&);
Ken Martin's avatar
Ken Martin committed
286 287 288 289 290 291 292

  /**
   * Convert the path to string that can be used in a windows project or
   * makefile.   Double slashes are removed if they are not at the start of
   * the string, the slashes are converted to windows style backslashes, and
   * if there are spaces in the string it is double quoted.
   */
Brad King's avatar
Brad King committed
293
  static std::string ConvertToWindowsOutputPath(const std::string&);
Ken Martin's avatar
Ken Martin committed
294

295 296 297 298 299
  /**
   * Return true if a path with the given name exists in the current directory.
   */
  static bool PathExists(const std::string& path);

300
  /**
301
   * Return true if a file exists in the current directory.
302
   * If isFile = true, then make sure the file is a file and
303
   * not a directory.  If isFile = false, then return true
304 305 306
   * if it is a file or a directory.  Note that the file will
   * also be checked for read access.  (Currently, this check
   * for read access is only done on POSIX systems.)
307
   */
308
  static bool FileExists(const char* filename, bool isFile);
Brad King's avatar
Brad King committed
309
  static bool FileExists(const std::string& filename, bool isFile);
310
  static bool FileExists(const char* filename);
Brad King's avatar
Brad King committed
311
  static bool FileExists(const std::string& filename);
312

313 314 315 316 317 318 319 320 321 322 323 324
  /**
   * Test if a file exists and can be accessed with the requested
   * permissions.  Symbolic links are followed.  Returns true if
   * the access test was successful.
   *
   * On POSIX systems (including Cygwin), this maps to the access
   * function.  On Windows systems, all existing files are
   * considered readable, and writable files are considered to
   * have the read-only file attribute cleared.
   */
  static bool TestFileAccess(const char* filename,
                             TestFilePermissions permissions);
Brad King's avatar
Brad King committed
325
  static bool TestFileAccess(const std::string& filename,
326 327
                             TestFilePermissions permissions);

328 329 330 331 332
/**
 * Converts Cygwin path to Win32 path. Uses dictionary container for
 * caching and calls to cygwin_conv_to_win32_path from Cygwin dll
 * for actual translation.  Returns true on success, else false.
 */
333
#ifdef __CYGWIN__
334
  static bool PathCygwinToWin32(const char* path, char* win32_path);
335
#endif
336

337 338 339
  /**
   * Return file length
   */
Brad King's avatar
Brad King committed
340
  static unsigned long FileLength(const std::string& filename);
341

342 343 344
  /**
     Change the modification time or create a file
  */
Brad King's avatar
Brad King committed
345
  static bool Touch(const std::string& filename, bool create);
346

347
  /**
348 349 350
   *  Compare file modification times.
   *  Return true for successful comparison and false for error.
   *  When true is returned, result has -1, 0, +1 for
351
   *  f1 older, same, or newer than f2.
352
   */
353
  static bool FileTimeCompare(const std::string& f1, const std::string& f2,
354
                              int* result);
Brad King's avatar
Brad King committed
355

356 357 358 359 360 361
  /**
   *  Get the file extension (including ".") needed for an executable
   *  on the current platform ("" for unix, ".exe" for Windows).
   */
  static const char* GetExecutableExtension();

362
  /**
363 364 365 366 367
   * Given a path on a Windows machine, return the actual case of
   * the path as it exists on disk.  Path components that do not
   * exist on disk are returned unchanged.  Relative paths are always
   * returned unchanged.  Drive letters are always made upper case.
   * This does nothing on non-Windows systems but return the path.
368
   */
Brad King's avatar
Brad King committed
369
  static std::string GetActualCaseForPath(const std::string& path);
370

371 372 373 374 375
  /**
   * Given the path to a program executable, get the directory part of
   * the path with the file stripped off.  If there is no directory
   * part, the empty string is returned.
   */
Brad King's avatar
Brad King committed
376
  static std::string GetProgramPath(const std::string&);
377 378
  static bool SplitProgramPath(const std::string& in_name, std::string& dir,
                               std::string& file, bool errorReport = true);
379 380

  /**
381 382 383 384 385 386
   *  Given argv[0] for a unix program find the full path to a running
   *  executable.  argv0 can be null for windows WinMain programs
   *  in this case GetModuleFileName will be used to find the path
   *  to the running executable.  If argv0 is not a full path,
   *  then this will try to find the full path.  If the path is not
   *  found false is returned, if found true is returned.  An error
387
   *  message of the attempted paths is stored in errorMsg.
388 389 390 391
   *  exeName is the name of the executable.
   *  buildDir is a possibly null path to the build directory.
   *  installPrefix is a possibly null pointer to the install directory.
   */
392 393
  static bool FindProgramPath(const char* argv0, std::string& pathOut,
                              std::string& errorMsg, const char* exeName = 0,
394
                              const char* buildDir = 0,
395
                              const char* installPrefix = 0);
396

397 398 399 400 401 402
  /**
   * Given a path to a file or directory, convert it to a full path.
   * This collapses away relative paths relative to the cwd argument
   * (which defaults to the current working directory).  The full path
   * is returned.
   */
Brad King's avatar
Brad King committed
403 404
  static std::string CollapseFullPath(const std::string& in_relative);
  static std::string CollapseFullPath(const std::string& in_relative,
405
                                      const char* in_base);
Brad King's avatar
Brad King committed
406
  static std::string CollapseFullPath(const std::string& in_relative,
407
                                      const std::string& in_base);
408

409
  /**
410 411
   * Get the real path for a given path, removing all symlinks.  In
   * the event of an error (non-existent path, permissions issue,
412 413 414
   * etc.) the original path is returned if errorMessage pointer is
   * NULL.  Otherwise empty string is returned and errorMessage
   * contains error description.
415
   */
Brad King's avatar
Brad King committed
416
  static std::string GetRealPath(const std::string& path,
417
                                 std::string* errorMessage = 0);
418

419
  /**
420 421 422
   * Split a path name into its root component and the rest of the
   * path.  The root component is one of the following:
   *    "/"   = UNIX full path
423 424 425
   *    "c:/" = Windows full path (can be any drive letter)
   *    "c:"  = Windows drive-letter relative path (can be any drive letter)
   *    "//"  = Network path
426 427
   *    "~/"  = Home path for current user
   *    "~u/" = Home path for user 'u'
428
   *    ""    = Relative path
429 430 431 432 433
   *
   * A pointer to the rest of the path after the root component is
   * returned.  The root component is stored in the "root" string if
   * given.
   */
434
  static const char* SplitPathRootComponent(const std::string& p,
435
                                            std::string* root = 0);
436 437 438

  /**
   * Split a path name into its basic components.  The first component
439
   * always exists and is the root returned by SplitPathRootComponent.
440 441 442
   * The remaining components form the path.  If there is a trailing
   * slash then the last component is the empty string.  The
   * components can be recombined as "c[0]c[1]/c[2]/.../c[n]" to
443 444 445
   * produce the original path.  Home directory references are
   * automatically expanded if expand_home_dir is true and this
   * platform supports them.
446
   */
447
  static void SplitPath(const std::string& p,
Brad King's avatar
Brad King committed
448
                        std::vector<std::string>& components,
449
                        bool expand_home_dir = true);
450 451 452 453 454

  /**
   * Join components of a path name into a single string.  See
   * SplitPath for the format of the components.
   */
455 456 457
  static std::string JoinPath(const std::vector<std::string>& components);
  static std::string JoinPath(std::vector<std::string>::const_iterator first,
                              std::vector<std::string>::const_iterator last);
458

Brad King's avatar
Brad King committed
459 460 461
  /**
   * Compare a path or components of a path.
   */
Brad King's avatar
Brad King committed
462
  static bool ComparePath(const std::string& c1, const std::string& c2);
Brad King's avatar
Brad King committed
463

464 465 466
  /**
   * Return path of a full filename (no trailing slashes)
   */
Brad King's avatar
Brad King committed
467
  static std::string GetFilenamePath(const std::string&);
468

469 470 471
  /**
   * Return file name of a full filename (i.e. file name without path)
   */
Brad King's avatar
Brad King committed
472
  static std::string GetFilenameName(const std::string&);
473

474 475 476
  /**
   * Split a program from its arguments and handle spaces in the paths
   */
477 478
  static void SplitProgramFromArgs(const std::string& path,
                                   std::string& program, std::string& args);
479

480 481 482
  /**
   * Return longest file extension of a full filename (dot included)
   */
Brad King's avatar
Brad King committed
483
  static std::string GetFilenameExtension(const std::string&);
484

485 486 487
  /**
   * Return shortest file extension of a full filename (dot included)
   */
488
  static std::string GetFilenameLastExtension(const std::string& filename);
489

490 491 492
  /**
   * Return file name without extension of a full filename
   */
493
  static std::string GetFilenameWithoutExtension(const std::string&);
494

495 496 497
  /**
   * Return file name without its last (shortest) extension
   */
498
  static std::string GetFilenameWithoutLastExtension(const std::string&);
499

500 501 502
  /**
   * Return whether the path represents a full path (not relative)
   */
Brad King's avatar
Brad King committed
503
  static bool FileIsFullPath(const std::string&);
504
  static bool FileIsFullPath(const char*);
505

506 507 508 509
  /**
   * For windows return the short path for the given path,
   * Unix just a pass through
   */
Brad King's avatar
Brad King committed
510
  static bool GetShortPath(const std::string& path, std::string& result);
511

512 513
  /**
   * Read line from file. Make sure to get everything. Due to a buggy stream
514
   * library on the HP and another on Mac OS X, we need this very carefully
515 516 517 518
   * written version of getline. Returns true if any data were read before the
   * end-of-file was reached. If the has_newline argument is specified, it will
   * be true when the line read had a newline character.
   */
519 520
  static bool GetLineFromStream(std::istream& istr, std::string& line,
                                bool* has_newline = 0, long sizeLimit = -1);
521

522 523 524
  /**
   * Get the parent directory of the directory or file
   */
Brad King's avatar
Brad King committed
525
  static std::string GetParentDirectory(const std::string& fileOrDir);
526

527 528
  /**
   * Check if the given file or directory is in subdirectory of dir
529
   */
530 531
  static bool IsSubDirectory(const std::string& fileOrDir,
                             const std::string& dir);
532

533 534 535 536 537
  /** -----------------------------------------------------------------
   *               File Manipulation Routines
   *  -----------------------------------------------------------------
   */

538 539 540
  /**
   * Open a file considering unicode.
   */
Brad King's avatar
Brad King committed
541
  static FILE* Fopen(const std::string& file, const char* mode);
542

543 544 545
  /**
   * Make a new directory if it is not there.  This function
   * can make a full path even if none of the directories existed
546
   * prior to calling this function.
547 548
   */
  static bool MakeDirectory(const char* path);
Brad King's avatar
Brad King committed
549
  static bool MakeDirectory(const std::string& path);
550 551 552

  /**
   * Copy the source file to the destination file only
553
   * if the two files differ.
554
   */
Brad King's avatar
Brad King committed
555 556
  static bool CopyFileIfDifferent(const std::string& source,
                                  const std::string& destination);
557

558 559 560
  /**
   * Compare the contents of two files.  Return true if different
   */
561 562
  static bool FilesDiffer(const std::string& source,
                          const std::string& destination);
563

564 565 566
  /**
   * Return true if the two files are the same file
   */
Brad King's avatar
Brad King committed
567
  static bool SameFile(const std::string& file1, const std::string& file2);
568

569
  /**
570
   * Copy a file.
571
   */
572 573
  static bool CopyFileAlways(const std::string& source,
                             const std::string& destination);
574 575

  /**
576 577
   * Copy a file.  If the "always" argument is true the file is always
   * copied.  If it is false, the file is copied only if it is new or
578
   * has changed.
579
   */
580 581
  static bool CopyAFile(const std::string& source,
                        const std::string& destination, bool always = true);
582 583 584 585 586 587 588

  /**
   * Copy content directory to another directory with all files and
   * subdirectories.  If the "always" argument is true all files are
   * always copied.  If it is false, only files that have changed or
   * are new are copied.
   */
589 590
  static bool CopyADirectory(const std::string& source,
                             const std::string& destination,
591
                             bool always = true);
592

593 594 595
  /**
   * Remove a file
   */
Brad King's avatar
Brad King committed
596
  static bool RemoveFile(const std::string& source);
597

598 599 600
  /**
   * Remove a directory
   */
Brad King's avatar
Brad King committed
601
  static bool RemoveADirectory(const std::string& source);
602

603 604 605 606 607
  /**
   * Get the maximum full file path length
   */
  static size_t GetMaximumFilePathLength();

608 609 610
  /**
   * Find a file in the system PATH, with optional extra paths
   */
Brad King's avatar
Brad King committed
611 612
  static std::string FindFile(
    const std::string& name,
613
    const std::vector<std::string>& path = std::vector<std::string>(),
614 615 616 617 618
    bool no_system_path = false);

  /**
   * Find a directory in the system PATH, with optional extra paths
   */
Brad King's avatar
Brad King committed
619 620
  static std::string FindDirectory(
    const std::string& name,
621
    const std::vector<std::string>& path = std::vector<std::string>(),
622
    bool no_system_path = false);
623 624 625 626

  /**
   * Find an executable in the system PATH, with optional extra paths
   */
Brad King's avatar
Brad King committed
627
  static std::string FindProgram(
628
    const char* name,
629
    const std::vector<std::string>& path = std::vector<std::string>(),
630
    bool no_system_path = false);
Brad King's avatar
Brad King committed
631 632
  static std::string FindProgram(
    const std::string& name,
633
    const std::vector<std::string>& path = std::vector<std::string>(),
634
    bool no_system_path = false);
Brad King's avatar
Brad King committed
635 636
  static std::string FindProgram(
    const std::vector<std::string>& names,
637
    const std::vector<std::string>& path = std::vector<std::string>(),
638
    bool no_system_path = false);
639 640 641 642

  /**
   * Find a library in the system PATH, with optional extra paths
   */
643 644
  static std::string FindLibrary(const std::string& name,
                                 const std::vector<std::string>& path);
645

646 647 648
  /**
   * Return true if the file is a directory
   */
Brad King's avatar
Brad King committed
649
  static bool FileIsDirectory(const std::string& name);
650

651 652 653
  /**
   * Return true if the file is a symlink
   */
Brad King's avatar
Brad King committed
654
  static bool FileIsSymlink(const std::string& name);
655

656
  /**
657
   * Return true if the file has a given signature (first set of bytes)
658
   */
659 660
  static bool FileHasSignature(const char* filename, const char* signature,
                               long offset = 0);
661

662 663 664 665 666
  /**
   * Attempt to detect and return the type of a file.
   * Up to 'length' bytes are read from the file, if more than 'percent_bin' %
   * of the bytes are non-textual elements, the file is considered binary,
   * otherwise textual. Textual elements are bytes in the ASCII [0x20, 0x7E]
Brad King's avatar
Brad King committed
667
   * range, but also \\n, \\r, \\t.
668 669 670
   * The algorithm is simplistic, and should probably check for usual file
   * extensions, 'magic' signature, unicode, etc.
   */
671 672
  enum FileTypeEnum
  {
673 674 675 676
    FileTypeUnknown,
    FileTypeBinary,
    FileTypeText
  };
677 678 679
  static SystemTools::FileTypeEnum DetectFileType(const char* filename,
                                                  unsigned long length = 256,
                                                  double percent_bin = 0.05);
680

681 682
  /**
   * Create a symbolic link if the platform supports it.  Returns whether
683
   * creation succeeded.
684
   */
685 686
  static bool CreateSymlink(const std::string& origName,
                            const std::string& newName);
687 688 689

  /**
   * Read the contents of a symbolic link.  Returns whether reading
690
   * succeeded.
691
   */
Brad King's avatar
Brad King committed
692
  static bool ReadSymlink(const std::string& newName, std::string& origName);
693

694 695 696 697 698 699 700 701 702 703
  /**
   * Try to locate the file 'filename' in the directory 'dir'.
   * If 'filename' is a fully qualified filename, the basename of the file is
   * used to check for its existence in 'dir'.
   * If 'dir' is not a directory, GetFilenamePath() is called on 'dir' to
   * get its directory first (thus, you can pass a filename as 'dir', as
   * a convenience).
   * 'filename_found' is assigned the fully qualified name/path of the file
   * if it is found (not touched otherwise).
   * If 'try_filename_dirs' is true, try to find the file using the
704
   * components of its path, i.e. if we are looking for c:/foo/bar/bill.txt,
705 706 707 708
   * first look for bill.txt in 'dir', then in 'dir'/bar, then in 'dir'/foo/bar
   * etc.
   * Return true if the file was found, false otherwise.
   */
709
  static bool LocateFileInDir(const char* filename, const char* dir,
Brad King's avatar
Brad King committed
710
                              std::string& filename_found,
711 712
                              int try_filename_dirs = 0);

713 714
  /** compute the relative path from local to remote.  local must
      be a directory.  remote can be a file or a directory.
715 716 717 718 719 720
      Both remote and local must be full paths.  Basically, if
      you are in directory local and you want to access the file in remote
      what is the relative path to do that.  For example:
      /a/b/c/d to /a/b/c1/d1 -> ../../c1/d1
      from /usr/src to /usr/src/test/blah/foo.cpp -> test/blah/foo.cpp
  */
721 722
  static std::string RelativePath(const std::string& local,
                                  const std::string& remote);
723

724 725 726
  /**
   * Return file's modified time
   */
Brad King's avatar
Brad King committed
727
  static long int ModifiedTime(const std::string& filename);
728 729 730 731

  /**
   * Return file's creation time (Win32: works only for NTFS, not FAT)
   */
Brad King's avatar
Brad King committed
732
  static long int CreationTime(const std::string& filename);
733

734 735 736 737
/**
 * Visual C++ does not define mode_t (note that Borland does, however).
 */
#if defined(_MSC_VER)
738
  typedef unsigned short mode_t;
739
#endif
740

741
  /**
742 743 744 745 746 747
   * Get and set permissions of the file.  If honor_umask is set, the umask
   * is queried and applied to the given permissions.  Returns false if
   * failure.
   *
   * WARNING:  A non-thread-safe method is currently used to get the umask
   * if a honor_umask parameter is set to true.
748 749
   */
  static bool GetPermissions(const char* file, mode_t& mode);
Brad King's avatar
Brad King committed
750
  static bool GetPermissions(const std::string& file, mode_t& mode);
751 752 753 754
  static bool SetPermissions(const char* file, mode_t mode,
                             bool honor_umask = false);
  static bool SetPermissions(const std::string& file, mode_t mode,
                             bool honor_umask = false);
755 756 757 758 759 760

  /** -----------------------------------------------------------------
   *               Time Manipulation Routines
   *  -----------------------------------------------------------------
   */

761
  /** Get current time in seconds since Posix Epoch (Jan 1, 1970).  */
762 763 764 765 766
  static double GetTime();

  /**
   * Get current date/time
   */
Brad King's avatar
Brad King committed
767
  static std::string GetCurrentDateTime(const char* format);
768

769 770 771 772 773
  /** -----------------------------------------------------------------
   *               Registry Manipulation Routines
   *  -----------------------------------------------------------------
   */

774 775 776 777 778
  /**
   * Specify access to the 32-bit or 64-bit application view of
   * registry values.  The default is to match the currently running
   * binary type.
   */
779 780 781 782 783 784
  enum KeyWOW64
  {
    KeyWOW64_Default,
    KeyWOW64_32,
    KeyWOW64_64
  };
785

786 787 788
  /**
   * Get a list of subkeys.
   */
Brad King's avatar
Brad King committed
789 790
  static bool GetRegistrySubKeys(const std::string& key,
                                 std::vector<std::string>& subkeys,
791 792
                                 KeyWOW64 view = KeyWOW64_Default);

793 794 795
  /**
   * Read a registry value
   */
796
  static bool ReadRegistryValue(const std::string& key, std::string& value,
797
                                KeyWOW64 view = KeyWOW64_Default);
798 799 800 801

  /**
   * Write a registry value
   */
802 803
  static bool WriteRegistryValue(const std::string& key,
                                 const std::string& value,
804
                                 KeyWOW64 view = KeyWOW64_Default);
805 806 807 808

  /**
   * Delete a registry value
   */
Brad King's avatar
Brad King committed
809
  static bool DeleteRegistryValue(const std::string& key,
810
                                  KeyWOW64 view = KeyWOW64_Default);
811 812 813 814 815 816 817

  /** -----------------------------------------------------------------
   *               Environment Manipulation Routines
   *  -----------------------------------------------------------------
   */

  /**
818
   *  Add the paths from the environment variable PATH to the
819 820 821
   *  string vector passed in.  If env is set then the value
   *  of env will be used instead of PATH.
   */
822
  static void GetPath(std::vector<std::string>& path, const char* env = 0);
823 824 825 826 827

  /**
   * Read an environment variable
   */
  static const char* GetEnv(const char* key);
Brad King's avatar
Brad King committed
828 829 830
  static const char* GetEnv(const std::string& key);
  static bool GetEnv(const char* key, std::string& result);
  static bool GetEnv(const std::string& key, std::string& result);
831 832
  static bool HasEnv(const char* key);
  static bool HasEnv(const std::string& key);
833

834 835
  /** Put a string into the environment
      of the form var=value */
Brad King's avatar
Brad King committed
836
  static bool PutEnv(const std::string& env);
837 838 839

  /** Remove a string from the environment.
      Input is of the form "var" or "var=value" (value is ignored). */
Brad King's avatar
Brad King committed
840
  static bool UnPutEnv(const std::string& env);
841

842 843 844
  /**
   * Get current working directory CWD
   */
845
  static std::string GetCurrentWorkingDirectory(bool collapse = true);
846 847

  /**
848
   * Change directory to the directory specified
849
   */
Brad King's avatar
Brad King committed
850
  static int ChangeDirectory(const std::string& dir);
851 852 853 854

  /**
   * Get the result of strerror(errno)
   */
Brad King's avatar
Brad King committed
855
  static std::string GetLastSystemError();
856 857

  /**
858
   * When building DEBUG with MSVC, this enables a hook that prevents
859 860 861 862 863
   * error dialogs from popping up if the program is being run from
   * DART.
   */
  static void EnableMSVCDebugHook();

864 865 866 867 868 869
  /**
   * Get the width of the terminal window. The code may or may not work, so
   * make sure you have some resonable defaults prepared if the code returns
   * some bogus size.
   */
  static int GetTerminalWidth();
870

871 872 873
  /**
   * Add an entry in the path translation table.
   */
874 875
  static void AddTranslationPath(const std::string& dir,
                                 const std::string& refdir);
876 877 878 879 880

  /**
   * If dir is different after CollapseFullPath is called,
   * Then insert it into the path translation table
   */
Brad King's avatar
Brad King committed
881
  static void AddKeepPath(const std::string& dir);
882 883 884 885

  /**
   * Update path by going through the Path Translation table;
   */
886
  static void CheckTranslationPath(std::string& path);
887

888 889 890
  /**
   * Delay the execution for a specified amount of time specified
   * in miliseconds
891
   */
Andy Cedilnik's avatar
Andy Cedilnik committed
892 893
  static void Delay(unsigned int msec);

894
  /**
895 896 897
   * Get the operating system name and version
   * This is implemented for Win32 only for the moment
   */
Brad King's avatar
Brad King committed
898
  static std::string GetOperatingSystemNameAndVersion();
899

900 901 902 903 904 905 906 907 908 909 910
  /** -----------------------------------------------------------------
   *               URL Manipulation Routines
   *  -----------------------------------------------------------------
   */

  /**
   * Parse a character string :
   *       protocol://dataglom
   * and fill protocol as appropriate.
   * Return false if the URL does not have the required form, true otherwise.
   */
911 912
  static bool ParseURLProtocol(const std::string& URL, std::string& protocol,
                               std::string& dataglom);
913 914 915 916 917 918 919 920

  /**
   * Parse a string (a URL without protocol prefix) with the form:
   *  protocol://[[username[':'password]'@']hostname[':'dataport]]'/'[datapath]
   * and fill protocol, username, password, hostname, dataport, and datapath
   * when values are found.
   * Return true if the string matches the format; false otherwise.
   */
921 922 923 924
  static bool ParseURL(const std::string& URL, std::string& protocol,
                       std::string& username, std::string& password,
                       std::string& hostname, std::string& dataport,
                       std::string& datapath);
925

926
private:
927
  /**
928
   * Allocate the stl map that serve as the Path Translation table.
929 930 931 932
   */
  static void ClassInitialize();

  /**
933
   * Deallocate the stl map that serve as the Path Translation table.
934 935 936
   */
  static void ClassFinalize();

937 938 939 940
  /**
   * This method prevents warning on SGI
   */
  SystemToolsManager* GetSystemToolsManager()
941
  {
942
    return &SystemToolsManagerInstance;
943
  }
944

945 946 947
  /**
   * Actual implementation of ReplaceString.
   */
948 949
  static void ReplaceString(std::string& source, const char* replace,
                            size_t replaceSize, const std::string& with);
950

951 952 953 954 955
  /**
   * Actual implementation of FileIsFullPath.
   */
  static bool FileIsFullPath(const char*, size_t);

956 957 958 959
  /**
   * Find a filename (file or directory) in the system PATH, with
   * optional extra paths.
   */
Brad King's avatar
Brad King committed
960 961
  static std::string FindName(
    const std::string& name,
962
    const std::vector<std::string>& path = std::vector<std::string>(),
963 964
    bool no_system_path = false);

965
  static const char* GetEnvImpl(const char* key);
966

967 968 969 970
  /**
   * Path translation table from dir to refdir
   * Each time 'dir' will be found it will be replace by 'refdir'
   */
971
  static SystemToolsTranslationMap* TranslationMap;
972
#ifdef _WIN32
973 974
  static SystemToolsPathCaseMap* PathCaseMap;
  static SystemToolsEnvMap* EnvMap;
975
#endif
976
#ifdef __CYGWIN__
977
  static SystemToolsTranslationMap* Cyg2Win32Map;
978
#endif
979 980 981
  friend class SystemToolsManager;
};

982 983 984
} // namespace @KWSYS_NAMESPACE@

#endif