7 changed files with 8645 additions and 8130 deletions
-
4ChangeLog
-
5src/frontend/Makefile.am
-
492src/frontend/com_sysinfo.c
-
4src/frontend/commands.c
-
2src/include/fteext.h
-
4visualc/vngspice.sln
-
16264visualc/vngspice.vcproj
@ -0,0 +1,492 @@ |
|||||
|
/* Provide system information |
||||
|
|
||||
|
LINUX: /proc file system |
||||
|
Windows: GlobalMemoryStatusEx, GetSystemInfo, GetVersionExA, RegQueryValueExA |
||||
|
|
||||
|
Authors: Holger Vogt, Hendrik Vogt |
||||
|
|
||||
|
$Id$ |
||||
|
*/ |
||||
|
|
||||
|
#include "config.h" |
||||
|
#include "ngspice.h" |
||||
|
#include "cpdefs.h" |
||||
|
|
||||
|
/* We might compile for Windows, but only as a console application (e.g. tcl) */ |
||||
|
#if defined(HAS_WINDOWS) || defined(__MINGW32__) || defined(_MSC_VER) |
||||
|
#define HAVE_WIN32 |
||||
|
#endif |
||||
|
|
||||
|
#ifdef HAVE_WIN32 |
||||
|
|
||||
|
#define WIN32_LEAN_AND_MEAN |
||||
|
|
||||
|
#ifdef __MINGW32__ /* access to GlobalMemoryStatusEx in winbase.h:1558 */ |
||||
|
#define WINVER 0x0500 |
||||
|
#endif |
||||
|
|
||||
|
#undef BOOLEAN |
||||
|
#include "windows.h" |
||||
|
#if defined(__MINGW32__) || (_MSC_VER > 1200) /* Exclude VC++ 6.0 from using the psapi */ |
||||
|
#include <psapi.h> |
||||
|
#endif |
||||
|
#endif |
||||
|
|
||||
|
#include "stdio.h" |
||||
|
#include "stdlib.h" |
||||
|
#include "string.h" |
||||
|
|
||||
|
#define tInt int |
||||
|
#define TesError int |
||||
|
#define TES_FAIL 1 |
||||
|
#define TES_SUCCESS 0 |
||||
|
|
||||
|
/* system info */ |
||||
|
typedef struct TSI { |
||||
|
char* cpuModelName; |
||||
|
int numPhysicalProcessors; |
||||
|
int numLogicalProcessors; |
||||
|
char* osName; |
||||
|
} TesSystemInfo; |
||||
|
|
||||
|
/* memory info */ |
||||
|
static struct sys_memory { |
||||
|
unsigned long int size; /* Total memory size */ |
||||
|
unsigned long int free; /* Free memory */ |
||||
|
unsigned long int swap_t; /* Swap total */ |
||||
|
unsigned long int swap_f; /* Swap free */ |
||||
|
}; |
||||
|
|
||||
|
static struct sys_memory mem_t_act; |
||||
|
|
||||
|
TesError tesCreateSystemInfo(TesSystemInfo *info); |
||||
|
static size_t get_sysmem(struct sys_memory *memall); |
||||
|
|
||||
|
/* Print to stream the given memory size in a human friendly format */ |
||||
|
static void |
||||
|
fprintmem(FILE* stream, unsigned long int memory) { |
||||
|
if (memory > 1048576) |
||||
|
fprintf(stream, "%8.6f MB", memory/1048576.); |
||||
|
else if (memory > 1024) |
||||
|
fprintf(stream, "%5.3f kB", memory/1024.); |
||||
|
else |
||||
|
fprintf(stream, "%lu bytes", memory); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
static void tesFreeSystemInfo(TesSystemInfo *info) { |
||||
|
if(info != NULL) { |
||||
|
free(info->cpuModelName); |
||||
|
free(info->osName); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* print system info */ |
||||
|
void com_sysinfo(void) |
||||
|
{ |
||||
|
int errorcode; |
||||
|
TesSystemInfo* info; |
||||
|
|
||||
|
info = (TesSystemInfo*)tmalloc(sizeof(TesSystemInfo)); |
||||
|
|
||||
|
errorcode = tesCreateSystemInfo(info); |
||||
|
if (errorcode) |
||||
|
fprintf(cp_err, "No system info available! \n"); |
||||
|
else { |
||||
|
fprintf(cp_out, "\nOS: %s\n", info->osName); |
||||
|
fprintf(cp_out, "CPU: %s\n", info->cpuModelName); |
||||
|
if (info->numPhysicalProcessors > 0) |
||||
|
fprintf(cp_out, "Physical processors: %d, ", info->numPhysicalProcessors); |
||||
|
fprintf(cp_out, "Logical processors: %d\n", |
||||
|
info->numLogicalProcessors); |
||||
|
} |
||||
|
#if defined(HAVE_WIN32) || defined(HAVE__PROC_MEMINFO) |
||||
|
|
||||
|
get_sysmem(&mem_t_act); |
||||
|
|
||||
|
/* get_sysmem returns bytes */ |
||||
|
fprintf(cp_out, "Total DRAM available = "); |
||||
|
fprintmem(cp_out, mem_t_act.size); |
||||
|
fprintf(cp_out, ".\n"); |
||||
|
|
||||
|
fprintf(cp_out, "DRAM currently available = "); |
||||
|
fprintmem(cp_out, mem_t_act.free); |
||||
|
fprintf(cp_out, ".\n\n"); |
||||
|
|
||||
|
#endif |
||||
|
|
||||
|
/* |
||||
|
Console.WriteLine("Number of CPUs: {0}", Environment.GetEnvironmentVariable _ |
||||
|
("NUMBER_OF_PROCESSORS")) |
||||
|
Console.WriteLine("CPU Architecture: {0}", Environment.GetEnvironmentVariable _ |
||||
|
("PROCESSOR_ARCHITECTURE")) |
||||
|
Console.WriteLine("CPU Identifier: {0}", Environment.GetEnvironmentVariable _ |
||||
|
("PROCESSOR_IDENTIFIER")) |
||||
|
Console.WriteLine("CPU Level: {0}", Environment.GetEnvironmentVariable _ |
||||
|
("PROCESSOR_LEVEL")) |
||||
|
Console.WriteLine("CPU Revision: {0}", Environment.GetEnvironmentVariable _ |
||||
|
("PROCESSOR_REVISION")) |
||||
|
|
||||
|
*/ |
||||
|
tesFreeSystemInfo(info); |
||||
|
tfree(info); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
#ifdef HAVE__PROC_MEMINFO |
||||
|
|
||||
|
/* Get memory information */ |
||||
|
static size_t get_sysmem(struct sys_memory *memall) { |
||||
|
FILE *fp; |
||||
|
char buffer[2048]; |
||||
|
size_t bytes_read; |
||||
|
char *match; |
||||
|
long mem_got; |
||||
|
|
||||
|
if((fp = fopen("/proc/meminfo", "r")) == NULL) { |
||||
|
perror("fopen(\"/proc/meminfo\")"); |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
bytes_read = fread (buffer, 1, sizeof (buffer), fp); |
||||
|
fclose (fp); |
||||
|
if (bytes_read == 0 || bytes_read == sizeof (buffer)) |
||||
|
return 0; |
||||
|
buffer[bytes_read] = '\0'; |
||||
|
|
||||
|
/* Search for string "MemTotal" */ |
||||
|
match = strstr (buffer, "MemTotal"); |
||||
|
if (match == NULL) /* not found */ |
||||
|
return 0; |
||||
|
sscanf (match, "MemTotal: %ld", &mem_got); |
||||
|
memall->size = mem_got*1024; /* 1MB = 1024KB */ |
||||
|
/* Search for string "MemFree" */ |
||||
|
match = strstr (buffer, "MemFree"); |
||||
|
if (match == NULL) /* not found */ |
||||
|
return 0; |
||||
|
sscanf (match, "MemFree: %ld", &mem_got); |
||||
|
memall->free = mem_got*1024; /* 1MB = 1024KB */ |
||||
|
/* Search for string "SwapTotal" */ |
||||
|
match = strstr (buffer, "SwapTotal"); |
||||
|
if (match == NULL) /* not found */ |
||||
|
return 0; |
||||
|
sscanf (match, "SwapTotal: %ld", &mem_got); |
||||
|
memall->swap_t = mem_got*1024; /* 1MB = 1024KB */ |
||||
|
/* Search for string "SwapFree" */ |
||||
|
match = strstr (buffer, "SwapFree"); |
||||
|
if (match == NULL) /* not found */ |
||||
|
return 0; |
||||
|
sscanf (match, "SwapFree: %ld", &mem_got); |
||||
|
memall->swap_f = mem_got*1024; /* 1MB = 1024KB */ |
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
/* Return length of first line in a string */ |
||||
|
tInt getLineLength(const char *str) { |
||||
|
tInt length = strlen(str); |
||||
|
char c = str[0]; |
||||
|
tInt index = 0; |
||||
|
|
||||
|
while((c != '\n') && (index < length)) { |
||||
|
index++; |
||||
|
c = str[index]; |
||||
|
} |
||||
|
return index; |
||||
|
} |
||||
|
|
||||
|
/* Checks if number 'match' is found in a vector 'set' of size 'size' |
||||
|
Returns 1 if yes, otherwise, 0 */ |
||||
|
tInt searchInSet(const tInt *set, tInt size, tInt match) { |
||||
|
tInt index; |
||||
|
for(index = 0; index < size; index++) { |
||||
|
if(match == set[index]) { |
||||
|
return 1; |
||||
|
} |
||||
|
} |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
TESAPI void TESAPIENTRY tesFreeSystemInfo(TesSystemInfo *info) { |
||||
|
if(info != NULL) { |
||||
|
free(info->cpuModelName); |
||||
|
free(info->osName); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* Get system information */ |
||||
|
TESAPI TesError TESAPIENTRY tesCreateSystemInfo(TesSystemInfo *info) { |
||||
|
FILE *file; |
||||
|
TesError error = TES_SUCCESS; |
||||
|
|
||||
|
if(info == NULL) |
||||
|
return TES_INVALID_PARAMS; |
||||
|
info->cpuModelName = NULL; |
||||
|
info->osName = NULL; |
||||
|
info->numLogicalProcessors = info->numPhysicalProcessors = 0; |
||||
|
|
||||
|
/* get kernel version string */ |
||||
|
file = fopen("/proc/version", "rb"); |
||||
|
if(file != NULL) { |
||||
|
tInt size = 0; |
||||
|
char buf; |
||||
|
|
||||
|
/* read bytes and find end of file */ |
||||
|
buf = fgetc(file); |
||||
|
while(buf != EOF) { |
||||
|
size++; |
||||
|
buf = fgetc(file); |
||||
|
} |
||||
|
|
||||
|
info->osName = malloc((size) * sizeof(char)); |
||||
|
rewind(file); |
||||
|
fread(info->osName, sizeof(char), size, file); |
||||
|
fclose(file); |
||||
|
|
||||
|
info->osName[size-1] = '\0'; |
||||
|
} |
||||
|
else { |
||||
|
error = TES_FAIL; |
||||
|
} |
||||
|
|
||||
|
/* get cpu information */ |
||||
|
file = fopen("/proc/cpuinfo", "rb"); |
||||
|
if(file != NULL) { |
||||
|
tInt size = 0; |
||||
|
char buf, *inStr; |
||||
|
|
||||
|
/* read bytes and find end of file */ |
||||
|
buf = fgetc(file); |
||||
|
while(buf != EOF) { |
||||
|
size++; |
||||
|
buf = fgetc(file); |
||||
|
} |
||||
|
/* get complete string */ |
||||
|
inStr = malloc((size+1) * sizeof(char)); |
||||
|
rewind(file); |
||||
|
fread(inStr, sizeof(char), size, file); |
||||
|
inStr[size] = '\0'; |
||||
|
|
||||
|
{ |
||||
|
const char *matchStr = "model name"; |
||||
|
/* pointer to first occurrence of model name*/ |
||||
|
const char *modelStr = strstr(inStr, matchStr); |
||||
|
if(modelStr != NULL) { |
||||
|
/* search for ':' */ |
||||
|
const char *modelPtr = strchr(modelStr, ':'); |
||||
|
if(modelPtr != NULL) { |
||||
|
/*length of string from ':' till end of line */ |
||||
|
tInt numToEOL = getLineLength(modelPtr); |
||||
|
if(numToEOL > 2) { |
||||
|
/* skip ": "*/ |
||||
|
numToEOL-=2; |
||||
|
info->cpuModelName = malloc(numToEOL+1); |
||||
|
memcpy(info->cpuModelName, modelPtr+2, numToEOL); |
||||
|
info->cpuModelName[numToEOL] = '\0'; |
||||
|
} |
||||
|
} |
||||
|
else { |
||||
|
error = TES_FAIL; |
||||
|
} |
||||
|
} |
||||
|
else { |
||||
|
error = TES_FAIL; |
||||
|
} |
||||
|
} |
||||
|
{ |
||||
|
const char *matchStrProc = "processor"; |
||||
|
const char *matchStrPhys = "physical id"; |
||||
|
char *strPtr = inStr; |
||||
|
tInt numProcs = 0; |
||||
|
tInt *physIDs; |
||||
|
|
||||
|
/* get number of logical processors */ |
||||
|
while((strPtr = strstr(strPtr, matchStrProc)) != NULL) { |
||||
|
numProcs++; |
||||
|
strPtr += strlen(matchStrProc); |
||||
|
} |
||||
|
info->numLogicalProcessors = numProcs; |
||||
|
physIDs = malloc(numProcs * sizeof(tInt)); |
||||
|
|
||||
|
/* get number of physical CPUs */ |
||||
|
numProcs = 0; |
||||
|
strPtr = inStr; |
||||
|
while((strPtr = strstr(strPtr, matchStrProc)) != NULL) { |
||||
|
|
||||
|
/* search for first occurrence of physical id */ |
||||
|
strPtr = strstr(strPtr, matchStrPhys); |
||||
|
if(strPtr != NULL) { |
||||
|
/* go to ';' */ |
||||
|
strPtr = strchr(strPtr, ':'); |
||||
|
if(strPtr != NULL) { |
||||
|
tInt buffer = 0; |
||||
|
/* skip ": " */ |
||||
|
strPtr += 2; |
||||
|
/* get number */ |
||||
|
sscanf(strPtr, "%d", &buffer); |
||||
|
/* If this physical id is unique, |
||||
|
we have another physically available CPU */ |
||||
|
if(searchInSet(physIDs, numProcs, buffer) == 0) { |
||||
|
physIDs[numProcs] = buffer; |
||||
|
numProcs++; |
||||
|
} |
||||
|
} |
||||
|
else { |
||||
|
// error = TES_FAIL; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
else { |
||||
|
// error = TES_FAIL; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
info->numPhysicalProcessors = numProcs; |
||||
|
free(physIDs); |
||||
|
} |
||||
|
|
||||
|
/* another test to get number of logical processors */ |
||||
|
if {info->numLogicalProcessors == 0) { |
||||
|
char* token; |
||||
|
char* cpustr = copy(inStr); |
||||
|
while (cpustr) |
||||
|
if cieq(gettok(&cpustr), "processor") { |
||||
|
gettok(&cpustr); |
||||
|
token = gettok(&cpustr); |
||||
|
} |
||||
|
|
||||
|
info->numLogicalProcessors = atoi(token) + 1; |
||||
|
tfree cpustr; |
||||
|
} |
||||
|
|
||||
|
free(inStr); |
||||
|
fclose(file); |
||||
|
} |
||||
|
else { |
||||
|
error = TES_FAIL; |
||||
|
} |
||||
|
|
||||
|
return error; |
||||
|
} |
||||
|
|
||||
|
#elif HAS_WINDOWS |
||||
|
|
||||
|
/* get memory information */ |
||||
|
static size_t get_sysmem(struct sys_memory *memall) { |
||||
|
#if ( _WIN32_WINNT >= 0x0500) |
||||
|
MEMORYSTATUSEX ms; |
||||
|
ms.dwLength = sizeof(MEMORYSTATUSEX); |
||||
|
GlobalMemoryStatusEx( &ms); |
||||
|
memall->size = ms.ullTotalPhys; |
||||
|
memall->free = ms.ullAvailPhys; |
||||
|
memall->swap_t = ms.ullTotalPageFile; |
||||
|
memall->swap_f = ms.ullAvailPageFile; |
||||
|
#else |
||||
|
MEMORYSTATUS ms; |
||||
|
ms.dwLength = sizeof(MEMORYSTATUS); |
||||
|
GlobalMemoryStatus( &ms); |
||||
|
memall->size = ms.dwTotalPhys; |
||||
|
memall->free = ms.dwAvailPhys; |
||||
|
memall->swap_t = ms.dwTotalPageFile; |
||||
|
memall->swap_f = ms.dwAvailPageFile; |
||||
|
#endif /*_WIN32_WINNT 0x0500*/ |
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
/* get system information */ |
||||
|
TesError tesCreateSystemInfo(TesSystemInfo *info) { |
||||
|
OSVERSIONINFOA version; |
||||
|
char *versionStr = NULL, *procStr, *freeStr; |
||||
|
tInt major, minor; |
||||
|
DWORD dwLen; |
||||
|
HKEY hkBaseCPU; |
||||
|
LONG lResult; |
||||
|
|
||||
|
SYSTEM_INFO sysinfo; |
||||
|
GetSystemInfo(&sysinfo); |
||||
|
|
||||
|
|
||||
|
info->numPhysicalProcessors = 0; |
||||
|
info->numLogicalProcessors = sysinfo.dwNumberOfProcessors; //atoi(getenv("NUMBER_OF_PROCESSORS")); |
||||
|
info->osName = NULL; |
||||
|
|
||||
|
version.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); |
||||
|
if(GetVersionExA(&version) == 0) { |
||||
|
return TES_FAIL; |
||||
|
} |
||||
|
major = version.dwMajorVersion; |
||||
|
minor = version.dwMinorVersion; |
||||
|
switch(major) { |
||||
|
case 4: |
||||
|
if(minor == 0) { |
||||
|
versionStr = "Windows 95/NT4.0"; |
||||
|
} |
||||
|
else if(minor == 10) { |
||||
|
versionStr = "Windows 98"; |
||||
|
} |
||||
|
else if (minor == 90) { |
||||
|
versionStr = "Windows ME"; |
||||
|
} |
||||
|
break; |
||||
|
case 5: |
||||
|
if(minor == 0) { |
||||
|
versionStr = "Windows 2000"; |
||||
|
} |
||||
|
else if(minor == 1) { |
||||
|
versionStr = "Windows XP"; |
||||
|
} |
||||
|
else if(minor == 2) { |
||||
|
versionStr = "Windows Server 2003"; |
||||
|
} |
||||
|
break; |
||||
|
case 6: |
||||
|
if(minor == 0) { |
||||
|
versionStr = "Windows Vista"; |
||||
|
} |
||||
|
break; |
||||
|
default: |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
if(versionStr != NULL) { |
||||
|
tInt lengthCSD = strlen(version.szCSDVersion); |
||||
|
tInt lengthVer = strlen(versionStr); |
||||
|
|
||||
|
info->osName = malloc(lengthVer + lengthCSD + 2); |
||||
|
memcpy(info->osName, versionStr, lengthVer); |
||||
|
memcpy(info->osName + lengthVer + 1, version.szCSDVersion, lengthCSD); |
||||
|
info->osName[lengthVer] = ' '; |
||||
|
info->osName[lengthVer + lengthCSD + 1] = '\0'; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
lResult = RegOpenKeyExA(HKEY_LOCAL_MACHINE, |
||||
|
"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", |
||||
|
0,KEY_READ,&hkBaseCPU); |
||||
|
if(lResult != ERROR_SUCCESS) { |
||||
|
info->cpuModelName = NULL; |
||||
|
return TES_FAIL; |
||||
|
} |
||||
|
|
||||
|
RegQueryValueExA(hkBaseCPU,"ProcessorNameString",0,0,NULL,&dwLen); |
||||
|
freeStr = procStr = tmalloc(dwLen+1); |
||||
|
RegQueryValueExA(hkBaseCPU,"ProcessorNameString",0,0,(LPBYTE)procStr,&dwLen); |
||||
|
procStr[dwLen] = '\0'; |
||||
|
while (*procStr == ' ') procStr++; |
||||
|
info->cpuModelName = copy(procStr); |
||||
|
tfree(freeStr); |
||||
|
|
||||
|
RegCloseKey(hkBaseCPU); |
||||
|
|
||||
|
return TES_SUCCESS; |
||||
|
} |
||||
|
|
||||
|
#else |
||||
|
/* no Windows OS, no proc info file system */ |
||||
|
TesError tesCreateSystemInfo(TesSystemInfo *info) { |
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
#endif |
||||
|
|
||||
16264
visualc/vngspice.vcproj
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
Write
Preview
Loading…
Cancel
Save
Reference in new issue