summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2003-04-08 17:10:44 (GMT)
committerBrad King <brad.king@kitware.com>2003-04-08 17:10:44 (GMT)
commit7dff3a7f69d1ec1e36d38903e94e433f6583d96e (patch)
tree52188fec4a7e35d1fd08e3ed6c3dcfbf1095a818
parent7f48313225537a7bcc92c0f1c73754bdc50a2ca4 (diff)
downloadCMake-7dff3a7f69d1ec1e36d38903e94e433f6583d96e.zip
CMake-7dff3a7f69d1ec1e36d38903e94e433f6583d96e.tar.gz
CMake-7dff3a7f69d1ec1e36d38903e94e433f6583d96e.tar.bz2
ENH: Added kwsys library for platform-independent system tools.
-rw-r--r--Source/kwsys/CMakeLists.txt47
-rw-r--r--Source/kwsys/Configure.hxx.in10
-rw-r--r--Source/kwsys/Directory.cxx116
-rw-r--r--Source/kwsys/Directory.hxx.in65
-rw-r--r--Source/kwsys/RegularExpression.cxx1211
-rw-r--r--Source/kwsys/RegularExpression.hxx.in385
-rw-r--r--Source/kwsys/StandardIncludes.hxx.in44
-rw-r--r--Source/kwsys/SystemTools.cxx1793
-rw-r--r--Source/kwsys/SystemTools.hxx.in285
9 files changed, 3956 insertions, 0 deletions
diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt
new file mode 100644
index 0000000..f5df8e2
--- /dev/null
+++ b/Source/kwsys/CMakeLists.txt
@@ -0,0 +1,47 @@
+PROJECT(${KWSYS_NAMESPACE})
+INCLUDE(${CMAKE_ROOT}/Modules/TestForANSIStreamHeaders.cmake)
+INCLUDE(${CMAKE_ROOT}/Modules/CheckIncludeFileCXX.cmake)
+INCLUDE(${CMAKE_ROOT}/Modules/TestForSTDNamespace.cmake)
+INCLUDE(${CMAKE_ROOT}/Modules/TestForANSIForScope.cmake)
+CHECK_INCLUDE_FILE_CXX("sstream" CMAKE_HAS_ANSI_STRING_STREAM)
+
+SET(KWSYS_NO_STD_NAMESPACE ${CMAKE_NO_STD_NAMESPACE})
+SET(KWSYS_NO_ANSI_STREAM_HEADERS ${CMAKE_NO_ANSI_STREAM_HEADERS})
+SET(KWSYS_NO_ANSI_STRING_STREAM ${CMAKE_NO_ANSI_STRING_STREAM})
+SET(KWSYS_NO_ANSI_FOR_SCOPE ${CMAKE_NO_ANSI_FOR_SCOPE})
+
+SET(CLASSES Directory RegularExpression SystemTools)
+SET(HEADERS Configure StandardIncludes)
+
+SET(SRCS)
+SET(KWSYS_INCLUDES)
+FOREACH(c ${CLASSES})
+ SET(SRCS ${SRCS} ${c}.cxx)
+ CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/${c}.hxx.in
+ ${PROJECT_BINARY_DIR}/../${KWSYS_NAMESPACE}/${c}.hxx
+ @ONLY IMMEDIATE)
+ SET(KWSYS_INCLUDES ${KWSYS_INCLUDES}
+ ${PROJECT_BINARY_DIR}/../${KWSYS_NAMESPACE}/${c}.hxx)
+ENDFOREACH(c)
+
+FOREACH(h ${HEADERS})
+ CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/${h}.hxx.in
+ ${PROJECT_BINARY_DIR}/../${KWSYS_NAMESPACE}/${h}.hxx
+ @ONLY IMMEDIATE)
+ SET(KWSYS_INCLUDES ${KWSYS_INCLUDES}
+ ${PROJECT_BINARY_DIR}/../${KWSYS_NAMESPACE}/${h}.hxx)
+ENDFOREACH(h)
+
+ADD_LIBRARY(${KWSYS_NAMESPACE} ${SRCS})
+
+ADD_DEFINITIONS("-DKWSYS_NAMESPACE=${KWSYS_NAMESPACE}")
+INCLUDE_DIRECTORIES(BEFORE ${PROJECT_BINARY_DIR}/../${KWSYS_NAMESPACE})
+
+IF(KWSYS_LIBRARY_INSTALL_DIR)
+ INSTALL_TARGETS(${KWSYS_LIBRARY_INSTALL_DIR} ${KWSYS_NAMESPACE})
+ENDIF(KWSYS_LIBRARY_INSTALL_DIR)
+
+IF(KWSYS_INCLUDE_INSTALL_DIR)
+ INSTALL_FILES(${KWSYS_INCLUDE_INSTALL_DIR}/${KWSYS_NAMESPACE}
+ FILES ${KWSYS_INCLUDES})
+ENDIF(KWSYS_INCLUDE_INSTALL_DIR)
diff --git a/Source/kwsys/Configure.hxx.in b/Source/kwsys/Configure.hxx.in
new file mode 100644
index 0000000..baa9c74
--- /dev/null
+++ b/Source/kwsys/Configure.hxx.in
@@ -0,0 +1,10 @@
+#ifndef @KWSYS_NAMESPACE@_Configure_hxx
+#define @KWSYS_NAMESPACE@_Configure_hxx
+
+/* This configuration should match for all instances of kwsys. */
+#cmakedefine KWSYS_NO_STD_NAMESPACE
+#cmakedefine KWSYS_NO_ANSI_STREAM_HEADERS
+#cmakedefine KWSYS_NO_ANSI_STRING_STREAM
+#cmakedefine KWSYS_NO_ANSI_FOR_SCOPE
+
+#endif
diff --git a/Source/kwsys/Directory.cxx b/Source/kwsys/Directory.cxx
new file mode 100644
index 0000000..3036081
--- /dev/null
+++ b/Source/kwsys/Directory.cxx
@@ -0,0 +1,116 @@
+/*=========================================================================
+
+ Program: KWSys - Kitware System Library
+ Module: $RCSfile$
+ Language: C++
+ Date: $Date$
+ Version: $Revision$
+
+ Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
+ See http://www.cmake.org/HTML/Copyright.html for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the above copyright notices for more information.
+
+=========================================================================*/
+#include <Directory.hxx>
+
+// First microsoft compilers
+
+#ifdef _MSC_VER
+#include <windows.h>
+#include <io.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+namespace KWSYS_NAMESPACE
+{
+
+bool Directory::Load(const char* name)
+{
+ char* buf;
+ size_t n = strlen(name);
+ if ( name[n - 1] == '/' )
+ {
+ buf = new char[n + 1 + 1];
+ sprintf(buf, "%s*", name);
+ }
+ else
+ {
+ buf = new char[n + 2 + 1];
+ sprintf(buf, "%s/*", name);
+ }
+ struct _finddata_t data; // data of current file
+
+ // Now put them into the file array
+ size_t srchHandle = _findfirst(buf, &data);
+ delete [] buf;
+
+ if ( srchHandle == -1 )
+ {
+ return 0;
+ }
+
+ // Loop through names
+ do
+ {
+ m_Files.push_back(data.name);
+ }
+ while ( _findnext(srchHandle, &data) != -1 );
+ m_Path = name;
+ return _findclose(srchHandle) != -1;
+}
+
+} // namespace KWSYS_NAMESPACE
+
+#else
+
+// Now the POSIX style directory access
+
+#include <sys/types.h>
+#include <dirent.h>
+
+namespace KWSYS_NAMESPACE
+{
+
+bool Directory::Load(const char* name)
+{
+ DIR* dir = opendir(name);
+
+ if (!dir)
+ {
+ return 0;
+ }
+
+ for (dirent* d = readdir(dir); d; d = readdir(dir) )
+ {
+ m_Files.push_back(d->d_name);
+ }
+ m_Path = name;
+ closedir(dir);
+ return 1;
+}
+
+} // namespace KWSYS_NAMESPACE
+
+#endif
+
+namespace KWSYS_NAMESPACE
+{
+
+const char* Directory::GetFile(size_t dindex)
+{
+ if ( dindex >= m_Files.size() )
+ {
+ return 0;
+ }
+ return m_Files[dindex].c_str();
+}
+
+} // namespace KWSYS_NAMESPACE
diff --git a/Source/kwsys/Directory.hxx.in b/Source/kwsys/Directory.hxx.in
new file mode 100644
index 0000000..7182a28
--- /dev/null
+++ b/Source/kwsys/Directory.hxx.in
@@ -0,0 +1,65 @@
+/*=========================================================================
+
+ Program: KWSys - Kitware System Library
+ Module: $RCSfile$
+ Language: C++
+ Date: $Date$
+ Version: $Revision$
+
+ Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
+ See http://www.cmake.org/HTML/Copyright.html for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef @KWSYS_NAMESPACE@_Directory_hxx
+#define @KWSYS_NAMESPACE@_Directory_hxx
+
+#include <@KWSYS_NAMESPACE@/StandardIncludes.hxx>
+
+#include <string>
+#include <vector>
+
+namespace @KWSYS_NAMESPACE@
+{
+
+/** \class Directory
+ * \brief Portable directory/filename traversal.
+ *
+ * Directory provides a portable way of finding the names of the files
+ * in a system directory.
+ *
+ * Directory currently works with Windows and Unix operating systems.
+ */
+
+class Directory
+{
+public:
+ /**
+ * Load the specified directory and load the names of the files
+ * in that directory. 0 is returned if the directory can not be
+ * opened, 1 if it is opened.
+ */
+ bool Load(const char* dir);
+
+ /**
+ * Return the number of files in the current directory.
+ */
+ size_t GetNumberOfFiles() { return m_Files.size();}
+
+ /**
+ * Return the file at the given index, the indexing is 0 based
+ */
+ const char* GetFile(size_t );
+
+private:
+ kwsys_std::vector<kwsys_std::string> m_Files; // Array of Files
+ kwsys_std::string m_Path; // Path to Open'ed directory
+
+}; // End Class: Directory
+
+} // namespace @KWSYS_NAMESPACE@
+
+#endif
diff --git a/Source/kwsys/RegularExpression.cxx b/Source/kwsys/RegularExpression.cxx
new file mode 100644
index 0000000..f9a3291
--- /dev/null
+++ b/Source/kwsys/RegularExpression.cxx
@@ -0,0 +1,1211 @@
+/*=========================================================================
+
+ Program: KWSys - Kitware System Library
+ Module: $RCSfile$
+ Language: C++
+ Date: $Date$
+ Version: $Revision$
+
+ Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
+ See http://www.cmake.org/HTML/Copyright.html for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the above copyright notices for more information.
+
+=========================================================================*/
+//
+// Copyright (C) 1991 Texas Instruments Incorporated.
+//
+// Permission is granted to any individual or institution to use, copy, modify,
+// and distribute this software, provided that this complete copyright and
+// permission notice is maintained, intact, in all copies and supporting
+// documentation.
+//
+// Texas Instruments Incorporated provides this software "as is" without
+// express or implied warranty.
+//
+//
+// Created: MNF 06/13/89 Initial Design and Implementation
+// Updated: LGO 08/09/89 Inherit from Generic
+// Updated: MBN 09/07/89 Added conditional exception handling
+// Updated: MBN 12/15/89 Sprinkled "const" qualifiers all over the place!
+// Updated: DLS 03/22/91 New lite version
+//
+
+#include <RegularExpression.hxx> // Include class specification
+#include <stdio.h>
+
+namespace KWSYS_NAMESPACE
+{
+
+// RegularExpression -- Copies the given regular expression.
+RegularExpression::RegularExpression (const RegularExpression& rxp) {
+ if ( !rxp.program )
+ {
+ this->program = 0;
+ return;
+ }
+ int ind;
+ this->progsize = rxp.progsize; // Copy regular expression size
+ this->program = new char[this->progsize]; // Allocate storage
+ for(ind=this->progsize; ind-- != 0;) // Copy regular expresion
+ this->program[ind] = rxp.program[ind];
+ this->startp[0] = rxp.startp[0]; // Copy pointers into last
+ this->endp[0] = rxp.endp[0]; // Successful "find" operation
+ this->regmust = rxp.regmust; // Copy field
+ if (rxp.regmust != 0) {
+ char* dum = rxp.program;
+ ind = 0;
+ while (dum != rxp.regmust) {
+ ++dum;
+ ++ind;
+ }
+ this->regmust = this->program + ind;
+ }
+ this->regstart = rxp.regstart; // Copy starting index
+ this->reganch = rxp.reganch; // Copy remaining private data
+ this->regmlen = rxp.regmlen; // Copy remaining private data
+}
+
+// operator== -- Returns true if two regular expressions have the same
+// compiled program for pattern matching.
+bool RegularExpression::operator== (const RegularExpression& rxp) const {
+ if (this != &rxp) { // Same address?
+ int ind = this->progsize; // Get regular expression size
+ if (ind != rxp.progsize) // If different size regexp
+ return false; // Return failure
+ while(ind-- != 0) // Else while still characters
+ if(this->program[ind] != rxp.program[ind]) // If regexp are different
+ return false; // Return failure
+ }
+ return true; // Else same, return success
+}
+
+
+// deep_equal -- Returns true if have the same compiled regular expressions
+// and the same start and end pointers.
+
+bool RegularExpression::deep_equal (const RegularExpression& rxp) const {
+ int ind = this->progsize; // Get regular expression size
+ if (ind != rxp.progsize) // If different size regexp
+ return false; // Return failure
+ while(ind-- != 0) // Else while still characters
+ if(this->program[ind] != rxp.program[ind]) // If regexp are different
+ return false; // Return failure
+ return (this->startp[0] == rxp.startp[0] && // Else if same start/end ptrs,
+ this->endp[0] == rxp.endp[0]); // Return true
+}
+
+// The remaining code in this file is derived from the regular expression code
+// whose copyright statement appears below. It has been changed to work
+// with the class concepts of C++ and COOL.
+
+/*
+ * compile and find
+ *
+ * Copyright (c) 1986 by University of Toronto.
+ * Written by Henry Spencer. Not derived from licensed software.
+ *
+ * Permission is granted to anyone to use this software for any
+ * purpose on any computer system, and to redistribute it freely,
+ * subject to the following restrictions:
+ *
+ * 1. The author is not responsible for the consequences of use of
+ * this software, no matter how awful, even if they arise
+ * from defects in it.
+ *
+ * 2. The origin of this software must not be misrepresented, either
+ * by explicit claim or by omission.
+ *
+ * 3. Altered versions must be plainly marked as such, and must not
+ * be misrepresented as being the original software.
+ *
+ * Beware that some of this code is subtly aware of the way operator
+ * precedence is structured in regular expressions. Serious changes in
+ * regular-expression syntax might require a total rethink.
+ */
+
+/*
+ * The "internal use only" fields in regexp.h are present to pass info from
+ * compile to execute that permits the execute phase to run lots faster on
+ * simple cases. They are:
+ *
+ * regstart char that must begin a match; '\0' if none obvious
+ * reganch is the match anchored (at beginning-of-line only)?
+ * regmust string (pointer into program) that match must include, or NULL
+ * regmlen length of regmust string
+ *
+ * Regstart and reganch permit very fast decisions on suitable starting points
+ * for a match, cutting down the work a lot. Regmust permits fast rejection
+ * of lines that cannot possibly match. The regmust tests are costly enough
+ * that compile() supplies a regmust only if the r.e. contains something
+ * potentially expensive (at present, the only such thing detected is * or +
+ * at the start of the r.e., which can involve a lot of backup). Regmlen is
+ * supplied because the test in find() needs it and compile() is computing
+ * it anyway.
+ */
+
+/*
+ * Structure for regexp "program". This is essentially a linear encoding
+ * of a nondeterministic finite-state machine (aka syntax charts or
+ * "railroad normal form" in parsing technology). Each node is an opcode
+ * plus a "next" pointer, possibly plus an operand. "Next" pointers of
+ * all nodes except BRANCH implement concatenation; a "next" pointer with
+ * a BRANCH on both ends of it is connecting two alternatives. (Here we
+ * have one of the subtle syntax dependencies: an individual BRANCH (as
+ * opposed to a collection of them) is never concatenated with anything
+ * because of operator precedence.) The operand of some types of node is
+ * a literal string; for others, it is a node leading into a sub-FSM. In
+ * particular, the operand of a BRANCH node is the first node of the branch.
+ * (NB this is *not* a tree structure: the tail of the branch connects
+ * to the thing following the set of BRANCHes.) The opcodes are:
+ */
+
+// definition number opnd? meaning
+#define END 0 // no End of program.
+#define BOL 1 // no Match "" at beginning of line.
+#define EOL 2 // no Match "" at end of line.
+#define ANY 3 // no Match any one character.
+#define ANYOF 4 // str Match any character in this string.
+#define ANYBUT 5 // str Match any character not in this
+ // string.
+#define BRANCH 6 // node Match this alternative, or the
+ // next...
+#define BACK 7 // no Match "", "next" ptr points backward.
+#define EXACTLY 8 // str Match this string.
+#define NOTHING 9 // no Match empty string.
+#define STAR 10 // node Match this (simple) thing 0 or more
+ // times.
+#define PLUS 11 // node Match this (simple) thing 1 or more
+ // times.
+#define OPEN 20 // no Mark this point in input as start of
+ // #n.
+// OPEN+1 is number 1, etc.
+#define CLOSE 30 // no Analogous to OPEN.
+
+/*
+ * Opcode notes:
+ *
+ * BRANCH The set of branches constituting a single choice are hooked
+ * together with their "next" pointers, since precedence prevents
+ * anything being concatenated to any individual branch. The
+ * "next" pointer of the last BRANCH in a choice points to the
+ * thing following the whole choice. This is also where the
+ * final "next" pointer of each individual branch points; each
+ * branch starts with the operand node of a BRANCH node.
+ *
+ * BACK Normal "next" pointers all implicitly point forward; BACK
+ * exists to make loop structures possible.
+ *
+ * STAR,PLUS '?', and complex '*' and '+', are implemented as circular
+ * BRANCH structures using BACK. Simple cases (one character
+ * per match) are implemented with STAR and PLUS for speed
+ * and to minimize recursive plunges.
+ *
+ * OPEN,CLOSE ...are numbered at compile time.
+ */
+
+/*
+ * A node is one char of opcode followed by two chars of "next" pointer.
+ * "Next" pointers are stored as two 8-bit pieces, high order first. The
+ * value is a positive offset from the opcode of the node containing it.
+ * An operand, if any, simply follows the node. (Note that much of the
+ * code generation knows about this implicit relationship.)
+ *
+ * Using two bytes for the "next" pointer is vast overkill for most things,
+ * but allows patterns to get big without disasters.
+ */
+
+#define OP(p) (*(p))
+#define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
+#define OPERAND(p) ((p) + 3)
+
+const unsigned char MAGIC = 0234;
+/*
+ * Utility definitions.
+ */
+
+#define UCHARAT(p) ((const unsigned char*)(p))[0]
+
+
+#define FAIL(m) { regerror(m); return(0); }
+#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?')
+#define META "^$.[()|?+*\\"
+
+
+/*
+ * Flags to be passed up and down.
+ */
+#define HASWIDTH 01 // Known never to match null string.
+#define SIMPLE 02 // Simple enough to be STAR/PLUS operand.
+#define SPSTART 04 // Starts with * or +.
+#define WORST 0 // Worst case.
+
+
+
+/////////////////////////////////////////////////////////////////////////
+//
+// COMPILE AND ASSOCIATED FUNCTIONS
+//
+/////////////////////////////////////////////////////////////////////////
+
+
+/*
+ * Global work variables for compile().
+ */
+static const char* regparse; // Input-scan pointer.
+static int regnpar; // () count.
+static char regdummy;
+static char* regcode; // Code-emit pointer; &regdummy = don't.
+static long regsize; // Code size.
+
+/*
+ * Forward declarations for compile()'s friends.
+ */
+// #ifndef static
+// #define static static
+// #endif
+static char* reg (int, int*);
+static char* regbranch (int*);
+static char* regpiece (int*);
+static char* regatom (int*);
+static char* regnode (char);
+static const char* regnext (register const char*);
+static char* regnext (register char*);
+static void regc (unsigned char);
+static void reginsert (char, char*);
+static void regtail (char*, const char*);
+static void regoptail (char*, const char*);
+
+#ifdef STRCSPN
+static int strcspn ();
+#endif
+
+
+
+/*
+ * We can't allocate space until we know how big the compiled form will be,
+ * but we can't compile it (and thus know how big it is) until we've got a
+ * place to put the code. So we cheat: we compile it twice, once with code
+ * generation turned off and size counting turned on, and once "for real".
+ * This also means that we don't allocate space until we are sure that the
+ * thing really will compile successfully, and we never have to move the
+ * code and thus invalidate pointers into it. (Note that it has to be in
+ * one piece because free() must be able to free it all.)
+ *
+ * Beware that the optimization-preparation code in here knows about some
+ * of the structure of the compiled regexp.
+ */
+
+
+// compile -- compile a regular expression into internal code
+// for later pattern matching.
+
+bool RegularExpression::compile (const char* exp) {
+ register const char* scan;
+ register const char* longest;
+ register unsigned long len;
+ int flags;
+
+ if (exp == 0) {
+ //RAISE Error, SYM(RegularExpression), SYM(No_Expr),
+ printf ("RegularExpression::compile(): No expression supplied.\n");
+ return false;
+ }
+
+ // First pass: determine size, legality.
+ regparse = exp;
+ regnpar = 1;
+ regsize = 0L;
+ regcode = &regdummy;
+ regc(MAGIC);
+ if(!reg(0, &flags))
+ {
+ printf ("RegularExpression::compile(): Error in compile.\n");
+ return false;
+ }
+ this->startp[0] = this->endp[0] = this->searchstring = 0;
+
+ // Small enough for pointer-storage convention?
+ if (regsize >= 32767L) { // Probably could be 65535L.
+ //RAISE Error, SYM(RegularExpression), SYM(Expr_Too_Big),
+ printf ("RegularExpression::compile(): Expression too big.\n");
+ return false;
+ }
+
+ // Allocate space.
+//#ifndef WIN32
+ if (this->program != 0) delete [] this->program;
+//#endif
+ this->program = new char[regsize];
+ this->progsize = (int) regsize;
+
+ if (this->program == 0) {
+ //RAISE Error, SYM(RegularExpression), SYM(Out_Of_Memory),
+ printf ("RegularExpression::compile(): Out of memory.\n");
+ return false;
+ }
+
+ // Second pass: emit code.
+ regparse = exp;
+ regnpar = 1;
+ regcode = this->program;
+ regc(MAGIC);
+ reg(0, &flags);
+
+ // Dig out information for optimizations.
+ this->regstart = '\0'; // Worst-case defaults.
+ this->reganch = 0;
+ this->regmust = 0;
+ this->regmlen = 0;
+ scan = this->program + 1; // First BRANCH.
+ if (OP(regnext(scan)) == END) { // Only one top-level choice.
+ scan = OPERAND(scan);
+
+ // Starting-point info.
+ if (OP(scan) == EXACTLY)
+ this->regstart = *OPERAND(scan);
+ else if (OP(scan) == BOL)
+ this->reganch++;
+
+ //
+ // If there's something expensive in the r.e., find the longest
+ // literal string that must appear and make it the regmust. Resolve
+ // ties in favor of later strings, since the regstart check works
+ // with the beginning of the r.e. and avoiding duplication
+ // strengthens checking. Not a strong reason, but sufficient in the
+ // absence of others.
+ //
+ if (flags & SPSTART) {
+ longest = 0;
+ len = 0;
+ for (; scan != 0; scan = regnext(scan))
+ if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) {
+ longest = OPERAND(scan);
+ len = int(strlen(OPERAND(scan)));
+ }
+ this->regmust = longest;
+ this->regmlen = len;
+ }
+ }
+ return true;
+}
+
+
+/*
+ - reg - regular expression, i.e. main body or parenthesized thing
+ *
+ * Caller must absorb opening parenthesis.
+ *
+ * Combining parenthesis handling with the base level of regular expression
+ * is a trifle forced, but the need to tie the tails of the branches to what
+ * follows makes it hard to avoid.
+ */
+static char* reg (int paren, int *flagp) {
+ register char* ret;
+ register char* br;
+ register char* ender;
+ register int parno =0;
+ int flags;
+
+ *flagp = HASWIDTH; // Tentatively.
+
+ // Make an OPEN node, if parenthesized.
+ if (paren) {
+ if (regnpar >= RegularExpressionNSUBEXP) {
+ //RAISE Error, SYM(RegularExpression), SYM(Too_Many_Parens),
+ printf ("RegularExpression::compile(): Too many parentheses.\n");
+ return 0;
+ }
+ parno = regnpar;
+ regnpar++;
+ ret = regnode(OPEN + parno);
+ }
+ else
+ ret = 0;
+
+ // Pick up the branches, linking them together.
+ br = regbranch(&flags);
+ if (br == 0)
+ return (0);
+ if (ret != 0)
+ regtail(ret, br); // OPEN -> first.
+ else
+ ret = br;
+ if (!(flags & HASWIDTH))
+ *flagp &= ~HASWIDTH;
+ *flagp |= flags & SPSTART;
+ while (*regparse == '|') {
+ regparse++;
+ br = regbranch(&flags);
+ if (br == 0)
+ return (0);
+ regtail(ret, br); // BRANCH -> BRANCH.
+ if (!(flags & HASWIDTH))
+ *flagp &= ~HASWIDTH;
+ *flagp |= flags & SPSTART;
+ }
+
+ // Make a closing node, and hook it on the end.
+ ender = regnode((paren) ? CLOSE + parno : END);
+ regtail(ret, ender);
+
+ // Hook the tails of the branches to the closing node.
+ for (br = ret; br != 0; br = regnext(br))
+ regoptail(br, ender);
+
+ // Check for proper termination.
+ if (paren && *regparse++ != ')') {
+ //RAISE Error, SYM(RegularExpression), SYM(Unmatched_Parens),
+ printf ("RegularExpression::compile(): Unmatched parentheses.\n");
+ return 0;
+ }
+ else if (!paren && *regparse != '\0') {
+ if (*regparse == ')') {
+ //RAISE Error, SYM(RegularExpression), SYM(Unmatched_Parens),
+ printf ("RegularExpression::compile(): Unmatched parentheses.\n");
+ return 0;
+ }
+ else {
+ //RAISE Error, SYM(RegularExpression), SYM(Internal_Error),
+ printf ("RegularExpression::compile(): Internal error.\n");
+ return 0;
+ }
+ // NOTREACHED
+ }
+ return (ret);
+}
+
+
+/*
+ - regbranch - one alternative of an | operator
+ *
+ * Implements the concatenation operator.
+ */
+static char* regbranch (int *flagp) {
+ register char* ret;
+ register char* chain;
+ register char* latest;
+ int flags;
+
+ *flagp = WORST; // Tentatively.
+
+ ret = regnode(BRANCH);
+ chain = 0;
+ while (*regparse != '\0' && *regparse != '|' && *regparse != ')') {
+ latest = regpiece(&flags);
+ if (latest == 0)
+ return (0);
+ *flagp |= flags & HASWIDTH;
+ if (chain == 0) // First piece.
+ *flagp |= flags & SPSTART;
+ else
+ regtail(chain, latest);
+ chain = latest;
+ }
+ if (chain == 0) // Loop ran zero times.
+ regnode(NOTHING);
+
+ return (ret);
+}
+
+
+/*
+ - regpiece - something followed by possible [*+?]
+ *
+ * Note that the branching code sequences used for ? and the general cases
+ * of * and + are somewhat optimized: they use the same NOTHING node as
+ * both the endmarker for their branch list and the body of the last branch.
+ * It might seem that this node could be dispensed with entirely, but the
+ * endmarker role is not redundant.
+ */
+static char* regpiece (int *flagp) {
+ register char* ret;
+ register char op;
+ register char* next;
+ int flags;
+
+ ret = regatom(&flags);
+ if (ret == 0)
+ return (0);
+
+ op = *regparse;
+ if (!ISMULT(op)) {
+ *flagp = flags;
+ return (ret);
+ }
+
+ if (!(flags & HASWIDTH) && op != '?') {
+ //RAISE Error, SYM(RegularExpression), SYM(Empty_Operand),
+ printf ("RegularExpression::compile() : *+ operand could be empty.\n");
+ return 0;
+ }
+ *flagp = (op != '+') ? (WORST | SPSTART) : (WORST | HASWIDTH);
+
+ if (op == '*' && (flags & SIMPLE))
+ reginsert(STAR, ret);
+ else if (op == '*') {
+ // Emit x* as (x&|), where & means "self".
+ reginsert(BRANCH, ret); // Either x
+ regoptail(ret, regnode(BACK)); // and loop
+ regoptail(ret, ret); // back
+ regtail(ret, regnode(BRANCH)); // or
+ regtail(ret, regnode(NOTHING)); // null.
+ }
+ else if (op == '+' && (flags & SIMPLE))
+ reginsert(PLUS, ret);
+ else if (op == '+') {
+ // Emit x+ as x(&|), where & means "self".
+ next = regnode(BRANCH); // Either
+ regtail(ret, next);
+ regtail(regnode(BACK), ret); // loop back
+ regtail(next, regnode(BRANCH)); // or
+ regtail(ret, regnode(NOTHING)); // null.
+ }
+ else if (op == '?') {
+ // Emit x? as (x|)
+ reginsert(BRANCH, ret); // Either x
+ regtail(ret, regnode(BRANCH)); // or
+ next = regnode(NOTHING);// null.
+ regtail(ret, next);
+ regoptail(ret, next);
+ }
+ regparse++;
+ if (ISMULT(*regparse)) {
+ //RAISE Error, SYM(RegularExpression), SYM(Nested_Operand),
+ printf ("RegularExpression::compile(): Nested *?+.\n");
+ return 0;
+ }
+ return (ret);
+}
+
+
+/*
+ - regatom - the lowest level
+ *
+ * Optimization: gobbles an entire sequence of ordinary characters so that
+ * it can turn them into a single node, which is smaller to store and
+ * faster to run. Backslashed characters are exceptions, each becoming a
+ * separate node; the code is simpler that way and it's not worth fixing.
+ */
+static char* regatom (int *flagp) {
+ register char* ret;
+ int flags;
+
+ *flagp = WORST; // Tentatively.
+
+ switch (*regparse++) {
+ case '^':
+ ret = regnode(BOL);
+ break;
+ case '$':
+ ret = regnode(EOL);
+ break;
+ case '.':
+ ret = regnode(ANY);
+ *flagp |= HASWIDTH | SIMPLE;
+ break;
+ case '[':{
+ register int rxpclass;
+ register int rxpclassend;
+
+ if (*regparse == '^') { // Complement of range.
+ ret = regnode(ANYBUT);
+ regparse++;
+ }
+ else
+ ret = regnode(ANYOF);
+ if (*regparse == ']' || *regparse == '-')
+ regc(*regparse++);
+ while (*regparse != '\0' && *regparse != ']') {
+ if (*regparse == '-') {
+ regparse++;
+ if (*regparse == ']' || *regparse == '\0')
+ regc('-');
+ else {
+ rxpclass = UCHARAT(regparse - 2) + 1;
+ rxpclassend = UCHARAT(regparse);
+ if (rxpclass > rxpclassend + 1) {
+ //RAISE Error, SYM(RegularExpression), SYM(Invalid_Range),
+ printf ("RegularExpression::compile(): Invalid range in [].\n");
+ return 0;
+ }
+ for (; rxpclass <= rxpclassend; rxpclass++)
+ regc(rxpclass);
+ regparse++;
+ }
+ }
+ else
+ regc(*regparse++);
+ }
+ regc('\0');
+ if (*regparse != ']') {
+ //RAISE Error, SYM(RegularExpression), SYM(Unmatched_Bracket),
+ printf ("RegularExpression::compile(): Unmatched [].\n");
+ return 0;
+ }
+ regparse++;
+ *flagp |= HASWIDTH | SIMPLE;
+ }
+ break;
+ case '(':
+ ret = reg(1, &flags);
+ if (ret == 0)
+ return (0);
+ *flagp |= flags & (HASWIDTH | SPSTART);
+ break;
+ case '\0':
+ case '|':
+ case ')':
+ //RAISE Error, SYM(RegularExpression), SYM(Internal_Error),
+ printf ("RegularExpression::compile(): Internal error.\n"); // Never here
+ return 0;
+ case '?':
+ case '+':
+ case '*':
+ //RAISE Error, SYM(RegularExpression), SYM(No_Operand),
+ printf ("RegularExpression::compile(): ?+* follows nothing.\n");
+ return 0;
+ case '\\':
+ if (*regparse == '\0') {
+ //RAISE Error, SYM(RegularExpression), SYM(Trailing_Backslash),
+ printf ("RegularExpression::compile(): Trailing backslash.\n");
+ return 0;
+ }
+ ret = regnode(EXACTLY);
+ regc(*regparse++);
+ regc('\0');
+ *flagp |= HASWIDTH | SIMPLE;
+ break;
+ default:{
+ register int len;
+ register char ender;
+
+ regparse--;
+ len = int(strcspn(regparse, META));
+ if (len <= 0) {
+ //RAISE Error, SYM(RegularExpression), SYM(Internal_Error),
+ printf ("RegularExpression::compile(): Internal error.\n");
+ return 0;
+ }
+ ender = *(regparse + len);
+ if (len > 1 && ISMULT(ender))
+ len--; // Back off clear of ?+* operand.
+ *flagp |= HASWIDTH;
+ if (len == 1)
+ *flagp |= SIMPLE;
+ ret = regnode(EXACTLY);
+ while (len > 0) {
+ regc(*regparse++);
+ len--;
+ }
+ regc('\0');
+ }
+ break;
+ }
+ return (ret);
+}
+
+
+/*
+ - regnode - emit a node
+ Location.
+ */
+static char* regnode (char op) {
+ register char* ret;
+ register char* ptr;
+
+ ret = regcode;
+ if (ret == &regdummy) {
+ regsize += 3;
+ return (ret);
+ }
+
+ ptr = ret;
+ *ptr++ = op;
+ *ptr++ = '\0'; // Null "next" pointer.
+ *ptr++ = '\0';
+ regcode = ptr;
+
+ return (ret);
+}
+
+
+/*
+ - regc - emit (if appropriate) a byte of code
+ */
+static void regc (unsigned char b) {
+ if (regcode != &regdummy)
+ *regcode++ = b;
+ else
+ regsize++;
+}
+
+
+/*
+ - reginsert - insert an operator in front of already-emitted operand
+ *
+ * Means relocating the operand.
+ */
+static void reginsert (char op, char* opnd) {
+ register char* src;
+ register char* dst;
+ register char* place;
+
+ if (regcode == &regdummy) {
+ regsize += 3;
+ return;
+ }
+
+ src = regcode;
+ regcode += 3;
+ dst = regcode;
+ while (src > opnd)
+ *--dst = *--src;
+
+ place = opnd; // Op node, where operand used to be.
+ *place++ = op;
+ *place++ = '\0';
+ *place++ = '\0';
+}
+
+
+/*
+ - regtail - set the next-pointer at the end of a node chain
+ */
+static void regtail (char* p, const char* val) {
+ register char* scan;
+ register char* temp;
+ register int offset;
+
+ if (p == &regdummy)
+ return;
+
+ // Find last node.
+ scan = p;
+ for (;;) {
+ temp = regnext(scan);
+ if (temp == 0)
+ break;
+ scan = temp;
+ }
+
+ if (OP(scan) == BACK)
+ offset = int(scan - val);
+ else
+ offset = int(val - scan);
+ *(scan + 1) = (offset >> 8) & 0377;
+ *(scan + 2) = offset & 0377;
+}
+
+
+/*
+ - regoptail - regtail on operand of first argument; nop if operandless
+ */
+static void regoptail (char* p, const char* val) {
+ // "Operandless" and "op != BRANCH" are synonymous in practice.
+ if (p == 0 || p == &regdummy || OP(p) != BRANCH)
+ return;
+ regtail(OPERAND(p), val);
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+//
+// find and friends
+//
+////////////////////////////////////////////////////////////////////////
+
+
+/*
+ * Global work variables for find().
+ */
+static const char* reginput; // String-input pointer.
+static const char* regbol; // Beginning of input, for ^ check.
+static const char* *regstartp; // Pointer to startp array.
+static const char* *regendp; // Ditto for endp.
+
+/*
+ * Forwards.
+ */
+static int regtry (const char*, const char* *,
+ const char* *, const char*);
+static int regmatch (const char*);
+static int regrepeat (const char*);
+
+#ifdef DEBUG
+int regnarrate = 0;
+void regdump ();
+static char* regprop ();
+#endif
+
+bool RegularExpression::find (kwsys_std::string const& s)
+{
+ return find(s.c_str());
+}
+
+
+
+// find -- Matches the regular expression to the given string.
+// Returns true if found, and sets start and end indexes accordingly.
+
+bool RegularExpression::find (const char* string) {
+ register const char* s;
+
+ this->searchstring = string;
+
+ if (!this->program)
+ {
+ return false;
+ }
+
+ // Check validity of program.
+ if (UCHARAT(this->program) != MAGIC) {
+ //RAISE Error, SYM(RegularExpression), SYM(Internal_Error),
+ printf ("RegularExpression::find(): Compiled regular expression corrupted.\n");
+ return 0;
+ }
+
+ // If there is a "must appear" string, look for it.
+ if (this->regmust != 0) {
+ s = string;
+ while ((s = strchr(s, this->regmust[0])) != 0) {
+ if (strncmp(s, this->regmust, this->regmlen) == 0)
+ break; // Found it.
+ s++;
+ }
+ if (s == 0) // Not present.
+ return (0);
+ }
+
+ // Mark beginning of line for ^ .
+ regbol = string;
+
+ // Simplest case: anchored match need be tried only once.
+ if (this->reganch)
+ return (regtry(string, this->startp, this->endp, this->program) != 0);
+
+ // Messy cases: unanchored match.
+ s = string;
+ if (this->regstart != '\0')
+ // We know what char it must start with.
+ while ((s = strchr(s, this->regstart)) != 0) {
+ if (regtry(s, this->startp, this->endp, this->program))
+ return (1);
+ s++;
+
+ }
+ else
+ // We don't -- general case.
+ do {
+ if (regtry(s, this->startp, this->endp, this->program))
+ return (1);
+ } while (*s++ != '\0');
+
+ // Failure.
+ return (0);
+}
+
+
+/*
+ - regtry - try match at specific point
+ 0 failure, 1 success
+ */
+static int regtry (const char* string, const char* *start,
+ const char* *end, const char* prog) {
+ register int i;
+ register const char* *sp1;
+ register const char* *ep;
+
+ reginput = string;
+ regstartp = start;
+ regendp = end;
+
+ sp1 = start;
+ ep = end;
+ for (i = RegularExpressionNSUBEXP; i > 0; i--) {
+ *sp1++ = 0;
+ *ep++ = 0;
+ }
+ if (regmatch(prog + 1)) {
+ start[0] = string;
+ end[0] = reginput;
+ return (1);
+ }
+ else
+ return (0);
+}
+
+
+/*
+ - regmatch - main matching routine
+ *
+ * Conceptually the strategy is simple: check to see whether the current
+ * node matches, call self recursively to see whether the rest matches,
+ * and then act accordingly. In practice we make some effort to avoid
+ * recursion, in particular by going through "ordinary" nodes (that don't
+ * need to know whether the rest of the match failed) by a loop instead of
+ * by recursion.
+ * 0 failure, 1 success
+ */
+static int regmatch (const char* prog) {
+ register const char* scan; // Current node.
+ const char* next; // Next node.
+
+ scan = prog;
+
+ while (scan != 0) {
+
+ next = regnext(scan);
+
+ switch (OP(scan)) {
+ case BOL:
+ if (reginput != regbol)
+ return (0);
+ break;
+ case EOL:
+ if (*reginput != '\0')
+ return (0);
+ break;
+ case ANY:
+ if (*reginput == '\0')
+ return (0);
+ reginput++;
+ break;
+ case EXACTLY:{
+ register int len;
+ register const char* opnd;
+
+ opnd = OPERAND(scan);
+ // Inline the first character, for speed.
+ if (*opnd != *reginput)
+ return (0);
+ len = int(strlen(opnd));
+ if (len > 1 && strncmp(opnd, reginput, len) != 0)
+ return (0);
+ reginput += len;
+ }
+ break;
+ case ANYOF:
+ if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == 0)
+ return (0);
+ reginput++;
+ break;
+ case ANYBUT:
+ if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != 0)
+ return (0);
+ reginput++;
+ break;
+ case NOTHING:
+ break;
+ case BACK:
+ break;
+ case OPEN + 1:
+ case OPEN + 2:
+ case OPEN + 3:
+ case OPEN + 4:
+ case OPEN + 5:
+ case OPEN + 6:
+ case OPEN + 7:
+ case OPEN + 8:
+ case OPEN + 9:{
+ register int no;
+ register const char* save;
+
+ no = OP(scan) - OPEN;
+ save = reginput;
+
+ if (regmatch(next)) {
+
+ //
+ // Don't set startp if some later invocation of the
+ // same parentheses already has.
+ //
+ if (regstartp[no] == 0)
+ regstartp[no] = save;
+ return (1);
+ }
+ else
+ return (0);
+ }
+// break;
+ case CLOSE + 1:
+ case CLOSE + 2:
+ case CLOSE + 3:
+ case CLOSE + 4:
+ case CLOSE + 5:
+ case CLOSE + 6:
+ case CLOSE + 7:
+ case CLOSE + 8:
+ case CLOSE + 9:{
+ register int no;
+ register const char* save;
+
+ no = OP(scan) - CLOSE;
+ save = reginput;
+
+ if (regmatch(next)) {
+
+ //
+ // Don't set endp if some later invocation of the
+ // same parentheses already has.
+ //
+ if (regendp[no] == 0)
+ regendp[no] = save;
+ return (1);
+ }
+ else
+ return (0);
+ }
+// break;
+ case BRANCH:{
+
+ register const char* save;
+
+ if (OP(next) != BRANCH) // No choice.
+ next = OPERAND(scan); // Avoid recursion.
+ else {
+ do {
+ save = reginput;
+ if (regmatch(OPERAND(scan)))
+ return (1);
+ reginput = save;
+ scan = regnext(scan);
+ } while (scan != 0 && OP(scan) == BRANCH);
+ return (0);
+ // NOTREACHED
+ }
+ }
+ break;
+ case STAR:
+ case PLUS:{
+ register char nextch;
+ register int no;
+ register const char* save;
+ register int min_no;
+
+ //
+ // Lookahead to avoid useless match attempts when we know
+ // what character comes next.
+ //
+ nextch = '\0';
+ if (OP(next) == EXACTLY)
+ nextch = *OPERAND(next);
+ min_no = (OP(scan) == STAR) ? 0 : 1;
+ save = reginput;
+ no = regrepeat(OPERAND(scan));
+ while (no >= min_no) {
+ // If it could work, try it.
+ if (nextch == '\0' || *reginput == nextch)
+ if (regmatch(next))
+ return (1);
+ // Couldn't or didn't -- back up.
+ no--;
+ reginput = save + no;
+ }
+ return (0);
+ }
+// break;
+ case END:
+ return (1); // Success!
+
+ default:
+ //RAISE Error, SYM(RegularExpression), SYM(Internal_Error),
+ printf ("RegularExpression::find(): Internal error -- memory corrupted.\n");
+ return 0;
+ }
+ scan = next;
+ }
+
+ //
+ // We get here only if there's trouble -- normally "case END" is the
+ // terminating point.
+ //
+ //RAISE Error, SYM(RegularExpression), SYM(Internal_Error),
+ printf ("RegularExpression::find(): Internal error -- corrupted pointers.\n");
+ return (0);
+}
+
+
+/*
+ - regrepeat - repeatedly match something simple, report how many
+ */
+static int regrepeat (const char* p) {
+ register int count = 0;
+ register const char* scan;
+ register const char* opnd;
+
+ scan = reginput;
+ opnd = OPERAND(p);
+ switch (OP(p)) {
+ case ANY:
+ count = int(strlen(scan));
+ scan += count;
+ break;
+ case EXACTLY:
+ while (*opnd == *scan) {
+ count++;
+ scan++;
+ }
+ break;
+ case ANYOF:
+ while (*scan != '\0' && strchr(opnd, *scan) != 0) {
+ count++;
+ scan++;
+ }
+ break;
+ case ANYBUT:
+ while (*scan != '\0' && strchr(opnd, *scan) == 0) {
+ count++;
+ scan++;
+ }
+ break;
+ default: // Oh dear. Called inappropriately.
+ //RAISE Error, SYM(RegularExpression), SYM(Internal_Error),
+ printf ("cm RegularExpression::find(): Internal error.\n");
+ return 0;
+ }
+ reginput = scan;
+ return (count);
+}
+
+
+/*
+ - regnext - dig the "next" pointer out of a node
+ */
+static const char* regnext (register const char* p) {
+ register int offset;
+
+ if (p == &regdummy)
+ return (0);
+
+ offset = NEXT(p);
+ if (offset == 0)
+ return (0);
+
+ if (OP(p) == BACK)
+ return (p - offset);
+ else
+ return (p + offset);
+}
+
+
+static char* regnext (register char* p) {
+ register int offset;
+
+ if (p == &regdummy)
+ return (0);
+
+ offset = NEXT(p);
+ if (offset == 0)
+ return (0);
+
+ if (OP(p) == BACK)
+ return (p - offset);
+ else
+ return (p + offset);
+}
+
+} // namespace KWSYS_NAMESPACE
diff --git a/Source/kwsys/RegularExpression.hxx.in b/Source/kwsys/RegularExpression.hxx.in
new file mode 100644
index 0000000..a766225
--- /dev/null
+++ b/Source/kwsys/RegularExpression.hxx.in
@@ -0,0 +1,385 @@
+/*=========================================================================
+
+ Program: KWSys - Kitware System Library
+ Module: $RCSfile$
+ Language: C++
+ Date: $Date$
+ Version: $Revision$
+
+ Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
+ See http://www.cmake.org/HTML/Copyright.html for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the above copyright notices for more information.
+
+=========================================================================*/
+// Original Copyright notice:
+// Copyright (C) 1991 Texas Instruments Incorporated.
+//
+// Permission is granted to any individual or institution to use, copy, modify,
+// and distribute this software, provided that this complete copyright and
+// permission notice is maintained, intact, in all copies and supporting
+// documentation.
+//
+// Texas Instruments Incorporated provides this software "as is" without
+// express or implied warranty.
+//
+// Created: MNF 06/13/89 Initial Design and Implementation
+// Updated: LGO 08/09/89 Inherit from Generic
+// Updated: MBN 09/07/89 Added conditional exception handling
+// Updated: MBN 12/15/89 Sprinkled "const" qualifiers all over the place!
+// Updated: DLS 03/22/91 New lite version
+//
+
+#ifndef @KWSYS_NAMESPACE@_RegularExpression_hxx
+#define @KWSYS_NAMESPACE@_RegularExpression_hxx
+
+#include <@KWSYS_NAMESPACE@/StandardIncludes.hxx>
+
+#include <string>
+
+namespace @KWSYS_NAMESPACE@
+{
+
+const int RegularExpressionNSUBEXP = 10;
+
+/** \class cmRegularExpression
+ * \brief Implements pattern matching with regular expressions.
+ *
+ * This is the header file for the regular expression class. An object of
+ * this class contains a regular expression, in a special "compiled" format.
+ * This compiled format consists of several slots all kept as the objects
+ * private data. The cmRegularExpression class provides a convenient way to
+ * represent regular expressions. It makes it easy to search for the same
+ * regular expression in many different strings without having to compile a
+ * string to regular expression format more than necessary.
+ *
+ * This class implements pattern matching via regular expressions.
+ * A regular expression allows a programmer to specify complex
+ * patterns that can be searched for and matched against the
+ * character string of a string object. In its simplest form, a
+ * regular expression is a sequence of characters used to
+ * search for exact character matches. However, many times the
+ * exact sequence to be found is not known, or only a match at
+ * the beginning or end of a string is desired. The cmRegularExpression regu-
+ * lar expression class implements regular expression pattern
+ * matching as is found and implemented in many UNIX commands
+ * and utilities.
+ *
+ * Example: The perl code
+ *
+ * $filename =~ m"([a-z]+)\.cc";
+ * print $1;
+ *
+ * Is written as follows in C++
+ *
+ * cmRegularExpression re("([a-z]+)\\.cc");
+ * re.find(filename);
+ * cerr << re.match(1);
+ *
+ *
+ * The regular expression class provides a convenient mechanism
+ * for specifying and manipulating regular expressions. The
+ * regular expression object allows specification of such pat-
+ * terns by using the following regular expression metacharac-
+ * ters:
+ *
+ * ^ Matches at beginning of a line
+ *
+ * $ Matches at end of a line
+ *
+ * . Matches any single character
+ *
+ * [ ] Matches any character(s) inside the brackets
+ *
+ * [^ ] Matches any character(s) not inside the brackets
+ *
+ * - Matches any character in range on either side of a dash
+ *
+ * * Matches preceding pattern zero or more times
+ *
+ * + Matches preceding pattern one or more times
+ *
+ * ? Matches preceding pattern zero or once only
+ *
+ * () Saves a matched expression and uses it in a later match
+ *
+ * Note that more than one of these metacharacters can be used
+ * in a single regular expression in order to create complex
+ * search patterns. For example, the pattern [^ab1-9] says to
+ * match any character sequence that does not begin with the
+ * characters "ab" followed by numbers in the series one
+ * through nine.
+ *
+ * There are three constructors for cmRegularExpression. One just creates an
+ * empty cmRegularExpression object. Another creates a cmRegularExpression
+ * object and initializes it with a regular expression that is given in the
+ * form of a char*. The third takes a reference to a cmRegularExpression
+ * object as an argument and creates an object initialized with the
+ * information from the given cmRegularExpression object.
+ *
+ * The find member function finds the first occurence of the regualr
+ * expression of that object in the string given to find as an argument. Find
+ * returns a boolean, and if true, mutates the private data appropriately.
+ * Find sets pointers to the beginning and end of the thing last found, they
+ * are pointers into the actual string that was searched. The start and end
+ * member functions return indicies into the searched string that correspond
+ * to the beginning and end pointers respectively. The compile member
+ * function takes a char* and puts the compiled version of the char* argument
+ * into the object's private data fields. The == and != operators only check
+ * the to see if the compiled regular expression is the same, and the
+ * deep_equal functions also checks to see if the start and end pointers are
+ * the same. The is_valid function returns false if program is set to NULL,
+ * (i.e. there is no valid compiled exression). The set_invalid function sets
+ * the program to NULL (Warning: this deletes the compiled expression). The
+ * following examples may help clarify regular expression usage:
+ *
+ * * The regular expression "^hello" matches a "hello" only at the
+ * beginning of a line. It would match "hello there" but not "hi,
+ * hello there".
+ *
+ * * The regular expression "long$" matches a "long" only at the end
+ * of a line. It would match "so long\0", but not "long ago".
+ *
+ * * The regular expression "t..t..g" will match anything that has a
+ * "t" then any two characters, another "t", any two characters and
+ * then a "g". It will match "testing", or "test again" but would
+ * not match "toasting"
+ *
+ * * The regular expression "[1-9ab]" matches any number one through
+ * nine, and the characters "a" and "b". It would match "hello 1"
+ * or "begin", but would not match "no-match".
+ *
+ * * The regular expression "[^1-9ab]" matches any character that is
+ * not a number one through nine, or an "a" or "b". It would NOT
+ * match "hello 1" or "begin", but would match "no-match".
+ *
+ * * The regular expression "br* " matches something that begins with
+ * a "b", is followed by zero or more "r"s, and ends in a space. It
+ * would match "brrrrr ", and "b ", but would not match "brrh ".
+ *
+ * * The regular expression "br+ " matches something that begins with
+ * a "b", is followed by one or more "r"s, and ends in a space. It
+ * would match "brrrrr ", and "br ", but would not match "b " or
+ * "brrh ".
+ *
+ * * The regular expression "br? " matches something that begins with
+ * a "b", is followed by zero or one "r"s, and ends in a space. It
+ * would match "br ", and "b ", but would not match "brrrr " or
+ * "brrh ".
+ *
+ * * The regular expression "(..p)b" matches something ending with pb
+ * and beginning with whatever the two characters before the first p
+ * encounterd in the line were. It would find "repb" in "rep drepa
+ * qrepb". The regular expression "(..p)a" would find "repa qrepb"
+ * in "rep drepa qrepb"
+ *
+ * * The regular expression "d(..p)" matches something ending with p,
+ * beginning with d, and having two characters in between that are
+ * the same as the two characters before the first p encounterd in
+ * the line. It would match "drepa qrepb" in "rep drepa qrepb".
+ *
+ */
+class RegularExpression
+{
+public:
+ /**
+ * Instantiate RegularExpression with program=NULL.
+ */
+ inline RegularExpression ();
+
+ /**
+ * Instantiate RegularExpression with compiled char*.
+ */
+ inline RegularExpression (char const*);
+
+ /**
+ * Instantiate RegularExpression as a copy of another regular expression.
+ */
+ RegularExpression (RegularExpression const&);
+
+ /**
+ * Destructor.
+ */
+ inline ~RegularExpression();
+
+ /**
+ * Compile a regular expression into internal code
+ * for later pattern matching.
+ */
+ bool compile (char const*);
+
+ /**
+ * Matches the regular expression to the given string.
+ * Returns true if found, and sets start and end indexes accordingly.
+ */
+ bool find (char const*);
+
+ /**
+ * Matches the regular expression to the given std string.
+ * Returns true if found, and sets start and end indexes accordingly.
+ */
+ bool find (kwsys_std::string const&);
+
+ /**
+ * Index to start of first find.
+ */
+ inline kwsys_std::string::size_type start() const;
+
+ /**
+ * Index to end of first find.
+ */
+ inline kwsys_std::string::size_type end() const;
+
+ /**
+ * Returns true if two regular expressions have the same
+ * compiled program for pattern matching.
+ */
+ bool operator== (RegularExpression const&) const;
+
+ /**
+ * Returns true if two regular expressions have different
+ * compiled program for pattern matching.
+ */
+ inline bool operator!= (RegularExpression const&) const;
+
+ /**
+ * Returns true if have the same compiled regular expressions
+ * and the same start and end pointers.
+ */
+ bool deep_equal (RegularExpression const&) const;
+
+ /**
+ * True if the compiled regexp is valid.
+ */
+ inline bool is_valid() const;
+
+ /**
+ * Marks the regular expression as invalid.
+ */
+ inline void set_invalid();
+
+ /**
+ * Destructor.
+ */
+ // awf added
+ kwsys_std::string::size_type start(int n) const;
+ kwsys_std::string::size_type end(int n) const;
+ kwsys_std::string match(int n) const;
+
+private:
+ const char* startp[RegularExpressionNSUBEXP];
+ const char* endp[RegularExpressionNSUBEXP];
+ char regstart; // Internal use only
+ char reganch; // Internal use only
+ const char* regmust; // Internal use only
+ int regmlen; // Internal use only
+ char* program;
+ int progsize;
+ const char* searchstring;
+};
+
+/**
+ * Create an empty regular expression.
+ */
+inline RegularExpression::RegularExpression ()
+{
+ this->program = 0;
+}
+
+/**
+ * Creates a regular expression from string s, and
+ * compiles s.
+ */
+inline RegularExpression::RegularExpression (const char* s)
+{
+ this->program = 0;
+ if ( s )
+ {
+ this->compile(s);
+ }
+}
+
+/**
+ * Destroys and frees space allocated for the regular expression.
+ */
+inline RegularExpression::~RegularExpression ()
+{
+//#ifndef WIN32
+ delete [] this->program;
+//#endif
+}
+
+/**
+ * Set the start position for the regular expression.
+ */
+inline kwsys_std::string::size_type RegularExpression::start () const
+{
+ return(this->startp[0] - searchstring);
+}
+
+
+/**
+ * Returns the start/end index of the last item found.
+ */
+inline kwsys_std::string::size_type RegularExpression::end () const
+{
+ return(this->endp[0] - searchstring);
+}
+
+/**
+ * Returns true if two regular expressions have different
+ * compiled program for pattern matching.
+ */
+inline bool RegularExpression::operator!= (const RegularExpression& r) const
+{
+ return(!(*this == r));
+}
+
+/**
+ * Returns true if a valid regular expression is compiled
+ * and ready for pattern matching.
+ */
+inline bool RegularExpression::is_valid () const
+{
+ return (this->program != 0);
+}
+
+
+inline void RegularExpression::set_invalid ()
+{
+//#ifndef WIN32
+ delete [] this->program;
+//#endif
+ this->program = 0;
+}
+
+/**
+ * Return start index of nth submatch. start(0) is the start of the full match.
+ */
+inline kwsys_std::string::size_type RegularExpression::start(int n) const
+{
+ return this->startp[n] - searchstring;
+}
+
+
+/**
+ * Return end index of nth submatch. end(0) is the end of the full match.
+ */
+inline kwsys_std::string::size_type RegularExpression::end(int n) const
+{
+ return this->endp[n] - searchstring;
+}
+
+/**
+ * Return nth submatch as a string.
+ */
+inline kwsys_std::string RegularExpression::match(int n) const
+{
+ return kwsys_std::string(this->startp[n], this->endp[n] - this->startp[n]);
+}
+
+} // namespace @KWSYS_NAMESPACE@
+
+#endif
diff --git a/Source/kwsys/StandardIncludes.hxx.in b/Source/kwsys/StandardIncludes.hxx.in
new file mode 100644
index 0000000..f91cec1
--- /dev/null
+++ b/Source/kwsys/StandardIncludes.hxx.in
@@ -0,0 +1,44 @@
+/*=========================================================================
+
+ Program: KWSys - Kitware System Library
+ Module: $RCSfile$
+ Language: C++
+ Date: $Date$
+ Version: $Revision$
+
+ Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
+ See http://www.cmake.org/HTML/Copyright.html for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef @KWSYS_NAMESPACE@_StandardIncludes_hxx
+#define @KWSYS_NAMESPACE@_StandardIncludes_hxx
+
+#include <@KWSYS_NAMESPACE@/Configure.hxx>
+
+#ifndef KWSYS_NO_ANSI_STREAM_HEADERS
+# include <fstream>
+# include <iostream>
+#else
+# include <fstream.h>
+# include <iostream.h>
+#endif
+
+#if !defined(KWSYS_NO_ANSI_STRING_STREAM)
+# include <sstream>
+#elif !defined(KWSYS_NO_ANSI_STREAM_HEADERS)
+# include <strstream>
+#else
+# include <strstream.h>
+#endif
+
+#if defined(KWSYS_NO_STD_NAMESPACE)
+# define kwsys_std
+#else
+# define kwsys_std std
+#endif
+
+#endif
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
new file mode 100644
index 0000000..fca3f46
--- /dev/null
+++ b/Source/kwsys/SystemTools.cxx
@@ -0,0 +1,1793 @@
+/*=========================================================================
+
+ Program: KWSys - Kitware System Library
+ Module: $RCSfile$
+ Language: C++
+ Date: $Date$
+ Version: $Revision$
+
+ Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
+ See http://www.cmake.org/HTML/Copyright.html for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the above copyright notices for more information.
+
+=========================================================================*/
+#include <SystemTools.hxx>
+#include <RegularExpression.hxx>
+#include <Directory.hxx>
+
+#include <fstream>
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <errno.h>
+#include <time.h>
+
+// support for realpath call
+#ifndef _WIN32
+#include <limits.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <sys/wait.h>
+#endif
+
+#if defined(_WIN32) && (defined(_MSC_VER) || defined(__BORLANDC__))
+#include <string.h>
+#include <windows.h>
+#include <direct.h>
+#define _unlink unlink
+inline int Mkdir(const char* dir)
+{
+ return _mkdir(dir);
+}
+inline const char* Getcwd(char* buf, unsigned int len)
+{
+ return _getcwd(buf, len);
+}
+inline int Chdir(const char* dir)
+{
+ #if defined(__BORLANDC__)
+ return chdir(dir);
+ #else
+ return _chdir(dir);
+ #endif
+}
+#else
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+inline int Mkdir(const char* dir)
+{
+ return mkdir(dir, 00777);
+}
+inline const char* Getcwd(char* buf, unsigned int len)
+{
+ return getcwd(buf, len);
+}
+inline int Chdir(const char* dir)
+{
+ return chdir(dir);
+}
+#endif
+
+
+/* Implement floattime() for various platforms */
+// Taken from Python 2.1.3
+
+#if defined( _WIN32 ) && !defined( __CYGWIN__ )
+# include <sys/timeb.h>
+# define HAVE_FTIME
+# if defined( __BORLANDC__)
+# define FTIME ftime
+# define TIMEB timeb
+# else // Visual studio?
+# define FTIME _ftime
+# define TIMEB _timeb
+# endif
+#elif defined( __CYGWIN__ ) || defined( __linux__ )
+# include <sys/time.h>
+# include <time.h>
+# define HAVE_GETTIMEOFDAY
+#endif
+
+namespace KWSYS_NAMESPACE
+{
+
+double
+SystemTools::GetTime(void)
+{
+ /* There are three ways to get the time:
+ (1) gettimeofday() -- resolution in microseconds
+ (2) ftime() -- resolution in milliseconds
+ (3) time() -- resolution in seconds
+ In all cases the return value is a float in seconds.
+ Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may
+ fail, so we fall back on ftime() or time().
+ Note: clock resolution does not imply clock accuracy! */
+#ifdef HAVE_GETTIMEOFDAY
+ {
+ struct timeval t;
+#ifdef GETTIMEOFDAY_NO_TZ
+ if (gettimeofday(&t) == 0)
+ return (double)t.tv_sec + t.tv_usec*0.000001;
+#else /* !GETTIMEOFDAY_NO_TZ */
+ if (gettimeofday(&t, (struct timezone *)NULL) == 0)
+ return (double)t.tv_sec + t.tv_usec*0.000001;
+#endif /* !GETTIMEOFDAY_NO_TZ */
+ }
+#endif /* !HAVE_GETTIMEOFDAY */
+ {
+#if defined(HAVE_FTIME)
+ struct TIMEB t;
+ FTIME(&t);
+ return (double)t.time + (double)t.millitm * (double)0.001;
+#else /* !HAVE_FTIME */
+ time_t secs;
+ time(&secs);
+ return (double)secs;
+#endif /* !HAVE_FTIME */
+ }
+}
+
+// adds the elements of the env variable path to the arg passed in
+void SystemTools::GetPath(kwsys_std::vector<kwsys_std::string>& path)
+{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ const char* pathSep = ";";
+#else
+ const char* pathSep = ":";
+#endif
+ kwsys_std::string pathEnv = getenv("PATH");
+ // A hack to make the below algorithm work.
+ if(pathEnv[pathEnv.length()-1] != ':')
+ {
+ pathEnv += pathSep;
+ }
+ kwsys_std::string::size_type start =0;
+ bool done = false;
+ while(!done)
+ {
+ kwsys_std::string::size_type endpos = pathEnv.find(pathSep, start);
+ if(endpos != kwsys_std::string::npos)
+ {
+ path.push_back(pathEnv.substr(start, endpos-start));
+ start = endpos+1;
+ }
+ else
+ {
+ done = true;
+ }
+ }
+ for(kwsys_std::vector<kwsys_std::string>::iterator i = path.begin();
+ i != path.end(); ++i)
+ {
+ SystemTools::ConvertToUnixSlashes(*i);
+ }
+}
+
+
+const char* SystemTools::GetExecutableExtension()
+{
+#if defined(_WIN32) || defined(__CYGWIN__)
+ return ".exe";
+#else
+ return "";
+#endif
+}
+
+
+bool SystemTools::MakeDirectory(const char* path)
+{
+ if(SystemTools::FileExists(path))
+ {
+ return true;
+ }
+ kwsys_std::string dir = path;
+ if(dir.size() == 0)
+ {
+ return false;
+ }
+ SystemTools::ConvertToUnixSlashes(dir);
+
+ kwsys_std::string::size_type pos = dir.find(':');
+ if(pos == kwsys_std::string::npos)
+ {
+ pos = 0;
+ }
+ kwsys_std::string topdir;
+ while((pos = dir.find('/', pos)) != kwsys_std::string::npos)
+ {
+ topdir = dir.substr(0, pos);
+ Mkdir(topdir.c_str());
+ pos++;
+ }
+ if(dir[dir.size()-1] == '/')
+ {
+ topdir = dir.substr(0, dir.size());
+ }
+ else
+ {
+ topdir = dir;
+ }
+ if(Mkdir(topdir.c_str()) != 0)
+ {
+ // There is a bug in the Borland Run time library which makes MKDIR
+ // return EACCES when it should return EEXISTS
+ // if it is some other error besides directory exists
+ // then return false
+ if( (errno != EEXIST)
+#ifdef __BORLANDC__
+ && (errno != EACCES)
+#endif
+ )
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+
+// replace replace with with as many times as it shows up in source.
+// write the result into source.
+void SystemTools::ReplaceString(kwsys_std::string& source,
+ const char* replace,
+ const char* with)
+{
+ // get out quick if string is not found
+ kwsys_std::string::size_type start = source.find(replace);
+ if(start == kwsys_std::string::npos)
+ {
+ return;
+ }
+ kwsys_std::string rest;
+ kwsys_std::string::size_type lengthReplace = strlen(replace);
+ kwsys_std::string::size_type lengthWith = strlen(with);
+ while(start != kwsys_std::string::npos)
+ {
+ rest = source.substr(start+lengthReplace);
+ source = source.substr(0, start);
+ source += with;
+ source += rest;
+ start = source.find(replace, start + lengthWith );
+ }
+}
+
+// Read a registry value.
+// Example :
+// HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
+// => will return the data of the "default" value of the key
+// HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
+// => will return the data of the "Root" value of the key
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+bool SystemTools::ReadRegistryValue(const char *key, kwsys_std::string &value)
+{
+
+ kwsys_std::string primary = key;
+ kwsys_std::string second;
+ kwsys_std::string valuename;
+
+ size_t start = primary.find("\\");
+ if (start == kwsys_std::string::npos)
+ {
+ return false;
+ }
+
+ size_t valuenamepos = primary.find(";");
+ if (valuenamepos != kwsys_std::string::npos)
+ {
+ valuename = primary.substr(valuenamepos+1);
+ }
+
+ second = primary.substr(start+1, valuenamepos-start-1);
+ primary = primary.substr(0, start);
+
+ HKEY primaryKey;
+ if (primary == "HKEY_CURRENT_USER")
+ {
+ primaryKey = HKEY_CURRENT_USER;
+ }
+ if (primary == "HKEY_CURRENT_CONFIG")
+ {
+ primaryKey = HKEY_CURRENT_CONFIG;
+ }
+ if (primary == "HKEY_CLASSES_ROOT")
+ {
+ primaryKey = HKEY_CLASSES_ROOT;
+ }
+ if (primary == "HKEY_LOCAL_MACHINE")
+ {
+ primaryKey = HKEY_LOCAL_MACHINE;
+ }
+ if (primary == "HKEY_USERS")
+ {
+ primaryKey = HKEY_USERS;
+ }
+
+ HKEY hKey;
+ if(RegOpenKeyEx(primaryKey,
+ second.c_str(),
+ 0,
+ KEY_READ,
+ &hKey) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+ else
+ {
+ DWORD dwType, dwSize;
+ dwSize = 1023;
+ char data[1024];
+ if(RegQueryValueEx(hKey,
+ (LPTSTR)valuename.c_str(),
+ NULL,
+ &dwType,
+ (BYTE *)data,
+ &dwSize) == ERROR_SUCCESS)
+ {
+ if (dwType == REG_SZ)
+ {
+ value = data;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+#else
+bool SystemTools::ReadRegistryValue(const char *, kwsys_std::string &)
+{
+ return false;
+}
+#endif
+
+
+// Write a registry value.
+// Example :
+// HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
+// => will set the data of the "default" value of the key
+// HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
+// => will set the data of the "Root" value of the key
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+bool SystemTools::WriteRegistryValue(const char *key, const char *value)
+{
+ kwsys_std::string primary = key;
+ kwsys_std::string second;
+ kwsys_std::string valuename;
+
+ size_t start = primary.find("\\");
+ if (start == kwsys_std::string::npos)
+ {
+ return false;
+ }
+
+ size_t valuenamepos = primary.find(";");
+ if (valuenamepos != kwsys_std::string::npos)
+ {
+ valuename = primary.substr(valuenamepos+1);
+ }
+
+ second = primary.substr(start+1, valuenamepos-start-1);
+ primary = primary.substr(0, start);
+
+ HKEY primaryKey;
+ if (primary == "HKEY_CURRENT_USER")
+ {
+ primaryKey = HKEY_CURRENT_USER;
+ }
+ if (primary == "HKEY_CURRENT_CONFIG")
+ {
+ primaryKey = HKEY_CURRENT_CONFIG;
+ }
+ if (primary == "HKEY_CLASSES_ROOT")
+ {
+ primaryKey = HKEY_CLASSES_ROOT;
+ }
+ if (primary == "HKEY_LOCAL_MACHINE")
+ {
+ primaryKey = HKEY_LOCAL_MACHINE;
+ }
+ if (primary == "HKEY_USERS")
+ {
+ primaryKey = HKEY_USERS;
+ }
+
+ HKEY hKey;
+ DWORD dwDummy;
+ if(RegCreateKeyEx(primaryKey,
+ second.c_str(),
+ 0,
+ "",
+ REG_OPTION_NON_VOLATILE,
+ KEY_WRITE,
+ NULL,
+ &hKey,
+ &dwDummy) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+
+ if(RegSetValueEx(hKey,
+ (LPTSTR)valuename.c_str(),
+ 0,
+ REG_SZ,
+ (CONST BYTE *)value,
+ (DWORD)(strlen(value) + 1)) == ERROR_SUCCESS)
+ {
+ return true;
+ }
+ return false;
+}
+#else
+bool SystemTools::WriteRegistryValue(const char *, const char *)
+{
+ return false;
+}
+#endif
+
+// Delete a registry value.
+// Example :
+// HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
+// => will delete the data of the "default" value of the key
+// HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
+// => will delete the data of the "Root" value of the key
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+bool SystemTools::DeleteRegistryValue(const char *key)
+{
+ kwsys_std::string primary = key;
+ kwsys_std::string second;
+ kwsys_std::string valuename;
+
+ size_t start = primary.find("\\");
+ if (start == kwsys_std::string::npos)
+ {
+ return false;
+ }
+
+ size_t valuenamepos = primary.find(";");
+ if (valuenamepos != kwsys_std::string::npos)
+ {
+ valuename = primary.substr(valuenamepos+1);
+ }
+
+ second = primary.substr(start+1, valuenamepos-start-1);
+ primary = primary.substr(0, start);
+
+ HKEY primaryKey;
+ if (primary == "HKEY_CURRENT_USER")
+ {
+ primaryKey = HKEY_CURRENT_USER;
+ }
+ if (primary == "HKEY_CURRENT_CONFIG")
+ {
+ primaryKey = HKEY_CURRENT_CONFIG;
+ }
+ if (primary == "HKEY_CLASSES_ROOT")
+ {
+ primaryKey = HKEY_CLASSES_ROOT;
+ }
+ if (primary == "HKEY_LOCAL_MACHINE")
+ {
+ primaryKey = HKEY_LOCAL_MACHINE;
+ }
+ if (primary == "HKEY_USERS")
+ {
+ primaryKey = HKEY_USERS;
+ }
+
+ HKEY hKey;
+ if(RegOpenKeyEx(primaryKey,
+ second.c_str(),
+ 0,
+ KEY_WRITE,
+ &hKey) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+ else
+ {
+ if(RegDeleteValue(hKey,
+ (LPTSTR)valuename.c_str()) == ERROR_SUCCESS)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+#else
+bool SystemTools::DeleteRegistryValue(const char *)
+{
+ return false;
+}
+#endif
+
+// replace replace with with as many times as it shows up in source.
+// write the result into source.
+#if defined(_WIN32) && !defined(__CYGWIN__)
+void SystemTools::ExpandRegistryValues(kwsys_std::string& source)
+{
+ // Regular expression to match anything inside [...] that begins in HKEY.
+ // Note that there is a special rule for regular expressions to match a
+ // close square-bracket inside a list delimited by square brackets.
+ // The "[^]]" part of this expression will match any character except
+ // a close square-bracket. The ']' character must be the first in the
+ // list of characters inside the [^...] block of the expression.
+ cmRegularExpression regEntry("\\[(HKEY[^]]*)\\]");
+
+ // check for black line or comment
+ while (regEntry.find(source))
+ {
+ // the arguments are the second match
+ kwsys_std::string key = regEntry.match(1);
+ kwsys_std::string val;
+ if (ReadRegistryValue(key.c_str(), val))
+ {
+ kwsys_std::string reg = "[";
+ reg += key + "]";
+ SystemTools::ReplaceString(source, reg.c_str(), val.c_str());
+ }
+ else
+ {
+ kwsys_std::string reg = "[";
+ reg += key + "]";
+ SystemTools::ReplaceString(source, reg.c_str(), "/registry");
+ }
+ }
+}
+#else
+void SystemTools::ExpandRegistryValues(kwsys_std::string&)
+{
+}
+#endif
+
+
+kwsys_std::string SystemTools::EscapeQuotes(const char* str)
+{
+ kwsys_std::string result = "";
+ for(const char* ch = str; *ch != '\0'; ++ch)
+ {
+ if(*ch == '"')
+ {
+ result += '\\';
+ }
+ result += *ch;
+ }
+ return result;
+}
+
+bool SystemTools::SameFile(const char* file1, const char* file2)
+{
+#ifdef _WIN32
+ HANDLE hFile1, hFile2;
+
+ hFile1 = CreateFile( file1,
+ GENERIC_READ,
+ FILE_SHARE_READ ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS,
+ NULL
+ );
+ hFile2 = CreateFile( file2,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS,
+ NULL
+ );
+ if( hFile1 == INVALID_HANDLE_VALUE || hFile2 == INVALID_HANDLE_VALUE)
+ {
+ if(hFile1 != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(hFile1);
+ }
+ if(hFile2 != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(hFile2);
+ }
+ return false;
+ }
+
+ BY_HANDLE_FILE_INFORMATION fiBuf1;
+ BY_HANDLE_FILE_INFORMATION fiBuf2;
+ GetFileInformationByHandle( hFile1, &fiBuf1 );
+ GetFileInformationByHandle( hFile2, &fiBuf2 );
+ CloseHandle(hFile1);
+ CloseHandle(hFile2);
+ return (fiBuf1.nFileIndexHigh == fiBuf2.nFileIndexHigh &&
+ fiBuf1.nFileIndexLow == fiBuf2.nFileIndexLow);
+#else
+ struct stat fileStat1, fileStat2;
+ if (stat(file1, &fileStat1) == 0 && stat(file2, &fileStat2) == 0)
+ {
+ // see if the files are the same file
+ // check the device inode and size
+ if(memcmp(&fileStat2.st_dev, &fileStat1.st_dev, sizeof(fileStat1.st_dev)) == 0 &&
+ memcmp(&fileStat2.st_ino, &fileStat1.st_ino, sizeof(fileStat1.st_ino)) == 0 &&
+ fileStat2.st_size == fileStat1.st_size
+ )
+ {
+ return true;
+ }
+ }
+ return false;
+#endif
+}
+
+
+// return true if the file exists
+bool SystemTools::FileExists(const char* filename)
+{
+ struct stat fs;
+ if (stat(filename, &fs) != 0)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
+
+
+// Return a capitalized string (i.e the first letter is uppercased, all other
+// are lowercased)
+kwsys_std::string SystemTools::Capitalized(const kwsys_std::string& s)
+{
+ kwsys_std::string n;
+ n.resize(s.size());
+ n[0] = toupper(s[0]);
+ for (size_t i = 1; i < s.size(); i++)
+ {
+ n[i] = tolower(s[i]);
+ }
+ return n;
+}
+
+
+// Return a lower case string
+kwsys_std::string SystemTools::LowerCase(const kwsys_std::string& s)
+{
+ kwsys_std::string n;
+ n.resize(s.size());
+ for (size_t i = 0; i < s.size(); i++)
+ {
+ n[i] = tolower(s[i]);
+ }
+ return n;
+}
+
+// Return a lower case string
+kwsys_std::string SystemTools::UpperCase(const kwsys_std::string& s)
+{
+ kwsys_std::string n;
+ n.resize(s.size());
+ for (size_t i = 0; i < s.size(); i++)
+ {
+ n[i] = toupper(s[i]);
+ }
+ return n;
+}
+
+
+// convert windows slashes to unix slashes
+void SystemTools::ConvertToUnixSlashes(kwsys_std::string& path)
+{
+ kwsys_std::string::size_type pos = 0;
+ while((pos = path.find('\\', pos)) != kwsys_std::string::npos)
+ {
+ path[pos] = '/';
+ pos++;
+ }
+ // Remove all // from the path just like most unix shells
+ int start_find = 0;
+
+#ifdef _WIN32
+ // However, on windows if the first characters are both slashes,
+ // then keep them that way, so that network paths can be handled.
+ start_find = 1;
+#endif
+
+ while((pos = path.find("//", start_find)) != kwsys_std::string::npos)
+ {
+ SystemTools::ReplaceString(path, "//", "/");
+ }
+
+ // remove any trailing slash
+ if(path.size() && path[path.size()-1] == '/')
+ {
+ path = path.substr(0, path.size()-1);
+ }
+
+ // if there is a tilda ~ then replace it with HOME
+ if(path.find("~") == 0)
+ {
+ if (getenv("HOME"))
+ {
+ path = kwsys_std::string(getenv("HOME")) + path.substr(1);
+ }
+ }
+
+ // if there is a /tmp_mnt in a path get rid of it!
+ // stupid sgi's
+ if(path.find("/tmp_mnt") == 0)
+ {
+ path = path.substr(8);
+ }
+}
+
+
+// change // to /, and escape any spaces in the path
+kwsys_std::string SystemTools::ConvertToUnixOutputPath(const char* path)
+{
+ kwsys_std::string ret = path;
+
+ // remove // except at the beginning might be a cygwin drive
+ kwsys_std::string::size_type pos = 1;
+ while((pos = ret.find("//", pos)) != kwsys_std::string::npos)
+ {
+ ret.erase(pos, 1);
+ }
+ // now escape spaces if there is a space in the path
+ if(ret.find(" ") != kwsys_std::string::npos)
+ {
+ kwsys_std::string result = "";
+ char lastch = 1;
+ for(const char* ch = ret.c_str(); *ch != '\0'; ++ch)
+ {
+ // if it is already escaped then don't try to escape it again
+ if(*ch == ' ' && lastch != '\\')
+ {
+ result += '\\';
+ }
+ result += *ch;
+ lastch = *ch;
+ }
+ ret = result;
+ }
+ return ret;
+}
+
+
+
+kwsys_std::string SystemTools::EscapeSpaces(const char* str)
+{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ kwsys_std::string result;
+
+ // if there are spaces
+ kwsys_std::string temp = str;
+ if (temp.find(" ") != kwsys_std::string::npos &&
+ temp.find("\"")==kwsys_std::string::npos)
+ {
+ result = "\"";
+ result += str;
+ result += "\"";
+ return result;
+ }
+ return str;
+#else
+ kwsys_std::string result = "";
+ for(const char* ch = str; *ch != '\0'; ++ch)
+ {
+ if(*ch == ' ')
+ {
+ result += '\\';
+ }
+ result += *ch;
+ }
+ return result;
+#endif
+}
+
+kwsys_std::string SystemTools::ConvertToOutputPath(const char* path)
+{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ return SystemTools::ConvertToWindowsOutputPath(path);
+#else
+ return SystemTools::ConvertToUnixOutputPath(path);
+#endif
+}
+
+
+// remove double slashes not at the start
+kwsys_std::string SystemTools::ConvertToWindowsOutputPath(const char* path)
+{
+ kwsys_std::string ret = path;
+ kwsys_std::string::size_type pos = 0;
+ // first convert all of the slashes
+ while((pos = ret.find('/', pos)) != kwsys_std::string::npos)
+ {
+ ret[pos] = '\\';
+ pos++;
+ }
+ // check for really small paths
+ if(ret.size() < 2)
+ {
+ return ret;
+ }
+ // now clean up a bit and remove double slashes
+ // Only if it is not the first position in the path which is a network
+ // path on windows
+ pos = 1; // start at position 1
+ if(ret[0] == '\"')
+ {
+ pos = 2; // if the string is already quoted then start at 2
+ if(ret.size() < 3)
+ {
+ return ret;
+ }
+ }
+ while((pos = ret.find("\\\\", pos)) != kwsys_std::string::npos)
+ {
+ ret.erase(pos, 1);
+ }
+ // now double quote the path if it has spaces in it
+ // and is not already double quoted
+ if(ret.find(" ") != kwsys_std::string::npos
+ && ret[0] != '\"')
+ {
+ kwsys_std::string result;
+ result = "\"" + ret + "\"";
+ ret = result;
+ }
+ return ret;
+}
+
+bool SystemTools::CopyFileIfDifferent(const char* source,
+ const char* destination)
+{
+ if(SystemTools::FilesDiffer(source, destination))
+ {
+ SystemTools::CopyFileAlways(source, destination);
+ return true;
+ }
+ return false;
+}
+
+
+bool SystemTools::FilesDiffer(const char* source,
+ const char* destination)
+{
+ struct stat statSource;
+ if (stat(source, &statSource) != 0)
+ {
+ return true;
+ }
+
+ struct stat statDestination;
+ if (stat(destination, &statDestination) != 0)
+ {
+ return true;
+ }
+
+ if(statSource.st_size != statDestination.st_size)
+ {
+ return true;
+ }
+
+ if(statSource.st_size == 0)
+ {
+ return false;
+ }
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+ kwsys_std::ifstream finSource(source,
+ kwsys_std::ios::binary | kwsys_std::ios::in);
+ kwsys_std::ifstream finDestination(destination,
+ kwsys_std::ios::binary | kwsys_std::ios::in);
+#else
+ kwsys_std::ifstream finSource(source);
+ kwsys_std::ifstream finDestination(destination);
+#endif
+ if(!finSource || !finDestination)
+ {
+ return true;
+ }
+
+ char* source_buf = new char[statSource.st_size];
+ char* dest_buf = new char[statSource.st_size];
+
+ finSource.read(source_buf, statSource.st_size);
+ finDestination.read(dest_buf, statSource.st_size);
+
+ if(statSource.st_size != static_cast<long>(finSource.gcount()) ||
+ statSource.st_size != static_cast<long>(finDestination.gcount()))
+ {
+ // Failed to read files.
+ delete [] source_buf;
+ delete [] dest_buf;
+ return true;
+ }
+ int ret = memcmp((const void*)source_buf,
+ (const void*)dest_buf,
+ statSource.st_size);
+
+ delete [] dest_buf;
+ delete [] source_buf;
+
+ return ret != 0;
+}
+
+
+/**
+ * Copy a file named by "source" to the file named by "destination".
+ */
+bool SystemTools::CopyFileAlways(const char* source, const char* destination)
+{
+ const int bufferSize = 4096;
+ char buffer[bufferSize];
+
+ // If destination is a directory, try to create a file with the same
+ // name as the source in that directory.
+
+ kwsys_std::string new_destination;
+ if(SystemTools::FileExists(destination) &&
+ SystemTools::FileIsDirectory(destination))
+ {
+ new_destination = destination;
+ SystemTools::ConvertToUnixSlashes(new_destination);
+ new_destination += '/';
+ kwsys_std::string source_name = source;
+ new_destination += SystemTools::GetFilenameName(source_name);
+ destination = new_destination.c_str();
+ }
+
+ // Create destination directory
+
+ kwsys_std::string destination_dir = destination;
+ destination_dir = SystemTools::GetFilenamePath(destination_dir);
+ SystemTools::MakeDirectory(destination_dir.c_str());
+
+ // Open files
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+ kwsys_std::ifstream fin(source,
+ kwsys_std::ios::binary | kwsys_std::ios::in);
+#else
+ kwsys_std::ifstream fin(source);
+#endif
+ if(!fin)
+ {
+ return false;
+ }
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+ kwsys_std::ofstream fout(destination,
+ kwsys_std::ios::binary | kwsys_std::ios::out | kwsys_std::ios::trunc);
+#else
+ kwsys_std::ofstream fout(destination,
+ kwsys_std::ios::out | kwsys_std::ios::trunc);
+#endif
+ if(!fout)
+ {
+ return false;
+ }
+
+ // This copy loop is very sensitive on certain platforms with
+ // slightly broken stream libraries (like HPUX). Normally, it is
+ // incorrect to not check the error condition on the fin.read()
+ // before using the data, but the fin.gcount() will be zero if an
+ // error occurred. Therefore, the loop should be safe everywhere.
+ while(fin)
+ {
+ fin.read(buffer, bufferSize);
+ if(fin.gcount())
+ {
+ fout.write(buffer, fin.gcount());
+ }
+ }
+
+ // Make sure the operating system has finished writing the file
+ // before closing it. This will ensure the file is finished before
+ // the check below.
+ fout.flush();
+
+ fin.close();
+ fout.close();
+
+ // More checks.
+ struct stat statSource, statDestination;
+ statSource.st_size = 12345;
+ statDestination.st_size = 12345;
+ if(stat(source, &statSource) != 0)
+ {
+ return false;
+ }
+ else if(stat(destination, &statDestination) != 0)
+ {
+ return false;
+ }
+ else if(statSource.st_size != statDestination.st_size)
+ {
+ return false;
+ }
+ return true;
+}
+
+// return true if the file exists
+long int SystemTools::ModifiedTime(const char* filename)
+{
+ struct stat fs;
+ if (stat(filename, &fs) != 0)
+ {
+ return 0;
+ }
+ else
+ {
+ return (long int)fs.st_mtime;
+ }
+}
+
+
+kwsys_std::string SystemTools::GetLastSystemError()
+{
+ int e = errno;
+ return strerror(e);
+}
+
+bool SystemTools::RemoveFile(const char* source)
+{
+ return unlink(source) != 0 ? false : true;
+}
+
+/**
+ * Find the file the given name. Searches the given path and then
+ * the system search path. Returns the full path to the file if it is
+ * found. Otherwise, the empty string is returned.
+ */
+kwsys_std::string SystemTools::FindFile(const char* name,
+ const kwsys_std::vector<kwsys_std::string>& userPaths)
+{
+ // Add the system search path to our path.
+ kwsys_std::vector<kwsys_std::string> path = userPaths;
+ SystemTools::GetPath(path);
+
+ kwsys_std::string tryPath;
+ for(kwsys_std::vector<kwsys_std::string>::const_iterator p = path.begin();
+ p != path.end(); ++p)
+ {
+ tryPath = *p;
+ tryPath += "/";
+ tryPath += name;
+ if(SystemTools::FileExists(tryPath.c_str()) &&
+ !SystemTools::FileIsDirectory(tryPath.c_str()))
+ {
+ return SystemTools::CollapseFullPath(tryPath.c_str());
+ }
+ }
+ // Couldn't find the file.
+ return "";
+}
+
+/**
+ * Find the executable with the given name. Searches the given path and then
+ * the system search path. Returns the full path to the executable if it is
+ * found. Otherwise, the empty string is returned.
+ */
+kwsys_std::string SystemTools::FindProgram(const char* name,
+ const kwsys_std::vector<kwsys_std::string>& userPaths,
+ bool no_system_path)
+{
+ if(!name)
+ {
+ return "";
+ }
+ // See if the executable exists as written.
+ if(SystemTools::FileExists(name) &&
+ !SystemTools::FileIsDirectory(name))
+ {
+ return SystemTools::CollapseFullPath(name);
+ }
+ kwsys_std::string tryPath = name;
+ tryPath += SystemTools::GetExecutableExtension();
+ if(SystemTools::FileExists(tryPath.c_str()) &&
+ !SystemTools::FileIsDirectory(tryPath.c_str()))
+ {
+ return SystemTools::CollapseFullPath(tryPath.c_str());
+ }
+
+ // Add the system search path to our path.
+ kwsys_std::vector<kwsys_std::string> path = userPaths;
+ if (!no_system_path)
+ {
+ SystemTools::GetPath(path);
+ }
+
+ for(kwsys_std::vector<kwsys_std::string>::const_iterator p = path.begin();
+ p != path.end(); ++p)
+ {
+ tryPath = *p;
+ tryPath += "/";
+ tryPath += name;
+ if(SystemTools::FileExists(tryPath.c_str()) &&
+ !SystemTools::FileIsDirectory(tryPath.c_str()))
+ {
+ return SystemTools::CollapseFullPath(tryPath.c_str());
+ }
+#ifdef _WIN32
+ tryPath += ".com";
+ if(SystemTools::FileExists(tryPath.c_str()) &&
+ !SystemTools::FileIsDirectory(tryPath.c_str()))
+ {
+ return SystemTools::CollapseFullPath(tryPath.c_str());
+ }
+ tryPath = *p;
+ tryPath += "/";
+ tryPath += name;
+#endif
+ tryPath += SystemTools::GetExecutableExtension();
+ if(SystemTools::FileExists(tryPath.c_str()) &&
+ !SystemTools::FileIsDirectory(tryPath.c_str()))
+ {
+ return SystemTools::CollapseFullPath(tryPath.c_str());
+ }
+ }
+
+ // Couldn't find the program.
+ return "";
+}
+
+
+/**
+ * Find the library with the given name. Searches the given path and then
+ * the system search path. Returns the full path to the library if it is
+ * found. Otherwise, the empty string is returned.
+ */
+kwsys_std::string SystemTools::FindLibrary(const char* name,
+ const kwsys_std::vector<kwsys_std::string>& userPaths)
+{
+ // See if the executable exists as written.
+ if(SystemTools::FileExists(name) &&
+ !SystemTools::FileIsDirectory(name))
+ {
+ return SystemTools::CollapseFullPath(name);
+ }
+
+ // Add the system search path to our path.
+ kwsys_std::vector<kwsys_std::string> path = userPaths;
+ SystemTools::GetPath(path);
+
+ kwsys_std::string tryPath;
+ for(kwsys_std::vector<kwsys_std::string>::const_iterator p = path.begin();
+ p != path.end(); ++p)
+ {
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ tryPath = *p;
+ tryPath += "/";
+ tryPath += name;
+ tryPath += ".lib";
+ if(SystemTools::FileExists(tryPath.c_str()))
+ {
+ return SystemTools::CollapseFullPath(tryPath.c_str());
+ }
+#else
+ tryPath = *p;
+ tryPath += "/lib";
+ tryPath += name;
+ tryPath += ".so";
+ if(SystemTools::FileExists(tryPath.c_str()))
+ {
+ return SystemTools::CollapseFullPath(tryPath.c_str());
+ }
+ tryPath = *p;
+ tryPath += "/lib";
+ tryPath += name;
+ tryPath += ".a";
+ if(SystemTools::FileExists(tryPath.c_str()))
+ {
+ return SystemTools::CollapseFullPath(tryPath.c_str());
+ }
+ tryPath = *p;
+ tryPath += "/lib";
+ tryPath += name;
+ tryPath += ".sl";
+ if(SystemTools::FileExists(tryPath.c_str()))
+ {
+ return SystemTools::CollapseFullPath(tryPath.c_str());
+ }
+ tryPath = *p;
+ tryPath += "/lib";
+ tryPath += name;
+ tryPath += ".dylib";
+ if(SystemTools::FileExists(tryPath.c_str()))
+ {
+ return SystemTools::CollapseFullPath(tryPath.c_str());
+ }
+#endif
+ }
+
+ // Couldn't find the library.
+ return "";
+}
+
+bool SystemTools::FileIsDirectory(const char* name)
+{
+ struct stat fs;
+ if(stat(name, &fs) == 0)
+ {
+#if _WIN32
+ return ((fs.st_mode & _S_IFDIR) != 0);
+#else
+ return S_ISDIR(fs.st_mode);
+#endif
+ }
+ else
+ {
+ return false;
+ }
+}
+
+int SystemTools::ChangeDirectory(const char *dir)
+{
+ return Chdir(dir);
+}
+
+kwsys_std::string SystemTools::GetCurrentWorkingDirectory()
+{
+ char buf[2048];
+ kwsys_std::string path = Getcwd(buf, 2048);
+ return path;
+}
+
+kwsys_std::string SystemTools::GetProgramPath(const char* in_name)
+{
+ kwsys_std::string dir, file;
+ SystemTools::SplitProgramPath(in_name, dir, file);
+ return dir;
+}
+
+bool SystemTools::SplitProgramPath(const char* in_name,
+ kwsys_std::string& dir,
+ kwsys_std::string& file,
+ bool errorReport)
+{
+ dir = in_name;
+ file = "";
+ SystemTools::ConvertToUnixSlashes(dir);
+
+ if(!SystemTools::FileIsDirectory(dir.c_str()))
+ {
+ kwsys_std::string::size_type slashPos = dir.rfind("/");
+ if(slashPos != kwsys_std::string::npos)
+ {
+ file = dir.substr(slashPos+1);
+ dir = dir.substr(0, slashPos);
+ }
+ else
+ {
+ file = dir;
+ dir = "";
+ }
+ }
+ if((dir != "") && !SystemTools::FileIsDirectory(dir.c_str()))
+ {
+ kwsys_std::string oldDir = in_name;
+ SystemTools::ConvertToUnixSlashes(oldDir);
+ dir = in_name;
+ return false;
+ }
+ return true;
+}
+
+kwsys_std::string SystemTools::CollapseFullPath(const char* in_relative)
+{
+ return SystemTools::CollapseFullPath(in_relative, 0);
+}
+
+kwsys_std::string SystemTools::CollapseFullPath(const char* in_relative,
+ const char* in_base)
+{
+ kwsys_std::string dir, file;
+ SystemTools::SplitProgramPath(in_relative, dir, file, false);
+
+ // Save original working directory.
+ kwsys_std::string orig = SystemTools::GetCurrentWorkingDirectory();
+
+ // Change to base of relative path.
+ if(in_base)
+ {
+ Chdir(in_base);
+ }
+
+#ifdef _WIN32
+ // Follow relative path.
+ if(dir != "")
+ {
+ Chdir(dir.c_str());
+ }
+
+ // Get the resulting directory.
+ kwsys_std::string newDir = SystemTools::GetCurrentWorkingDirectory();
+
+ // Add the file back on to the directory.
+ SystemTools::ConvertToUnixSlashes(newDir);
+#else
+# ifdef MAXPATHLEN
+ char resolved_name[MAXPATHLEN];
+# else
+# ifdef PATH_MAX
+ char resolved_name[PATH_MAX];
+# else
+ char resolved_name[5024];
+# endif
+# endif
+
+ // Resolve relative path.
+ kwsys_std::string newDir;
+ if(dir != "")
+ {
+ realpath(dir.c_str(), resolved_name);
+ newDir = resolved_name;
+ }
+ else
+ {
+ newDir = SystemTools::GetCurrentWorkingDirectory();
+ }
+#endif
+
+ // Restore original working directory.
+ Chdir(orig.c_str());
+
+ // Construct and return the full path.
+ kwsys_std::string newPath = newDir;
+ if(file != "")
+ {
+ newPath += "/";
+ newPath += file;
+ }
+ return newPath;
+}
+
+bool SystemTools::Split(const char* str, kwsys_std::vector<kwsys_std::string>& lines)
+{
+ kwsys_std::string data(str);
+ kwsys_std::string::size_type lpos = 0;
+ while(lpos < data.length())
+ {
+ kwsys_std::string::size_type rpos = data.find_first_of("\n", lpos);
+ if(rpos == kwsys_std::string::npos)
+ {
+ // Line ends at end of string without a newline.
+ lines.push_back(data.substr(lpos));
+ return false;
+ }
+ if((rpos > lpos) && (data[rpos-1] == '\r'))
+ {
+ // Line ends in a "\r\n" pair, remove both characters.
+ lines.push_back(data.substr(lpos, (rpos-1)-lpos));
+ }
+ else
+ {
+ // Line ends in a "\n", remove the character.
+ lines.push_back(data.substr(lpos, rpos-lpos));
+ }
+ lpos = rpos+1;
+ }
+ return true;
+}
+
+/**
+ * Return path of a full filename (no trailing slashes).
+ * Warning: returned path is converted to Unix slashes format.
+ */
+kwsys_std::string SystemTools::GetFilenamePath(const kwsys_std::string& filename)
+{
+ kwsys_std::string fn = filename;
+ SystemTools::ConvertToUnixSlashes(fn);
+
+ kwsys_std::string::size_type slash_pos = fn.rfind("/");
+ if(slash_pos != kwsys_std::string::npos)
+ {
+ return fn.substr(0, slash_pos);
+ }
+ else
+ {
+ return "";
+ }
+}
+
+
+/**
+ * Return file name of a full filename (i.e. file name without path).
+ */
+kwsys_std::string SystemTools::GetFilenameName(const kwsys_std::string& filename)
+{
+ kwsys_std::string fn = filename;
+ SystemTools::ConvertToUnixSlashes(fn);
+
+ kwsys_std::string::size_type slash_pos = fn.rfind("/");
+ if(slash_pos != kwsys_std::string::npos)
+ {
+ return fn.substr(slash_pos + 1);
+ }
+ else
+ {
+ return filename;
+ }
+}
+
+
+/**
+ * Return file extension of a full filename (dot included).
+ * Warning: this is the longest extension (for example: .tar.gz)
+ */
+kwsys_std::string SystemTools::GetFilenameExtension(const kwsys_std::string& filename)
+{
+ kwsys_std::string name = SystemTools::GetFilenameName(filename);
+ kwsys_std::string::size_type dot_pos = name.find(".");
+ if(dot_pos != kwsys_std::string::npos)
+ {
+ return name.substr(dot_pos);
+ }
+ else
+ {
+ return "";
+ }
+}
+
+
+/**
+ * Return file name without extension of a full filename (i.e. without path).
+ * Warning: it considers the longest extension (for example: .tar.gz)
+ */
+kwsys_std::string SystemTools::GetFilenameWithoutExtension(const kwsys_std::string& filename)
+{
+ kwsys_std::string name = SystemTools::GetFilenameName(filename);
+ kwsys_std::string::size_type dot_pos = name.find(".");
+ if(dot_pos != kwsys_std::string::npos)
+ {
+ return name.substr(0, dot_pos);
+ }
+ else
+ {
+ return name;
+ }
+}
+
+
+/**
+ * Return file name without extension of a full filename (i.e. without path).
+ * Warning: it considers the last extension (for example: removes .gz
+ * from .tar.gz)
+ */
+kwsys_std::string
+SystemTools::GetFilenameWithoutLastExtension(const kwsys_std::string& filename)
+{
+ kwsys_std::string name = SystemTools::GetFilenameName(filename);
+ kwsys_std::string::size_type dot_pos = name.rfind(".");
+ if(dot_pos != kwsys_std::string::npos)
+ {
+ return name.substr(0, dot_pos);
+ }
+ else
+ {
+ return name;
+ }
+}
+
+bool SystemTools::FileIsFullPath(const char* in_name)
+{
+ kwsys_std::string name = in_name;
+#if defined(_WIN32)
+ // On Windows, the name must be at least two characters long.
+ if(name.length() < 2)
+ {
+ return false;
+ }
+ if(name[1] == ':')
+ {
+ return true;
+ }
+ if(name[0] == '\\')
+ {
+ return true;
+ }
+#else
+ // On UNIX, the name must be at least one character long.
+ if(name.length() < 1)
+ {
+ return false;
+ }
+#endif
+ // On UNIX, the name must begin in a '/'.
+ // On Windows, if the name begins in a '/', then it is a full
+ // network path.
+ if(name[0] == '/')
+ {
+ return true;
+ }
+ return false;
+}
+
+void SystemTools::Glob(const char *directory, const char *regexp,
+ kwsys_std::vector<kwsys_std::string>& files)
+{
+ Directory d;
+ RegularExpression reg(regexp);
+
+ if (d.Load(directory))
+ {
+ size_t numf;
+ unsigned int i;
+ numf = d.GetNumberOfFiles();
+ for (i = 0; i < numf; i++)
+ {
+ kwsys_std::string fname = d.GetFile(i);
+ if (reg.find(fname))
+ {
+ files.push_back(fname);
+ }
+ }
+ }
+}
+
+
+void SystemTools::GlobDirs(const char *fullPath,
+ kwsys_std::vector<kwsys_std::string>& files)
+{
+ kwsys_std::string path = fullPath;
+ kwsys_std::string::size_type pos = path.find("/*");
+ if(pos == kwsys_std::string::npos)
+ {
+ files.push_back(fullPath);
+ return;
+ }
+ kwsys_std::string startPath = path.substr(0, pos);
+ kwsys_std::string finishPath = path.substr(pos+2);
+
+ Directory d;
+ if (d.Load(startPath.c_str()))
+ {
+ for (unsigned int i = 0; i < d.GetNumberOfFiles(); ++i)
+ {
+ if((kwsys_std::string(d.GetFile(i)) != ".")
+ && (kwsys_std::string(d.GetFile(i)) != ".."))
+ {
+ kwsys_std::string fname = startPath;
+ fname +="/";
+ fname += d.GetFile(i);
+ if(SystemTools::FileIsDirectory(fname.c_str()))
+ {
+ fname += finishPath;
+ SystemTools::GlobDirs(fname.c_str(), files);
+ }
+ }
+ }
+ }
+}
+
+bool SystemTools::GetShortPath(const char* path, kwsys_std::string& shortPath)
+{
+#if defined(WIN32) && !defined(__CYGWIN__)
+ const int size = int(strlen(path)) +1; // size of return
+ char *buffer = new char[size]; // create a buffer
+ char *tempPath = new char[size]; // create a buffer
+ int ret;
+
+ // if the path passed in has quotes around it, first remove the quotes
+ if (path[0] == '"' && path[strlen(path)-1] == '"')
+ {
+ strcpy(tempPath,path+1);
+ tempPath[strlen(tempPath)-1] = '\0';
+ }
+ else
+ {
+ strcpy(tempPath,path);
+ }
+
+ buffer[0] = 0;
+ ret = GetShortPathName(tempPath, buffer, size);
+
+ if(buffer[0] == 0 || ret > size)
+ {
+ delete [] buffer;
+ delete [] tempPath;
+ return false;
+ }
+ else
+ {
+ shortPath = buffer;
+ delete [] buffer;
+ delete [] tempPath;
+ return true;
+ }
+#else
+ shortPath = path;
+ return true;
+#endif
+}
+
+bool SystemTools::SimpleGlob(const kwsys_std::string& glob,
+ kwsys_std::vector<kwsys_std::string>& files,
+ int type /* = 0 */)
+{
+ files.clear();
+ if ( glob[glob.size()-1] != '*' )
+ {
+ return false;
+ }
+ kwsys_std::string path = SystemTools::GetFilenamePath(glob);
+ kwsys_std::string ppath = SystemTools::GetFilenameName(glob);
+ ppath = ppath.substr(0, ppath.size()-1);
+ if ( path.size() == 0 )
+ {
+ path = "/";
+ }
+
+ bool res = false;
+ Directory d;
+ if (d.Load(path.c_str()))
+ {
+ for (unsigned int i = 0; i < d.GetNumberOfFiles(); ++i)
+ {
+ if((kwsys_std::string(d.GetFile(i)) != ".")
+ && (kwsys_std::string(d.GetFile(i)) != ".."))
+ {
+ kwsys_std::string fname = path;
+ if ( path[path.size()-1] != '/' )
+ {
+ fname +="/";
+ }
+ fname += d.GetFile(i);
+ kwsys_std::string sfname = d.GetFile(i);
+ if ( type > 0 && SystemTools::FileIsDirectory(fname.c_str()) )
+ {
+ continue;
+ }
+ if ( type < 0 && !SystemTools::FileIsDirectory(fname.c_str()) )
+ {
+ continue;
+ }
+ if ( sfname.size() >= ppath.size() &&
+ sfname.substr(0, ppath.size()) ==
+ ppath )
+ {
+ files.push_back(fname);
+ res = true;
+ }
+ }
+ }
+ }
+ return res;
+}
+
+
+void SystemTools::SplitProgramFromArgs(const char* path,
+ kwsys_std::string& program, kwsys_std::string& args)
+{
+ if(SystemTools::FileExists(path))
+ {
+ program = path;
+ args = "";
+ return;
+ }
+ kwsys_std::vector<kwsys_std::string> e;
+ kwsys_std::string findProg = SystemTools::FindProgram(path, e);
+ if(findProg.size())
+ {
+ program = findProg;
+ args = "";
+ return;
+ }
+ kwsys_std::string dir = path;
+ kwsys_std::string::size_type spacePos = dir.rfind(' ');
+ if(spacePos == kwsys_std::string::npos)
+ {
+ program = "";
+ args = "";
+ return;
+ }
+ while(spacePos != kwsys_std::string::npos)
+ {
+ kwsys_std::string tryProg = dir.substr(0, spacePos);
+ if(SystemTools::FileExists(tryProg.c_str()))
+ {
+ program = tryProg;
+ args = dir.substr(spacePos, dir.size()-spacePos);
+ return;
+ }
+ findProg = SystemTools::FindProgram(tryProg.c_str(), e);
+ if(findProg.size())
+ {
+ program = findProg;
+ args = dir.substr(spacePos, dir.size()-spacePos);
+ return;
+ }
+ spacePos = dir.rfind(' ', spacePos--);
+ }
+ program = "";
+ args = "";
+}
+
+kwsys_std::string SystemTools::GetCurrentDateTime(const char* format)
+{
+ char buf[1024];
+ time_t t;
+ time(&t);
+ strftime(buf, sizeof(buf), format, localtime(&t));
+ return buf;
+}
+
+kwsys_std::string SystemTools::MakeCindentifier(const char* s)
+{
+ kwsys_std::string str(s);
+ if (str.find_first_of("0123456789") == 0)
+ {
+ str = "_" + str;
+ }
+
+ kwsys_std::string permited_chars("_"
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789");
+ kwsys_std::string::size_type pos = 0;
+ while ((pos = str.find_first_not_of(permited_chars, pos)) != kwsys_std::string::npos)
+ {
+ str[pos] = '_';
+ }
+ return str;
+}
+
+// Due to a buggy stream library on the HP and another on Mac OSX, we
+// need this very carefully written version of getline. Returns true
+// if any data were read before the end-of-file was reached.
+bool SystemTools::GetLineFromStream(kwsys_std::istream& is, kwsys_std::string& line)
+{
+ const int bufferSize = 1024;
+ char buffer[bufferSize];
+ line = "";
+ bool haveData = false;
+
+ // If no characters are read from the stream, the end of file has
+ // been reached.
+ while((is.getline(buffer, bufferSize), is.gcount() > 0))
+ {
+ haveData = true;
+ line.append(buffer);
+
+ // If newline character was read, the gcount includes the
+ // character, but the buffer does not. The end of line has been
+ // reached.
+ if(strlen(buffer) < static_cast<size_t>(is.gcount()))
+ {
+ break;
+ }
+
+ // The fail bit may be set. Clear it.
+ is.clear(is.rdstate() & ~kwsys_std::ios::failbit);
+ }
+ return haveData;
+}
+
+#if defined(_MSC_VER) && defined(_DEBUG)
+# include <crtdbg.h>
+# include <stdio.h>
+# include <stdlib.h>
+static int SystemToolsDebugReport(int, char* message, int*)
+{
+ fprintf(stderr, message);
+ exit(1);
+ return 0;
+}
+void SystemTools::EnableMSVCDebugHook()
+{
+ if(getenv("DART_TEST_FROM_DART"))
+ {
+ _CrtSetReportHook(SystemToolsDebugReport);
+ }
+}
+#else
+void SystemTools::EnableMSVCDebugHook()
+{
+}
+#endif
+
+} // namespace KWSYS_NAMESPACE
diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in
new file mode 100644
index 0000000..725e8ae
--- /dev/null
+++ b/Source/kwsys/SystemTools.hxx.in
@@ -0,0 +1,285 @@
+/*=========================================================================
+
+ Program: KWSys - Kitware System Library
+ Module: $RCSfile$
+ Language: C++
+ Date: $Date$
+ Version: $Revision$
+
+ Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
+ See http://www.cmake.org/HTML/Copyright.html for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef @KWSYS_NAMESPACE@_SystemTools_hxx
+#define @KWSYS_NAMESPACE@_SystemTools_hxx
+
+#include <@KWSYS_NAMESPACE@/StandardIncludes.hxx>
+
+#include <string>
+#include <vector>
+
+namespace @KWSYS_NAMESPACE@
+{
+
+/** \class SystemTools
+ * \brief A collection of useful platform-independent system functions.
+ */
+class SystemTools
+{
+public:
+ /**
+ * 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 __.*).
+ */
+ static kwsys_std::string MakeCindentifier(const char* s);
+
+ /**
+ * Make a new directory if it is not there. This function
+ * can make a full path even if none of the directories existed
+ * prior to calling this function.
+ */
+ static bool MakeDirectory(const char* path);
+
+ /**
+ * Get current time as a double. On certain platforms this will
+ * return higher resolution than seconds:
+ * (1) gettimeofday() -- resolution in microseconds
+ * (2) ftime() -- resolution in milliseconds
+ * (3) time() -- resolution in seconds
+ */
+ static double GetTime();
+
+ /**
+ * Replace replace all occurances of the string in
+ * the source string.
+ */
+ static void ReplaceString(kwsys_std::string& source,
+ const char* replace,
+ const char* with);
+
+ /**
+ * Read a registry value
+ */
+ static bool ReadRegistryValue(const char *key, kwsys_std::string &value);
+
+ /**
+ * Write a registry value
+ */
+ static bool WriteRegistryValue(const char *key, const char *value);
+
+ /**
+ * Delete a registry value
+ */
+ static bool DeleteRegistryValue(const char *key);
+
+ /**
+ * Look for and replace registry values in a string
+ */
+ static void ExpandRegistryValues(kwsys_std::string& source);
+
+ /**
+ * Return a capitalized string (i.e the first letter is uppercased,
+ * all other are lowercased).
+ */
+ static kwsys_std::string Capitalized(const kwsys_std::string&);
+
+ /**
+ * Return a lower case string
+ */
+ static kwsys_std::string LowerCase(const kwsys_std::string&);
+
+ /**
+ * Return a lower case string
+ */
+ static kwsys_std::string UpperCase(const kwsys_std::string&);
+
+ /**
+ * Replace Windows file system slashes with Unix-style slashes.
+ */
+ static void ConvertToUnixSlashes(kwsys_std::string& path);
+
+ /**
+ * Platform independent escape spaces, unix uses backslash,
+ * windows double quotes the string.
+ */
+ static kwsys_std::string EscapeSpaces(const char* str);
+
+ /** Escape quotes in a string. */
+ static kwsys_std::string EscapeQuotes(const char* str);
+
+ /**
+ * For windows this calles ConvertToWindowsOutputPath and for unix
+ * it calls ConvertToUnixOutputPath
+ */
+ static kwsys_std::string ConvertToOutputPath(const char*);
+
+ /** Return true if a file exists in the current directory. */
+ static bool FileExists(const char* filename);
+
+ /**
+ * Add the paths from the environment variable PATH to the
+ * string vector passed in.
+ */
+ static void GetPath(kwsys_std::vector<kwsys_std::string>& path);
+
+ /**
+ * Get the file extension (including ".") needed for an executable
+ * on the current platform ("" for unix, ".exe" for Windows).
+ */
+ static const char* GetExecutableExtension();
+
+ /**
+ * Copy the source file to the destination file only
+ * if the two files differ.
+ */
+ static bool CopyFileIfDifferent(const char* source,
+ const char* destination);
+
+ ///! Compare the contents of two files. Return true if different.
+ static bool FilesDiffer(const char* source,
+ const char* destination);
+
+ ///! return true if the two files are the same file
+ static bool SameFile(const char* file1, const char* file2);
+
+ ///! Copy a file.
+ static bool CopyFileAlways(const char* source, const char* destination);
+
+ ///! Remove a file.
+ static bool RemoveFile(const char* source);
+
+ ///! Find a file in the system PATH, with optional extra paths.
+ static kwsys_std::string FindFile(const char* name,
+ const kwsys_std::vector<kwsys_std::string>& path= kwsys_std::vector<kwsys_std::string>());
+
+ ///! Find an executable in the system PATH, with optional extra paths.
+ static kwsys_std::string FindProgram(const char* name,
+ const kwsys_std::vector<kwsys_std::string>& path = kwsys_std::vector<kwsys_std::string>(),
+ bool no_system_path = false);
+
+ ///! Find a library in the system PATH, with optional extra paths.
+ static kwsys_std::string FindLibrary(const char* name,
+ const kwsys_std::vector<kwsys_std::string>& path);
+
+ ///! return true if the file is a directory.
+ static bool FileIsDirectory(const char* name);
+ static void Glob(const char *directory, const char *regexp,
+ kwsys_std::vector<kwsys_std::string>& files);
+ static void GlobDirs(const char *fullPath, kwsys_std::vector<kwsys_std::string>& files);
+
+ /**
+ * Try to find a list of files that match the "simple" globbing
+ * expression. At this point in time the globbing expressions have
+ * to be in form: /directory/partial_file_name*. The * character has
+ * to be at the end of the string and it does not support ?
+ * []... The optional argument type specifies what kind of files you
+ * want to find. 0 means all files, -1 means directories, 1 means
+ * files only. This method returns true if search was succesfull.
+ */
+ static bool SimpleGlob(const kwsys_std::string& glob, kwsys_std::vector<kwsys_std::string>& files,
+ int type = 0);
+
+ static kwsys_std::string GetCurrentWorkingDirectory();
+
+ /**
+ * 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.
+ */
+ static kwsys_std::string GetProgramPath(const char*);
+ static bool SplitProgramPath(const char* in_name,
+ kwsys_std::string& dir,
+ kwsys_std::string& file,
+ bool errorReport = true);
+
+ /**
+ * 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.
+ */
+ static kwsys_std::string CollapseFullPath(const char* in_relative);
+ static kwsys_std::string CollapseFullPath(const char* in_relative,
+ const char* in_base);
+
+ ///! return path of a full filename (no trailing slashes).
+ static kwsys_std::string GetFilenamePath(const kwsys_std::string&);
+
+
+ ///! return file name of a full filename (i.e. file name without path).
+ static kwsys_std::string GetFilenameName(const kwsys_std::string&);
+
+ ///! Split a program from its arguments and handle spaces in the paths.
+ static void SplitProgramFromArgs(const char* path,
+ kwsys_std::string& program, kwsys_std::string& args);
+
+ ///! return file extension of a full filename (dot included).
+ static kwsys_std::string GetFilenameExtension(const kwsys_std::string&);
+
+ ///! return file name without extension of a full filename.
+ static kwsys_std::string GetFilenameWithoutExtension(const kwsys_std::string&);
+
+ ///! return file name without its last (shortest) extension.
+ static kwsys_std::string GetFilenameWithoutLastExtension(const kwsys_std::string&);
+
+ /** Return whether the path represents a full path (not relative). */
+ static bool FileIsFullPath(const char*);
+
+ static long int ModifiedTime(const char* filename);
+
+ ///! for windows return the short path for the given path, unix just a pass through
+ static bool GetShortPath(const char* path, kwsys_std::string& result);
+
+ ///! change directory the the directory specified
+ static int ChangeDirectory(const char* dir);
+
+ /** Split a string on its newlines into multiple lines. Returns
+ false only if the last line stored had no newline. */
+ static bool Split(const char* s, kwsys_std::vector<kwsys_std::string>& l);
+
+ static kwsys_std::string GetCurrentDateTime(const char* format);
+
+ /** Get the result of strerror(errno). */
+ static kwsys_std::string GetLastSystemError();
+
+ /** When building DEBUG with MSVC, this enables a hook that prevents
+ * error dialogs from popping up if the program is being run from
+ * DART.
+ */
+ static void EnableMSVCDebugHook();
+
+ /**
+ * Read line from file. Make sure to get everything. Due to a buggy stream
+ * library on the HP and another on Mac OSX, we need this very carefully
+ * written version of getline. Returns true if any data were read before the
+ * end-of-file was reached.
+ */
+ static bool GetLineFromStream(kwsys_std::istream& istr, kwsys_std::string& line);
+
+protected:
+ // these two functions can be called from ConvertToOutputPath
+ /**
+ * Convert the path to a string that can be used in a unix makefile.
+ * double slashes are removed, and spaces are escaped.
+ */
+ static kwsys_std::string ConvertToUnixOutputPath(const char*);
+
+ /**
+ * 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.
+ */
+ static kwsys_std::string ConvertToWindowsOutputPath(const char*);
+};
+
+} // namespace @KWSYS_NAMESPACE@
+
+#endif