-//uchime by Robert C. Edgar http://drive5.com/uchime This code is donated to the public domain.\r
-\r
#include <time.h>\r
#include <stdarg.h>\r
#include <sys/stat.h>\r
#include <signal.h>\r
#include <float.h>\r
\r
-#ifdef _MSC_VER\r
-#include <crtdbg.h>\r
-#include <process.h>\r
-#include <windows.h>\r
-#include <psapi.h>\r
-#include <io.h>\r
-#else\r
+#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)\r
#include <sys/time.h>\r
#include <sys/resource.h>\r
#include <unistd.h>\r
#include <errno.h>\r
#include <fcntl.h>\r
#include <stdlib.h>\r
+#else\r
+//#include <crtdbg.h>\r
+#include <process.h>\r
+#include <windows.h>\r
+#include <psapi.h>\r
+#include <io.h>\r
#endif\r
\r
#include "myutils.h"\r
\r
#if TEST_UTILS\r
void TestUtils()\r
- {\r
+{\r
const int C = 100000000;\r
for (int i = 0; i < C; ++i)\r
ProgressStep(i, C, "something or other");\r
-\r
+ \r
Progress("\n");\r
Progress("Longer message\r");\r
Sleep(1000);\r
const unsigned N = 10;\r
unsigned M = 10;\r
for (unsigned i = 0; i < N; ++i)\r
- {\r
+ {\r
ProgressStep(i, N, "Allocating 1MB blocks");\r
for (unsigned j = 0; j < M; ++j)\r
- {\r
+ {\r
ProgressStep(j, M, "Inner loop"); \r
malloc(100000);\r
Sleep(500);\r
- }\r
}\r
}\r
+}\r
#endif // TEST_UTILS\r
\r
static void AllocBuffer(FILE *f)\r
- {\r
+{\r
int fd = fileno(f);\r
if (fd < 0 || fd >= 256)\r
return;\r
if (g_IOBuffers[fd] == 0)\r
g_IOBuffers[fd] = myalloc(char, MY_IO_BUFSIZ);\r
setvbuf(f, g_IOBuffers[fd], _IOFBF, MY_IO_BUFSIZ);\r
- }\r
+}\r
\r
static void FreeBuffer(FILE *f)\r
- {\r
+{\r
int fd = fileno(f);\r
if (fd < 0 || fd >= 256)\r
return;\r
return;\r
myfree(g_IOBuffers[fd]);\r
g_IOBuffers[fd] = 0;\r
- }\r
+}\r
\r
unsigned GetElapsedSecs()\r
- {\r
+{\r
return (unsigned) (time(0) - g_StartTime);\r
- }\r
+}\r
\r
static unsigned g_NewCalls;\r
static unsigned g_FreeCalls;\r
static double g_MaxNetBytes;\r
\r
void LogAllocStats()\r
- {\r
+{\r
Log("\n");\r
Log(" Allocs %u\n", g_NewCalls);\r
Log(" Frees %u\n", g_FreeCalls);\r
Log(" Net bytes %s\n", MemBytesToStr(g_NetBytes));\r
Log("Max net bytes %s\n", MemBytesToStr(g_MaxNetBytes));\r
Log(" Peak total %s\n", MemBytesToStr(g_MaxNetBytes + g_InitialMemUseBytes));\r
- }\r
+}\r
\r
bool StdioFileExists(const string &FileName)\r
- {\r
+{\r
struct stat SD;\r
int i = stat(FileName.c_str(), &SD);\r
return i == 0;\r
- }\r
+}\r
\r
void myassertfail(const char *Exp, const char *File, unsigned Line)\r
- {\r
+{\r
Die("%s(%u) assert failed: %s", File, Line, Exp);\r
- }\r
+}\r
\r
bool myisatty(int fd)\r
- {\r
+{\r
return isatty(fd) != 0;\r
- }\r
+}\r
\r
-#ifdef _MSC_VER\r
-#include <io.h>\r
+#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)\r
+#else\r
+//#ifdef BIT_VERSION\r
+//#include <io.h>\r
+//int fseeko(FILE *stream, off_t offset, int whence)\r
+//// {\r
+// off_t FilePos = _fseeki64(stream, offset, whence);\r
+// return (FilePos == -1L) ? -1 : 0;\r
+// }\r
+//#define ftello(fm) (off_t) _ftelli64(fm)\r
+//#else \r
int fseeko(FILE *stream, off_t offset, int whence)\r
- {\r
- off_t FilePos = _fseeki64(stream, offset, whence);\r
+{\r
+ off_t FilePos = fseek(stream, offset, whence);\r
return (FilePos == -1L) ? -1 : 0;\r
- }\r
-#define ftello(fm) (off_t) _ftelli64(fm)\r
+}\r
+#define ftello(fm) (off_t) ftell(fm)\r
+//#endif\r
#endif\r
\r
void LogStdioFileState(FILE *f)\r
- {\r
+{\r
unsigned long tellpos = (unsigned long) ftello(f);\r
long fseek_pos = fseek(f, 0, SEEK_CUR);\r
int fd = fileno(f);\r
fpos_t fpos;\r
int fgetpos_retval = fgetpos(f, &fpos);\r
Log("fpos %ld (retval %d)\n", (long) fpos, fgetpos_retval);\r
-// Log("eof %d\n", _eof(fd));\r
+ // Log("eof %d\n", _eof(fd));\r
#endif\r
-#ifdef _MSC_VER\r
+#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)\r
+#else\r
+#ifdef BIT_VERSION\r
__int64 pos64 = _ftelli64(f);\r
Log("_ftelli64 %lld\n", pos64);\r
+#else\r
+ __int32 pos32 = ftell(f);\r
+ Log("ftell %lld\n", pos32);\r
+ \r
#endif\r
- }\r
+#endif\r
+}\r
\r
FILE *OpenStdioFile(const string &FileName)\r
- {\r
+{\r
const char *Mode = "rb";\r
FILE *f = fopen(FileName.c_str(), Mode);\r
if (f == 0)\r
- {\r
+ {\r
if (errno == EFBIG)\r
- {\r
+ {\r
if (sizeof(off_t) == 4)\r
Die("File too big, off_t is 32 bits, recompile needed");\r
else\r
Die("Cannot open '%s', file too big (off_t=%u bits)",\r
- FileName.c_str(), sizeof(off_t)*8);\r
- }\r
- Die("Cannot open %s, errno=%d %s",\r
- FileName.c_str(), errno, strerror(errno));\r
+ FileName.c_str(), sizeof(off_t)*8);\r
}\r
+ Die("Cannot open %s, errno=%d %s",\r
+ FileName.c_str(), errno, strerror(errno));\r
+ }\r
AllocBuffer(f);\r
return f;\r
- }\r
+}\r
\r
FILE *CreateStdioFile(const string &FileName)\r
- {\r
+{\r
FILE *f = fopen(FileName.c_str(), "wb+");\r
if (0 == f)\r
Die("Cannot create %s, errno=%d %s",\r
- FileName.c_str(), errno, strerror(errno));\r
+ FileName.c_str(), errno, strerror(errno));\r
AllocBuffer(f);\r
return f;\r
- }\r
+}\r
\r
void SetStdioFilePos(FILE *f, off_t Pos)\r
- {\r
+{\r
if (0 == f)\r
Die("SetStdioFilePos failed, f=NULL");\r
int Ok = fseeko(f, Pos, SEEK_SET);\r
off_t NewPos = ftello(f);\r
if (Ok != 0 || Pos != NewPos)\r
- {\r
+ {\r
LogStdioFileState(f);\r
Die("SetStdioFilePos(%d) failed, Ok=%d NewPos=%d",\r
- (int) Pos, Ok, (int) NewPos);\r
- }\r
+ (int) Pos, Ok, (int) NewPos);\r
}\r
+}\r
\r
void ReadStdioFile(FILE *f, off_t Pos, void *Buffer, unsigned Bytes)\r
- {\r
+{\r
if (0 == f)\r
Die("ReadStdioFile failed, f=NULL");\r
SetStdioFilePos(f, Pos);\r
unsigned BytesRead = fread(Buffer, 1, Bytes, f);\r
if (BytesRead != Bytes)\r
- {\r
+ {\r
LogStdioFileState(f);\r
Die("ReadStdioFile failed, attempted %d bytes, read %d bytes, errno=%d",\r
- (int) Bytes, (int) BytesRead, errno);\r
- }\r
+ (int) Bytes, (int) BytesRead, errno);\r
}\r
+}\r
\r
void ReadStdioFile(FILE *f, void *Buffer, unsigned Bytes)\r
- {\r
+{\r
if (0 == f)\r
Die("ReadStdioFile failed, f=NULL");\r
unsigned BytesRead = fread(Buffer, 1, Bytes, f);\r
if (BytesRead != Bytes)\r
- {\r
+ {\r
LogStdioFileState(f);\r
Die("ReadStdioFile failed, attempted %d bytes, read %d bytes, errno=%d",\r
- (int) Bytes, (int) BytesRead, errno);\r
- }\r
+ (int) Bytes, (int) BytesRead, errno);\r
}\r
+}\r
\r
// Return values from functions like lseek, ftell, fgetpos are\r
// "undefined" for files that cannot seek. Attempt to detect\r
// whether a file can seek by checking for error returns.\r
bool CanSetStdioFilePos(FILE *f)\r
- {\r
-// Common special cases\r
+{\r
+ // Common special cases\r
if (f == stdin || f == stdout || f == stderr)\r
return false;\r
-\r
+ \r
fpos_t CurrPos;\r
int ok1 = fgetpos(f, &CurrPos);\r
if (ok1 < 0)\r
if (!ok3 || !ok4)\r
return false;\r
return true;\r
- }\r
+}\r
\r
byte *ReadAllStdioFile(FILE *f, unsigned &FileSize)\r
- {\r
+{\r
const unsigned BUFF_SIZE = 1024*1024;\r
-\r
+ \r
if (CanSetStdioFilePos(f))\r
- {\r
+ {\r
off_t Pos = GetStdioFilePos(f);\r
off_t FileSize = GetStdioFileSize(f);\r
if (FileSize > UINT_MAX)\r
SetStdioFilePos(f, Pos);\r
FileSize = unsigned(FileSize);\r
return Buffer;\r
- }\r
-\r
-// Can't seek, read one buffer at a time.\r
+ }\r
+ \r
+ // Can't seek, read one buffer at a time.\r
FileSize = 0;\r
-\r
-// Just to initialize so that first call to realloc works.\r
+ \r
+ // Just to initialize so that first call to realloc works.\r
byte *Buffer = (byte *) malloc(4);\r
if (Buffer == 0)\r
Die("ReadAllStdioFile, out of memory");\r
for (;;)\r
- {\r
+ {\r
Buffer = (byte *) realloc(Buffer, FileSize + BUFF_SIZE);\r
unsigned BytesRead = fread(Buffer + FileSize, 1, BUFF_SIZE, f);\r
FileSize += BytesRead;\r
if (BytesRead < BUFF_SIZE)\r
- {\r
+ {\r
Buffer = (byte *) realloc(Buffer, FileSize);\r
return Buffer;\r
- }\r
}\r
}\r
+}\r
\r
byte *ReadAllStdioFile(const std::string &FileName, off_t &FileSize)\r
- {\r
+{\r
#if WIN32\r
FILE *f = OpenStdioFile(FileName);\r
FileSize = GetStdioFileSize(f);\r
CloseStdioFile(f);\r
-\r
+ \r
HANDLE h = CreateFile(FileName.c_str(), GENERIC_READ, FILE_SHARE_READ,\r
- NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\r
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\r
if (h == INVALID_HANDLE_VALUE)\r
Die("ReadAllStdioFile:Open(%s) failed", FileName.c_str());\r
-\r
+ \r
unsigned uFileSize = (unsigned) FileSize;\r
if ((off_t) uFileSize != FileSize)\r
Die("File too big (%.1f Gb): %s", double(FileSize)/1e9, FileName.c_str());\r
-\r
+ \r
byte *Buffer = myalloc(byte, uFileSize);\r
DWORD BytesRead;\r
ReadFile(h, Buffer, uFileSize, &BytesRead, NULL);\r
if (FileSize != BytesRead)\r
Die("ReadAllStdioFile:Error reading %s, attempted %u got %u",\r
- FileName.c_str(), FileSize, (unsigned) BytesRead);\r
-\r
+ FileName.c_str(), FileSize, (unsigned) BytesRead);\r
+ \r
CloseHandle(h);\r
return Buffer;\r
#else\r
size_t n = read(h, Buffer, stBytes);\r
if (n != FileSize)\r
Die("ReadAllStdioFile, Error reading %s, attempted %g got %g",\r
- FileName.c_str(), (double) FileSize, (double) n);\r
+ FileName.c_str(), (double) FileSize, (double) n);\r
close(h);\r
return Buffer;\r
#endif\r
- }\r
+}\r
\r
void WriteStdioFile(FILE *f, off_t Pos, const void *Buffer, unsigned Bytes)\r
- {\r
+{\r
if (0 == f)\r
Die("WriteStdioFile failed, f=NULL");\r
SetStdioFilePos(f, Pos);\r
unsigned BytesWritten = fwrite(Buffer, 1, Bytes, f);\r
if (BytesWritten != Bytes)\r
- {\r
+ {\r
LogStdioFileState(f);\r
Die("WriteStdioFile failed, attempted %d bytes, wrote %d bytes, errno=%d",\r
- (int) Bytes, (int) BytesWritten, errno);\r
- }\r
+ (int) Bytes, (int) BytesWritten, errno);\r
}\r
+}\r
\r
void WriteStdioFile(FILE *f, const void *Buffer, unsigned Bytes)\r
- {\r
+{\r
if (0 == f)\r
Die("WriteStdioFile failed, f=NULL");\r
unsigned BytesWritten = fwrite(Buffer, 1, Bytes, f);\r
if (BytesWritten != Bytes)\r
- {\r
+ {\r
LogStdioFileState(f);\r
Die("WriteStdioFile failed, attempted %d bytes, wrote %d bytes, errno=%d",\r
- (int) Bytes, (int) BytesWritten, errno);\r
- }\r
+ (int) Bytes, (int) BytesWritten, errno);\r
}\r
+}\r
\r
// Return false on EOF, true if line successfully read.\r
bool ReadLineStdioFile(FILE *f, char *Line, unsigned Bytes)\r
- {\r
+{\r
if (feof(f))\r
return false;\r
if ((int) Bytes < 0)\r
Die("ReadLineStdioFile: Bytes < 0");\r
char *RetVal = fgets(Line, (int) Bytes, f);\r
if (NULL == RetVal)\r
- {\r
+ {\r
if (feof(f))\r
return false;\r
if (ferror(f))\r
Die("ReadLineStdioFile: errno=%d", errno);\r
Die("ReadLineStdioFile: fgets=0, feof=0, ferror=0");\r
- }\r
-\r
+ }\r
+ \r
if (RetVal != Line)\r
Die("ReadLineStdioFile: fgets != Buffer");\r
unsigned n = strlen(Line);\r
if (n > 1 && (Line[n-2] == '\r' || Line[n-2] == '\n'))\r
Line[n-2] = 0;\r
return true;\r
- }\r
+}\r
\r
// Return false on EOF, true if line successfully read.\r
bool ReadLineStdioFile(FILE *f, string &Line)\r
- {\r
+{\r
Line.clear();\r
for (;;)\r
- {\r
+ {\r
int c = fgetc(f);\r
if (c == -1)\r
- {\r
+ {\r
if (feof(f))\r
- {\r
+ {\r
if (!Line.empty())\r
return true;\r
return false;\r
- }\r
- Die("ReadLineStdioFile, errno=%d", errno);\r
}\r
+ Die("ReadLineStdioFile, errno=%d", errno);\r
+ }\r
if (c == '\r')\r
continue;\r
if (c == '\n')\r
return true;\r
Line.push_back((char) c);\r
- }\r
}\r
+}\r
\r
// Copies all of fFrom regardless of current\r
// file position, appends to fTo.\r
void AppendStdioFileToFile(FILE *fFrom, FILE *fTo)\r
- {\r
+{\r
off_t SavedFromPos = GetStdioFilePos(fFrom);\r
off_t FileSize = GetStdioFileSize(fFrom);\r
const off_t BUFF_SIZE = 1024*1024;\r
SetStdioFilePos(fFrom, 0);\r
off_t BytesRemaining = FileSize;\r
while (BytesRemaining > 0)\r
- {\r
+ {\r
off_t BytesToRead = BytesRemaining;\r
if (BytesToRead > BUFF_SIZE)\r
BytesToRead = BUFF_SIZE;\r
ReadStdioFile(fFrom, Buffer, (unsigned) BytesToRead);\r
WriteStdioFile(fTo, Buffer, (unsigned) BytesToRead);\r
BytesRemaining -= BytesToRead;\r
- }\r
- SetStdioFilePos(fFrom, SavedFromPos);\r
}\r
+ SetStdioFilePos(fFrom, SavedFromPos);\r
+}\r
\r
void RenameStdioFile(const string &FileNameFrom, const string &FileNameTo)\r
- {\r
+{\r
int Ok = rename(FileNameFrom.c_str(), FileNameTo.c_str());\r
if (Ok != 0)\r
Die("RenameStdioFile(%s,%s) failed, errno=%d %s",\r
- FileNameFrom.c_str(), FileNameTo.c_str(), errno, strerror(errno));\r
- }\r
+ FileNameFrom.c_str(), FileNameTo.c_str(), errno, strerror(errno));\r
+}\r
\r
void FlushStdioFile(FILE *f)\r
- {\r
+{\r
int Ok = fflush(f);\r
if (Ok != 0)\r
Die("fflush(%p)=%d,", f, Ok);\r
- }\r
+}\r
\r
void CloseStdioFile(FILE *f)\r
- {\r
+{\r
if (f == 0)\r
return;\r
int Ok = fclose(f);\r
if (Ok != 0)\r
Die("fclose(%p)=%d", f, Ok);\r
FreeBuffer(f);\r
- }\r
+}\r
\r
off_t GetStdioFilePos(FILE *f)\r
- {\r
+{\r
off_t FilePos = ftello(f);\r
if (FilePos < 0)\r
Die("ftello=%d", (int) FilePos);\r
return FilePos;\r
- }\r
+}\r
\r
off_t GetStdioFileSize(FILE *f)\r
- {\r
+{\r
off_t CurrentPos = GetStdioFilePos(f);\r
- int Ok = fseeko(f, 0, SEEK_END);\r
+ off_t zeroPos = 0;\r
+ int Ok = fseeko(f, zeroPos, SEEK_END);\r
if (Ok < 0)\r
Die("fseek in GetFileSize");\r
-\r
+ \r
off_t Length = ftello(f);\r
if (Length < 0)\r
Die("ftello in GetFileSize");\r
SetStdioFilePos(f, CurrentPos);\r
return Length;\r
- }\r
+}\r
\r
void DeleteStdioFile(const string &FileName)\r
- {\r
+{\r
int Ok = remove(FileName.c_str());\r
if (Ok != 0)\r
Die("remove(%s) failed, errno=%d %s", FileName.c_str(), errno, strerror(errno));\r
- }\r
+}\r
\r
void myvstrprintf(string &Str, const char *Format, va_list ArgList)\r
- {\r
+{\r
static char szStr[MAX_FORMATTED_STRING_LENGTH];\r
vsnprintf(szStr, MAX_FORMATTED_STRING_LENGTH-1, Format, ArgList);\r
szStr[MAX_FORMATTED_STRING_LENGTH - 1] = '\0';\r
Str.assign(szStr);\r
- }\r
+}\r
\r
void myvstrprintf(string &Str, const char *Format, ...)\r
- {\r
+{\r
va_list ArgList;\r
va_start(ArgList, Format);\r
myvstrprintf(Str, Format, ArgList);\r
va_end(ArgList);\r
- }\r
+}\r
\r
FILE *g_fLog = 0;\r
\r
void SetLogFileName(const string &FileName)\r
- {\r
+{\r
if (g_fLog != 0)\r
CloseStdioFile(g_fLog);\r
g_fLog = 0;\r
if (FileName.empty())\r
return;\r
g_fLog = CreateStdioFile(FileName);\r
- }\r
+}\r
\r
void Log(const char *Format, ...)\r
- {\r
+{\r
if (g_fLog == 0)\r
return;\r
-\r
+ \r
static bool InLog = false;\r
if (InLog)\r
return;\r
-\r
+ \r
InLog = true;\r
va_list ArgList;\r
va_start(ArgList, Format);\r
va_end(ArgList);\r
fflush(g_fLog);\r
InLog = false;\r
- }\r
+}\r
\r
void Die(const char *Format, ...)\r
- {\r
+{\r
static bool InDie = false;\r
if (InDie)\r
exit(1);\r
InDie = true;\r
string Msg;\r
-\r
+ \r
if (g_fLog != 0)\r
setbuf(g_fLog, 0);\r
va_list ArgList;\r
va_start(ArgList, Format);\r
myvstrprintf(Msg, Format, ArgList);\r
va_end(ArgList);\r
-\r
+ \r
fprintf(stderr, "\n\n");\r
Log("\n");\r
time_t t = time(0);\r
Log("%s", asctime(localtime(&t)));\r
for (unsigned i = 0; i < g_Argv.size(); i++)\r
- {\r
+ {\r
fprintf(stderr, (i == 0) ? "%s" : " %s", g_Argv[i].c_str());\r
Log((i == 0) ? "%s" : " %s", g_Argv[i].c_str());\r
- }\r
+ }\r
fprintf(stderr, "\n");\r
Log("\n");\r
-\r
+ \r
time_t CurrentTime = time(0);\r
unsigned ElapsedSeconds = unsigned(CurrentTime - g_StartTime);\r
const char *sstr = SecsToStr(ElapsedSeconds);\r
Log("Elapsed time: %s\n", sstr);\r
-\r
+ \r
const char *szStr = Msg.c_str();\r
fprintf(stderr, "\n---Fatal error---\n%s\n", szStr);\r
Log("\n---Fatal error---\n%s\n", szStr);\r
-\r
-#ifdef _MSC_VER\r
- if (IsDebuggerPresent())\r
- __debugbreak();\r
- _CrtSetDbgFlag(0);\r
+ \r
+#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)\r
+#else\r
+ //if (IsDebuggerPresent())\r
+ // __debugbreak();\r
+ //_CrtSetDbgFlag(0);\r
#endif\r
-\r
+ \r
exit(1);\r
- }\r
+}\r
\r
void Warning(const char *Format, ...)\r
- {\r
+{\r
string Msg;\r
-\r
+ \r
va_list ArgList;\r
va_start(ArgList, Format);\r
myvstrprintf(Msg, Format, ArgList);\r
va_end(ArgList);\r
-\r
+ \r
const char *szStr = Msg.c_str();\r
-\r
+ \r
fprintf(stderr, "\nWARNING: %s\n", szStr);\r
if (g_fLog != stdout)\r
- {\r
+ {\r
Log("\nWARNING: %s\n", szStr);\r
fflush(g_fLog);\r
- }\r
}\r
+}\r
\r
-#ifdef _MSC_VER\r
-double GetMemUseBytes()\r
- {\r
- HANDLE hProc = GetCurrentProcess();\r
- PROCESS_MEMORY_COUNTERS PMC;\r
- BOOL bOk = GetProcessMemoryInfo(hProc, &PMC, sizeof(PMC));\r
- if (!bOk)\r
- return 1000000;\r
- double Bytes = (double) PMC.WorkingSetSize;\r
- if (Bytes > g_PeakMemUseBytes)\r
- g_PeakMemUseBytes = Bytes;\r
- return Bytes;\r
- }\r
-#elif linux || __linux__\r
+#if defined linux || __linux__\r
double GetMemUseBytes()\r
- {\r
+{\r
static char statm[64];\r
static int PageSize = 1;\r
if (0 == statm[0])\r
- {\r
+ {\r
PageSize = sysconf(_SC_PAGESIZE);\r
pid_t pid = getpid();\r
sprintf(statm, "/proc/%d/statm", (int) pid);\r
- }\r
-\r
+ }\r
+ \r
int fd = open(statm, O_RDONLY);\r
if (-1 == fd)\r
return 1000000;\r
int n = read(fd, Buffer, sizeof(Buffer) - 1);\r
close(fd);\r
fd = -1;\r
-\r
+ \r
if (n <= 0)\r
return 1000000;\r
-\r
+ \r
Buffer[n] = 0;\r
double Pages = atof(Buffer);\r
-\r
+ \r
double Bytes = Pages*PageSize;\r
if (Bytes > g_PeakMemUseBytes)\r
g_PeakMemUseBytes = Bytes;\r
return Bytes;\r
- }\r
-#elif defined(__MACH__)\r
+}\r
+#elif defined(__APPLE__) || (__MACH__)\r
#include <memory.h>\r
#include <stdlib.h>\r
#include <stdio.h>\r
#define DEFAULT_MEM_USE 100000000.0\r
\r
double GetMemUseBytes()\r
- {\r
+{\r
task_t mytask = mach_task_self();\r
struct task_basic_info ti;\r
memset((void *) &ti, 0, sizeof(ti));\r
kern_return_t ok = task_info(mytask, TASK_BASIC_INFO, (task_info_t) &ti, &count);\r
if (ok == KERN_INVALID_ARGUMENT)\r
return DEFAULT_MEM_USE;\r
-\r
+ \r
if (ok != KERN_SUCCESS)\r
return DEFAULT_MEM_USE;\r
-\r
+ \r
double Bytes = (double ) ti.resident_size;\r
if (Bytes > g_PeakMemUseBytes)\r
g_PeakMemUseBytes = Bytes;\r
return Bytes;\r
- }\r
+}\r
#else\r
double GetMemUseBytes()\r
- {\r
+{\r
return 0;\r
- }\r
+}\r
#endif\r
\r
double GetPeakMemUseBytes()\r
- {\r
+{\r
return g_PeakMemUseBytes;\r
- }\r
+}\r
\r
const char *SecsToHHMMSS(int Secs)\r
- {\r
+{\r
int HH = Secs/3600;\r
int MM = (Secs - HH*3600)/60;\r
int SS = Secs%60;\r
else\r
sprintf(Str, "%02d:%02d:%02d", HH, MM, SS);\r
return Str;\r
- }\r
+}\r
\r
const char *SecsToStr(double Secs)\r
- {\r
+{\r
if (Secs >= 10.0)\r
return SecsToHHMMSS((int) Secs);\r
-\r
+ \r
static char Str[16];\r
if (Secs < 1e-6)\r
sprintf(Str, "%.2gs", Secs);\r
else\r
sprintf(Str, "%.3fs", Secs);\r
return Str;\r
- }\r
+}\r
\r
const char *MemBytesToStr(double Bytes)\r
- {\r
+{\r
static char Str[32];\r
-\r
+ \r
if (Bytes < 1e6)\r
sprintf(Str, "%.1fkb", Bytes/1e3);\r
else if (Bytes < 10e6)\r
else\r
sprintf(Str, "%.3gb", Bytes);\r
return Str;\r
- }\r
+}\r
\r
const char *IntToStr(unsigned i)\r
- {\r
+{\r
static char Str[32];\r
-\r
+ \r
double d = (double) i;\r
if (i < 10000)\r
sprintf(Str, "%u", i);\r
else\r
sprintf(Str, "%.3g", d);\r
return Str;\r
- }\r
+}\r
\r
const char *FloatToStr(double d)\r
- {\r
+{\r
static char Str[32];\r
-\r
+ \r
double a = fabs(d);\r
if (a < 0.01)\r
sprintf(Str, "%.3g", a);\r
else if (a >= 0.01 && a < 1)\r
sprintf(Str, "%.3f", a);\r
else if (a <= 10 && a >= 1)\r
- {\r
+ {\r
double intpart;\r
if (modf(a, &intpart) < 0.05)\r
sprintf(Str, "%.0f", d);\r
else\r
sprintf(Str, "%.1f", d);\r
- }\r
+ }\r
else if (a > 10 && a < 10000)\r
sprintf(Str, "%.0f", d);\r
else if (a < 1e6)\r
else\r
sprintf(Str, "%.3g", d);\r
return Str;\r
- }\r
+}\r
\r
bool opt_quiet = false;\r
bool opt_version = false;\r
static time_t g_TimeLastOutputStep;\r
\r
static string &GetProgressPrefixStr(string &s)\r
- {\r
+{\r
double Bytes = GetMemUseBytes();\r
unsigned Secs = GetElapsedSecs();\r
s = string(SecsToHHMMSS(Secs));\r
if (Bytes > 0)\r
- {\r
+ {\r
s.push_back(' ');\r
char Str[32];\r
sprintf(Str, "%5.5s", MemBytesToStr(Bytes));\r
s += string(Str);\r
- }\r
+ }\r
s.push_back(' ');\r
return s;\r
- }\r
+}\r
\r
void ProgressLog(const char *Format, ...)\r
- {\r
+{\r
string Str;\r
va_list ArgList;\r
va_start(ArgList, Format);\r
myvstrprintf(Str, Format, ArgList);\r
va_end(ArgList);\r
-\r
+ \r
Log("%s", Str.c_str());\r
Progress("%s", Str.c_str());\r
- }\r
+}\r
\r
void Progress(const char *Format, ...)\r
- {\r
+{\r
if (opt_quiet)\r
return;\r
-\r
+ \r
string Str;\r
va_list ArgList;\r
va_start(ArgList, Format);\r
myvstrprintf(Str, Format, ArgList);\r
va_end(ArgList);\r
-\r
+ \r
#if 0\r
Log("Progress(");\r
for (unsigned i = 0; i < Str.size(); ++i)\r
- {\r
+ {\r
char c = Str[i];\r
if (c == '\r')\r
Log("\\r");\r
Log("\\n");\r
else\r
Log("%c", c);\r
- }\r
+ }\r
Log(")\n");\r
#endif //0\r
-\r
+ \r
for (unsigned i = 0; i < Str.size(); ++i)\r
- {\r
+ {\r
if (g_CurrProgressLineLength == 0)\r
- {\r
+ {\r
string s;\r
GetProgressPrefixStr(s);\r
for (unsigned j = 0; j < s.size(); ++j)\r
- {\r
+ {\r
fputc(s[j], stderr);\r
++g_CurrProgressLineLength;\r
- }\r
}\r
-\r
+ }\r
+ \r
char c = Str[i];\r
if (c == '\n' || c == '\r')\r
- {\r
+ {\r
for (unsigned j = g_CurrProgressLineLength; j < g_LastProgressLineLength; ++j)\r
fputc(' ', stderr);\r
if (c == '\n')\r
g_LastProgressLineLength = g_CurrProgressLineLength;\r
g_CurrProgressLineLength = 0;\r
fputc(c, stderr);\r
- }\r
+ }\r
else\r
- {\r
+ {\r
fputc(c, stderr);\r
++g_CurrProgressLineLength;\r
- }\r
}\r
}\r
+}\r
\r
void ProgressExit()\r
- {\r
+{\r
time_t Now = time(0);\r
struct tm *t = localtime(&Now);\r
const char *s = asctime(t);\r
unsigned Secs = GetElapsedSecs();\r
-\r
+ \r
Log("\n");\r
Log("Finished %s", s); // there is a newline in s\r
Log("Elapsed time %s\n", SecsToHHMMSS((int) Secs));\r
Log("Max memory %s\n", MemBytesToStr(g_PeakMemUseBytes));\r
#if WIN32 && DEBUG\r
-// Skip exit(), which can be very slow in DEBUG build\r
-// VERY DANGEROUS practice, because it skips global destructors.\r
-// But if you know the rules, you can break 'em, right?\r
- ExitProcess(0);\r
+ // Skip exit(), which can be very slow in DEBUG build\r
+ // VERY DANGEROUS practice, because it skips global destructors.\r
+ // But if you know the rules, you can break 'em, right?\r
+ //ExitProcess(0);\r
#endif\r
- }\r
+}\r
\r
const char *PctStr(double x, double y)\r
- {\r
+{\r
if (y == 0)\r
- {\r
+ {\r
if (x == 0)\r
return "100%";\r
else\r
return "inf%";\r
- }\r
+ }\r
static char Str[16];\r
double p = x*100.0/y;\r
sprintf(Str, "%5.1f%%", p);\r
return Str;\r
- }\r
+}\r
\r
string &GetProgressLevelStr(string &s)\r
- {\r
+{\r
unsigned Index = g_ProgressIndex;\r
unsigned Count = g_ProgressCount;\r
if (Count == UINT_MAX)\r
- {\r
+ {\r
if (Index == UINT_MAX)\r
s = "100%";\r
else\r
- {\r
+ {\r
char Tmp[16];\r
sprintf(Tmp, "%u", Index); \r
s = Tmp;\r
- }\r
}\r
+ }\r
else\r
s = string(PctStr(Index+1, Count));\r
s += string(" ") + g_ProgressDesc;\r
return s;\r
- }\r
+}\r
\r
void ProgressStep(unsigned i, unsigned N, const char *Format, ...)\r
- {\r
+{\r
if (opt_quiet)\r
return;\r
-\r
+ \r
if (i == 0)\r
- {\r
+ {\r
string Str;\r
va_list ArgList;\r
va_start(ArgList, Format);\r
g_TimeLastOutputStep = 0;\r
if (g_CurrProgressLineLength > 0)\r
Progress("\n");\r
- }\r
-\r
+ }\r
+ \r
if (i >= N && i != UINT_MAX)\r
Die("ProgressStep(%u,%u)", i, N);\r
bool IsLastStep = (i == UINT_MAX || i + 1 == N);\r
if (!IsLastStep)\r
- {\r
+ {\r
++g_StepCalls;\r
if (g_StepCalls%g_CountsInterval != 0)\r
return;\r
-\r
+ \r
time_t Now = time(0);\r
if (Now == g_TimeLastOutputStep)\r
- {\r
+ {\r
if (g_CountsInterval < 128)\r
g_CountsInterval = (g_CountsInterval*3)/2;\r
else\r
g_CountsInterval += 64;\r
return;\r
- }\r
+ }\r
else\r
- {\r
+ {\r
time_t Secs = Now - g_TimeLastOutputStep;\r
if (Secs > 1)\r
g_CountsInterval = unsigned(g_CountsInterval/(Secs*8));\r
- }\r
-\r
+ }\r
+ \r
if (g_CountsInterval < 1)\r
g_CountsInterval = 1;\r
-\r
+ \r
g_TimeLastOutputStep = Now;\r
- }\r
-\r
+ }\r
+ \r
g_ProgressIndex = i;\r
-\r
+ \r
if (i > 0)\r
- {\r
+ {\r
va_list ArgList;\r
va_start(ArgList, Format);\r
myvstrprintf(g_ProgressDesc, Format, ArgList);\r
- }\r
-\r
+ }\r
+ \r
string LevelStr;\r
GetProgressLevelStr(LevelStr);\r
Progress(" %s\r", LevelStr.c_str());\r
-\r
+ \r
if (IsLastStep)\r
- {\r
+ {\r
g_CountsInterval = 1;\r
fputc('\n', stderr);\r
- }\r
}\r
+}\r
\r
enum OptType\r
- {\r
+{\r
OT_Flag,\r
OT_Tog,\r
OT_Int,\r
OT_Str,\r
OT_Float,\r
OT_Enum\r
- };\r
+};\r
\r
struct OptInfo\r
- {\r
+{\r
void *Value;\r
bool *OptSet;\r
string LongName;\r
double dMin;\r
double dMax;\r
map<string, unsigned> EnumValues;\r
-\r
+ \r
bool bDefault;\r
int iDefault;\r
unsigned uDefault;\r
double dDefault;\r
string strDefault;\r
-\r
+ \r
string Help;\r
-\r
+ \r
bool operator<(const OptInfo &rhs) const\r
- {\r
+ {\r
return LongName < rhs.LongName;\r
- }\r
- };\r
+ }\r
+};\r
\r
static set<OptInfo> g_Opts;\r
\r
void Help()\r
- {\r
+{\r
printf("\n");\r
-\r
+ \r
void Usage();\r
Usage();\r
-\r
+ \r
for (set<OptInfo>::const_iterator p = g_Opts.begin(); p != g_Opts.end(); ++p)\r
- {\r
+ {\r
const OptInfo &Opt = *p;\r
-\r
+ \r
printf("\n");\r
string LongName = Opt.LongName.c_str();\r
if (Opt.Type == OT_Tog)\r
LongName = string("[no]") + LongName;\r
printf(" --%s ", LongName.c_str());\r
-\r
+ \r
switch (Opt.Type)\r
- {\r
- case OT_Flag:\r
- break;\r
- case OT_Tog:\r
- break;\r
- case OT_Int:\r
- printf("<int>");\r
- break;\r
- case OT_Uns:\r
- printf("<uint>");\r
- break;\r
- case OT_Str:\r
- printf("<str>");\r
- break;\r
- case OT_Float:\r
- printf("<float>");\r
- break;\r
- case OT_Enum:\r
- printf("<enum>");\r
- break;\r
- default:\r
- printf("??type");\r
- break;\r
- }\r
-\r
+ {\r
+ case OT_Flag:\r
+ break;\r
+ case OT_Tog:\r
+ break;\r
+ case OT_Int:\r
+ printf("<int>");\r
+ break;\r
+ case OT_Uns:\r
+ printf("<uint>");\r
+ break;\r
+ case OT_Str:\r
+ printf("<str>");\r
+ break;\r
+ case OT_Float:\r
+ printf("<float>");\r
+ break;\r
+ case OT_Enum:\r
+ printf("<enum>");\r
+ break;\r
+ default:\r
+ printf("??type");\r
+ break;\r
+ }\r
+ \r
printf(" ");\r
const string &s = Opt.Help;\r
for (string::const_iterator q = s.begin(); q != s.end(); ++q)\r
- {\r
+ {\r
char c = *q;\r
if (c == '\n')\r
printf("\n ");\r
else\r
printf("%c", c);\r
- }\r
- printf("\n");\r
}\r
+ printf("\n");\r
+ }\r
printf("\n");\r
exit(0);\r
- }\r
+}\r
\r
void CmdLineErr(const char *Format, ...)\r
- {\r
+{\r
va_list ArgList;\r
va_start(ArgList, Format);\r
string Str;\r
fprintf(stderr, "For list of command-line options use --help.\n");\r
fprintf(stderr, "\n");\r
exit(1);\r
- }\r
+}\r
\r
static set<OptInfo>::iterator GetOptInfo(const string &LongName,\r
- bool ErrIfNotFound)\r
- {\r
+ bool ErrIfNotFound)\r
+{\r
for (set<OptInfo>::iterator p = g_Opts.begin();\r
- p != g_Opts.end(); ++p)\r
- {\r
+ p != g_Opts.end(); ++p)\r
+ {\r
const OptInfo &Opt = *p;\r
if (Opt.LongName == LongName)\r
return p;\r
if (Opt.Type == OT_Tog && "no" + Opt.LongName == LongName)\r
return p;\r
- }\r
+ }\r
if (ErrIfNotFound)\r
CmdLineErr("Option --%s is invalid", LongName.c_str());\r
return g_Opts.end();\r
- }\r
+}\r
\r
static void AddOpt(const OptInfo &Opt)\r
- {\r
+{\r
if (GetOptInfo(Opt.LongName, false) != g_Opts.end())\r
Die("Option --%s defined twice", Opt.LongName.c_str());\r
g_Opts.insert(Opt);\r
- }\r
+}\r
\r
-#ifdef _MSC_VER\r
+#if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)\r
+#else\r
#pragma warning(disable: 4505) // unreferenced local function\r
#endif\r
\r
static void DefineFlagOpt(const string &LongName, const string &Help,\r
- void *Value, bool *OptSet)\r
- {\r
+ void *Value, bool *OptSet)\r
+{\r
*(bool *) Value = false;\r
-\r
+ \r
OptInfo Opt;\r
Opt.Value = Value;\r
Opt.OptSet = OptSet;\r
Opt.Help = Help;\r
Opt.Type = OT_Flag;\r
AddOpt(Opt);\r
- }\r
+}\r
\r
static void DefineTogOpt(const string &LongName, bool Default, const string &Help,\r
- void *Value, bool *OptSet)\r
- {\r
+ void *Value, bool *OptSet)\r
+{\r
*(bool *) Value = Default;\r
-\r
+ \r
OptInfo Opt;\r
Opt.Value = Value;\r
Opt.OptSet = OptSet;\r
Opt.Help = Help;\r
Opt.Type = OT_Tog;\r
AddOpt(Opt);\r
- }\r
+}\r
\r
static void DefineIntOpt(const string &LongName, int Default, int Min, int Max,\r
- const string &Help, void *Value, bool *OptSet)\r
- {\r
+ const string &Help, void *Value, bool *OptSet)\r
+{\r
*(int *) Value = Default;\r
-\r
+ \r
OptInfo Opt;\r
Opt.Value = Value;\r
Opt.OptSet = OptSet;\r
Opt.Help = Help;\r
Opt.Type = OT_Int;\r
AddOpt(Opt);\r
- }\r
+}\r
\r
static void DefineUnsOpt(const string &LongName, unsigned Default, unsigned Min,\r
- unsigned Max, const string &Help, void *Value, bool *OptSet)\r
- {\r
+ unsigned Max, const string &Help, void *Value, bool *OptSet)\r
+{\r
*(unsigned *) Value = Default;\r
-\r
+ \r
OptInfo Opt;\r
Opt.Value = Value;\r
Opt.OptSet = OptSet;\r
Opt.Help = Help;\r
Opt.Type = OT_Uns;\r
AddOpt(Opt);\r
- }\r
+}\r
\r
static void DefineFloatOpt(const string &LongName, double Default, double Min,\r
- double Max, const string &Help, void *Value, bool *OptSet)\r
- {\r
+ double Max, const string &Help, void *Value, bool *OptSet)\r
+{\r
*(double *) Value = Default;\r
-\r
+ \r
OptInfo Opt;\r
Opt.Value = Value;\r
Opt.OptSet = OptSet;\r
Opt.Help = Help;\r
Opt.Type = OT_Float;\r
AddOpt(Opt);\r
- }\r
+}\r
\r
static void DefineStrOpt(const string &LongName, const char *Default,\r
- const string &Help, void *Value, bool *OptSet)\r
- {\r
+ const string &Help, void *Value, bool *OptSet)\r
+{\r
*(string *) Value = (Default == 0 ? "" : string(Default));\r
-\r
+ \r
OptInfo Opt;\r
Opt.Value = Value;\r
Opt.OptSet = OptSet;\r
Opt.Help = Help;\r
Opt.Type = OT_Str;\r
AddOpt(Opt);\r
- }\r
+}\r
\r
static void ParseEnumValues(const string &Values, map<string, unsigned> &EnumValues)\r
- {\r
+{\r
EnumValues.clear();\r
\r
string Name;\r
string Value;\r
bool Eq = false;\r
for (string::const_iterator p = Values.begin(); ; ++p)\r
- {\r
+ {\r
char c = (p == Values.end() ? '|' : *p);\r
if (isspace(c))\r
;\r
else if (c == '|')\r
- {\r
+ {\r
if (EnumValues.find(Name) != EnumValues.end())\r
Die("Invalid enum values, '%s' defined twice: '%s'",\r
- Name.c_str(), Values.c_str());\r
+ Name.c_str(), Values.c_str());\r
if (Name.empty() || Value.empty())\r
Die("Invalid enum values, empty name or value: '%s'",\r
- Values.c_str());\r
-\r
+ Values.c_str());\r
+ \r
EnumValues[Name] = atoi(Value.c_str());\r
Name.clear();\r
Value.clear();\r
Eq = false;\r
- }\r
+ }\r
else if (c == '=')\r
Eq = true;\r
else if (Eq)\r
Name.push_back(c);\r
if (p == Values.end())\r
return;\r
- }\r
}\r
+}\r
\r
static void DefineEnumOpt(const string &LongName, const string &ShortName,\r
- int Default, const string &Values, const string &Help, void *Value)\r
- {\r
+ int Default, const string &Values, const string &Help, void *Value)\r
+{\r
*(int *) Value = Default;\r
-\r
+ \r
OptInfo Opt;\r
Opt.Value = Value;\r
Opt.LongName = LongName;\r
Opt.Type = OT_Enum;\r
ParseEnumValues(Values, Opt.EnumValues);\r
AddOpt(Opt);\r
- }\r
+}\r
#undef FLAG_OPT\r
#undef TOG_OPT\r
#undef INT_OPT\r
#include "myopts.h"\r
\r
static int EnumStrToInt(const OptInfo &Opt, const string &Value)\r
- {\r
+{\r
const map<string, unsigned> &e = Opt.EnumValues;\r
string s;\r
for (map<string, unsigned>::const_iterator p = e.begin(); p != e.end(); ++p)\r
- {\r
+ {\r
if (Value == p->first)\r
return p->second;\r
s += " " + p->first;\r
- }\r
+ }\r
CmdLineErr("--%s %s not recognized, valid are: %s",\r
- Opt.LongName.c_str(), Value.c_str(), s.c_str());\r
+ Opt.LongName.c_str(), Value.c_str(), s.c_str());\r
ureturn(-1);\r
- }\r
+}\r
\r
static void SetOpt(OptInfo &Opt, const string &Value)\r
- {\r
+{\r
*Opt.OptSet = true;\r
switch (Opt.Type)\r
+ {\r
+ case OT_Int:\r
{\r
- case OT_Int:\r
- {\r
- *(int *) Opt.Value = atoi(Value.c_str());\r
- break;\r
+ *(int *) Opt.Value = atoi(Value.c_str());\r
+ break;\r
}\r
- case OT_Uns:\r
+ case OT_Uns:\r
{\r
- unsigned uValue = 0;\r
- int n = sscanf(Value.c_str(), "%u", &uValue);\r
- if (n != 1)\r
- CmdLineErr("Invalid value '%s' for --%s",\r
- Value.c_str(), Opt.LongName.c_str());\r
- *(unsigned *) Opt.Value = uValue;\r
- break;\r
+ unsigned uValue = 0;\r
+ int n = sscanf(Value.c_str(), "%u", &uValue);\r
+ if (n != 1)\r
+ CmdLineErr("Invalid value '%s' for --%s",\r
+ Value.c_str(), Opt.LongName.c_str());\r
+ *(unsigned *) Opt.Value = uValue;\r
+ break;\r
}\r
- case OT_Float:\r
+ case OT_Float:\r
{\r
- *(double *) Opt.Value = atof(Value.c_str());\r
- break;\r
+ *(double *) Opt.Value = atof(Value.c_str());\r
+ break;\r
}\r
- case OT_Str:\r
+ case OT_Str:\r
{\r
- *(string *) Opt.Value = Value;\r
- break;\r
+ *(string *) Opt.Value = Value;\r
+ break;\r
}\r
- case OT_Enum:\r
+ case OT_Enum:\r
{\r
- *(int *) Opt.Value = EnumStrToInt(Opt, Value);\r
- break;\r
- }\r
- default:\r
- asserta(false);\r
+ *(int *) Opt.Value = EnumStrToInt(Opt, Value);\r
+ break;\r
}\r
+ default:\r
+ asserta(false);\r
}\r
+}\r
\r
void LogOpts()\r
- {\r
+{\r
for (set<OptInfo>::const_iterator p = g_Opts.begin(); p != g_Opts.end(); ++p)\r
- {\r
+ {\r
const OptInfo &Opt = *p;\r
Log("%s = ", Opt.LongName.c_str());\r
switch (Opt.Type)\r
+ {\r
+ case OT_Flag:\r
+ Log("%s", (*(bool *) Opt.Value) ? "yes" : "no");\r
+ break;\r
+ case OT_Tog:\r
+ Log("%s", (*(bool *) Opt.Value) ? "on" : "off");\r
+ break;\r
+ case OT_Int:\r
+ Log("%d", *(int *) Opt.Value);\r
+ break;\r
+ case OT_Uns:\r
+ Log("%u", *(unsigned *) Opt.Value);\r
+ break;\r
+ case OT_Float:\r
{\r
- case OT_Flag:\r
- Log("%s", (*(bool *) Opt.Value) ? "yes" : "no");\r
- break;\r
- case OT_Tog:\r
- Log("%s", (*(bool *) Opt.Value) ? "on" : "off");\r
- break;\r
- case OT_Int:\r
- Log("%d", *(int *) Opt.Value);\r
- break;\r
- case OT_Uns:\r
- Log("%u", *(unsigned *) Opt.Value);\r
- break;\r
- case OT_Float:\r
- {\r
- double Value = *(double *) Opt.Value;\r
- if (Value == FLT_MAX)\r
- Log("*");\r
- else\r
- Log("%g", Value);\r
- break;\r
- }\r
- case OT_Str:\r
- Log("%s", (*(string *) Opt.Value).c_str());\r
- break;\r
- case OT_Enum:\r
- Log("%d", *(int *) Opt.Value);\r
- break;\r
- default:\r
- asserta(false);\r
+ double Value = *(double *) Opt.Value;\r
+ if (Value == FLT_MAX)\r
+ Log("*");\r
+ else\r
+ Log("%g", Value);\r
+ break;\r
}\r
- Log("\n");\r
+ case OT_Str:\r
+ Log("%s", (*(string *) Opt.Value).c_str());\r
+ break;\r
+ case OT_Enum:\r
+ Log("%d", *(int *) Opt.Value);\r
+ break;\r
+ default:\r
+ asserta(false);\r
}\r
+ Log("\n");\r
}\r
+}\r
\r
static void CompilerInfo()\r
- {\r
+{\r
#ifdef _FILE_OFFSET_BITS\r
printf("_FILE_OFFSET_BITS=%d\n", _FILE_OFFSET_BITS);\r
#else\r
printf("_FILE_OFFSET_BITS not defined\n");\r
#endif\r
-\r
+ \r
#define x(t) printf("sizeof(" #t ") = %d\n", (int) sizeof(t));\r
x(int)\r
x(long)\r
x(off_t)\r
#undef x\r
exit(0);\r
- }\r
+}\r
\r
void Split(const string &Str, vector<string> &Fields, char Sep)\r
- {\r
+{\r
Fields.clear();\r
const unsigned Length = (unsigned) Str.size();\r
string s;\r
for (unsigned i = 0; i < Length; ++i)\r
- {\r
+ {\r
char c = Str[i];\r
if ((Sep == 0 && isspace(c)) || c == Sep)\r
- {\r
+ {\r
if (!s.empty() || Sep != 0)\r
Fields.push_back(s);\r
s.clear();\r
- }\r
+ }\r
else\r
s.push_back(c);\r
- }\r
+ }\r
if (!s.empty())\r
Fields.push_back(s);\r
- }\r
+}\r
\r
static void GetArgsFromFile(const string &FileName, vector<string> &Args)\r
- {\r
+{\r
Args.clear();\r
-\r
+ \r
FILE *f = OpenStdioFile(FileName);\r
string Line;\r
while (ReadLineStdioFile(f, Line))\r
- {\r
+ {\r
size_t n = Line.find('#');\r
if (n != string::npos)\r
Line = Line.substr(0, n);\r
vector<string> Fields;\r
Split(Line, Fields);\r
Args.insert(Args.end(), Fields.begin(), Fields.end());\r
- }\r
- CloseStdioFile(f);\r
}\r
+ CloseStdioFile(f);\r
+}\r
\r
void MyCmdLine(int argc, char **argv)\r
- {\r
+{\r
+ g_Opts.clear(); g_Argv.clear();\r
static unsigned RecurseDepth = 0;\r
++RecurseDepth;\r
-\r
+ \r
DefineFlagOpt("compilerinfo", "Write info about compiler types and #defines to stdout.",\r
- (void *) &opt_compilerinfo, &optset_compilerinfo);\r
+ (void *) &opt_compilerinfo, &optset_compilerinfo);\r
DefineFlagOpt("quiet", "Turn off progress messages.", (void *) &opt_quiet, &optset_quiet);\r
DefineFlagOpt("version", "Show version and exit.", (void *) &opt_version, &optset_version);\r
DefineFlagOpt("logopts", "Log options.", (void *) &opt_logopts, &optset_logopts);\r
DefineFlagOpt("help", "Display command-line options.", (void *) &opt_help, &optset_help);\r
DefineStrOpt("log", "", "Log file name.", (void *) &opt_log, &optset_log);\r
-\r
+ \r
#undef FLAG_OPT\r
#undef TOG_OPT\r
#undef INT_OPT\r
#define STR_OPT(LongName, Default) DefineStrOpt(#LongName, Default, "help", (void *) &opt_##LongName, &optset_##LongName);\r
#define ENUM_OPT(LongName, Values, Default) DefineEnumOpt(#LongName, Values, Default, "help", (void *) &opt_##LongName, &optset_##LongName);\r
#include "myopts.h"\r
-\r
+ \r
if (RecurseDepth == 0)\r
g_Argv.clear();\r
-\r
+ \r
for (int i = 0; i < argc; ++i) \r
g_Argv.push_back(string(argv[i]));\r
\r
-\r
+ \r
int i = 1;\r
for (;;)\r
- {\r
+ {\r
if (i >= argc)\r
break;\r
const string &Arg = g_Argv[i];\r
if (Arg.empty())\r
continue;\r
else if (Arg == "file:" && i + 1 < argc)\r
- {\r
+ {\r
const string &FileName = g_Argv[i+1];\r
vector<string> Args;\r
GetArgsFromFile(FileName, Args);\r
for (vector<string>::const_iterator p = Args.begin();\r
- p != Args.end(); ++p)\r
- {\r
+ p != Args.end(); ++p)\r
+ {\r
g_Argv.push_back(*p);\r
++argc;\r
- }\r
+ }\r
i += 2;\r
continue;\r
- }\r
+ }\r
else if (Arg.size() > 1 && Arg[0] == '-')\r
- {\r
+ {\r
string LongName = (Arg.size() > 2 && Arg[1] == '-' ? Arg.substr(2) : Arg.substr(1));\r
OptInfo Opt = *GetOptInfo(LongName, true);\r
*Opt.OptSet = true;\r
if (Opt.Type == OT_Flag)\r
- {\r
+ {\r
g_Opts.erase(Opt);\r
*(bool *) Opt.Value = true;\r
g_Opts.insert(Opt);\r
++i;\r
continue;\r
- }\r
+ }\r
else if (Opt.Type == OT_Tog)\r
- {\r
+ {\r
g_Opts.erase(Opt);\r
if (string("no") + Opt.LongName == LongName)\r
*(bool *) Opt.Value = false;\r
else\r
- {\r
+ {\r
asserta(Opt.LongName == LongName);\r
*(bool *) Opt.Value = true;\r
- }\r
+ }\r
g_Opts.insert(Opt);\r
++i;\r
continue;\r
- }\r
-\r
+ }\r
+ \r
++i;\r
if (i >= argc)\r
CmdLineErr("Missing value for option --%s", LongName.c_str());\r
-\r
+ \r
string Value = g_Argv[i];\r
SetOpt(Opt, Value);\r
-\r
+ \r
++i;\r
continue;\r
- }\r
+ }\r
else\r
CmdLineErr("Expected -option_name or --option_name, got '%s'", Arg.c_str());\r
- }\r
-\r
+ }\r
+ \r
--RecurseDepth;\r
if (RecurseDepth > 0)\r
return;\r
-\r
+ \r
if (opt_help)\r
Help();\r
-\r
+ \r
if (opt_compilerinfo)\r
CompilerInfo();\r
-\r
+ \r
SetLogFileName(opt_log);\r
-\r
+ \r
if (opt_log != "")\r
- {\r
+ {\r
for (int i = 0; i < argc; ++i)\r
Log("%s%s", i == 0 ? "" : " ", g_Argv[i].c_str());\r
Log("\n");\r
Log("Started %s", s); // there is a newline in s\r
Log("Version " MY_VERSION ".%s\n", SVN_VERSION);\r
Log("\n");\r
- }\r
-\r
+ }\r
+ \r
if (opt_logopts)\r
LogOpts();\r
- }\r
+}\r
\r
double Pct(double x, double y)\r
- {\r
+{\r
if (y == 0.0f)\r
return 0.0f;\r
return (x*100.0f)/y;\r
- }\r
+}\r
\r
void GetCmdLine(string &s)\r
- {\r
+{\r
s.clear();\r
for (unsigned i = 0; i < SIZE(g_Argv); ++i)\r
- {\r
+ {\r
if (i > 0)\r
s += " ";\r
s += g_Argv[i];\r
- }\r
}\r
+}\r
\r
char *mystrsave(const char *s)\r
- {\r
+{\r
unsigned n = unsigned(strlen(s));\r
char *t = myalloc(char, n+1);\r
memcpy(t, s, n+1);\r
return t;\r
- }\r
+}\r
\r
void Logu(unsigned u, unsigned w, unsigned prefixspaces)\r
- {\r
+{\r
for (unsigned i = 0; i < prefixspaces; ++i)\r
Log(" ");\r
if (u == UINT_MAX)\r
Log("%*.*s", w, w, "*");\r
else\r
Log("%*u", w, u);\r
- }\r
+}\r
\r
void Logf(float x, unsigned w, unsigned prefixspaces)\r
- {\r
+{\r
for (unsigned i = 0; i < prefixspaces; ++i)\r
Log(" ");\r
if (x == FLT_MAX)\r
Log("%*.*s", w, w, "*");\r
else\r
Log("%*.2f", w, x);\r
- }\r
+}\r
\r
static uint32 g_SLCG_state = 1;\r
\r
// Simple Linear Congruential Generator\r
// Bad properties; used just to initialize the better generator.\r
static uint32 SLCG_rand()\r
- {\r
+{\r
g_SLCG_state = g_SLCG_state*g_SLCG_a + g_SLCG_c;\r
return g_SLCG_state;\r
- }\r
+}\r
\r
static void SLCG_srand(uint32 Seed)\r
- {\r
+{\r
g_SLCG_state = Seed;\r
for (int i = 0; i < 10; ++i)\r
SLCG_rand();\r
- }\r
+}\r
\r
/***\r
-A multiply-with-carry random number generator, see:\r
-http://en.wikipedia.org/wiki/Multiply-with-carry\r
-\r
-The particular multipliers used here were found on\r
-the web where they are attributed to George Marsaglia.\r
-***/\r
+ A multiply-with-carry random number generator, see:\r
+ http://en.wikipedia.org/wiki/Multiply-with-carry\r
+ \r
+ The particular multipliers used here were found on\r
+ the web where they are attributed to George Marsaglia.\r
+ ***/\r
\r
static bool g_InitRandDone = false;\r
static uint32 g_X[5];\r
\r
uint32 RandInt32()\r
- {\r
+{\r
InitRand();\r
-\r
+ \r
uint64 Sum = 2111111111*(uint64) g_X[3] + 1492*(uint64) g_X[2] +\r
- 1776*(uint64) g_X[1] + 5115*(uint64) g_X[0] + g_X[4];\r
+ 1776*(uint64) g_X[1] + 5115*(uint64) g_X[0] + g_X[4];\r
g_X[3] = g_X[2];\r
g_X[2] = g_X[1];\r
g_X[1] = g_X[0];\r
g_X[4] = (uint32) (Sum >> 32);\r
g_X[0] = (uint32) Sum;\r
return g_X[0];\r
- }\r
+}\r
\r
unsigned randu32()\r
- {\r
+{\r
return (unsigned) RandInt32();\r
- }\r
+}\r
\r
void InitRand()\r
- {\r
+{\r
if (g_InitRandDone)\r
return;\r
-// Do this first to avoid recursion\r
+ // Do this first to avoid recursion\r
g_InitRandDone = true;\r
-\r
+ \r
unsigned Seed = (optset_randseed ? opt_randseed : (unsigned) (time(0)*getpid()));\r
Log("RandSeed=%u\n", Seed);\r
SLCG_srand(Seed);\r
-\r
+ \r
for (unsigned i = 0; i < 5; i++)\r
g_X[i] = SLCG_rand();\r
-\r
+ \r
for (unsigned i = 0; i < 100; i++)\r
RandInt32();\r
- }\r
+}\r
\r
// MUST COME AT END BECAUSE OF #undef\r
#if RCE_MALLOC\r
#undef myfree\r
#undef myfree2\r
void *mymalloc(unsigned bytes, const char *FileName, int Line)\r
- {\r
+{\r
void *rce_malloc(unsigned bytes, const char *FileName, int Line);\r
return rce_malloc(bytes, FileName, Line);\r
- }\r
+}\r
\r
void myfree(void *p, const char *FileName, int Line)\r
- {\r
+{\r
void rce_free(void *p, const char *FileName, int Line);\r
rce_free(p, FileName, Line);\r
- }\r
+}\r
\r
void myfree2(void *p, unsigned bytes, const char *FileName, int Line)\r
- {\r
+{\r
void rce_free(void *p, const char *FileName, int Line);\r
rce_free(p, FileName, Line);\r
- }\r
+}\r
\r
#else // RCE_MALLOC\r
void *mymalloc(unsigned bytes)\r
- {\r
+{\r
++g_NewCalls;\r
if (g_InitialMemUseBytes == 0)\r
g_InitialMemUseBytes = GetMemUseBytes();\r
-\r
+ \r
g_TotalAllocBytes += bytes;\r
g_NetBytes += bytes;\r
if (g_NetBytes > g_MaxNetBytes)\r
- {\r
+ {\r
if (g_NetBytes > g_MaxNetBytes + 10000000)\r
GetMemUseBytes();//to force update of peak\r
g_MaxNetBytes = g_NetBytes;\r
- }\r
+ }\r
void *p = malloc(bytes);\r
//void *p = _malloc_dbg(bytes, _NORMAL_BLOCK, __FILE__, __LINE__);\r
if (0 == p)\r
- {\r
+ {\r
double b = GetMemUseBytes();\r
fprintf(stderr, "\nOut of memory mymalloc(%u), curr %.3g bytes",\r
- (unsigned) bytes, b);\r
+ (unsigned) bytes, b);\r
void LogAllocs();\r
LogAllocs();\r
#if DEBUG && defined(_MSC_VER)\r
asserta(_CrtCheckMemory());\r
#endif\r
Die("Out of memory, mymalloc(%u), curr %.3g bytes\n",\r
- (unsigned) bytes, b);\r
- }\r
- return p;\r
+ (unsigned) bytes, b);\r
}\r
+ return p;\r
+}\r
\r
void myfree(void *p)\r
- {\r
+{\r
if (p == 0)\r
return;\r
free(p);\r
//_free_dbg(p, _NORMAL_BLOCK);\r
- }\r
+}\r
\r
void myfree2(void *p, unsigned bytes)\r
- {\r
+{\r
++g_FreeCalls;\r
g_TotalFreeBytes += bytes;\r
g_NetBytes -= bytes;\r
-\r
+ \r
if (p == 0)\r
return;\r
free(p);\r
- }\r
+}\r
#endif\r