fixed some signed/unsigned warnings; added gamma control via SDL
This was SVN commit r258.
This commit is contained in:
parent
cf5e2524c2
commit
df6fceba62
@ -58,7 +58,40 @@ u32 fnv_hash(const void* buf, const size_t len)
|
||||
}
|
||||
|
||||
|
||||
// FNV1-A hash - good for strings.
|
||||
// if len = 0 (default), treat buf as a C-string;
|
||||
// otherwise, hash <len> bytes of buf.
|
||||
u64 fnv_hash64(const void* buf, const size_t len)
|
||||
{
|
||||
u64 h = 0xCBF29CE484222325;
|
||||
// give distinct values for different length 0 buffers.
|
||||
// value taken from FNV; it has no special significance.
|
||||
|
||||
const u8* p = (const u8*)buf;
|
||||
|
||||
// expected case: string
|
||||
if(!len)
|
||||
{
|
||||
while(*p)
|
||||
{
|
||||
h ^= *p++;
|
||||
h *= 0x100000001B3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t bytes_left = len;
|
||||
while(bytes_left != 0)
|
||||
{
|
||||
h ^= *p++;
|
||||
h *= 0x100000001B3;
|
||||
|
||||
bytes_left--;
|
||||
}
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
void bswap32(const u8* data, int cnt)
|
||||
@ -173,6 +206,26 @@ float fminf(float a, float b)
|
||||
|
||||
|
||||
|
||||
long round(double x)
|
||||
{
|
||||
return (long)(x + 0.5);
|
||||
}
|
||||
|
||||
// input in [0, 1); convert to u16 range
|
||||
u16 fp_to_u16(double in)
|
||||
{
|
||||
if(!(0 <= in && in < 1.0))
|
||||
{
|
||||
debug_warn("clampf not in [0,1)");
|
||||
return 65535;
|
||||
}
|
||||
|
||||
long l = round(in * 65535.0);
|
||||
assert((unsigned long)l <= 65535);
|
||||
return (u16)l;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// big endian!
|
||||
void base32(const int len, const u8* in, u8* out)
|
||||
|
@ -32,6 +32,7 @@
|
||||
// if len = 0 (default), treat buf as a C-string;
|
||||
// otherwise, hash <len> bytes of buf.
|
||||
extern u32 fnv_hash(const void* buf, const size_t len = 0);
|
||||
extern u64 fnv_hash64(const void* buf, const size_t len);
|
||||
|
||||
// hash (currently FNV) of a filename
|
||||
typedef u32 FnHash;
|
||||
@ -104,6 +105,8 @@ extern float fminf(float, float);
|
||||
|
||||
|
||||
|
||||
extern long round(double);
|
||||
extern u16 fp_to_u16(double in);
|
||||
|
||||
// big endian!
|
||||
extern void base32(const int len, const u8* in, u8* out);
|
||||
|
@ -22,3 +22,5 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include <numeric>
|
||||
|
||||
#pragma warning(disable:4996)
|
@ -5,4 +5,12 @@
|
||||
int res_reload(const char* const fn)
|
||||
{
|
||||
return h_reload(fn);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// purpose of this routine (intended to be called once a frame):
|
||||
// file notification may come at any time. by forcing the reloads
|
||||
// to take place here, we don't require everything to be thread-safe.
|
@ -96,10 +96,14 @@ __asm
|
||||
long cpu_caps = 0;
|
||||
long cpu_ext_caps = 0;
|
||||
|
||||
int tsc_is_safe = -1;
|
||||
|
||||
|
||||
static char cpu_vendor[13];
|
||||
static int family, model; // used to detect cpu_type
|
||||
|
||||
int tsc_is_safe = -1;
|
||||
static int have_brand_string = 0;
|
||||
// int instead of bool for easier setting from asm
|
||||
|
||||
|
||||
// optimized for size
|
||||
@ -148,11 +152,11 @@ __asm
|
||||
mov esi, 0x80000000
|
||||
mov eax, esi
|
||||
cpuid
|
||||
cmp eax, esi
|
||||
jbe no_ext_funcs
|
||||
lea esi, [esi+4]
|
||||
cmp eax, esi
|
||||
jb no_brand_str
|
||||
cmp eax, esi ; max ext <= 0x80000000?
|
||||
jbe no_ext_funcs ; yes - no ext funcs at all
|
||||
lea esi, [esi+4] ; esi = 0x80000004
|
||||
cmp eax, esi ; max ext < 0x80000004?
|
||||
jb no_brand_str ; yes - brand string not available, skip
|
||||
|
||||
; get CPU brand string (>= Athlon XP, P4)
|
||||
mov edi, offset cpu_type
|
||||
@ -171,6 +175,8 @@ $1: lea eax, [ebp+esi] ; 0x80000002 .. 4
|
||||
jle $1
|
||||
; (already 0 terminated)
|
||||
|
||||
mov [have_brand_string], ebp ; ebp = 1 = true
|
||||
|
||||
no_brand_str:
|
||||
|
||||
; get extended feature flags
|
||||
@ -194,8 +200,54 @@ void ia32_get_cpu_info()
|
||||
if(cpu_caps == 0) // cpuid not supported - can't do the rest
|
||||
return;
|
||||
|
||||
// cpu_type set from brand string - clean it up some
|
||||
if(strcmp(cpu_type, "unknown") != 0)
|
||||
// fall back to manual detect of CPU type if it didn't supply
|
||||
// a brand string, or if the brand string is useless (i.e. "Unknown").
|
||||
if(!have_brand_string || strncmp(cpu_type, "Unknow", 6) == 0)
|
||||
// we use an extra flag to detect if we got the brand string:
|
||||
// safer than comparing against the default name, which may change.
|
||||
//
|
||||
// some older boards reprogram the brand string with
|
||||
// "Unknow[n] CPU Type" on CPUs the BIOS doesn't recognize.
|
||||
// in that case, we ignore the brand string and detect manually.
|
||||
{
|
||||
// AMD
|
||||
if(!strcmp(cpu_vendor, "AuthenticAMD"))
|
||||
{
|
||||
// everything else is either too old, or should have a brand string.
|
||||
if(family == 6)
|
||||
{
|
||||
if(model == 3 || model == 7)
|
||||
strcpy(cpu_type, "AMD Duron");
|
||||
else if(model <= 5)
|
||||
strcpy(cpu_type, "AMD Athlon");
|
||||
else
|
||||
{
|
||||
if(cpu_ext_caps & EXT_MP_CAPABLE)
|
||||
strcpy(cpu_type, "AMD Athlon MP");
|
||||
else
|
||||
strcpy(cpu_type, "AMD Athlon XP");
|
||||
}
|
||||
}
|
||||
}
|
||||
// Intel
|
||||
else if(!strcmp(cpu_vendor, "GenuineIntel"))
|
||||
{
|
||||
// everything else is either too old, or should have a brand string.
|
||||
if(family == 6)
|
||||
{
|
||||
if(model == 1)
|
||||
strcpy(cpu_type, "Intel Pentium Pro");
|
||||
else if(model == 3 || model == 5)
|
||||
strcpy(cpu_type, "Intel Pentium II");
|
||||
else if(model == 6)
|
||||
strcpy(cpu_type, "Intel Celeron");
|
||||
else
|
||||
strcpy(cpu_type, "Intel Pentium III");
|
||||
}
|
||||
}
|
||||
}
|
||||
// we have a valid brand string; try to pretty it up some
|
||||
else
|
||||
{
|
||||
// strip (tm) from Athlon string
|
||||
if(!strncmp(cpu_type, "AMD Athlon(tm)", 14))
|
||||
@ -209,22 +261,11 @@ void ia32_get_cpu_info()
|
||||
if(sscanf(cpu_type, " Intel(R) Pentium(R) 4 CPU %fGHz", &a) == 1)
|
||||
strcpy(cpu_type, "Intel Pentium 4");
|
||||
}
|
||||
// detect cpu_type ourselves
|
||||
else
|
||||
{
|
||||
// AMD
|
||||
if(!strcmp(cpu_vendor, "AuthenticAMD"))
|
||||
{
|
||||
if(family == 6)
|
||||
strcpy(cpu_type, (model == 3)? "AMD Duron" : "AMD Athlon");
|
||||
}
|
||||
// Intel
|
||||
else if(!strcmp(cpu_vendor, "GenuineIntel"))
|
||||
{
|
||||
if(family == 6 && model >= 7)
|
||||
strcpy(cpu_type, "Intel Pentium III / Celeron");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// measure CPU frequency
|
||||
//
|
||||
|
||||
// .. get old policy and priority
|
||||
int old_policy;
|
||||
|
@ -52,8 +52,9 @@ enum
|
||||
extern long cpu_caps;
|
||||
|
||||
// define instead of enum to avoid stupid sign conversion warning
|
||||
#define EXT_3DNOW_PRO BIT(30)
|
||||
#define EXT_3DNOW BIT(31)
|
||||
#define EXT_MP_CAPABLE BIT(19)
|
||||
#define EXT_3DNOW_PRO BIT(30)
|
||||
#define EXT_3DNOW BIT(31)
|
||||
|
||||
extern long cpu_ext_caps;
|
||||
|
||||
|
@ -29,10 +29,11 @@
|
||||
// powrprof is loaded manually - we only need 1 function.
|
||||
#endif
|
||||
|
||||
#include "Tlhelp32.h"
|
||||
|
||||
|
||||
// EnumDisplayDevices is not available on Win95 or NT.
|
||||
// try to import it manually here; return -1 if not available.
|
||||
// note: FreeLibrary at exit avoids BoundsChecker resource leak warnings.
|
||||
static BOOL (WINAPI *pEnumDisplayDevicesA)(void*, DWORD, void*, DWORD);
|
||||
static int import_EnumDisplayDevices()
|
||||
{
|
||||
@ -40,7 +41,10 @@ static int import_EnumDisplayDevices()
|
||||
{
|
||||
static HMODULE hUser32Dll = LoadLibrary("user32.dll");
|
||||
*(void**)&pEnumDisplayDevicesA = GetProcAddress(hUser32Dll, "EnumDisplayDevicesA");
|
||||
ONCE(atexit2(FreeLibrary, (uintptr_t)hUser32Dll, CC_STDCALL_1));
|
||||
FreeLibrary(hUser32Dll);
|
||||
// make sure the reference is released so BoundsChecker
|
||||
// doesn't complain. it won't actually be unloaded anyway -
|
||||
// there is at least one other reference.
|
||||
}
|
||||
|
||||
return pEnumDisplayDevicesA? 0 : -1;
|
||||
@ -94,21 +98,53 @@ int win_get_gfx_card()
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
get ogl client DLL name
|
||||
enum loaded dlls
|
||||
ogl must be running; ambiguous (need to eliminate MCD and opengl32.dll)
|
||||
*/
|
||||
// no .dll appended
|
||||
//
|
||||
static int get_ogl_drv_name(char* const ogl_drv_name, const size_t max_name_len)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
HKEY hkOglDrivers;
|
||||
const char* key = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\OpenGLDrivers";
|
||||
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, KEY_ENUMERATE_SUB_KEYS, &hkOglDrivers) != 0)
|
||||
return -1;
|
||||
|
||||
char key_name[32];
|
||||
DWORD key_name_len = sizeof(key_name);
|
||||
if(RegEnumKeyEx(hkOglDrivers, 0, key_name, &key_name_len, 0, 0, 0, 0) == 0)
|
||||
{
|
||||
HKEY hkClass;
|
||||
if(RegOpenKeyEx(hkOglDrivers, key_name, 0, KEY_QUERY_VALUE, &hkClass) == 0)
|
||||
{
|
||||
DWORD size = (DWORD)max_name_len;
|
||||
if(RegQueryValueEx(hkClass, "Dll", 0, 0, (LPBYTE)ogl_drv_name, &size) == 0)
|
||||
ret = 0; // success
|
||||
|
||||
RegCloseKey(hkClass);
|
||||
}
|
||||
}
|
||||
|
||||
RegCloseKey(hkOglDrivers);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// split out so we can return on failure, instead of goto
|
||||
// method: http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/009679.html
|
||||
int win_get_gfx_drv()
|
||||
{
|
||||
// get driver DLL name
|
||||
DEVMODEA dm;
|
||||
// note: dmDriverVersion is not what we're looking for
|
||||
memset(&dm, 0, sizeof(dm));
|
||||
dm.dmSize = sizeof(dm);
|
||||
// note: dmSize isn't the first member!
|
||||
if(!EnumDisplaySettingsA(0, ENUM_CURRENT_SETTINGS, &dm))
|
||||
return -1;
|
||||
char drv_name[CCHDEVICENAME+5]; // we add ".dll"
|
||||
strcpy(drv_name, (const char*)dm.dmDeviceName);
|
||||
strcat(drv_name, ".dll");
|
||||
|
||||
/* want ogl icd, instead of 2d driver */
|
||||
|
||||
char ogl_drv_name[MAX_PATH];
|
||||
CHECK_ERR(get_ogl_drv_name(ogl_drv_name, sizeof(ogl_drv_name)));
|
||||
|
||||
|
||||
// don't want to return 0 on success - we'd need to duplicate free(buf).
|
||||
// instead, set this variable and return that.
|
||||
@ -116,21 +152,21 @@ int win_get_gfx_drv()
|
||||
|
||||
// read the DLL's version info
|
||||
DWORD unused;
|
||||
DWORD ver_size = GetFileVersionInfoSize(drv_name, &unused);
|
||||
const DWORD ver_size = GetFileVersionInfoSize(ogl_drv_name, &unused);
|
||||
if(!ver_size)
|
||||
return -1;
|
||||
void* buf = malloc(ver_size);
|
||||
void* const buf = malloc(ver_size);
|
||||
if(!buf)
|
||||
return -1;
|
||||
if(GetFileVersionInfo(drv_name, 0, ver_size, buf))
|
||||
if(GetFileVersionInfo(ogl_drv_name, 0, ver_size, buf))
|
||||
{
|
||||
u16* lang; // -> 16 bit language ID, 16 bit codepage
|
||||
uint lang_len;
|
||||
BOOL ok = VerQueryValue(buf, "\\VarFileInfo\\Translation", (void**)&lang, &lang_len);
|
||||
const BOOL ok = VerQueryValue(buf, "\\VarFileInfo\\Translation", (void**)&lang, &lang_len);
|
||||
if(ok && lang && lang_len == 4)
|
||||
{
|
||||
char subblock[64];
|
||||
sprintf(subblock, "\\StringFileInfo\\%04X%04X\\ProductName", lang[0], lang[1]);
|
||||
sprintf(subblock, "\\StringFileInfo\\%04X%04X\\FileVersion", lang[0], lang[1]);
|
||||
const char* ver;
|
||||
uint ver_len;
|
||||
if(VerQueryValue(buf, subblock, (void**)&ver, &ver_len))
|
||||
|
@ -17,9 +17,90 @@
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "res/res.h"
|
||||
#include "wfam.h"
|
||||
#include "win_internal.h"
|
||||
|
||||
#if 0
|
||||
|
||||
static const size_t CHANGE_BUF_SIZE = 15000;
|
||||
// better be enough - if too small, we miss changes made to a directory.
|
||||
|
||||
|
||||
// don't worry about size: the user only passes around a pointer
|
||||
// to this struct, due to the pImpl idiom. this is heap-allocated.
|
||||
struct FAMRequest_
|
||||
{
|
||||
std::string dir_name;
|
||||
HANDLE hDir;
|
||||
|
||||
// history to detect series of notifications, so we can skip
|
||||
// redundant reloads (slow)
|
||||
std::string last_path;
|
||||
DWORD last_action; // FILE_ACTION_* codes or 0
|
||||
DWORD last_ticks; // timestamp via GetTickCount
|
||||
|
||||
OVERLAPPED ovl;
|
||||
// we don't use any of its fields.
|
||||
// overlapped I/O completation notification is via IOCP.
|
||||
// rationale: see below.
|
||||
char changes[CHANGE_BUF_SIZE];
|
||||
|
||||
|
||||
FAMRequest_(const char* _dir_name)
|
||||
: dir_name(_dir_name), last_path("")
|
||||
{
|
||||
last_action = 0;
|
||||
last_ticks = 0;
|
||||
|
||||
memset(&ovl, 0, sizeof(ovl));
|
||||
|
||||
// changes[] doesn't need init
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// don't worry about size: the user only passes around a pointer
|
||||
// to this struct, due to the pImpl idiom. this is heap-allocated.
|
||||
struct FAMConnection_
|
||||
{
|
||||
std::string app_name;
|
||||
|
||||
|
||||
HANDLE hIOCP;
|
||||
|
||||
// queue necessary - race condition if pass to app and re-issue
|
||||
// needs to be FIFO, and don't want to constantly shuffle items (can be rather large)
|
||||
// around => list
|
||||
typedef std::list<FAMEvent> Events;
|
||||
Events pending_events;
|
||||
|
||||
// list of all pending requests to detect duplicates and
|
||||
// for easier cleanup. only store pointer in container -
|
||||
// they're not copy-equivalent.
|
||||
typedef std::map<std::string, FAMRequest*> Requests;
|
||||
typedef Requests::iterator RequestIt;
|
||||
Requests requests;
|
||||
|
||||
FAMConnection_(const char* _app_name)
|
||||
: app_name(_app_name)
|
||||
{
|
||||
hIOCP = 0;
|
||||
// not INVALID_HANDLE_VALUE! (CreateIoCompletionPort requirement)
|
||||
}
|
||||
|
||||
~FAMConnection_()
|
||||
{
|
||||
CloseHandle(hIOCP);
|
||||
hIOCP = INVALID_HANDLE_VALUE;
|
||||
|
||||
// container holds dynamically allocated Watch structs
|
||||
// for(WatchIt it = watches.begin(); it != watches.end(); ++it)
|
||||
// delete it->second;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#include "sysdep/win/win_internal.h"
|
||||
|
||||
|
||||
// rationale for using I/O completion ports for notification:
|
||||
@ -43,118 +124,158 @@
|
||||
// IOCPs work well and are elegant; have not yet noticed any drawbacks.
|
||||
|
||||
|
||||
static HANDLE hIOCP = 0;
|
||||
// not INVALID_HANDLE_VALUE! (CreateIoCompletionPort requirement)
|
||||
|
||||
|
||||
static const size_t WATCH_BUF_SIZE = 16384;
|
||||
// better be enough - if too small, we miss changes made to a directory.
|
||||
|
||||
|
||||
|
||||
// ReadDirectoryChangesW must be called again after each time it returns data,
|
||||
// so we need to pass this struct to the notification "callback".
|
||||
// we do this implicitly with the guarantee that &ovl = &Watch (verified via
|
||||
// assert). rationale: the Key param is already in use (tells the callback to
|
||||
// call RDC - see KEY_ADD_WATCH_ONLY); this way of passing the parameter is
|
||||
// cleaner IMO than stuffing the address in an unused member of OVERLAPPED.
|
||||
struct Watch
|
||||
{
|
||||
OVERLAPPED ovl;
|
||||
// we don't use any of its fields.
|
||||
|
||||
void* buf;
|
||||
|
||||
HANDLE hDir;
|
||||
|
||||
bool watch_subdirs;
|
||||
|
||||
// history to detect series of notifications, so we can skip
|
||||
// redundant reloads (slow)
|
||||
std::string last_path;
|
||||
DWORD last_action; // FILE_ACTION_* codes or 0
|
||||
DWORD last_ticks; // timestamp via GetTickCount
|
||||
// so we need to pass along the associated Request.
|
||||
// since we issue RDC immediately, instead of sending a bogus packet
|
||||
// to the IOCP that triggers the issue, we don't need the key parameter
|
||||
// for anything - use it to pass along the Request.
|
||||
// cleaner than assuming &ovl = &Request, or stuffing it in an unused
|
||||
// member of OVERLAPPED.
|
||||
|
||||
|
||||
Watch(HANDLE hDir, bool watch_subdirs)
|
||||
{
|
||||
this->hDir = hDir;
|
||||
this->watch_subdirs = watch_subdirs;
|
||||
|
||||
buf = mem_alloc(WATCH_BUF_SIZE, 32);
|
||||
// ReadDirectoryChangesW requirement: at least 4-byte alignment.
|
||||
|
||||
memset(&ovl, 0, sizeof(ovl));
|
||||
|
||||
last_action = 0;
|
||||
}
|
||||
|
||||
~Watch()
|
||||
{
|
||||
// mem_free(buf);
|
||||
// FIXME: mem has already shut down when this is called.
|
||||
|
||||
CancelIo(hDir);
|
||||
|
||||
CloseHandle(hDir);
|
||||
hDir = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// don't store directly in container - not copy-equivalent.
|
||||
typedef std::map<std::string, Watch*> Watches;
|
||||
typedef Watches::iterator WatchIt;
|
||||
static Watches watches;
|
||||
|
||||
|
||||
static void cleanup(void)
|
||||
{
|
||||
CloseHandle(hIOCP);
|
||||
|
||||
// container holds dynamically allocated Watch structs
|
||||
for(WatchIt it = watches.begin(); it != watches.end(); ++it)
|
||||
delete it->second;
|
||||
}
|
||||
|
||||
|
||||
int dir_watch_abort(const char* const dir)
|
||||
{
|
||||
// find watch
|
||||
const std::string dir_s(dir);
|
||||
/* const std::string dir_s(dir);
|
||||
WatchIt it = watches.find(dir_s);
|
||||
if(it == watches.end())
|
||||
return -1;
|
||||
|
||||
delete it->second;
|
||||
watches.erase(it);
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// it's nice to have only 1 call site of ReadDirectoryChangesW, namely
|
||||
// in the notification "callback". posting an event to the IOCP with
|
||||
// KEY_ADD_WATCH_ONLY tells it to call RDC; normal events pass KEY_NORMAL.
|
||||
static enum
|
||||
// it'd be nice to have only 1 call site of ReadDirectoryChangesW, namely
|
||||
// in the notification "callback". however, posting a dummy event to the IOCP
|
||||
// and having the callback issue RDC is a bit ugly, and loses changes made
|
||||
// before the poll routine is first called.
|
||||
|
||||
static int dir_watch_issue(FAMRequest_* fr)
|
||||
{
|
||||
KEY_NORMAL,
|
||||
KEY_ADD_WATCH_ONLY
|
||||
};
|
||||
// (re-)request change notification from now on
|
||||
const DWORD filter = FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME |
|
||||
FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE |
|
||||
FILE_NOTIFY_CHANGE_CREATION;
|
||||
BOOL ret = ReadDirectoryChangesW(fr->hDir, fr->changes, CHANGE_BUF_SIZE, FALSE, filter, 0, &fr->ovl, 0);
|
||||
return ret? 0 : -1;
|
||||
}
|
||||
|
||||
|
||||
int dir_add_watch(const char* const dir, const bool watch_subdirs)
|
||||
{
|
||||
ONCE(atexit2(cleanup));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FAMCancelMonitor(FAMConnection*, FAMRequest* req)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void wfam_shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
int FAMOpen2(FAMConnection* const fc, const char* app_name)
|
||||
{
|
||||
try
|
||||
{
|
||||
fc->internal = new FAMConnection_(app_name);
|
||||
}
|
||||
catch(std::bad_alloc)
|
||||
{
|
||||
fc->internal = 0;
|
||||
}
|
||||
|
||||
// either (VC6) new returned 0, or we caught bad_alloc => fail.
|
||||
if(!fc->internal)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int FAMClose(FAMConnection* const fc)
|
||||
{
|
||||
FAMConnection_*& fc_ = (FAMConnection_*)fc->internal;
|
||||
if(!fc_)
|
||||
{
|
||||
debug_warn("FAMClose: already closed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
delete fc_;
|
||||
fc_ = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int FAMMonitorDirectory(FAMConnection* fc, char* dir, FAMRequest* fr, void* user)
|
||||
{
|
||||
FAMConnection_* fc_ = (FAMConnection_*)fc->internal;
|
||||
|
||||
/*
|
||||
// make sure dir is not already being watched
|
||||
const std::string dir_s(dir);
|
||||
WatchIt it = watches.find(dir_s);
|
||||
if(it != watches.end())
|
||||
return -1;
|
||||
*/
|
||||
HANDLE hDir = INVALID_HANDLE_VALUE;
|
||||
HANDLE& hIOCP = fc_->hIOCP;
|
||||
|
||||
// open handle to directory
|
||||
const DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
|
||||
const DWORD flags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED;
|
||||
const HANDLE hDir = CreateFile(dir, FILE_LIST_DIRECTORY, share, 0, OPEN_EXISTING, flags, 0);
|
||||
hDir = CreateFile(dir, FILE_LIST_DIRECTORY, share, 0, OPEN_EXISTING, flags, 0);
|
||||
if(hDir == INVALID_HANDLE_VALUE)
|
||||
return -1;
|
||||
|
||||
@ -162,105 +283,139 @@ int dir_add_watch(const char* const dir, const bool watch_subdirs)
|
||||
hIOCP = CreateIoCompletionPort(hDir, hIOCP, KEY_NORMAL, 0);
|
||||
if(hIOCP == 0 || hIOCP == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
fail:
|
||||
CloseHandle(hDir);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// insert
|
||||
Watch* const w = new Watch(hDir, watch_subdirs);
|
||||
watches[dir_s] = w;
|
||||
|
||||
// tell the notification "callback" to actually add the watch
|
||||
const DWORD bytes_transferred = 0;
|
||||
PostQueuedCompletionStatus(hIOCP, bytes_transferred, KEY_ADD_WATCH_ONLY, &w->ovl);
|
||||
dir_watch_issue(w);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int dir_changed(const FILE_NOTIFY_INFORMATION*, Watch*);
|
||||
|
||||
// purpose of this routine (intended to be called once a frame):
|
||||
// file notification may come at any time. by forcing the reloads
|
||||
// to take place here, we don't require everything to be thread-safe.
|
||||
//
|
||||
// added bonus: can actually "poll" for changes here - obviates a worker
|
||||
// thread, mutex, and 2 queues.
|
||||
int allow_reload()
|
||||
|
||||
|
||||
|
||||
static int extract_events(FAMConnection* conn, FAMRequest* req)
|
||||
{
|
||||
// deque and process all pending IOCP packets
|
||||
FAMConnection_ conn_ = (FAMConnection_*)conn->internal;
|
||||
const FILE_NOTIFY_INFORMATION* fni = (const FILE_NOTIFY_INFORMATION*)req->changes;
|
||||
Events& events = fc_->pending_events;
|
||||
|
||||
FAMEvent event_template;
|
||||
event_template.conn = conn;
|
||||
event_template.req = req;
|
||||
|
||||
// for every packet in buffer: (there's at least one)
|
||||
for(;;)
|
||||
{
|
||||
// check for change_notification or add_watch packets
|
||||
DWORD bytes_transferred; // unused
|
||||
ULONG_PTR key;
|
||||
OVERLAPPED* povl;
|
||||
BOOL got_packet = GetQueuedCompletionStatus(hIOCP, &bytes_transferred, &key, &povl, 0);
|
||||
if(!got_packet)
|
||||
break;
|
||||
// many apps save by creating a temp file, deleting the original,
|
||||
// and renaming the temp file. that leads to 2 reloads, which is slow.
|
||||
// try to detect this case with a simple state machine - we assume
|
||||
// the notification order is always the same.
|
||||
|
||||
// retrieve the corresponding Watch
|
||||
// (see Watch definition for rationale)
|
||||
Watch* const w = (Watch*)povl;
|
||||
assert(offsetof(struct Watch, ovl) == 0);
|
||||
// TODO:
|
||||
|
||||
// (re-)request change notification from now on
|
||||
const DWORD filter = FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME |
|
||||
FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE |
|
||||
FILE_NOTIFY_CHANGE_CREATION;
|
||||
ReadDirectoryChangesW(w->hDir, w->buf, WATCH_BUF_SIZE, TRUE, filter, 0, &w->ovl, 0);
|
||||
const char* actions[] = { "", "FILE_ACTION_ADDED", "FILE_ACTION_REMOVED", "FILE_ACTION_MODIFIED", "FILE_ACTION_RENAMED_OLD_NAME", "FILE_ACTION_RENAMED_NEW_NAME" };
|
||||
const char* action = actions[fni->Action];
|
||||
|
||||
// dir_add_watch requests the watch be added;
|
||||
// we didn't actually receive any change notification
|
||||
if(key == KEY_ADD_WATCH_ONLY)
|
||||
continue;
|
||||
|
||||
FILE_NOTIFY_INFORMATION* fni = (FILE_NOTIFY_INFORMATION*)w->buf;
|
||||
for(;;)
|
||||
// convert Windows BSTR-style path to
|
||||
// portable C string path for the resource manager.
|
||||
// HACK: convert in place, we copy it into
|
||||
char fn[MAX_PATH];
|
||||
char* p = fn;
|
||||
const int num_chars = fni->FileNameLength/2;
|
||||
for(int i = 0; i < num_chars; i++)
|
||||
{
|
||||
dir_changed(fni, w);
|
||||
|
||||
DWORD ofs = fni->NextEntryOffset;
|
||||
// this was the last entry
|
||||
if(!ofs)
|
||||
break;
|
||||
|
||||
// advance to next FILE_NOTIFY_INFORMATION (variable length)
|
||||
(char*&)fni += ofs;
|
||||
char c = (char)fni->FileName[i];
|
||||
if(c == '\\')
|
||||
c = '/';
|
||||
*p++ = c;
|
||||
}
|
||||
*p = '\0';
|
||||
|
||||
// don't want to expose details
|
||||
|
||||
events.push_back(event_template);
|
||||
|
||||
|
||||
const DWORD ofs = fni->NextEntryOffset;
|
||||
// advance to next FILE_NOTIFY_INFORMATION (variable length)
|
||||
if(ofs)
|
||||
(char*&)fni += ofs;
|
||||
// this was the last entry - no more elements left in buffer.
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int dir_changed(const FILE_NOTIFY_INFORMATION* const fni, Watch* const w)
|
||||
{
|
||||
// many apps save by creating a temp file, deleting the original,
|
||||
// and renaming the temp file. that leads to 2 reloads, which is slow.
|
||||
// try to detect this case with a simple state machine - we assume
|
||||
// the notification order is always the same.
|
||||
|
||||
// TODO:
|
||||
|
||||
const char* actions[] = { "", "FILE_ACTION_ADDED", "FILE_ACTION_REMOVED", "FILE_ACTION_MODIFIED", "FILE_ACTION_RENAMED_OLD_NAME", "FILE_ACTION_RENAMED_NEW_NAME" };
|
||||
const char* action = actions[fni->Action];
|
||||
|
||||
// convert Windows BSTR-style path to
|
||||
// portable C string path for the resource manager.
|
||||
char fn[MAX_PATH];
|
||||
char* p = fn;
|
||||
const int num_chars = fni->FileNameLength/2;
|
||||
for(int i = 0; i < num_chars; i++)
|
||||
{
|
||||
char c = (char)fni->FileName[i];
|
||||
if(c == '\\')
|
||||
c = '/';
|
||||
*p++ = c;
|
||||
}
|
||||
*p = '\0';
|
||||
|
||||
res_reload(fn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int FAMPending(FAMConnection* fc)
|
||||
{
|
||||
FAMConnection_* const fc_ = (FAMConnection_*)fc->internal;
|
||||
Events& pending_events = fc_->pending_events;
|
||||
|
||||
if(!pending_events.empty())
|
||||
return 1;
|
||||
|
||||
// check if new buffer has been filled
|
||||
DWORD bytes_transferred; // unused
|
||||
ULONG_PTR key;
|
||||
OVERLAPPED* povl;
|
||||
BOOL got_packet = GetQueuedCompletionStatus(fc_->hIOCP, &bytes_transferred, &key, &povl, 0);
|
||||
if(!got_packet)
|
||||
return 0;
|
||||
|
||||
CHECK_ERR(extract_events(conn, req));
|
||||
|
||||
// dir_watch_issue(buf);
|
||||
|
||||
|
||||
|
||||
|
||||
fc->fni = (FILE_NOTIFY_INFORMATION*)w->buf;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int FAMNextEvent(FAMConnection* const fc, FAMEvent* const fe)
|
||||
{
|
||||
FAMConnection_* const fc_ = (FAMConnection_*)fc->internal;
|
||||
Events& pending_events = fc_->pending_events;
|
||||
|
||||
if(!fe)
|
||||
{
|
||||
debug_warn("FAMNextEvent: fe = 0");
|
||||
return ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if(pending_events.empty())
|
||||
{
|
||||
debug_warn("FAMNextEvent: no pending events");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*fe = pending_events.front();
|
||||
pending_events.pop_front();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -466,6 +466,41 @@ inline void SDL_GL_SwapBuffers()
|
||||
}
|
||||
|
||||
|
||||
static int calc_gamma(float gamma, u16* ramp)
|
||||
{
|
||||
if(gamma <= 0.0f)
|
||||
return ERR_INVALID_PARAM;
|
||||
|
||||
// identity
|
||||
// (special-case it to make sure we get the exact value)
|
||||
if(gamma == 1.0f)
|
||||
{
|
||||
for(u16 i = 0; i < 256; i++)
|
||||
ramp[i] = (i << 8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const double inv_gamma = 1.0 / gamma;
|
||||
for(int i = 0; i < 256; i++)
|
||||
{
|
||||
const double frac = i / 256.0;
|
||||
// make sure pow arg types are unambiguous
|
||||
ramp[i] = fp_to_u16(pow(frac, inv_gamma));
|
||||
// 8.8 fixed point
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int SDL_SetGamma(float r, float g, float b)
|
||||
{
|
||||
u16 ramp[3][256];
|
||||
CHECK_ERR(calc_gamma(r, ramp[0]));
|
||||
CHECK_ERR(calc_gamma(g, ramp[1]));
|
||||
CHECK_ERR(calc_gamma(b, ramp[2]));
|
||||
return SetDeviceGammaRamp(hDC, ramp)? 0 : -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -87,7 +87,7 @@ extern int SDL_KillThread(SDL_Thread*);
|
||||
extern int __stdcall SDL_WarpMouse(int, int);
|
||||
|
||||
|
||||
|
||||
extern int SDL_SetGamma(float r, float g, float b);
|
||||
|
||||
/* macros */
|
||||
|
||||
|
1101
source/main.cpp
1101
source/main.cpp
File diff suppressed because it is too large
Load Diff
@ -400,16 +400,9 @@ ostream &operator<<(ostream &os, CStr &Str)
|
||||
|
||||
size_t CStr::GetHashCode() const
|
||||
{
|
||||
// FNV-1 hash for 64 bit integers.
|
||||
size_t hash = 14695981039346656037;
|
||||
const char* data = m_String.data();
|
||||
for( int t = 0; t < m_String.length(); t++ )
|
||||
{
|
||||
hash *= 1099511628211;
|
||||
hash ^= *(data++);
|
||||
}
|
||||
return( hash );
|
||||
|
||||
return (size_t)fnv_hash64(m_String.data(), m_String.length());
|
||||
// janwas asks: do we care about the hash being 64 bits?
|
||||
// it is truncated here on 32-bit systems; why go 64 bit at all?
|
||||
}
|
||||
|
||||
uint CStr::GetSerializedLength() const
|
||||
|
@ -18,7 +18,7 @@ using namespace std;
|
||||
|
||||
// use GetDouble and type-cast it to <<type>>
|
||||
#define FUNC_IMPL_CAST_GETDOUBLE(func_name,type) \
|
||||
_bool CParserValue::func_name(type &ret) \
|
||||
bool CParserValue::func_name(type &ret) \
|
||||
{ \
|
||||
_double d; \
|
||||
if (GetDouble(d)) \
|
||||
@ -31,7 +31,7 @@ _bool CParserValue::func_name(type &ret) \
|
||||
// Get%type% from the CParserValue
|
||||
// func_name must belong to CParserFile
|
||||
#define FUNC_IMPL_GETARG(func_name, get_name, type) \
|
||||
_bool CParserLine::func_name(const _int & arg, type &ret) \
|
||||
bool CParserLine::func_name(const int & arg, type &ret) \
|
||||
{ \
|
||||
if (GetArgCount() <= arg) \
|
||||
return false; \
|
||||
@ -42,15 +42,15 @@ _bool CParserLine::func_name(const _int & arg, type &ret) \
|
||||
// Function definitions
|
||||
//-------------------------------------------------
|
||||
|
||||
static _bool _IsStrictNameChar(const _char& c);
|
||||
static _bool _IsValueChar(const _char& c);
|
||||
static bool _IsStrictNameChar(const _char& c);
|
||||
static bool _IsValueChar(const _char& c);
|
||||
|
||||
|
||||
// Functions used for checking a character if it belongs to a value
|
||||
// or not
|
||||
|
||||
// Checks ident
|
||||
static _bool _IsStrictNameChar(const _char& c)
|
||||
static bool _IsStrictNameChar(const _char& c)
|
||||
{
|
||||
return ((c >= 'a' && c <= 'z') ||
|
||||
(c >= 'A' && c <= 'Z') ||
|
||||
@ -58,7 +58,7 @@ static _bool _IsStrictNameChar(const _char& c)
|
||||
}
|
||||
|
||||
// Checks value
|
||||
static _bool _IsValueChar(const _char& c)
|
||||
static bool _IsValueChar(const _char& c)
|
||||
{
|
||||
return ((c >= 'a' && c <= 'z') ||
|
||||
(c >= 'A' && c <= 'Z') ||
|
||||
@ -80,7 +80,7 @@ CParserValue::~CParserValue()
|
||||
// Parse the string in Value to different types
|
||||
|
||||
// bool
|
||||
_bool CParserValue::GetBool(_bool &ret)
|
||||
bool CParserValue::GetBool(bool &ret)
|
||||
{
|
||||
// TODO Raj Add or remove some? I can make it all lowercase
|
||||
// first so True and TRUE also works, or you could just
|
||||
@ -111,16 +111,16 @@ _bool CParserValue::GetBool(_bool &ret)
|
||||
}
|
||||
|
||||
// double
|
||||
_bool CParserValue::GetDouble(_double &ret)
|
||||
bool CParserValue::GetDouble(_double &ret)
|
||||
{
|
||||
// locals
|
||||
_double TempRet = 0.0;
|
||||
_int Size = m_String.size();
|
||||
_int i;
|
||||
_bool AtLeastOne = false; // Checked if at least one of the loops
|
||||
int Size = m_String.size();
|
||||
int i;
|
||||
bool AtLeastOne = false; // Checked if at least one of the loops
|
||||
// run, otherwise "." would parse OK
|
||||
_int DecimalPos;
|
||||
_bool Negative = false; // "-" is found
|
||||
int DecimalPos;
|
||||
bool Negative = false; // "-" is found
|
||||
|
||||
// Check if '-' is found
|
||||
if (m_String[0]=='-')
|
||||
@ -180,7 +180,7 @@ _bool CParserValue::GetDouble(_double &ret)
|
||||
}
|
||||
|
||||
// string - only return m_String, can't fail
|
||||
_bool CParserValue::GetString(std::string &ret)
|
||||
bool CParserValue::GetString(std::string &ret)
|
||||
{
|
||||
ret = m_String;
|
||||
return true;
|
||||
@ -192,7 +192,7 @@ _bool CParserValue::GetString(std::string &ret)
|
||||
FUNC_IMPL_CAST_GETDOUBLE(GetFloat, _float)
|
||||
FUNC_IMPL_CAST_GETDOUBLE(GetChar, _char)
|
||||
FUNC_IMPL_CAST_GETDOUBLE(GetShort, _short)
|
||||
FUNC_IMPL_CAST_GETDOUBLE(GetInt, _int)
|
||||
FUNC_IMPL_CAST_GETDOUBLE(GetInt, int)
|
||||
FUNC_IMPL_CAST_GETDOUBLE(GetLong, _long)
|
||||
FUNC_IMPL_CAST_GETDOUBLE(GetUnsignedShort, _ushort)
|
||||
FUNC_IMPL_CAST_GETDOUBLE(GetUnsignedInt, _uint)
|
||||
@ -264,7 +264,7 @@ CParserLine::~CParserLine()
|
||||
}
|
||||
|
||||
// Clear arguments (deleting m_Memory
|
||||
_bool CParserLine::ClearArguments()
|
||||
bool CParserLine::ClearArguments()
|
||||
{
|
||||
// Now we can actually clear it
|
||||
m_Arguments.clear();
|
||||
@ -275,10 +275,10 @@ _bool CParserLine::ClearArguments()
|
||||
// it just checks if argument isn't out of range, and
|
||||
// then it uses the the respective function in CParserValue
|
||||
FUNC_IMPL_GETARG(GetArgString, GetString, string)
|
||||
FUNC_IMPL_GETARG(GetArgBool, GetBool, _bool)
|
||||
FUNC_IMPL_GETARG(GetArgBool, GetBool, bool)
|
||||
FUNC_IMPL_GETARG(GetArgChar, GetChar, _char)
|
||||
FUNC_IMPL_GETARG(GetArgShort, GetShort, _short)
|
||||
FUNC_IMPL_GETARG(GetArgInt, GetInt, _int)
|
||||
FUNC_IMPL_GETARG(GetArgInt, GetInt, int)
|
||||
FUNC_IMPL_GETARG(GetArgLong, GetLong, _long)
|
||||
FUNC_IMPL_GETARG(GetArgUnsignedShort, GetUnsignedShort, _ushort)
|
||||
FUNC_IMPL_GETARG(GetArgUnsignedInt, GetUnsignedInt, _uint)
|
||||
@ -293,7 +293,7 @@ FUNC_IMPL_GETARG(GetArgDouble, GetDouble, _double)
|
||||
// ex:
|
||||
// variable = 5 => variable, =, 5
|
||||
// CallFunc(4,2) => CallFunc, 4, 2
|
||||
_bool CParserLine::ParseString(const CParser& Parser, string strLine)
|
||||
bool CParserLine::ParseString(const CParser& Parser, string strLine)
|
||||
{
|
||||
// Don't process empty string
|
||||
if (strLine == string())
|
||||
@ -303,13 +303,13 @@ _bool CParserLine::ParseString(const CParser& Parser, string strLine)
|
||||
}
|
||||
|
||||
// Locals
|
||||
_bool Extract=false;
|
||||
_int ExtractPos=0;
|
||||
bool Extract=false;
|
||||
int ExtractPos=0;
|
||||
_char Buffer[256];
|
||||
_char Letter[] = {'\0','\0'}; // Letter as string
|
||||
vector<string> Segments;
|
||||
string strSub;
|
||||
_int i;
|
||||
int i;
|
||||
|
||||
// Set result to false, then if a match is found, turn it true
|
||||
m_ParseOK = false;
|
||||
@ -343,7 +343,7 @@ _bool CParserLine::ParseString(const CParser& Parser, string strLine)
|
||||
if (strLine[i] == '\"')
|
||||
{
|
||||
// Extract a string, search for another "
|
||||
_int pos = strLine.find("\"", i+1);
|
||||
int pos = strLine.find("\"", i+1);
|
||||
|
||||
// If matching can't be found,
|
||||
// the parsing will fail!
|
||||
@ -419,23 +419,23 @@ _bool CParserLine::ParseString(const CParser& Parser, string strLine)
|
||||
// * * * *
|
||||
|
||||
// Locals
|
||||
_int Progress; // progress in Segments index
|
||||
_int Lane=0; // Have many alternative routes we are in
|
||||
_bool Match; // If a task-type match has been found
|
||||
int Progress; // progress in Segments index
|
||||
int Lane=0; // Have many alternative routes we are in
|
||||
bool Match; // If a task-type match has been found
|
||||
// The vector of these three represents the different lanes
|
||||
// LastValidProgress[1] takes you back to lane 1 and how
|
||||
// the variables was set at that point
|
||||
vector<_int> LastValidProgress; // When diving into a dynamic argument store store
|
||||
vector<int> LastValidProgress; // When diving into a dynamic argument store store
|
||||
// the last valid so you can go back to it
|
||||
vector<_int> LastValidArgCount; // If an alternative route turns out to fail, we
|
||||
vector<int> LastValidArgCount; // If an alternative route turns out to fail, we
|
||||
// need to know the amount of arguments on the last
|
||||
// valid position, so we can remove them.
|
||||
vector<_bool> LastValidMatch; // Match at that point
|
||||
_bool BlockAltNode = false; // If this turns true, the alternative route
|
||||
vector<bool> LastValidMatch; // Match at that point
|
||||
bool BlockAltNode = false; // If this turns true, the alternative route
|
||||
// tested was not a success, and the settings
|
||||
// should be set back in order to test the
|
||||
// next node instead
|
||||
_bool LookNoFurther = false; // If this turns true, it means a definite match has been
|
||||
bool LookNoFurther = false; // If this turns true, it means a definite match has been
|
||||
// found and no further looking is required
|
||||
CParserTaskTypeNode *CurNode=NULL; // Current node on task type
|
||||
CParserTaskTypeNode *PrevNode=NULL; // Last node
|
||||
@ -626,7 +626,7 @@ _bool CParserLine::ParseString(const CParser& Parser, string strLine)
|
||||
{
|
||||
// Store argument in CParserValue!
|
||||
CParserValue value;
|
||||
_int i;
|
||||
int i;
|
||||
|
||||
switch(CurNode->m_Type)
|
||||
{
|
||||
@ -754,7 +754,7 @@ _bool CParserLine::ParseString(const CParser& Parser, string strLine)
|
||||
// if _minus is found as argument, remove it and add "-" to the one after that
|
||||
// note, it's easier if std::iterator isn't used here
|
||||
|
||||
for (i=1; i<GetArgCount(); ++i)
|
||||
for (i=1; i<(int)GetArgCount(); ++i)
|
||||
{
|
||||
if (m_Arguments[i-1].m_String == "_minus")
|
||||
{
|
||||
@ -793,18 +793,18 @@ CParser::~CParser()
|
||||
// A task-type is a string representing the acquired syntax when parsing
|
||||
// This function converts that string into a binary tree, making it easier
|
||||
// and faster to later parse.
|
||||
_bool CParser::InputTaskType(const string& strName, const string& strSyntax)
|
||||
bool CParser::InputTaskType(const string& strName, const string& strSyntax)
|
||||
{
|
||||
// Locals
|
||||
CParserTaskType TaskType; // Object we acquire to create
|
||||
_char Buffer[REGULAR_MAX_LENGTH];
|
||||
_int ExtractPos = 0;
|
||||
_bool Extract = false;
|
||||
_bool Error = false;
|
||||
_int i;
|
||||
_bool ConstructNew = false; // If it's the first input, then don't
|
||||
// construct a new node, because we
|
||||
// we already have m_BaseNode
|
||||
CParserTaskType TaskType; // Object we acquire to create
|
||||
char Buffer[REGULAR_MAX_LENGTH];
|
||||
size_t ExtractPos = 0;
|
||||
bool Extract = false;
|
||||
bool Error = false;
|
||||
int i;
|
||||
bool ConstructNew = false; // If it's the first input, then don't
|
||||
// construct a new node, because we
|
||||
// we already have m_BaseNode
|
||||
|
||||
// Construct base node
|
||||
TaskType.m_BaseNode = new CParserTaskTypeNode();
|
||||
@ -837,7 +837,7 @@ _bool CParser::InputTaskType(const string& strName, const string& strSyntax)
|
||||
CurNode->m_AltNode->m_ParentNode = CurNode;
|
||||
|
||||
// It's repeatable
|
||||
CurNode->m_AltNodeRepeatable = _bool(strSyntax[i]==START_DYNAMIC);
|
||||
CurNode->m_AltNodeRepeatable = bool(strSyntax[i]==START_DYNAMIC);
|
||||
|
||||
// Set to current
|
||||
CurNode = CurNode->m_AltNode;
|
||||
@ -974,7 +974,7 @@ _bool CParser::InputTaskType(const string& strName, const string& strSyntax)
|
||||
}
|
||||
|
||||
// Now try finding the second ')'
|
||||
_int Pos = strSyntax.find(")", ExtractPos+5);
|
||||
size_t Pos = strSyntax.find(")", ExtractPos+5);
|
||||
|
||||
// Check if ')' exists at all
|
||||
if (Pos == string::npos)
|
||||
|
Loading…
Reference in New Issue
Block a user