/* PIP - Platform Independent Primitives Initialization Ivan Pelipenko peri4ko@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "piincludes_p.h" #include "piinit.h" #ifndef MICRO_PIP #include "pitime.h" #include "pisignals.h" #include "piobject.h" #include "pisysteminfo.h" #include "piresourcesstorage.h" #include "pidir.h" #include "piprocess.h" #ifdef ESP_PLATFORM # include "esp_system.h" #endif #include #ifdef WINDOWS # include extern FILETIME __pi_ftjan1970; extern PINtQueryTimerResolution getTimerResolutionAddr; extern PINtSetTimerResolution setTimerResolutionAddr; void __PISetTimerResolution() { if (setTimerResolutionAddr == NULL || getTimerResolutionAddr == NULL) return; ULONG _max(0), _min(0), _cur(0); //printf("getTimerResolution ...\n"); LONG q = getTimerResolutionAddr(&_max, &_min, &_cur); //printf("getTimerResolution %d %lu %lu %lu\n", q, _min, _max, _cur); if (q == 0) setTimerResolutionAddr(_min, TRUE, &_cur); //printf("setTimerResolution %lu\n", cur); } #else # include # include # include # ifdef BLACKBERRY # include # else # include # endif #endif #ifdef MAC_OS # include # include # include extern clock_serv_t __pi_mac_clock; #endif #ifdef PIP_ICU # define U_NOEXCEPT # include # include #endif #ifdef HAS_LOCALE static locale_t currentLocale_t = 0; #endif PRIVATE_DEFINITION_START(PIInit) #ifdef WINDOWS HMODULE ntlib; ULONG prev_res; #endif bool delete_locs; PRIVATE_DEFINITION_END(PIInit) void __sighandler__(PISignals::Signal s) { //piCout << Hex << int(s); if (s == PISignals::StopTTYInput || s == PISignals::StopTTYOutput) piMSleep(10); if (s == PISignals::UserDefined1) dumpApplicationToFile(PIDir::home().path() + PIDir::separator + PIStringAscii("_PIP_DUMP_") + PIString::fromNumber(PIProcess::currentPID())); } #ifdef ANDROID void android_thread_exit_handler(int sig) { pthread_exit(0); } #endif PIInit::PIInit() { file_charset = 0; PISystemInfo * sinfo = PISystemInfo::instance(); sinfo->execDateTime = PIDateTime::current(); setFileCharset("UTF-8"); #ifndef ANDROID PISignals::setSlot(__sighandler__); PISignals::grabSignals(PISignals::UserDefined1); # ifndef WINDOWS PISignals::grabSignals(PISignals::StopTTYInput | PISignals::StopTTYOutput); sigset_t ss; sigemptyset(&ss); sigaddset(&ss, SIGALRM); sigprocmask(SIG_BLOCK, &ss, 0); pthread_sigmask(SIG_BLOCK, &ss, 0); signal(SIGPIPE, SIG_IGN); PIStringList ifpathes; ifpathes << PIStringAscii("/bin/ifconfig") << PIStringAscii("/sbin/ifconfig") << PIStringAscii("/usr/bin/ifconfig") << PIStringAscii("/usr/sbin/ifconfig"); piForeachC (PIString & i, ifpathes) { if (fileExists(i)) { sinfo->ifconfigPath = i; break; } } # else //WINDOWS // OS version DWORD dwVersion = GetVersion(); DWORD dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); DWORD dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion))); sinfo->OS_version = PIString::fromNumber(dwMajorVersion) + "." + PIString::fromNumber(dwMinorVersion); // WinSock inint WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); // Timers init SYSTEMTIME jan1970 = {1970, 1, 4, 1, 0, 0, 0, 0}; SystemTimeToFileTime(&jan1970, &__pi_ftjan1970); LARGE_INTEGER pf; pf.QuadPart = -1; if (QueryPerformanceFrequency(&pf) != 0) __pi_perf_freq = pf.QuadPart; if (__pi_perf_freq == 0) __pi_perf_freq = -1; // Sleep precision init PRIVATE->ntlib = LoadLibrary("ntdll.dll"); if (PRIVATE->ntlib) { getTimerResolutionAddr = (PINtQueryTimerResolution)GetProcAddress(PRIVATE->ntlib, "NtQueryTimerResolution"); setTimerResolutionAddr = (PINtSetTimerResolution)GetProcAddress(PRIVATE->ntlib, "NtSetTimerResolution"); __PISetTimerResolution(); } # endif //WINDOWS # ifdef HAS_LOCALE //std::cout << "has locale" << std::endl; if (currentLocale_t != 0) { freelocale(currentLocale_t); currentLocale_t = 0; } currentLocale_t = newlocale(LC_ALL, setlocale(LC_ALL, "C"), 0); setlocale(LC_CTYPE, "en_US.UTF-8"); //std::ios_base::sync_with_stdio(false); //std::locale utf8( std::locale(), new std::codecvt_utf8 ); //std::wcout.imbue(utf8); # else //HAS_LOCALE setlocale(LC_ALL, ""); setlocale(LC_NUMERIC, "C"); # endif //HAS_LOCALE #else //ANDROID struct sigaction actions; memset(&actions, 0, sizeof(actions)); sigemptyset(&actions.sa_mask); actions.sa_flags = 0; actions.sa_handler = android_thread_exit_handler; sigaction(SIGTERM, &actions, 0); #endif //ANDROID PRIVATE->delete_locs = false; __syslocname__ = __sysoemname__ = 0; __utf8name__ = const_cast("UTF-8"); #ifdef PIP_ICU UErrorCode e((UErrorCode)0); u_init(&e); # ifdef WINDOWS PRIVATE->delete_locs = true; CPINFOEX cpinfo; int l = 0; GetCPInfoEx(CP_OEMCP, 0, &cpinfo); for (l = 0; l < MAX_PATH; ++l) if (cpinfo.CodePageName[l] == '\0' || cpinfo.CodePageName[l] == ' ') break; __sysoemname__ = new char[256]; memset(__sysoemname__, 0, 256); memcpy(__sysoemname__, "ibm-", 4); memcpy(&(__sysoemname__[4]), cpinfo.CodePageName, l); # else /*PIString en(getenv("LANG")); if (!en.isEmpty()) en = en.mid(en.find(".") + 1); PIByteArray enba = en.toByteArray(); memcpy(__syslocname__, enba.data(), enba.size_s());*/ # endif //piCout << __syslocname__; //piCout << __sysoemname__; #else //PIP_ICU # ifdef WINDOWS __syslocname__ = (char *)CP_ACP; __sysoemname__ = (char *)CP_OEMCP; __utf8name__ = (char *)CP_UTF8; # endif #endif //PIP_ICU #ifdef MAC_OS host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &__pi_mac_clock); #endif char cbuff[1024]; memset(cbuff, 0, 1024); if (gethostname(cbuff, 1023) == 0) { sinfo->hostname = cbuff; } #ifdef WINDOWS SYSTEM_INFO sysinfo; GetSystemInfo(&sysinfo); sinfo->processorsCount = sysinfo.dwNumberOfProcessors; switch (sysinfo.wProcessorArchitecture) { case PROCESSOR_ARCHITECTURE_AMD64: sinfo->architecture = PIStringAscii("x86_64"); break; case PROCESSOR_ARCHITECTURE_ARM: sinfo->architecture = PIStringAscii("arm"); break; case PROCESSOR_ARCHITECTURE_IA64: sinfo->architecture = PIStringAscii("Intel Itanium-based"); break; case PROCESSOR_ARCHITECTURE_INTEL: sinfo->architecture = PIStringAscii("x86"); break; case PROCESSOR_ARCHITECTURE_UNKNOWN: default: sinfo->architecture = PIStringAscii("unknown"); break; } int argc_(0); wchar_t ** argv_ = CommandLineToArgvW(GetCommandLineW(), &argc_); if (argc_ > 0 && argv_ != 0) sinfo->execCommand = argv_[0]; LocalFree(argv_); memset(cbuff, 0, 1024); ulong unlen = 1023; if (GetUserName(cbuff, &unlen) != 0) sinfo->user = cbuff; #else //WINDOWS sinfo->processorsCount = piMaxi(1, int(sysconf(_SC_NPROCESSORS_ONLN))); passwd * ps = getpwuid(getuid()); if (ps) sinfo->user = ps->pw_name; else { memset(cbuff, 0, 1024); char * l = getlogin(); if (l) sinfo->user = l; } struct utsname uns; if (uname(&uns) == 0) { sinfo->OS_version = uns.release; sinfo->architecture = uns.machine; } #endif //WINDOWS #ifdef ESP_PLATFORM esp_chip_info_t chip_info; esp_chip_info(&chip_info); sinfo->processorsCount = chip_info.cores; sinfo->architecture = "Xtensa LX6"; //printf("silicon revision %d, ", chip_info.revision); sinfo->OS_version = esp_get_idf_version(); #endif sinfo->OS_name = #ifdef WINDOWS PIStringAscii("Windows"); #elif defined(QNX) PIStringAscii("QNX"); #elif defined(MAC_OS) PIStringAscii("MacOS"); #elif defined(ANDROID) PIStringAscii("Android"); #elif defined(FREE_BSD) PIStringAscii("FreeBSD"); #elif defined(FREERTOS) PIStringAscii("FreeRTOS"); #elif defined(MICRO_PIP) PIStringAscii("MicroPIP"); #else uns.sysname; #endif } PIInit::~PIInit() { if (file_charset) delete[] file_charset; file_charset = 0; PIResourcesStorage::instance()->clear(); #ifdef WINDOWS WSACleanup(); if (PRIVATE->ntlib) FreeLibrary(PRIVATE->ntlib); PRIVATE->ntlib = 0; #endif #ifdef MAC_OS mach_port_deallocate(mach_task_self(), __pi_mac_clock); #endif if (PRIVATE->delete_locs) { if (__syslocname__) delete __syslocname__; if (__sysoemname__) delete __sysoemname__; } #ifdef PIP_ICU u_cleanup(); #endif } bool PIInit::isBuildOptionEnabled(PIInit::BuildOption o) { switch (o) { case boICU: return #ifdef PIP_ICU true; #else false; #endif case boUSB: return #ifdef PIP_USB true; #else false; #endif case boCrypt: return #ifdef PIP_CRYPT true; #else false; #endif case boIntrospection: return #ifdef PIP_INTROSPECTION true; #else false; #endif case boFFTW: return #ifdef PIP_FFTW true; #else false; #endif case boCompress: return #ifdef PIP_COMPRESS true; #else false; #endif case boOpenCL: return #ifdef PIP_OPENCL true; #else false; #endif case boCloud: return #ifdef PIP_CLOUD true; #else false; #endif default: return false; } return false; } PIStringList PIInit::buildOptions() { PIStringList ret; if (isBuildOptionEnabled(boICU)) ret << "ICU"; if (isBuildOptionEnabled(boUSB)) ret << "USB"; if (isBuildOptionEnabled(boCrypt)) ret << "Crypt"; if (isBuildOptionEnabled(boIntrospection)) ret << "Introspection"; if (isBuildOptionEnabled(boFFTW)) ret << "FFTW"; if (isBuildOptionEnabled(boCompress)) ret << "Compress"; if (isBuildOptionEnabled(boOpenCL)) ret << "OpenCL"; if (isBuildOptionEnabled(boCloud)) ret << "Cloud"; return ret; } void PIInit::setFileCharset(const char *charset) { if (file_charset) delete file_charset; file_charset = 0; if (charset) { file_charset = new char[1024]; memset(file_charset, 0, 1024); strcpy(file_charset, charset); } } bool PIInit::fileExists(const PIString & p) { FILE * f = fopen(p.data(), "r"); if (f == 0) return false; fclose(f); return true; } int __PIInit_Initializer__::count_(0); PIInit * __PIInit_Initializer__::__instance__(0); __PIInit_Initializer__::__PIInit_Initializer__() { count_++; if (count_ > 1) return; //piCout << "create PIInit"; __instance__ = new PIInit(); } __PIInit_Initializer__::~__PIInit_Initializer__() { count_--; if (count_ > 0) return; //piCout << "delete PIInit"; if (__instance__ != 0) { delete __instance__; __instance__ = 0; } } #endif // MICRO_PIP