ptlib.cxx
上传用户:hzhsqp
上传日期:2007-01-06
资源大小:1600k
文件大小:21k
- /*
- * ptlib.cxx
- *
- * General implementation of classes for Microsoft operating systems.
- *
- * Portable Windows Library
- *
- * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.0 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * The Original Code is Portable Windows Library.
- *
- * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
- *
- * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
- * All Rights Reserved.
- *
- * Contributor(s): ______________________________________.
- *
- * $Log: ptlib.cxx,v $
- * Revision 1.52 2000/07/09 14:05:46 robertj
- * Added file share options.
- *
- * Revision 1.51 2000/04/29 06:44:17 robertj
- * Added some stuff to make sure symbols included in library.
- *
- * Revision 1.50 2000/02/19 23:46:09 robertj
- * Fixed incorrect values for PFile::Access() function, thanks Stefan Ditscheid.
- *
- * Revision 1.49 1999/08/17 03:46:40 robertj
- * Fixed usage of inlines in optimised version.
- *
- * Revision 1.48 1999/06/14 07:59:38 robertj
- * Enhanced tracing again to add options to trace output (timestamps etc).
- *
- * Revision 1.47 1999/06/13 13:54:07 robertj
- * Added PConsoleChannel class for access to stdin/stdout/stderr.
- *
- * Revision 1.46 1999/06/09 02:05:20 robertj
- * Added ability to open file as standard input, output and error streams.
- *
- * Revision 1.45 1999/05/06 06:11:50 robertj
- * Fixed date to be forgiving of rubbish at end of date string.
- * Fixed PTime::GetHour() etc to not crash on time=-1.
- *
- * Revision 1.44 1998/11/30 07:30:31 robertj
- * Fixed problems with PFilePath parsing functions.
- *
- * Revision 1.43 1998/11/26 10:34:19 robertj
- * Fixed problem with PFileInfo::GetVolume() on UNC paths.
- *
- * Revision 1.42 1998/11/14 23:37:08 robertj
- * Fixed file path directory extraction, not able to return root directory
- *
- * Revision 1.41 1998/10/19 00:20:38 robertj
- * Moved error and trace stream functions to common code.
- *
- * Revision 1.40 1998/10/18 14:27:10 robertj
- * Improved tracing functions.
- *
- * Revision 1.39 1998/10/13 14:13:17 robertj
- * Complete rewrite of memory leak detection code.
- *
- * Revision 1.38 1998/09/24 03:30:53 robertj
- * Added open software license.
- *
- * Revision 1.37 1998/09/14 12:55:06 robertj
- * Changed memory debug to dump leaks not including static globals.
- *
- * Revision 1.36 1998/05/26 01:29:53 robertj
- * Removed assert as this Close() function is now called all the time for Unix reasons.
- *
- * Revision 1.35 1998/05/21 04:27:31 robertj
- * Compensated for MSC run time library bug.
- *
- * Revision 1.34 1998/04/01 01:54:45 robertj
- * Added memory leak checking to debug version.
- *
- * Revision 1.33 1998/03/29 06:16:51 robertj
- * Rearranged initialisation sequence so PProcess descendent constructors can do "things".
- *
- * Revision 1.32 1998/03/20 03:20:16 robertj
- * Added MSVC RT debug support.
- *
- * Revision 1.31 1998/01/26 00:54:15 robertj
- * 64 bit integer string conversions.
- *
- * Revision 1.30 1998/01/05 10:38:25 robertj
- * Unix pthreads compatibility, added threadsafe time functions.
- *
- * Revision 1.29 1997/12/11 10:40:29 robertj
- * Fixed bug in SetType() function of FilePath.
- *
- * Revision 1.28 1997/08/28 12:49:51 robertj
- * Fixed bug where could not change directory to UNC.
- *
- * Revision 1.27 1997/04/27 05:50:26 robertj
- * DLL support.
- *
- * Revision 1.26 1997/01/12 04:23:43 robertj
- * Fixed PDirectory::IsRoot() so works with UNC's
- *
- * Revision 1.25 1996/08/17 10:00:37 robertj
- * Changes for Windows DLL support.
- *
- * Revision 1.24 1996/08/08 10:09:23 robertj
- * Directory structure changes for common files.
- *
- * Revision 1.23 1996/01/28 02:56:16 robertj
- * Fixed bug in PFilePath functions for if path ends in a directory separator.
- *
- * Revision 1.22 1996/01/23 13:23:51 robertj
- * Fixed bug in PFileInfo for if path ends in directory separator.
- *
- * Revision 1.21 1996/01/02 12:56:49 robertj
- * Fixed copy of directories.
- *
- * Revision 1.20 1995/12/10 11:59:33 robertj
- * Changes to main() startup mechanism to support Mac.
- * Fixed bug in time interfval constant variable initialisation. Not guarenteed to work.
- * Moved error code for specific WIN32 and MS-DOS versions.
- *
- * Revision 1.19 1995/10/14 15:12:29 robertj
- * Added function to get parent directory.
- *
- * Revision 1.18 1995/07/31 12:18:11 robertj
- * Removed PContainer from PChannel ancestor.
- *
- * Revision 1.17 1995/06/04 13:10:19 robertj
- * Fixed rename bug.
- *
- * Revision 1.16 1995/06/04 12:48:06 robertj
- * Changed unknown error string to hex.
- * Added missing GetInfo function for directory entries
- *
- * Revision 1.15 1995/04/25 11:33:35 robertj
- * Changes for DLL support.
- *
- * Revision 1.14 1995/04/22 00:53:49 robertj
- * Added Move() function to PFile.
- * Changed semantics of Rename() function in PFile.
- * Changed file path string to use PFilePath object.
- *
- * Revision 1.13 1995/03/12 05:00:08 robertj
- * Re-organisation of DOS/WIN16 and WIN32 platforms to maximise common code.
- * Used built-in equate for WIN32 API (_WIN32).
- *
- * Revision 1.12 1995/02/27 10:37:06 robertj
- * Added GetUserNmae().
- * Removed superfluous Read() and Write() for text files.
- *
- * Revision 1.11 1995/01/06 10:41:43 robertj
- * Moved identifiers into different scope.
- * Changed file size to 64 bit integer.
- *
- * Revision 1.10 1994/12/21 11:36:07 robertj
- * Fixed caseless string for file paths.
- *
- * Revision 1.9 1994/10/30 11:26:54 robertj
- * Fixed set current directory function.
- * Changed PFilePath to be case insignificant according to platform.
- *
- * Revision 1.8 1994/10/23 05:42:39 robertj
- * PipeChannel headers.
- * ConvertOSError function added.
- * Numerous implementation enhancements.
- *
- * Revision 1.7 1994/08/04 13:24:27 robertj
- * Added debug stream.
- *
- * Revision 1.6 1994/07/27 06:00:10 robertj
- * Backup
- *
- * Revision 1.5 1994/07/21 12:35:18 robertj
- * *** empty log message ***
- *
- * Revision 1.4 1994/07/17 11:01:04 robertj
- * Ehancements, implementation, bug fixes etc.
- *
- * Revision 1.3 1994/07/02 03:18:09 robertj
- * Multi-threading implementation.
- *
- * Revision 1.2 1994/06/25 12:13:01 robertj
- * Synchronisation.
- *
- // Revision 1.1 1994/04/01 14:39:35 robertj
- // Initial revision
- //
- */
- #include <ptlib.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <share.h>
- #include <sysstat.h>
- #include <crtdbg.h>
- #if !P_USE_INLINES
- #include <ptlib/osutil.inl>
- #include <ptlib/ptlib.inl>
- #endif
- ostream & operator<<(ostream & s, PInt64 v)
- {
- char buffer[25];
- if ((s.flags()&ios::hex) != 0)
- return s << _ui64toa(v, buffer, 16);
- if ((s.flags()&ios::oct) != 0)
- return s << _ui64toa(v, buffer, 8);
- if (v < 0) {
- s << '-';
- v = -v;
- }
- return s << _i64toa(v, buffer, 10);
- }
- ostream & operator<<(ostream & s, PUInt64 v)
- {
- char buffer[25];
- return s << _ui64toa(v, buffer, (s.flags()&ios::oct) ? 8 : ((s.flags()&ios::hex) ? 16 : 10));
- }
- PInt64 PString::AsInt64(unsigned base) const
- {
- if (base == 10)
- return _atoi64(theArray);
- PAssert(base >= 2 && base <= 36, PInvalidParameter);
- PInt64 total = 0;
- const char * ptr = theArray;
- while (isspace(*ptr))
- ptr++;
- BOOL negative = *ptr == '-';
- if (*ptr == '-' || *ptr == '+')
- ptr++;
- for (;;) {
- unsigned c = *ptr++;
- if (c < '0')
- break;
- if (c <= '9')
- c -= '0';
- else
- c = toupper(c) - 'A' + 10;
- if (c >= base)
- break;
- total = base * total + c;
- c = *ptr++;
- }
- if (negative)
- return -total;
- else
- return total;
- }
- PUInt64 PString::AsUnsigned64(unsigned base) const
- {
- PAssert(base >= 2 && base <= 36, PInvalidParameter);
- PUInt64 total = 0;
- const char * ptr = theArray;
- while (isspace(*ptr))
- ptr++;
- for (;;) {
- unsigned c = *ptr++;
- if (c < '0')
- break;
- if (c <= '9')
- c -= '0';
- else
- c = toupper(c) - 'A' + 10;
- if (c >= base)
- break;
- total = base * total + c;
- c = *ptr++;
- }
- return total;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // PTime
- struct tm * PTime::os_localtime(const time_t * clock, struct tm * tb)
- {
- struct tm * tp = ::localtime(clock);
- if (tp != NULL)
- return tp;
- memset(tb, 0, sizeof(*tb));
- return tb;
- }
- struct tm * PTime::os_gmtime(const time_t * clock, struct tm * tb)
- {
- struct tm * tp = ::gmtime(clock);
- if (tp != NULL)
- return tp;
- memset(tb, 0, sizeof(*tb));
- return tb;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // PChannel
- void PChannel::Construct()
- {
- }
- PString PChannel::GetName() const
- {
- PAssertAlways(PUnimplementedFunction);
- return PString();
- }
- BOOL PChannel::Read(void *, PINDEX)
- {
- PAssertAlways(PUnimplementedFunction);
- return FALSE;
- }
- BOOL PChannel::Write(const void *, PINDEX)
- {
- PAssertAlways(PUnimplementedFunction);
- return FALSE;
- }
- BOOL PChannel::Close()
- {
- return FALSE;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // Directories
- PDirectory PDirectory::GetParent() const
- {
- if (IsRoot())
- return *this;
-
- return *this + "..";
- }
- BOOL PDirectory::Change(const PString & p)
- {
- PDirectory d = p;
- if (d[0] != '\')
- if (_chdrive(toupper(d[0])-'A'+1) != 0)
- return FALSE;
- return _chdir(d + ".") == 0;
- }
- BOOL PDirectory::Filtered()
- {
- #if defined(_WIN32)
- char * name = fileinfo.cFileName;
- #else
- char * name = fileinfo.name;
- #endif
- if (strcmp(name, ".") == 0)
- return TRUE;
- if (strcmp(name, "..") == 0)
- return TRUE;
- if (scanMask == PFileInfo::AllPermissions)
- return FALSE;
- PFileInfo inf;
- PAssert(PFile::GetInfo(*this+name, inf), POperatingSystemError);
- return (inf.type&scanMask) == 0;
- }
- BOOL PDirectory::IsRoot() const
- {
- if ((*this)[1] == ':')
- return GetLength() == 3;
- PINDEX pos = FindOneOf("/\", 2);
- return pos == GetLength();
- }
- BOOL PDirectory::GetInfo(PFileInfo & info) const
- {
- return PFile::GetInfo(*this + GetEntryName(), info);
- }
- ///////////////////////////////////////////////////////////////////////////////
- // File Path
- PFilePath::PFilePath(const PString & str)
- : PCaselessString(PDirectory::CreateFullPath(str, FALSE))
- {
- }
- PFilePath::PFilePath(const char * cstr)
- : PCaselessString(PDirectory::CreateFullPath(cstr, FALSE))
- {
- }
- PFilePath::PFilePath(const char * prefix, const char * dir)
- {
- if (dir != NULL) {
- PDirectory tmpdir(dir);
- operator=(tmpdir);
- }
- else {
- PConfig cfg(PConfig::Environment);
- PString path = cfg.GetString("TMPDIR");
- if (path.IsEmpty()) {
- path = cfg.GetString("TMP");
- if (path.IsEmpty())
- path = cfg.GetString("TEMP");
- }
- if (path.IsEmpty() || path[path.GetLength()-1] != '\')
- path += '\';
- *this = path;
- }
- if (prefix != NULL)
- *this += prefix;
- else
- *this += "PW";
- *this += "XXXXXX";
- PAssert(_mktemp(GetPointer()) != NULL, "Could not make temporary file");
- }
- PFilePath & PFilePath::operator=(const PString & str)
- {
- PCaselessString::operator=(PDirectory::CreateFullPath(str, FALSE));
- return *this;
- }
- static PINDEX GetVolumeSubStringLength(const PString & path)
- {
- if (path[1] == ':')
- return 2;
- if (path[0] == '\' && path[1] == '\') {
- PINDEX backslash = path.Find('\', 2);
- if (backslash != P_MAX_INDEX) {
- backslash = path.Find('\', backslash+1);
- if (backslash != P_MAX_INDEX)
- return backslash;
- }
- }
- PINDEX backslash = path.Find('\');
- if (backslash != P_MAX_INDEX)
- return backslash;
- return 0;
- }
- PCaselessString PFilePath::GetVolume() const
- {
- return Left(GetVolumeSubStringLength(*this));
- }
- PDirectory PFilePath::GetDirectory() const
- {
- PINDEX backslash = FindLast('\');
- if (backslash != P_MAX_INDEX)
- return Left(backslash+1);
- return PCaselessString();
- }
- PCaselessString PFilePath::GetPath() const
- {
- return operator()(GetVolumeSubStringLength(*this), FindLast('\', GetLength()-2));
- }
- PCaselessString PFilePath::GetFileName() const
- {
- PINDEX backslash = FindLast('\', GetLength()-2);
- if (backslash == P_MAX_INDEX)
- backslash = 0;
- else
- backslash++;
- return Mid(backslash);
- }
- PCaselessString PFilePath::GetTitle() const
- {
- PINDEX backslash = FindLast('\', GetLength()-2);
- if (backslash == P_MAX_INDEX)
- backslash = 0;
- else
- backslash++;
- return operator()(backslash, FindLast('.')-1);
- }
- PCaselessString PFilePath::GetType() const
- {
- PINDEX dot = Find('.', FindLast('\'));
- if (dot == P_MAX_INDEX)
- return PCaselessString();
- return operator()(dot, P_MAX_INDEX);
- }
- void PFilePath::SetType(const PCaselessString & type)
- {
- PINDEX dot = Find('.', FindLast('\'));
- if (dot != P_MAX_INDEX)
- Splice(type, dot, GetLength()-dot);
- else
- *this += type;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // PFile
- void PFile::SetFilePath(const PString & newName)
- {
- if (!IsOpen())
- path = newName;
- }
- BOOL PFile::Access(const PFilePath & name, OpenMode mode)
- {
- int accmode;
- switch (mode) {
- case ReadOnly :
- #ifndef R_OK
- #define R_OK 4
- #endif
- accmode = R_OK;
- break;
- case WriteOnly :
- #ifndef W_OK
- #define W_OK 2
- #endif
- accmode = W_OK;
- break;
- default :
- accmode = R_OK|W_OK;
- }
- return access(name, accmode) == 0;
- }
- BOOL PFile::Remove(const PFilePath & name, BOOL force)
- {
- if (remove(name) == 0)
- return TRUE;
- if (!force || errno != EACCES)
- return FALSE;
- if (_chmod(name, _S_IWRITE) != 0)
- return FALSE;
- return remove(name) == 0;
- }
- BOOL PFile::Rename(const PFilePath & oldname, const PString & newname, BOOL force)
- {
- if (newname.FindOneOf(":\/") != P_MAX_INDEX) {
- errno = EINVAL;
- return FALSE;
- }
- PString fullname = oldname.GetDirectory() + newname;
- if (rename(oldname, fullname) == 0)
- return TRUE;
- if (!force || errno == ENOENT || !Exists(fullname))
- return FALSE;
- if (!Remove(fullname, TRUE))
- return FALSE;
- return rename(oldname, fullname) == 0;
- }
- BOOL PFile::Move(const PFilePath & oldname, const PFilePath & newname, BOOL force)
- {
- if (rename(oldname, newname) == 0)
- return TRUE;
- if (errno == ENOENT)
- return FALSE;
- if (force && Exists(newname)) {
- if (!Remove(newname, TRUE))
- return FALSE;
- if (rename(oldname, newname) == 0)
- return TRUE;
- }
- return Copy(oldname, newname, force) && Remove(oldname);
- }
- BOOL PFile::GetInfo(const PFilePath & name, PFileInfo & info)
- {
- PString fn = name;
- PINDEX pos = fn.GetLength()-1;
- while (PDirectory::IsSeparator(fn[pos]))
- pos--;
- fn.Delete(pos+1, P_MAX_INDEX);
- struct stat s;
- if (stat(fn, &s) != 0)
- return FALSE;
- info.created = (s.st_ctime < 0) ? 0 : s.st_ctime;
- info.modified = (s.st_mtime < 0) ? 0 : s.st_mtime;
- info.accessed = (s.st_atime < 0) ? 0 : s.st_atime;
- info.size = s.st_size;
- info.permissions = 0;
- if ((s.st_mode&S_IREAD) != 0)
- info.permissions |=
- PFileInfo::UserRead|PFileInfo::GroupRead|PFileInfo::WorldRead;
- if ((s.st_mode&S_IWRITE) != 0)
- info.permissions |=
- PFileInfo::UserWrite|PFileInfo::GroupWrite|PFileInfo::WorldWrite;
- if ((s.st_mode&S_IEXEC) != 0)
- info.permissions |=
- PFileInfo::UserExecute|PFileInfo::GroupExecute|PFileInfo::WorldExecute;
- switch (s.st_mode & S_IFMT) {
- case S_IFREG :
- info.type = PFileInfo::RegularFile;
- break;
- case S_IFDIR :
- info.type = PFileInfo::SubDirectory;
- break;
- default:
- info.type = PFileInfo::UnknownFileType;
- break;
- }
- #if defined(_WIN32)
- info.hidden = (GetFileAttributes(name) & FILE_ATTRIBUTE_HIDDEN) != 0;
- #else
- unsigned int attr;
- _dos_getfileattr(name, &attr);
- info.hidden = (attr & _A_HIDDEN) != 0;
- #endif
- return TRUE;
- }
- BOOL PFile::SetPermissions(const PFilePath & name, int permissions)
- {
- return _chmod(name, permissions&(_S_IWRITE|_S_IREAD)) == 0;
- }
- BOOL PFile::IsTextFile() const
- {
- return FALSE;
- }
- BOOL PFile::Open(OpenMode mode, int opts)
- {
- Close();
- clear();
- if (path.IsEmpty())
- path = PFilePath("PWL", NULL);
- int oflags = IsTextFile() ? _O_TEXT : _O_BINARY;
- switch (mode) {
- case ReadOnly :
- oflags |= O_RDONLY;
- if (opts == ModeDefault)
- opts = MustExist;
- break;
- case WriteOnly :
- oflags |= O_WRONLY;
- if (opts == ModeDefault)
- opts = Create|Truncate;
- break;
- case ReadWrite :
- oflags |= O_RDWR;
- if (opts == ModeDefault)
- opts = Create;
- break;
- default :
- PAssertAlways(PInvalidParameter);
- }
- if ((opts&Create) != 0)
- oflags |= O_CREAT;
- if ((opts&Exclusive) != 0)
- oflags |= O_EXCL;
- if ((opts&Truncate) != 0)
- oflags |= O_TRUNC;
- if ((opts&Temporary) != 0)
- removeOnClose = TRUE;
- int sflags = _SH_DENYNO;
- if ((opts&DenySharedRead) == DenySharedRead)
- sflags = _SH_DENYRD;
- else if ((opts&DenySharedWrite) == DenySharedWrite)
- sflags = _SH_DENYWR;
- else if ((opts&(DenySharedRead|DenySharedWrite)) != 0)
- sflags = _SH_DENYWR;
- return ConvertOSError(os_handle = _sopen(path, oflags, sflags, S_IREAD|S_IWRITE));
- }
- BOOL PFile::SetLength(off_t len)
- {
- return ConvertOSError(_chsize(GetHandle(), len));
- }
- ///////////////////////////////////////////////////////////////////////////////
- // PTextFile
- BOOL PTextFile::IsTextFile() const
- {
- return TRUE;
- }
- BOOL PTextFile::ReadLine(PString & str)
- {
- char * ptr = str.GetPointer(100);
- PINDEX len = 0;
- int c;
- while ((c = ReadChar()) >= 0 && c != 'n') {
- *ptr++ = (char)c;
- if (++len >= str.GetSize())
- ptr = str.GetPointer(len + 100) + len;
- }
- *ptr = ' ';
- PAssert(str.MakeMinimumSize(), POutOfMemory);
- return c >= 0 || len > 0;
- }
- BOOL PTextFile::WriteLine(const PString & str)
- {
- return WriteString(str) && WriteChar('n');
- }
- ///////////////////////////////////////////////////////////////////////////////
- // PConsoleChannel
- PConsoleChannel::PConsoleChannel()
- {
- }
- PConsoleChannel::PConsoleChannel(ConsoleType type)
- {
- Open(type);
- }
- BOOL PConsoleChannel::Open(ConsoleType type)
- {
- switch (type) {
- case StandardInput :
- os_handle = 0;
- return TRUE;
- case StandardOutput :
- os_handle = 1;
- return TRUE;
- case StandardError :
- os_handle = 2;
- return TRUE;
- }
- return FALSE;
- }
- PString PConsoleChannel::GetName() const
- {
- return "\\.\Console";
- }
- BOOL PConsoleChannel::Read(void * buffer, PINDEX length)
- {
- flush();
- lastReadCount = _read(os_handle, buffer, length);
- return ConvertOSError(lastReadCount) && lastReadCount > 0;
- }
- BOOL PConsoleChannel::Write(const void * buffer, PINDEX length)
- {
- flush();
- lastWriteCount = _write(os_handle, buffer, length);
- return ConvertOSError(lastWriteCount) && lastWriteCount >= length;
- }
- BOOL PConsoleChannel::Close()
- {
- os_handle = -1;
- return TRUE;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // PProcess
- void PProcess::Construct()
- {
- PSetErrorStream(&cerr);
- #if !defined(_WIN32) && defined(_MSC_VER) && defined(_WINDOWS)
- _wsetscreenbuf(1, _WINBUFINF);
- _wsizeinfo ws;
- ws._version = _QWINVER;
- ws._type = _WINSIZEMAX;
- _wsetsize(1, &ws);
- #endif
- houseKeeper = NULL;
- }
- //////////////////////////////////////////////////////////////////////////////
- #define INCLUDE_STUFF1(cls)
- cls i##cls;
- i##cls = i##cls
- #define INCLUDE_STUFF2(cls)
- INCLUDE_STUFF1(cls);
- i##cls.GetPointer();
- i##cls.Attach(0, 0);
- i##cls.SetAt(0, 0);
- i##cls.GetAt(0);
- i##cls[0]
- void PDummyFunctionToMakeSureSymbolsAreInDEFFile()
- {
- INCLUDE_STUFF2(PCharArray);
- INCLUDE_STUFF2(PShortArray);
- INCLUDE_STUFF2(PIntArray);
- INCLUDE_STUFF2(PLongArray);
- INCLUDE_STUFF2(PBYTEArray);
- INCLUDE_STUFF2(PWORDArray);
- INCLUDE_STUFF2(PUnsignedArray);
- INCLUDE_STUFF2(PDWORDArray);
- INCLUDE_STUFF1(PStringSet);
- INCLUDE_STUFF1(POrdinalToString);
- INCLUDE_STUFF1(PStringToOrdinal);
- INCLUDE_STUFF1(PStringToString);
- }
- // End Of File ///////////////////////////////////////////////////////////////