mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 08:26:27 +00:00
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@13100 72102866-910b-0410-8b05-ffd578937521
860 lines
17 KiB
Objective-C
860 lines
17 KiB
Objective-C
/** Implementation of ObjC runtime for GNUStep
|
|
Copyright (C) 1995 Free Software Foundation, Inc.
|
|
|
|
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
|
Date: Aug 1995
|
|
|
|
This file is part of the GNUstep Base Library.
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library 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
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public
|
|
License along with this library; if not, write to the Free
|
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
|
|
|
<title>NSObjCRuntime class reference</title>
|
|
$Date$ $Revision$
|
|
*/
|
|
|
|
#include <config.h>
|
|
#include <base/preface.h>
|
|
#include <Foundation/NSException.h>
|
|
#include <Foundation/NSObjCRuntime.h>
|
|
#include <Foundation/NSString.h>
|
|
#include <mframe.h>
|
|
#include <string.h>
|
|
|
|
NSString *
|
|
NSStringFromSelector(SEL aSelector)
|
|
{
|
|
if (aSelector != (SEL)0)
|
|
return [NSString stringWithCString: GSNameFromSelector(aSelector)];
|
|
return nil;
|
|
}
|
|
|
|
SEL
|
|
NSSelectorFromString(NSString *aSelectorName)
|
|
{
|
|
if (aSelectorName != nil)
|
|
return GSSelectorFromName ([aSelectorName lossyCString]);
|
|
return (SEL)0;
|
|
}
|
|
|
|
Class
|
|
NSClassFromString(NSString *aClassName)
|
|
{
|
|
if (aClassName != nil)
|
|
return GSClassFromName ([aClassName lossyCString]);
|
|
return (Class)0;
|
|
}
|
|
|
|
NSString *
|
|
NSStringFromClass(Class aClass)
|
|
{
|
|
if (aClass != (Class)0)
|
|
return [NSString stringWithCString: (char*)GSNameFromClass(aClass)];
|
|
return nil;
|
|
}
|
|
|
|
const char *
|
|
NSGetSizeAndAlignment(const char *typePtr, unsigned *sizep, unsigned *alignp)
|
|
{
|
|
NSArgumentInfo info;
|
|
typePtr = mframe_next_arg(typePtr, &info);
|
|
if (sizep)
|
|
*sizep = info.size;
|
|
if (alignp)
|
|
*alignp = info.align;
|
|
return typePtr;
|
|
}
|
|
|
|
/**
|
|
* This function is used to locate information about the instance
|
|
* variable of obj called name. It returns YES if the variable
|
|
* was found, NO otherwise. If it returns YES, then the values
|
|
* pointed to by type, size, and offset will be set (except where
|
|
* they are nul pointers).
|
|
*/
|
|
BOOL
|
|
GSFindInstanceVariable(id obj, const char *name,
|
|
const char **type, unsigned int *size, int *offset)
|
|
{
|
|
Class class;
|
|
struct objc_ivar_list *ivars;
|
|
struct objc_ivar *ivar = 0;
|
|
|
|
class = [obj class];
|
|
while (class != nil && ivar == 0)
|
|
{
|
|
ivars = class->ivars;
|
|
class = class->super_class;
|
|
if (ivars != 0)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < ivars->ivar_count; i++)
|
|
{
|
|
if (strcmp(ivars->ivar_list[i].ivar_name, name) == 0)
|
|
{
|
|
ivar = &ivars->ivar_list[i];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (ivar == 0)
|
|
{
|
|
return NO;
|
|
}
|
|
|
|
if (type)
|
|
*type = ivar->ivar_type;
|
|
if (size)
|
|
*size = objc_sizeof_type(ivar->ivar_type);
|
|
if (offset)
|
|
*offset = ivar->ivar_offset;
|
|
return YES;
|
|
}
|
|
|
|
/**
|
|
* This function performs no checking ... you should use it only where
|
|
* you are providing information from a call to GSFindInstanceVariable()
|
|
* and you know that the data area provided is the correct size.
|
|
*/
|
|
void
|
|
GSGetVariable(id obj, int offset, unsigned int size, void *data)
|
|
{
|
|
memcpy(data, ((void*)obj) + offset, size);
|
|
}
|
|
|
|
/**
|
|
* This function performs no checking ... you should use it only where
|
|
* you are providing information from a call to GSFindInstanceVariable()
|
|
* and you know that the data area provided is the correct size.
|
|
*/
|
|
void
|
|
GSSetVariable(id obj, int offset, unsigned int size, const void *data)
|
|
{
|
|
memcpy(((void*)obj) + offset, data, size);
|
|
}
|
|
|
|
/** ## deprecated ##
|
|
*/
|
|
BOOL
|
|
GSInstanceVariableInfo(id obj, NSString *iVarName,
|
|
const char **type, unsigned *size, unsigned *offset)
|
|
{
|
|
const char *name = [iVarName cString];
|
|
|
|
return GSFindInstanceVariable(obj, name, type, size, offset);
|
|
}
|
|
|
|
/** ## deprecated ##
|
|
*/
|
|
BOOL
|
|
GSGetInstanceVariable(id obj, NSString *iVarName, void *data)
|
|
{
|
|
const char *name = [iVarName cString];
|
|
int offset;
|
|
unsigned int size;
|
|
|
|
if (GSFindInstanceVariable(obj, name, 0, &size, &offset) == YES)
|
|
{
|
|
GSGetVariable(obj, offset, size, data);
|
|
return YES;
|
|
}
|
|
return NO;
|
|
}
|
|
|
|
/** ## deprecated ##
|
|
*/
|
|
BOOL
|
|
GSSetInstanceVariable(id obj, NSString *iVarName, const void *data)
|
|
{
|
|
const char *name = [iVarName cString];
|
|
int offset;
|
|
unsigned int size;
|
|
|
|
if (GSFindInstanceVariable(obj, name, 0, &size, &offset) == YES)
|
|
{
|
|
GSSetVariable(obj, offset, size, data);
|
|
return YES;
|
|
}
|
|
return NO;
|
|
}
|
|
|
|
#include <Foundation/NSValue.h>
|
|
#include <Foundation/NSKeyValueCoding.h>
|
|
/**
|
|
* This is used internally by the key-value coding methods, to get a
|
|
* value from an object either via an accessor method (if sel is
|
|
* supplied), or via direct access (if type, size, and offset are
|
|
* supplied).<br />
|
|
* Automatic conversion between NSNumber and C scalar types is performed.<br />
|
|
* If type is nul and can't be determined from the selector, the
|
|
* [NSObject-handleQueryWithUnboundKey:] method is called to try
|
|
* to get a value.
|
|
*/
|
|
id
|
|
GSGetValue(NSObject *self, NSString *key, SEL sel,
|
|
const char *type, unsigned size, int offset)
|
|
{
|
|
if (sel != 0)
|
|
{
|
|
NSMethodSignature *sig = [self methodSignatureForSelector: sel];
|
|
|
|
if ([sig numberOfArguments] != 2)
|
|
{
|
|
[NSException raise: NSInvalidArgumentException
|
|
format: @"key-value get method has wrong number of args"];
|
|
}
|
|
type = [sig methodReturnType];
|
|
}
|
|
if (type == NULL)
|
|
{
|
|
return [self handleQueryWithUnboundKey: key];
|
|
}
|
|
else
|
|
{
|
|
id val = nil;
|
|
|
|
switch (*type)
|
|
{
|
|
case _C_ID:
|
|
case _C_CLASS:
|
|
{
|
|
id v;
|
|
|
|
if (sel == 0)
|
|
{
|
|
v = *(id *)((char *)self + offset);
|
|
}
|
|
else
|
|
{
|
|
id (*imp)(id, SEL) =
|
|
(id (*)(id, SEL))[self methodForSelector: sel];
|
|
|
|
v = (*imp)(self, sel);
|
|
}
|
|
val = v;
|
|
}
|
|
break;
|
|
|
|
case _C_CHR:
|
|
{
|
|
signed char v;
|
|
|
|
if (sel == 0)
|
|
{
|
|
v = *(char *)((char *)self + offset);
|
|
}
|
|
else
|
|
{
|
|
signed char (*imp)(id, SEL) =
|
|
(signed char (*)(id, SEL))[self methodForSelector: sel];
|
|
|
|
v = (*imp)(self, sel);
|
|
}
|
|
val = [NSNumber numberWithChar: v];
|
|
}
|
|
break;
|
|
|
|
case _C_UCHR:
|
|
{
|
|
unsigned char v;
|
|
|
|
if (sel == 0)
|
|
{
|
|
v = *(unsigned char *)((char *)self + offset);
|
|
}
|
|
else
|
|
{
|
|
unsigned char (*imp)(id, SEL) =
|
|
(unsigned char (*)(id, SEL))[self methodForSelector:
|
|
sel];
|
|
|
|
v = (*imp)(self, sel);
|
|
}
|
|
val = [NSNumber numberWithUnsignedChar: v];
|
|
}
|
|
break;
|
|
|
|
case _C_SHT:
|
|
{
|
|
short v;
|
|
|
|
if (sel == 0)
|
|
{
|
|
v = *(short *)((char *)self + offset);
|
|
}
|
|
else
|
|
{
|
|
short (*imp)(id, SEL) =
|
|
(short (*)(id, SEL))[self methodForSelector: sel];
|
|
|
|
v = (*imp)(self, sel);
|
|
}
|
|
val = [NSNumber numberWithShort: v];
|
|
}
|
|
break;
|
|
|
|
case _C_USHT:
|
|
{
|
|
unsigned short v;
|
|
|
|
if (sel == 0)
|
|
{
|
|
v = *(unsigned short *)((char *)self + offset);
|
|
}
|
|
else
|
|
{
|
|
unsigned short (*imp)(id, SEL) =
|
|
(unsigned short (*)(id, SEL))[self methodForSelector:
|
|
sel];
|
|
|
|
v = (*imp)(self, sel);
|
|
}
|
|
val = [NSNumber numberWithUnsignedShort: v];
|
|
}
|
|
break;
|
|
|
|
case _C_INT:
|
|
{
|
|
int v;
|
|
|
|
if (sel == 0)
|
|
{
|
|
v = *(int *)((char *)self + offset);
|
|
}
|
|
else
|
|
{
|
|
int (*imp)(id, SEL) =
|
|
(int (*)(id, SEL))[self methodForSelector: sel];
|
|
|
|
v = (*imp)(self, sel);
|
|
}
|
|
val = [NSNumber numberWithInt: v];
|
|
}
|
|
break;
|
|
|
|
case _C_UINT:
|
|
{
|
|
unsigned int v;
|
|
|
|
if (sel == 0)
|
|
{
|
|
v = *(unsigned int *)((char *)self + offset);
|
|
}
|
|
else
|
|
{
|
|
unsigned int (*imp)(id, SEL) =
|
|
(unsigned int (*)(id, SEL))[self methodForSelector:
|
|
sel];
|
|
|
|
v = (*imp)(self, sel);
|
|
}
|
|
val = [NSNumber numberWithUnsignedInt: v];
|
|
}
|
|
break;
|
|
|
|
case _C_LNG:
|
|
{
|
|
long v;
|
|
|
|
if (sel == 0)
|
|
{
|
|
v = *(long *)((char *)self + offset);
|
|
}
|
|
else
|
|
{
|
|
long (*imp)(id, SEL) =
|
|
(long (*)(id, SEL))[self methodForSelector: sel];
|
|
|
|
v = (*imp)(self, sel);
|
|
}
|
|
val = [NSNumber numberWithLong: v];
|
|
}
|
|
break;
|
|
|
|
case _C_ULNG:
|
|
{
|
|
unsigned long v;
|
|
|
|
if (sel == 0)
|
|
{
|
|
v = *(unsigned long *)((char *)self + offset);
|
|
}
|
|
else
|
|
{
|
|
unsigned long (*imp)(id, SEL) =
|
|
(unsigned long (*)(id, SEL))[self methodForSelector:
|
|
sel];
|
|
|
|
v = (*imp)(self, sel);
|
|
}
|
|
val = [NSNumber numberWithUnsignedLong: v];
|
|
}
|
|
break;
|
|
|
|
#ifdef _C_LNG_LNG
|
|
case _C_LNG_LNG:
|
|
{
|
|
long long v;
|
|
|
|
if (sel == 0)
|
|
{
|
|
v = *(long long *)((char *)self + offset);
|
|
}
|
|
else
|
|
{
|
|
long long (*imp)(id, SEL) =
|
|
(long long (*)(id, SEL))[self methodForSelector: sel];
|
|
|
|
v = (*imp)(self, sel);
|
|
}
|
|
val = [NSNumber numberWithLongLong: v];
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
#ifdef _C_ULNG_LNG
|
|
case _C_ULNG_LNG:
|
|
{
|
|
unsigned long long v;
|
|
|
|
if (sel == 0)
|
|
{
|
|
v = *(unsigned long long *)((char *)self + offset);
|
|
}
|
|
else
|
|
{
|
|
unsigned long long (*imp)(id, SEL) =
|
|
(unsigned long long (*)(id, SEL))[self
|
|
methodForSelector: sel];
|
|
|
|
v = (*imp)(self, sel);
|
|
}
|
|
val = [NSNumber numberWithUnsignedLongLong: v];
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
case _C_FLT:
|
|
{
|
|
float v;
|
|
|
|
if (sel == 0)
|
|
{
|
|
v = *(float *)((char *)self + offset);
|
|
}
|
|
else
|
|
{
|
|
float (*imp)(id, SEL) =
|
|
(float (*)(id, SEL))[self methodForSelector: sel];
|
|
|
|
v = (*imp)(self, sel);
|
|
}
|
|
val = [NSNumber numberWithFloat: v];
|
|
}
|
|
break;
|
|
|
|
case _C_DBL:
|
|
{
|
|
double v;
|
|
|
|
if (sel == 0)
|
|
{
|
|
v = *(double *)((char *)self + offset);
|
|
}
|
|
else
|
|
{
|
|
double (*imp)(id, SEL) =
|
|
(double (*)(id, SEL))[self methodForSelector: sel];
|
|
|
|
v = (*imp)(self, sel);
|
|
}
|
|
val = [NSNumber numberWithDouble: v];
|
|
}
|
|
break;
|
|
|
|
case _C_VOID:
|
|
{
|
|
void (*imp)(id, SEL) =
|
|
(void (*)(id, SEL))[self methodForSelector: sel];
|
|
|
|
(*imp)(self, sel);
|
|
}
|
|
val = nil;
|
|
break;
|
|
|
|
default:
|
|
[NSException raise: NSInvalidArgumentException
|
|
format: @"key-value get method has unsupported type"];
|
|
}
|
|
return val;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This is used internally by the key-value coding methods, to set a
|
|
* value in an object either via an accessor method (if sel is
|
|
* supplied), or via direct access (if type, size, and offset are
|
|
* supplied).<br />
|
|
* Automatic conversion between NSNumber and C scalar types is performed.<br />
|
|
* If type is nul and can't be determined from the selector, the
|
|
* [NSObject-handleTakevalue:forUnboundKey:] method is called to try
|
|
* to set a value.
|
|
*/
|
|
void
|
|
GSSetValue(NSObject *self, NSString *key, id val, SEL sel,
|
|
const char *type, unsigned size, int offset)
|
|
{
|
|
if (sel != 0)
|
|
{
|
|
NSMethodSignature *sig = [self methodSignatureForSelector: sel];
|
|
|
|
if ([sig numberOfArguments] != 3)
|
|
{
|
|
[NSException raise: NSInvalidArgumentException
|
|
format: @"key-value set method has wrong number of args"];
|
|
}
|
|
type = [sig getArgumentTypeAtIndex: 2];
|
|
}
|
|
if (type == NULL)
|
|
{
|
|
[self handleTakeValue: val forUnboundKey: key];
|
|
}
|
|
else
|
|
{
|
|
switch (*type)
|
|
{
|
|
case _C_ID:
|
|
case _C_CLASS:
|
|
{
|
|
id v = val;
|
|
|
|
if (sel == 0)
|
|
{
|
|
id *ptr = (id *)((char *)self + offset);
|
|
|
|
[*ptr autorelease];
|
|
*ptr = [v retain];
|
|
}
|
|
else
|
|
{
|
|
void (*imp)(id, SEL, id) =
|
|
(void (*)(id, SEL, id))[self methodForSelector: sel];
|
|
|
|
(*imp)(self, sel, val);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case _C_CHR:
|
|
{
|
|
char v = [val charValue];
|
|
|
|
if (sel == 0)
|
|
{
|
|
char *ptr = (char *)((char *)self + offset);
|
|
|
|
*ptr = v;
|
|
}
|
|
else
|
|
{
|
|
void (*imp)(id, SEL, char) =
|
|
(void (*)(id, SEL, char))[self methodForSelector: sel];
|
|
|
|
(*imp)(self, sel, v);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case _C_UCHR:
|
|
{
|
|
unsigned char v = [val unsignedCharValue];
|
|
|
|
if (sel == 0)
|
|
{
|
|
unsigned char *ptr = (unsigned char*)((char *)self + offset);
|
|
|
|
*ptr = v;
|
|
}
|
|
else
|
|
{
|
|
void (*imp)(id, SEL, unsigned char) =
|
|
(void (*)(id, SEL, unsigned char))[self methodForSelector:
|
|
sel];
|
|
|
|
(*imp)(self, sel, v);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case _C_SHT:
|
|
{
|
|
short v = [val shortValue];
|
|
|
|
if (sel == 0)
|
|
{
|
|
short *ptr = (short*)((char *)self + offset);
|
|
|
|
*ptr = v;
|
|
}
|
|
else
|
|
{
|
|
void (*imp)(id, SEL, short) =
|
|
(void (*)(id, SEL, short))[self methodForSelector: sel];
|
|
|
|
(*imp)(self, sel, v);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case _C_USHT:
|
|
{
|
|
unsigned short v = [val unsignedShortValue];
|
|
|
|
if (sel == 0)
|
|
{
|
|
unsigned short *ptr;
|
|
|
|
ptr = (unsigned short*)((char *)self + offset);
|
|
*ptr = v;
|
|
}
|
|
else
|
|
{
|
|
void (*imp)(id, SEL, unsigned short) =
|
|
(void (*)(id, SEL, unsigned short))[self methodForSelector:
|
|
sel];
|
|
|
|
(*imp)(self, sel, v);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case _C_INT:
|
|
{
|
|
int v = [val intValue];
|
|
|
|
if (sel == 0)
|
|
{
|
|
int *ptr = (int*)((char *)self + offset);
|
|
|
|
*ptr = v;
|
|
}
|
|
else
|
|
{
|
|
void (*imp)(id, SEL, int) =
|
|
(void (*)(id, SEL, int))[self methodForSelector: sel];
|
|
|
|
(*imp)(self, sel, v);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case _C_UINT:
|
|
{
|
|
unsigned int v = [val unsignedIntValue];
|
|
|
|
if (sel == 0)
|
|
{
|
|
unsigned int *ptr = (unsigned int*)((char *)self + offset);
|
|
|
|
*ptr = v;
|
|
}
|
|
else
|
|
{
|
|
void (*imp)(id, SEL, unsigned int) =
|
|
(void (*)(id, SEL, unsigned int))[self methodForSelector:
|
|
sel];
|
|
|
|
(*imp)(self, sel, v);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case _C_LNG:
|
|
{
|
|
long v = [val longValue];
|
|
|
|
if (sel == 0)
|
|
{
|
|
long *ptr = (long*)((char *)self + offset);
|
|
|
|
*ptr = v;
|
|
}
|
|
else
|
|
{
|
|
void (*imp)(id, SEL, long) =
|
|
(void (*)(id, SEL, long))[self methodForSelector: sel];
|
|
|
|
(*imp)(self, sel, v);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case _C_ULNG:
|
|
{
|
|
unsigned long v = [val unsignedLongValue];
|
|
|
|
if (sel == 0)
|
|
{
|
|
unsigned long *ptr = (unsigned long*)((char *)self + offset);
|
|
|
|
*ptr = v;
|
|
}
|
|
else
|
|
{
|
|
void (*imp)(id, SEL, unsigned long) =
|
|
(void (*)(id, SEL, unsigned long))[self methodForSelector:
|
|
sel];
|
|
|
|
(*imp)(self, sel, v);
|
|
}
|
|
}
|
|
break;
|
|
|
|
#ifdef _C_LNG_LNG
|
|
case _C_LNG_LNG:
|
|
{
|
|
long long v = [val longLongValue];
|
|
|
|
if (sel == 0)
|
|
{
|
|
long long *ptr = (long long*)((char *)self + offset);
|
|
|
|
*ptr = v;
|
|
}
|
|
else
|
|
{
|
|
void (*imp)(id, SEL, long long) =
|
|
(void (*)(id, SEL, long long))[self methodForSelector: sel];
|
|
|
|
(*imp)(self, sel, v);
|
|
}
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
#ifdef _C_ULNG_LNG
|
|
case _C_ULNG_LNG:
|
|
{
|
|
unsigned long long v = [val unsignedLongLongValue];
|
|
|
|
if (sel == 0)
|
|
{
|
|
unsigned long long *ptr = (unsigned long long*)((char*)self +
|
|
offset);
|
|
|
|
*ptr = v;
|
|
}
|
|
else
|
|
{
|
|
void (*imp)(id, SEL, unsigned long long) =
|
|
(void (*)(id, SEL, unsigned long long))[self
|
|
methodForSelector: sel];
|
|
|
|
(*imp)(self, sel, v);
|
|
}
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
case _C_FLT:
|
|
{
|
|
float v = [val floatValue];
|
|
|
|
if (sel == 0)
|
|
{
|
|
float *ptr = (float*)((char *)self + offset);
|
|
|
|
*ptr = v;
|
|
}
|
|
else
|
|
{
|
|
void (*imp)(id, SEL, float) =
|
|
(void (*)(id, SEL, float))[self methodForSelector: sel];
|
|
|
|
(*imp)(self, sel, v);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case _C_DBL:
|
|
{
|
|
double v = [val doubleValue];
|
|
|
|
if (sel == 0)
|
|
{
|
|
double *ptr = (double*)((char *)self + offset);
|
|
|
|
*ptr = v;
|
|
}
|
|
else
|
|
{
|
|
void (*imp)(id, SEL, double) =
|
|
(void (*)(id, SEL, double))[self methodForSelector: sel];
|
|
|
|
(*imp)(self, sel, v);
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
[NSException raise: NSInvalidArgumentException
|
|
format: @"key-value set method has unsupported type"];
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* Getting a system error message on a variety of systems */
|
|
#ifdef __MINGW__
|
|
LPTSTR GetErrorMsg(DWORD msgId)
|
|
{
|
|
LPVOID lpMsgBuf;
|
|
|
|
FormatMessage(
|
|
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL, msgId,
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
|
(LPTSTR)&lpMsgBuf, 0, NULL);
|
|
|
|
return (LPTSTR)lpMsgBuf;
|
|
}
|
|
#else
|
|
#ifndef HAVE_STRERROR
|
|
const char*
|
|
strerror(int eno)
|
|
{
|
|
extern char* sys_errlist[];
|
|
extern int sys_nerr;
|
|
|
|
if (eno < 0 || eno >= sys_nerr)
|
|
{
|
|
return("unknown error number");
|
|
}
|
|
return(sys_errlist[eno]);
|
|
}
|
|
#endif
|
|
#endif /* __MINGW__ */
|
|
|
|
const char *GSLastErrorStr(long error_id)
|
|
{
|
|
#ifdef __MINGW__
|
|
return GetErrorMsg(GetLastError());
|
|
#else
|
|
return strerror(error_id);
|
|
#endif
|
|
}
|