// // Common log file functions. // char LogPath[100]; FILE *hLog; int LogDirty; int LogQuiet; DWORD LogTick; void LogReOpen (void) #ifndef DEBUG #define DEBUG if (0) #endif { if (LogPath[0] != '\0') { hLog = fopen(LogPath, "ab"); if (hLog == NULL) { fprintf(stderr, "Open failed: %s\n", LogPath); exit(1); } LogDirty = 0; LogTick = GetTickCount(); } return; } // // Get next log sequence number. This is found // in the file \seq.txt -- which is created if // not present. // int NextSequence (void) { FILE *f; char *Path = "\\seq.txt"; // Or getenv? windir? registry? long Value; f = fopen(Path, "r"); if (f == NULL) { Value = 1; } else { fscanf(f, "%ld", &Value); fclose(f); } f = fopen(Path, "w"); fprintf(f, "%ld", Value + 1); fclose(f); return Value; } BOOL WINAPI CtrlHandler (DWORD CtrlType); void LogOpen (char *Path) { long LogNumber; if (Path == NULL) { LogNumber = NextSequence(); sprintf(LogPath, "log%d.txt", LogNumber); } else if (strstr(Path, "%d") != NULL) { LogNumber = NextSequence(); sprintf(LogPath, Path, LogNumber); } else if (strstr(Path, "-") != NULL) { // Use stdout only with no file logging LogPath[0] = '\0'; fprintf(stderr, "** Display but no log file\n"); } else { strcpy(LogPath, Path); } if (LogPath[0] != '\0') { fprintf(stderr, "** Opening file %s\n", LogPath); LogReOpen(); } SetConsoleCtrlHandler(CtrlHandler, TRUE); return; } void LogClose (void) { if (hLog != NULL) { fprintf(stderr, "** Closing %s\n", LogPath); fclose(hLog); } return; } // // Close and re-open the log file to guarantee // the data has been flushed to disk. // #define SYNC_SECONDS 15 void LogSync (void) { if (LogDirty) { if (GetTickCount() - LogTick > (SYNC_SECONDS * 1000)) { fclose(hLog); DEBUG printf("[checkpoint]\n"); LogReOpen(); } } return; } void LogWrite (char *Buffer, DWORD Size) { if (Size != 0) { if (LogQuiet == 0) { fwrite(Buffer, Size, 1, stdout); fflush(stdout); } if (hLog != NULL) { if (fwrite(Buffer, Size, 1, hLog) != 1) { fprintf(stderr, "Log file fwrite error - ignoring!\n"); // exit(1); } fflush(hLog); LogDirty = 1; } } LogSync(); return; } // // Return Modified Julian Day (MJD) given // calendar year, month (1-12), and day (1-31). // - Valid for Gregorian dates from 17-Nov-1858. // - Adapted from sci.astro FAQ. // long _DateToMjd (long Year, long Month, long Day) { return 367 * Year - 7 * (Year + (Month + 9) / 12) / 4 - 3 * ((Year + (Month - 9) / 7) / 100 + 1) / 4 + 275 * Month / 9 + Day + 1721028 - 2400000; } // // Return highest resolution timer available in Win32. // double _FineTime (void) { static double freq = 0.0; static LARGE_INTEGER base; LARGE_INTEGER Frequency; LARGE_INTEGER PerformanceCount; double et; if (freq == 0.0) { QueryPerformanceFrequency(&Frequency); freq = (double) Frequency.QuadPart; QueryPerformanceCounter(&base); } QueryPerformanceCounter(&PerformanceCount); et = (double) (PerformanceCount.QuadPart - base.QuadPart); return et / freq; } // // Generate sequence number, MJD, and/or UTC time stamp. // // MJD to Excel date format #define MJD_TO_EXCEL(n) ( (n) - 15018 ) void LogTimeStamp (int type) { static char buf[100]; static long Sequence = 0; char *p; SYSTEMTIME St; GetSystemTime(&St); buf[0] = '\0'; p = buf; // Display line sequence number. if (type & TS_SEQ) { Sequence += 1; p += sprintf(p, "%ld ", Sequence); } // Display Modified Julian Date (and fraction). if (type & (TS_MJD | TS_XL)) { long Mjd, sec; double fMjd; Mjd = _DateToMjd(St.wYear, St.wMonth, St.wDay); sec = (((St.wHour * 60) + St.wMinute) * 60) + St.wSecond; fMjd = Mjd + ((double)sec + (double)St.wMilliseconds * 1e-3) / 86400.0; if (type & TS_XL) { p += sprintf(p, "%.6lf ", MJD_TO_EXCEL(fMjd)); } if (type & TS_MJD) { p += sprintf(p, "%.6lf ", fMjd); } } // Display UTC date and time (and milliseconds). if (type & TS_HMS) { if (type & TS_YMD) { p += sprintf(p, "%.4d-%.2d-%.2d ", St.wYear, St.wMonth, St.wDay); } p += sprintf(p, "%.2d:%.2d:%.2d", St.wHour, St.wMinute, St.wSecond); if (type & TS_MS) { p += sprintf(p, ".%.3ld", St.wMilliseconds); } p += sprintf(p, " "); } // Display precise time interval. if (type & (TS_ET | TS_TI)) { double et; static double prev_et = 0.0; et = _FineTime(); if (type & TS_ET) { // Display elapsed time. p += sprintf(p, "%.6lf ", et); } if (type & TS_TI) { // Display time interval. p += sprintf(p, "%.6lf ", et - prev_et); } prev_et = et; } LogWrite(buf, strlen(buf)); return; } // // Make UTC time stamped comment in log file. // void LogComment (char *s) { char buf[100]; int n; SYSTEMTIME St; GetSystemTime(&St); #define ZULU 'z' n = sprintf(buf, "# %.4d-%.2d-%.2d%c%.2d:%.2d:%.2d.%.3d %s\n", St.wYear, St.wMonth, St.wDay, ZULU, St.wHour, St.wMinute, St.wSecond, St.wMilliseconds, s); LogWrite(buf, n); } #ifndef CTRL_HANDLER // // Flush log file on ctrl-c exit. // BOOL WINAPI CtrlHandler (DWORD CtrlType) { if (CtrlType == CTRL_C_EVENT) { LogClose(); #ifdef COMM_CLOSE CommClose(); #endif exit(0); } return TRUE; } #define CTRL_HANDLER #endif