Revert "Merge branch 'master' of github.com:pawn-lang/compiler into HEAD"
This reverts commit 5400511d8616964ddf2c78bb65e72dfc23fa3a25, reversing changes made to 2e15e645e687bc0ad4a210963de0bfadc56d48fc.
This commit is contained in:
parent
5400511d86
commit
c565a5d1df
202
source/amx/amx.h
202
source/amx/amx.h
@ -27,63 +27,54 @@
|
||||
#include <stdlib.h> /* for size_t */
|
||||
#include <limits.h>
|
||||
|
||||
#if (defined __linux || defined __linux__) && !defined __LINUX__
|
||||
#define __LINUX__
|
||||
#endif
|
||||
#if defined FREEBSD && !defined __FreeBSD__
|
||||
#define __FreeBSD__
|
||||
#endif
|
||||
#if defined __LINUX__ || defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__
|
||||
#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
|
||||
#include <sclinux.h>
|
||||
#endif
|
||||
|
||||
#if defined __GNUC__
|
||||
#define GCC_VERSION (__GNUC__ * 10000 \
|
||||
+ __GNUC_MINOR__ * 100 \
|
||||
+ __GNUC_PATCHLEVEL__)
|
||||
#endif
|
||||
|
||||
#if !defined HAVE_STDINT_H
|
||||
#if (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) \
|
||||
|| defined __GNUC__ || defined __LCC__ || defined __DMC__ \
|
||||
|| (defined __WATCOMC__ && __WATCOMC__ >= 1200)
|
||||
#define HAVE_STDINT_H 1
|
||||
#endif
|
||||
#endif
|
||||
#if !defined HAVE_INTTYPES_H
|
||||
#if defined __FreeBSD__ || defined __APPLE__
|
||||
#define HAVE_INTTYPES_H 1
|
||||
#endif
|
||||
#endif
|
||||
#if defined HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#elif defined HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#else
|
||||
#if defined __MACH__
|
||||
#include <ppc/types.h>
|
||||
#endif
|
||||
typedef short int int16_t;
|
||||
typedef unsigned short int uint16_t;
|
||||
#if defined SN_TARGET_PS2
|
||||
typedef int int32_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#else
|
||||
typedef long int int32_t;
|
||||
typedef unsigned long int uint32_t;
|
||||
#endif
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#define HAVE_I64
|
||||
#endif
|
||||
#if !defined _INTPTR_T_DEFINED
|
||||
#if defined _LP64 || defined WIN64 || defined _WIN64
|
||||
typedef __int64 intptr_t;
|
||||
#if defined __LCC__ || defined __DMC__ || defined LINUX || (defined __WATCOMC__ && __WATCOMC__ >= 1200)
|
||||
#if defined HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#else
|
||||
typedef int32_t intptr_t;
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#elif !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
|
||||
/* The ISO C99 defines the int16_t and int_32t types. If the compiler got
|
||||
* here, these types are probably undefined.
|
||||
*/
|
||||
#if defined __MACH__
|
||||
#include <ppc/types.h>
|
||||
typedef unsigned short int uint16_t;
|
||||
typedef unsigned long int uint32_t;
|
||||
#elif defined __FreeBSD__
|
||||
#include <inttypes.h>
|
||||
#else
|
||||
typedef short int int16_t;
|
||||
typedef unsigned short int uint16_t;
|
||||
#if defined SN_TARGET_PS2
|
||||
typedef int int32_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#else
|
||||
typedef long int int32_t;
|
||||
typedef unsigned long int uint32_t;
|
||||
#endif
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#define HAVE_I64
|
||||
#elif defined __GNUC__
|
||||
typedef long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
#define HAVE_I64
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#define HAVE_STDINT_H
|
||||
#endif
|
||||
#if defined _LP64 || defined WIN64 || defined _WIN64
|
||||
#if !defined __64BIT__
|
||||
@ -91,17 +82,8 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined HAVE_ALLOCA_H
|
||||
#if defined __GNUC__ || defined __LCC__ || defined __DMC__ || defined __ARMCC_VERSION
|
||||
#define HAVE_ALLOCA_H 1
|
||||
#elif defined __WATCOMC__ && __WATCOMC__ >= 1200
|
||||
#define HAVE_ALLOCA_H 1
|
||||
#endif
|
||||
#endif
|
||||
#if defined HAVE_ALLOCA_H && HAVE_ALLOCA_H
|
||||
#if HAVE_ALLOCA_H
|
||||
#include <alloca.h>
|
||||
#elif defined __BORLANDC__
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32 /* || defined __MSDOS__ */
|
||||
#if !defined alloca
|
||||
@ -112,21 +94,14 @@
|
||||
#if !defined arraysize
|
||||
#define arraysize(array) (sizeof(array) / sizeof((array)[0]))
|
||||
#endif
|
||||
|
||||
#if !defined assert_static
|
||||
#if (defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112) || GCC_VERSION >= 40600
|
||||
#define assert_static(test) _Static_assert(test, "assert")
|
||||
#else
|
||||
/* see "Compile-Time Assertions" by Greg Miller,
|
||||
* (with modifications to port it to C)
|
||||
*/
|
||||
#define _ASSERT_STATIC_SYMBOL_INNER(line) __ASSERT_STATIC_ ## line
|
||||
#define _ASSERT_STATIC_SYMBOL(line) _ASSERT_STATIC_SYMBOL_INNER(line)
|
||||
#define assert_static(test) \
|
||||
do { \
|
||||
typedef char _ASSERT_STATIC_SYMBOL(__LINE__)[ ((test) ? 1 : -1) ]; \
|
||||
} while (0)
|
||||
#endif
|
||||
/* see "Compile-Time Assertions" by Ralf Holly,
|
||||
* C/C++ Users Journal, November 2004
|
||||
*/
|
||||
#define assert_static(e) \
|
||||
do { \
|
||||
enum { assert_static__ = 1/(e) }; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -217,14 +192,9 @@ typedef int (AMXAPI *AMX_IDLE)(struct tagAMX *amx, int AMXAPI Exec(struct tagAMX
|
||||
#endif
|
||||
|
||||
#if defined _MSC_VER
|
||||
#pragma warning(disable:4103) /* disable warning message 4103 that complains
|
||||
* about pragma pack in a header file */
|
||||
#pragma warning(disable:4100) /* "'%$S' : unreferenced formal parameter" */
|
||||
#pragma warning(disable:4103) /* disable warning message 4103 that complains about pragma pack in a header file */
|
||||
#pragma warning(disable:4127) /* "conditional expression is constant" (needed for static_assert) */
|
||||
#pragma warning(disable:4996) /* POSIX name is deprecated */
|
||||
#elif defined __GNUC__
|
||||
#elif defined __clang__
|
||||
#pragma GCC diagnostic ignored "-Wlogical-op-parentheses"
|
||||
#pragma GCC diagnostic ignored "-Wbitwise-op-parentheses"
|
||||
#endif
|
||||
|
||||
/* Some compilers do not support the #pragma align, which should be fine. Some
|
||||
@ -337,15 +307,12 @@ typedef struct tagAMX_HEADER {
|
||||
int32_t nametable PACKED; /* name table */
|
||||
} AMX_HEADER;
|
||||
|
||||
#define AMX_MAGIC_16 0xf1e2
|
||||
#define AMX_MAGIC_32 0xf1e0
|
||||
#define AMX_MAGIC_64 0xf1e1
|
||||
#if PAWN_CELL_SIZE==16
|
||||
#define AMX_MAGIC AMX_MAGIC_16
|
||||
#define AMX_MAGIC 0xf1e2
|
||||
#elif PAWN_CELL_SIZE==32
|
||||
#define AMX_MAGIC AMX_MAGIC_32
|
||||
#define AMX_MAGIC 0xf1e0
|
||||
#elif PAWN_CELL_SIZE==64
|
||||
#define AMX_MAGIC AMX_MAGIC_64
|
||||
#define AMX_MAGIC 0xf1e1
|
||||
#endif
|
||||
|
||||
enum {
|
||||
@ -410,51 +377,19 @@ enum {
|
||||
#define amx_ftoc(f) ( * ((cell*)&f) ) /* float to cell */
|
||||
#define amx_ctof(c) ( * ((double*)&c) ) /* cell to float */
|
||||
#else
|
||||
// amx_ftoc() and amx_ctof() cannot be used
|
||||
#error Unsupported cell size
|
||||
#endif
|
||||
|
||||
/* when a pointer cannot be stored in a cell, cells that hold relocated
|
||||
* addresses need to be expanded
|
||||
*/
|
||||
#if defined __64BIT__ && PAWN_CELL_SIZE<64
|
||||
#define CELLMASK (((int64_t)1 << PAWN_CELL_SIZE) - 1)
|
||||
#define amx_Address(amx,addr) \
|
||||
(cell*)(((int64_t)((amx)->data ? (amx)->data : (amx)->code) & ~CELLMASK) | ((int64_t)(addr) & CELLMASK))
|
||||
#elif defined __32BIT__ && PAWN_CELL_SIZE<32
|
||||
#define CELLMASK ((1L << PAWN_CELL_SIZE) - 1)
|
||||
#define amx_Address(amx,addr) \
|
||||
(cell*)(((int32_t)((amx)->data ? (amx)->data : (amx)->code) & ~CELLMASK) | ((int32_t)(addr) & CELLMASK))
|
||||
#else
|
||||
#define amx_Address(amx,addr) \
|
||||
(cell*)(((int32_t)((amx)->data ? (amx)->data : (amx)->base+(int)((AMX_HEADER *)(amx)->base)->dat)) + ((int32_t)(addr)))
|
||||
#endif
|
||||
|
||||
#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
|
||||
/* C99: use variable-length arrays */
|
||||
#define amx_StrParam_Type(amx,param,result,type) \
|
||||
int result##_length_; \
|
||||
amx_StrLen(amx_Address(amx,param),&result##_length_); \
|
||||
char result##_vla_[(result##_length_+1)*sizeof(*(result))]; \
|
||||
(result)=(type)result##_vla_; \
|
||||
amx_GetString((char*)(result),amx_Address(amx,param), \
|
||||
sizeof(*(result))>1,result##_length_+1)
|
||||
#define amx_StrParam(amx,param,result) \
|
||||
amx_StrParam_Type(amx,param,result,void*)
|
||||
#else
|
||||
/* macro using alloca() */
|
||||
#define amx_StrParam_Type(amx,param,result,type) \
|
||||
#define amx_StrParam(amx,param,result) \
|
||||
do { \
|
||||
int result##_length_; \
|
||||
amx_StrLen(amx_Address(amx,param),&result##_length_); \
|
||||
if (result##_length_>0 && \
|
||||
((result)=(type)alloca((result##_length_+1)*sizeof(*(result))))!=NULL) \
|
||||
amx_GetString((char*)(result),amx_Address(amx,param), \
|
||||
sizeof(*(result))>1,result##_length_+1); \
|
||||
cell *amx_cstr_; int amx_length_; \
|
||||
amx_GetAddr((amx), (param), &amx_cstr_); \
|
||||
amx_StrLen(amx_cstr_, &amx_length_); \
|
||||
if (amx_length_ > 0 && \
|
||||
((result) = (void*)alloca((amx_length_ + 1) * sizeof(*(result)))) != NULL) \
|
||||
amx_GetString((char*)(result), amx_cstr_, sizeof(*(result))>1, amx_length_ + 1); \
|
||||
else (result) = NULL; \
|
||||
} while (0)
|
||||
#define amx_StrParam(amx,param,result) \
|
||||
amx_StrParam_Type(amx,param,result,void*)
|
||||
#endif
|
||||
|
||||
uint16_t * AMXAPI amx_Align16(uint16_t *v);
|
||||
uint32_t * AMXAPI amx_Align32(uint32_t *v);
|
||||
@ -504,24 +439,11 @@ int AMXAPI amx_UTF8Len(const cell *cstr, int *length);
|
||||
int AMXAPI amx_UTF8Put(char *string, char **endptr, int maxchars, cell value);
|
||||
|
||||
#if PAWN_CELL_SIZE==16
|
||||
void amx_Swap16(uint16_t *v);
|
||||
#endif
|
||||
#if PAWN_CELL_SIZE==32
|
||||
void amx_Swap32(uint32_t *v);
|
||||
#endif
|
||||
#if PAWN_CELL_SIZE==64 && (defined _I64_MAX || defined INT64_MAX || defined HAVE_I64)
|
||||
void amx_Swap64(uint64_t *v);
|
||||
#endif
|
||||
|
||||
#if PAWN_CELL_SIZE==16
|
||||
#define amx_AlignCell(v) amx_Align16((uint16_t*)(v))
|
||||
#define amx_SwapCell(v) amx_Swap16((uint16_t*)(v))
|
||||
#define amx_AlignCell(v) amx_Align16(v)
|
||||
#elif PAWN_CELL_SIZE==32
|
||||
#define amx_AlignCell(v) amx_Align32((uint32_t*)(v))
|
||||
#define amx_SwapCell(v) amx_Swap32((uint32_t*)(v))
|
||||
#elif PAWN_CELL_SIZE==64 && (defined _I64_MAX || defined INT64_MAX || defined HAVE_I64)
|
||||
#define amx_AlignCell(v) amx_Align64((uint64_t*)(v))
|
||||
#define amx_SwapCell(v) amx_Swap64((uint64_t*)(v))
|
||||
#define amx_AlignCell(v) amx_Align32(v)
|
||||
#elif PAWN_CELL_SIZE==64 && (defined _I64_MAX || defined HAVE_I64)
|
||||
#define amx_AlignCell(v) amx_Align64(v)
|
||||
#else
|
||||
#error Unsupported cell size
|
||||
#endif
|
||||
@ -530,7 +452,7 @@ int AMXAPI amx_UTF8Put(char *string, char **endptr, int maxchars, cell value);
|
||||
amx_Register((amx), amx_NativeInfo((name),(func)), 1);
|
||||
|
||||
#if !defined AMX_NO_ALIGN
|
||||
#if defined __LINUX__ || defined __FreeBSD__ || defined __APPLE__
|
||||
#if defined LINUX || defined __FreeBSD__
|
||||
#pragma pack() /* reset default packing */
|
||||
#elif defined MACOS && defined __MWERKS__
|
||||
#pragma options align=reset
|
||||
|
@ -10,15 +10,15 @@
|
||||
* All strings MUST have an explicit \0. See the Windows SDK documentation
|
||||
* for details on version information and the VERSIONINFO structure.
|
||||
*/
|
||||
#define VERSION 4
|
||||
#define REVISION 0
|
||||
#define VERSION 1
|
||||
#define REVISION 1
|
||||
#define BUILD 0
|
||||
#define VERSIONSTR "4.0.0\0"
|
||||
#define VERSIONSTR "1.1.0\0"
|
||||
#define VERSIONNAME "amxFile.dll\0"
|
||||
#define VERSIONDESCRIPTION "Pawn AMX: File I/O support\0"
|
||||
#define VERSIONCOMPANYNAME "ITB CompuPhase\0"
|
||||
#define VERSIONPRODUCTNAME "amxFile\0"
|
||||
#define VERSIONCOPYRIGHT "Copyright \251 2004-2016 ITB CompuPhase\0"
|
||||
#define VERSIONCOPYRIGHT "Copyright \251 2004-2006 ITB CompuPhase\0"
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION VERSION, REVISION, BUILD, 0
|
||||
|
@ -10,15 +10,15 @@
|
||||
* All strings MUST have an explicit \0. See the Windows SDK documentation
|
||||
* for details on version information and the VERSIONINFO structure.
|
||||
*/
|
||||
#define VERSION 4
|
||||
#define VERSION 1
|
||||
#define REVISION 0
|
||||
#define BUILD 0
|
||||
#define VERSIONSTR "4.0.0\0"
|
||||
#define VERSIONSTR "1.0.0\0"
|
||||
#define VERSIONNAME "amxFloat.dll\0"
|
||||
#define VERSIONDESCRIPTION "Pawn AMX: Floating Point support\0"
|
||||
#define VERSIONCOMPANYNAME "ITB CompuPhase\0"
|
||||
#define VERSIONPRODUCTNAME "amxFloat\0"
|
||||
#define VERSIONCOPYRIGHT "Copyright \251 2003-2013 ITB CompuPhase\0"
|
||||
#define VERSIONCOPYRIGHT "Copyright \251 2003-2006 ITB CompuPhase\0"
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION VERSION, REVISION, BUILD, 0
|
||||
|
@ -1,20 +1,24 @@
|
||||
/* Script Arguments support module for the Pawn Abstract Machine
|
||||
*
|
||||
* Copyright (c) ITB CompuPhase, 2005-2016
|
||||
* Copyright (c) ITB CompuPhase, 2005-2006
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at
|
||||
* This software is provided "as-is", without any express or implied warranty.
|
||||
* In no event will the authors be held liable for any damages arising from
|
||||
* the use of this software.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software in
|
||||
* a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* Version: $Id: amxargs.c 5588 2016-10-25 11:13:28Z $
|
||||
* Version: $Id: amxargs.c 3649 2006-10-12 13:13:57Z thiadmer $
|
||||
*/
|
||||
|
||||
#if defined _UNICODE || defined __UNICODE__ || defined UNICODE
|
||||
@ -32,16 +36,13 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "osdefs.h"
|
||||
#if defined __WIN32__ || defined __MSDOS__
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32 || defined __MSDOS__
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#if defined __WIN32__ || defined _Windows
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32 || defined _Windows
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#if defined __GNUC__ || defined __clang__
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include "osdefs.h"
|
||||
#include "amx.h"
|
||||
|
||||
#if defined _UNICODE
|
||||
@ -91,8 +92,8 @@ static const TCHAR *rawcmdline(void)
|
||||
{
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32
|
||||
#elif defined _Windows || defined __MSDOS__
|
||||
static char cmdbuffer[128]; /* DOS & Windows 3.1 are never in Unicode mode */
|
||||
#elif defined __LINUX__
|
||||
static char cmdbuffer[128];
|
||||
#elif defined LINUX
|
||||
static char cmdbuffer[1024]; /* some arbitrary maximum */
|
||||
#endif
|
||||
const TCHAR *ptr;
|
||||
@ -115,7 +116,7 @@ static const TCHAR *rawcmdline(void)
|
||||
if ((cmd == strchr(cmdbuffer, '\r')) != NULL)
|
||||
*cmd = '\0'; /* also erase \r after the last option (if any) */
|
||||
cmdline = cmdbuffer;
|
||||
#elif defined __LINUX__
|
||||
#elif defined LINUX
|
||||
/* Options in /proc/<pid>/cmdline are delimited with '\0' characters
|
||||
* rather than spaces.
|
||||
*/
|
||||
@ -132,6 +133,7 @@ static const TCHAR *rawcmdline(void)
|
||||
fread(cmdbuffer, 1, fsize, fp);
|
||||
fclose(fp);
|
||||
cmdbuffer[fsize] = '\0'; /* terminate with double-zero */
|
||||
// ??? convert to Unicode
|
||||
/* convert '\0' characters to spaces, for uniform parsing */
|
||||
for (ptr = cmdbuffer; *ptr != ' '; ptr = strchr(ptr, '\0') + 1)
|
||||
*ptr = ' ';
|
||||
@ -139,10 +141,7 @@ static const TCHAR *rawcmdline(void)
|
||||
skip++;
|
||||
} /* if */
|
||||
#else
|
||||
/* no mechanism for determining the commandline, so it
|
||||
* must be supplied with amx_ArgsSetCmdLine() instead.
|
||||
*/
|
||||
ptr = "";
|
||||
#error Platform not supported
|
||||
#endif
|
||||
|
||||
/* skip leading white space */
|
||||
@ -210,7 +209,7 @@ static const TCHAR *matcharg(const TCHAR *key, int skip, int *length)
|
||||
int index, optlen, keylen;
|
||||
const TCHAR *option, *vptr;
|
||||
|
||||
keylen = (key != NULL) ? (int)_tcslen(key) : 0;
|
||||
keylen = (key != NULL) ? _tcslen(key) : 0;
|
||||
index = 0;
|
||||
while ((option = tokenize(cmdline, index, length)) != NULL) {
|
||||
/* check for a colon or an equal sign (':' or '=') */
|
||||
@ -229,7 +228,7 @@ static const TCHAR *matcharg(const TCHAR *key, int skip, int *length)
|
||||
optlen++; /* if ':' or '=' was found, skip it too */
|
||||
option += optlen; /* point behind option */
|
||||
*length -= optlen; /* length of the value, not of the option */
|
||||
assert(*length >= 0);
|
||||
assert(length >= 0);
|
||||
if (skip-- == 0)
|
||||
break;
|
||||
} /* if */
|
||||
@ -253,7 +252,11 @@ static cell AMX_NATIVE_CALL n_argindex(AMX *amx, const cell *params)
|
||||
max = (int)params[3];
|
||||
if (max <= 0)
|
||||
return 0;
|
||||
cptr = amx_Address(amx, params[2]);
|
||||
amx_GetAddr(amx, params[2], &cptr);
|
||||
if (cptr == NULL) {
|
||||
amx_RaiseError(amx, AMX_ERR_NATIVE);
|
||||
return 0;
|
||||
} /* if */
|
||||
|
||||
if ((option = tokenize(cmdline, params[1], &length)) == NULL) {
|
||||
/* option not found, return an empty string */
|
||||
@ -291,7 +294,11 @@ static cell AMX_NATIVE_CALL n_argstr(AMX *amx, const cell *params)
|
||||
if (max <= 0)
|
||||
return 0;
|
||||
amx_StrParam(amx, params[2], key);
|
||||
cptr = amx_Address(amx, params[3]);
|
||||
amx_GetAddr(amx, params[3], &cptr);
|
||||
if (cptr == NULL) {
|
||||
amx_RaiseError(amx, AMX_ERR_NATIVE);
|
||||
return 0;
|
||||
} /* if */
|
||||
|
||||
option = matcharg(key, (int)params[1], &length);
|
||||
if (option == NULL)
|
||||
@ -330,7 +337,11 @@ static cell AMX_NATIVE_CALL n_argvalue(AMX *amx, const cell *params)
|
||||
cell *cptr;
|
||||
|
||||
amx_StrParam(amx, params[2], key);
|
||||
cptr = amx_Address(amx, params[3]);
|
||||
amx_GetAddr(amx, params[3], &cptr);
|
||||
if (cptr == NULL) {
|
||||
amx_RaiseError(amx, AMX_ERR_NATIVE);
|
||||
return 0;
|
||||
} /* if */
|
||||
|
||||
option = matcharg(key, (int)params[1], &length);
|
||||
if (option == NULL)
|
||||
@ -367,12 +378,12 @@ const AMX_NATIVE_INFO args_Natives[] = {
|
||||
{ NULL, NULL } /* terminator */
|
||||
};
|
||||
|
||||
int AMXEXPORT AMXAPI amx_ArgsInit(AMX *amx)
|
||||
int AMXEXPORT amx_ArgsInit(AMX *amx)
|
||||
{
|
||||
return amx_Register(amx, args_Natives, -1);
|
||||
}
|
||||
|
||||
int AMXEXPORT AMXAPI amx_ArgsCleanup(AMX *amx)
|
||||
int AMXEXPORT amx_ArgsCleanup(AMX *amx)
|
||||
{
|
||||
(void)amx;
|
||||
return AMX_ERR_NONE;
|
||||
@ -384,7 +395,7 @@ int AMXEXPORT AMXAPI amx_ArgsCleanup(AMX *amx)
|
||||
* that is passed in to this function is NOT copied, so it may not be freed
|
||||
* after the call.
|
||||
*/
|
||||
int AMXEXPORT AMXAPI amx_ArgsSetCmdLine(const TCHAR *cmd)
|
||||
int AMXEXPORT amx_ArgsSetCmdLine(const TCHAR *cmd)
|
||||
{
|
||||
cmdline = cmd;
|
||||
return AMX_ERR_NONE;
|
||||
|
@ -1,6 +0,0 @@
|
||||
NAME amxArgs
|
||||
DESCRIPTION 'Pawn AMX: Script Arguments support'
|
||||
|
||||
EXPORTS
|
||||
amx_ArgsInit
|
||||
amx_ArgsCleanup
|
@ -10,15 +10,15 @@
|
||||
* All strings MUST have an explicit \0. See the Windows SDK documentation
|
||||
* for details on version information and the VERSIONINFO structure.
|
||||
*/
|
||||
#define VERSION 4
|
||||
#define VERSION 1
|
||||
#define REVISION 0
|
||||
#define BUILD 0
|
||||
#define VERSIONSTR "4.0.0\0"
|
||||
#define VERSIONSTR "1.0.0\0"
|
||||
#define VERSIONNAME "amxArgs.dll\0"
|
||||
#define VERSIONDESCRIPTION "Pawn AMX: Script Arguments support\0"
|
||||
#define VERSIONCOMPANYNAME "ITB CompuPhase\0"
|
||||
#define VERSIONPRODUCTNAME "amxArgs\0"
|
||||
#define VERSIONCOPYRIGHT "Copyright \251 2005-2016 ITB CompuPhase\0"
|
||||
#define VERSIONCOPYRIGHT "Copyright \251 2005-2006 ITB CompuPhase\0"
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION VERSION, REVISION, BUILD, 0
|
||||
|
@ -4,21 +4,25 @@
|
||||
* cannot always be implemented with portable C functions. In other words,
|
||||
* these routines must be ported to other environments.
|
||||
*
|
||||
* Copyright (c) ITB CompuPhase, 1997-2016
|
||||
* Copyright (c) ITB CompuPhase, 1997-2006
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at
|
||||
* This software is provided "as-is", without any express or implied warranty.
|
||||
* In no event will the authors be held liable for any damages arising from
|
||||
* the use of this software.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software in
|
||||
* a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* Version: $Id: amxcons.c 5587 2016-10-25 09:59:46Z $
|
||||
* Version: $Id: amxcons.c 3649 2006-10-12 13:13:57Z thiadmer $
|
||||
*/
|
||||
|
||||
#if defined _UNICODE || defined __UNICODE__ || defined UNICODE
|
||||
@ -36,26 +40,13 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32 || defined __MSDOS__
|
||||
#define HAVE_CONIO
|
||||
#include <conio.h>
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#if defined USE_CURSES || defined HAVE_CURSES_H
|
||||
#if defined USE_CURSES
|
||||
#include <curses.h>
|
||||
#if !defined CURSES
|
||||
#define CURSES 1
|
||||
#endif
|
||||
#endif
|
||||
#include "osdefs.h"
|
||||
#if defined __ECOS__
|
||||
/* eCos puts include files in cyg/package_name */
|
||||
#include <cyg/hal/hal_if.h>
|
||||
#include <cyg/infra/diag.h>
|
||||
#include <cyg/hal/hal_diag.h>
|
||||
#include <cyg/pawn/amx.h>
|
||||
#else
|
||||
#include "amx.h"
|
||||
#endif
|
||||
#include "amx.h"
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
@ -65,21 +56,18 @@
|
||||
#elif !defined __T
|
||||
typedef char TCHAR;
|
||||
# define __T(string) string
|
||||
# define _fgetts fgets
|
||||
# define _puttchar putchar
|
||||
# define _stprintf sprintf
|
||||
# define _tcschr strchr
|
||||
# define _tcscpy strcpy
|
||||
# define _tcsdup strdup
|
||||
# define _tcslen strlen
|
||||
# define _tprintf printf
|
||||
# define _stprintf sprintf
|
||||
#endif
|
||||
#include "amxcons.h"
|
||||
|
||||
#if defined AMX_TERMINAL
|
||||
#if defined __MSDOS__
|
||||
#define EOL_CHAR '\r'
|
||||
#endif
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32 || defined __MSDOS__
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32
|
||||
#define EOL_CHAR '\r'
|
||||
#endif
|
||||
#if !defined EOL_CHAR
|
||||
@ -99,118 +87,17 @@
|
||||
int amx_termctl(int,int);
|
||||
void amx_clrscr(void);
|
||||
void amx_clreol(void);
|
||||
int amx_gotoxy(int x,int y);
|
||||
void amx_gotoxy(int x,int y);
|
||||
void amx_wherexy(int *x,int *y);
|
||||
unsigned int amx_setattr(int foregr,int backgr,int highlight);
|
||||
void amx_console(int columns, int lines, int flags);
|
||||
void amx_viewsize(int *width,int *height);
|
||||
int amx_kbhit(void);
|
||||
#elif defined CURSES && CURSES != 0
|
||||
/* Use the "curses" library to implement the console */
|
||||
static WINDOW *curseswin;
|
||||
#define amx_putstr(s) printw("%s",(s))
|
||||
#define amx_putchar(c) addch(c)
|
||||
#define amx_fflush() refresh()
|
||||
#define amx_getch() getch()
|
||||
#define amx_gets(s,n) getnstr((s),(n))
|
||||
#define amx_clrscr() clear()
|
||||
#define amx_clreol() clrtoeol()
|
||||
#define amx_gotoxy(x,y) move((y)-1,(x)-1)
|
||||
#define amx_console(c,l,f) ((void)(c),(void)(l),(void)(f))
|
||||
unsigned int amx_setattr(int foregr,int backgr,int highlight)
|
||||
{
|
||||
if (highlight>0)
|
||||
attron(A_STANDOUT);
|
||||
else
|
||||
attroff(A_STANDOUT);
|
||||
//??? in future, also handle colours
|
||||
}
|
||||
void CreateConsole(void);
|
||||
int amx_kbhit(void)
|
||||
{
|
||||
int result;
|
||||
CreateConsole();
|
||||
nodelay(curseswin,TRUE); /* enter non-blocking state */
|
||||
result=getch(); /* read key (if any) */
|
||||
nodelay(curseswin,FALSE); /* leave non-blocking state */
|
||||
if (result!=ERR)
|
||||
ungetch(result); /* a key is waiting, push it back */
|
||||
return (result==ERR) ? 0 : 1;
|
||||
}
|
||||
int amx_termctl(int code,int value)
|
||||
{
|
||||
switch (code) {
|
||||
case 0: /* query terminal support */
|
||||
return 1;
|
||||
/* case 1: */ /* switch auto-wrap on/off (not supported in curses!) */
|
||||
/* case 2: */ /* create/switch to another console */
|
||||
case 3: /* set emphasized font */
|
||||
if (value)
|
||||
attron(A_BOLD);
|
||||
else
|
||||
attroff(A_BOLD);
|
||||
return 1;
|
||||
/* case 4: */ /* query whether a terminal is "open" */
|
||||
default:
|
||||
return 0;
|
||||
} /* switch */
|
||||
}
|
||||
void amx_wherexy(int *x,int *y)
|
||||
{
|
||||
int row,col;
|
||||
getyx(curseswin,row,col);
|
||||
if (x!=NULL)
|
||||
*x=col+1;
|
||||
if (y!=NULL)
|
||||
*y=row+1;
|
||||
}
|
||||
void amx_viewsize(int *width,int *height)
|
||||
{
|
||||
int row,col;
|
||||
getmaxyx(curseswin,row,col);
|
||||
if (width!=NULL)
|
||||
*width=col;
|
||||
if (height!=NULL)
|
||||
*height=row;
|
||||
}
|
||||
#elif defined VT100 || defined __LINUX__ || defined ANSITERM || defined __ECOS__
|
||||
#elif defined VT100 || defined LINUX || defined ANSITERM
|
||||
/* ANSI/VT100 terminal, or shell emulating "xterm" */
|
||||
#if defined __ECOS__
|
||||
#define AMXCONSOLE_NOIDLE
|
||||
#endif
|
||||
|
||||
#if CYGPKG_PAWN_AMXCONSOLE_DIAG==1
|
||||
/* eCos has basically two ways to make simple exchanges with a terminal:
|
||||
* - with the diag_*() functions (no input provided!)
|
||||
* - with f*() functions (fprintf(),fputs(), etc).
|
||||
*/
|
||||
#define amx_fflush()
|
||||
|
||||
static int amx_putstr(TCHAR *s)
|
||||
{
|
||||
diag_write_string(s);
|
||||
return 1;
|
||||
}
|
||||
static int amx_putchar(TCHAR c)
|
||||
{
|
||||
diag_write_char(c);
|
||||
return c;
|
||||
}
|
||||
static char amx_getch(void)
|
||||
{
|
||||
char c=-1;
|
||||
HAL_DIAG_READ_CHAR(c);
|
||||
return c;
|
||||
}
|
||||
#else
|
||||
|
||||
#define amx_putstr(s) fputs((s),stdout)
|
||||
#define amx_putchar(c) putchar(c)
|
||||
#define amx_fflush() fflush(stdout)
|
||||
#define amx_getch() getch()
|
||||
#define amx_gets(s,n) fgets(s,n,stdin)
|
||||
#define amx_kbhit() kbhit()
|
||||
#endif
|
||||
#define amx_putstr(s) printf("%s",(s))
|
||||
#define amx_putchar(c) putchar(c)
|
||||
#define amx_fflush() fflush(stdout)
|
||||
#define amx_getch() getch()
|
||||
#define amx_gets(s,n) fgets(s,n,stdin)
|
||||
|
||||
int amx_termctl(int code,int value)
|
||||
{
|
||||
@ -257,13 +144,12 @@
|
||||
amx_putstr("\033[K");
|
||||
amx_fflush(); /* pump through the terminal codes */
|
||||
}
|
||||
int amx_gotoxy(int x,int y)
|
||||
void amx_gotoxy(int x,int y)
|
||||
{
|
||||
char str[30];
|
||||
_stprintf(str,"\033[%d;%dH",y,x);
|
||||
amx_putstr(str);
|
||||
amx_fflush(); /* pump through the terminal codes */
|
||||
return 1;
|
||||
}
|
||||
void amx_wherexy(int *x,int *y)
|
||||
{
|
||||
@ -280,13 +166,11 @@
|
||||
for (i=0; i<8 && (val=amx_getch())!=';'; i++)
|
||||
str[i]=(char)val;
|
||||
str[i]='\0';
|
||||
if (y!=NULL)
|
||||
*y=atoi(str);
|
||||
*y=atoi(str);
|
||||
for (i=0; i<8 && (val=amx_getch())!='R'; i++)
|
||||
str[i]=(char)val;
|
||||
str[i]='\0';
|
||||
if (x!=NULL)
|
||||
*x=atoi(str);
|
||||
*x=atoi(str);
|
||||
#if defined ANSITERM
|
||||
val=amx_getch();
|
||||
assert(val=='\r'); /* ANSI driver adds CR to the end of the command */
|
||||
@ -330,20 +214,13 @@
|
||||
amx_putstr(str);
|
||||
amx_fflush();
|
||||
}
|
||||
void amx_viewsize(int *width,int *height)
|
||||
{
|
||||
/* a trick to get the size of the terminal is to position the cursor far
|
||||
* away and then read it back
|
||||
*/
|
||||
amx_gotoxy(999,999);
|
||||
amx_wherexy(width,height);
|
||||
}
|
||||
#elif defined __WIN32__ || defined _WIN32 || defined WIN32
|
||||
/* Win32 console */
|
||||
#define amx_putstr(s) _tprintf("%s",(s))
|
||||
#define amx_putchar(c) _puttchar(c)
|
||||
#define amx_fflush() fflush(stdout)
|
||||
#define amx_gets(s,n) _fgetts(s,n,stdin)
|
||||
#define amx_putstr(s) printf("%s",(s))
|
||||
#define amx_putchar(c) putchar(c)
|
||||
#define amx_fflush() fflush(stdout)
|
||||
#define amx_getch() getch()
|
||||
#define amx_gets(s,n) fgets(s,n,stdin)
|
||||
|
||||
int amx_termctl(int code,int value)
|
||||
{
|
||||
@ -354,13 +231,10 @@
|
||||
case 1: { /* switch auto-wrap on/off */
|
||||
/* only works in Windows 2000/XP */
|
||||
HANDLE hConsole=GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
DWORD mode;
|
||||
GetConsoleMode(hConsole,&mode);
|
||||
DWORD Flags=ENABLE_PROCESSED_OUTPUT;
|
||||
if (value)
|
||||
mode |= ENABLE_WRAP_AT_EOL_OUTPUT;
|
||||
else
|
||||
mode &= ~ENABLE_WRAP_AT_EOL_OUTPUT;
|
||||
SetConsoleMode(hConsole,mode);
|
||||
Flags |= ENABLE_WRAP_AT_EOL_OUTPUT;
|
||||
SetConsoleMode(hConsole,Flags);
|
||||
return 1;
|
||||
} /* case */
|
||||
|
||||
@ -399,7 +273,7 @@
|
||||
FillConsoleOutputCharacter(hConsole,' ',dwConSize,csbi.dwCursorPosition,&cCharsWritten);
|
||||
FillConsoleOutputAttribute(hConsole,csbi.wAttributes,dwConSize,csbi.dwCursorPosition,&cCharsWritten);
|
||||
}
|
||||
int amx_gotoxy(int x,int y)
|
||||
void amx_gotoxy(int x,int y)
|
||||
{
|
||||
COORD point;
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
@ -407,12 +281,11 @@
|
||||
|
||||
GetConsoleScreenBufferInfo(hConsole, &csbi);
|
||||
if (x<=0 || x>csbi.dwSize.X || y<=0 || y>csbi.dwSize.Y)
|
||||
return 0;
|
||||
return;
|
||||
amx_fflush(); /* make sure all output is written */
|
||||
point.X=(short)(x-1);
|
||||
point.Y=(short)(y-1);
|
||||
SetConsoleCursorPosition(hConsole,point);
|
||||
return 1;
|
||||
}
|
||||
void amx_wherexy(int *x,int *y)
|
||||
{
|
||||
@ -450,58 +323,30 @@
|
||||
{
|
||||
SMALL_RECT rect;
|
||||
COORD dwSize;
|
||||
HANDLE hConsole;
|
||||
(void)flags;
|
||||
dwSize.X=(short)columns;
|
||||
dwSize.Y=(short)lines;
|
||||
hConsole=GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
SetConsoleScreenBufferSize(hConsole,dwSize);
|
||||
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE),dwSize);
|
||||
rect.Left=0;
|
||||
rect.Top=0;
|
||||
rect.Right=(short)(columns-1);
|
||||
rect.Bottom=(short)(lines-1);
|
||||
SetConsoleWindowInfo(hConsole,TRUE,&rect);
|
||||
}
|
||||
void amx_viewsize(int *width,int *height)
|
||||
{
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),&csbi);
|
||||
if (width!=NULL)
|
||||
*width=(int)csbi.dwSize.X;
|
||||
if (height!=NULL)
|
||||
*height=(int)(csbi.srWindow.Bottom-csbi.srWindow.Top+1);
|
||||
}
|
||||
int amx_getch(void)
|
||||
{
|
||||
TCHAR ch;
|
||||
DWORD count,mode;
|
||||
HANDLE hConsole=GetStdHandle(STD_INPUT_HANDLE);
|
||||
GetConsoleMode(hConsole,&mode);
|
||||
SetConsoleMode(hConsole,mode & ~(ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT));
|
||||
while (ReadFile(hConsole,&ch,1,&count,NULL) && count==0)
|
||||
/* nothing */;
|
||||
SetConsoleMode(hConsole,mode);
|
||||
if (count>0)
|
||||
return ch;
|
||||
return EOF;
|
||||
}
|
||||
int amx_kbhit(void)
|
||||
{
|
||||
DWORD count=0;
|
||||
HANDLE hConsole;
|
||||
hConsole=GetStdHandle(STD_INPUT_HANDLE);
|
||||
if (GetFileType(hConsole)==FILE_TYPE_PIPE) {
|
||||
PeekNamedPipe(hConsole,NULL,0,NULL,&count,NULL);
|
||||
} else {
|
||||
INPUT_RECORD rec;
|
||||
while (PeekConsoleInput(hConsole,&rec,1,&count)) {
|
||||
if (count==0 || (rec.EventType==KEY_EVENT && rec.Event.KeyEvent.bKeyDown))
|
||||
break;
|
||||
ReadConsoleInput(hConsole,&rec,1,&count);
|
||||
}
|
||||
}
|
||||
return (count>0);
|
||||
SetConsoleWindowInfo(GetStdHandle(STD_OUTPUT_HANDLE),TRUE,&rect);
|
||||
}
|
||||
#elif defined USE_CURSES
|
||||
/* Use the "curses" library to implement the console */
|
||||
#define amx_putstr(s) printw("%s",(s))
|
||||
#define amx_putchar(c) addch(c)
|
||||
#define amx_fflush() (0)
|
||||
#define amx_getch() getch()
|
||||
#define amx_gets(s,n) getnstr(s,n)
|
||||
#define amx_clrscr() clear()
|
||||
#define amx_clreol() clrtoeol()
|
||||
#define amx_gotoxy(x,y) (void)(0)
|
||||
#define amx_wherexy(x,y) (*(x)=*(y)=0)
|
||||
#define amx_setattr(c,b,h) (0)
|
||||
#define amx_termctl(c,v) (0)
|
||||
#define amx_console(c,l,f) (void)(0)
|
||||
#else
|
||||
/* assume a streaming terminal; limited features (no colour, no cursor
|
||||
* control)
|
||||
@ -509,22 +354,15 @@
|
||||
#define amx_putstr(s) printf("%s",(s))
|
||||
#define amx_putchar(c) putchar(c)
|
||||
#define amx_fflush() fflush(stdout)
|
||||
#define amx_getch() getch()
|
||||
#define amx_gets(s,n) fgets(s,n,stdin)
|
||||
#define amx_clrscr() (void)(0)
|
||||
#define amx_clreol() (void)(0)
|
||||
#define amx_gotoxy(x,y) ((void)(x),(void)(y),(0))
|
||||
#define amx_gotoxy(x,y) ((void)(x),(void)(y))
|
||||
#define amx_wherexy(x,y) (*(x)=*(y)=0)
|
||||
#define amx_setattr(c,b,h) ((void)(c),(void)(b),(void)(h),(0))
|
||||
#define amx_termctl(c,v) ((void)(c),(void)(v),(0))
|
||||
#define amx_console(c,l,f) ((void)(c),(void)(l),(void)(f))
|
||||
#define amx_viewsize (*(x)=80,*(y)=25)
|
||||
#if defined HAVE_CONIO
|
||||
#define amx_getch() getch()
|
||||
#define amx_kbhit() kbhit()
|
||||
#else
|
||||
#define amx_getch() getchar()
|
||||
#define amx_kbhit() (0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined AMX_TERMINAL && (defined __WIN32__ || defined _WIN32 || defined WIN32)
|
||||
@ -535,22 +373,20 @@
|
||||
createdconsole=1;
|
||||
} /* if */
|
||||
}
|
||||
#elif defined CURSES && CURSES != 0
|
||||
#elif defined USE_CURSES
|
||||
// The Mac OS X build variant uses curses.
|
||||
void CreateConsole(void)
|
||||
{ static int createdconsole=0;
|
||||
if (!createdconsole) {
|
||||
curseswin=initscr();
|
||||
if (has_colors())
|
||||
start_color();
|
||||
initscr();
|
||||
cbreak();
|
||||
noecho();
|
||||
nonl();
|
||||
scrollok(curseswin,TRUE);
|
||||
intrflush(curseswin,FALSE);
|
||||
keypad(curseswin,TRUE);
|
||||
createdconsole=1;
|
||||
} /* if */
|
||||
intrflush(stdscr, FALSE);
|
||||
keypad(stdscr, TRUE);
|
||||
|
||||
createdconsole=1;
|
||||
} /* if */
|
||||
}
|
||||
#else
|
||||
#define CreateConsole()
|
||||
@ -610,19 +446,12 @@ static TCHAR *amx_strval(TCHAR buffer[], long value, int format, int width)
|
||||
if (value < 0) {
|
||||
buffer[0] = __T('-');
|
||||
start = stop = 1;
|
||||
do {
|
||||
temp = (TCHAR)(value % 10);
|
||||
if (temp > 0)
|
||||
temp = (TCHAR)(temp - 10);
|
||||
buffer[stop++] = (TCHAR)(__T('0') - temp);
|
||||
value /= 10;
|
||||
} while (value != 0);
|
||||
} else {
|
||||
do {
|
||||
buffer[stop++] = (TCHAR)((value % 10) + __T('0'));
|
||||
value /= 10;
|
||||
} while (value != 0);
|
||||
}
|
||||
value = -value;
|
||||
} /* if */
|
||||
do {
|
||||
buffer[stop++] = (TCHAR)((value % 10) + __T('0'));
|
||||
value /= 10;
|
||||
} while (value > 0);
|
||||
} else {
|
||||
/* hexadecimal */
|
||||
unsigned long v = (unsigned long)value; /* copy to unsigned value for shifting */
|
||||
@ -690,7 +519,7 @@ static TCHAR *formatfixed(TCHAR *string,cell value,TCHAR align,int width,TCHAR d
|
||||
string[0]=__T('\0');
|
||||
|
||||
/* add sign */
|
||||
i=(int)_tcslen(string);
|
||||
i=_tcslen(string);
|
||||
string[i]=vsign;
|
||||
string[i+1]=__T('\0');
|
||||
|
||||
@ -699,12 +528,12 @@ static TCHAR *formatfixed(TCHAR *string,cell value,TCHAR align,int width,TCHAR d
|
||||
|
||||
/* add fractional part */
|
||||
if (digits>0) {
|
||||
i=(int)_tcslen(string);
|
||||
i=_tcslen(string);
|
||||
string[i]=decpoint;
|
||||
amx_strval(string+i+1,(long)value,SV_DECIMAL,-digits);
|
||||
} /* if */
|
||||
|
||||
len=(int)_tcslen(string);
|
||||
len=_tcslen(string);
|
||||
if (len<width) {
|
||||
/* pad to the requested width */
|
||||
for (i=len; i<width; i++)
|
||||
@ -741,8 +570,12 @@ static int dochar(AMX *amx,TCHAR ch,cell param,TCHAR sign,TCHAR decpoint,int wid
|
||||
assert(f_putchar!=NULL);
|
||||
|
||||
switch (ch) {
|
||||
case __T('%'):
|
||||
f_putchar(user,ch);
|
||||
return 0;
|
||||
|
||||
case __T('c'):
|
||||
cptr=amx_Address(amx,param);
|
||||
amx_GetAddr(amx,param,&cptr);
|
||||
width--; /* single character itself has a with of 1 */
|
||||
if (sign!=__T('-'))
|
||||
while (width-->0)
|
||||
@ -755,7 +588,7 @@ static int dochar(AMX *amx,TCHAR ch,cell param,TCHAR sign,TCHAR decpoint,int wid
|
||||
case __T('d'): {
|
||||
cell value;
|
||||
int length=1;
|
||||
cptr=amx_Address(amx,param);
|
||||
amx_GetAddr(amx,param,&cptr);
|
||||
value=*cptr;
|
||||
if (value<0 || sign==__T('+'))
|
||||
length++;
|
||||
@ -792,17 +625,9 @@ static int dochar(AMX *amx,TCHAR ch,cell param,TCHAR sign,TCHAR decpoint,int wid
|
||||
if (width>0)
|
||||
_stprintf(formatstring+_tcslen(formatstring),__T("%d"),width);
|
||||
_stprintf(formatstring+_tcslen(formatstring),__T(".%df"),digits);
|
||||
cptr=amx_Address(amx,param);
|
||||
#if PAWN_CELL_SIZE == 64
|
||||
_stprintf(buffer,formatstring,*(double*)cptr);
|
||||
#else
|
||||
_stprintf(buffer,formatstring,*(float*)cptr);
|
||||
#endif
|
||||
if (decpoint==__T(',')) {
|
||||
TCHAR *ptr=_tcschr(buffer,__T('.'));
|
||||
if (ptr!=NULL)
|
||||
*ptr=__T(',');
|
||||
} /* if */
|
||||
/* ??? decimal comma? */
|
||||
amx_GetAddr(amx,param,&cptr);
|
||||
_stprintf(buffer,formatstring,*(float*)cptr);
|
||||
f_putstr(user,buffer);
|
||||
return 1;
|
||||
#endif
|
||||
@ -813,7 +638,7 @@ static int dochar(AMX *amx,TCHAR ch,cell param,TCHAR sign,TCHAR decpoint,int wid
|
||||
#if !defined FLOATPOINT
|
||||
case __T('r'): /* if fixed point is enabled, and floating point is not, %r == %q */
|
||||
#endif
|
||||
cptr=amx_Address(amx,param);
|
||||
amx_GetAddr(amx,param,&cptr);
|
||||
/* format the number */
|
||||
if (digits==INT_MAX)
|
||||
digits=3;
|
||||
@ -840,7 +665,7 @@ static int dochar(AMX *amx,TCHAR ch,cell param,TCHAR sign,TCHAR decpoint,int wid
|
||||
info.f_putstr=f_putstr;
|
||||
info.f_putchar=f_putchar;
|
||||
info.user=user;
|
||||
cptr=amx_Address(amx,param);
|
||||
amx_GetAddr(amx,param,&cptr);
|
||||
amx_printstring(amx,cptr,&info);
|
||||
return 1;
|
||||
} /* case */
|
||||
@ -848,7 +673,7 @@ static int dochar(AMX *amx,TCHAR ch,cell param,TCHAR sign,TCHAR decpoint,int wid
|
||||
case __T('x'): {
|
||||
ucell value;
|
||||
int length=1;
|
||||
cptr=amx_Address(amx,param);
|
||||
amx_GetAddr(amx,param,&cptr);
|
||||
value=*(ucell*)cptr;
|
||||
while (value>=0x10) {
|
||||
length++;
|
||||
@ -873,7 +698,7 @@ static int dochar(AMX *amx,TCHAR ch,cell param,TCHAR sign,TCHAR decpoint,int wid
|
||||
|
||||
enum {
|
||||
FMT_NONE, /* not in format state; accept '%' */
|
||||
FMT_START, /* found '%', accept '+', '-' (START), '0' (filler; START), digit (WIDTH), '.' (DECIM), or '%' or format letter (done) */
|
||||
FMT_START, /* found '%', accept '+', '-' (START), '0' (filler; START), digit (WIDTH), '.' (DECIM) or format letter (done) */
|
||||
FMT_WIDTH, /* found digit after '%' or sign, accept digit (WIDTH), '.' (DECIM) or format letter (done) */
|
||||
FMT_DECIM, /* found digit after '.', accept accept digit (DECIM) or format letter (done) */
|
||||
};
|
||||
@ -906,11 +731,8 @@ static int formatstate(TCHAR c,int *state,TCHAR *sign,TCHAR *decpoint,int *width
|
||||
*decpoint=c;
|
||||
*digits=0;
|
||||
*state=FMT_DECIM;
|
||||
} else if (c==__T('%')) {
|
||||
*state=FMT_NONE;
|
||||
return -1; /* print literal '%' */
|
||||
} else {
|
||||
return 1; /* print formatted character */
|
||||
return 1; /* print formatted character */
|
||||
} /* if */
|
||||
break;
|
||||
case FMT_WIDTH:
|
||||
@ -921,14 +743,14 @@ static int formatstate(TCHAR c,int *state,TCHAR *sign,TCHAR *decpoint,int *width
|
||||
*digits=0;
|
||||
*state=FMT_DECIM;
|
||||
} else {
|
||||
return 1; /* print formatted character */
|
||||
return 1; /* print formatted character */
|
||||
} /* if */
|
||||
break;
|
||||
case FMT_DECIM:
|
||||
if (c>=__T('0') && c<=__T('9')) {
|
||||
*digits=*digits*10+(int)(c-__T('0'));
|
||||
} else {
|
||||
return 1; /* print formatted character */
|
||||
return 1; /* print formatted character */
|
||||
} /* if */
|
||||
break;
|
||||
} /* switch */
|
||||
@ -976,10 +798,11 @@ int amx_printstring(AMX *amx,cell *cstr,AMX_FMTINFO *info)
|
||||
|
||||
if ((ucell)*cstr>UNPACKEDMAX) {
|
||||
int j=sizeof(cell)-sizeof(char);
|
||||
char c;
|
||||
/* the string is packed */
|
||||
i=0;
|
||||
for ( ; ; ) {
|
||||
char c=(char)((ucell)cstr[i] >> 8*j);
|
||||
c=(char)((ucell)cstr[i] >> 8*j);
|
||||
if (c==0)
|
||||
break;
|
||||
if (skip>0) {
|
||||
@ -1023,29 +846,28 @@ int amx_printstring(AMX *amx,cell *cstr,AMX_FMTINFO *info)
|
||||
/* check whether this is a packed string */
|
||||
if ((ucell)*cstr>UNPACKEDMAX) {
|
||||
int j=sizeof(cell)-sizeof(char);
|
||||
char c;
|
||||
/* the string is packed */
|
||||
i=0;
|
||||
for ( ; ; ) {
|
||||
char c=(char)((ucell)cstr[i] >> 8*j);
|
||||
c=(char)((ucell)cstr[i] >> 8*j);
|
||||
if (c==0)
|
||||
break;
|
||||
switch (formatstate(c,&fmtstate,&sign,&decpoint,&width,&digits,&filler)) {
|
||||
case -1:
|
||||
f_putchar(user,c);
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
assert(info!=NULL && info->params!=NULL);
|
||||
paramidx+=dochar(amx,c,info->params[paramidx],sign,decpoint,width,digits,filler,
|
||||
f_putstr,f_putchar,user);
|
||||
fmtstate=FMT_NONE;
|
||||
break;
|
||||
case 0:
|
||||
assert(info!=NULL && info->params!=NULL);
|
||||
if (paramidx>=info->numparams) /* insufficient parameters passed */
|
||||
amx_RaiseError(amx, AMX_ERR_NATIVE);
|
||||
else
|
||||
paramidx+=dochar(amx,c,info->params[paramidx],sign,decpoint,width,digits,filler,
|
||||
f_putstr,f_putchar,user);
|
||||
fmtstate=FMT_NONE;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
} /* switch */
|
||||
if (j==0)
|
||||
i++;
|
||||
@ -1058,19 +880,17 @@ int amx_printstring(AMX *amx,cell *cstr,AMX_FMTINFO *info)
|
||||
case -1:
|
||||
f_putchar(user,(TCHAR)cstr[i]);
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
assert(info!=NULL && info->params!=NULL);
|
||||
paramidx+=dochar(amx,(TCHAR)cstr[i],info->params[paramidx],sign,decpoint,width,digits,filler,
|
||||
f_putstr,f_putchar,user);
|
||||
fmtstate=FMT_NONE;
|
||||
break;
|
||||
case 0:
|
||||
assert(info!=NULL && info->params!=NULL);
|
||||
if (paramidx>=info->numparams) /* insufficient parameters passed */
|
||||
amx_RaiseError(amx, AMX_ERR_NATIVE);
|
||||
else
|
||||
paramidx+=dochar(amx,(TCHAR)cstr[i],info->params[paramidx],sign,decpoint,width,digits,filler,
|
||||
f_putstr,f_putchar,user);
|
||||
fmtstate=FMT_NONE;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
} /* switch */
|
||||
} /* for */
|
||||
} /* if */
|
||||
@ -1094,7 +914,7 @@ static cell AMX_NATIVE_CALL n_print(AMX *amx,const cell *params)
|
||||
info.length= ((size_t)params[0]>=3*sizeof(cell)) ? (int)(params[3]-info.skip) : INT_MAX;
|
||||
|
||||
CreateConsole();
|
||||
cstr=amx_Address(amx,params[1]);
|
||||
amx_GetAddr(amx,params[1],&cstr);
|
||||
amx_printstring(amx,cstr,&info);
|
||||
amx_fflush();
|
||||
return 0;
|
||||
@ -1111,7 +931,7 @@ static cell AMX_NATIVE_CALL n_print(AMX *amx,const cell *params)
|
||||
/* set the new colours */
|
||||
oldcolours=amx_setattr((int)params[2],(int)params[3],(int)params[4]);
|
||||
|
||||
cstr=amx_Address(amx,params[1]);
|
||||
amx_GetAddr(amx,params[1],&cstr);
|
||||
amx_printstring(amx,cstr,NULL);
|
||||
|
||||
/* reset the colours */
|
||||
@ -1133,7 +953,7 @@ static cell AMX_NATIVE_CALL n_printf(AMX *amx,const cell *params)
|
||||
info.length=INT_MAX;
|
||||
|
||||
CreateConsole();
|
||||
cstr=amx_Address(amx,params[1]);
|
||||
amx_GetAddr(amx,params[1],&cstr);
|
||||
amx_printstring(amx,cstr,&info);
|
||||
amx_fflush();
|
||||
return 0;
|
||||
@ -1162,20 +982,18 @@ static cell AMX_NATIVE_CALL n_getchar(AMX *amx,const cell *params)
|
||||
static cell AMX_NATIVE_CALL n_getstring(AMX *amx,const cell *params)
|
||||
{
|
||||
int c,chars,max;
|
||||
TCHAR *str;
|
||||
cell *cptr;
|
||||
|
||||
(void)amx;
|
||||
CreateConsole();
|
||||
chars=0;
|
||||
max=(int)params[2];
|
||||
if (max>0) {
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
TCHAR str[max]; /* use C99 feature if available */
|
||||
#else
|
||||
TCHAR *str=(TCHAR *)alloca(max*sizeof(TCHAR));
|
||||
if (str==NULL)
|
||||
return chars;
|
||||
#endif
|
||||
if (max<=0)
|
||||
return 0;
|
||||
|
||||
chars=0;
|
||||
|
||||
str=(TCHAR *)alloca(max*sizeof(TCHAR));
|
||||
if (str!=NULL) {
|
||||
|
||||
c=amx_getch();
|
||||
while (c!=EOF && c!=EOL_CHAR && chars<max-1) {
|
||||
@ -1195,7 +1013,7 @@ static cell AMX_NATIVE_CALL n_getstring(AMX *amx,const cell *params)
|
||||
assert(chars<max);
|
||||
str[chars]='\0';
|
||||
|
||||
cptr=amx_Address(amx,params[1]);
|
||||
amx_GetAddr(amx,params[1],&cptr);
|
||||
amx_SetString(cptr,(char*)str,(int)params[3],sizeof(TCHAR)>1,max);
|
||||
|
||||
} /* if */
|
||||
@ -1234,14 +1052,13 @@ static int inlist(AMX *amx,int c,const cell *params,int num)
|
||||
{
|
||||
int i, key;
|
||||
|
||||
(void)amx;
|
||||
for (i=0; i<num; i++) {
|
||||
if (i==0) {
|
||||
/* first key is passed by value, others are passed by reference */
|
||||
key = (int)params[i];
|
||||
} else {
|
||||
cell *cptr;
|
||||
cptr=amx_Address(amx,params[i]);
|
||||
amx_GetAddr(amx,params[i],&cptr);
|
||||
key=(int)*cptr;
|
||||
} /* if */
|
||||
if (c==key || c==-key)
|
||||
@ -1279,8 +1096,8 @@ static cell AMX_NATIVE_CALL n_getvalue(AMX *amx,const cell *params)
|
||||
} /* if */
|
||||
|
||||
/* check end of input */
|
||||
#if EOL_CHAR!='\r'
|
||||
if (c==EOL_CHAR && inlist(amx,'\r',params+2,(int)params[0]/sizeof(cell)-1)!=0)
|
||||
#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined MACOS
|
||||
if (c=='\n' && inlist(amx,'\r',params+2,(int)params[0]/sizeof(cell)-1)!=0)
|
||||
c='\r';
|
||||
#endif
|
||||
if ((chars>1 || (chars>0 && sign>0))
|
||||
@ -1290,10 +1107,6 @@ static cell AMX_NATIVE_CALL n_getvalue(AMX *amx,const cell *params)
|
||||
acceptchar(c,&chars);
|
||||
break;
|
||||
} /* if */
|
||||
#if EOL_CHAR!='\r'
|
||||
if (c=='\r')
|
||||
c=EOL_CHAR;
|
||||
#endif
|
||||
|
||||
/* get value */
|
||||
d=base; /* by default, do not accept the character */
|
||||
@ -1340,7 +1153,8 @@ static cell AMX_NATIVE_CALL n_gotoxy(AMX *amx,const cell *params)
|
||||
{
|
||||
(void)amx;
|
||||
CreateConsole();
|
||||
return amx_gotoxy((int)params[1],(int)params[2]);
|
||||
amx_gotoxy((int)params[1],(int)params[2]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL n_wherexy(AMX *amx,const cell *params)
|
||||
@ -1348,13 +1162,12 @@ static cell AMX_NATIVE_CALL n_wherexy(AMX *amx,const cell *params)
|
||||
cell *px,*py;
|
||||
int x,y;
|
||||
|
||||
(void)amx;
|
||||
CreateConsole();
|
||||
amx_wherexy(&x,&y);
|
||||
px=amx_Address(amx,params[1]);
|
||||
py=amx_Address(amx,params[2]);
|
||||
*px=x;
|
||||
*py=y;
|
||||
amx_GetAddr(amx,params[1],&px);
|
||||
amx_GetAddr(amx,params[2],&py);
|
||||
if (px!=NULL) *px=x;
|
||||
if (py!=NULL) *py=y;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1370,7 +1183,8 @@ static cell AMX_NATIVE_CALL n_consctrl(AMX *amx,const cell *params)
|
||||
{
|
||||
(void)amx;
|
||||
CreateConsole();
|
||||
return amx_termctl((int)params[1],(int)params[2]);
|
||||
(void)amx_termctl((int)params[1],(int)params[2]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL n_console(AMX *amx,const cell *params)
|
||||
@ -1395,8 +1209,8 @@ static int AMXAPI amx_ConsoleIdle(AMX *amx, int AMXAPI Exec(AMX *, cell *, int))
|
||||
if (PrevIdle != NULL)
|
||||
PrevIdle(amx, Exec);
|
||||
|
||||
if (amx_kbhit()) {
|
||||
key = amx_getch();
|
||||
if (kbhit()) {
|
||||
key = getch();
|
||||
amx_Push(amx, key);
|
||||
err = Exec(amx, NULL, idxKeyPressed);
|
||||
while (err == AMX_ERR_SLEEP)
|
||||
@ -1426,7 +1240,7 @@ const AMX_NATIVE_INFO console_Natives[] = {
|
||||
{ NULL, NULL } /* terminator */
|
||||
};
|
||||
|
||||
int AMXEXPORT AMXAPI amx_ConsoleInit(AMX *amx)
|
||||
int AMXEXPORT amx_ConsoleInit(AMX *amx)
|
||||
{
|
||||
#if !defined AMXCONSOLE_NOIDLE
|
||||
/* see whether there is an @keypressed() function */
|
||||
@ -1440,7 +1254,7 @@ int AMXEXPORT AMXAPI amx_ConsoleInit(AMX *amx)
|
||||
return amx_Register(amx, console_Natives, -1);
|
||||
}
|
||||
|
||||
int AMXEXPORT AMXAPI amx_ConsoleCleanup(AMX *amx)
|
||||
int AMXEXPORT amx_ConsoleCleanup(AMX *amx)
|
||||
{
|
||||
(void)amx;
|
||||
#if !defined AMXCONSOLE_NOIDLE
|
||||
|
@ -1,20 +1,24 @@
|
||||
/* Core module for the Pawn AMX
|
||||
*
|
||||
* Copyright (c) ITB CompuPhase, 1997-2016
|
||||
* Copyright (c) ITB CompuPhase, 1997-2006
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at
|
||||
* This software is provided "as-is", without any express or implied warranty.
|
||||
* In no event will the authors be held liable for any damages arising from
|
||||
* the use of this software.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software in
|
||||
* a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* Version: $Id: amxcore.c 5504 2016-05-15 13:42:30Z $
|
||||
* Version: $Id: amxcore.c 3657 2006-10-24 20:09:50Z thiadmer $
|
||||
*/
|
||||
|
||||
#if defined _UNICODE || defined __UNICODE__ || defined UNICODE
|
||||
@ -30,14 +34,7 @@
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <assert.h>
|
||||
#include "osdefs.h"
|
||||
#if defined __ECOS__
|
||||
/* eCos puts include files in cyg/package_name */
|
||||
#include <cyg/pawn/amx.h>
|
||||
#define stricmp(a,b) strcasecmp(a,b)
|
||||
#else
|
||||
#include "amx.h"
|
||||
#endif
|
||||
#include "amx.h"
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32 || defined _Windows
|
||||
#include <windows.h>
|
||||
#endif
|
||||
@ -199,10 +196,18 @@ static cell AMX_NATIVE_CALL funcidx(AMX *amx,const cell *params)
|
||||
{
|
||||
char name[64];
|
||||
cell *cstr;
|
||||
int index,err;
|
||||
int index,err,len;
|
||||
|
||||
cstr=amx_Address(amx,params[1]);
|
||||
amx_GetString(name,cstr,0,sizeof name);
|
||||
amx_GetAddr(amx,params[1],&cstr);
|
||||
|
||||
/* verify string length */
|
||||
amx_StrLen(cstr,&len);
|
||||
if (len>=64) {
|
||||
amx_RaiseError(amx,AMX_ERR_NATIVE);
|
||||
return 0;
|
||||
} /* if */
|
||||
|
||||
amx_GetString(name,cstr,0,UNLIMITED);
|
||||
err=amx_FindPublic(amx,name,&index);
|
||||
if (err!=AMX_ERR_NONE)
|
||||
index=-1; /* this is not considered a fatal error */
|
||||
@ -272,9 +277,9 @@ static cell AMX_NATIVE_CALL swapchars(AMX *amx,const cell *params)
|
||||
static cell AMX_NATIVE_CALL core_tolower(AMX *amx,const cell *params)
|
||||
{
|
||||
(void)amx;
|
||||
#if (defined __WIN32__ || defined _WIN32 || defined WIN32) && !defined _WIN64
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32
|
||||
return (cell)CharLower((LPTSTR)params[1]);
|
||||
#elif defined _Windows && !defined _WIN64
|
||||
#elif defined _Windows
|
||||
return (cell)AnsiLower((LPSTR)params[1]);
|
||||
#else
|
||||
if ((unsigned)(params[1]-'A')<26u)
|
||||
@ -286,9 +291,9 @@ static cell AMX_NATIVE_CALL core_tolower(AMX *amx,const cell *params)
|
||||
static cell AMX_NATIVE_CALL core_toupper(AMX *amx,const cell *params)
|
||||
{
|
||||
(void)amx;
|
||||
#if (defined __WIN32__ || defined _WIN32 || defined WIN32) && !defined _WIN64
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32
|
||||
return (cell)CharUpper((LPTSTR)params[1]);
|
||||
#elif defined _Windows && !defined _WIN64
|
||||
#elif defined _Windows
|
||||
return (cell)AnsiUpper((LPSTR)params[1]);
|
||||
#else
|
||||
if ((unsigned)(params[1]-'a')<26u)
|
||||
@ -329,31 +334,44 @@ static char *MakePackedString(cell *cptr)
|
||||
|
||||
amx_StrLen(cptr,&len);
|
||||
dest=(char *)malloc(len+sizeof(cell));
|
||||
amx_GetString(dest,cptr,0,len+sizeof(cell));
|
||||
amx_GetString(dest,cptr,0,UNLIMITED);
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* getproperty(id=0, const name[]="", value=cellmin, string[]="", size=sizeof string) */
|
||||
static int verify_addr(AMX *amx,cell addr)
|
||||
{
|
||||
int err;
|
||||
cell *cdest;
|
||||
|
||||
err=amx_GetAddr(amx,addr,&cdest);
|
||||
if (err!=AMX_ERR_NONE)
|
||||
amx_RaiseError(amx,err);
|
||||
return err;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL getproperty(AMX *amx,const cell *params)
|
||||
{
|
||||
cell *cstr;
|
||||
char *name;
|
||||
proplist *item;
|
||||
|
||||
(void)amx;
|
||||
cstr=amx_Address(amx,params[2]);
|
||||
amx_GetAddr(amx,params[2],&cstr);
|
||||
name=MakePackedString(cstr);
|
||||
item=list_finditem(&proproot,params[1],name,params[3],NULL);
|
||||
/* if list_finditem() found the value, store the name */
|
||||
if (item!=NULL && item->value==params[3] && strlen(name)==0) {
|
||||
cstr=amx_Address(amx,params[4]);
|
||||
amx_SetString(cstr,item->name,1,0,params[5]);
|
||||
int needed=(strlen(item->name)+sizeof(cell)-1)/sizeof(cell); /* # of cells needed */
|
||||
if (verify_addr(amx,(cell)(params[4]+needed))!=AMX_ERR_NONE) {
|
||||
free(name);
|
||||
return 0;
|
||||
} /* if */
|
||||
amx_GetAddr(amx,params[4],&cstr);
|
||||
amx_SetString(cstr,item->name,1,0,UNLIMITED);
|
||||
} /* if */
|
||||
free(name);
|
||||
return (item!=NULL) ? item->value : 0;
|
||||
}
|
||||
|
||||
/* setproperty(id=0, const name[]="", value=cellmin, const string[]="") */
|
||||
static cell AMX_NATIVE_CALL setproperty(AMX *amx,const cell *params)
|
||||
{
|
||||
cell prev=0;
|
||||
@ -361,7 +379,7 @@ static cell AMX_NATIVE_CALL setproperty(AMX *amx,const cell *params)
|
||||
char *name;
|
||||
proplist *item;
|
||||
|
||||
cstr=amx_Address(amx,params[2]);
|
||||
amx_GetAddr(amx,params[2],&cstr);
|
||||
name=MakePackedString(cstr);
|
||||
item=list_finditem(&proproot,params[1],name,params[3],NULL);
|
||||
if (item==NULL)
|
||||
@ -372,7 +390,7 @@ static cell AMX_NATIVE_CALL setproperty(AMX *amx,const cell *params)
|
||||
prev=item->value;
|
||||
if (strlen(name)==0) {
|
||||
free(name);
|
||||
cstr=amx_Address(amx,params[4]);
|
||||
amx_GetAddr(amx,params[4],&cstr);
|
||||
name=MakePackedString(cstr);
|
||||
} /* if */
|
||||
list_setitem(item,params[1],name,params[3]);
|
||||
@ -381,7 +399,6 @@ static cell AMX_NATIVE_CALL setproperty(AMX *amx,const cell *params)
|
||||
return prev;
|
||||
}
|
||||
|
||||
/* deleteproperty(id=0, const name[]="", value=cellmin) */
|
||||
static cell AMX_NATIVE_CALL delproperty(AMX *amx,const cell *params)
|
||||
{
|
||||
cell prev=0;
|
||||
@ -389,8 +406,7 @@ static cell AMX_NATIVE_CALL delproperty(AMX *amx,const cell *params)
|
||||
char *name;
|
||||
proplist *item,*pred;
|
||||
|
||||
(void)amx;
|
||||
cstr=amx_Address(amx,params[2]);
|
||||
amx_GetAddr(amx,params[2],&cstr);
|
||||
name=MakePackedString(cstr);
|
||||
item=list_finditem(&proproot,params[1],name,params[3],&pred);
|
||||
if (item!=NULL) {
|
||||
@ -401,15 +417,13 @@ static cell AMX_NATIVE_CALL delproperty(AMX *amx,const cell *params)
|
||||
return prev;
|
||||
}
|
||||
|
||||
/* existproperty(id=0, const name[]="", value=cellmin) */
|
||||
static cell AMX_NATIVE_CALL existproperty(AMX *amx,const cell *params)
|
||||
{
|
||||
cell *cstr;
|
||||
char *name;
|
||||
proplist *item;
|
||||
|
||||
(void)amx;
|
||||
cstr=amx_Address(amx,params[2]);
|
||||
amx_GetAddr(amx,params[2],&cstr);
|
||||
name=MakePackedString(cstr);
|
||||
item=list_finditem(&proproot,params[1],name,params[3],NULL);
|
||||
free(name);
|
||||
@ -485,12 +499,12 @@ const AMX_NATIVE_INFO core_Natives[] = {
|
||||
{ NULL, NULL } /* terminator */
|
||||
};
|
||||
|
||||
int AMXEXPORT AMXAPI amx_CoreInit(AMX *amx)
|
||||
int AMXEXPORT amx_CoreInit(AMX *amx)
|
||||
{
|
||||
return amx_Register(amx, core_Natives, -1);
|
||||
}
|
||||
|
||||
int AMXEXPORT AMXAPI amx_CoreCleanup(AMX *amx)
|
||||
int AMXEXPORT amx_CoreCleanup(AMX *amx)
|
||||
{
|
||||
(void)amx;
|
||||
#if !defined AMX_NOPROPLIST
|
||||
|
@ -1,20 +1,24 @@
|
||||
/* Text file I/O module for the Pawn Abstract Machine
|
||||
*
|
||||
* Copyright (c) ITB CompuPhase, 2003-2016
|
||||
* Copyright (c) ITB CompuPhase, 2003-2006
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at
|
||||
* This software is provided "as-is", without any express or implied warranty.
|
||||
* In no event will the authors be held liable for any damages arising from
|
||||
* the use of this software.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software in
|
||||
* a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* Version: $Id: amxfile.c 5588 2016-10-25 11:13:28Z $
|
||||
* Version: $Id: amxfile.c 3660 2006-11-05 13:05:09Z thiadmer $
|
||||
*/
|
||||
|
||||
#if defined _UNICODE || defined __UNICODE__ || defined UNICODE
|
||||
@ -26,116 +30,53 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include "osdefs.h"
|
||||
#if (defined __linux || defined __linux__) && !defined __LINUX__
|
||||
#define __LINUX__
|
||||
#endif
|
||||
#if defined FREEBSD && !defined __FreeBSD__
|
||||
#define __FreeBSD__
|
||||
#endif
|
||||
#if defined __BORLANDC__
|
||||
#include <dir.h>
|
||||
#endif
|
||||
#if defined __BORLANDC__ || defined __LINUX__ || defined __FreeBSD__ || defined __OpenBSD__ || defined MACOS || defined __APPLE__
|
||||
#include <utime.h>
|
||||
#else
|
||||
#include <sys/utime.h>
|
||||
#endif
|
||||
#if defined __WIN32__ || defined __MSDOS__
|
||||
#include <assert.h>
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32 || defined __MSDOS__
|
||||
#include <io.h>
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#if defined __WATCOMC__ || defined _MSC_VER
|
||||
#include <direct.h>
|
||||
#endif
|
||||
#if defined __LINUX__ || defined __FreeBSD__ || defined __OpenBSD__ || defined MACOS || defined __APPLE__
|
||||
#include <dirent.h>
|
||||
#else
|
||||
#include <io.h>
|
||||
#endif
|
||||
#if defined __GNUC__ || defined __clang__
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include "amx.h"
|
||||
#if defined __WIN32__ || defined _Windows
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32 || defined _Windows
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined MACOS
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
#include "osdefs.h"
|
||||
#include "amx.h"
|
||||
|
||||
#include "fpattern.c"
|
||||
|
||||
#if !defined AMXFILE_VAR
|
||||
#define AMXFILE_VAR "AMXFILE"
|
||||
#endif
|
||||
|
||||
#if !defined sizearray
|
||||
#define sizearray(a) (sizeof(a)/sizeof((a)[0]))
|
||||
#elif AMXFILE_VAR==""
|
||||
#undef AMXFILE_VAR
|
||||
#endif
|
||||
|
||||
#if defined _UNICODE
|
||||
#include <tchar.h>
|
||||
# include <tchar.h>
|
||||
#elif !defined __T
|
||||
typedef char TCHAR;
|
||||
#define __T(string) string
|
||||
#define _tchmod chmod
|
||||
#define _tcscat strcat
|
||||
#define _tcschr strchr
|
||||
#define _tcscmp strcmp
|
||||
#define _tcscpy strcpy
|
||||
#define _tcsdup strdup
|
||||
#define _tcslen strlen
|
||||
#define _tcsncpy strncpy
|
||||
#define _tcsnicmp strnicmp
|
||||
#define _tcspbrk strpbrk
|
||||
#define _tcsrchr strrchr
|
||||
#define _tcstol strtol
|
||||
#define _tfopen fopen
|
||||
#define _tfputs fputs
|
||||
#define _tgetenv getenv
|
||||
#define _tremove remove
|
||||
#define _trename rename
|
||||
#if defined __BORLANDC__ || defined __LINUX__ || defined __FreeBSD__ || defined __OpenBSD__ || defined MACOS || defined __APPLE__
|
||||
#define _tmkdir mkdir
|
||||
#define _trmdir rmdir
|
||||
#define _tstat stat
|
||||
#define _tutime utime
|
||||
#else
|
||||
#define _tmkdir _mkdir
|
||||
#define _trmdir _rmdir
|
||||
#define _tstat _stat
|
||||
#define _tstat64 _stat64
|
||||
#define _tutime _utime
|
||||
#endif
|
||||
#if defined __APPLE__
|
||||
#define t_stat stat
|
||||
#elif defined __WIN32__
|
||||
#if defined __WATCOMC__
|
||||
#define t_stat __stat
|
||||
#else
|
||||
#define t_stat _stat
|
||||
#endif
|
||||
#else
|
||||
#define t_stat stat
|
||||
#endif
|
||||
#endif
|
||||
#if !defined t_stat
|
||||
#if defined _tstat
|
||||
#define t_stat _tstat
|
||||
#else
|
||||
#define t_stat stat
|
||||
#endif
|
||||
#endif
|
||||
#if !defined S_ISDIR
|
||||
#define S_ISDIR(mode) (((mode) & _S_IFDIR) != 0)
|
||||
# define __T(string) string
|
||||
# define _tfopen fopen
|
||||
# define _tgetenv getenv
|
||||
# define _tfputs fputs
|
||||
# define _tcscat strcat
|
||||
# define _tcschr strchr
|
||||
# define _tcscpy strcpy
|
||||
# define _tcsdup strdup
|
||||
# define _tcslen strlen
|
||||
# define _tcsncpy strncpy
|
||||
# define _tcspbrk strpbrk
|
||||
# define _tcsrchr strrchr
|
||||
#endif
|
||||
|
||||
#include "minIni.c"
|
||||
#if !defined UNUSED_PARAM
|
||||
#define UNUSED_PARAM(p) ((void)(p))
|
||||
#endif
|
||||
|
||||
enum filemode {
|
||||
io_read, /* file must exist */
|
||||
@ -363,13 +304,13 @@ static size_t fgets_char(FILE *fp, char *string, size_t max)
|
||||
return index;
|
||||
}
|
||||
|
||||
#if (defined __WIN32__ || defined _WIN32 || defined WIN32) && _MSC_VER < 1500
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32
|
||||
#if defined _UNICODE
|
||||
wchar_t *_wgetenv(wchar_t *name)
|
||||
{
|
||||
static wchar_t buffer[_MAX_PATH];
|
||||
buffer[0]=L'\0';
|
||||
GetEnvironmentVariable(name,buffer,sizearray(buffer));
|
||||
GetEnvironmentVariable(name,buffer,sizeof buffer/sizeof(wchar_t));
|
||||
return buffer[0]!=L'\0' ? buffer : NULL;
|
||||
}
|
||||
#else
|
||||
@ -377,7 +318,7 @@ char *getenv(const char *name)
|
||||
{
|
||||
static char buffer[_MAX_PATH];
|
||||
buffer[0]='\0';
|
||||
GetEnvironmentVariable(name,buffer,sizearray(buffer));
|
||||
GetEnvironmentVariable(name,buffer,sizeof buffer);
|
||||
return buffer[0]!='\0' ? buffer : NULL;
|
||||
}
|
||||
#endif
|
||||
@ -488,7 +429,6 @@ static cell AMX_NATIVE_CALL n_fopen(AMX *amx, const cell *params)
|
||||
TCHAR *name,fullname[_MAX_PATH];
|
||||
FILE *f = NULL;
|
||||
|
||||
(void)amx;
|
||||
altattrib=NULL;
|
||||
switch (params[2] & 0x7fff) {
|
||||
case io_read:
|
||||
@ -510,7 +450,7 @@ static cell AMX_NATIVE_CALL n_fopen(AMX *amx, const cell *params)
|
||||
|
||||
/* get the filename */
|
||||
amx_StrParam(amx,params[1],name);
|
||||
if (name!=NULL && completename(fullname,name,sizearray(fullname))!=NULL) {
|
||||
if (name!=NULL && completename(fullname,name,sizeof fullname)!=NULL) {
|
||||
f=_tfopen(fullname,attrib);
|
||||
if (f==NULL && altattrib!=NULL)
|
||||
f=_tfopen(fullname,altattrib);
|
||||
@ -521,20 +461,19 @@ static cell AMX_NATIVE_CALL n_fopen(AMX *amx, const cell *params)
|
||||
/* fclose(File: handle) */
|
||||
static cell AMX_NATIVE_CALL n_fclose(AMX *amx, const cell *params)
|
||||
{
|
||||
(void)amx;
|
||||
UNUSED_PARAM(amx);
|
||||
return fclose((FILE*)params[1]) == 0;
|
||||
}
|
||||
|
||||
/* fwrite(File: handle, const string[]) */
|
||||
static cell AMX_NATIVE_CALL n_fwrite(AMX *amx, const cell *params)
|
||||
{
|
||||
size_t r = 0;
|
||||
int r = 0;
|
||||
cell *cptr;
|
||||
char *str;
|
||||
int len;
|
||||
|
||||
(void)amx;
|
||||
cptr=amx_Address(amx,params[2]);
|
||||
amx_GetAddr(amx,params[2],&cptr);
|
||||
amx_StrLen(cptr,&len);
|
||||
if (len==0)
|
||||
return 0;
|
||||
@ -549,14 +488,13 @@ static cell AMX_NATIVE_CALL n_fwrite(AMX *amx, const cell *params)
|
||||
/* the string is unpacked, write it as UTF-8 */
|
||||
r=fputs_cell((FILE*)params[1],cptr,1);
|
||||
} /* if */
|
||||
return (cell)r;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* fread(File: handle, string[], size=sizeof string, bool:pack=false) */
|
||||
static cell AMX_NATIVE_CALL n_fread(AMX *amx, const cell *params)
|
||||
{
|
||||
size_t chars;
|
||||
int max;
|
||||
int chars,max;
|
||||
char *str;
|
||||
cell *cptr;
|
||||
|
||||
@ -566,7 +504,7 @@ static cell AMX_NATIVE_CALL n_fread(AMX *amx, const cell *params)
|
||||
if (params[4])
|
||||
max*=sizeof(cell);
|
||||
|
||||
cptr=amx_Address(amx,params[2]);
|
||||
amx_GetAddr(amx,params[2],&cptr);
|
||||
str=(char *)alloca(max);
|
||||
if (str==NULL || cptr==NULL) {
|
||||
amx_RaiseError(amx, AMX_ERR_NATIVE);
|
||||
@ -576,15 +514,15 @@ static cell AMX_NATIVE_CALL n_fread(AMX *amx, const cell *params)
|
||||
if (params[4]) {
|
||||
/* store as packed string, read an ASCII/ANSI string */
|
||||
chars=fgets_char((FILE*)params[1],str,max);
|
||||
assert((int)chars<max);
|
||||
amx_SetString(cptr,str,1,0,max);
|
||||
assert(chars<max);
|
||||
amx_SetString(cptr,str,(int)params[4],0,max);
|
||||
} else {
|
||||
/* store and unpacked string, interpret UTF-8 */
|
||||
chars=fgets_cell((FILE*)params[1],cptr,max,1);
|
||||
} /* if */
|
||||
|
||||
assert((int)chars<max);
|
||||
return (cell)chars;
|
||||
assert(chars<max);
|
||||
return chars;
|
||||
}
|
||||
|
||||
/* fputchar(File: handle, value, bool:utf8 = true) */
|
||||
@ -592,7 +530,7 @@ static cell AMX_NATIVE_CALL n_fputchar(AMX *amx, const cell *params)
|
||||
{
|
||||
size_t result;
|
||||
|
||||
(void)amx;
|
||||
UNUSED_PARAM(amx);
|
||||
if (params[3]) {
|
||||
cell str[2];
|
||||
str[0]=params[2];
|
||||
@ -600,10 +538,9 @@ static cell AMX_NATIVE_CALL n_fputchar(AMX *amx, const cell *params)
|
||||
result=fputs_cell((FILE*)params[1],str,1);
|
||||
} else {
|
||||
fputc((int)params[2],(FILE*)params[1]);
|
||||
result=1;
|
||||
} /* if */
|
||||
assert(result==0 || result==1);
|
||||
return (cell)result;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* fgetchar(File: handle, bool:utf8 = true) */
|
||||
@ -612,7 +549,7 @@ static cell AMX_NATIVE_CALL n_fgetchar(AMX *amx, const cell *params)
|
||||
cell str[2];
|
||||
size_t result;
|
||||
|
||||
(void)amx;
|
||||
UNUSED_PARAM(amx);
|
||||
if (params[2]) {
|
||||
result=fgets_cell((FILE*)params[1],str,2,1);
|
||||
} else {
|
||||
@ -640,10 +577,9 @@ static cell AMX_NATIVE_CALL n_fgetchar(AMX *amx, const cell *params)
|
||||
static cell AMX_NATIVE_CALL n_fblockwrite(AMX *amx, const cell *params)
|
||||
{
|
||||
cell *cptr;
|
||||
cell count=0;
|
||||
cell count;
|
||||
|
||||
(void)amx;
|
||||
cptr=amx_Address(amx,params[2]);
|
||||
amx_GetAddr(amx,params[2],&cptr);
|
||||
if (cptr!=NULL) {
|
||||
cell max=params[3];
|
||||
ucell v;
|
||||
@ -660,10 +596,9 @@ static cell AMX_NATIVE_CALL n_fblockwrite(AMX *amx, const cell *params)
|
||||
static cell AMX_NATIVE_CALL n_fblockread(AMX *amx, const cell *params)
|
||||
{
|
||||
cell *cptr;
|
||||
cell count=0;
|
||||
cell count;
|
||||
|
||||
(void)amx;
|
||||
cptr=amx_Address(amx,params[2]);
|
||||
amx_GetAddr(amx,params[2],&cptr);
|
||||
if (cptr!=NULL) {
|
||||
cell max=params[3];
|
||||
ucell v;
|
||||
@ -679,8 +614,8 @@ static cell AMX_NATIVE_CALL n_fblockread(AMX *amx, const cell *params)
|
||||
/* File: ftemp() */
|
||||
static cell AMX_NATIVE_CALL n_ftemp(AMX *amx, const cell *params)
|
||||
{
|
||||
(void)amx;
|
||||
(void)params;
|
||||
UNUSED_PARAM(amx);
|
||||
UNUSED_PARAM(params);
|
||||
return (cell)tmpfile();
|
||||
}
|
||||
|
||||
@ -688,7 +623,6 @@ static cell AMX_NATIVE_CALL n_ftemp(AMX *amx, const cell *params)
|
||||
static cell AMX_NATIVE_CALL n_fseek(AMX *amx, const cell *params)
|
||||
{
|
||||
int whence;
|
||||
(void)amx;
|
||||
switch (params[3]) {
|
||||
case seek_start:
|
||||
whence=SEEK_SET;
|
||||
@ -704,6 +638,7 @@ static cell AMX_NATIVE_CALL n_fseek(AMX *amx, const cell *params)
|
||||
default:
|
||||
return 0;
|
||||
} /* switch */
|
||||
UNUSED_PARAM(amx);
|
||||
return lseek(fileno((FILE*)params[1]),params[2],whence);
|
||||
}
|
||||
|
||||
@ -713,61 +648,9 @@ static cell AMX_NATIVE_CALL n_fremove(AMX *amx, const cell *params)
|
||||
int r=1;
|
||||
TCHAR *name,fullname[_MAX_PATH];
|
||||
|
||||
(void)amx;
|
||||
amx_StrParam(amx,params[1],name);
|
||||
if (name!=NULL && completename(fullname,name,sizearray(fullname))!=NULL) {
|
||||
/* if this is a directory, try _trmdir() */
|
||||
#if defined _WIN64
|
||||
struct __stat64 stbuf;
|
||||
_tstat64(fullname, &stbuf);
|
||||
#else
|
||||
struct t_stat stbuf;
|
||||
_tstat(fullname, &stbuf);
|
||||
#endif
|
||||
if (S_ISDIR(stbuf.st_mode))
|
||||
r=_trmdir(fullname);
|
||||
else
|
||||
r=_tremove(fullname);
|
||||
} /* if */
|
||||
return r==0;
|
||||
}
|
||||
|
||||
/* bool: fcopy(const source[], const target[]) */
|
||||
static cell AMX_NATIVE_CALL n_fcopy(AMX *amx, const cell *params)
|
||||
{
|
||||
int r=1;
|
||||
TCHAR *name,oldname[_MAX_PATH],newname[_MAX_PATH];
|
||||
|
||||
(void)amx;
|
||||
amx_StrParam(amx,params[1],name);
|
||||
if (name!=NULL && completename(oldname,name,sizearray(oldname))!=NULL) {
|
||||
amx_StrParam(amx,params[2],name);
|
||||
if (name!=NULL && completename(newname,name,sizearray(newname))!=NULL) {
|
||||
#if defined __WIN32__
|
||||
r= CopyFile(oldname,newname,FALSE)==FALSE;
|
||||
#else
|
||||
TCHAR cmd[2*_MAX_PATH + 10];
|
||||
sprintf(cmd,"cp %s %s",oldname,newname);
|
||||
r= system(cmd)<0;
|
||||
#endif
|
||||
} /* if */
|
||||
} /* if */
|
||||
return r==0;
|
||||
}
|
||||
|
||||
/* bool: frename(const oldname[], const newname[]) */
|
||||
static cell AMX_NATIVE_CALL n_frename(AMX *amx, const cell *params)
|
||||
{
|
||||
int r=1;
|
||||
TCHAR *name,oldname[_MAX_PATH],newname[_MAX_PATH];
|
||||
|
||||
(void)amx;
|
||||
amx_StrParam(amx,params[1],name);
|
||||
if (name!=NULL && completename(oldname,name,sizearray(oldname))!=NULL) {
|
||||
amx_StrParam(amx,params[2],name);
|
||||
if (name!=NULL && completename(newname,name,sizearray(newname))!=NULL)
|
||||
r=_trename(oldname,newname);
|
||||
} /* if */
|
||||
if (name!=NULL && completename(fullname,name,sizeof fullname)!=NULL)
|
||||
r=remove(fullname);
|
||||
return r==0;
|
||||
}
|
||||
|
||||
@ -779,7 +662,7 @@ static cell AMX_NATIVE_CALL n_flength(AMX *amx, const cell *params)
|
||||
c=lseek(fn,0,SEEK_CUR); /* save the current position */
|
||||
l=lseek(fn,0,SEEK_END); /* return the file position at its end */
|
||||
lseek(fn,c,SEEK_SET); /* restore the file pointer */
|
||||
(void)amx;
|
||||
UNUSED_PARAM(amx);
|
||||
return l;
|
||||
}
|
||||
|
||||
@ -830,10 +713,10 @@ static int matchfiles(const TCHAR *path,int skip,TCHAR *out,int outlen)
|
||||
#else
|
||||
/* copy directory part only (zero-terminate) */
|
||||
if (basename==path) {
|
||||
_tcscpy(dirname,".");
|
||||
strcpy(dirname,".");
|
||||
} else {
|
||||
_tcsncpy(dirname,path,(int)(basename-path));
|
||||
dirname[(int)(basename-path)]=__T('\0');
|
||||
strncpy(dirname,path,(int)(basename-path));
|
||||
dirname[(int)(basename-path)]=_T('\0');
|
||||
} /* if */
|
||||
if ((dir=opendir(dirname))!=NULL) {
|
||||
while ((entry=readdir(dir))!=NULL) {
|
||||
@ -855,9 +738,8 @@ static cell AMX_NATIVE_CALL n_fexist(AMX *amx, const cell *params)
|
||||
int r=0;
|
||||
TCHAR *name,fullname[_MAX_PATH];
|
||||
|
||||
(void)amx;
|
||||
amx_StrParam(amx,params[1],name);
|
||||
if (name!=NULL && completename(fullname,name,sizearray(fullname))!=NULL)
|
||||
if (name!=NULL && completename(fullname,name,sizeof fullname)!=NULL)
|
||||
r=matchfiles(fullname,0,NULL,0);
|
||||
return r;
|
||||
}
|
||||
@ -868,361 +750,48 @@ static cell AMX_NATIVE_CALL n_fmatch(AMX *amx, const cell *params)
|
||||
TCHAR *name,fullname[_MAX_PATH]="";
|
||||
cell *cptr;
|
||||
|
||||
(void)amx;
|
||||
amx_StrParam(amx,params[2],name);
|
||||
if (name!=NULL && completename(fullname,name,sizearray(fullname))!=NULL) {
|
||||
if (!matchfiles(fullname,params[3],fullname,sizearray(fullname))) {
|
||||
if (name!=NULL && completename(fullname,name,sizeof fullname)!=NULL) {
|
||||
if (!matchfiles(fullname,params[3],fullname,sizeof fullname)) {
|
||||
fullname[0]='\0';
|
||||
} else {
|
||||
/* copy the string into the destination */
|
||||
cptr=amx_Address(amx,params[1]);
|
||||
amx_GetAddr(amx,params[1],&cptr);
|
||||
amx_SetString(cptr,fullname,1,0,params[4]);
|
||||
} /* if */
|
||||
} /* if */
|
||||
return fullname[0]!='\0';
|
||||
}
|
||||
|
||||
/* bool: fstat(const name[], &size = 0, ×tamp = 0, &attrib = 0, &inode = 0) */
|
||||
static cell AMX_NATIVE_CALL n_fstat(AMX *amx, const cell *params)
|
||||
{
|
||||
TCHAR *name,fullname[_MAX_PATH]="";
|
||||
cell *cptr;
|
||||
int result=0;
|
||||
|
||||
(void)amx;
|
||||
amx_StrParam(amx,params[1],name);
|
||||
if (name!=NULL && completename(fullname,name,sizearray(fullname))!=NULL) {
|
||||
int err;
|
||||
#if defined _WIN64
|
||||
struct __stat64 stbuf;
|
||||
err = _tstat64(fullname, &stbuf);
|
||||
#else
|
||||
struct t_stat stbuf;
|
||||
err = _tstat(fullname, &stbuf);
|
||||
#endif
|
||||
if (err == 0) {
|
||||
cptr=amx_Address(amx,params[2]);
|
||||
*cptr=(cell)stbuf.st_size;
|
||||
cptr=amx_Address(amx,params[3]);
|
||||
*cptr=(cell)stbuf.st_mtime;
|
||||
cptr=amx_Address(amx,params[4]);
|
||||
*cptr=stbuf.st_mode; /* mode/protection bits */
|
||||
cptr=amx_Address(amx,params[5]);
|
||||
*cptr=stbuf.st_ino; /* inode number, unique id for a file */
|
||||
result=1;
|
||||
} /* if */
|
||||
} /* if */
|
||||
return result;
|
||||
}
|
||||
|
||||
/* bool: fattrib(const name[], timestamp=0, attrib=0x0f) */
|
||||
static cell AMX_NATIVE_CALL n_fattrib(AMX *amx, const cell *params)
|
||||
{
|
||||
#if !(defined __WIN32__ || defined _WIN32 || defined WIN32) || defined __BORLANDC__
|
||||
#define _utime(n,t) utime(n,t)
|
||||
#define _utimbuf utimbuf
|
||||
#endif
|
||||
TCHAR *name,fullname[_MAX_PATH]="";
|
||||
int result=0;
|
||||
|
||||
(void)amx;
|
||||
amx_StrParam(amx,params[1],name);
|
||||
if (name!=NULL && completename(fullname,name,sizearray(fullname))!=NULL) {
|
||||
result=1;
|
||||
if (params[2]!=0) {
|
||||
struct _utimbuf times;
|
||||
times.actime=(unsigned long)params[2];
|
||||
times.modtime=(unsigned long)params[2];
|
||||
result=result && (_tutime(name,×)==0);
|
||||
} /* if */
|
||||
if (params[3]!=0x0f)
|
||||
result=result && (_tchmod(name,(int)params[3])==0);
|
||||
} /* if */
|
||||
return result;
|
||||
}
|
||||
|
||||
/* bool: fcreatedir(const name[]) */
|
||||
static cell AMX_NATIVE_CALL n_fcreatedir(AMX *amx, const cell *params)
|
||||
{
|
||||
TCHAR *name,fullname[_MAX_PATH]="";
|
||||
int r=1;
|
||||
|
||||
(void)amx;
|
||||
amx_StrParam(amx,params[1],name);
|
||||
if (name!=NULL && completename(fullname,name,sizearray(fullname))!=NULL) {
|
||||
#if defined __WIN32__ || defined __DOS__
|
||||
r=_tmkdir(fullname);
|
||||
#else
|
||||
r=_tmkdir(fullname,0755);
|
||||
#endif
|
||||
} /* if */
|
||||
return r==0;
|
||||
}
|
||||
|
||||
/* CRC32 functions are adapted from source code from www.networkdls.com
|
||||
* The table generation routines are replaced by a hard-coded table, which
|
||||
* can be stored in Flash ROM.
|
||||
*/
|
||||
const unsigned long ulCRCTable[256] = // CRC Lookup Table Array
|
||||
{
|
||||
0x00000000Lu, 0x77073096Lu, 0xee0e612cLu, 0x990951baLu,
|
||||
0x076dc419Lu, 0x706af48fLu, 0xe963a535Lu, 0x9e6495a3Lu,
|
||||
0x0edb8832Lu, 0x79dcb8a4Lu, 0xe0d5e91eLu, 0x97d2d988Lu,
|
||||
0x09b64c2bLu, 0x7eb17cbdLu, 0xe7b82d07Lu, 0x90bf1d91Lu,
|
||||
0x1db71064Lu, 0x6ab020f2Lu, 0xf3b97148Lu, 0x84be41deLu,
|
||||
0x1adad47dLu, 0x6ddde4ebLu, 0xf4d4b551Lu, 0x83d385c7Lu,
|
||||
0x136c9856Lu, 0x646ba8c0Lu, 0xfd62f97aLu, 0x8a65c9ecLu,
|
||||
0x14015c4fLu, 0x63066cd9Lu, 0xfa0f3d63Lu, 0x8d080df5Lu,
|
||||
0x3b6e20c8Lu, 0x4c69105eLu, 0xd56041e4Lu, 0xa2677172Lu,
|
||||
0x3c03e4d1Lu, 0x4b04d447Lu, 0xd20d85fdLu, 0xa50ab56bLu,
|
||||
0x35b5a8faLu, 0x42b2986cLu, 0xdbbbc9d6Lu, 0xacbcf940Lu,
|
||||
0x32d86ce3Lu, 0x45df5c75Lu, 0xdcd60dcfLu, 0xabd13d59Lu,
|
||||
0x26d930acLu, 0x51de003aLu, 0xc8d75180Lu, 0xbfd06116Lu,
|
||||
0x21b4f4b5Lu, 0x56b3c423Lu, 0xcfba9599Lu, 0xb8bda50fLu,
|
||||
0x2802b89eLu, 0x5f058808Lu, 0xc60cd9b2Lu, 0xb10be924Lu,
|
||||
0x2f6f7c87Lu, 0x58684c11Lu, 0xc1611dabLu, 0xb6662d3dLu,
|
||||
0x76dc4190Lu, 0x01db7106Lu, 0x98d220bcLu, 0xefd5102aLu,
|
||||
0x71b18589Lu, 0x06b6b51fLu, 0x9fbfe4a5Lu, 0xe8b8d433Lu,
|
||||
0x7807c9a2Lu, 0x0f00f934Lu, 0x9609a88eLu, 0xe10e9818Lu,
|
||||
0x7f6a0dbbLu, 0x086d3d2dLu, 0x91646c97Lu, 0xe6635c01Lu,
|
||||
0x6b6b51f4Lu, 0x1c6c6162Lu, 0x856530d8Lu, 0xf262004eLu,
|
||||
0x6c0695edLu, 0x1b01a57bLu, 0x8208f4c1Lu, 0xf50fc457Lu,
|
||||
0x65b0d9c6Lu, 0x12b7e950Lu, 0x8bbeb8eaLu, 0xfcb9887cLu,
|
||||
0x62dd1ddfLu, 0x15da2d49Lu, 0x8cd37cf3Lu, 0xfbd44c65Lu,
|
||||
0x4db26158Lu, 0x3ab551ceLu, 0xa3bc0074Lu, 0xd4bb30e2Lu,
|
||||
0x4adfa541Lu, 0x3dd895d7Lu, 0xa4d1c46dLu, 0xd3d6f4fbLu,
|
||||
0x4369e96aLu, 0x346ed9fcLu, 0xad678846Lu, 0xda60b8d0Lu,
|
||||
0x44042d73Lu, 0x33031de5Lu, 0xaa0a4c5fLu, 0xdd0d7cc9Lu,
|
||||
0x5005713cLu, 0x270241aaLu, 0xbe0b1010Lu, 0xc90c2086Lu,
|
||||
0x5768b525Lu, 0x206f85b3Lu, 0xb966d409Lu, 0xce61e49fLu,
|
||||
0x5edef90eLu, 0x29d9c998Lu, 0xb0d09822Lu, 0xc7d7a8b4Lu,
|
||||
0x59b33d17Lu, 0x2eb40d81Lu, 0xb7bd5c3bLu, 0xc0ba6cadLu,
|
||||
0xedb88320Lu, 0x9abfb3b6Lu, 0x03b6e20cLu, 0x74b1d29aLu,
|
||||
0xead54739Lu, 0x9dd277afLu, 0x04db2615Lu, 0x73dc1683Lu,
|
||||
0xe3630b12Lu, 0x94643b84Lu, 0x0d6d6a3eLu, 0x7a6a5aa8Lu,
|
||||
0xe40ecf0bLu, 0x9309ff9dLu, 0x0a00ae27Lu, 0x7d079eb1Lu,
|
||||
0xf00f9344Lu, 0x8708a3d2Lu, 0x1e01f268Lu, 0x6906c2feLu,
|
||||
0xf762575dLu, 0x806567cbLu, 0x196c3671Lu, 0x6e6b06e7Lu,
|
||||
0xfed41b76Lu, 0x89d32be0Lu, 0x10da7a5aLu, 0x67dd4accLu,
|
||||
0xf9b9df6fLu, 0x8ebeeff9Lu, 0x17b7be43Lu, 0x60b08ed5Lu,
|
||||
0xd6d6a3e8Lu, 0xa1d1937eLu, 0x38d8c2c4Lu, 0x4fdff252Lu,
|
||||
0xd1bb67f1Lu, 0xa6bc5767Lu, 0x3fb506ddLu, 0x48b2364bLu,
|
||||
0xd80d2bdaLu, 0xaf0a1b4cLu, 0x36034af6Lu, 0x41047a60Lu,
|
||||
0xdf60efc3Lu, 0xa867df55Lu, 0x316e8eefLu, 0x4669be79Lu,
|
||||
0xcb61b38cLu, 0xbc66831aLu, 0x256fd2a0Lu, 0x5268e236Lu,
|
||||
0xcc0c7795Lu, 0xbb0b4703Lu, 0x220216b9Lu, 0x5505262fLu,
|
||||
0xc5ba3bbeLu, 0xb2bd0b28Lu, 0x2bb45a92Lu, 0x5cb36a04Lu,
|
||||
0xc2d7ffa7Lu, 0xb5d0cf31Lu, 0x2cd99e8bLu, 0x5bdeae1dLu,
|
||||
0x9b64c2b0Lu, 0xec63f226Lu, 0x756aa39cLu, 0x026d930aLu,
|
||||
0x9c0906a9Lu, 0xeb0e363fLu, 0x72076785Lu, 0x05005713Lu,
|
||||
0x95bf4a82Lu, 0xe2b87a14Lu, 0x7bb12baeLu, 0x0cb61b38Lu,
|
||||
0x92d28e9bLu, 0xe5d5be0dLu, 0x7cdcefb7Lu, 0x0bdbdf21Lu,
|
||||
0x86d3d2d4Lu, 0xf1d4e242Lu, 0x68ddb3f8Lu, 0x1fda836eLu,
|
||||
0x81be16cdLu, 0xf6b9265bLu, 0x6fb077e1Lu, 0x18b74777Lu,
|
||||
0x88085ae6Lu, 0xff0f6a70Lu, 0x66063bcaLu, 0x11010b5cLu,
|
||||
0x8f659effLu, 0xf862ae69Lu, 0x616bffd3Lu, 0x166ccf45Lu,
|
||||
0xa00ae278Lu, 0xd70dd2eeLu, 0x4e048354Lu, 0x3903b3c2Lu,
|
||||
0xa7672661Lu, 0xd06016f7Lu, 0x4969474dLu, 0x3e6e77dbLu,
|
||||
0xaed16a4aLu, 0xd9d65adcLu, 0x40df0b66Lu, 0x37d83bf0Lu,
|
||||
0xa9bcae53Lu, 0xdebb9ec5Lu, 0x47b2cf7fLu, 0x30b5ffe9Lu,
|
||||
0xbdbdf21cLu, 0xcabac28aLu, 0x53b39330Lu, 0x24b4a3a6Lu,
|
||||
0xbad03605Lu, 0xcdd70693Lu, 0x54de5729Lu, 0x23d967bfLu,
|
||||
0xb3667a2eLu, 0xc4614ab8Lu, 0x5d681b02Lu, 0x2a6f2b94Lu,
|
||||
0xb40bbe37Lu, 0xc30c8ea1Lu, 0x5a05df1bLu, 0x2d02ef8dLu
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// This function uses the ulCRCTable lookup table to generate a CRC for xData
|
||||
|
||||
static unsigned long PartialCRC(unsigned long ulCRC, unsigned char *sBuf, unsigned long lBufSz)
|
||||
{
|
||||
while(lBufSz--)
|
||||
ulCRC = (ulCRC >> 8) ^ ulCRCTable[(ulCRC & 0xFF) ^ *sBuf++];
|
||||
|
||||
return ulCRC;
|
||||
}
|
||||
|
||||
/* filecrc(const name[]) */
|
||||
static cell AMX_NATIVE_CALL n_filecrc(AMX *amx, const cell *params)
|
||||
{
|
||||
TCHAR *name,fullname[_MAX_PATH]="";
|
||||
FILE *fp;
|
||||
unsigned char buffer[256];
|
||||
unsigned long ulCRC = 0xffffffff;
|
||||
size_t numread;
|
||||
|
||||
(void)amx;
|
||||
amx_StrParam(amx,params[1],name);
|
||||
if (name!=NULL && completename(fullname,name,sizearray(fullname))!=NULL
|
||||
&& (fp=_tfopen(fullname,"rb"))!=NULL)
|
||||
{
|
||||
do {
|
||||
numread=fread(buffer,sizeof(unsigned char),sizeof buffer,fp);
|
||||
ulCRC=PartialCRC(ulCRC,buffer,(unsigned long)numread);
|
||||
} while(numread==sizeof buffer);
|
||||
fclose(fp);
|
||||
} /* if */
|
||||
return(ulCRC ^ 0xffffffff);
|
||||
}
|
||||
|
||||
|
||||
const TCHAR default_ini_name[] = "config.ini";
|
||||
|
||||
/* readcfg(const filename[]="", const section[]="", const key[], value[], size=sizeof value, const defvalue[]="", bool:packed=false) */
|
||||
static cell AMX_NATIVE_CALL n_readcfg(AMX *amx, const cell *params)
|
||||
{
|
||||
TCHAR *name,fullname[_MAX_PATH]="";
|
||||
TCHAR *section,*key,*defvalue;
|
||||
TCHAR *buffer;
|
||||
int size,result=0;
|
||||
cell *cptr;
|
||||
|
||||
size=(int)params[5];
|
||||
if (size<=0)
|
||||
return 0;
|
||||
if (params[7])
|
||||
size*=sizeof(cell);
|
||||
|
||||
amx_StrParam(amx,params[1],name);
|
||||
if (name!=NULL && *name=='\0')
|
||||
name=(TCHAR*)default_ini_name;
|
||||
if (name!=NULL && completename(fullname,name,sizearray(fullname))!=NULL) {
|
||||
amx_StrParam(amx,params[2],section);
|
||||
amx_StrParam(amx,params[3],key);
|
||||
amx_StrParam(amx,params[6],defvalue);
|
||||
|
||||
cptr=amx_Address(amx,params[4]);
|
||||
buffer=(char *)alloca(size);
|
||||
if (buffer==NULL || cptr==NULL) {
|
||||
amx_RaiseError(amx, AMX_ERR_NATIVE);
|
||||
return 0;
|
||||
} /* if */
|
||||
result=ini_gets(section,key,defvalue,buffer,size,fullname);
|
||||
amx_SetString(cptr,buffer,params[7],0,size);
|
||||
} /* if */
|
||||
return result;
|
||||
}
|
||||
|
||||
/* readcfgvalue(const filename[]="", const section[]="", const key[], defvalue=0) */
|
||||
static cell AMX_NATIVE_CALL n_readcfgvalue(AMX *amx, const cell *params)
|
||||
{
|
||||
TCHAR *name,fullname[_MAX_PATH]="";
|
||||
TCHAR *section,*key;
|
||||
long result=0;
|
||||
|
||||
(void)amx;
|
||||
amx_StrParam(amx,params[1],name);
|
||||
if (name!=NULL && *name=='\0')
|
||||
name=(TCHAR*)default_ini_name;
|
||||
if (name!=NULL && completename(fullname,name,sizearray(fullname))!=NULL) {
|
||||
amx_StrParam(amx,params[2],section);
|
||||
amx_StrParam(amx,params[3],key);
|
||||
result=ini_getl(section,key,(long)params[4],fullname);
|
||||
} /* if */
|
||||
return result;
|
||||
}
|
||||
|
||||
/* writecfg(const filename[]="", const section[]="", const key[], const value[]) */
|
||||
static cell AMX_NATIVE_CALL n_writecfg(AMX *amx, const cell *params)
|
||||
{
|
||||
TCHAR *name,fullname[_MAX_PATH]="";
|
||||
TCHAR *section,*key,*value;
|
||||
int result=0;
|
||||
|
||||
(void)amx;
|
||||
amx_StrParam(amx,params[1],name);
|
||||
if (name!=NULL && *name=='\0')
|
||||
name=(TCHAR*)default_ini_name;
|
||||
if (name!=NULL && completename(fullname,name,sizearray(fullname))!=NULL) {
|
||||
amx_StrParam(amx,params[2],section);
|
||||
amx_StrParam(amx,params[3],key);
|
||||
amx_StrParam(amx,params[4],value);
|
||||
result=ini_puts(section,key,value,fullname);
|
||||
} /* if */
|
||||
return result;
|
||||
}
|
||||
|
||||
/* writecfgvalue(const filename[]="", const section[]="", const key[], value) */
|
||||
static cell AMX_NATIVE_CALL n_writecfgvalue(AMX *amx, const cell *params)
|
||||
{
|
||||
TCHAR *name,fullname[_MAX_PATH]="";
|
||||
TCHAR *section,*key;
|
||||
int result=0;
|
||||
|
||||
(void)amx;
|
||||
amx_StrParam(amx,params[1],name);
|
||||
if (name!=NULL && *name=='\0')
|
||||
name=(TCHAR*)default_ini_name;
|
||||
if (name!=NULL && completename(fullname,name,sizearray(fullname))!=NULL) {
|
||||
amx_StrParam(amx,params[2],section);
|
||||
amx_StrParam(amx,params[3],key);
|
||||
result=ini_putl(section,key,(long)params[4],fullname);
|
||||
} /* if */
|
||||
return result;
|
||||
}
|
||||
|
||||
/* deletecfg(const filename[]="", const section[]="", const key[]="") */
|
||||
static cell AMX_NATIVE_CALL n_deletecfg(AMX *amx, const cell *params)
|
||||
{
|
||||
TCHAR *name,fullname[_MAX_PATH]="";
|
||||
TCHAR *section,*key;
|
||||
int result=0;
|
||||
|
||||
(void)amx;
|
||||
amx_StrParam(amx,params[1],name);
|
||||
if (name!=NULL && *name=='\0')
|
||||
name=(TCHAR*)default_ini_name;
|
||||
if (name!=NULL && completename(fullname,name,sizearray(fullname))!=NULL) {
|
||||
amx_StrParam(amx,params[2],section);
|
||||
if (section!=NULL && *section=='\0')
|
||||
section=NULL;
|
||||
amx_StrParam(amx,params[3],key);
|
||||
if (key!=NULL && *key=='\0')
|
||||
key=NULL;
|
||||
result=ini_puts(section,key,NULL,fullname);
|
||||
} /* if */
|
||||
return result;
|
||||
}
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
AMX_NATIVE_INFO file_Natives[] = {
|
||||
{ "fopen", n_fopen },
|
||||
{ "fclose", n_fclose },
|
||||
{ "fwrite", n_fwrite },
|
||||
{ "fread", n_fread },
|
||||
{ "fputchar", n_fputchar },
|
||||
{ "fgetchar", n_fgetchar },
|
||||
{ "fblockwrite", n_fblockwrite },
|
||||
{ "fblockread", n_fblockread },
|
||||
{ "ftemp", n_ftemp },
|
||||
{ "fseek", n_fseek },
|
||||
{ "flength", n_flength },
|
||||
{ "fremove", n_fremove },
|
||||
{ "fcopy", n_fcopy },
|
||||
{ "frename", n_frename },
|
||||
{ "fexist", n_fexist },
|
||||
{ "fmatch", n_fmatch },
|
||||
{ "fstat", n_fstat },
|
||||
{ "fattrib", n_fattrib },
|
||||
{ "filecrc", n_filecrc },
|
||||
{ "fcreatedir", n_fcreatedir },
|
||||
{ "readcfg", n_readcfg },
|
||||
{ "readcfgvalue", n_readcfgvalue },
|
||||
{ "writecfg", n_writecfg },
|
||||
{ "writecfgvalue",n_writecfgvalue },
|
||||
{ "deletecfg", n_deletecfg },
|
||||
{ "fopen", n_fopen },
|
||||
{ "fclose", n_fclose },
|
||||
{ "fwrite", n_fwrite },
|
||||
{ "fread", n_fread },
|
||||
{ "fputchar", n_fputchar },
|
||||
{ "fgetchar", n_fgetchar },
|
||||
{ "fblockwrite", n_fblockwrite },
|
||||
{ "fblockread", n_fblockread },
|
||||
{ "ftemp", n_ftemp },
|
||||
{ "fseek", n_fseek },
|
||||
{ "flength", n_flength },
|
||||
{ "fremove", n_fremove },
|
||||
{ "fexist", n_fexist },
|
||||
{ "fmatch", n_fmatch },
|
||||
{ NULL, NULL } /* terminator */
|
||||
};
|
||||
|
||||
int AMXEXPORT AMXAPI amx_FileInit(AMX *amx)
|
||||
int AMXEXPORT amx_FileInit(AMX *amx)
|
||||
{
|
||||
return amx_Register(amx, file_Natives, -1);
|
||||
}
|
||||
|
||||
int AMXEXPORT AMXAPI amx_FileCleanup(AMX *amx)
|
||||
int AMXEXPORT amx_FileCleanup(AMX *amx)
|
||||
{
|
||||
(void)amx;
|
||||
UNUSED_PARAM(amx);
|
||||
return AMX_ERR_NONE;
|
||||
}
|
||||
|
@ -1,20 +1,24 @@
|
||||
/* String functions for the Pawn Abstract Machine
|
||||
*
|
||||
* Copyright (c) ITB CompuPhase, 2005-2016
|
||||
* Copyright (c) ITB CompuPhase, 2005-2006
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at
|
||||
* This software is provided "as-is", without any express or implied warranty.
|
||||
* In no event will the authors be held liable for any damages arising from
|
||||
* the use of this software.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software in
|
||||
* a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* Version: $Id: amxstring.c 5514 2016-05-20 14:26:51Z $
|
||||
* Version: $Id: amxstring.c 3656 2006-10-24 07:20:26Z thiadmer $
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
@ -48,14 +52,11 @@
|
||||
#if !defined isdigit
|
||||
# define isdigit(c) ((unsigned)((c)-'0')<10u)
|
||||
#endif
|
||||
#if !defined sizearray
|
||||
# define sizearray(a) (sizeof(a) / sizeof((a)[0]))
|
||||
#endif
|
||||
|
||||
|
||||
/* dest the destination buffer; the buffer must point to the start of a cell
|
||||
* source the source buffer, this must be aligned to a cell edge
|
||||
* len the number of characters (bytes) to copy, excluding the zero terminator
|
||||
* len the number of characters (bytes) to copy
|
||||
* offs the offset in dest, in characters (bytes)
|
||||
*/
|
||||
static int amx_StrPack(cell *dest,cell *source,int len,int offs)
|
||||
@ -126,10 +127,6 @@ static int amx_StrPack(cell *dest,cell *source,int len,int offs)
|
||||
return AMX_ERR_NONE;
|
||||
}
|
||||
|
||||
/* dest the destination buffer, this must be aligned to a cell edge
|
||||
* source the source buffer, it must point to the start of a cell
|
||||
* len the number of cells to copy, excluding the zero terminator
|
||||
*/
|
||||
static int amx_StrUnpack(cell *dest,cell *source,int len)
|
||||
{
|
||||
/* len excludes the terminating '\0' byte */
|
||||
@ -183,6 +180,17 @@ static cell extractchar(cell *string,int index,int mklower)
|
||||
return c;
|
||||
}
|
||||
|
||||
static int verify_addr(AMX *amx,cell addr)
|
||||
{
|
||||
int err;
|
||||
cell *cdest;
|
||||
|
||||
err=amx_GetAddr(amx,addr,&cdest);
|
||||
if (err!=AMX_ERR_NONE)
|
||||
amx_RaiseError(amx,err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* strlen(const string[])
|
||||
*/
|
||||
static cell AMX_NATIVE_CALL n_strlen(AMX *amx,const cell *params)
|
||||
@ -190,9 +198,8 @@ static cell AMX_NATIVE_CALL n_strlen(AMX *amx,const cell *params)
|
||||
cell *cptr;
|
||||
int len = 0;
|
||||
|
||||
(void)(amx);
|
||||
cptr=amx_Address(amx,params[1]);
|
||||
amx_StrLen(cptr,&len);
|
||||
if (amx_GetAddr(amx,params[1],&cptr)==AMX_ERR_NONE)
|
||||
amx_StrLen(cptr,&len);
|
||||
return len;
|
||||
}
|
||||
|
||||
@ -201,14 +208,21 @@ static cell AMX_NATIVE_CALL n_strlen(AMX *amx,const cell *params)
|
||||
static cell AMX_NATIVE_CALL n_strpack(AMX *amx,const cell *params)
|
||||
{
|
||||
cell *cdest,*csrc;
|
||||
int len,err;
|
||||
int len,needed,err;
|
||||
size_t lastaddr;
|
||||
|
||||
csrc=amx_Address(amx,params[2]);
|
||||
/* calculate number of cells needed for (packed) destination */
|
||||
amx_GetAddr(amx,params[2],&csrc);
|
||||
amx_StrLen(csrc,&len);
|
||||
if ((unsigned)len>params[3]*sizeof(cell)-1)
|
||||
len=params[3]*sizeof(cell)-1;
|
||||
needed=(len+sizeof(cell))/sizeof(cell); /* # of cells needed */
|
||||
assert(needed>0);
|
||||
lastaddr=(size_t)(params[1]+sizeof(cell)*needed-1);
|
||||
if (verify_addr(amx,(cell)lastaddr)!=AMX_ERR_NONE)
|
||||
return amx_RaiseError(amx,AMX_ERR_NATIVE);
|
||||
|
||||
cdest=amx_Address(amx,params[1]);
|
||||
amx_GetAddr(amx,params[1],&cdest);
|
||||
err=amx_StrPack(cdest,csrc,len,0);
|
||||
if (err!=AMX_ERR_NONE)
|
||||
return amx_RaiseError(amx,err);
|
||||
@ -222,14 +236,19 @@ static cell AMX_NATIVE_CALL n_strunpack(AMX *amx,const cell *params)
|
||||
{
|
||||
cell *cdest,*csrc;
|
||||
int len,err;
|
||||
size_t lastaddr;
|
||||
|
||||
csrc=amx_Address(amx,params[2]);
|
||||
/* calculate number of cells needed for (unpacked) destination */
|
||||
amx_GetAddr(amx,params[2],&csrc);
|
||||
amx_StrLen(csrc,&len);
|
||||
assert(len>=0);
|
||||
if (len>=params[3])
|
||||
len=params[3]-1;
|
||||
lastaddr=(size_t)(params[1]+sizeof(cell)*(len+1)-1);
|
||||
if (verify_addr(amx,(cell)lastaddr)!=AMX_ERR_NONE)
|
||||
return amx_RaiseError(amx,AMX_ERR_NATIVE);
|
||||
|
||||
cdest=amx_Address(amx,params[1]);
|
||||
amx_GetAddr(amx,params[1],&cdest);
|
||||
err=amx_StrUnpack(cdest,csrc,len);
|
||||
if (err!=AMX_ERR_NONE)
|
||||
return amx_RaiseError(amx,err);
|
||||
@ -244,22 +263,29 @@ static cell AMX_NATIVE_CALL n_strunpack(AMX *amx,const cell *params)
|
||||
static cell AMX_NATIVE_CALL n_strcat(AMX *amx,const cell *params)
|
||||
{
|
||||
cell *cdest,*csrc;
|
||||
int len,len2;
|
||||
int len,len2,needed;
|
||||
int packed,err;
|
||||
size_t lastaddr;
|
||||
|
||||
/* calculate number of cells needed for (packed) destination */
|
||||
csrc=amx_Address(amx,params[2]);
|
||||
cdest=amx_Address(amx,params[1]);
|
||||
amx_GetAddr(amx,params[2],&csrc);
|
||||
amx_GetAddr(amx,params[1],&cdest);
|
||||
amx_StrLen(csrc,&len);
|
||||
amx_StrLen(cdest,&len2);
|
||||
packed=(*cdest==0) ? ((ucell)*csrc>UNPACKEDMAX) : ((ucell)*cdest>UNPACKEDMAX);
|
||||
if (packed) {
|
||||
if ((unsigned)(len+len2)>params[3]*sizeof(cell)-1)
|
||||
len=params[3]*sizeof(cell)-len2-1;
|
||||
needed=(len+len2+sizeof(cell))/sizeof(cell); /* # of cells needed */
|
||||
assert(needed>0);
|
||||
lastaddr=(size_t)(params[1]+sizeof(cell)*needed-1);
|
||||
} else {
|
||||
if (len+len2>params[3]-1)
|
||||
len=params[3]-len2-1;
|
||||
lastaddr=(size_t)(params[1]+sizeof(cell)*(len+len2+1)-1);
|
||||
} /* if */
|
||||
if (verify_addr(amx,(cell)lastaddr)!=AMX_ERR_NONE)
|
||||
return amx_RaiseError(amx,AMX_ERR_NATIVE);
|
||||
|
||||
if (packed) {
|
||||
err=amx_StrPack(cdest,csrc,len,len2);
|
||||
@ -274,37 +300,6 @@ static cell AMX_NATIVE_CALL n_strcat(AMX *amx,const cell *params)
|
||||
return len;
|
||||
}
|
||||
|
||||
/* strcopy(dest[], const source[], maxlength=sizeof dest)
|
||||
* packed/unpacked attribute from source[]
|
||||
*/
|
||||
static cell AMX_NATIVE_CALL n_strcopy(AMX *amx,const cell *params)
|
||||
{
|
||||
cell *cdest,*csrc;
|
||||
int len,packed,err;
|
||||
|
||||
/* calculate number of cells needed for (packed) destination */
|
||||
csrc=amx_Address(amx,params[2]);
|
||||
cdest=amx_Address(amx,params[1]);
|
||||
amx_StrLen(csrc,&len);
|
||||
packed=(ucell)*csrc>UNPACKEDMAX;
|
||||
if (packed) {
|
||||
if ((unsigned)len>params[3]*sizeof(cell)-1)
|
||||
len=params[3]*sizeof(cell)-1;
|
||||
} else {
|
||||
if (len>params[3]-1)
|
||||
len=params[3]-1;
|
||||
} /* if */
|
||||
|
||||
if (packed)
|
||||
err=amx_StrPack(cdest,csrc,len,0);
|
||||
else
|
||||
err=amx_StrUnpack(cdest,csrc,len);
|
||||
if (err!=AMX_ERR_NONE)
|
||||
return amx_RaiseError(amx,err);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int compare(cell *cstr1,cell *cstr2,int ignorecase,int length,int offs1)
|
||||
{
|
||||
int index;
|
||||
@ -333,9 +328,8 @@ static cell AMX_NATIVE_CALL n_strcmp(AMX *amx,const cell *params)
|
||||
int len1,len2,len;
|
||||
cell result;
|
||||
|
||||
(void)(amx);
|
||||
cstr1=amx_Address(amx,params[1]);
|
||||
cstr2=amx_Address(amx,params[2]);
|
||||
amx_GetAddr(amx,params[1],&cstr1);
|
||||
amx_GetAddr(amx,params[2],&cstr2);
|
||||
|
||||
/* get the maximum length to compare */
|
||||
amx_StrLen(cstr1,&len1);
|
||||
@ -345,16 +339,12 @@ static cell AMX_NATIVE_CALL n_strcmp(AMX *amx,const cell *params)
|
||||
len=len2;
|
||||
if (len>params[4])
|
||||
len=params[4];
|
||||
if (len==0) {
|
||||
if (params[4]==0 || len1==len2)
|
||||
result=0;
|
||||
else
|
||||
result=(len1<len2) ? -1 : 1;
|
||||
} else {
|
||||
result=compare(cstr1,cstr2,params[3],len,0);
|
||||
if (result==0 && len!=params[4] && len1!=len2)
|
||||
result=(len1<len2) ? -1 : 1;
|
||||
}
|
||||
if (len==0)
|
||||
return 0;
|
||||
|
||||
result=compare(cstr1,cstr2,params[3],len,0);
|
||||
if (result==0 && len!=params[4])
|
||||
result=len1-len2;
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -366,9 +356,8 @@ static cell AMX_NATIVE_CALL n_strfind(AMX *amx,const cell *params)
|
||||
int lenstr,lensub,offs;
|
||||
cell c,f;
|
||||
|
||||
(void)(amx);
|
||||
cstr=amx_Address(amx,params[1]);
|
||||
csub=amx_Address(amx,params[2]);
|
||||
amx_GetAddr(amx,params[1],&cstr);
|
||||
amx_GetAddr(amx,params[2],&csub);
|
||||
|
||||
/* get the maximum length to compare */
|
||||
amx_StrLen(cstr,&lenstr);
|
||||
@ -398,16 +387,17 @@ static cell AMX_NATIVE_CALL n_strfind(AMX *amx,const cell *params)
|
||||
static cell AMX_NATIVE_CALL n_strmid(AMX *amx,const cell *params)
|
||||
{
|
||||
cell *cdest,*csrc;
|
||||
int len,err;
|
||||
int len,needed,err;
|
||||
int soffs,doffs;
|
||||
size_t lastaddr;
|
||||
unsigned char *ptr;
|
||||
unsigned char c;
|
||||
int start=params[3];
|
||||
int end=params[4];
|
||||
|
||||
/* calculate number of cells needed for (packed) destination */
|
||||
csrc=amx_Address(amx,params[2]);
|
||||
cdest=amx_Address(amx,params[1]);
|
||||
amx_GetAddr(amx,params[2],&csrc);
|
||||
amx_GetAddr(amx,params[1],&cdest);
|
||||
amx_StrLen(csrc,&len);
|
||||
|
||||
/* clamp the start/end parameters */
|
||||
@ -424,10 +414,16 @@ static cell AMX_NATIVE_CALL n_strmid(AMX *amx,const cell *params)
|
||||
if ((ucell)*csrc>UNPACKEDMAX) {
|
||||
if ((unsigned)len>params[5]*sizeof(cell)-1)
|
||||
len=params[5]*sizeof(cell)-1;
|
||||
needed=(len+sizeof(cell))/sizeof(cell); /* # of cells needed */
|
||||
assert(needed>0);
|
||||
lastaddr=(size_t)(params[1]+sizeof(cell)*needed-1);
|
||||
} else {
|
||||
if (len>params[5]-1)
|
||||
len=params[5]-1;
|
||||
lastaddr=(size_t)(params[1]+sizeof(cell)*(len+1)-1);
|
||||
} /* if */
|
||||
if (verify_addr(amx,(cell)lastaddr)!=AMX_ERR_NONE)
|
||||
return amx_RaiseError(amx,AMX_ERR_NATIVE);
|
||||
|
||||
if ((ucell)*csrc>UNPACKEDMAX) {
|
||||
/* first align the source to a cell boundary */
|
||||
@ -463,9 +459,8 @@ static cell AMX_NATIVE_CALL n_strdel(AMX *amx,const cell *params)
|
||||
unsigned char *ptr;
|
||||
unsigned char c;
|
||||
|
||||
(void)(amx);
|
||||
/* calculate number of cells needed for (packed) destination */
|
||||
cstr=amx_Address(amx,params[1]);
|
||||
amx_GetAddr(amx,params[1],&cstr);
|
||||
amx_StrLen(cstr,&length);
|
||||
index=(int)params[2];
|
||||
offs=(int)params[3]-index;
|
||||
@ -500,28 +495,34 @@ static cell AMX_NATIVE_CALL n_strdel(AMX *amx,const cell *params)
|
||||
static cell AMX_NATIVE_CALL n_strins(AMX *amx,const cell *params)
|
||||
{
|
||||
cell *cstr,*csub;
|
||||
int index,lenstr,lensub,maxlen,count;
|
||||
int index,lenstr,lensub,count;
|
||||
int needed;
|
||||
size_t lastaddr;
|
||||
unsigned char *ptr;
|
||||
cell c;
|
||||
|
||||
/* calculate number of cells needed for (packed) destination */
|
||||
cstr=amx_Address(amx,params[1]);
|
||||
csub=amx_Address(amx,params[2]);
|
||||
amx_GetAddr(amx,params[1],&cstr);
|
||||
amx_GetAddr(amx,params[2],&csub);
|
||||
amx_StrLen(cstr,&lenstr);
|
||||
amx_StrLen(csub,&lensub);
|
||||
index=(int)params[3];
|
||||
maxlen=(int)params[4];
|
||||
if ((ucell)*cstr>UNPACKEDMAX)
|
||||
maxlen*=sizeof(cell);
|
||||
maxlen-=1;
|
||||
if (index>lenstr || index>maxlen)
|
||||
if (index>lenstr)
|
||||
return amx_RaiseError(amx,AMX_ERR_NATIVE);
|
||||
|
||||
if (lenstr==0) {
|
||||
if (((ucell)*cstr>UNPACKEDMAX)) {
|
||||
needed=(lenstr+lensub+sizeof(cell))/sizeof(cell); /* # of cells needed */
|
||||
assert(needed>0);
|
||||
lastaddr=(size_t)(params[1]+sizeof(cell)*needed-1);
|
||||
} else {
|
||||
lastaddr=(size_t)(params[1]+sizeof(cell)*(lenstr+lensub+1)-1);
|
||||
} /* if */
|
||||
if (verify_addr(amx,(cell)lastaddr)!=AMX_ERR_NONE)
|
||||
return amx_RaiseError(amx,AMX_ERR_NATIVE);
|
||||
|
||||
if (*cstr==0) {
|
||||
/* current string is empty (and the insertion point is zero), just make a copy */
|
||||
assert(index==0);
|
||||
if (lensub>maxlen)
|
||||
lensub=maxlen;
|
||||
if ((ucell)*csub>UNPACKEDMAX)
|
||||
amx_StrPack(cstr,csub,lensub,0);
|
||||
else
|
||||
@ -529,12 +530,9 @@ static cell AMX_NATIVE_CALL n_strins(AMX *amx,const cell *params)
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
lenstr+=lensub; /* length after insertion */
|
||||
if (lenstr>=maxlen)
|
||||
lenstr=maxlen-1;
|
||||
if ((ucell)*cstr>UNPACKEDMAX) {
|
||||
if (((ucell)*cstr>UNPACKEDMAX)) {
|
||||
/* make room for the new characters */
|
||||
for (count=lenstr; count>index; count--) {
|
||||
for (count=lenstr+lensub; count>index; count--) {
|
||||
ptr=packedptr(cstr,count-lensub);
|
||||
c=*ptr;
|
||||
ptr=packedptr(cstr,count);
|
||||
@ -548,7 +546,7 @@ static cell AMX_NATIVE_CALL n_strins(AMX *amx,const cell *params)
|
||||
} /* for */
|
||||
} else {
|
||||
/* make room for the new characters */
|
||||
for (count=lenstr; count>index; count--)
|
||||
for (count=lenstr+lensub; count>index; count--)
|
||||
cstr[count]=cstr[count-lensub];
|
||||
/* copy in the new characters */
|
||||
for (count=0; count<lensub; count++) {
|
||||
@ -569,9 +567,8 @@ static cell AMX_NATIVE_CALL n_strval(AMX *amx,const cell *params)
|
||||
int len,negate=0;
|
||||
int offset=0;
|
||||
|
||||
(void)(amx);
|
||||
/* get parameters */
|
||||
cstr=amx_Address(amx,params[1]);
|
||||
amx_GetAddr(amx,params[1],&cstr);
|
||||
amx_StrLen(cstr,&len);
|
||||
if ((unsigned)params[0]>=2*sizeof(cell))
|
||||
offset=params[2];
|
||||
@ -581,22 +578,16 @@ static cell AMX_NATIVE_CALL n_strval(AMX *amx,const cell *params)
|
||||
offset=len-1;
|
||||
|
||||
/* skip a number of cells */
|
||||
if ((ucell)*cstr>UNPACKEDMAX) {
|
||||
/* packed string */
|
||||
while (offset>=(int)sizeof(cell)) {
|
||||
cstr++;
|
||||
offset-=sizeof(cell);
|
||||
len-=sizeof(cell);
|
||||
} /* while */
|
||||
} else {
|
||||
/* unpacked string, one character per cell */
|
||||
while (offset>0) {
|
||||
cstr++;
|
||||
offset--;
|
||||
len--;
|
||||
} /* while */
|
||||
} /* if */
|
||||
while (offset>=(int)sizeof(cell)) {
|
||||
cstr++;
|
||||
offset-=sizeof(cell);
|
||||
len-=sizeof(cell);
|
||||
} /* while */
|
||||
|
||||
if (len>=(int)sizeof str) {
|
||||
amx_RaiseError(amx,AMX_ERR_NATIVE);
|
||||
return 0;
|
||||
} /* if */
|
||||
amx_GetString(str,cstr,sizeof(TCHAR)>1,sizeof str);
|
||||
assert(offset<(int)sizeof(cell) && offset>=0);
|
||||
ptr=str+offset;
|
||||
@ -622,12 +613,12 @@ static cell AMX_NATIVE_CALL n_strval(AMX *amx,const cell *params)
|
||||
static cell AMX_NATIVE_CALL n_valstr(AMX *amx,const cell *params)
|
||||
{
|
||||
TCHAR str[50];
|
||||
cell value,temp;
|
||||
cell value,mult;
|
||||
cell *cstr;
|
||||
int len,result,negate=0;
|
||||
|
||||
(void)(amx);
|
||||
/* find out how many digits are needed */
|
||||
mult=10;
|
||||
len=1;
|
||||
value=params[2];
|
||||
if (value<0) {
|
||||
@ -635,9 +626,10 @@ static cell AMX_NATIVE_CALL n_valstr(AMX *amx,const cell *params)
|
||||
len++;
|
||||
value=-value;
|
||||
} /* if */
|
||||
for (temp=value; temp>=10; temp/=10)
|
||||
while (value>=mult) {
|
||||
len++;
|
||||
assert(len<=sizearray(str));
|
||||
mult*=10;
|
||||
} /* while */
|
||||
|
||||
/* put in the string */
|
||||
result=len;
|
||||
@ -648,16 +640,16 @@ static cell AMX_NATIVE_CALL n_valstr(AMX *amx,const cell *params)
|
||||
} /* while */
|
||||
if (negate)
|
||||
str[0]='-';
|
||||
cstr=amx_Address(amx,params[1]);
|
||||
amx_SetString(cstr,str,params[3],sizeof(TCHAR)>1,sizearray(str));
|
||||
amx_GetAddr(amx,params[1],&cstr);
|
||||
amx_SetString(cstr,str,params[3],sizeof(TCHAR)>1,UNLIMITED);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ispacked(const string[]) */
|
||||
static cell AMX_NATIVE_CALL n_ispacked(AMX *amx,const cell *params)
|
||||
{
|
||||
cell *cstr=amx_Address(amx,params[1]);
|
||||
(void)(amx);
|
||||
cell *cstr;
|
||||
amx_GetAddr(amx,params[1],&cstr);
|
||||
return *cstr>=UNPACKEDMAX;
|
||||
}
|
||||
|
||||
@ -736,14 +728,13 @@ static cell AMX_NATIVE_CALL n_uudecode(AMX *amx,const cell *params)
|
||||
int len;
|
||||
size_t size;
|
||||
|
||||
(void)(amx);
|
||||
/* get the source */
|
||||
cstr=amx_Address(amx,params[2]);
|
||||
amx_GetAddr(amx,params[2],&cstr);
|
||||
amx_GetString(src,cstr,0,sizeof src);
|
||||
/* decode */
|
||||
len=uudecode(dst,src);
|
||||
/* store */
|
||||
cstr=amx_Address(amx,params[1]);
|
||||
amx_GetAddr(amx,params[1],&cstr);
|
||||
size=len;
|
||||
if (size>params[3]*sizeof(cell))
|
||||
size=params[3]*sizeof(cell);
|
||||
@ -764,14 +755,12 @@ static cell AMX_NATIVE_CALL n_uuencode(AMX *amx,const cell *params)
|
||||
unsigned char src[BITMASK+2];
|
||||
char dst[BITMASK+BITMASK/3+2];
|
||||
|
||||
(void)(amx);
|
||||
/* get the source */
|
||||
cstr=amx_Address(amx,params[2]);
|
||||
amx_GetString((char *)src,cstr,0,sizeof src);
|
||||
amx_GetAddr(amx,params[2],&cstr);
|
||||
/* encode (and check for errors) */
|
||||
if (uuencode(dst,src,params[3])) {
|
||||
if (params[4]>0) {
|
||||
cstr=amx_Address(amx,params[1]);
|
||||
amx_GetAddr(amx,params[1],&cstr);
|
||||
*cstr=0;
|
||||
} /* if */
|
||||
return 0;
|
||||
@ -780,142 +769,11 @@ static cell AMX_NATIVE_CALL n_uuencode(AMX *amx,const cell *params)
|
||||
assert(strlen(dst)+1<sizeof dst);
|
||||
strcat(dst,"\n");
|
||||
/* store */
|
||||
cstr=amx_Address(amx,params[1]);
|
||||
amx_GetAddr(amx,params[1],&cstr);
|
||||
amx_SetString(cstr,dst,1,0,params[4]);
|
||||
return (((params[3]+2)/3) << 2)+2;
|
||||
}
|
||||
|
||||
/* urldecode(dest[], const source[], maxlength=sizeof dest, bool:pack=false)
|
||||
* Returns the number of characters decoded; if the dest buffer is
|
||||
* too small, not all bytes are stored.
|
||||
* A buffer may be decoded "in-place"; the destination size is always
|
||||
* smaller than the source size.
|
||||
*/
|
||||
static cell AMX_NATIVE_CALL n_urldecode(AMX *amx,const cell *params)
|
||||
{
|
||||
cell *cstr;
|
||||
TCHAR *str;
|
||||
int idx_src=0,idx_dst=0;
|
||||
|
||||
/* get the source */
|
||||
(void)(amx);
|
||||
amx_StrParam(amx,params[2],str);
|
||||
|
||||
/* decode */
|
||||
while (idx_src!='\0') {
|
||||
assert(idx_dst<=idx_src);
|
||||
if (str[idx_src]=='%') {
|
||||
int p,q;
|
||||
if (str[idx_src+1]>='0' && str[idx_src+1]<='9')
|
||||
p=str[idx_src+1]-'0';
|
||||
else if (str[idx_src+1]>='A' && str[idx_src+1]<='F')
|
||||
p=str[idx_src+1]-'A'+10;
|
||||
else if (str[idx_src+1]>='a' && str[idx_src+1]<='f')
|
||||
p=str[idx_src+1]-'a'+10;
|
||||
else
|
||||
p=-1;
|
||||
if (p>=0) {
|
||||
if (str[idx_src+2]>='0' && str[idx_src+2]<='9')
|
||||
q=str[idx_src+2]-'0';
|
||||
else if (str[idx_src+2]>='A' && str[idx_src+2]<='F')
|
||||
q=str[idx_src+2]-'A'+10;
|
||||
else if (str[idx_src+2]>='a' && str[idx_src+2]<='f')
|
||||
q=str[idx_src+2]-'a'+10;
|
||||
else
|
||||
q=-1;
|
||||
} /* if */
|
||||
if (p>=0 && q >=0) {
|
||||
assert(p<=15 && q<=15);
|
||||
str[idx_dst]=(TCHAR)((p<<4) | q);
|
||||
idx_src+=3;
|
||||
} else {
|
||||
/* invalid '%xx' syntax, copy literal '%' */
|
||||
str[idx_dst]=str[idx_src++];
|
||||
} /* if */
|
||||
} else {
|
||||
str[idx_dst]=str[idx_src++];
|
||||
} /* if */
|
||||
idx_dst++;
|
||||
} /* while */
|
||||
str[idx_dst]='\0';
|
||||
|
||||
/* store */
|
||||
cstr=amx_Address(amx,params[1]);
|
||||
amx_SetString(cstr,str,1,0,params[4]); /* store as packed ot unpacked */
|
||||
|
||||
return idx_dst;
|
||||
}
|
||||
|
||||
#define INVALIDURI(c) ((c)<',' \
|
||||
|| (c)>'9' && (c)<'A' \
|
||||
|| (c)>'Z' && (c)<'_' \
|
||||
|| (c)>'_' && (c)<'a' \
|
||||
|| (c)>'z' && (unsigned)(c)<0xa1)
|
||||
|
||||
#define TOHEX(c) (TCHAR)((c)<10 ? '0'+(c) : 'A'-10+(c))
|
||||
|
||||
/* urlencode(dest[], const source[], maxlength=sizeof dest, bool:pack=false)
|
||||
* Returns the number of characters encoded, excluding the zero string
|
||||
* terminator; if the dest buffer is too small, not all bytes are stored.
|
||||
* Always creates a packed string. This string has a newline character at the
|
||||
* end. A buffer may be encoded "in-place" if the destination is large enough.
|
||||
* Endian issues (for multi-byte values in the data stream) are not handled.
|
||||
*/
|
||||
static cell AMX_NATIVE_CALL n_urlencode(AMX *amx,const cell *params)
|
||||
{
|
||||
cell *cstr;
|
||||
int length,destlen,count,lastwidth;
|
||||
TCHAR *str;
|
||||
|
||||
/* allocate memory and get the source */
|
||||
(void)(amx);
|
||||
if ((length=(int)params[3])==0)
|
||||
return 0;
|
||||
if ((str = (TCHAR*)alloca(length * sizeof(TCHAR)))==NULL)
|
||||
return 0;
|
||||
cstr=amx_Address(amx,params[2]);
|
||||
amx_GetString((char*)str, cstr, sizeof(TCHAR)>1, length);
|
||||
|
||||
/* run through the string and determine the new length */
|
||||
destlen=1; /* space for the '\0' terminator */
|
||||
lastwidth=0;
|
||||
for (count=0; str[count]!='\0' && destlen<length; count++) {
|
||||
if (INVALIDURI(str[count]))
|
||||
lastwidth=3;
|
||||
else
|
||||
lastwidth=1;
|
||||
destlen+=lastwidth;
|
||||
} /* for */
|
||||
if (destlen>length) { /* correct for overrun */
|
||||
destlen-=lastwidth;
|
||||
count--;
|
||||
} /* if */
|
||||
assert(destlen<=length);
|
||||
assert(count>=0);
|
||||
|
||||
/* store string terminator */
|
||||
assert(destlen>0);
|
||||
str[--destlen]='\0';
|
||||
/* convert string from end to start */
|
||||
while (--count>=0) {
|
||||
assert(destlen>count);
|
||||
if (INVALIDURI(str[count])) {
|
||||
str[--destlen]=TOHEX(str[count] & 0x0f);
|
||||
str[--destlen]=TOHEX((str[count] >> 4) & 0x0f);
|
||||
str[--destlen]='%';
|
||||
} else {
|
||||
str[--destlen]=str[count];
|
||||
} /* if */
|
||||
} /* while */
|
||||
assert(destlen==0);
|
||||
|
||||
/* store the result */
|
||||
cstr=amx_Address(amx,params[1]);
|
||||
amx_SetString(cstr,str,1,0,params[4]); /* store as packed ot unpacked */
|
||||
|
||||
return (cell)strlen(str);
|
||||
}
|
||||
|
||||
/* memcpy(dest[], const source[], index=0, numbytes, maxlength=sizeof dest)
|
||||
* This function can align byte strings in cell arrays, or concatenate two
|
||||
* byte strings in two arrays. The parameter "index" is a byte offset; "numbytes"
|
||||
@ -928,11 +786,10 @@ static cell AMX_NATIVE_CALL n_memcpy(AMX *amx,const cell *params)
|
||||
cell *cdest,*csrc;
|
||||
unsigned char *pdest,*psrc;
|
||||
|
||||
(void)(amx);
|
||||
if (params[3]<0 || params[4]<0 || (params[3]+params[4])>params[5]*(int)sizeof(cell))
|
||||
return 0;
|
||||
cdest=amx_Address(amx,params[1]);
|
||||
csrc=amx_Address(amx,params[2]);
|
||||
amx_GetAddr(amx,params[1],&cdest);
|
||||
amx_GetAddr(amx,params[2],&csrc);
|
||||
pdest=(unsigned char*)cdest+params[3];
|
||||
psrc=(unsigned char*)csrc;
|
||||
memmove(pdest,psrc,params[4]);
|
||||
@ -949,7 +806,7 @@ static cell AMX_NATIVE_CALL n_memcpy(AMX *amx,const cell *params)
|
||||
|
||||
static int str_putchar(void *dest,TCHAR ch)
|
||||
{
|
||||
int len=(int)_tcslen((TCHAR*)dest);
|
||||
int len=_tcslen((TCHAR*)dest);
|
||||
if (len<MAX_FORMATSTR-1) {
|
||||
((TCHAR*)dest)[len]=ch;
|
||||
((TCHAR*)dest)[len+1]='\0';
|
||||
@ -981,11 +838,11 @@ static cell AMX_NATIVE_CALL n_strformat(AMX *amx,const cell *params)
|
||||
info.user=output;
|
||||
output[0] = __T('\0');
|
||||
|
||||
cstr=amx_Address(amx,params[4]);
|
||||
amx_GetAddr(amx,params[4],&cstr);
|
||||
amx_printstring(amx,cstr,&info);
|
||||
|
||||
/* store the output string */
|
||||
cstr=amx_Address(amx,params[1]);
|
||||
amx_GetAddr(amx,params[1],&cstr);
|
||||
amx_SetString(cstr,(char*)output,(int)params[3],sizeof(TCHAR)>1,(int)params[2]);
|
||||
return 1;
|
||||
#endif
|
||||
@ -1000,7 +857,6 @@ const AMX_NATIVE_INFO string_Natives[] = {
|
||||
{ "memcpy", n_memcpy },
|
||||
{ "strcat", n_strcat },
|
||||
{ "strcmp", n_strcmp },
|
||||
{ "strcopy", n_strcopy },
|
||||
{ "strdel", n_strdel },
|
||||
{ "strfind", n_strfind },
|
||||
{ "strformat", n_strformat },
|
||||
@ -1012,18 +868,16 @@ const AMX_NATIVE_INFO string_Natives[] = {
|
||||
{ "strval", n_strval },
|
||||
{ "uudecode", n_uudecode },
|
||||
{ "uuencode", n_uuencode },
|
||||
{ "urldecode", n_urldecode },
|
||||
{ "urlencode", n_urlencode },
|
||||
{ "valstr", n_valstr },
|
||||
{ NULL, NULL } /* terminator */
|
||||
};
|
||||
|
||||
int AMXEXPORT AMXAPI amx_StringInit(AMX *amx)
|
||||
int AMXEXPORT amx_StringInit(AMX *amx)
|
||||
{
|
||||
return amx_Register(amx, string_Natives, -1);
|
||||
}
|
||||
|
||||
int AMXEXPORT AMXAPI amx_StringCleanup(AMX *amx)
|
||||
int AMXEXPORT amx_StringCleanup(AMX *amx)
|
||||
{
|
||||
(void)amx;
|
||||
return AMX_ERR_NONE;
|
||||
|
@ -10,15 +10,15 @@
|
||||
* All strings MUST have an explicit \0. See the Windows SDK documentation
|
||||
* for details on version information and the VERSIONINFO structure.
|
||||
*/
|
||||
#define VERSION 4
|
||||
#define REVISION 0
|
||||
#define VERSION 1
|
||||
#define REVISION 1
|
||||
#define BUILD 0
|
||||
#define VERSIONSTR "4.0.0\0"
|
||||
#define VERSIONSTR "1.1.0\0"
|
||||
#define VERSIONNAME "amxString.dll\0"
|
||||
#define VERSIONDESCRIPTION "Pawn AMX: String manipulation routines\0"
|
||||
#define VERSIONCOMPANYNAME "ITB CompuPhase\0"
|
||||
#define VERSIONPRODUCTNAME "amxString\0"
|
||||
#define VERSIONCOPYRIGHT "Copyright \251 2005-2016 ITB CompuPhase\0"
|
||||
#define VERSIONCOPYRIGHT "Copyright \251 2005-2006 ITB CompuPhase\0"
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION VERSION, REVISION, BUILD, 0
|
||||
|
@ -1,45 +1,36 @@
|
||||
/* Date/time module for the Pawn Abstract Machine
|
||||
*
|
||||
* Copyright (c) ITB CompuPhase, 2001-2016
|
||||
* Copyright (c) ITB CompuPhase, 2001-2006
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at
|
||||
* This software is provided "as-is", without any express or implied warranty.
|
||||
* In no event will the authors be held liable for any damages arising from
|
||||
* the use of this software.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software in
|
||||
* a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* Version: $Id: amxtime.c 5588 2016-10-25 11:13:28Z $
|
||||
* Version: $Id: amxtime.c 3649 2006-10-12 13:13:57Z thiadmer $
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
#include "amx.h"
|
||||
#if defined __WIN32__ || defined _WIN32 || defined _Windows
|
||||
#if defined __WIN32__ || defined _WIN32
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
#endif
|
||||
#if defined __GNUC__ || defined __clang__
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#if defined __clang__
|
||||
/* ignore this warning, because fixing the macro would make it depend on
|
||||
two's-complement arithmetic */
|
||||
#pragma GCC diagnostic ignored "-Wshift-negative-value"
|
||||
#endif
|
||||
#define CELLMIN (-1 << (8*sizeof(cell) - 1))
|
||||
|
||||
#define SECONDS_PER_MINUTE 60
|
||||
#define SECONDS_PER_HOUR 3600
|
||||
#define SECONDS_PER_DAY 86400
|
||||
#define SECONDS_PER_YEAR 31556952 /* based on 365.2425 days per year */
|
||||
|
||||
#if !defined CLOCKS_PER_SEC
|
||||
#define CLOCKS_PER_SEC CLK_TCK
|
||||
#endif
|
||||
@ -75,168 +66,52 @@ static unsigned long gettimestamp(void)
|
||||
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32
|
||||
value=timeGetTime(); /* this value is already in milliseconds */
|
||||
#elif defined __linux || defined __linux__ || defined __LINUX__ || defined __APPLE__
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
value = ((tv.tv_sec * 1000) + (tv.tv_usec / 1000));
|
||||
#else
|
||||
value=clock();
|
||||
#if CLOCKS_PER_SEC<1000
|
||||
value=(cell)clock();
|
||||
#if CLOCKS_PER_SEC!=1000
|
||||
/* convert to milliseconds */
|
||||
value=(cell)((1000L * value) / CLOCKS_PER_SEC);
|
||||
#elif CLOCKS_PER_SEC>1000
|
||||
/* convert to milliseconds */
|
||||
value=(cell)(value/(CLOCKS_PER_SEC/1000));
|
||||
value=(cell)((1000L * (value+CLOCKS_PER_SEC/2)) / CLOCKS_PER_SEC);
|
||||
#endif
|
||||
#endif
|
||||
return value;
|
||||
}
|
||||
|
||||
void stamp2datetime(unsigned long sec1970,
|
||||
int *year, int *month, int *day,
|
||||
int *hour, int *minute, int *second)
|
||||
{
|
||||
int days, seconds;
|
||||
|
||||
/* find the year */
|
||||
assert(year!=NULL);
|
||||
for (*year = 1970; ; *year += 1) {
|
||||
days = 365 + ((*year & 0x03) == 0); /* clumsy "leap-year" routine, fails for 2100 */
|
||||
seconds = days * SECONDS_PER_DAY;
|
||||
if ((unsigned long)seconds > sec1970)
|
||||
break;
|
||||
sec1970 -= seconds;
|
||||
} /* if */
|
||||
|
||||
/* find the month */
|
||||
assert(month!=NULL);
|
||||
for (*month = 1; ; *month += 1) {
|
||||
days = monthdays[*month - 1];
|
||||
seconds = days * SECONDS_PER_DAY;
|
||||
if ((unsigned long)seconds > sec1970)
|
||||
break;
|
||||
sec1970 -= seconds;
|
||||
} /* if */
|
||||
|
||||
/* find the day */
|
||||
assert(day!=NULL);
|
||||
for (*day = 1; sec1970 >= SECONDS_PER_DAY; *day += 1)
|
||||
sec1970 -= SECONDS_PER_DAY;
|
||||
|
||||
/* find the hour */
|
||||
assert(hour!=NULL);
|
||||
for (*hour = 0; sec1970 >= SECONDS_PER_HOUR; *hour += 1)
|
||||
sec1970 -= SECONDS_PER_HOUR;
|
||||
|
||||
/* find the minute */
|
||||
assert(minute!=NULL);
|
||||
for (*minute = 0; sec1970 >= SECONDS_PER_MINUTE; *minute += 1)
|
||||
sec1970 -= SECONDS_PER_MINUTE;
|
||||
|
||||
/* remainder is the number of seconds */
|
||||
assert(second!=NULL);
|
||||
*second = (int)sec1970;
|
||||
}
|
||||
|
||||
static void settime(cell hour,cell minute,cell second)
|
||||
{
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32
|
||||
SYSTEMTIME systim;
|
||||
|
||||
GetLocalTime(&systim);
|
||||
if (hour!=CELLMIN)
|
||||
systim.wHour=(WORD)wrap((int)hour,0,23);
|
||||
if (minute!=CELLMIN)
|
||||
systim.wMinute=(WORD)wrap((int)minute,0,59);
|
||||
if (second!=CELLMIN)
|
||||
systim.wSecond=(WORD)wrap((int)second,0,59);
|
||||
SetLocalTime(&systim);
|
||||
#else
|
||||
/* Linux/Unix (and some DOS compilers) have stime(); on Linux/Unix, you
|
||||
* must have "root" permission to call stime(); many POSIX systems will
|
||||
* have settimeofday() instead
|
||||
*/
|
||||
time_t sec1970;
|
||||
struct tm gtm;
|
||||
#if defined __APPLE__ /* also valid for other POSIX systems */
|
||||
struct timeval tv;
|
||||
#endif
|
||||
|
||||
time(&sec1970);
|
||||
gtm=*localtime(&sec1970);
|
||||
if (hour!=CELLMIN)
|
||||
gtm.tm_hour=wrap((int)hour,0,23);
|
||||
if (minute!=CELLMIN)
|
||||
gtm.tm_min=wrap((int)minute,0,59);
|
||||
if (second!=CELLMIN)
|
||||
gtm.tm_sec=wrap((int)second,0,59);
|
||||
sec1970=mktime(>m);
|
||||
#if defined __APPLE__ /* also valid for other POSIX systems */
|
||||
tv.tv_sec = sec1970;
|
||||
tv.tv_usec = 0;
|
||||
settimeofday(&tv, 0);
|
||||
#else
|
||||
stime(&sec1970);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
static void setdate(cell year,cell month,cell day)
|
||||
{
|
||||
int maxday;
|
||||
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32
|
||||
SYSTEMTIME systim;
|
||||
|
||||
GetLocalTime(&systim);
|
||||
if (year!=CELLMIN)
|
||||
systim.wYear=(WORD)wrap((int)year,1970,2099);
|
||||
if (month!=CELLMIN)
|
||||
systim.wMonth=(WORD)wrap((int)month,1,12);
|
||||
maxday=monthdays[systim.wMonth - 1];
|
||||
if (systim.wMonth==2 && ((systim.wYear % 4)==0 && ((systim.wYear % 100)!=0 || (systim.wYear % 400)==0)))
|
||||
maxday++;
|
||||
if (day!=CELLMIN)
|
||||
systim.wDay=(WORD)wrap((int)day,1,maxday);
|
||||
SetLocalTime(&systim);
|
||||
#else
|
||||
/* Linux/Unix (and some DOS compilers) have stime(); on Linux/Unix, you
|
||||
* must have "root" permission to call stime(); many POSIX systems will
|
||||
* have settimeofday() instead
|
||||
*/
|
||||
time_t sec1970;
|
||||
struct tm gtm;
|
||||
#if defined __APPLE__ /* also valid for other POSIX systems */
|
||||
struct timeval tv;
|
||||
#endif
|
||||
|
||||
time(&sec1970);
|
||||
gtm=*localtime(&sec1970);
|
||||
if (year!=CELLMIN)
|
||||
gtm.tm_year=year-1900;
|
||||
if (month!=CELLMIN)
|
||||
gtm.tm_mon=month-1;
|
||||
if (day!=CELLMIN)
|
||||
gtm.tm_mday=day;
|
||||
sec1970=mktime(>m);
|
||||
#if defined __APPLE__ /* also valid for other POSIX systems */
|
||||
tv.tv_sec = sec1970;
|
||||
tv.tv_usec = 0;
|
||||
settimeofday(&tv, 0);
|
||||
#else
|
||||
stime(&sec1970);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* settime(hour, minute, second)
|
||||
* Always returns 0
|
||||
*/
|
||||
static cell AMX_NATIVE_CALL n_settime(AMX *amx, const cell *params)
|
||||
{
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32
|
||||
SYSTEMTIME systim;
|
||||
|
||||
GetLocalTime(&systim);
|
||||
if (params[1]!=CELLMIN)
|
||||
systim.wHour=(WORD)wrap((int)params[1],0,23);
|
||||
if (params[2]!=CELLMIN)
|
||||
systim.wMinute=(WORD)wrap((int)params[2],0,59);
|
||||
if (params[3]!=CELLMIN)
|
||||
systim.wSecond=(WORD)wrap((int)params[3],0,59);
|
||||
SetLocalTime(&systim);
|
||||
#else
|
||||
/* Linux/Unix (and some DOS compilers) have stime(); on Linux/Unix, you
|
||||
* must have "root" permission to call stime()
|
||||
*/
|
||||
time_t sec1970;
|
||||
struct tm gtm;
|
||||
|
||||
(void)amx;
|
||||
time(&sec1970);
|
||||
gtm=*localtime(&sec1970);
|
||||
if (params[1]!=CELLMIN)
|
||||
gtm.tm_hour=wrap((int)params[1],0,23);
|
||||
if (params[2]!=CELLMIN)
|
||||
gtm.tm_min=wrap((int)params[2],0,59);
|
||||
if (params[3]!=CELLMIN)
|
||||
gtm.tm_sec=wrap((int)params[3],0,59);
|
||||
sec1970=mktime(>m);
|
||||
stime(&sec1970);
|
||||
#endif
|
||||
(void)amx;
|
||||
settime(params[1],params[2],params[3]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -258,17 +133,17 @@ static cell AMX_NATIVE_CALL n_gettime(AMX *amx, const cell *params)
|
||||
* library; in that case gmtime() and localtime() return the same value
|
||||
*/
|
||||
gtm=*localtime(&sec1970);
|
||||
cptr=amx_Address(amx,params[1]);
|
||||
*cptr=gtm.tm_hour;
|
||||
cptr=amx_Address(amx,params[2]);
|
||||
*cptr=gtm.tm_min;
|
||||
cptr=amx_Address(amx,params[3]);
|
||||
*cptr=gtm.tm_sec;
|
||||
if (amx_GetAddr(amx,params[1],&cptr)==AMX_ERR_NONE)
|
||||
*cptr=gtm.tm_hour;
|
||||
if (amx_GetAddr(amx,params[2],&cptr)==AMX_ERR_NONE)
|
||||
*cptr=gtm.tm_min;
|
||||
if (amx_GetAddr(amx,params[3],&cptr)==AMX_ERR_NONE)
|
||||
*cptr=gtm.tm_sec;
|
||||
|
||||
/* the time() function returns the number of seconds since January 1 1970
|
||||
* in Universal Coordinated Time (the successor to Greenwich Mean Time)
|
||||
*/
|
||||
return (cell)sec1970;
|
||||
return sec1970;
|
||||
}
|
||||
|
||||
/* setdate(year, month, day)
|
||||
@ -276,8 +151,42 @@ static cell AMX_NATIVE_CALL n_gettime(AMX *amx, const cell *params)
|
||||
*/
|
||||
static cell AMX_NATIVE_CALL n_setdate(AMX *amx, const cell *params)
|
||||
{
|
||||
int maxday;
|
||||
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32
|
||||
SYSTEMTIME systim;
|
||||
|
||||
GetLocalTime(&systim);
|
||||
if (params[1]!=CELLMIN)
|
||||
systim.wYear=(WORD)wrap((int)params[1],1970,2099);
|
||||
if (params[2]!=CELLMIN)
|
||||
systim.wMonth=(WORD)wrap((int)params[2],1,12);
|
||||
maxday=monthdays[systim.wMonth - 1];
|
||||
if (systim.wMonth==2 && ((systim.wYear % 4)==0 && ((systim.wYear % 100)!=0 || (systim.wYear % 400)==0)))
|
||||
maxday++;
|
||||
if (params[3]!=CELLMIN)
|
||||
systim.wDay=(WORD)wrap((int)params[3],1,maxday);
|
||||
SetLocalTime(&systim);
|
||||
#else
|
||||
/* Linux/Unix (and some DOS compilers) have stime(); on Linux/Unix, you
|
||||
* must have "root" permission to call stime()
|
||||
*/
|
||||
time_t sec1970;
|
||||
struct tm gtm;
|
||||
|
||||
(void)amx;
|
||||
time(&sec1970);
|
||||
gtm=*localtime(&sec1970);
|
||||
if (params[1]!=CELLMIN)
|
||||
gtm.tm_year=params[1]-1900;
|
||||
if (params[2]!=CELLMIN)
|
||||
gtm.tm_mon=params[2]-1;
|
||||
if (params[3]!=CELLMIN)
|
||||
gtm.tm_mday=params[3];
|
||||
sec1970=mktime(>m);
|
||||
stime(&sec1970);
|
||||
#endif
|
||||
(void)amx;
|
||||
setdate(params[1],params[2],params[3]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -296,12 +205,12 @@ static cell AMX_NATIVE_CALL n_getdate(AMX *amx, const cell *params)
|
||||
time(&sec1970);
|
||||
|
||||
gtm=*localtime(&sec1970);
|
||||
cptr=amx_Address(amx,params[1]);
|
||||
*cptr=gtm.tm_year+1900;
|
||||
cptr=amx_Address(amx,params[2]);
|
||||
*cptr=gtm.tm_mon+1;
|
||||
cptr=amx_Address(amx,params[3]);
|
||||
*cptr=gtm.tm_mday;
|
||||
if (amx_GetAddr(amx,params[1],&cptr)==AMX_ERR_NONE)
|
||||
*cptr=gtm.tm_year+1900;
|
||||
if (amx_GetAddr(amx,params[2],&cptr)==AMX_ERR_NONE)
|
||||
*cptr=gtm.tm_mon+1;
|
||||
if (amx_GetAddr(amx,params[3],&cptr)==AMX_ERR_NONE)
|
||||
*cptr=gtm.tm_mday;
|
||||
|
||||
return gtm.tm_yday+1;
|
||||
}
|
||||
@ -317,11 +226,12 @@ static cell AMX_NATIVE_CALL n_tickcount(AMX *amx, const cell *params)
|
||||
assert(params[0]==(int)sizeof(cell));
|
||||
|
||||
INIT_TIMER();
|
||||
cptr=amx_Address(amx,params[1]);
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32
|
||||
*cptr=1000; /* granularity = 1 ms */
|
||||
if (amx_GetAddr(amx,params[1],&cptr)==AMX_ERR_NONE)
|
||||
*cptr=1000; /* granularity = 1 ms */
|
||||
#else
|
||||
*cptr=(cell)CLOCKS_PER_SEC; /* in Unix/Linux, this is often 100 */
|
||||
if (amx_GetAddr(amx,params[1],&cptr)==AMX_ERR_NONE)
|
||||
*cptr=(cell)CLOCKS_PER_SEC; /* in Unix/Linux, this is often 100 */
|
||||
#endif
|
||||
return gettimestamp() & 0x7fffffff;
|
||||
}
|
||||
@ -366,59 +276,13 @@ static cell AMX_NATIVE_CALL n_gettimer(AMX *amx, const cell *params)
|
||||
cell *cptr;
|
||||
|
||||
assert(params[0]==(int)(2*sizeof(cell)));
|
||||
cptr=amx_Address(amx,params[1]);
|
||||
*cptr=timelimit;
|
||||
cptr=amx_Address(amx,params[2]);
|
||||
*cptr=timerepeat;
|
||||
if (amx_GetAddr(amx,params[1],&cptr)==AMX_ERR_NONE)
|
||||
*cptr=timelimit;
|
||||
if (amx_GetAddr(amx,params[1],&cptr)==AMX_ERR_NONE)
|
||||
*cptr=timerepeat;
|
||||
return timelimit>0;
|
||||
}
|
||||
|
||||
/* settimestamp(seconds1970) sets the date and time from a single parameter: the
|
||||
* number of seconds since 1 January 1970.
|
||||
*/
|
||||
static cell AMX_NATIVE_CALL n_settimestamp(AMX *amx, const cell *params)
|
||||
{
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32
|
||||
int year, month, day, hour, minute, second;
|
||||
|
||||
stamp2datetime(params[1],
|
||||
&year, &month, &day,
|
||||
&hour, &minute, &second);
|
||||
setdate(year, month, day);
|
||||
settime(hour, minute, second);
|
||||
#else
|
||||
/* Linux/Unix (and some DOS compilers) have stime(); on Linux/Unix, you
|
||||
* must have "root" permission to call stime(); many POSIX systems will
|
||||
* have settimeofday() instead
|
||||
*/
|
||||
#if defined __APPLE__ /* also valid for other POSIX systems */
|
||||
struct timeval tv;
|
||||
tv.tv_sec = params[1];
|
||||
tv.tv_usec = 0;
|
||||
settimeofday(&tv, 0);
|
||||
#else
|
||||
time_t sec1970=(time_t)params[1];
|
||||
stime(&sec1970);
|
||||
#endif
|
||||
#endif
|
||||
(void)amx;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* cvttimestamp(seconds1970, &year, &month, &day, &hour, &minute, &second)
|
||||
*/
|
||||
static cell AMX_NATIVE_CALL n_cvttimestamp(AMX *amx, const cell *params)
|
||||
{
|
||||
int year, month, day, hour, minute, second;
|
||||
|
||||
(void)amx;
|
||||
stamp2datetime(params[1],
|
||||
&year, &month, &day,
|
||||
&hour, &minute, &second);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if !defined AMXTIME_NOIDLE
|
||||
static AMX_IDLE PrevIdle = NULL;
|
||||
@ -452,20 +316,18 @@ static int AMXAPI amx_TimeIdle(AMX *amx, int AMXAPI Exec(AMX *, cell *, int))
|
||||
extern "C"
|
||||
#endif
|
||||
const AMX_NATIVE_INFO time_Natives[] = {
|
||||
{ "gettime", n_gettime },
|
||||
{ "settime", n_settime },
|
||||
{ "getdate", n_getdate },
|
||||
{ "setdate", n_setdate },
|
||||
{ "tickcount", n_tickcount },
|
||||
{ "settimer", n_settimer },
|
||||
{ "gettimer", n_gettimer },
|
||||
{ "delay", n_delay },
|
||||
{ "settimestamp", n_settimestamp },
|
||||
{ "cvttimestamp", n_cvttimestamp },
|
||||
{ "gettime", n_gettime },
|
||||
{ "settime", n_settime },
|
||||
{ "getdate", n_getdate },
|
||||
{ "setdate", n_setdate },
|
||||
{ "tickcount", n_tickcount },
|
||||
{ "settimer", n_settimer },
|
||||
{ "gettimer", n_gettimer },
|
||||
{ "delay", n_delay },
|
||||
{ NULL, NULL } /* terminator */
|
||||
};
|
||||
|
||||
int AMXEXPORT AMXAPI amx_TimeInit(AMX *amx)
|
||||
int AMXEXPORT amx_TimeInit(AMX *amx)
|
||||
{
|
||||
#if !defined AMXTIME_NOIDLE
|
||||
/* see whether there is a @timer() function */
|
||||
@ -479,7 +341,7 @@ int AMXEXPORT AMXAPI amx_TimeInit(AMX *amx)
|
||||
return amx_Register(amx, time_Natives, -1);
|
||||
}
|
||||
|
||||
int AMXEXPORT AMXAPI amx_TimeCleanup(AMX *amx)
|
||||
int AMXEXPORT amx_TimeCleanup(AMX *amx)
|
||||
{
|
||||
(void)amx;
|
||||
#if !defined AMXTIME_NOIDLE
|
||||
|
@ -10,15 +10,15 @@
|
||||
* All strings MUST have an explicit \0. See the Windows SDK documentation
|
||||
* for details on version information and the VERSIONINFO structure.
|
||||
*/
|
||||
#define VERSION 4
|
||||
#define REVISION 0
|
||||
#define VERSION 1
|
||||
#define REVISION 1
|
||||
#define BUILD 0
|
||||
#define VERSIONSTR "4.0.0\0"
|
||||
#define VERSIONSTR "1.2.0\0"
|
||||
#define VERSIONNAME "amxTime.dll\0"
|
||||
#define VERSIONDESCRIPTION "Pawn AMX: time routines\0"
|
||||
#define VERSIONCOMPANYNAME "ITB CompuPhase\0"
|
||||
#define VERSIONPRODUCTNAME "amxTime\0"
|
||||
#define VERSIONCOPYRIGHT "Copyright \251 2005-2016 ITB CompuPhase\0"
|
||||
#define VERSIONCOPYRIGHT "Copyright \251 2005-2006 ITB CompuPhase\0"
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION VERSION, REVISION, BUILD, 0
|
||||
|
@ -45,7 +45,7 @@ static cell AMX_NATIVE_CALL n_float(AMX *amx,const cell *params)
|
||||
{
|
||||
/*
|
||||
* params[0] = number of bytes
|
||||
* params[1] = integer value to convert to a float
|
||||
* params[1] = long value to convert to a float
|
||||
*/
|
||||
REAL fValue;
|
||||
|
||||
@ -74,7 +74,7 @@ static cell AMX_NATIVE_CALL n_strfloat(AMX *amx,const cell *params)
|
||||
assert(params[0]/sizeof(cell)==1);
|
||||
|
||||
/* Get the real address of the string. */
|
||||
pString=amx_Address(amx,params[1]);
|
||||
amx_GetAddr(amx,params[1],&pString);
|
||||
|
||||
/* Find out how long the string is in characters. */
|
||||
amx_StrLen(pString, &nLen);
|
||||
@ -163,20 +163,20 @@ static cell AMX_NATIVE_CALL n_floatround(AMX *amx,const cell *params)
|
||||
/*
|
||||
* params[0] = number of bytes
|
||||
* params[1] = float operand
|
||||
* params[2] = Type of rounding (integer)
|
||||
* params[2] = Type of rounding (long)
|
||||
*/
|
||||
REAL fA = amx_ctof(params[1]);
|
||||
|
||||
(void)amx;
|
||||
switch (params[2])
|
||||
{
|
||||
case 1: /* round downwards */
|
||||
case 1: /* round downwards (truncate) */
|
||||
fA = (REAL)(floor((double)fA));
|
||||
break;
|
||||
case 2: /* round upwards */
|
||||
fA = (REAL)(ceil((double)fA));
|
||||
break;
|
||||
case 3: /* round towards zero (truncate) */
|
||||
case 3: /* round towards zero */
|
||||
if ( fA>=0.0 )
|
||||
fA = (REAL)(floor((double)fA));
|
||||
else
|
||||
@ -187,7 +187,7 @@ static cell AMX_NATIVE_CALL n_floatround(AMX *amx,const cell *params)
|
||||
break;
|
||||
}
|
||||
|
||||
return (cell)fA;
|
||||
return (long)fA;
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
@ -284,7 +284,7 @@ static cell AMX_NATIVE_CALL n_floatsin(AMX *amx,const cell *params)
|
||||
*/
|
||||
REAL fA = amx_ctof(params[1]);
|
||||
fA = ToRadians(fA, params[2]);
|
||||
fA = (float)sin(fA);
|
||||
fA = sin(fA);
|
||||
(void)amx;
|
||||
return amx_ftoc(fA);
|
||||
}
|
||||
@ -299,7 +299,7 @@ static cell AMX_NATIVE_CALL n_floatcos(AMX *amx,const cell *params)
|
||||
*/
|
||||
REAL fA = amx_ctof(params[1]);
|
||||
fA = ToRadians(fA, params[2]);
|
||||
fA = (float)cos(fA);
|
||||
fA = cos(fA);
|
||||
(void)amx;
|
||||
return amx_ftoc(fA);
|
||||
}
|
||||
@ -314,7 +314,7 @@ static cell AMX_NATIVE_CALL n_floattan(AMX *amx,const cell *params)
|
||||
*/
|
||||
REAL fA = amx_ctof(params[1]);
|
||||
fA = ToRadians(fA, params[2]);
|
||||
fA = (float)tan(fA);
|
||||
fA = tan(fA);
|
||||
(void)amx;
|
||||
return amx_ftoc(fA);
|
||||
}
|
||||
@ -328,22 +328,6 @@ static cell AMX_NATIVE_CALL n_floatabs(AMX *amx,const cell *params)
|
||||
return amx_ftoc(fA);
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
/* return the integer part of a real value, truncated
|
||||
* Return integer part of float, truncated (same as floatround
|
||||
* with mode 3)
|
||||
*/
|
||||
static cell AMX_NATIVE_CALL n_floatint(AMX *amx,const cell *params)
|
||||
{
|
||||
REAL fA = amx_ctof(params[1]);
|
||||
if ( fA>=0.0 )
|
||||
fA = (REAL)(floor((double)fA));
|
||||
else
|
||||
fA = (REAL)(ceil((double)fA));
|
||||
(void)amx;
|
||||
return (cell)fA;
|
||||
}
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
@ -364,16 +348,15 @@ const AMX_NATIVE_INFO float_Natives[] = {
|
||||
{ "floatcos", n_floatcos },
|
||||
{ "floattan", n_floattan },
|
||||
{ "floatabs", n_floatabs },
|
||||
{ "floatint", n_floatint }, // also add user-defined operator "="
|
||||
{ NULL, NULL } /* terminator */
|
||||
};
|
||||
|
||||
int AMXEXPORT AMXAPI amx_FloatInit(AMX *amx)
|
||||
int AMXEXPORT amx_FloatInit(AMX *amx)
|
||||
{
|
||||
return amx_Register(amx,float_Natives,-1);
|
||||
}
|
||||
|
||||
int AMXEXPORT AMXAPI amx_FloatCleanup(AMX *amx)
|
||||
int AMXEXPORT amx_FloatCleanup(AMX *amx)
|
||||
{
|
||||
(void)amx;
|
||||
return AMX_ERR_NONE;
|
@ -1,31 +0,0 @@
|
||||
/* Glue functions for the minIni library, based on the C/C++ stdio library
|
||||
*
|
||||
* Or better said: this file contains macros that maps the function interface
|
||||
* used by minIni to the standard C/C++ file I/O functions.
|
||||
*
|
||||
* By CompuPhase, 2008-2014
|
||||
* This "glue file" is in the public domain. It is distributed without
|
||||
* warranties or conditions of any kind, either express or implied.
|
||||
*/
|
||||
|
||||
/* map required file I/O types and functions to the standard C library */
|
||||
#include <stdio.h>
|
||||
|
||||
#define INI_FILETYPE FILE*
|
||||
#define ini_openread(filename,file) ((*(file) = fopen((filename),"rb")) != NULL)
|
||||
#define ini_openwrite(filename,file) ((*(file) = fopen((filename),"wb")) != NULL)
|
||||
#define ini_openrewrite(filename,file) ((*(file) = fopen((filename),"r+b")) != NULL)
|
||||
#define ini_close(file) (fclose(*(file)) == 0)
|
||||
#define ini_read(buffer,size,file) (fgets((buffer),(size),*(file)) != NULL)
|
||||
#define ini_write(buffer,file) (fputs((buffer),*(file)) >= 0)
|
||||
#define ini_rename(source,dest) (rename((source), (dest)) == 0)
|
||||
#define ini_remove(filename) (remove(filename) == 0)
|
||||
|
||||
#define INI_FILEPOS long int
|
||||
#define ini_tell(file,pos) (*(pos) = ftell(*(file)))
|
||||
#define ini_seek(file,pos) (fseek(*(file), *(pos), SEEK_SET) == 0)
|
||||
|
||||
/* for floating-point support, define additional types and functions */
|
||||
#define INI_REAL float
|
||||
#define ini_ftoa(string,value) sprintf((string),"%f",(value))
|
||||
#define ini_atof(string) (INI_REAL)strtod((string),NULL)
|
@ -1,878 +0,0 @@
|
||||
/* minIni - Multi-Platform INI file parser, suitable for embedded systems
|
||||
*
|
||||
* These routines are in part based on the article "Multiplatform .INI Files"
|
||||
* by Joseph J. Graf in the March 1994 issue of Dr. Dobb's Journal.
|
||||
*
|
||||
* Copyright (c) CompuPhase, 2008-2017
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Version: $Id: minIni.c 5690 2017-06-08 14:04:08Z thiadmer $
|
||||
*/
|
||||
|
||||
#if (defined _UNICODE || defined __UNICODE__ || defined UNICODE) && !defined INI_ANSIONLY
|
||||
# if !defined UNICODE /* for Windows */
|
||||
# define UNICODE
|
||||
# endif
|
||||
# if !defined _UNICODE /* for C library */
|
||||
# define _UNICODE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define MININI_IMPLEMENTATION
|
||||
#include "minIni.h"
|
||||
#if defined NDEBUG
|
||||
#if defined assert
|
||||
#undef assert
|
||||
#endif
|
||||
#define assert(e)
|
||||
#else
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
#if !defined __T || defined INI_ANSIONLY
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#define TCHAR char
|
||||
#define __T(s) s
|
||||
#define _tcscat strcat
|
||||
#define _tcschr strchr
|
||||
#define _tcscmp strcmp
|
||||
#define _tcscpy strcpy
|
||||
#define _tcsicmp stricmp
|
||||
#define _tcslen strlen
|
||||
#define _tcsncmp strncmp
|
||||
#define _tcsnicmp strnicmp
|
||||
#define _tcsrchr strrchr
|
||||
#define _tcstol strtol
|
||||
#define _tcstod strtod
|
||||
#define _totupper toupper
|
||||
#define _stprintf sprintf
|
||||
#define _tfgets fgets
|
||||
#define _tfputs fputs
|
||||
#define _tfopen fopen
|
||||
#define _tremove remove
|
||||
#define _trename rename
|
||||
#endif
|
||||
|
||||
#if defined __linux || defined __linux__
|
||||
#define __LINUX__
|
||||
#elif defined FREEBSD && !defined __FreeBSD__
|
||||
#define __FreeBSD__
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma warning(disable: 4996) /* for Microsoft Visual C/C++ */
|
||||
#endif
|
||||
#if !defined strnicmp && !defined PORTABLE_STRNICMP
|
||||
#if defined __LINUX__ || defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__
|
||||
#define strnicmp strncasecmp
|
||||
#endif
|
||||
#endif
|
||||
#if !defined _totupper
|
||||
#include <ctype.h>
|
||||
#define _totupper toupper
|
||||
#endif
|
||||
|
||||
#if !defined INI_LINETERM
|
||||
#if defined __LINUX__ || defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__
|
||||
#define INI_LINETERM __T("\n")
|
||||
#else
|
||||
#define INI_LINETERM __T("\r\n")
|
||||
#endif
|
||||
#endif
|
||||
#if !defined INI_FILETYPE
|
||||
#error Missing definition for INI_FILETYPE.
|
||||
#endif
|
||||
|
||||
#if !defined sizearray
|
||||
#define sizearray(a) (sizeof(a) / sizeof((a)[0]))
|
||||
#endif
|
||||
|
||||
enum quote_option {
|
||||
QUOTE_NONE,
|
||||
QUOTE_ENQUOTE,
|
||||
QUOTE_DEQUOTE,
|
||||
};
|
||||
|
||||
#if defined PORTABLE_STRNICMP
|
||||
int strnicmp(const TCHAR *s1, const TCHAR *s2, size_t n)
|
||||
{
|
||||
while (n-- != 0 && (*s1 || *s2)) {
|
||||
register int c1, c2;
|
||||
c1 = *s1++;
|
||||
if ('a' <= c1 && c1 <= 'z')
|
||||
c1 += ('A' - 'a');
|
||||
c2 = *s2++;
|
||||
if ('a' <= c2 && c2 <= 'z')
|
||||
c2 += ('A' - 'a');
|
||||
if (c1 != c2)
|
||||
return c1 - c2;
|
||||
} /* while */
|
||||
return 0;
|
||||
}
|
||||
#endif /* PORTABLE_STRNICMP */
|
||||
|
||||
static TCHAR *skipleading(const TCHAR *str)
|
||||
{
|
||||
assert(str != NULL);
|
||||
while ('\0' < *str && *str <= ' ')
|
||||
str++;
|
||||
return (TCHAR *)str;
|
||||
}
|
||||
|
||||
static TCHAR *skiptrailing(const TCHAR *str, const TCHAR *base)
|
||||
{
|
||||
assert(str != NULL);
|
||||
assert(base != NULL);
|
||||
while (str > base && '\0' < *(str-1) && *(str-1) <= ' ')
|
||||
str--;
|
||||
return (TCHAR *)str;
|
||||
}
|
||||
|
||||
static TCHAR *striptrailing(TCHAR *str)
|
||||
{
|
||||
TCHAR *ptr = skiptrailing(_tcschr(str, '\0'), str);
|
||||
assert(ptr != NULL);
|
||||
*ptr = '\0';
|
||||
return str;
|
||||
}
|
||||
|
||||
static TCHAR *save_strncpy(TCHAR *dest, const TCHAR *source, size_t maxlen, enum quote_option option)
|
||||
{
|
||||
size_t d, s;
|
||||
|
||||
assert(maxlen>0);
|
||||
assert(dest <= source || dest >= source + maxlen);
|
||||
if (option == QUOTE_ENQUOTE && maxlen < 3)
|
||||
option = QUOTE_NONE; /* cannot store two quotes and a terminating zero in less than 3 characters */
|
||||
|
||||
switch (option) {
|
||||
case QUOTE_NONE:
|
||||
for (d = 0; d < maxlen - 1 && source[d] != '\0'; d++)
|
||||
dest[d] = source[d];
|
||||
assert(d < maxlen);
|
||||
dest[d] = '\0';
|
||||
break;
|
||||
case QUOTE_ENQUOTE:
|
||||
d = 0;
|
||||
dest[d++] = '"';
|
||||
for (s = 0; source[s] != '\0' && d < maxlen - 2; s++, d++) {
|
||||
if (source[s] == '"') {
|
||||
if (d >= maxlen - 3)
|
||||
break; /* no space to store the escape character plus the one that follows it */
|
||||
dest[d++] = '\\';
|
||||
} /* if */
|
||||
dest[d] = source[s];
|
||||
} /* for */
|
||||
dest[d++] = '"';
|
||||
dest[d] = '\0';
|
||||
break;
|
||||
case QUOTE_DEQUOTE:
|
||||
for (d = s = 0; source[s] != '\0' && d < maxlen - 1; s++, d++) {
|
||||
if ((source[s] == '"' || source[s] == '\\') && source[s + 1] == '"')
|
||||
s++;
|
||||
dest[d] = source[s];
|
||||
} /* for */
|
||||
dest[d] = '\0';
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
} /* switch */
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
static TCHAR *cleanstring(TCHAR *string, enum quote_option *quotes)
|
||||
{
|
||||
int isstring;
|
||||
TCHAR *ep;
|
||||
|
||||
assert(string != NULL);
|
||||
assert(quotes != NULL);
|
||||
|
||||
/* Remove a trailing comment */
|
||||
isstring = 0;
|
||||
for (ep = string; *ep != '\0' && ((*ep != ';' && *ep != '#') || isstring); ep++) {
|
||||
if (*ep == '"') {
|
||||
if (*(ep + 1) == '"')
|
||||
ep++; /* skip "" (both quotes) */
|
||||
else
|
||||
isstring = !isstring; /* single quote, toggle isstring */
|
||||
} else if (*ep == '\\' && *(ep + 1) == '"') {
|
||||
ep++; /* skip \" (both quotes */
|
||||
} /* if */
|
||||
} /* for */
|
||||
assert(ep != NULL && (*ep == '\0' || *ep == ';' || *ep == '#'));
|
||||
*ep = '\0'; /* terminate at a comment */
|
||||
striptrailing(string);
|
||||
/* Remove double quotes surrounding a value */
|
||||
*quotes = QUOTE_NONE;
|
||||
if (*string == '"' && (ep = _tcschr(string, '\0')) != NULL && *(ep - 1) == '"') {
|
||||
string++;
|
||||
*--ep = '\0';
|
||||
*quotes = QUOTE_DEQUOTE; /* this is a string, so remove escaped characters */
|
||||
} /* if */
|
||||
return string;
|
||||
}
|
||||
|
||||
static int getkeystring(INI_FILETYPE *fp, const TCHAR *Section, const TCHAR *Key,
|
||||
int idxSection, int idxKey, TCHAR *Buffer, int BufferSize,
|
||||
INI_FILEPOS *mark)
|
||||
{
|
||||
TCHAR *sp, *ep;
|
||||
int len, idx;
|
||||
enum quote_option quotes;
|
||||
TCHAR LocalBuffer[INI_BUFFERSIZE];
|
||||
|
||||
assert(fp != NULL);
|
||||
/* Move through file 1 line at a time until a section is matched or EOF. If
|
||||
* parameter Section is NULL, only look at keys above the first section. If
|
||||
* idxSection is postive, copy the relevant section name.
|
||||
*/
|
||||
len = (Section != NULL) ? (int)_tcslen(Section) : 0;
|
||||
if (len > 0 || idxSection >= 0) {
|
||||
assert(Section != NULL);
|
||||
idx = -1;
|
||||
do {
|
||||
if (!ini_read(LocalBuffer, INI_BUFFERSIZE, fp))
|
||||
return 0;
|
||||
sp = skipleading(LocalBuffer);
|
||||
ep = _tcsrchr(sp, ']');
|
||||
} while (*sp != '[' || ep == NULL || (((int)(ep-sp-1) != len || _tcsnicmp(sp+1,Section,len) != 0) && ++idx != idxSection));
|
||||
if (idxSection >= 0) {
|
||||
if (idx == idxSection) {
|
||||
assert(ep != NULL);
|
||||
assert(*ep == ']');
|
||||
*ep = '\0';
|
||||
save_strncpy(Buffer, sp + 1, BufferSize, QUOTE_NONE);
|
||||
return 1;
|
||||
} /* if */
|
||||
return 0; /* no more section found */
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
/* Now that the section has been found, find the entry.
|
||||
* Stop searching upon leaving the section's area.
|
||||
*/
|
||||
assert(Key != NULL || idxKey >= 0);
|
||||
len = (Key != NULL) ? (int)_tcslen(Key) : 0;
|
||||
idx = -1;
|
||||
do {
|
||||
if (mark != NULL)
|
||||
ini_tell(fp, mark); /* optionally keep the mark to the start of the line */
|
||||
if (!ini_read(LocalBuffer,INI_BUFFERSIZE,fp) || *(sp = skipleading(LocalBuffer)) == '[')
|
||||
return 0;
|
||||
sp = skipleading(LocalBuffer);
|
||||
ep = _tcschr(sp, '='); /* Parse out the equal sign */
|
||||
if (ep == NULL)
|
||||
ep = _tcschr(sp, ':');
|
||||
} while (*sp == ';' || *sp == '#' || ep == NULL
|
||||
|| ((len == 0 || (int)(skiptrailing(ep,sp)-sp) != len || _tcsnicmp(sp,Key,len) != 0) && ++idx != idxKey));
|
||||
if (idxKey >= 0) {
|
||||
if (idx == idxKey) {
|
||||
assert(ep != NULL);
|
||||
assert(*ep == '=' || *ep == ':');
|
||||
*ep = '\0';
|
||||
striptrailing(sp);
|
||||
save_strncpy(Buffer, sp, BufferSize, QUOTE_NONE);
|
||||
return 1;
|
||||
} /* if */
|
||||
return 0; /* no more key found (in this section) */
|
||||
} /* if */
|
||||
|
||||
/* Copy up to BufferSize chars to buffer */
|
||||
assert(ep != NULL);
|
||||
assert(*ep == '=' || *ep == ':');
|
||||
sp = skipleading(ep + 1);
|
||||
sp = cleanstring(sp, "es); /* Remove a trailing comment */
|
||||
save_strncpy(Buffer, sp, BufferSize, quotes);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** ini_gets()
|
||||
* \param Section the name of the section to search for
|
||||
* \param Key the name of the entry to find the value of
|
||||
* \param DefValue default string in the event of a failed read
|
||||
* \param Buffer a pointer to the buffer to copy into
|
||||
* \param BufferSize the maximum number of characters to copy
|
||||
* \param Filename the name and full path of the .ini file to read from
|
||||
*
|
||||
* \return the number of characters copied into the supplied buffer
|
||||
*/
|
||||
int ini_gets(const TCHAR *Section, const TCHAR *Key, const TCHAR *DefValue,
|
||||
TCHAR *Buffer, int BufferSize, const TCHAR *Filename)
|
||||
{
|
||||
INI_FILETYPE fp;
|
||||
int ok = 0;
|
||||
|
||||
if (Buffer == NULL || BufferSize <= 0 || Key == NULL)
|
||||
return 0;
|
||||
if (ini_openread(Filename, &fp)) {
|
||||
ok = getkeystring(&fp, Section, Key, -1, -1, Buffer, BufferSize, NULL);
|
||||
(void)ini_close(&fp);
|
||||
} /* if */
|
||||
if (!ok)
|
||||
save_strncpy(Buffer, (DefValue != NULL) ? DefValue : __T(""), BufferSize, QUOTE_NONE);
|
||||
return (int)_tcslen(Buffer);
|
||||
}
|
||||
|
||||
/** ini_getl()
|
||||
* \param Section the name of the section to search for
|
||||
* \param Key the name of the entry to find the value of
|
||||
* \param DefValue the default value in the event of a failed read
|
||||
* \param Filename the name of the .ini file to read from
|
||||
*
|
||||
* \return the value located at Key
|
||||
*/
|
||||
long ini_getl(const TCHAR *Section, const TCHAR *Key, long DefValue, const TCHAR *Filename)
|
||||
{
|
||||
TCHAR LocalBuffer[64];
|
||||
int len = ini_gets(Section, Key, __T(""), LocalBuffer, sizearray(LocalBuffer), Filename);
|
||||
return (len == 0) ? DefValue
|
||||
: ((len >= 2 && _totupper((int)LocalBuffer[1]) == 'X') ? _tcstol(LocalBuffer, NULL, 16)
|
||||
: _tcstol(LocalBuffer, NULL, 10));
|
||||
}
|
||||
|
||||
#if defined INI_REAL
|
||||
/** ini_getf()
|
||||
* \param Section the name of the section to search for
|
||||
* \param Key the name of the entry to find the value of
|
||||
* \param DefValue the default value in the event of a failed read
|
||||
* \param Filename the name of the .ini file to read from
|
||||
*
|
||||
* \return the value located at Key
|
||||
*/
|
||||
INI_REAL ini_getf(const TCHAR *Section, const TCHAR *Key, INI_REAL DefValue, const TCHAR *Filename)
|
||||
{
|
||||
TCHAR LocalBuffer[64];
|
||||
int len = ini_gets(Section, Key, __T(""), LocalBuffer, sizearray(LocalBuffer), Filename);
|
||||
return (len == 0) ? DefValue : ini_atof(LocalBuffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** ini_getbool()
|
||||
* \param Section the name of the section to search for
|
||||
* \param Key the name of the entry to find the value of
|
||||
* \param DefValue default value in the event of a failed read; it should
|
||||
* zero (0) or one (1).
|
||||
* \param Filename the name and full path of the .ini file to read from
|
||||
*
|
||||
* A true boolean is found if one of the following is matched:
|
||||
* - A string starting with 'y' or 'Y'
|
||||
* - A string starting with 't' or 'T'
|
||||
* - A string starting with '1'
|
||||
*
|
||||
* A false boolean is found if one of the following is matched:
|
||||
* - A string starting with 'n' or 'N'
|
||||
* - A string starting with 'f' or 'F'
|
||||
* - A string starting with '0'
|
||||
*
|
||||
* \return the true/false flag as interpreted at Key
|
||||
*/
|
||||
int ini_getbool(const TCHAR *Section, const TCHAR *Key, int DefValue, const TCHAR *Filename)
|
||||
{
|
||||
TCHAR LocalBuffer[2] = __T("");
|
||||
int ret;
|
||||
|
||||
ini_gets(Section, Key, __T(""), LocalBuffer, sizearray(LocalBuffer), Filename);
|
||||
LocalBuffer[0] = (TCHAR)_totupper((int)LocalBuffer[0]);
|
||||
if (LocalBuffer[0] == 'Y' || LocalBuffer[0] == '1' || LocalBuffer[0] == 'T')
|
||||
ret = 1;
|
||||
else if (LocalBuffer[0] == 'N' || LocalBuffer[0] == '0' || LocalBuffer[0] == 'F')
|
||||
ret = 0;
|
||||
else
|
||||
ret = DefValue;
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/** ini_getsection()
|
||||
* \param idx the zero-based sequence number of the section to return
|
||||
* \param Buffer a pointer to the buffer to copy into
|
||||
* \param BufferSize the maximum number of characters to copy
|
||||
* \param Filename the name and full path of the .ini file to read from
|
||||
*
|
||||
* \return the number of characters copied into the supplied buffer
|
||||
*/
|
||||
int ini_getsection(int idx, TCHAR *Buffer, int BufferSize, const TCHAR *Filename)
|
||||
{
|
||||
INI_FILETYPE fp;
|
||||
int ok = 0;
|
||||
|
||||
if (Buffer == NULL || BufferSize <= 0 || idx < 0)
|
||||
return 0;
|
||||
if (ini_openread(Filename, &fp)) {
|
||||
ok = getkeystring(&fp, NULL, NULL, idx, -1, Buffer, BufferSize, NULL);
|
||||
(void)ini_close(&fp);
|
||||
} /* if */
|
||||
if (!ok)
|
||||
*Buffer = '\0';
|
||||
return (int)_tcslen(Buffer);
|
||||
}
|
||||
|
||||
/** ini_getkey()
|
||||
* \param Section the name of the section to browse through, or NULL to
|
||||
* browse through the keys outside any section
|
||||
* \param idx the zero-based sequence number of the key to return
|
||||
* \param Buffer a pointer to the buffer to copy into
|
||||
* \param BufferSize the maximum number of characters to copy
|
||||
* \param Filename the name and full path of the .ini file to read from
|
||||
*
|
||||
* \return the number of characters copied into the supplied buffer
|
||||
*/
|
||||
int ini_getkey(const TCHAR *Section, int idx, TCHAR *Buffer, int BufferSize, const TCHAR *Filename)
|
||||
{
|
||||
INI_FILETYPE fp;
|
||||
int ok = 0;
|
||||
|
||||
if (Buffer == NULL || BufferSize <= 0 || idx < 0)
|
||||
return 0;
|
||||
if (ini_openread(Filename, &fp)) {
|
||||
ok = getkeystring(&fp, Section, NULL, -1, idx, Buffer, BufferSize, NULL);
|
||||
(void)ini_close(&fp);
|
||||
} /* if */
|
||||
if (!ok)
|
||||
*Buffer = '\0';
|
||||
return (int)_tcslen(Buffer);
|
||||
}
|
||||
|
||||
|
||||
#if !defined INI_NOBROWSE
|
||||
/** ini_browse()
|
||||
* \param Callback a pointer to a function that will be called for every
|
||||
* setting in the INI file.
|
||||
* \param UserData arbitrary data, which the function passes on the the
|
||||
* \c Callback function
|
||||
* \param Filename the name and full path of the .ini file to read from
|
||||
*
|
||||
* \return 1 on success, 0 on failure (INI file not found)
|
||||
*
|
||||
* \note The \c Callback function must return 1 to continue
|
||||
* browsing through the INI file, or 0 to stop. Even when the
|
||||
* callback stops the browsing, this function will return 1
|
||||
* (for success).
|
||||
*/
|
||||
int ini_browse(INI_CALLBACK Callback, const void *UserData, const TCHAR *Filename)
|
||||
{
|
||||
TCHAR LocalBuffer[INI_BUFFERSIZE];
|
||||
int lenSec, lenKey;
|
||||
enum quote_option quotes;
|
||||
INI_FILETYPE fp;
|
||||
|
||||
if (Callback == NULL)
|
||||
return 0;
|
||||
if (!ini_openread(Filename, &fp))
|
||||
return 0;
|
||||
|
||||
LocalBuffer[0] = '\0'; /* copy an empty section in the buffer */
|
||||
lenSec = (int)_tcslen(LocalBuffer) + 1;
|
||||
for ( ;; ) {
|
||||
TCHAR *sp, *ep;
|
||||
if (!ini_read(LocalBuffer + lenSec, INI_BUFFERSIZE - lenSec, &fp))
|
||||
break;
|
||||
sp = skipleading(LocalBuffer + lenSec);
|
||||
/* ignore empty strings and comments */
|
||||
if (*sp == '\0' || *sp == ';' || *sp == '#')
|
||||
continue;
|
||||
/* see whether we reached a new section */
|
||||
ep = _tcsrchr(sp, ']');
|
||||
if (*sp == '[' && ep != NULL) {
|
||||
*ep = '\0';
|
||||
save_strncpy(LocalBuffer, sp + 1, INI_BUFFERSIZE, QUOTE_NONE);
|
||||
lenSec = (int)_tcslen(LocalBuffer) + 1;
|
||||
continue;
|
||||
} /* if */
|
||||
/* not a new section, test for a key/value pair */
|
||||
ep = _tcschr(sp, '='); /* test for the equal sign or colon */
|
||||
if (ep == NULL)
|
||||
ep = _tcschr(sp, ':');
|
||||
if (ep == NULL)
|
||||
continue; /* invalid line, ignore */
|
||||
*ep++ = '\0'; /* split the key from the value */
|
||||
striptrailing(sp);
|
||||
save_strncpy(LocalBuffer + lenSec, sp, INI_BUFFERSIZE - lenSec, QUOTE_NONE);
|
||||
lenKey = (int)_tcslen(LocalBuffer + lenSec) + 1;
|
||||
/* clean up the value */
|
||||
sp = skipleading(ep);
|
||||
sp = cleanstring(sp, "es); /* Remove a trailing comment */
|
||||
save_strncpy(LocalBuffer + lenSec + lenKey, sp, INI_BUFFERSIZE - lenSec - lenKey, quotes);
|
||||
/* call the callback */
|
||||
if (!Callback(LocalBuffer, LocalBuffer + lenSec, LocalBuffer + lenSec + lenKey, UserData))
|
||||
break;
|
||||
} /* for */
|
||||
|
||||
(void)ini_close(&fp);
|
||||
return 1;
|
||||
}
|
||||
#endif /* INI_NOBROWSE */
|
||||
|
||||
#if ! defined INI_READONLY
|
||||
static void ini_tempname(TCHAR *dest, const TCHAR *source, int maxlength)
|
||||
{
|
||||
TCHAR *p;
|
||||
|
||||
save_strncpy(dest, source, maxlength, QUOTE_NONE);
|
||||
p = _tcsrchr(dest, '\0');
|
||||
assert(p != NULL);
|
||||
*(p - 1) = '~';
|
||||
}
|
||||
|
||||
static enum quote_option check_enquote(const TCHAR *Value)
|
||||
{
|
||||
const TCHAR *p;
|
||||
|
||||
/* run through the value, if it has trailing spaces, or '"', ';' or '#'
|
||||
* characters, enquote it
|
||||
*/
|
||||
assert(Value != NULL);
|
||||
for (p = Value; *p != '\0' && *p != '"' && *p != ';' && *p != '#'; p++)
|
||||
/* nothing */;
|
||||
return (*p != '\0' || (p > Value && *(p - 1) == ' ')) ? QUOTE_ENQUOTE : QUOTE_NONE;
|
||||
}
|
||||
|
||||
static void writesection(TCHAR *LocalBuffer, const TCHAR *Section, INI_FILETYPE *fp)
|
||||
{
|
||||
if (Section != NULL && _tcslen(Section) > 0) {
|
||||
TCHAR *p;
|
||||
LocalBuffer[0] = '[';
|
||||
save_strncpy(LocalBuffer + 1, Section, INI_BUFFERSIZE - 4, QUOTE_NONE); /* -1 for '[', -1 for ']', -2 for '\r\n' */
|
||||
p = _tcsrchr(LocalBuffer, '\0');
|
||||
assert(p != NULL);
|
||||
*p++ = ']';
|
||||
_tcscpy(p, INI_LINETERM); /* copy line terminator (typically "\n") */
|
||||
if (fp != NULL)
|
||||
(void)ini_write(LocalBuffer, fp);
|
||||
} /* if */
|
||||
}
|
||||
|
||||
static void writekey(TCHAR *LocalBuffer, const TCHAR *Key, const TCHAR *Value, INI_FILETYPE *fp)
|
||||
{
|
||||
TCHAR *p;
|
||||
enum quote_option option = check_enquote(Value);
|
||||
save_strncpy(LocalBuffer, Key, INI_BUFFERSIZE - 3, QUOTE_NONE); /* -1 for '=', -2 for '\r\n' */
|
||||
p = _tcsrchr(LocalBuffer, '\0');
|
||||
assert(p != NULL);
|
||||
*p++ = '=';
|
||||
save_strncpy(p, Value, INI_BUFFERSIZE - (p - LocalBuffer) - 2, option); /* -2 for '\r\n' */
|
||||
p = _tcsrchr(LocalBuffer, '\0');
|
||||
assert(p != NULL);
|
||||
_tcscpy(p, INI_LINETERM); /* copy line terminator (typically "\n") */
|
||||
if (fp != NULL)
|
||||
(void)ini_write(LocalBuffer, fp);
|
||||
}
|
||||
|
||||
static int cache_accum(const TCHAR *string, int *size, int max)
|
||||
{
|
||||
int len = (int)_tcslen(string);
|
||||
if (*size + len >= max)
|
||||
return 0;
|
||||
*size += len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cache_flush(TCHAR *buffer, int *size,
|
||||
INI_FILETYPE *rfp, INI_FILETYPE *wfp, INI_FILEPOS *mark)
|
||||
{
|
||||
int terminator_len = (int)_tcslen(INI_LINETERM);
|
||||
int pos = 0;
|
||||
|
||||
(void)ini_seek(rfp, mark);
|
||||
assert(buffer != NULL);
|
||||
buffer[0] = '\0';
|
||||
assert(size != NULL);
|
||||
assert(*size <= INI_BUFFERSIZE);
|
||||
while (pos < *size) {
|
||||
(void)ini_read(buffer + pos, INI_BUFFERSIZE - pos, rfp);
|
||||
while (pos < *size && buffer[pos] != '\0')
|
||||
pos++; /* cannot use _tcslen() because buffer may not be zero-terminated */
|
||||
} /* while */
|
||||
if (buffer[0] != '\0') {
|
||||
assert(pos > 0 && pos <= INI_BUFFERSIZE);
|
||||
if (pos == INI_BUFFERSIZE)
|
||||
pos--;
|
||||
buffer[pos] = '\0'; /* force zero-termination (may be left unterminated in the above while loop) */
|
||||
(void)ini_write(buffer, wfp);
|
||||
}
|
||||
ini_tell(rfp, mark); /* update mark */
|
||||
*size = 0;
|
||||
/* return whether the buffer ended with a line termination */
|
||||
return (pos > terminator_len) && (_tcscmp(buffer + pos - terminator_len, INI_LINETERM) == 0);
|
||||
}
|
||||
|
||||
static int close_rename(INI_FILETYPE *rfp, INI_FILETYPE *wfp, const TCHAR *filename, TCHAR *buffer)
|
||||
{
|
||||
(void)ini_close(rfp);
|
||||
(void)ini_close(wfp);
|
||||
(void)ini_remove(filename);
|
||||
(void)ini_tempname(buffer, filename, INI_BUFFERSIZE);
|
||||
(void)ini_rename(buffer, filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** ini_puts()
|
||||
* \param Section the name of the section to write the string in
|
||||
* \param Key the name of the entry to write, or NULL to erase all keys in the section
|
||||
* \param Value a pointer to the buffer the string, or NULL to erase the key
|
||||
* \param Filename the name and full path of the .ini file to write to
|
||||
*
|
||||
* \return 1 if successful, otherwise 0
|
||||
*/
|
||||
int ini_puts(const TCHAR *Section, const TCHAR *Key, const TCHAR *Value, const TCHAR *Filename)
|
||||
{
|
||||
INI_FILETYPE rfp;
|
||||
INI_FILETYPE wfp;
|
||||
INI_FILEPOS mark;
|
||||
INI_FILEPOS head, tail;
|
||||
TCHAR *sp, *ep;
|
||||
TCHAR LocalBuffer[INI_BUFFERSIZE];
|
||||
int len, match, flag, cachelen;
|
||||
|
||||
assert(Filename != NULL);
|
||||
if (!ini_openread(Filename, &rfp)) {
|
||||
/* If the .ini file doesn't exist, make a new file */
|
||||
if (Key != NULL && Value != NULL) {
|
||||
if (!ini_openwrite(Filename, &wfp))
|
||||
return 0;
|
||||
writesection(LocalBuffer, Section, &wfp);
|
||||
writekey(LocalBuffer, Key, Value, &wfp);
|
||||
(void)ini_close(&wfp);
|
||||
} /* if */
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
/* If parameters Key and Value are valid (so this is not an "erase" request)
|
||||
* and the setting already exists, there are two short-cuts to avoid rewriting
|
||||
* the INI file.
|
||||
*/
|
||||
if (Key != NULL && Value != NULL) {
|
||||
ini_tell(&rfp, &mark);
|
||||
match = getkeystring(&rfp, Section, Key, -1, -1, LocalBuffer, sizearray(LocalBuffer), &head);
|
||||
if (match) {
|
||||
/* if the current setting is identical to the one to write, there is
|
||||
* nothing to do.
|
||||
*/
|
||||
if (_tcscmp(LocalBuffer,Value) == 0) {
|
||||
(void)ini_close(&rfp);
|
||||
return 1;
|
||||
} /* if */
|
||||
/* if the new setting has the same length as the current setting, and the
|
||||
* glue file permits file read/write access, we can modify in place.
|
||||
*/
|
||||
#if defined ini_openrewrite
|
||||
/* we already have the start of the (raw) line, get the end too */
|
||||
ini_tell(&rfp, &tail);
|
||||
/* create new buffer (without writing it to file) */
|
||||
writekey(LocalBuffer, Key, Value, NULL);
|
||||
if (_tcslen(LocalBuffer) == (size_t)(tail - head)) {
|
||||
/* length matches, close the file & re-open for read/write, then
|
||||
* write at the correct position
|
||||
*/
|
||||
(void)ini_close(&rfp);
|
||||
if (!ini_openrewrite(Filename, &wfp))
|
||||
return 0;
|
||||
(void)ini_seek(&wfp, &head);
|
||||
(void)ini_write(LocalBuffer, &wfp);
|
||||
(void)ini_close(&wfp);
|
||||
return 1;
|
||||
} /* if */
|
||||
#endif
|
||||
} /* if */
|
||||
/* key not found, or different value & length -> proceed (but rewind the
|
||||
* input file first)
|
||||
*/
|
||||
(void)ini_seek(&rfp, &mark);
|
||||
} /* if */
|
||||
|
||||
/* Get a temporary file name to copy to. Use the existing name, but with
|
||||
* the last character set to a '~'.
|
||||
*/
|
||||
ini_tempname(LocalBuffer, Filename, INI_BUFFERSIZE);
|
||||
if (!ini_openwrite(LocalBuffer, &wfp)) {
|
||||
(void)ini_close(&rfp);
|
||||
return 0;
|
||||
} /* if */
|
||||
(void)ini_tell(&rfp, &mark);
|
||||
cachelen = 0;
|
||||
|
||||
/* Move through the file one line at a time until a section is
|
||||
* matched or until EOF. Copy to temp file as it is read.
|
||||
*/
|
||||
len = (Section != NULL) ? (int)_tcslen(Section) : 0;
|
||||
if (len > 0) {
|
||||
do {
|
||||
if (!ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp)) {
|
||||
/* Failed to find section, so add one to the end */
|
||||
flag = cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark);
|
||||
if (Key!=NULL && Value!=NULL) {
|
||||
if (!flag)
|
||||
(void)ini_write(INI_LINETERM, &wfp); /* force a new line behind the last line of the INI file */
|
||||
writesection(LocalBuffer, Section, &wfp);
|
||||
writekey(LocalBuffer, Key, Value, &wfp);
|
||||
} /* if */
|
||||
return close_rename(&rfp, &wfp, Filename, LocalBuffer); /* clean up and rename */
|
||||
} /* if */
|
||||
/* Copy the line from source to dest, but not if this is the section that
|
||||
* we are looking for and this section must be removed
|
||||
*/
|
||||
sp = skipleading(LocalBuffer);
|
||||
ep = _tcsrchr(sp, ']');
|
||||
match = (*sp == '[' && ep != NULL && (int)(ep-sp-1) == len && _tcsnicmp(sp + 1,Section,len) == 0);
|
||||
if (!match || Key != NULL) {
|
||||
if (!cache_accum(LocalBuffer, &cachelen, INI_BUFFERSIZE)) {
|
||||
cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark);
|
||||
(void)ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp);
|
||||
cache_accum(LocalBuffer, &cachelen, INI_BUFFERSIZE);
|
||||
} /* if */
|
||||
} /* if */
|
||||
} while (!match);
|
||||
} /* if */
|
||||
cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark);
|
||||
/* when deleting a section, the section head that was just found has not been
|
||||
* copied to the output file, but because this line was not "accumulated" in
|
||||
* the cache, the position in the input file was reset to the point just
|
||||
* before the section; this must now be skipped (again)
|
||||
*/
|
||||
if (Key == NULL) {
|
||||
(void)ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp);
|
||||
(void)ini_tell(&rfp, &mark);
|
||||
} /* if */
|
||||
|
||||
/* Now that the section has been found, find the entry. Stop searching
|
||||
* upon leaving the section's area. Copy the file as it is read
|
||||
* and create an entry if one is not found.
|
||||
*/
|
||||
len = (Key != NULL) ? (int)_tcslen(Key) : 0;
|
||||
for( ;; ) {
|
||||
if (!ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp)) {
|
||||
/* EOF without an entry so make one */
|
||||
flag = cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark);
|
||||
if (Key!=NULL && Value!=NULL) {
|
||||
if (!flag)
|
||||
(void)ini_write(INI_LINETERM, &wfp); /* force a new line behind the last line of the INI file */
|
||||
writekey(LocalBuffer, Key, Value, &wfp);
|
||||
} /* if */
|
||||
return close_rename(&rfp, &wfp, Filename, LocalBuffer); /* clean up and rename */
|
||||
} /* if */
|
||||
sp = skipleading(LocalBuffer);
|
||||
ep = _tcschr(sp, '='); /* Parse out the equal sign */
|
||||
if (ep == NULL)
|
||||
ep = _tcschr(sp, ':');
|
||||
match = (ep != NULL && len > 0 && (int)(skiptrailing(ep,sp)-sp) == len && _tcsnicmp(sp,Key,len) == 0);
|
||||
if ((Key != NULL && match) || *sp == '[')
|
||||
break; /* found the key, or found a new section */
|
||||
/* copy other keys in the section */
|
||||
if (Key == NULL) {
|
||||
(void)ini_tell(&rfp, &mark); /* we are deleting the entire section, so update the read position */
|
||||
} else {
|
||||
if (!cache_accum(LocalBuffer, &cachelen, INI_BUFFERSIZE)) {
|
||||
cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark);
|
||||
(void)ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp);
|
||||
cache_accum(LocalBuffer, &cachelen, INI_BUFFERSIZE);
|
||||
} /* if */
|
||||
} /* if */
|
||||
} /* for */
|
||||
/* the key was found, or we just dropped on the next section (meaning that it
|
||||
* wasn't found); in both cases we need to write the key, but in the latter
|
||||
* case, we also need to write the line starting the new section after writing
|
||||
* the key
|
||||
*/
|
||||
flag = (*sp == '[');
|
||||
cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark);
|
||||
if (Key != NULL && Value != NULL)
|
||||
writekey(LocalBuffer, Key, Value, &wfp);
|
||||
/* cache_flush() reset the "read pointer" to the start of the line with the
|
||||
* previous key or the new section; read it again (because writekey() destroyed
|
||||
* the buffer)
|
||||
*/
|
||||
(void)ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp);
|
||||
if (flag) {
|
||||
/* the new section heading needs to be copied to the output file */
|
||||
cache_accum(LocalBuffer, &cachelen, INI_BUFFERSIZE);
|
||||
} else {
|
||||
/* forget the old key line */
|
||||
(void)ini_tell(&rfp, &mark);
|
||||
} /* if */
|
||||
/* Copy the rest of the INI file */
|
||||
while (ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp)) {
|
||||
if (!cache_accum(LocalBuffer, &cachelen, INI_BUFFERSIZE)) {
|
||||
cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark);
|
||||
(void)ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp);
|
||||
cache_accum(LocalBuffer, &cachelen, INI_BUFFERSIZE);
|
||||
} /* if */
|
||||
} /* while */
|
||||
cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark);
|
||||
return close_rename(&rfp, &wfp, Filename, LocalBuffer); /* clean up and rename */
|
||||
}
|
||||
|
||||
/* Ansi C "itoa" based on Kernighan & Ritchie's "Ansi C" book. */
|
||||
#define ABS(v) ((v) < 0 ? -(v) : (v))
|
||||
|
||||
static void strreverse(TCHAR *str)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0, j = (int)_tcslen(str) - 1; i < j; i++, j--) {
|
||||
TCHAR t = str[i];
|
||||
str[i] = str[j];
|
||||
str[j] = t;
|
||||
} /* for */
|
||||
}
|
||||
|
||||
static void long2str(long value, TCHAR *str)
|
||||
{
|
||||
int i = 0;
|
||||
long sign = value;
|
||||
|
||||
/* generate digits in reverse order */
|
||||
do {
|
||||
int n = (int)(value % 10); /* get next lowest digit */
|
||||
str[i++] = (TCHAR)(ABS(n) + '0'); /* handle case of negative digit */
|
||||
} while (value /= 10); /* delete the lowest digit */
|
||||
if (sign < 0)
|
||||
str[i++] = '-';
|
||||
str[i] = '\0';
|
||||
|
||||
strreverse(str);
|
||||
}
|
||||
|
||||
/** ini_putl()
|
||||
* \param Section the name of the section to write the value in
|
||||
* \param Key the name of the entry to write
|
||||
* \param Value the value to write
|
||||
* \param Filename the name and full path of the .ini file to write to
|
||||
*
|
||||
* \return 1 if successful, otherwise 0
|
||||
*/
|
||||
int ini_putl(const TCHAR *Section, const TCHAR *Key, long Value, const TCHAR *Filename)
|
||||
{
|
||||
TCHAR LocalBuffer[32];
|
||||
long2str(Value, LocalBuffer);
|
||||
return ini_puts(Section, Key, LocalBuffer, Filename);
|
||||
}
|
||||
|
||||
#if defined INI_REAL
|
||||
/** ini_putf()
|
||||
* \param Section the name of the section to write the value in
|
||||
* \param Key the name of the entry to write
|
||||
* \param Value the value to write
|
||||
* \param Filename the name and full path of the .ini file to write to
|
||||
*
|
||||
* \return 1 if successful, otherwise 0
|
||||
*/
|
||||
int ini_putf(const TCHAR *Section, const TCHAR *Key, INI_REAL Value, const TCHAR *Filename)
|
||||
{
|
||||
TCHAR LocalBuffer[64];
|
||||
ini_ftoa(LocalBuffer, Value);
|
||||
return ini_puts(Section, Key, LocalBuffer, Filename);
|
||||
}
|
||||
#endif /* INI_REAL */
|
||||
#endif /* !INI_READONLY */
|
@ -1,152 +0,0 @@
|
||||
/* minIni - Multi-Platform INI file parser, suitable for embedded systems
|
||||
*
|
||||
* Copyright (c) CompuPhase, 2008-2012
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Version: $Id: minIni.h 5181 2015-01-21 09:44:28Z thiadmer $
|
||||
*/
|
||||
#ifndef MININI_H
|
||||
#define MININI_H
|
||||
|
||||
#include "minGlue.h"
|
||||
|
||||
#if (defined _UNICODE || defined __UNICODE__ || defined UNICODE) && !defined INI_ANSIONLY
|
||||
#include <tchar.h>
|
||||
#define mTCHAR TCHAR
|
||||
#else
|
||||
/* force TCHAR to be "char", but only for minIni */
|
||||
#define mTCHAR char
|
||||
#endif
|
||||
|
||||
#if !defined INI_BUFFERSIZE
|
||||
#define INI_BUFFERSIZE 512
|
||||
#endif
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int ini_getbool(const mTCHAR *Section, const mTCHAR *Key, int DefValue, const mTCHAR *Filename);
|
||||
long ini_getl(const mTCHAR *Section, const mTCHAR *Key, long DefValue, const mTCHAR *Filename);
|
||||
int ini_gets(const mTCHAR *Section, const mTCHAR *Key, const mTCHAR *DefValue, mTCHAR *Buffer, int BufferSize, const mTCHAR *Filename);
|
||||
int ini_getsection(int idx, mTCHAR *Buffer, int BufferSize, const mTCHAR *Filename);
|
||||
int ini_getkey(const mTCHAR *Section, int idx, mTCHAR *Buffer, int BufferSize, const mTCHAR *Filename);
|
||||
|
||||
#if defined INI_REAL
|
||||
INI_REAL ini_getf(const mTCHAR *Section, const mTCHAR *Key, INI_REAL DefValue, const mTCHAR *Filename);
|
||||
#endif
|
||||
|
||||
#if !defined INI_READONLY
|
||||
int ini_putl(const mTCHAR *Section, const mTCHAR *Key, long Value, const mTCHAR *Filename);
|
||||
int ini_puts(const mTCHAR *Section, const mTCHAR *Key, const mTCHAR *Value, const mTCHAR *Filename);
|
||||
#if defined INI_REAL
|
||||
int ini_putf(const mTCHAR *Section, const mTCHAR *Key, INI_REAL Value, const mTCHAR *Filename);
|
||||
#endif
|
||||
#endif /* INI_READONLY */
|
||||
|
||||
#if !defined INI_NOBROWSE
|
||||
typedef int (*INI_CALLBACK)(const mTCHAR *Section, const mTCHAR *Key, const mTCHAR *Value, const void *UserData);
|
||||
int ini_browse(INI_CALLBACK Callback, const void *UserData, const mTCHAR *Filename);
|
||||
#endif /* INI_NOBROWSE */
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined __cplusplus
|
||||
|
||||
#if defined __WXWINDOWS__
|
||||
#include "wxMinIni.h"
|
||||
#else
|
||||
#include <string>
|
||||
|
||||
/* The C++ class in minIni.h was contributed by Steven Van Ingelgem. */
|
||||
class minIni
|
||||
{
|
||||
public:
|
||||
minIni(const std::string& filename) : iniFilename(filename)
|
||||
{ }
|
||||
|
||||
bool getbool(const std::string& Section, const std::string& Key, bool DefValue=false) const
|
||||
{ return ini_getbool(Section.c_str(), Key.c_str(), int(DefValue), iniFilename.c_str()) != 0; }
|
||||
|
||||
long getl(const std::string& Section, const std::string& Key, long DefValue=0) const
|
||||
{ return ini_getl(Section.c_str(), Key.c_str(), DefValue, iniFilename.c_str()); }
|
||||
|
||||
int geti(const std::string& Section, const std::string& Key, int DefValue=0) const
|
||||
{ return static_cast<int>(this->getl(Section, Key, long(DefValue))); }
|
||||
|
||||
std::string gets(const std::string& Section, const std::string& Key, const std::string& DefValue="") const
|
||||
{
|
||||
char buffer[INI_BUFFERSIZE];
|
||||
ini_gets(Section.c_str(), Key.c_str(), DefValue.c_str(), buffer, INI_BUFFERSIZE, iniFilename.c_str());
|
||||
return buffer;
|
||||
}
|
||||
|
||||
std::string getsection(int idx) const
|
||||
{
|
||||
char buffer[INI_BUFFERSIZE];
|
||||
ini_getsection(idx, buffer, INI_BUFFERSIZE, iniFilename.c_str());
|
||||
return buffer;
|
||||
}
|
||||
|
||||
std::string getkey(const std::string& Section, int idx) const
|
||||
{
|
||||
char buffer[INI_BUFFERSIZE];
|
||||
ini_getkey(Section.c_str(), idx, buffer, INI_BUFFERSIZE, iniFilename.c_str());
|
||||
return buffer;
|
||||
}
|
||||
|
||||
#if defined INI_REAL
|
||||
INI_REAL getf(const std::string& Section, const std::string& Key, INI_REAL DefValue=0) const
|
||||
{ return ini_getf(Section.c_str(), Key.c_str(), DefValue, iniFilename.c_str()); }
|
||||
#endif
|
||||
|
||||
#if ! defined INI_READONLY
|
||||
bool put(const std::string& Section, const std::string& Key, long Value) const
|
||||
{ return ini_putl(Section.c_str(), Key.c_str(), Value, iniFilename.c_str()) != 0; }
|
||||
|
||||
bool put(const std::string& Section, const std::string& Key, int Value) const
|
||||
{ return ini_putl(Section.c_str(), Key.c_str(), (long)Value, iniFilename.c_str()) != 0; }
|
||||
|
||||
bool put(const std::string& Section, const std::string& Key, bool Value) const
|
||||
{ return ini_putl(Section.c_str(), Key.c_str(), (long)Value, iniFilename.c_str()) != 0; }
|
||||
|
||||
bool put(const std::string& Section, const std::string& Key, const std::string& Value) const
|
||||
{ return ini_puts(Section.c_str(), Key.c_str(), Value.c_str(), iniFilename.c_str()) != 0; }
|
||||
|
||||
bool put(const std::string& Section, const std::string& Key, const char* Value) const
|
||||
{ return ini_puts(Section.c_str(), Key.c_str(), Value, iniFilename.c_str()) != 0; }
|
||||
|
||||
#if defined INI_REAL
|
||||
bool put(const std::string& Section, const std::string& Key, INI_REAL Value) const
|
||||
{ return ini_putf(Section.c_str(), Key.c_str(), Value, iniFilename.c_str()) != 0; }
|
||||
#endif
|
||||
|
||||
bool del(const std::string& Section, const std::string& Key) const
|
||||
{ return ini_puts(Section.c_str(), Key.c_str(), 0, iniFilename.c_str()) != 0; }
|
||||
|
||||
bool del(const std::string& Section) const
|
||||
{ return ini_puts(Section.c_str(), 0, 0, iniFilename.c_str()) != 0; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
std::string iniFilename;
|
||||
};
|
||||
|
||||
#endif /* __WXWINDOWS__ */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* MININI_H */
|
Loading…
x
Reference in New Issue
Block a user