2
Copyright (c) 2008, 2009 Jussi Pakkanen
4
Разрешается повторное распространение и использование как в виде исходного кода,
5
так и в двоичной форме, с изменениями или без, при соблюдении следующих условий:
7
* При повторном распространении исходного кода должны оставаться указанное
8
выше уведомление об авторском праве, этот список условий и последующий
10
* При повторном распространении двоичного кода в документации и/или в
11
других материалах, поставляемых при распространении, должны сохраняться
12
указанная выше информация об авторском праве, этот список условий и
13
последующий отказ от гарантий.
14
* Ни название Cognitive Technologies, ни имена ее сотрудников не могут
15
быть использованы в качестве средства поддержки и/или продвижения
16
продуктов, основанных на этом ПО, без предварительного письменного
19
ЭТА ПРОГРАММА ПРЕДОСТАВЛЕНА ВЛАДЕЛЬЦАМИ АВТОРСКИХ ПРАВ И/ИЛИ ДРУГИМИ ЛИЦАМИ "КАК
20
ОНА ЕСТЬ" БЕЗ КАКОГО-ЛИБО ВИДА ГАРАНТИЙ, ВЫРАЖЕННЫХ ЯВНО ИЛИ ПОДРАЗУМЕВАЕМЫХ,
21
ВКЛЮЧАЯ ГАРАНТИИ КОММЕРЧЕСКОЙ ЦЕННОСТИ И ПРИГОДНОСТИ ДЛЯ КОНКРЕТНОЙ ЦЕЛИ, НО НЕ
22
ОГРАНИЧИВАЯСЬ ИМИ. НИ ВЛАДЕЛЕЦ АВТОРСКИХ ПРАВ И НИ ОДНО ДРУГОЕ ЛИЦО, КОТОРОЕ
23
МОЖЕТ ИЗМЕНЯТЬ И/ИЛИ ПОВТОРНО РАСПРОСТРАНЯТЬ ПРОГРАММУ, НИ В КОЕМ СЛУЧАЕ НЕ
24
НЕСЁТ ОТВЕТСТВЕННОСТИ, ВКЛЮЧАЯ ЛЮБЫЕ ОБЩИЕ, СЛУЧАЙНЫЕ, СПЕЦИАЛЬНЫЕ ИЛИ
25
ПОСЛЕДОВАВШИЕ УБЫТКИ, СВЯЗАННЫЕ С ИСПОЛЬЗОВАНИЕМ ИЛИ ПОНЕСЕННЫЕ ВСЛЕДСТВИЕ
26
НЕВОЗМОЖНОСТИ ИСПОЛЬЗОВАНИЯ ПРОГРАММЫ (ВКЛЮЧАЯ ПОТЕРИ ДАННЫХ, ИЛИ ДАННЫЕ,
27
СТАВШИЕ НЕГОДНЫМИ, ИЛИ УБЫТКИ И/ИЛИ ПОТЕРИ ДОХОДОВ, ПОНЕСЕННЫЕ ИЗ-ЗА ДЕЙСТВИЙ
28
ТРЕТЬИХ ЛИЦ И/ИЛИ ОТКАЗА ПРОГРАММЫ РАБОТАТЬ СОВМЕСТНО С ДРУГИМИ ПРОГРАММАМИ,
29
НО НЕ ОГРАНИЧИВАЯСЬ ЭТИМИ СЛУЧАЯМИ), НО НЕ ОГРАНИЧИВАЯСЬ ИМИ, ДАЖЕ ЕСЛИ ТАКОЙ
30
ВЛАДЕЛЕЦ ИЛИ ДРУГОЕ ЛИЦО БЫЛИ ИЗВЕЩЕНЫ О ВОЗМОЖНОСТИ ТАКИХ УБЫТКОВ И ПОТЕРЬ.
32
Redistribution and use in source and binary forms, with or without modification,
33
are permitted provided that the following conditions are met:
35
* Redistributions of source code must retain the above copyright notice,
36
this list of conditions and the following disclaimer.
37
* Redistributions in binary form must reproduce the above copyright notice,
38
this list of conditions and the following disclaimer in the documentation
39
and/or other materials provided with the distribution.
40
* Neither the name of the Cognitive Technologies nor the names of its
41
contributors may be used to endorse or promote products derived from this
42
software without specific prior written permission.
44
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
45
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
46
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
47
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
48
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
50
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
51
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
52
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
53
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
57
#include <sys/types.h>
66
/* Minimal implementations of win32-functionality.
67
* Eventually these should be rewritten in standard POSIX.
69
* At the end of the file are some helper functions, which should be used
75
#include <sys/types.h>
83
#if defined(__APPLE__) && defined(__MACH__)
84
#include <malloc/malloc.h>
85
#define malloc_usable_size(a) malloc_size(a)
87
#elif defined(__FreeBSD__)
88
#include <malloc_np.h>
94
#include "compat_defs.h"
96
CFCOMPAT_FUNC(int) HFILE_ERROR;
98
int LoadString(HINSTANCE hInstance, uint uID, char* lpBuffer, int nBufferMax) {
102
int CreateDirectory(const char *dir, void *dummy) {
103
if (!mkdir(dir, 0755))
109
uint32_t GetTempPath(uint32_t nBufferLength, char* lpBuffer) {
110
strcpy(lpBuffer, "/tmp");
111
return strlen(lpBuffer);
114
int RemoveDirectory(const char *d) {
118
void* GlobalAlloc(uint uFlags, int dwBytes) {
119
if (uFlags & GMEM_ZEROINIT)
120
return calloc(dwBytes, 1);
121
return malloc(dwBytes);
124
HGLOBAL GlobalFree(void *f) {
129
void* GlobalReAlloc(void* hMem, int dwBytes, uint uFlags) {
130
return realloc(hMem, dwBytes); // Should init to zero on uFlags & GMEM_ZEROINIT.
133
int GetTempFileName(const char * lpPathName, const char * lpPrefixString, uint uUnique,
134
char* lpTempFileName) {
142
uint32_t GetModuleFileName(HMODULE hModule, char* lpFilename, uint32_t nSize) {
143
lpFilename[0] = '.'; /* Currently all modules must be in the directory pumatest was run in. */
144
lpFilename[1] = '\0';
148
Bool CloseHandle(HANDLE hObject) {
152
HANDLE CreateFile(const char * lpFileName, uint32_t dwDesiredAccess,
153
uint32_t dwShareMode, void* lpSecurityAttributes,
154
uint32_t dwCreationDisposition, uint32_t dwFlagsAndAttributes,
155
HANDLE hTemplateFile) {
159
HWND FindWindow(const char * lpClassName, const char * lpWindowName) {
163
uint RegisterWindowMessage(const char * lpString) {
167
int _findclose(long handle);
168
long _findfirst(const char *filespec, struct _finddata_t *fileinfo);
169
int _findnext(long handle, struct _finddata_t *fileinfo);
170
long _tell(int handle) {
171
return lseek(handle, 0, SEEK_CUR);
174
Bool GetComputerName(char* lpBuffer, long unsigned int *lpnSize) {
175
strncpy(lpBuffer, "CompName", *lpnSize);
176
*lpnSize = strlen(lpBuffer);
180
int32_t RegOpenKeyEx(HKEY hKey, const char * lpSubKey, uint32_t ulOptions,
181
REGSAM samDesired, PHKEY phkResult) {
185
int32_t RegQueryValueEx(HKEY hKey, const char * lpValueName, LPDWORD lpReserved,
186
LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData) {
190
Bool GetClientRect(HWND hWnd, LPRECT lpRect) {
194
Bool WritePrivateProfileString(const char * lpAppName, const char * lpKeyName,
195
const char * lpString, const char * lpFileName) {
199
uint32_t GetPrivateProfileString(const char * lpAppName, const char * lpKeyName,
200
const char * lpDefault, char* lpReturnedString, uint32_t nSize,
201
const char * lpFileName) {
205
uint GetPrivateProfileInt(const char * lpAppName, const char * lpKeyName, int16_t nDefault,
206
const char * lpFileName) {
210
int WideCharToMultiByte(uint CodePage, uint32_t dwFlags,
211
const wchar_t *lpWideCharStr, int cchWideChar, char* lpMultiByteStr,
212
int cbMultiByte, const char * lpDefaultChar, pBool lpUsedDefaultChar) {
215
Bool ShowWindow(HWND hWnd, int nCmdShow) {
219
long _filelength(int fd) {
221
if (fstat(fd, &foo) != 0) {
227
long filelength(int fd) {
228
return _filelength(fd);
231
long _msize(void *memblock) {
232
return malloc_usable_size(memblock);
235
/* All uses in Cuneiform just check if the file exists. Ignoring all other
238
int _access(const char *filename, int mode) {
241
return stat(filename, &foo);
244
Bool SetWindowText(HWND hWnd, const char * lpString) {
248
int ReleaseDC(HWND hWnd, HDC hDC) {
252
Bool IsIconic(HWND hWnd) {
256
HDC GetDC(HWND hWnd) {
260
Bool EndPaint(HWND hWnd, ...) {
264
HDC BeginPaint(HWND hwnd, ...) {
268
LRESULT SendMessage(HWND hWnd, uint Msg, WPARAM wParam, LPARAM lParam) {
273
void strlwr(char *foo) {
274
// FIXME: this is probably actually used somewhere.
278
HWND CreateWindow(const char * lpClassName, const char * lpWindowName, uint32_t dwStyle,
279
int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu,
280
HINSTANCE hInstance, pvoid lpParam) {
284
HGDIOBJ SelectObject(HDC hdc, HGDIOBJ hgdiobj) {
288
char* lstrcat(char* lpString1, char* lpString2) {
289
return strcat(lpString1, lpString2);
292
int lstrlen(const char * lpString) {
293
return strlen(lpString);
296
int lstrcmp(const char * lpString1, const char * lpString2) {
297
return strcmp(lpString1, lpString2);
300
char* lstrcpy(char* lpString1, const char * lpString2) {
301
return strcpy(lpString1, lpString2);
304
int wsprintf(char* lpOut, const char * lpFmt, ...) {
308
va_start (args, lpFmt);
309
ret = vsprintf(lpOut, lpFmt, args);
316
int lstrcmpi(const char * lpString1, const char * lpString2) {
317
return strcasecmp(lpString1, lpString2);
320
Bool DeleteObject(HGDIOBJ hObject) {
328
int MessageBox(HWND hWnd, const char * lpText, const char * lpCaption, uint uType) {
329
fprintf(stderr, "MessageBox %s: %s\n", lpCaption, lpText);
333
int WINAPI GlobalSize(HGLOBAL hMem) {
337
pvoid GlobalLock(HGLOBAL hMem) {
341
Bool GlobalUnlock(HGLOBAL hMem) {
345
Bool IsBadWritePtr(pvoid lp, int ucb) {
349
void OutputDebugString(const char * lpOutputString) {
353
Bool SetRect(LPRECT lprc, int xLeft, int yTop, int xRight, int yBottom) {
355
lprc->right = xRight;
357
lprc->bottom = yBottom;
361
Bool PtInRect(const RECT *lprc, POINT pt) {
362
if (pt.x >= lprc->left && pt.x < lprc->right && pt.y >= lprc->top && pt.y
368
/* This is only called from creatertf.cpp. It does not use lprcDst at all so
369
* we do not need to calculate it.
372
Bool IntersectRect(LPRECT lprcDst, const RECT *lprcSrc1, const RECT *lprcSrc2) {
373
if (lprcSrc1->left > lprcSrc2->right || lprcSrc1->right < lprcSrc2->left
374
|| lprcSrc1->top > lprcSrc2->bottom || lprcSrc1->bottom
380
Bool UnionRect(LPRECT lprcDst, const RECT *lprcSrc1, const RECT *lprcSrc2) {
381
if (lprcSrc1->left - lprcSrc1->right == 0 || lprcSrc1->top
382
- lprcSrc1->bottom == 0) {
383
lprcDst->left = lprcSrc2->left;
384
lprcDst->right = lprcSrc2->right;
385
lprcDst->top = lprcSrc2->top;
386
lprcDst->bottom = lprcSrc2->bottom;
389
if (lprcSrc2->left - lprcSrc2->right == 0 || lprcSrc2->top
390
- lprcSrc2->bottom == 0) {
391
lprcDst->left = lprcSrc1->left;
392
lprcDst->right = lprcSrc1->right;
393
lprcDst->top = lprcSrc1->top;
394
lprcDst->bottom = lprcSrc1->bottom;
398
lprcDst->left = lprcSrc1->left < lprcSrc2->left ? lprcSrc1->left
400
lprcDst->right = lprcSrc1->right > lprcSrc2->right ? lprcSrc1->right
402
lprcDst->top = lprcSrc1->top < lprcSrc2->top ? lprcSrc1->top
404
lprcDst->bottom = lprcSrc1->bottom > lprcSrc2->bottom ? lprcSrc1->bottom
410
HWND GetActiveWindow() {
414
HFONT CreateFont(int nHeight, int nWidth, int nEscapement, int nOrientation,
415
int fnWeight, uint32_t fdwItalic, uint32_t fdwUnderline,
416
uint32_t fdwStrikeOut, uint32_t fdwCharSet,
417
uint32_t fdwOutputPrecision, uint32_t fdwClipPrecision,
418
uint32_t fdwQuality, uint32_t fdwPitchAndFamily, const char * lpszFace) {
422
Bool GetTextExtentPoint32(HDC hdc, const char * lpString, int c, LPSIZE lpSize) {
426
Bool EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam) {
430
int GetWindowText(HWND hWnd, char* lpString, int nMaxCount) {
434
HMODULE LoadLibrary(const char * lpFileName) {
435
return dlopen(lpFileName, RTLD_LAZY);
438
Bool FreeLibrary(HMODULE hModule) {
439
return dlclose(hModule);
442
void* GetProcAddress(HMODULE hModule, const char * lpProcName) {
443
return dlsym(hModule, lpProcName);
446
HGDIOBJ GetStockObject(int fnObject) {
450
Bool IsWindowVisible(HWND hWnd) {
454
LRESULT DefWindowProc(HWND hWnd, uint Msg, WPARAM wParam, LPARAM lParam) {
458
int32_t GetWindowLong(HWND hWnd, int nIndex) {
462
Bool RegisterClass(const WNDCLASS *lpWndClass) {
466
HMODULE GetModuleHandle(const char * lpModuleName) {
470
HICON LoadIcon(HINSTANCE hInstance, const char * lpIconName) {
474
int LoadCursor(HINSTANCE hInstance, const char * lpCursorName) {
478
Bool Rectangle(HDC hdc, int nLeftRect, int nTopRect, int nRightRect,
483
/* String to uppercase. */
485
char* _strupr(char*s) {
498
static HMODULE thismod;
501
WINAPI DllMain(HINSTANCE hinstDLL, uint32_t fdwReason, pvoid lpvReserved) {
502
thismod = (HMODULE) hinstDLL;
507
mkdtemp(char *tmpl) {
508
static const char charset[] =
509
"=#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
510
static const unsigned int charset_len = sizeof(charset) - 1;
512
const int len = strlen (tmpl);
513
char* x_tail = tmpl + len - 6;
514
LARGE_INTEGER rand_seed;
515
uint64_t value = rand_seed.QuadPart ^ GetCurrentThreadId();
516
unsigned int cnt = 0;
520
if(memcmp(x_tail, "XXXXXX", 6))
523
QueryPerformanceCounter(&rand_seed);
526
uint64_t val = value;
527
char* x_char = x_tail;
529
*x_char++ = charset[val % charset_len];
532
if (CreateDirectory (tmpl, NULL))
534
if (ERROR_ALREADY_EXISTS != GetLastError())
538
}while (cnt < TMP_MAX);
545
/* General helper functions. */
547
static const char *separator = "/"; /* Yes, on Windows too. */
551
static void get_install_path(char *path) {
552
const int psize = 128;
553
char modulepath[128]; /* MSVC fails when psize is put in these brackets. */
557
GetModuleFileName(thismod, modulepath, psize);
558
winpath_to_internal(modulepath);
559
split_path(modulepath, path, fname, suffix);
564
static void get_install_path(char *path) {
565
strcat(path, INSTALL_DATADIR);
570
/* We try to locate data files in two locations:
572
* 1. At the directory pointed to by environment variable CF_DATADIR
573
* 2. At a platform-dependent install location
575
* Caller's responsibility is to ensure *e1 and *e2 are large enough.
579
static void build_name_estimates(const char *base_name, char *env_name,
581
const char *env_prefix;
582
const char *varname = "CF_DATADIR";
586
prefix_name[0] = '\0';
588
env_prefix = getenv(varname);
590
len = strlen(env_prefix);
592
strcat(env_name, env_prefix);
593
if (strcmp(env_prefix + len - 1, separator) != 0) {
594
strcat(env_name, separator);
596
strcat(env_name, base_name);
599
get_install_path(prefix_name);
600
if (strlen(prefix_name) > 0) {
601
strcat(prefix_name, separator);
602
strcat(prefix_name, base_name);
607
open_data_file(const char *basename, int mode) {
612
build_name_estimates(basename, ename, pname);
613
i = open(ename, mode);
616
return open(pname, mode);
620
data_file_exists(const char *basename) {
624
build_name_estimates(basename, ename, pname);
625
if(_access(ename, 0) == 0)
627
return _access(pname, 0);
630
/* Split a file name in three: path, base file name, and extension.
631
* All internal file names use / as path separator, even on Windows.
634
split_path(const char *fname, char *file_path, char *basename, char *ext) {
637
size_t l = strlen(fname);
638
int path_end, base_start, base_end, ext_start;
644
for (i = 0; i < l; i++) {
653
if (last_path == 0) { // File in root.
658
path_end = last_path;
659
base_start = last_path + 1;
662
if (suff > last_path) {
663
ext_start = suff + 1;
666
base_end = ext_start = l;
669
memcpy(file_path, fname, path_end);
670
file_path[path_end] = '\0';
671
memcpy(basename, fname + base_start, base_end - base_start);
672
basename[base_end - base_start] = '\0';
673
memcpy(ext, fname + ext_start, l - ext_start);
674
ext[l - ext_start] = '\0';
678
make_path(char *opath, const char *dir, const char *basename, const char *ext) {
679
const char dirsep = '/';
680
const char *dirseps = "/";
685
if(opath[strlen(opath) - 1] != dirsep) {
686
strcat(opath, dirseps);
691
strcat(opath, basename);
701
* Convert backslashes to slashes. No-op on UNIX.
704
winpath_to_internal(char *p) {
707
for(i=0; p[i] != '\0'; i++) {
714
/* Get current working directory. */
716
CFCOMPAT_FUNC(unsigned int) curr_dir(unsigned int bsize, char* buf) {
722
winpath_to_internal(buf);
730
CFCOMPAT_FUNC (FILE*)
731
create_temp_file(void) {
732
char temppath[BUFSIZE];
733
char tempfname[BUFSIZE];
736
retval = GetTempPath(BUFSIZE, temppath);
737
if(retval >= BUFSIZE || retval == 0)
740
if(GetTempFileName(temppath, "CF", 0, tempfname) == 0)
743
return fopen(tempfname, "w+bD");
748
CFCOMPAT_FUNC (FILE*)
749
create_temp_file(void) {
752
char* pattrn = malloc(100);
753
strcpy(pattrn, "/tmp/CF.XXXXXX");
755
tmp_fd = mkstemp(pattrn);
757
/* unlink file immediatly, it gets unlinked when file descriptor is closed */
764
if (!(tmp_file = fdopen(tmp_fd, "w+b"))) {