3 #include <sys/stat.h>
\r
14 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
\r
15 #include <sys/time.h>
\r
16 #include <sys/resource.h>
\r
22 //#include <crtdbg.h>
\r
23 #include <process.h>
\r
24 #include <windows.h>
\r
29 #include "myutils.h"
\r
31 const char *SVN_VERSION =
\r
32 #include "svnversion.h"
\r
35 #define TEST_UTILS 0
\r
37 using namespace std;
\r
39 const unsigned MY_IO_BUFSIZ = 32000;
\r
40 const unsigned MAX_FORMATTED_STRING_LENGTH = 64000;
\r
42 static char *g_IOBuffers[256];
\r
43 static time_t g_StartTime = time(0);
\r
44 static vector<string> g_Argv;
\r
45 static double g_PeakMemUseBytes;
\r
50 const int C = 100000000;
\r
51 for (int i = 0; i < C; ++i)
\r
52 ProgressStep(i, C, "something or other");
\r
55 Progress("Longer message\r");
\r
57 Progress("Short\r");
\r
59 Progress("And longer again\r");
\r
63 const unsigned N = 10;
\r
65 for (unsigned i = 0; i < N; ++i)
\r
67 ProgressStep(i, N, "Allocating 1MB blocks");
\r
68 for (unsigned j = 0; j < M; ++j)
\r
70 ProgressStep(j, M, "Inner loop");
\r
76 #endif // TEST_UTILS
\r
78 static void AllocBuffer(FILE *f)
\r
81 if (fd < 0 || fd >= 256)
\r
83 if (g_IOBuffers[fd] == 0)
\r
84 g_IOBuffers[fd] = myalloc(char, MY_IO_BUFSIZ);
\r
85 setvbuf(f, g_IOBuffers[fd], _IOFBF, MY_IO_BUFSIZ);
\r
88 static void FreeBuffer(FILE *f)
\r
91 if (fd < 0 || fd >= 256)
\r
93 if (g_IOBuffers[fd] == 0)
\r
95 myfree(g_IOBuffers[fd]);
\r
96 g_IOBuffers[fd] = 0;
\r
99 unsigned GetElapsedSecs()
\r
101 return (unsigned) (time(0) - g_StartTime);
\r
104 static unsigned g_NewCalls;
\r
105 static unsigned g_FreeCalls;
\r
106 static double g_InitialMemUseBytes;
\r
107 static double g_TotalAllocBytes;
\r
108 static double g_TotalFreeBytes;
\r
109 static double g_NetBytes;
\r
110 static double g_MaxNetBytes;
\r
112 void LogAllocStats()
\r
115 Log(" Allocs %u\n", g_NewCalls);
\r
116 Log(" Frees %u\n", g_FreeCalls);
\r
117 Log("Initial alloc %s\n", MemBytesToStr(g_InitialMemUseBytes));
\r
118 Log(" Total alloc %s\n", MemBytesToStr(g_TotalAllocBytes));
\r
119 Log(" Total free %s\n", MemBytesToStr(g_TotalFreeBytes));
\r
120 Log(" Net bytes %s\n", MemBytesToStr(g_NetBytes));
\r
121 Log("Max net bytes %s\n", MemBytesToStr(g_MaxNetBytes));
\r
122 Log(" Peak total %s\n", MemBytesToStr(g_MaxNetBytes + g_InitialMemUseBytes));
\r
125 bool StdioFileExists(const string &FileName)
\r
128 int i = stat(FileName.c_str(), &SD);
\r
132 void myassertfail(const char *Exp, const char *File, unsigned Line)
\r
134 Die("%s(%u) assert failed: %s", File, Line, Exp);
\r
137 bool myisatty(int fd)
\r
139 return isatty(fd) != 0;
\r
142 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
\r
144 //#ifdef BIT_VERSION
\r
146 //int fseeko(FILE *stream, off_t offset, int whence)
\r
148 // off_t FilePos = _fseeki64(stream, offset, whence);
\r
149 // return (FilePos == -1L) ? -1 : 0;
\r
151 //#define ftello(fm) (off_t) _ftelli64(fm)
\r
153 int fseeko(FILE *stream, off_t offset, int whence)
\r
155 off_t FilePos = fseek(stream, offset, whence);
\r
156 return (FilePos == -1L) ? -1 : 0;
\r
158 #define ftello(fm) (off_t) ftell(fm)
\r
162 void LogStdioFileState(FILE *f)
\r
164 unsigned long tellpos = (unsigned long) ftello(f);
\r
165 long fseek_pos = fseek(f, 0, SEEK_CUR);
\r
166 int fd = fileno(f);
\r
167 Log("FILE * %p\n", f);
\r
168 Log("fileno %d\n", fd);
\r
169 Log("feof %d\n", feof(f));
\r
170 Log("ferror %d\n", ferror(f));
\r
171 Log("ftell %ld\n", tellpos);
\r
172 Log("fseek %ld\n", fseek_pos);
\r
173 #if !defined(_GNU_SOURCE) && !defined(__APPLE_CC__)
\r
175 int fgetpos_retval = fgetpos(f, &fpos);
\r
176 Log("fpos %ld (retval %d)\n", (long) fpos, fgetpos_retval);
\r
177 // Log("eof %d\n", _eof(fd));
\r
179 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
\r
182 __int64 pos64 = _ftelli64(f);
\r
183 Log("_ftelli64 %lld\n", pos64);
\r
185 __int32 pos32 = ftell(f);
\r
186 Log("ftell %lld\n", pos32);
\r
192 FILE *OpenStdioFile(const string &FileName)
\r
194 const char *Mode = "rb";
\r
195 FILE *f = fopen(FileName.c_str(), Mode);
\r
198 if (errno == EFBIG)
\r
200 if (sizeof(off_t) == 4)
\r
201 Die("File too big, off_t is 32 bits, recompile needed");
\r
203 Die("Cannot open '%s', file too big (off_t=%u bits)",
\r
204 FileName.c_str(), sizeof(off_t)*8);
\r
206 Die("Cannot open %s, errno=%d %s",
\r
207 FileName.c_str(), errno, strerror(errno));
\r
213 FILE *CreateStdioFile(const string &FileName)
\r
215 FILE *f = fopen(FileName.c_str(), "wb+");
\r
217 Die("Cannot create %s, errno=%d %s",
\r
218 FileName.c_str(), errno, strerror(errno));
\r
223 void SetStdioFilePos(FILE *f, off_t Pos)
\r
226 Die("SetStdioFilePos failed, f=NULL");
\r
227 int Ok = fseeko(f, Pos, SEEK_SET);
\r
228 off_t NewPos = ftello(f);
\r
229 if (Ok != 0 || Pos != NewPos)
\r
231 LogStdioFileState(f);
\r
232 Die("SetStdioFilePos(%d) failed, Ok=%d NewPos=%d",
\r
233 (int) Pos, Ok, (int) NewPos);
\r
237 void ReadStdioFile(FILE *f, off_t Pos, void *Buffer, unsigned Bytes)
\r
240 Die("ReadStdioFile failed, f=NULL");
\r
241 SetStdioFilePos(f, Pos);
\r
242 unsigned BytesRead = fread(Buffer, 1, Bytes, f);
\r
243 if (BytesRead != Bytes)
\r
245 LogStdioFileState(f);
\r
246 Die("ReadStdioFile failed, attempted %d bytes, read %d bytes, errno=%d",
\r
247 (int) Bytes, (int) BytesRead, errno);
\r
251 void ReadStdioFile(FILE *f, void *Buffer, unsigned Bytes)
\r
254 Die("ReadStdioFile failed, f=NULL");
\r
255 unsigned BytesRead = fread(Buffer, 1, Bytes, f);
\r
256 if (BytesRead != Bytes)
\r
258 LogStdioFileState(f);
\r
259 Die("ReadStdioFile failed, attempted %d bytes, read %d bytes, errno=%d",
\r
260 (int) Bytes, (int) BytesRead, errno);
\r
264 // Return values from functions like lseek, ftell, fgetpos are
\r
265 // "undefined" for files that cannot seek. Attempt to detect
\r
266 // whether a file can seek by checking for error returns.
\r
267 bool CanSetStdioFilePos(FILE *f)
\r
269 // Common special cases
\r
270 if (f == stdin || f == stdout || f == stderr)
\r
274 int ok1 = fgetpos(f, &CurrPos);
\r
277 int ok2 = fseek(f, 0, SEEK_END);
\r
281 int ok3 = fgetpos(f, &EndPos);
\r
282 int ok4 = fsetpos(f, &CurrPos);
\r
288 byte *ReadAllStdioFile(FILE *f, unsigned &FileSize)
\r
290 const unsigned BUFF_SIZE = 1024*1024;
\r
292 if (CanSetStdioFilePos(f))
\r
294 off_t Pos = GetStdioFilePos(f);
\r
295 off_t FileSize = GetStdioFileSize(f);
\r
296 if (FileSize > UINT_MAX)
\r
297 Die("ReadAllStdioFile: file size > UINT_MAX");
\r
298 SetStdioFilePos(f, 0);
\r
299 byte *Buffer = myalloc(byte, unsigned(FileSize));
\r
300 ReadStdioFile(f, Buffer, unsigned(FileSize));
\r
301 SetStdioFilePos(f, Pos);
\r
302 FileSize = unsigned(FileSize);
\r
306 // Can't seek, read one buffer at a time.
\r
309 // Just to initialize so that first call to realloc works.
\r
310 byte *Buffer = (byte *) malloc(4);
\r
312 Die("ReadAllStdioFile, out of memory");
\r
315 Buffer = (byte *) realloc(Buffer, FileSize + BUFF_SIZE);
\r
316 unsigned BytesRead = fread(Buffer + FileSize, 1, BUFF_SIZE, f);
\r
317 FileSize += BytesRead;
\r
318 if (BytesRead < BUFF_SIZE)
\r
320 Buffer = (byte *) realloc(Buffer, FileSize);
\r
326 byte *ReadAllStdioFile(const std::string &FileName, off_t &FileSize)
\r
329 FILE *f = OpenStdioFile(FileName);
\r
330 FileSize = GetStdioFileSize(f);
\r
333 HANDLE h = CreateFile(FileName.c_str(), GENERIC_READ, FILE_SHARE_READ,
\r
334 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
\r
335 if (h == INVALID_HANDLE_VALUE)
\r
336 Die("ReadAllStdioFile:Open(%s) failed", FileName.c_str());
\r
338 unsigned uFileSize = (unsigned) FileSize;
\r
339 if ((off_t) uFileSize != FileSize)
\r
340 Die("File too big (%.1f Gb): %s", double(FileSize)/1e9, FileName.c_str());
\r
342 byte *Buffer = myalloc(byte, uFileSize);
\r
344 ReadFile(h, Buffer, uFileSize, &BytesRead, NULL);
\r
345 if (FileSize != BytesRead)
\r
346 Die("ReadAllStdioFile:Error reading %s, attempted %u got %u",
\r
347 FileName.c_str(), FileSize, (unsigned) BytesRead);
\r
352 int h = open(FileName.c_str(), O_RDONLY);
\r
354 Die("ReadAllStdioFile:Cannot open %s", FileName.c_str());
\r
355 FileSize = lseek(h, 0, SEEK_END);
\r
356 if (FileSize == (off_t) (-1))
\r
357 Die("ReadAllStdioFile:Error seeking %s", FileName.c_str());
\r
358 // byte *Buffer = myalloc<byte>(FileSize);
\r
359 size_t stBytes = (size_t) FileSize;
\r
360 if ((off_t) stBytes != FileSize)
\r
361 Die("ReadAllStdioFile: off_t overflow");
\r
362 byte *Buffer = (byte *) malloc(stBytes);
\r
364 Die("ReadAllStdioFile: failed to allocate %s", MemBytesToStr(stBytes));
\r
365 lseek(h, 0, SEEK_SET);
\r
366 size_t n = read(h, Buffer, stBytes);
\r
368 Die("ReadAllStdioFile, Error reading %s, attempted %g got %g",
\r
369 FileName.c_str(), (double) FileSize, (double) n);
\r
375 void WriteStdioFile(FILE *f, off_t Pos, const void *Buffer, unsigned Bytes)
\r
378 Die("WriteStdioFile failed, f=NULL");
\r
379 SetStdioFilePos(f, Pos);
\r
380 unsigned BytesWritten = fwrite(Buffer, 1, Bytes, f);
\r
381 if (BytesWritten != Bytes)
\r
383 LogStdioFileState(f);
\r
384 Die("WriteStdioFile failed, attempted %d bytes, wrote %d bytes, errno=%d",
\r
385 (int) Bytes, (int) BytesWritten, errno);
\r
389 void WriteStdioFile(FILE *f, const void *Buffer, unsigned Bytes)
\r
392 Die("WriteStdioFile failed, f=NULL");
\r
393 unsigned BytesWritten = fwrite(Buffer, 1, Bytes, f);
\r
394 if (BytesWritten != Bytes)
\r
396 LogStdioFileState(f);
\r
397 Die("WriteStdioFile failed, attempted %d bytes, wrote %d bytes, errno=%d",
\r
398 (int) Bytes, (int) BytesWritten, errno);
\r
402 // Return false on EOF, true if line successfully read.
\r
403 bool ReadLineStdioFile(FILE *f, char *Line, unsigned Bytes)
\r
407 if ((int) Bytes < 0)
\r
408 Die("ReadLineStdioFile: Bytes < 0");
\r
409 char *RetVal = fgets(Line, (int) Bytes, f);
\r
410 if (NULL == RetVal)
\r
415 Die("ReadLineStdioFile: errno=%d", errno);
\r
416 Die("ReadLineStdioFile: fgets=0, feof=0, ferror=0");
\r
419 if (RetVal != Line)
\r
420 Die("ReadLineStdioFile: fgets != Buffer");
\r
421 unsigned n = strlen(Line);
\r
422 if (n < 1 || Line[n-1] != '\n')
\r
423 Die("ReadLineStdioFile: line too long or missing end-of-line");
\r
424 if (n > 0 && (Line[n-1] == '\r' || Line[n-1] == '\n'))
\r
426 if (n > 1 && (Line[n-2] == '\r' || Line[n-2] == '\n'))
\r
431 // Return false on EOF, true if line successfully read.
\r
432 bool ReadLineStdioFile(FILE *f, string &Line)
\r
446 Die("ReadLineStdioFile, errno=%d", errno);
\r
452 Line.push_back((char) c);
\r
456 // Copies all of fFrom regardless of current
\r
457 // file position, appends to fTo.
\r
458 void AppendStdioFileToFile(FILE *fFrom, FILE *fTo)
\r
460 off_t SavedFromPos = GetStdioFilePos(fFrom);
\r
461 off_t FileSize = GetStdioFileSize(fFrom);
\r
462 const off_t BUFF_SIZE = 1024*1024;
\r
463 char *Buffer = myalloc(char, BUFF_SIZE);
\r
464 SetStdioFilePos(fFrom, 0);
\r
465 off_t BytesRemaining = FileSize;
\r
466 while (BytesRemaining > 0)
\r
468 off_t BytesToRead = BytesRemaining;
\r
469 if (BytesToRead > BUFF_SIZE)
\r
470 BytesToRead = BUFF_SIZE;
\r
471 ReadStdioFile(fFrom, Buffer, (unsigned) BytesToRead);
\r
472 WriteStdioFile(fTo, Buffer, (unsigned) BytesToRead);
\r
473 BytesRemaining -= BytesToRead;
\r
475 SetStdioFilePos(fFrom, SavedFromPos);
\r
478 void RenameStdioFile(const string &FileNameFrom, const string &FileNameTo)
\r
480 int Ok = rename(FileNameFrom.c_str(), FileNameTo.c_str());
\r
482 Die("RenameStdioFile(%s,%s) failed, errno=%d %s",
\r
483 FileNameFrom.c_str(), FileNameTo.c_str(), errno, strerror(errno));
\r
486 void FlushStdioFile(FILE *f)
\r
488 int Ok = fflush(f);
\r
490 Die("fflush(%p)=%d,", f, Ok);
\r
493 void CloseStdioFile(FILE *f)
\r
497 int Ok = fclose(f);
\r
499 Die("fclose(%p)=%d", f, Ok);
\r
503 off_t GetStdioFilePos(FILE *f)
\r
505 off_t FilePos = ftello(f);
\r
507 Die("ftello=%d", (int) FilePos);
\r
511 off_t GetStdioFileSize(FILE *f)
\r
513 off_t CurrentPos = GetStdioFilePos(f);
\r
515 int Ok = fseeko(f, zeroPos, SEEK_END);
\r
517 Die("fseek in GetFileSize");
\r
519 off_t Length = ftello(f);
\r
521 Die("ftello in GetFileSize");
\r
522 SetStdioFilePos(f, CurrentPos);
\r
526 void DeleteStdioFile(const string &FileName)
\r
528 int Ok = remove(FileName.c_str());
\r
530 Die("remove(%s) failed, errno=%d %s", FileName.c_str(), errno, strerror(errno));
\r
533 void myvstrprintf(string &Str, const char *Format, va_list ArgList)
\r
535 static char szStr[MAX_FORMATTED_STRING_LENGTH];
\r
536 vsnprintf(szStr, MAX_FORMATTED_STRING_LENGTH-1, Format, ArgList);
\r
537 szStr[MAX_FORMATTED_STRING_LENGTH - 1] = '\0';
\r
541 void myvstrprintf(string &Str, const char *Format, ...)
\r
544 va_start(ArgList, Format);
\r
545 myvstrprintf(Str, Format, ArgList);
\r
551 void SetLogFileName(const string &FileName)
\r
554 CloseStdioFile(g_fLog);
\r
556 if (FileName.empty())
\r
558 g_fLog = CreateStdioFile(FileName);
\r
561 void Log(const char *Format, ...)
\r
566 static bool InLog = false;
\r
572 va_start(ArgList, Format);
\r
573 vfprintf(g_fLog, Format, ArgList);
\r
579 void Die(const char *Format, ...)
\r
581 static bool InDie = false;
\r
590 va_start(ArgList, Format);
\r
591 myvstrprintf(Msg, Format, ArgList);
\r
594 fprintf(stderr, "\n\n");
\r
596 time_t t = time(0);
\r
597 Log("%s", asctime(localtime(&t)));
\r
598 for (unsigned i = 0; i < g_Argv.size(); i++)
\r
600 fprintf(stderr, (i == 0) ? "%s" : " %s", g_Argv[i].c_str());
\r
601 Log((i == 0) ? "%s" : " %s", g_Argv[i].c_str());
\r
603 fprintf(stderr, "\n");
\r
606 time_t CurrentTime = time(0);
\r
607 unsigned ElapsedSeconds = unsigned(CurrentTime - g_StartTime);
\r
608 const char *sstr = SecsToStr(ElapsedSeconds);
\r
609 Log("Elapsed time: %s\n", sstr);
\r
611 const char *szStr = Msg.c_str();
\r
612 fprintf(stderr, "\n---Fatal error---\n%s\n", szStr);
\r
613 Log("\n---Fatal error---\n%s\n", szStr);
\r
615 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
\r
617 //if (IsDebuggerPresent())
\r
619 //_CrtSetDbgFlag(0);
\r
625 void Warning(const char *Format, ...)
\r
630 va_start(ArgList, Format);
\r
631 myvstrprintf(Msg, Format, ArgList);
\r
634 const char *szStr = Msg.c_str();
\r
636 fprintf(stderr, "\nWARNING: %s\n", szStr);
\r
637 if (g_fLog != stdout)
\r
639 Log("\nWARNING: %s\n", szStr);
\r
644 #if defined linux || __linux__
\r
645 double GetMemUseBytes()
\r
647 static char statm[64];
\r
648 static int PageSize = 1;
\r
651 PageSize = sysconf(_SC_PAGESIZE);
\r
652 pid_t pid = getpid();
\r
653 sprintf(statm, "/proc/%d/statm", (int) pid);
\r
656 int fd = open(statm, O_RDONLY);
\r
660 int n = read(fd, Buffer, sizeof(Buffer) - 1);
\r
668 double Pages = atof(Buffer);
\r
670 double Bytes = Pages*PageSize;
\r
671 if (Bytes > g_PeakMemUseBytes)
\r
672 g_PeakMemUseBytes = Bytes;
\r
675 #elif defined(__APPLE__) || (__MACH__)
\r
676 #include <memory.h>
\r
677 #include <stdlib.h>
\r
679 #include <unistd.h>
\r
680 #include <sys/types.h>
\r
681 #include <sys/sysctl.h>
\r
682 #include <sys/socket.h>
\r
683 #include <sys/gmon.h>
\r
684 #include <mach/vm_param.h>
\r
685 #include <netinet/in.h>
\r
686 #include <netinet/icmp6.h>
\r
687 #include <sys/vmmeter.h>
\r
688 #include <sys/proc.h>
\r
689 #include <mach/task_info.h>
\r
690 #include <mach/task.h>
\r
691 #include <mach/mach_init.h>
\r
692 #include <mach/vm_statistics.h>
\r
694 #define DEFAULT_MEM_USE 100000000.0
\r
696 double GetMemUseBytes()
\r
698 task_t mytask = mach_task_self();
\r
699 struct task_basic_info ti;
\r
700 memset((void *) &ti, 0, sizeof(ti));
\r
701 mach_msg_type_number_t count = TASK_BASIC_INFO_COUNT;
\r
702 kern_return_t ok = task_info(mytask, TASK_BASIC_INFO, (task_info_t) &ti, &count);
\r
703 if (ok == KERN_INVALID_ARGUMENT)
\r
704 return DEFAULT_MEM_USE;
\r
706 if (ok != KERN_SUCCESS)
\r
707 return DEFAULT_MEM_USE;
\r
709 double Bytes = (double ) ti.resident_size;
\r
710 if (Bytes > g_PeakMemUseBytes)
\r
711 g_PeakMemUseBytes = Bytes;
\r
715 double GetMemUseBytes()
\r
721 double GetPeakMemUseBytes()
\r
723 return g_PeakMemUseBytes;
\r
726 const char *SecsToHHMMSS(int Secs)
\r
728 int HH = Secs/3600;
\r
729 int MM = (Secs - HH*3600)/60;
\r
731 static char Str[16];
\r
733 sprintf(Str, "%02d:%02d", MM, SS);
\r
735 sprintf(Str, "%02d:%02d:%02d", HH, MM, SS);
\r
739 const char *SecsToStr(double Secs)
\r
742 return SecsToHHMMSS((int) Secs);
\r
744 static char Str[16];
\r
746 sprintf(Str, "%.2gs", Secs);
\r
747 else if (Secs < 1e-3)
\r
748 sprintf(Str, "%.2fms", Secs*1e3);
\r
750 sprintf(Str, "%.3fs", Secs);
\r
754 const char *MemBytesToStr(double Bytes)
\r
756 static char Str[32];
\r
759 sprintf(Str, "%.1fkb", Bytes/1e3);
\r
760 else if (Bytes < 10e6)
\r
761 sprintf(Str, "%.1fMb", Bytes/1e6);
\r
762 else if (Bytes < 1e9)
\r
763 sprintf(Str, "%.0fMb", Bytes/1e6);
\r
764 else if (Bytes < 10e9)
\r
765 sprintf(Str, "%.1fGb", Bytes/1e9);
\r
766 else if (Bytes < 100e9)
\r
767 sprintf(Str, "%.0fGb", Bytes/1e9);
\r
769 sprintf(Str, "%.3gb", Bytes);
\r
773 const char *IntToStr(unsigned i)
\r
775 static char Str[32];
\r
777 double d = (double) i;
\r
779 sprintf(Str, "%u", i);
\r
781 sprintf(Str, "%.1fk", d/1e3);
\r
783 sprintf(Str, "%.1fM", d/1e6);
\r
785 sprintf(Str, "%.0fM", d/1e6);
\r
787 sprintf(Str, "%.1fG", d/1e9);
\r
788 else if (i < 100e9)
\r
789 sprintf(Str, "%.0fG", d/1e9);
\r
791 sprintf(Str, "%.3g", d);
\r
795 const char *FloatToStr(double d)
\r
797 static char Str[32];
\r
799 double a = fabs(d);
\r
801 sprintf(Str, "%.3g", a);
\r
802 else if (a >= 0.01 && a < 1)
\r
803 sprintf(Str, "%.3f", a);
\r
804 else if (a <= 10 && a >= 1)
\r
807 if (modf(a, &intpart) < 0.05)
\r
808 sprintf(Str, "%.0f", d);
\r
810 sprintf(Str, "%.1f", d);
\r
812 else if (a > 10 && a < 10000)
\r
813 sprintf(Str, "%.0f", d);
\r
815 sprintf(Str, "%.1fk", d/1e3);
\r
817 sprintf(Str, "%.1fM", d/1e6);
\r
819 sprintf(Str, "%.0fM", d/1e6);
\r
821 sprintf(Str, "%.1fG", d/1e9);
\r
822 else if (a < 100e9)
\r
823 sprintf(Str, "%.0fG", d/1e9);
\r
825 sprintf(Str, "%.3g", d);
\r
829 bool opt_quiet = false;
\r
830 bool opt_version = false;
\r
831 bool opt_logopts = false;
\r
832 bool opt_compilerinfo = false;
\r
833 bool opt_help = false;
\r
834 string opt_log = "";
\r
836 bool optset_quiet = false;
\r
837 bool optset_version = false;
\r
838 bool optset_logopts = false;
\r
839 bool optset_compilerinfo = false;
\r
840 bool optset_help = false;
\r
841 bool optset_log = false;
\r
843 static string g_CurrentProgressLine;
\r
844 static string g_ProgressDesc;
\r
845 static unsigned g_ProgressIndex;
\r
846 static unsigned g_ProgressCount;
\r
848 static unsigned g_CurrProgressLineLength;
\r
849 static unsigned g_LastProgressLineLength;
\r
850 static unsigned g_CountsInterval;
\r
851 static unsigned g_StepCalls;
\r
852 static time_t g_TimeLastOutputStep;
\r
854 static string &GetProgressPrefixStr(string &s)
\r
856 double Bytes = GetMemUseBytes();
\r
857 unsigned Secs = GetElapsedSecs();
\r
858 s = string(SecsToHHMMSS(Secs));
\r
863 sprintf(Str, "%5.5s", MemBytesToStr(Bytes));
\r
870 void ProgressLog(const char *Format, ...)
\r
874 va_start(ArgList, Format);
\r
875 myvstrprintf(Str, Format, ArgList);
\r
878 Log("%s", Str.c_str());
\r
879 Progress("%s", Str.c_str());
\r
882 void Progress(const char *Format, ...)
\r
889 va_start(ArgList, Format);
\r
890 myvstrprintf(Str, Format, ArgList);
\r
895 for (unsigned i = 0; i < Str.size(); ++i)
\r
900 else if (c == '\n')
\r
908 for (unsigned i = 0; i < Str.size(); ++i)
\r
910 if (g_CurrProgressLineLength == 0)
\r
913 GetProgressPrefixStr(s);
\r
914 for (unsigned j = 0; j < s.size(); ++j)
\r
916 fputc(s[j], stderr);
\r
917 ++g_CurrProgressLineLength;
\r
922 if (c == '\n' || c == '\r')
\r
924 for (unsigned j = g_CurrProgressLineLength; j < g_LastProgressLineLength; ++j)
\r
925 fputc(' ', stderr);
\r
927 g_LastProgressLineLength = 0;
\r
929 g_LastProgressLineLength = g_CurrProgressLineLength;
\r
930 g_CurrProgressLineLength = 0;
\r
936 ++g_CurrProgressLineLength;
\r
941 void ProgressExit()
\r
943 time_t Now = time(0);
\r
944 struct tm *t = localtime(&Now);
\r
945 const char *s = asctime(t);
\r
946 unsigned Secs = GetElapsedSecs();
\r
949 Log("Finished %s", s); // there is a newline in s
\r
950 Log("Elapsed time %s\n", SecsToHHMMSS((int) Secs));
\r
951 Log("Max memory %s\n", MemBytesToStr(g_PeakMemUseBytes));
\r
953 // Skip exit(), which can be very slow in DEBUG build
\r
954 // VERY DANGEROUS practice, because it skips global destructors.
\r
955 // But if you know the rules, you can break 'em, right?
\r
960 const char *PctStr(double x, double y)
\r
969 static char Str[16];
\r
970 double p = x*100.0/y;
\r
971 sprintf(Str, "%5.1f%%", p);
\r
975 string &GetProgressLevelStr(string &s)
\r
977 unsigned Index = g_ProgressIndex;
\r
978 unsigned Count = g_ProgressCount;
\r
979 if (Count == UINT_MAX)
\r
981 if (Index == UINT_MAX)
\r
986 sprintf(Tmp, "%u", Index);
\r
991 s = string(PctStr(Index+1, Count));
\r
992 s += string(" ") + g_ProgressDesc;
\r
996 void ProgressStep(unsigned i, unsigned N, const char *Format, ...)
\r
1005 va_start(ArgList, Format);
\r
1006 myvstrprintf(Str, Format, ArgList);
\r
1008 g_ProgressDesc = Str;
\r
1009 g_ProgressIndex = 0;
\r
1010 g_ProgressCount = N;
\r
1011 g_CountsInterval = 1;
\r
1013 g_TimeLastOutputStep = 0;
\r
1014 if (g_CurrProgressLineLength > 0)
\r
1018 if (i >= N && i != UINT_MAX)
\r
1019 Die("ProgressStep(%u,%u)", i, N);
\r
1020 bool IsLastStep = (i == UINT_MAX || i + 1 == N);
\r
1024 if (g_StepCalls%g_CountsInterval != 0)
\r
1027 time_t Now = time(0);
\r
1028 if (Now == g_TimeLastOutputStep)
\r
1030 if (g_CountsInterval < 128)
\r
1031 g_CountsInterval = (g_CountsInterval*3)/2;
\r
1033 g_CountsInterval += 64;
\r
1038 time_t Secs = Now - g_TimeLastOutputStep;
\r
1040 g_CountsInterval = unsigned(g_CountsInterval/(Secs*8));
\r
1043 if (g_CountsInterval < 1)
\r
1044 g_CountsInterval = 1;
\r
1046 g_TimeLastOutputStep = Now;
\r
1049 g_ProgressIndex = i;
\r
1054 va_start(ArgList, Format);
\r
1055 myvstrprintf(g_ProgressDesc, Format, ArgList);
\r
1059 GetProgressLevelStr(LevelStr);
\r
1060 Progress(" %s\r", LevelStr.c_str());
\r
1064 g_CountsInterval = 1;
\r
1065 fputc('\n', stderr);
\r
1092 map<string, unsigned> EnumValues;
\r
1096 unsigned uDefault;
\r
1098 string strDefault;
\r
1102 bool operator<(const OptInfo &rhs) const
\r
1104 return LongName < rhs.LongName;
\r
1108 static set<OptInfo> g_Opts;
\r
1117 for (set<OptInfo>::const_iterator p = g_Opts.begin(); p != g_Opts.end(); ++p)
\r
1119 const OptInfo &Opt = *p;
\r
1122 string LongName = Opt.LongName.c_str();
\r
1123 if (Opt.Type == OT_Tog)
\r
1124 LongName = string("[no]") + LongName;
\r
1125 printf(" --%s ", LongName.c_str());
\r
1143 printf("<float>");
\r
1154 const string &s = Opt.Help;
\r
1155 for (string::const_iterator q = s.begin(); q != s.end(); ++q)
\r
1169 void CmdLineErr(const char *Format, ...)
\r
1172 va_start(ArgList, Format);
\r
1174 myvstrprintf(Str, Format, ArgList);
\r
1176 fprintf(stderr, "\n");
\r
1177 fprintf(stderr, "Invalid command line\n");
\r
1178 fprintf(stderr, "%s\n", Str.c_str());
\r
1179 fprintf(stderr, "For list of command-line options use --help.\n");
\r
1180 fprintf(stderr, "\n");
\r
1184 static set<OptInfo>::iterator GetOptInfo(const string &LongName,
\r
1185 bool ErrIfNotFound)
\r
1187 for (set<OptInfo>::iterator p = g_Opts.begin();
\r
1188 p != g_Opts.end(); ++p)
\r
1190 const OptInfo &Opt = *p;
\r
1191 if (Opt.LongName == LongName)
\r
1193 if (Opt.Type == OT_Tog && "no" + Opt.LongName == LongName)
\r
1196 if (ErrIfNotFound)
\r
1197 CmdLineErr("Option --%s is invalid", LongName.c_str());
\r
1198 return g_Opts.end();
\r
1201 static void AddOpt(const OptInfo &Opt)
\r
1203 if (GetOptInfo(Opt.LongName, false) != g_Opts.end())
\r
1204 Die("Option --%s defined twice", Opt.LongName.c_str());
\r
1205 g_Opts.insert(Opt);
\r
1208 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
\r
1210 #pragma warning(disable: 4505) // unreferenced local function
\r
1213 static void DefineFlagOpt(const string &LongName, const string &Help,
\r
1214 void *Value, bool *OptSet)
\r
1216 *(bool *) Value = false;
\r
1219 Opt.Value = Value;
\r
1220 Opt.OptSet = OptSet;
\r
1221 Opt.LongName = LongName;
\r
1222 Opt.bDefault = false;
\r
1224 Opt.Type = OT_Flag;
\r
1228 static void DefineTogOpt(const string &LongName, bool Default, const string &Help,
\r
1229 void *Value, bool *OptSet)
\r
1231 *(bool *) Value = Default;
\r
1234 Opt.Value = Value;
\r
1235 Opt.OptSet = OptSet;
\r
1236 Opt.LongName = LongName;
\r
1237 Opt.bDefault = Default;
\r
1239 Opt.Type = OT_Tog;
\r
1243 static void DefineIntOpt(const string &LongName, int Default, int Min, int Max,
\r
1244 const string &Help, void *Value, bool *OptSet)
\r
1246 *(int *) Value = Default;
\r
1249 Opt.Value = Value;
\r
1250 Opt.OptSet = OptSet;
\r
1251 Opt.LongName = LongName;
\r
1252 Opt.iDefault = Default;
\r
1256 Opt.Type = OT_Int;
\r
1260 static void DefineUnsOpt(const string &LongName, unsigned Default, unsigned Min,
\r
1261 unsigned Max, const string &Help, void *Value, bool *OptSet)
\r
1263 *(unsigned *) Value = Default;
\r
1266 Opt.Value = Value;
\r
1267 Opt.OptSet = OptSet;
\r
1268 Opt.LongName = LongName;
\r
1269 Opt.uDefault = Default;
\r
1273 Opt.Type = OT_Uns;
\r
1277 static void DefineFloatOpt(const string &LongName, double Default, double Min,
\r
1278 double Max, const string &Help, void *Value, bool *OptSet)
\r
1280 *(double *) Value = Default;
\r
1283 Opt.Value = Value;
\r
1284 Opt.OptSet = OptSet;
\r
1285 Opt.LongName = LongName;
\r
1286 Opt.dDefault = Default;
\r
1290 Opt.Type = OT_Float;
\r
1294 static void DefineStrOpt(const string &LongName, const char *Default,
\r
1295 const string &Help, void *Value, bool *OptSet)
\r
1297 *(string *) Value = (Default == 0 ? "" : string(Default));
\r
1300 Opt.Value = Value;
\r
1301 Opt.OptSet = OptSet;
\r
1302 Opt.LongName = LongName;
\r
1303 Opt.strDefault = (Default == 0 ? "" : string(Default));
\r
1305 Opt.Type = OT_Str;
\r
1309 static void ParseEnumValues(const string &Values, map<string, unsigned> &EnumValues)
\r
1311 EnumValues.clear();
\r
1316 for (string::const_iterator p = Values.begin(); ; ++p)
\r
1318 char c = (p == Values.end() ? '|' : *p);
\r
1321 else if (c == '|')
\r
1323 if (EnumValues.find(Name) != EnumValues.end())
\r
1324 Die("Invalid enum values, '%s' defined twice: '%s'",
\r
1325 Name.c_str(), Values.c_str());
\r
1326 if (Name.empty() || Value.empty())
\r
1327 Die("Invalid enum values, empty name or value: '%s'",
\r
1330 EnumValues[Name] = atoi(Value.c_str());
\r
1335 else if (c == '=')
\r
1338 Value.push_back(c);
\r
1340 Name.push_back(c);
\r
1341 if (p == Values.end())
\r
1346 static void DefineEnumOpt(const string &LongName, const string &ShortName,
\r
1347 int Default, const string &Values, const string &Help, void *Value)
\r
1349 *(int *) Value = Default;
\r
1352 Opt.Value = Value;
\r
1353 Opt.LongName = LongName;
\r
1354 Opt.iDefault = Default;
\r
1356 Opt.Type = OT_Enum;
\r
1357 ParseEnumValues(Values, Opt.EnumValues);
\r
1367 #define FLAG_OPT(LongName) bool opt_##LongName; bool optset_##LongName;
\r
1368 #define TOG_OPT(LongName, Default) bool opt_##LongName; bool optset_##LongName;
\r
1369 #define INT_OPT(LongName, Default, Min, Max) int opt_##LongName; bool optset_##LongName;
\r
1370 #define UNS_OPT(LongName, Default, Min, Max) unsigned opt_##LongName; bool optset_##LongName;
\r
1371 #define FLT_OPT(LongName, Default, Min, Max) double opt_##LongName; bool optset_##LongName;
\r
1372 #define STR_OPT(LongName, Default) string opt_##LongName; bool optset_##LongName;
\r
1373 #define ENUM_OPT(LongName, Values, Default) int opt_##LongName; bool optset_##LongName;
\r
1374 #include "myopts.h"
\r
1376 static int EnumStrToInt(const OptInfo &Opt, const string &Value)
\r
1378 const map<string, unsigned> &e = Opt.EnumValues;
\r
1380 for (map<string, unsigned>::const_iterator p = e.begin(); p != e.end(); ++p)
\r
1382 if (Value == p->first)
\r
1384 s += " " + p->first;
\r
1386 CmdLineErr("--%s %s not recognized, valid are: %s",
\r
1387 Opt.LongName.c_str(), Value.c_str(), s.c_str());
\r
1391 static void SetOpt(OptInfo &Opt, const string &Value)
\r
1393 *Opt.OptSet = true;
\r
1398 *(int *) Opt.Value = atoi(Value.c_str());
\r
1403 unsigned uValue = 0;
\r
1404 int n = sscanf(Value.c_str(), "%u", &uValue);
\r
1406 CmdLineErr("Invalid value '%s' for --%s",
\r
1407 Value.c_str(), Opt.LongName.c_str());
\r
1408 *(unsigned *) Opt.Value = uValue;
\r
1413 *(double *) Opt.Value = atof(Value.c_str());
\r
1418 *(string *) Opt.Value = Value;
\r
1423 *(int *) Opt.Value = EnumStrToInt(Opt, Value);
\r
1433 for (set<OptInfo>::const_iterator p = g_Opts.begin(); p != g_Opts.end(); ++p)
\r
1435 const OptInfo &Opt = *p;
\r
1436 Log("%s = ", Opt.LongName.c_str());
\r
1440 Log("%s", (*(bool *) Opt.Value) ? "yes" : "no");
\r
1443 Log("%s", (*(bool *) Opt.Value) ? "on" : "off");
\r
1446 Log("%d", *(int *) Opt.Value);
\r
1449 Log("%u", *(unsigned *) Opt.Value);
\r
1453 double Value = *(double *) Opt.Value;
\r
1454 if (Value == FLT_MAX)
\r
1461 Log("%s", (*(string *) Opt.Value).c_str());
\r
1464 Log("%d", *(int *) Opt.Value);
\r
1473 static void CompilerInfo()
\r
1475 #ifdef _FILE_OFFSET_BITS
\r
1476 printf("_FILE_OFFSET_BITS=%d\n", _FILE_OFFSET_BITS);
\r
1478 printf("_FILE_OFFSET_BITS not defined\n");
\r
1481 #define x(t) printf("sizeof(" #t ") = %d\n", (int) sizeof(t));
\r
1492 void Split(const string &Str, vector<string> &Fields, char Sep)
\r
1495 const unsigned Length = (unsigned) Str.size();
\r
1497 for (unsigned i = 0; i < Length; ++i)
\r
1500 if ((Sep == 0 && isspace(c)) || c == Sep)
\r
1502 if (!s.empty() || Sep != 0)
\r
1503 Fields.push_back(s);
\r
1510 Fields.push_back(s);
\r
1513 static void GetArgsFromFile(const string &FileName, vector<string> &Args)
\r
1517 FILE *f = OpenStdioFile(FileName);
\r
1519 while (ReadLineStdioFile(f, Line))
\r
1521 size_t n = Line.find('#');
\r
1522 if (n != string::npos)
\r
1523 Line = Line.substr(0, n);
\r
1524 vector<string> Fields;
\r
1525 Split(Line, Fields);
\r
1526 Args.insert(Args.end(), Fields.begin(), Fields.end());
\r
1528 CloseStdioFile(f);
\r
1531 void MyCmdLine(int argc, char **argv)
\r
1533 g_Opts.clear(); g_Argv.clear();
\r
1534 static unsigned RecurseDepth = 0;
\r
1537 DefineFlagOpt("compilerinfo", "Write info about compiler types and #defines to stdout.",
\r
1538 (void *) &opt_compilerinfo, &optset_compilerinfo);
\r
1539 DefineFlagOpt("quiet", "Turn off progress messages.", (void *) &opt_quiet, &optset_quiet);
\r
1540 DefineFlagOpt("version", "Show version and exit.", (void *) &opt_version, &optset_version);
\r
1541 DefineFlagOpt("logopts", "Log options.", (void *) &opt_logopts, &optset_logopts);
\r
1542 DefineFlagOpt("help", "Display command-line options.", (void *) &opt_help, &optset_help);
\r
1543 DefineStrOpt("log", "", "Log file name.", (void *) &opt_log, &optset_log);
\r
1552 #define FLAG_OPT(LongName) DefineFlagOpt(#LongName, "help", (void *) &opt_##LongName, &optset_##LongName);
\r
1553 #define TOG_OPT(LongName, Default) DefineTogOpt(#LongName, Default, "help", (void *) &opt_##LongName, &optset_##LongName);
\r
1554 #define INT_OPT(LongName, Default, Min, Max) DefineIntOpt(#LongName, Default, Min, Max, "help", (void *) &opt_##LongName, &optset_##LongName);
\r
1555 #define UNS_OPT(LongName, Default, Min, Max) DefineUnsOpt(#LongName, Default, Min, Max, "help", (void *) &opt_##LongName, &optset_##LongName);
\r
1556 #define FLT_OPT(LongName, Default, Min, Max) DefineFloatOpt(#LongName, Default, Min, Max, "help", (void *) &opt_##LongName, &optset_##LongName);
\r
1557 #define STR_OPT(LongName, Default) DefineStrOpt(#LongName, Default, "help", (void *) &opt_##LongName, &optset_##LongName);
\r
1558 #define ENUM_OPT(LongName, Values, Default) DefineEnumOpt(#LongName, Values, Default, "help", (void *) &opt_##LongName, &optset_##LongName);
\r
1559 #include "myopts.h"
\r
1561 if (RecurseDepth == 0)
\r
1564 for (int i = 0; i < argc; ++i)
\r
1565 g_Argv.push_back(string(argv[i]));
\r
1573 const string &Arg = g_Argv[i];
\r
1577 else if (Arg == "file:" && i + 1 < argc)
\r
1579 const string &FileName = g_Argv[i+1];
\r
1580 vector<string> Args;
\r
1581 GetArgsFromFile(FileName, Args);
\r
1582 for (vector<string>::const_iterator p = Args.begin();
\r
1583 p != Args.end(); ++p)
\r
1585 g_Argv.push_back(*p);
\r
1591 else if (Arg.size() > 1 && Arg[0] == '-')
\r
1593 string LongName = (Arg.size() > 2 && Arg[1] == '-' ? Arg.substr(2) : Arg.substr(1));
\r
1594 OptInfo Opt = *GetOptInfo(LongName, true);
\r
1595 *Opt.OptSet = true;
\r
1596 if (Opt.Type == OT_Flag)
\r
1598 g_Opts.erase(Opt);
\r
1599 *(bool *) Opt.Value = true;
\r
1600 g_Opts.insert(Opt);
\r
1604 else if (Opt.Type == OT_Tog)
\r
1606 g_Opts.erase(Opt);
\r
1607 if (string("no") + Opt.LongName == LongName)
\r
1608 *(bool *) Opt.Value = false;
\r
1611 asserta(Opt.LongName == LongName);
\r
1612 *(bool *) Opt.Value = true;
\r
1614 g_Opts.insert(Opt);
\r
1621 CmdLineErr("Missing value for option --%s", LongName.c_str());
\r
1623 string Value = g_Argv[i];
\r
1624 SetOpt(Opt, Value);
\r
1630 CmdLineErr("Expected -option_name or --option_name, got '%s'", Arg.c_str());
\r
1634 if (RecurseDepth > 0)
\r
1640 if (opt_compilerinfo)
\r
1643 SetLogFileName(opt_log);
\r
1645 if (opt_log != "")
\r
1647 for (int i = 0; i < argc; ++i)
\r
1648 Log("%s%s", i == 0 ? "" : " ", g_Argv[i].c_str());
\r
1650 time_t Now = time(0);
\r
1651 struct tm *t = localtime(&Now);
\r
1652 const char *s = asctime(t);
\r
1653 Log("Started %s", s); // there is a newline in s
\r
1654 Log("Version " MY_VERSION ".%s\n", SVN_VERSION);
\r
1662 double Pct(double x, double y)
\r
1666 return (x*100.0f)/y;
\r
1669 void GetCmdLine(string &s)
\r
1672 for (unsigned i = 0; i < SIZE(g_Argv); ++i)
\r
1680 char *mystrsave(const char *s)
\r
1682 unsigned n = unsigned(strlen(s));
\r
1683 char *t = myalloc(char, n+1);
\r
1684 memcpy(t, s, n+1);
\r
1688 void Logu(unsigned u, unsigned w, unsigned prefixspaces)
\r
1690 for (unsigned i = 0; i < prefixspaces; ++i)
\r
1692 if (u == UINT_MAX)
\r
1693 Log("%*.*s", w, w, "*");
\r
1698 void Logf(float x, unsigned w, unsigned prefixspaces)
\r
1700 for (unsigned i = 0; i < prefixspaces; ++i)
\r
1703 Log("%*.*s", w, w, "*");
\r
1705 Log("%*.2f", w, x);
\r
1708 static uint32 g_SLCG_state = 1;
\r
1710 // Numerical values used by Microsoft C, according to wikipedia:
\r
1711 // http://en.wikipedia.org/wiki/Linear_congruential_generator
\r
1712 static uint32 g_SLCG_a = 214013;
\r
1713 static uint32 g_SLCG_c = 2531011;
\r
1715 // Simple Linear Congruential Generator
\r
1716 // Bad properties; used just to initialize the better generator.
\r
1717 static uint32 SLCG_rand()
\r
1719 g_SLCG_state = g_SLCG_state*g_SLCG_a + g_SLCG_c;
\r
1720 return g_SLCG_state;
\r
1723 static void SLCG_srand(uint32 Seed)
\r
1725 g_SLCG_state = Seed;
\r
1726 for (int i = 0; i < 10; ++i)
\r
1731 A multiply-with-carry random number generator, see:
\r
1732 http://en.wikipedia.org/wiki/Multiply-with-carry
\r
1734 The particular multipliers used here were found on
\r
1735 the web where they are attributed to George Marsaglia.
\r
1738 static bool g_InitRandDone = false;
\r
1739 static uint32 g_X[5];
\r
1741 uint32 RandInt32()
\r
1745 uint64 Sum = 2111111111*(uint64) g_X[3] + 1492*(uint64) g_X[2] +
\r
1746 1776*(uint64) g_X[1] + 5115*(uint64) g_X[0] + g_X[4];
\r
1750 g_X[4] = (uint32) (Sum >> 32);
\r
1751 g_X[0] = (uint32) Sum;
\r
1755 unsigned randu32()
\r
1757 return (unsigned) RandInt32();
\r
1762 if (g_InitRandDone)
\r
1764 // Do this first to avoid recursion
\r
1765 g_InitRandDone = true;
\r
1767 unsigned Seed = (optset_randseed ? opt_randseed : (unsigned) (time(0)*getpid()));
\r
1768 Log("RandSeed=%u\n", Seed);
\r
1771 for (unsigned i = 0; i < 5; i++)
\r
1772 g_X[i] = SLCG_rand();
\r
1774 for (unsigned i = 0; i < 100; i++)
\r
1778 // MUST COME AT END BECAUSE OF #undef
\r
1783 void *mymalloc(unsigned bytes, const char *FileName, int Line)
\r
1785 void *rce_malloc(unsigned bytes, const char *FileName, int Line);
\r
1786 return rce_malloc(bytes, FileName, Line);
\r
1789 void myfree(void *p, const char *FileName, int Line)
\r
1791 void rce_free(void *p, const char *FileName, int Line);
\r
1792 rce_free(p, FileName, Line);
\r
1795 void myfree2(void *p, unsigned bytes, const char *FileName, int Line)
\r
1797 void rce_free(void *p, const char *FileName, int Line);
\r
1798 rce_free(p, FileName, Line);
\r
1801 #else // RCE_MALLOC
\r
1802 void *mymalloc(unsigned bytes)
\r
1805 if (g_InitialMemUseBytes == 0)
\r
1806 g_InitialMemUseBytes = GetMemUseBytes();
\r
1808 g_TotalAllocBytes += bytes;
\r
1809 g_NetBytes += bytes;
\r
1810 if (g_NetBytes > g_MaxNetBytes)
\r
1812 if (g_NetBytes > g_MaxNetBytes + 10000000)
\r
1813 GetMemUseBytes();//to force update of peak
\r
1814 g_MaxNetBytes = g_NetBytes;
\r
1816 void *p = malloc(bytes);
\r
1817 //void *p = _malloc_dbg(bytes, _NORMAL_BLOCK, __FILE__, __LINE__);
\r
1820 double b = GetMemUseBytes();
\r
1821 fprintf(stderr, "\nOut of memory mymalloc(%u), curr %.3g bytes",
\r
1822 (unsigned) bytes, b);
\r
1825 #if DEBUG && defined(_MSC_VER)
\r
1826 asserta(_CrtCheckMemory());
\r
1828 Die("Out of memory, mymalloc(%u), curr %.3g bytes\n",
\r
1829 (unsigned) bytes, b);
\r
1834 void myfree(void *p)
\r
1839 //_free_dbg(p, _NORMAL_BLOCK);
\r
1842 void myfree2(void *p, unsigned bytes)
\r
1845 g_TotalFreeBytes += bytes;
\r
1846 g_NetBytes -= bytes;
\r