SystemInformation.cxx 148 KB
Newer Older
Kitware Robot's avatar
Kitware Robot committed
1
2
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing#kwsys for details.  */
Kitware Robot's avatar
Kitware Robot committed
3
#if defined(_WIN32)
Kitware Robot's avatar
Kitware Robot committed
4
5
6
7
8
#define NOMINMAX // use our min,max
#if !defined(_WIN32_WINNT) && !(defined(_MSC_VER) && _MSC_VER < 1300)
#define _WIN32_WINNT 0x0501
#endif
#include <winsock.h> // WSADATA, include before sys/types.h
Kitware Robot's avatar
Kitware Robot committed
9
10
#endif

Kitware Robot's avatar
Kitware Robot committed
11
#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
Kitware Robot's avatar
Kitware Robot committed
12
#define _GNU_SOURCE
Kitware Robot's avatar
Kitware Robot committed
13
14
#endif

Kitware Robot's avatar
Kitware Robot committed
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// TODO:
// We need an alternative implementation for many functions in this file
// when USE_ASM_INSTRUCTIONS gets defined as 0.
//
// Consider using these on Win32/Win64 for some of them:
//
// IsProcessorFeaturePresent
// http://msdn.microsoft.com/en-us/library/ms724482(VS.85).aspx
//
// GetProcessMemoryInfo
// http://msdn.microsoft.com/en-us/library/ms683219(VS.85).aspx

#include "kwsysPrivate.h"
#include KWSYS_HEADER(SystemInformation.hxx)
#include KWSYS_HEADER(Process.h)

// Work-around CMake dependency scanning limitation.  This must
// duplicate the above list of headers.
#if 0
Kitware Robot's avatar
Kitware Robot committed
34
35
#include "Process.h.in"
#include "SystemInformation.hxx.in"
Kitware Robot's avatar
Kitware Robot committed
36
37
#endif

Kitware Robot's avatar
Kitware Robot committed
38
39
40
#include <algorithm>
#include <bitset>
#include <cassert>
Kitware Robot's avatar
Kitware Robot committed
41
#include <fstream>
Kitware Robot's avatar
Kitware Robot committed
42
#include <iostream>
Kitware Robot's avatar
Kitware Robot committed
43
44
#include <limits>
#include <set>
Kitware Robot's avatar
Kitware Robot committed
45
46
47
48
#include <sstream>
#include <string>
#include <vector>

Kitware Robot's avatar
Kitware Robot committed
49
#if defined(_WIN32)
Kitware Robot's avatar
Kitware Robot committed
50
51
52
53
54
55
56
57
58
#include <windows.h>
#if defined(_MSC_VER) && _MSC_VER >= 1800
#define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
#endif
#include <errno.h>
#if defined(KWSYS_SYS_HAS_PSAPI)
#include <psapi.h>
#endif
#if !defined(siginfo_t)
Kitware Robot's avatar
Kitware Robot committed
59
typedef int siginfo_t;
Kitware Robot's avatar
Kitware Robot committed
60
#endif
Kitware Robot's avatar
Kitware Robot committed
61
#else
Kitware Robot's avatar
Kitware Robot committed
62
63
64
65
66
67
68
69
70
#include <sys/types.h>

#include <errno.h> // extern int errno;
#include <fcntl.h>
#include <signal.h>
#include <sys/resource.h> // getrlimit
#include <sys/time.h>
#include <sys/utsname.h> // int uname(struct utsname *buf);
#include <unistd.h>
Kitware Robot's avatar
Kitware Robot committed
71
72
#endif

Kitware Robot's avatar
Kitware Robot committed
73
74
75
#if defined(__CYGWIN__) && !defined(_WIN32)
#include <windows.h>
#undef _WIN32
Kitware Robot's avatar
Kitware Robot committed
76
77
#endif

Kitware Robot's avatar
Kitware Robot committed
78
79
80
81
82
83
84
85
86
#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) ||    \
  defined(__DragonFly__)
#include <netdb.h>
#include <netinet/in.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#if defined(KWSYS_SYS_HAS_IFADDRS_H)
#include <ifaddrs.h>
Kitware Robot's avatar
Kitware Robot committed
87
#include <net/if.h>
Kitware Robot's avatar
Kitware Robot committed
88
89
#define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
#endif
Kitware Robot's avatar
Kitware Robot committed
90
91
#endif

Kitware Robot's avatar
Kitware Robot committed
92
#if defined(KWSYS_SYS_HAS_MACHINE_CPU_H)
Kitware Robot's avatar
Kitware Robot committed
93
#include <machine/cpu.h>
Kitware Robot's avatar
Kitware Robot committed
94
95
#endif

Kitware Robot's avatar
Kitware Robot committed
96
#ifdef __APPLE__
Kitware Robot's avatar
Kitware Robot committed
97
98
99
100
101
102
103
104
105
106
#include <mach/host_info.h>
#include <mach/mach.h>
#include <mach/mach_types.h>
#include <mach/vm_statistics.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#if defined(KWSYS_SYS_HAS_IFADDRS_H)
#include <ifaddrs.h>
Kitware Robot's avatar
Kitware Robot committed
107
#include <net/if.h>
Kitware Robot's avatar
Kitware Robot committed
108
109
110
111
112
113
114
115
116
117
118
119
120
#define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
#endif
#if !(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ - 0 >= 1050)
#undef KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE
#endif
#endif

#if defined(__linux) || defined(__sun) || defined(_SCO_DS)
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#if defined(KWSYS_SYS_HAS_IFADDRS_H)
#include <ifaddrs.h>
Kitware Robot's avatar
Kitware Robot committed
121
#include <net/if.h>
Kitware Robot's avatar
Kitware Robot committed
122
123
124
125
126
#if defined(__LSB_VERSION__)
/* LSB has no getifaddrs */
#elif defined(__ANDROID_API__) && __ANDROID_API__ < 24
/* Android has no getifaddrs prior to API 24.  */
#else
Kitware Robot's avatar
Kitware Robot committed
127
128
129
130
#define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
#endif
#endif
#if defined(KWSYS_CXX_HAS_RLIMIT64)
Kitware Robot's avatar
Kitware Robot committed
131
typedef struct rlimit64 ResourceLimitType;
Kitware Robot's avatar
Kitware Robot committed
132
133
#define GetResourceLimit getrlimit64
#else
Kitware Robot's avatar
Kitware Robot committed
134
typedef struct rlimit ResourceLimitType;
Kitware Robot's avatar
Kitware Robot committed
135
136
137
138
139
140
141
142
#define GetResourceLimit getrlimit
#endif
#elif defined(__hpux)
#include <sys/param.h>
#include <sys/pstat.h>
#if defined(KWSYS_SYS_HAS_MPCTL_H)
#include <sys/mpctl.h>
#endif
Kitware Robot's avatar
Kitware Robot committed
143
144
145
#endif

#ifdef __HAIKU__
Kitware Robot's avatar
Kitware Robot committed
146
#include <OS.h>
Kitware Robot's avatar
Kitware Robot committed
147
148
#endif

Kitware Robot's avatar
Kitware Robot committed
149
#if defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
Kitware Robot's avatar
Kitware Robot committed
150
151
152
153
154
155
156
#include <execinfo.h>
#if defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE)
#include <cxxabi.h>
#endif
#if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
#include <dlfcn.h>
#endif
Kitware Robot's avatar
Kitware Robot committed
157
#else
Kitware Robot's avatar
Kitware Robot committed
158
159
#undef KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE
#undef KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP
Kitware Robot's avatar
Kitware Robot committed
160
161
#endif

Kitware Robot's avatar
Kitware Robot committed
162
#include <ctype.h> // int isdigit(int c);
Kitware Robot's avatar
Kitware Robot committed
163
164
#include <memory.h>
#include <stdio.h>
Kitware Robot's avatar
Kitware Robot committed
165
#include <stdlib.h>
Kitware Robot's avatar
Kitware Robot committed
166
167
#include <string.h>

Kitware Robot's avatar
Kitware Robot committed
168
#if defined(KWSYS_USE_LONG_LONG)
Kitware Robot's avatar
Kitware Robot committed
169
170
171
172
173
#if defined(KWSYS_IOS_HAS_OSTREAM_LONG_LONG)
#define iostreamLongLong(x) (x)
#else
#define iostreamLongLong(x) ((long)(x))
#endif
Kitware Robot's avatar
Kitware Robot committed
174
#elif defined(KWSYS_USE___INT64)
Kitware Robot's avatar
Kitware Robot committed
175
176
177
178
179
#if defined(KWSYS_IOS_HAS_OSTREAM___INT64)
#define iostreamLongLong(x) (x)
#else
#define iostreamLongLong(x) ((long)(x))
#endif
Kitware Robot's avatar
Kitware Robot committed
180
#else
Kitware Robot's avatar
Kitware Robot committed
181
#error "No Long Long"
Kitware Robot's avatar
Kitware Robot committed
182
183
184
#endif

#if defined(KWSYS_CXX_HAS_ATOLL)
Kitware Robot's avatar
Kitware Robot committed
185
#define atoLongLong atoll
Kitware Robot's avatar
Kitware Robot committed
186
#else
Kitware Robot's avatar
Kitware Robot committed
187
188
189
190
191
192
193
#if defined(KWSYS_CXX_HAS__ATOI64)
#define atoLongLong _atoi64
#elif defined(KWSYS_CXX_HAS_ATOL)
#define atoLongLong atol
#else
#define atoLongLong atoi
#endif
Kitware Robot's avatar
Kitware Robot committed
194
195
#endif

Kitware Robot's avatar
Kitware Robot committed
196
197
#if defined(_MSC_VER) && (_MSC_VER >= 1300) && !defined(_WIN64) &&            \
  !defined(__clang__)
Kitware Robot's avatar
Kitware Robot committed
198
199
200
201
202
#define USE_ASM_INSTRUCTIONS 1
#else
#define USE_ASM_INSTRUCTIONS 0
#endif

Kitware Robot's avatar
Kitware Robot committed
203
#if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__clang__)
Kitware Robot's avatar
Kitware Robot committed
204
205
206
207
208
209
#include <intrin.h>
#define USE_CPUID_INTRINSICS 1
#else
#define USE_CPUID_INTRINSICS 0
#endif

Kitware Robot's avatar
Kitware Robot committed
210
211
212
#if USE_ASM_INSTRUCTIONS || USE_CPUID_INTRINSICS ||                           \
  defined(KWSYS_CXX_HAS_BORLAND_ASM_CPUID)
#define USE_CPUID 1
Kitware Robot's avatar
Kitware Robot committed
213
#else
Kitware Robot's avatar
Kitware Robot committed
214
#define USE_CPUID 0
Kitware Robot's avatar
Kitware Robot committed
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
#endif

#if USE_CPUID

#define CPUID_AWARE_COMPILER

/**
 * call CPUID instruction
 *
 * Will return false if the instruction failed.
 */
static bool call_cpuid(int select, int result[4])
{
#if USE_CPUID_INTRINSICS
  __cpuid(result, select);
  return true;
#else
  int tmp[4];
Kitware Robot's avatar
Kitware Robot committed
233
#if defined(_MSC_VER)
Kitware Robot's avatar
Kitware Robot committed
234
235
236
237
238
  // Use SEH to determine CPUID presence
  __try {
    _asm {
#ifdef CPUID_AWARE_COMPILER
      ; we must push/pop the registers <<CPUID>> writes to, as the
Kitware Robot's avatar
Kitware Robot committed
239
      ; optimiser does not know about <<CPUID>>, and so does not expect
Kitware Robot's avatar
Kitware Robot committed
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
      ; these registers to change.
      push eax
      push ebx
      push ecx
      push edx
#endif
      ; <<CPUID>>
      mov eax, select
#ifdef CPUID_AWARE_COMPILER
      cpuid
#else
      _asm _emit 0x0f
      _asm _emit 0xa2
#endif
      mov tmp[0 * TYPE int], eax
      mov tmp[1 * TYPE int], ebx
      mov tmp[2 * TYPE int], ecx
      mov tmp[3 * TYPE int], edx

#ifdef CPUID_AWARE_COMPILER
      pop edx
      pop ecx
      pop ebx
      pop eax
#endif
    }
Kitware Robot's avatar
Kitware Robot committed
266
  } __except (1) {
Kitware Robot's avatar
Kitware Robot committed
267
    return false;
Kitware Robot's avatar
Kitware Robot committed
268
  }
Kitware Robot's avatar
Kitware Robot committed
269

Kitware Robot's avatar
Kitware Robot committed
270
  memcpy(result, tmp, sizeof(tmp));
Kitware Robot's avatar
Kitware Robot committed
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
#elif defined(KWSYS_CXX_HAS_BORLAND_ASM_CPUID)
  unsigned int a, b, c, d;
  __asm {
    mov EAX, select;
    cpuid
    mov a, EAX;
    mov b, EBX;
    mov c, ECX;
    mov d, EDX;
  }

  result[0] = a;
  result[1] = b;
  result[2] = c;
  result[3] = d;
#endif

Kitware Robot's avatar
Kitware Robot committed
288
289
290
291
292
293
  // The cpuid instruction succeeded.
  return true;
#endif
}
#endif

Kitware Robot's avatar
Kitware Robot committed
294
295
296
namespace KWSYS_NAMESPACE {
template <typename T>
T min(T a, T b)
Kitware Robot's avatar
Kitware Robot committed
297
{
Kitware Robot's avatar
Kitware Robot committed
298
299
  return a < b ? a : b;
}
Kitware Robot's avatar
Kitware Robot committed
300

Kitware Robot's avatar
Kitware Robot committed
301
302
303
extern "C" {
typedef void (*SigAction)(int, siginfo_t*, void*);
}
Kitware Robot's avatar
Kitware Robot committed
304
305

//  Define SystemInformationImplementation class
Kitware Robot's avatar
Kitware Robot committed
306
typedef void (*DELAY_FUNC)(unsigned int uiMS);
Kitware Robot's avatar
Kitware Robot committed
307
308
309
310

class SystemInformationImplementation
{
public:
Kitware Robot's avatar
Kitware Robot committed
311
  typedef SystemInformation::LongLong LongLong;
Kitware Robot's avatar
Kitware Robot committed
312
313
  SystemInformationImplementation();
  ~SystemInformationImplementation();
Kitware Robot's avatar
Kitware Robot committed
314

Kitware Robot's avatar
Kitware Robot committed
315
316
  const char* GetVendorString();
  const char* GetVendorID();
Kitware Robot's avatar
Kitware Robot committed
317
318
319
320
321
  std::string GetTypeID();
  std::string GetFamilyID();
  std::string GetModelID();
  std::string GetModelName();
  std::string GetSteppingCode();
Kitware Robot's avatar
Kitware Robot committed
322
323
  const char* GetExtendedProcessorName();
  const char* GetProcessorSerialNumber();
Kitware Robot's avatar
Kitware Robot committed
324
325
326
327
328
329
  int GetProcessorCacheSize();
  unsigned int GetLogicalProcessorsPerPhysical();
  float GetProcessorClockFrequency();
  int GetProcessorAPICID();
  int GetProcessorCacheXSize(long int);
  bool DoesCPUSupportFeature(long int);
Kitware Robot's avatar
Kitware Robot committed
330

Kitware Robot's avatar
Kitware Robot committed
331
332
333
334
335
336
  const char* GetOSName();
  const char* GetHostname();
  int GetFullyQualifiedDomainName(std::string& fqdn);
  const char* GetOSRelease();
  const char* GetOSVersion();
  const char* GetOSPlatform();
Kitware Robot's avatar
Kitware Robot committed
337
338
339
340
341
342
343
344

  bool Is64Bits();

  unsigned int GetNumberOfLogicalCPU(); // per physical cpu
  unsigned int GetNumberOfPhysicalCPU();

  bool DoesCPUSupportCPUID();

Kitware Robot's avatar
Kitware Robot committed
345
  // Retrieve memory information in MiB.
Kitware Robot's avatar
Kitware Robot committed
346
347
348
  size_t GetTotalVirtualMemory();
  size_t GetAvailableVirtualMemory();
  size_t GetTotalPhysicalMemory();
Kitware Robot's avatar
Kitware Robot committed
349
350
351
352
  size_t GetAvailablePhysicalMemory();

  LongLong GetProcessId();

Kitware Robot's avatar
Kitware Robot committed
353
  // Retrieve memory information in KiB.
Kitware Robot's avatar
Kitware Robot committed
354
  LongLong GetHostMemoryTotal();
Kitware Robot's avatar
Kitware Robot committed
355
  LongLong GetHostMemoryAvailable(const char* envVarName);
Kitware Robot's avatar
Kitware Robot committed
356
357
  LongLong GetHostMemoryUsed();

Kitware Robot's avatar
Kitware Robot committed
358
359
  LongLong GetProcMemoryAvailable(const char* hostLimitEnvVarName,
                                  const char* procLimitEnvVarName);
Kitware Robot's avatar
Kitware Robot committed
360
  LongLong GetProcMemoryUsed();
Kitware Robot's avatar
Kitware Robot committed
361

Kitware Robot's avatar
Kitware Robot committed
362
363
  double GetLoadAverage();

Kitware Robot's avatar
Kitware Robot committed
364
  // enable/disable stack trace signal handler.
Kitware Robot's avatar
Kitware Robot committed
365
  static void SetStackTraceOnError(int enable);
Kitware Robot's avatar
Kitware Robot committed
366

Kitware Robot's avatar
Kitware Robot committed
367
  // get current stack
Kitware Robot's avatar
Kitware Robot committed
368
  static std::string GetProgramStack(int firstFrame, int wholePath);
Kitware Robot's avatar
Kitware Robot committed
369

Kitware Robot's avatar
Kitware Robot committed
370
371
372
373
374
375
376
  /** Run the different checks */
  void RunCPUCheck();
  void RunOSCheck();
  void RunMemoryCheck();

public:
  typedef struct tagID
Kitware Robot's avatar
Kitware Robot committed
377
  {
Kitware Robot's avatar
Kitware Robot committed
378
379
380
381
382
383
    int Type;
    int Family;
    int Model;
    int Revision;
    int ExtendedFamily;
    int ExtendedModel;
Kitware Robot's avatar
Kitware Robot committed
384
385
386
387
    std::string ProcessorName;
    std::string Vendor;
    std::string SerialNumber;
    std::string ModelName;
Kitware Robot's avatar
Kitware Robot committed
388
  } ID;
Kitware Robot's avatar
Kitware Robot committed
389
390

  typedef struct tagCPUPowerManagement
Kitware Robot's avatar
Kitware Robot committed
391
  {
Kitware Robot's avatar
Kitware Robot committed
392
393
394
    bool HasVoltageID;
    bool HasFrequencyID;
    bool HasTempSenseDiode;
Kitware Robot's avatar
Kitware Robot committed
395
  } CPUPowerManagement;
Kitware Robot's avatar
Kitware Robot committed
396
397

  typedef struct tagCPUExtendedFeatures
Kitware Robot's avatar
Kitware Robot committed
398
  {
Kitware Robot's avatar
Kitware Robot committed
399
400
401
402
403
404
405
406
    bool Has3DNow;
    bool Has3DNowPlus;
    bool SupportsMP;
    bool HasMMXPlus;
    bool HasSSEMMX;
    unsigned int LogicalProcessorsPerPhysical;
    int APIC_ID;
    CPUPowerManagement PowerManagement;
Kitware Robot's avatar
Kitware Robot committed
407
  } CPUExtendedFeatures;
Kitware Robot's avatar
Kitware Robot committed
408
409

  typedef struct CPUtagFeatures
Kitware Robot's avatar
Kitware Robot committed
410
  {
Kitware Robot's avatar
Kitware Robot committed
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
    bool HasFPU;
    bool HasTSC;
    bool HasMMX;
    bool HasSSE;
    bool HasSSEFP;
    bool HasSSE2;
    bool HasIA64;
    bool HasAPIC;
    bool HasCMOV;
    bool HasMTRR;
    bool HasACPI;
    bool HasSerial;
    bool HasThermal;
    int CPUSpeed;
    int L1CacheSize;
    int L2CacheSize;
    int L3CacheSize;
    CPUExtendedFeatures ExtendedFeatures;
Kitware Robot's avatar
Kitware Robot committed
429
  } CPUFeatures;
Kitware Robot's avatar
Kitware Robot committed
430
431

  enum Manufacturer
Kitware Robot's avatar
Kitware Robot committed
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
  {
    AMD,
    Intel,
    NSC,
    UMC,
    Cyrix,
    NexGen,
    IDT,
    Rise,
    Transmeta,
    Sun,
    IBM,
    Motorola,
    HP,
    UnknownManufacturer
  };
Kitware Robot's avatar
Kitware Robot committed
448
449

protected:
Kitware Robot's avatar
Kitware Robot committed
450
  // For windows
Kitware Robot's avatar
Kitware Robot committed
451
452
453
454
455
456
457
458
459
460
461
462
463
  bool RetrieveCPUFeatures();
  bool RetrieveCPUIdentity();
  bool RetrieveCPUCacheDetails();
  bool RetrieveClassicalCPUCacheDetails();
  bool RetrieveCPUClockSpeed();
  bool RetrieveClassicalCPUClockSpeed();
  bool RetrieveCPUExtendedLevelSupport(int);
  bool RetrieveExtendedCPUFeatures();
  bool RetrieveProcessorSerialNumber();
  bool RetrieveCPUPowerManagement();
  bool RetrieveClassicalCPUIdentity();
  bool RetrieveExtendedCPUIdentity();

Kitware Robot's avatar
Kitware Robot committed
464
  // Processor information
Kitware Robot's avatar
Kitware Robot committed
465
466
467
468
469
470
  Manufacturer ChipManufacturer;
  CPUFeatures Features;
  ID ChipID;
  float CPUSpeedInMHz;
  unsigned int NumberOfLogicalCPU;
  unsigned int NumberOfPhysicalCPU;
Kitware Robot's avatar
Kitware Robot committed
471

Kitware Robot's avatar
Kitware Robot committed
472
  void CPUCountWindows();    // For windows
Kitware Robot's avatar
Kitware Robot committed
473
  unsigned char GetAPICId(); // For windows
Kitware Robot's avatar
Kitware Robot committed
474
  bool IsSMTSupported();
Kitware Robot's avatar
Kitware Robot committed
475
  static LongLong GetCyclesDifference(DELAY_FUNC, unsigned int); // For windows
Kitware Robot's avatar
Kitware Robot committed
476
477

  // For Linux and Cygwin, /proc/cpuinfo formats are slightly different
Kitware Robot's avatar
Kitware Robot committed
478
  bool RetreiveInformationFromCpuInfoFile();
Kitware Robot's avatar
Kitware Robot committed
479
480
  std::string ExtractValueFromCpuInfoFile(std::string buffer, const char* word,
                                          size_t init = 0);
Kitware Robot's avatar
Kitware Robot committed
481

Kitware Robot's avatar
Kitware Robot committed
482
483
484
  bool QueryLinuxMemory();
  bool QueryCygwinMemory();

Kitware Robot's avatar
Kitware Robot committed
485
486
  static void Delay(unsigned int);
  static void DelayOverhead(unsigned int);
Kitware Robot's avatar
Kitware Robot committed
487

Kitware Robot's avatar
Kitware Robot committed
488
  void FindManufacturer(const std::string& family = "");
Kitware Robot's avatar
Kitware Robot committed
489
490
491

  // For Mac
  bool ParseSysCtl();
Kitware Robot's avatar
Kitware Robot committed
492
  int CallSwVers(const char* arg, std::string& ver);
Kitware Robot's avatar
Kitware Robot committed
493
494
495
  void TrimNewline(std::string&);
  std::string ExtractValueFromSysCtl(const char* word);
  std::string SysCtlBuffer;
Kitware Robot's avatar
Kitware Robot committed
496
497

  // For Solaris
Kitware Robot's avatar
Kitware Robot committed
498
499
  bool QuerySolarisMemory();
  bool QuerySolarisProcessor();
Kitware Robot's avatar
Kitware Robot committed
500
501
  std::string ParseValueFromKStat(const char* arguments);
  std::string RunProcess(std::vector<const char*> args);
Kitware Robot's avatar
Kitware Robot committed
502

Kitware Robot's avatar
Kitware Robot committed
503
  // For Haiku OS
Kitware Robot's avatar
Kitware Robot committed
504
505
  bool QueryHaikuInfo();

Kitware Robot's avatar
Kitware Robot committed
506
  // For QNX
Kitware Robot's avatar
Kitware Robot committed
507
508
509
  bool QueryQNXMemory();
  bool QueryQNXProcessor();

Kitware Robot's avatar
Kitware Robot committed
510
  // For OpenBSD, FreeBSD, NetBSD, DragonFly
Kitware Robot's avatar
Kitware Robot committed
511
512
513
  bool QueryBSDMemory();
  bool QueryBSDProcessor();

Kitware Robot's avatar
Kitware Robot committed
514
  // For HP-UX
Kitware Robot's avatar
Kitware Robot committed
515
516
517
  bool QueryHPUXMemory();
  bool QueryHPUXProcessor();

Kitware Robot's avatar
Kitware Robot committed
518
  // For Microsoft Windows
Kitware Robot's avatar
Kitware Robot committed
519
520
  bool QueryWindowsMemory();

Kitware Robot's avatar
Kitware Robot committed
521
  // For AIX
Kitware Robot's avatar
Kitware Robot committed
522
523
  bool QueryAIXMemory();

Kitware Robot's avatar
Kitware Robot committed
524
  bool QueryProcessorBySysconf();
Kitware Robot's avatar
Kitware Robot committed
525
526
  bool QueryProcessor();

Kitware Robot's avatar
Kitware Robot committed
527
  // Evaluate the memory information.
Kitware Robot's avatar
Kitware Robot committed
528
  bool QueryMemoryBySysconf();
Kitware Robot's avatar
Kitware Robot committed
529
  bool QueryMemory();
Kitware Robot's avatar
Kitware Robot committed
530
531
532
533
534
535
536
537
538
  size_t TotalVirtualMemory;
  size_t AvailableVirtualMemory;
  size_t TotalPhysicalMemory;
  size_t AvailablePhysicalMemory;

  size_t CurrentPositionInFile;

  // Operating System information
  bool QueryOSInformation();
Kitware Robot's avatar
Kitware Robot committed
539
540
541
542
543
  std::string OSName;
  std::string Hostname;
  std::string OSRelease;
  std::string OSVersion;
  std::string OSPlatform;
Kitware Robot's avatar
Kitware Robot committed
544
  bool OSIs64Bit;
Kitware Robot's avatar
Kitware Robot committed
545
546
547
548
549
550
551
552
553
554
555
556
};

SystemInformation::SystemInformation()
{
  this->Implementation = new SystemInformationImplementation;
}

SystemInformation::~SystemInformation()
{
  delete this->Implementation;
}

Kitware Robot's avatar
Kitware Robot committed
557
const char* SystemInformation::GetVendorString()
Kitware Robot's avatar
Kitware Robot committed
558
559
560
561
{
  return this->Implementation->GetVendorString();
}

Kitware Robot's avatar
Kitware Robot committed
562
const char* SystemInformation::GetVendorID()
Kitware Robot's avatar
Kitware Robot committed
563
564
565
566
{
  return this->Implementation->GetVendorID();
}

Kitware Robot's avatar
Kitware Robot committed
567
std::string SystemInformation::GetTypeID()
Kitware Robot's avatar
Kitware Robot committed
568
569
570
571
{
  return this->Implementation->GetTypeID();
}

Kitware Robot's avatar
Kitware Robot committed
572
std::string SystemInformation::GetFamilyID()
Kitware Robot's avatar
Kitware Robot committed
573
574
575
576
{
  return this->Implementation->GetFamilyID();
}

Kitware Robot's avatar
Kitware Robot committed
577
std::string SystemInformation::GetModelID()
Kitware Robot's avatar
Kitware Robot committed
578
579
580
581
{
  return this->Implementation->GetModelID();
}

Kitware Robot's avatar
Kitware Robot committed
582
std::string SystemInformation::GetModelName()
Kitware Robot's avatar
Kitware Robot committed
583
584
585
586
{
  return this->Implementation->GetModelName();
}

Kitware Robot's avatar
Kitware Robot committed
587
std::string SystemInformation::GetSteppingCode()
Kitware Robot's avatar
Kitware Robot committed
588
589
590
591
{
  return this->Implementation->GetSteppingCode();
}

Kitware Robot's avatar
Kitware Robot committed
592
const char* SystemInformation::GetExtendedProcessorName()
Kitware Robot's avatar
Kitware Robot committed
593
594
595
596
{
  return this->Implementation->GetExtendedProcessorName();
}

Kitware Robot's avatar
Kitware Robot committed
597
const char* SystemInformation::GetProcessorSerialNumber()
Kitware Robot's avatar
Kitware Robot committed
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
{
  return this->Implementation->GetProcessorSerialNumber();
}

int SystemInformation::GetProcessorCacheSize()
{
  return this->Implementation->GetProcessorCacheSize();
}

unsigned int SystemInformation::GetLogicalProcessorsPerPhysical()
{
  return this->Implementation->GetLogicalProcessorsPerPhysical();
}

float SystemInformation::GetProcessorClockFrequency()
{
  return this->Implementation->GetProcessorClockFrequency();
}

int SystemInformation::GetProcessorAPICID()
{
  return this->Implementation->GetProcessorAPICID();
}

int SystemInformation::GetProcessorCacheXSize(long int l)
{
  return this->Implementation->GetProcessorCacheXSize(l);
}

bool SystemInformation::DoesCPUSupportFeature(long int i)
{
  return this->Implementation->DoesCPUSupportFeature(i);
}

Kitware Robot's avatar
Kitware Robot committed
632
std::string SystemInformation::GetCPUDescription()
Kitware Robot's avatar
Kitware Robot committed
633
{
Kitware Robot's avatar
Kitware Robot committed
634
  std::ostringstream oss;
Kitware Robot's avatar
Kitware Robot committed
635
636
637
638
639
  oss << this->GetNumberOfPhysicalCPU() << " core ";
  if (this->GetModelName().empty()) {
    oss << this->GetProcessorClockFrequency() << " MHz "
        << this->GetVendorString() << " " << this->GetExtendedProcessorName();
  } else {
Kitware Robot's avatar
Kitware Robot committed
640
    oss << this->GetModelName();
Kitware Robot's avatar
Kitware Robot committed
641
  }
Kitware Robot's avatar
Kitware Robot committed
642
643

  // remove extra spaces
Kitware Robot's avatar
Kitware Robot committed
644
  std::string tmp = oss.str();
Kitware Robot's avatar
Kitware Robot committed
645
  size_t pos;
Kitware Robot's avatar
Kitware Robot committed
646
647
648
  while ((pos = tmp.find("  ")) != std::string::npos) {
    tmp.replace(pos, 2, " ");
  }
Kitware Robot's avatar
Kitware Robot committed
649
650
651
652

  return tmp;
}

Kitware Robot's avatar
Kitware Robot committed
653
const char* SystemInformation::GetOSName()
Kitware Robot's avatar
Kitware Robot committed
654
655
656
657
{
  return this->Implementation->GetOSName();
}

Kitware Robot's avatar
Kitware Robot committed
658
const char* SystemInformation::GetHostname()
Kitware Robot's avatar
Kitware Robot committed
659
660
661
662
{
  return this->Implementation->GetHostname();
}

Kitware Robot's avatar
Kitware Robot committed
663
std::string SystemInformation::GetFullyQualifiedDomainName()
Kitware Robot's avatar
Kitware Robot committed
664
{
Kitware Robot's avatar
Kitware Robot committed
665
  std::string fqdn;
Kitware Robot's avatar
Kitware Robot committed
666
  this->Implementation->GetFullyQualifiedDomainName(fqdn);
Kitware Robot's avatar
Kitware Robot committed
667
668
669
  return fqdn;
}

Kitware Robot's avatar
Kitware Robot committed
670
const char* SystemInformation::GetOSRelease()
Kitware Robot's avatar
Kitware Robot committed
671
672
673
674
{
  return this->Implementation->GetOSRelease();
}

Kitware Robot's avatar
Kitware Robot committed
675
const char* SystemInformation::GetOSVersion()
Kitware Robot's avatar
Kitware Robot committed
676
677
678
679
{
  return this->Implementation->GetOSVersion();
}

Kitware Robot's avatar
Kitware Robot committed
680
const char* SystemInformation::GetOSPlatform()
Kitware Robot's avatar
Kitware Robot committed
681
682
683
684
{
  return this->Implementation->GetOSPlatform();
}

Kitware Robot's avatar
Kitware Robot committed
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
int SystemInformation::GetOSIsWindows()
{
#if defined(_WIN32)
  return 1;
#else
  return 0;
#endif
}

int SystemInformation::GetOSIsLinux()
{
#if defined(__linux)
  return 1;
#else
  return 0;
#endif
}

int SystemInformation::GetOSIsApple()
{
#if defined(__APPLE__)
  return 1;
#else
  return 0;
#endif
}

Kitware Robot's avatar
Kitware Robot committed
712
std::string SystemInformation::GetOSDescription()
Kitware Robot's avatar
Kitware Robot committed
713
{
Kitware Robot's avatar
Kitware Robot committed
714
  std::ostringstream oss;
Kitware Robot's avatar
Kitware Robot committed
715
716
  oss << this->GetOSName() << " " << this->GetOSRelease() << " "
      << this->GetOSVersion();
Kitware Robot's avatar
Kitware Robot committed
717
718
719
720

  return oss.str();
}

Kitware Robot's avatar
Kitware Robot committed
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
bool SystemInformation::Is64Bits()
{
  return this->Implementation->Is64Bits();
}

unsigned int SystemInformation::GetNumberOfLogicalCPU() // per physical cpu
{
  return this->Implementation->GetNumberOfLogicalCPU();
}

unsigned int SystemInformation::GetNumberOfPhysicalCPU()
{
  return this->Implementation->GetNumberOfPhysicalCPU();
}

bool SystemInformation::DoesCPUSupportCPUID()
{
  return this->Implementation->DoesCPUSupportCPUID();
}

Kitware Robot's avatar
Kitware Robot committed
741
// Retrieve memory information in MiB.
Kitware Robot's avatar
Kitware Robot committed
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
size_t SystemInformation::GetTotalVirtualMemory()
{
  return this->Implementation->GetTotalVirtualMemory();
}

size_t SystemInformation::GetAvailableVirtualMemory()
{
  return this->Implementation->GetAvailableVirtualMemory();
}

size_t SystemInformation::GetTotalPhysicalMemory()
{
  return this->Implementation->GetTotalPhysicalMemory();
}

size_t SystemInformation::GetAvailablePhysicalMemory()
{
  return this->Implementation->GetAvailablePhysicalMemory();
}

Kitware Robot's avatar
Kitware Robot committed
762
std::string SystemInformation::GetMemoryDescription(
Kitware Robot's avatar
Kitware Robot committed
763
  const char* hostLimitEnvVarName, const char* procLimitEnvVarName)
Kitware Robot's avatar
Kitware Robot committed
764
{
Kitware Robot's avatar
Kitware Robot committed
765
  std::ostringstream oss;
Kitware Robot's avatar
Kitware Robot committed
766
767
768
769
770
771
772
  oss << "Host Total: " << iostreamLongLong(this->GetHostMemoryTotal())
      << " KiB, Host Available: "
      << iostreamLongLong(this->GetHostMemoryAvailable(hostLimitEnvVarName))
      << " KiB, Process Available: "
      << iostreamLongLong(this->GetProcMemoryAvailable(hostLimitEnvVarName,
                                                       procLimitEnvVarName))
      << " KiB";
Kitware Robot's avatar
Kitware Robot committed
773
774
775
  return oss.str();
}

Kitware Robot's avatar
Kitware Robot committed
776
777
// host memory info in units of KiB.
SystemInformation::LongLong SystemInformation::GetHostMemoryTotal()
Kitware Robot's avatar
Kitware Robot committed
778
{
Kitware Robot's avatar
Kitware Robot committed
779
  return this->Implementation->GetHostMemoryTotal();
Kitware Robot's avatar
Kitware Robot committed
780
781
}

Kitware Robot's avatar
Kitware Robot committed
782
783
SystemInformation::LongLong SystemInformation::GetHostMemoryAvailable(
  const char* hostLimitEnvVarName)
Kitware Robot's avatar
Kitware Robot committed
784
785
786
787
788
{
  return this->Implementation->GetHostMemoryAvailable(hostLimitEnvVarName);
}

SystemInformation::LongLong SystemInformation::GetHostMemoryUsed()
Kitware Robot's avatar
Kitware Robot committed
789
{
Kitware Robot's avatar
Kitware Robot committed
790
791
792
793
  return this->Implementation->GetHostMemoryUsed();
}

// process memory info in units of KiB.
Kitware Robot's avatar
Kitware Robot committed
794
795
SystemInformation::LongLong SystemInformation::GetProcMemoryAvailable(
  const char* hostLimitEnvVarName, const char* procLimitEnvVarName)
Kitware Robot's avatar
Kitware Robot committed
796
{
Kitware Robot's avatar
Kitware Robot committed
797
798
  return this->Implementation->GetProcMemoryAvailable(hostLimitEnvVarName,
                                                      procLimitEnvVarName);
Kitware Robot's avatar
Kitware Robot committed
799
800
801
802
803
}

SystemInformation::LongLong SystemInformation::GetProcMemoryUsed()
{
  return this->Implementation->GetProcMemoryUsed();
Kitware Robot's avatar
Kitware Robot committed
804
805
}

Kitware Robot's avatar
Kitware Robot committed
806
807
808
809
810
double SystemInformation::GetLoadAverage()
{
  return this->Implementation->GetLoadAverage();
}

Kitware Robot's avatar
Kitware Robot committed
811
812
813
814
815
816
817
818
819
820
SystemInformation::LongLong SystemInformation::GetProcessId()
{
  return this->Implementation->GetProcessId();
}

void SystemInformation::SetStackTraceOnError(int enable)
{
  SystemInformationImplementation::SetStackTraceOnError(enable);
}

Kitware Robot's avatar
Kitware Robot committed
821
std::string SystemInformation::GetProgramStack(int firstFrame, int wholePath)
Kitware Robot's avatar
Kitware Robot committed
822
{
Kitware Robot's avatar
Kitware Robot committed
823
824
  return SystemInformationImplementation::GetProgramStack(firstFrame,
                                                          wholePath);
Kitware Robot's avatar
Kitware Robot committed
825
826
}

Kitware Robot's avatar
Kitware Robot committed
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
/** Run the different checks */
void SystemInformation::RunCPUCheck()
{
  this->Implementation->RunCPUCheck();
}

void SystemInformation::RunOSCheck()
{
  this->Implementation->RunOSCheck();
}

void SystemInformation::RunMemoryCheck()
{
  this->Implementation->RunMemoryCheck();
}

// SystemInformationImplementation starts here

Kitware Robot's avatar
Kitware Robot committed
845
846
847
848
#define STORE_TLBCACHE_INFO(x, y) x = (x < (y)) ? (y) : x
#define TLBCACHE_INFO_UNITS (15)
#define CLASSICAL_CPU_FREQ_LOOP 10000000
#define RDTSC_INSTRUCTION _asm _emit 0x0f _asm _emit 0x31
Kitware Robot's avatar
Kitware Robot committed
849
850

// Status Flag
Kitware Robot's avatar
Kitware Robot committed
851
852
853
#define HT_NOT_CAPABLE 0
#define HT_ENABLED 1
#define HT_DISABLED 2
Kitware Robot's avatar
Kitware Robot committed
854
#define HT_SUPPORTED_NOT_ENABLED 3
Kitware Robot's avatar
Kitware Robot committed
855
#define HT_CANNOT_DETECT 4
Kitware Robot's avatar
Kitware Robot committed
856
857

// EDX[28]  Bit 28 is set if HT is supported
Kitware Robot's avatar
Kitware Robot committed
858
#define HT_BIT 0x10000000
Kitware Robot's avatar
Kitware Robot committed
859
860

// EAX[11:8] Bit 8-11 contains family processor ID.
Kitware Robot's avatar
Kitware Robot committed
861
862
#define FAMILY_ID 0x0F00
#define PENTIUM4_ID 0x0F00
Kitware Robot's avatar
Kitware Robot committed
863
// EAX[23:20] Bit 20-23 contains extended family processor ID
Kitware Robot's avatar
Kitware Robot committed
864
#define EXT_FAMILY_ID 0x0F00000
Kitware Robot's avatar
Kitware Robot committed
865
// EBX[23:16] Bit 16-23 in ebx contains the number of logical
Kitware Robot's avatar
Kitware Robot committed
866
#define NUM_LOGICAL_BITS 0x00FF0000
Kitware Robot's avatar
Kitware Robot committed
867
// processors per physical processor when execute cpuid with
Kitware Robot's avatar
Kitware Robot committed
868
// eax set to 1
Kitware Robot's avatar
Kitware Robot committed
869
// EBX[31:24] Bits 24-31 (8 bits) return the 8-bit unique
Kitware Robot's avatar
Kitware Robot committed
870
#define INITIAL_APIC_ID_BITS 0xFF000000
Kitware Robot's avatar
Kitware Robot committed
871
872
873
// initial APIC ID for the processor this code is running on.
// Default value = 0xff if HT is not supported

Kitware Robot's avatar
Kitware Robot committed
874
875
876
877
// Hide implementation details in an anonymous namespace.
namespace {
// *****************************************************************************
#if defined(__linux) || defined(__APPLE__)
Kitware Robot's avatar
Kitware Robot committed
878
int LoadLines(FILE* file, std::vector<std::string>& lines)
Kitware Robot's avatar
Kitware Robot committed
879
880
{
  // Load each line in the given file into a the vector.
Kitware Robot's avatar
Kitware Robot committed
881
882
883
884
885
  int nRead = 0;
  const int bufSize = 1024;
  char buf[bufSize] = { '\0' };
  while (!feof(file) && !ferror(file)) {
    errno = 0;
Kitware Robot's avatar
Kitware Robot committed
886
    if (fgets(buf, bufSize, file) == KWSYS_NULLPTR) {
Kitware Robot's avatar
Kitware Robot committed
887
      if (ferror(file) && (errno == EINTR)) {
Kitware Robot's avatar
Kitware Robot committed
888
        clearerr(file);
Kitware Robot's avatar
Kitware Robot committed
889
      }
Kitware Robot's avatar
Kitware Robot committed
890
891
892
893
894
895
896
897
      continue;
    }
    char* pBuf = buf;
    while (*pBuf) {
      if (*pBuf == '\n')
        *pBuf = '\0';
      pBuf += 1;
    }
Kitware Robot's avatar
Kitware Robot committed
898
899
    lines.push_back(buf);
    ++nRead;
Kitware Robot's avatar
Kitware Robot committed
900
901
  }
  if (ferror(file)) {
Kitware Robot's avatar
Kitware Robot committed
902
    return 0;
Kitware Robot's avatar
Kitware Robot committed
903
  }
Kitware Robot's avatar
Kitware Robot committed
904
905
906
  return nRead;
}

Kitware Robot's avatar
Kitware Robot committed
907
#if defined(__linux)
Kitware Robot's avatar
Kitware Robot committed
908
// *****************************************************************************
Kitware Robot's avatar
Kitware Robot committed
909
int LoadLines(const char* fileName, std::vector<std::string>& lines)
Kitware Robot's avatar
Kitware Robot committed
910
{
Kitware Robot's avatar
Kitware Robot committed
911
912
  FILE* file = fopen(fileName, "r");
  if (file == 0) {
Kitware Robot's avatar
Kitware Robot committed
913
    return 0;
Kitware Robot's avatar
Kitware Robot committed
914
915
  }
  int nRead = LoadLines(file, lines);
Kitware Robot's avatar
Kitware Robot committed
916
  fclose(file);
Kitware Robot's avatar
Kitware Robot committed
917
918
  return nRead;
}
Kitware Robot's avatar
Kitware Robot committed
919
#endif
Kitware Robot's avatar
Kitware Robot committed
920
921

// ****************************************************************************
Kitware Robot's avatar
Kitware Robot committed
922
template <typename T>
Kitware Robot's avatar
Kitware Robot committed
923
924
int NameValue(std::vector<std::string> const& lines, std::string const& name,
              T& value)
Kitware Robot's avatar
Kitware Robot committed
925
{
Kitware Robot's avatar
Kitware Robot committed
926
927
928
929
  size_t nLines = lines.size();
  for (size_t i = 0; i < nLines; ++i) {
    size_t at = lines[i].find(name);
    if (at == std::string::npos) {
Kitware Robot's avatar
Kitware Robot committed
930
      continue;
Kitware Robot's avatar
Kitware Robot committed
931
932
    }
    std::istringstream is(lines[i].substr(at + name.size()));
Kitware Robot's avatar
Kitware Robot committed
933
934
    is >> value;
    return 0;
Kitware Robot's avatar
Kitware Robot committed
935
  }
Kitware Robot's avatar
Kitware Robot committed
936
937
  return -1;
}
Kitware Robot's avatar
Kitware Robot committed
938
939
940
941
#endif

#if defined(__linux)
// ****************************************************************************
Kitware Robot's avatar
Kitware Robot committed
942
943
template <typename T>
int GetFieldsFromFile(const char* fileName, const char** fieldNames, T* values)
Kitware Robot's avatar
Kitware Robot committed
944
{
Kitware Robot's avatar
Kitware Robot committed
945
  std::vector<std::string> fields;
Kitware Robot's avatar
Kitware Robot committed
946
  if (!LoadLines(fileName, fields)) {
Kitware Robot's avatar
Kitware Robot committed
947
    return -1;
Kitware Robot's avatar
Kitware Robot committed
948
949
950
951
952
953
  }
  int i = 0;
  while (fieldNames[i] != NULL) {
    int ierr = NameValue(fields, fieldNames[i], values[i]);
    if (ierr) {
      return -(i + 2);
Kitware Robot's avatar
Kitware Robot committed
954
    }
Kitware Robot's avatar
Kitware Robot committed
955
956
    i += 1;
  }
Kitware Robot's avatar
Kitware Robot committed
957
958
  return 0;
}
Kitware Robot's avatar
Kitware Robot committed
959
960

// ****************************************************************************
Kitware Robot's avatar
Kitware Robot committed
961
962
963
964
965
966
967
template <typename T>
int GetFieldFromFile(const char* fileName, const char* fieldName, T& value)
{
  const char* fieldNames[2] = { fieldName, NULL };
  T values[1] = { T(0) };
  int ierr = GetFieldsFromFile(fileName, fieldNames, values);
  if (ierr) {
Kitware Robot's avatar
Kitware Robot committed
968
    return ierr;
Kitware Robot's avatar
Kitware Robot committed
969
970
  }
  value = values[0];
Kitware Robot's avatar
Kitware Robot committed
971
972
973
974
975
976
  return 0;
}
#endif

// ****************************************************************************
#if defined(__APPLE__)
Kitware Robot's avatar
Kitware Robot committed
977
978
979
980
981
template <typename T>
int GetFieldsFromCommand(const char* command, const char** fieldNames,
                         T* values)
{
  FILE* file = popen(command, "r");
Kitware Robot's avatar
Kitware Robot committed
982
  if (file == KWSYS_NULLPTR) {
Kitware Robot's avatar
Kitware Robot committed
983
    return -1;
Kitware Robot's avatar
Kitware Robot committed
984
  }
Kitware Robot's avatar
Kitware Robot committed
985
  std::vector<std::string> fields;
Kitware Robot's avatar
Kitware Robot committed
986
  int nl = LoadLines(file, fields);
Kitware Robot's avatar
Kitware Robot committed
987
  pclose(file);
Kitware Robot's avatar
Kitware Robot committed
988
  if (nl == 0) {
Kitware Robot's avatar
Kitware Robot committed
989
    return -1;
Kitware Robot's avatar
Kitware Robot committed
990
991
  }
  int i = 0;
Kitware Robot's avatar
Kitware Robot committed
992
  while (fieldNames[i] != KWSYS_NULLPTR) {
Kitware Robot's avatar
Kitware Robot committed
993
994
995
    int ierr = NameValue(fields, fieldNames[i], values[i]);
    if (ierr) {
      return -(i + 2);
Kitware Robot's avatar
Kitware Robot committed
996
    }
Kitware Robot's avatar
Kitware Robot committed
997
998
    i += 1;
  }
Kitware Robot's avatar
Kitware Robot committed
999
1000
  return 0;
}
Kitware Robot's avatar
Kitware Robot committed
1001
#endif
Kitware Robot's avatar
Kitware Robot committed
1002

Kitware Robot's avatar
Kitware Robot committed
1003
1004
// ****************************************************************************
#if !defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
Kitware Robot's avatar
Kitware Robot committed
1005
1006
void StacktraceSignalHandler(int sigNo, siginfo_t* sigInfo,
                             void* /*sigContext*/)
Kitware Robot's avatar
Kitware Robot committed
1007
1008
{
#if defined(__linux) || defined(__APPLE__)
Kitware Robot's avatar
Kitware Robot committed
1009
  std::ostringstream oss;
Kitware Robot's avatar
Kitware Robot committed
1010
1011
1012
1013
1014
  oss << std::endl
      << "========================================================="
      << std::endl
      << "Process id " << getpid() << " ";
  switch (sigNo) {
Kitware Robot's avatar
Kitware Robot committed
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
    case SIGINT:
      oss << "Caught SIGINT";
      break;

    case SIGTERM:
      oss << "Caught SIGTERM";
      break;

    case SIGABRT:
      oss << "Caught SIGABRT";
      break;

Kitware Robot's avatar
Kitware Robot committed
1027
    case SIGFPE:
Kitware Robot's avatar
Kitware Robot committed
1028
1029
      oss << "Caught SIGFPE at "
          << (sigInfo->si_addr == KWSYS_NULLPTR ? "0x" : "")
Kitware Robot's avatar
Kitware Robot committed
1030
1031
1032
          << sigInfo->si_addr << " ";
      switch (sigInfo->si_code) {
#if defined(FPE_INTDIV)
Kitware Robot's avatar
Kitware Robot committed
1033
        case FPE_INTDIV:
Kitware Robot's avatar
Kitware Robot committed
1034
          oss << "integer division by zero";
Kitware Robot's avatar
Kitware Robot committed
1035
          break;
Kitware Robot's avatar
Kitware Robot committed
1036
#endif
Kitware Robot's avatar
Kitware Robot committed
1037

Kitware Robot's avatar
Kitware Robot committed
1038
#if defined(FPE_INTOVF)
Kitware Robot's avatar
Kitware Robot committed
1039
        case FPE_INTOVF:
Kitware Robot's avatar
Kitware Robot committed
1040
          oss << "integer overflow";
Kitware Robot's avatar
Kitware Robot committed
1041
          break;
Kitware Robot's avatar
Kitware Robot committed
1042
#endif
Kitware Robot's avatar
Kitware Robot committed
1043
1044

        case FPE_FLTDIV:
Kitware Robot's avatar
Kitware Robot committed
1045
          oss << "floating point divide by zero";
Kitware Robot's avatar
Kitware Robot committed
1046
1047
1048
          break;

        case FPE_FLTOVF:
Kitware Robot's avatar
Kitware Robot committed
1049
          oss << "floating point overflow";
Kitware Robot's avatar
Kitware Robot committed
1050
1051
1052
          break;

        case FPE_FLTUND:
Kitware Robot's avatar
Kitware Robot committed
1053
          oss << "floating point underflow";
Kitware Robot's avatar
Kitware Robot committed
1054
1055
1056
          break;

        case FPE_FLTRES:
Kitware Robot's avatar
Kitware Robot committed
1057
          oss << "floating point inexact result";
Kitware Robot's avatar
Kitware Robot committed
1058
1059
1060
          break;

        case FPE_FLTINV:
Kitware Robot's avatar
Kitware Robot committed
1061
          oss << "floating point invalid operation";
Kitware Robot's avatar
Kitware Robot committed
1062
1063
1064
1065
          break;

#if defined(FPE_FLTSUB)
        case FPE_FLTSUB:
Kitware Robot's avatar
Kitware Robot committed
1066
          oss << "floating point subscript out of range";
Kitware Robot's avatar
Kitware Robot committed
1067
1068
1069
1070
          break;
#endif

        default:
Kitware Robot's avatar
Kitware Robot committed
1071
          oss << "code " << sigInfo->si_code;
Kitware Robot's avatar
Kitware Robot committed
1072
          break;
Kitware Robot's avatar
Kitware Robot committed
1073
      }
Kitware Robot's avatar
Kitware Robot committed
1074
1075
1076
      break;

    case SIGSEGV:
Kitware Robot's avatar
Kitware Robot committed
1077
1078
      oss << "Caught SIGSEGV at "
          << (sigInfo->si_addr == KWSYS_NULLPTR ? "0x" : "")
Kitware Robot's avatar
Kitware Robot committed
1079
1080
          << sigInfo->si_addr << " ";
      switch (sigInfo->si_code) {
Kitware Robot's avatar
Kitware Robot committed
1081
        case SEGV_MAPERR:
Kitware Robot's avatar
Kitware Robot committed
1082
          oss << "address not mapped to object";
Kitware Robot's avatar
Kitware Robot committed
1083
1084
1085
          break;

        case SEGV_ACCERR:
Kitware Robot's avatar
Kitware Robot committed
1086
          oss << "invalid permission for mapped object";
Kitware Robot's avatar
Kitware Robot committed
1087
1088
1089
          break;

        default:
Kitware Robot's avatar
Kitware Robot committed
1090
          oss << "code " << sigInfo->si_code;
Kitware Robot's avatar
Kitware Robot committed
1091
          break;
Kitware Robot's avatar
Kitware Robot committed
1092
      }
Kitware Robot's avatar
Kitware Robot committed
1093
1094
1095
      break;

    case SIGBUS:
Kitware Robot's avatar
Kitware Robot committed
1096
1097
      oss << "Caught SIGBUS at "
          << (sigInfo->si_addr == KWSYS_NULLPTR ? "0x" : "")
Kitware Robot's avatar
Kitware Robot committed
1098
1099
          << sigInfo->si_addr << " ";
      switch (sigInfo->si_code) {
Kitware Robot's avatar
Kitware Robot committed
1100
        case BUS_ADRALN:
Kitware Robot's avatar
Kitware Robot committed
1101
          oss << "invalid address alignment";
Kitware Robot's avatar
Kitware Robot committed
1102
1103
          break;

Kitware Robot's avatar
Kitware Robot committed
1104
#if defined(BUS_ADRERR)
Kitware Robot's avatar
Kitware Robot committed
1105
        case BUS_ADRERR:
Kitware Robot's avatar
Kitware Robot committed
1106
          oss << "nonexistent physical address";
Kitware Robot's avatar
Kitware Robot committed
1107
          break;
Kitware Robot's avatar
Kitware Robot committed
1108
#endif
Kitware Robot's avatar
Kitware Robot committed
1109

Kitware Robot's avatar
Kitware Robot committed
1110
#if defined(BUS_OBJERR)
Kitware Robot's avatar
Kitware Robot committed
1111
        case BUS_OBJERR:
Kitware Robot's avatar
Kitware Robot committed
1112
1113
          oss << "object-specific hardware error";
          break;
Kitware Robot's avatar
Kitware Robot committed
1114
#endif
Kitware Robot's avatar
Kitware Robot committed
1115

Kitware Robot's avatar
Kitware Robot committed
1116
#if defined(BUS_MCEERR_AR)
Kitware Robot's avatar
Kitware Robot committed
1117
        case BUS_MCEERR_AR:
Kitware Robot's avatar
Kitware Robot committed
1118
1119
          oss << "Hardware memory error consumed on a machine check; action "
                 "required.";
Kitware Robot's avatar
Kitware Robot committed
1120
          break;
Kitware Robot's avatar
Kitware Robot committed
1121
#endif
Kitware Robot's avatar
Kitware Robot committed
1122

Kitware Robot's avatar
Kitware Robot committed
1123
#if defined(BUS_MCEERR_AO)
Kitware Robot's avatar
Kitware Robot committed
1124
        case BUS_MCEERR_AO:
Kitware Robot's avatar
Kitware Robot committed
1125
1126
          oss << "Hardware memory error detected in process but not consumed; "
                 "action optional.";
Kitware Robot's avatar
Kitware Robot committed
1127
          break;
Kitware Robot's avatar
Kitware Robot committed
1128
#endif
Kitware Robot's avatar
Kitware Robot committed
1129
1130

        default:
Kitware Robot's avatar
Kitware Robot committed
1131
          oss << "code " << sigInfo->si_code;
Kitware Robot's avatar
Kitware Robot committed
1132
          break;
Kitware Robot's avatar
Kitware Robot committed
1133
      }
Kitware Robot's avatar
Kitware Robot committed
1134
1135
1136
      break;

    case SIGILL:
Kitware Robot's avatar
Kitware Robot committed
1137
1138
      oss << "Caught SIGILL at "
          << (sigInfo->si_addr == KWSYS_NULLPTR ? "0x" : "")
Kitware Robot's avatar
Kitware Robot committed
1139
1140
          << sigInfo->si_addr << " ";
      switch (sigInfo->si_code) {
Kitware Robot's avatar
Kitware Robot committed
1141
        case ILL_ILLOPC:
Kitware Robot's avatar
Kitware Robot committed
1142
          oss << "illegal opcode";
Kitware Robot's avatar
Kitware Robot committed
1143
1144
          break;

Kitware Robot's avatar
Kitware Robot committed
1145
#if defined(ILL_ILLOPN)
Kitware Robot's avatar
Kitware Robot committed
1146
        case ILL_ILLOPN:
Kitware Robot's avatar
Kitware Robot committed
1147
          oss << "illegal operand";
Kitware Robot's avatar
Kitware Robot committed
1148
          break;
Kitware Robot's avatar
Kitware Robot committed
1149
#endif
Kitware Robot's avatar
Kitware Robot committed
1150

Kitware Robot's avatar
Kitware Robot committed
1151
#if defined(ILL_ILLADR)
Kitware Robot's avatar
Kitware Robot committed
1152
        case ILL_ILLADR:
Kitware Robot's avatar
Kitware Robot committed
1153
          oss << "illegal addressing mode.";
Kitware Robot's avatar
Kitware Robot committed
1154
          break;
Kitware Robot's avatar
Kitware Robot committed
1155
#endif
Kitware Robot's avatar
Kitware Robot committed
1156
1157

        case ILL_ILLTRP:
Kitware Robot's avatar
Kitware Robot committed
1158
          oss << "illegal trap";
Kitware Robot's avatar
Kitware Robot committed
1159
          break;
Kitware Robot's avatar
Kitware Robot committed
1160
1161

        case ILL_PRVOPC:
Kitware Robot's avatar
Kitware Robot committed
1162
          oss << "privileged opcode";
Kitware Robot's avatar
Kitware Robot committed
1163
1164
          break;

Kitware Robot's avatar
Kitware Robot committed
1165
#if defined(ILL_PRVREG)
Kitware Robot's avatar
Kitware Robot committed
1166
        case ILL_PRVREG:
Kitware Robot's avatar
Kitware Robot committed
1167
          oss << "privileged register";
Kitware Robot's avatar
Kitware Robot committed
1168
          break;
Kitware Robot's avatar
Kitware Robot committed
1169
#endif
Kitware Robot's avatar
Kitware Robot committed
1170

Kitware Robot's avatar
Kitware Robot committed
1171
#if defined(ILL_COPROC)
Kitware Robot's avatar
Kitware Robot committed
1172
        case ILL_COPROC:
Kitware Robot's avatar
Kitware Robot committed
1173
          oss << "co-processor error";
Kitware Robot's avatar
Kitware Robot committed
1174
          break;
Kitware Robot's avatar
Kitware Robot committed
1175
#endif
Kitware Robot's avatar
Kitware Robot committed
1176

Kitware Robot's avatar
Kitware Robot committed
1177
#if defined(ILL_BADSTK)
Kitware Robot's avatar
Kitware Robot committed
1178
        case ILL_BADSTK:
Kitware Robot's avatar
Kitware Robot committed
1179
          oss << "internal stack error";
Kitware Robot's avatar
Kitware Robot committed
1180
          break;