forked from mirror/openmw-tes3mp
Remove Pawn support
parent
bef53749ed
commit
685a80887b
@ -1,458 +0,0 @@
|
||||
//
|
||||
// Created by koncord on 08.05.16.
|
||||
//
|
||||
|
||||
#include "LangPAWN.hpp"
|
||||
|
||||
|
||||
#include <amxmodules.h>
|
||||
#include <amxaux.h>
|
||||
#include "Script.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
typedef long NetworkID;
|
||||
|
||||
static vector<vector<char>> strings;
|
||||
static vector<pair<cell*, double>> floats;
|
||||
static pair<cell*, NetworkID*> data = {nullptr, nullptr};
|
||||
|
||||
void free_strings() noexcept {
|
||||
strings.clear();
|
||||
}
|
||||
|
||||
void free_floats() noexcept {
|
||||
for (const auto& value : floats)
|
||||
*value.first = amx_ftoc(value.second);
|
||||
|
||||
floats.clear();
|
||||
}
|
||||
|
||||
void free_data(unsigned int size) noexcept {
|
||||
if (data.first && data.second)
|
||||
for (unsigned int i = 0; i < size; ++i)
|
||||
data.first[i] = data.second[i];
|
||||
|
||||
data.first = nullptr;
|
||||
data.second = nullptr;
|
||||
}
|
||||
|
||||
void after_call() noexcept {
|
||||
free_strings();
|
||||
free_floats();
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
void after_call(const R&) noexcept {
|
||||
free_strings();
|
||||
free_floats();
|
||||
}
|
||||
|
||||
template<>
|
||||
void after_call(const unsigned int& result) noexcept {
|
||||
free_strings();
|
||||
free_floats();
|
||||
free_data(result);
|
||||
}
|
||||
|
||||
template<typename R, unsigned int I, unsigned int F>
|
||||
struct PAWN_extract_ {
|
||||
inline static R PAWN_extract(AMX*&&, const cell*&& params) noexcept {
|
||||
return static_cast<R>(forward<const cell*>(params)[I]);
|
||||
}
|
||||
};
|
||||
|
||||
template<unsigned int I, unsigned int F>
|
||||
struct PAWN_extract_<void*, I, F>
|
||||
{
|
||||
inline static void* PAWN_extract(AMX *&&amx, const cell *&¶ms) noexcept
|
||||
{
|
||||
return amx_Address(amx, forward<const cell *>(params)[I]); // fixme: I'm not sure in this fix
|
||||
}
|
||||
};
|
||||
|
||||
template<unsigned int I, unsigned int F>
|
||||
struct PAWN_extract_<double, I, F> {
|
||||
inline static double PAWN_extract(AMX*&&, const cell*&& params) noexcept {
|
||||
return amx_ctof(forward<const cell*>(params)[I]);
|
||||
}
|
||||
};
|
||||
|
||||
template<unsigned int I, unsigned int F>
|
||||
struct PAWN_extract_<const char*, I, F> {
|
||||
inline static const char* PAWN_extract(AMX*&& amx, const cell*&& params) noexcept {
|
||||
int len;
|
||||
cell* source;
|
||||
|
||||
source = amx_Address(amx, params[I]);
|
||||
amx_StrLen(source, &len);
|
||||
|
||||
strings.emplace_back(len + 1);
|
||||
char* value = &strings.back()[0];
|
||||
amx_GetString(value, source, 0, UNLIMITED);
|
||||
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
template<unsigned int I, unsigned int F>
|
||||
struct PAWN_extract_<double*, I, F> {
|
||||
inline static double* PAWN_extract(AMX*&& amx, const cell*&& params) noexcept {
|
||||
floats.emplace_back(amx_Address(amx, params[I]), 0.00);
|
||||
return &floats.back().second;
|
||||
}
|
||||
};
|
||||
|
||||
template<unsigned int I, unsigned int F>
|
||||
struct PAWN_extract_<NetworkID**, I, F> {
|
||||
inline static NetworkID** PAWN_extract(AMX*&& amx, const cell*&& params) noexcept {
|
||||
constexpr ScriptFunctionData const& F_ = ScriptFunctions::functions[F];
|
||||
static_assert(F_.func.numargs == I, "NetworkID** must be the last parameter");
|
||||
data.first = amx_Address(amx, params[I]);
|
||||
return &data.second;
|
||||
}
|
||||
};
|
||||
|
||||
template<unsigned int I, unsigned int F>
|
||||
struct PAWN_dispatch_ {
|
||||
template<typename R, typename... Args>
|
||||
inline static R PAWN_dispatch(AMX*&& amx, const cell*&& params, Args&&... args) noexcept {
|
||||
constexpr ScriptFunctionData const& F_ = ScriptFunctions::functions[F];
|
||||
auto arg = PAWN_extract_<typename CharType<F_.func.types[I - 1]>::type, I, F>::PAWN_extract(forward<AMX*>(amx), forward<const cell*>(params));
|
||||
return PAWN_dispatch_<I - 1, F>::template PAWN_dispatch<R>(
|
||||
forward<AMX*>(amx),
|
||||
forward<const cell*>(params),
|
||||
arg,
|
||||
forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template<unsigned int F>
|
||||
struct PAWN_dispatch_<0, F> {
|
||||
template<typename R, typename... Args>
|
||||
inline static R PAWN_dispatch(AMX*&&, const cell*&&, Args&&... args) noexcept {
|
||||
constexpr ScriptFunctionData const& F_ = ScriptFunctions::functions[F];
|
||||
return reinterpret_cast<FunctionEllipsis<R>>(F_.func.addr)(forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template<unsigned int I>
|
||||
static typename enable_if<ScriptFunctions::functions[I].func.ret == 'v', cell>::type wrapper(AMX* amx, const cell* params) noexcept {
|
||||
PAWN_dispatch_<ScriptFunctions::functions[I].func.numargs, I>::template PAWN_dispatch<void>(forward<AMX*>(amx), forward<const cell*>(params));
|
||||
after_call();
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<unsigned int I>
|
||||
static typename enable_if<ScriptFunctions::functions[I].func.ret == 'f', cell>::type wrapper(AMX* amx, const cell* params) noexcept {
|
||||
double value = PAWN_dispatch_<ScriptFunctions::functions[I].func.numargs, I>::template PAWN_dispatch<double>(forward<AMX*>(amx), forward<const cell*>(params));
|
||||
after_call();
|
||||
return amx_ftoc(value);
|
||||
}
|
||||
|
||||
template<unsigned int I>
|
||||
static typename enable_if<ScriptFunctions::functions[I].func.ret == 's', cell>::type wrapper(AMX* amx, const cell* params) noexcept {
|
||||
const char* value = PAWN_dispatch_<ScriptFunctions::functions[I].func.numargs, I>::template PAWN_dispatch<const char*>(forward<AMX*>(amx), forward<const cell*>(params));
|
||||
after_call();
|
||||
|
||||
if (value) {
|
||||
cell* dest = amx_Address(amx, params[ScriptFunctions::functions[I].func.numargs + 1]);
|
||||
amx_SetString(dest, value, 1, 0, strlen(value) + 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<unsigned int I>
|
||||
static typename enable_if<ScriptFunctions::functions[I].func.ret != 'v' && ScriptFunctions::functions[I].func.ret != 'f' && ScriptFunctions::functions[I].func.ret != 's', cell>::type wrapper(AMX* amx, const cell* params) noexcept {
|
||||
auto result = PAWN_dispatch_<ScriptFunctions::functions[I].func.numargs, I>::template PAWN_dispatch<typename CharType<ScriptFunctions::functions[I].func.ret>::type>(forward<AMX*>(amx), forward<const cell*>(params));
|
||||
after_call(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<unsigned int I> struct F_ { static constexpr AMX_NATIVE_INFO F{ScriptFunctions::functions[I].name, wrapper<I>}; };
|
||||
template<> struct F_<0> { static constexpr AMX_NATIVE_INFO F{"CreateTimer", LangPAWN::CreateTimer}; };
|
||||
template<> struct F_<1> { static constexpr AMX_NATIVE_INFO F{"CreateTimerEx", LangPAWN::CreateTimerEx}; };
|
||||
template<> struct F_<2> { static constexpr AMX_NATIVE_INFO F{"MakePublic", LangPAWN::MakePublic}; };
|
||||
template<> struct F_<3> { static constexpr AMX_NATIVE_INFO F{"CallPublic", LangPAWN::CallPublic}; };
|
||||
|
||||
void LangPAWN::LoadProgram(const char *filename)
|
||||
{
|
||||
int err = aux_LoadProgram(amx, filename, 0);
|
||||
if (err != AMX_ERR_NONE)
|
||||
throw runtime_error("PAWN script " + string(filename) + " error (" + to_string(err) + "): \"" + string(aux_StrError(err)) + "\"");
|
||||
|
||||
amx_CoreInit(amx);
|
||||
amx_ConsoleInit(amx);
|
||||
amx_FloatInit(amx);
|
||||
amx_TimeInit(amx);
|
||||
amx_StringInit(amx);
|
||||
amx_FileInit(amx);
|
||||
|
||||
constexpr auto functions_n = sizeof(ScriptFunctions::functions) / sizeof(ScriptFunctions::functions[0]);
|
||||
|
||||
amx_Register(amx, functions(IndicesFor<functions_n>{}), functions_n); // TODO: throw if error
|
||||
|
||||
}
|
||||
|
||||
int LangPAWN::FreeProgram()
|
||||
{
|
||||
int err = aux_FreeProgram(amx);
|
||||
delete amx;
|
||||
return err;
|
||||
}
|
||||
|
||||
bool LangPAWN::IsCallbackPresent(const char *name)
|
||||
{
|
||||
int idx;
|
||||
return (amx_FindPublic(amx, name, &idx) == AMX_ERR_NONE);
|
||||
}
|
||||
|
||||
boost::any LangPAWN::Call(const char *name, const char *argl, int buf, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, buf);
|
||||
cell ret = 0;
|
||||
vector<pair<cell *, char *>> strings;
|
||||
|
||||
try
|
||||
{
|
||||
int idx = 0;
|
||||
int err = 0;
|
||||
|
||||
err = amx_FindPublic(amx, name, &idx);
|
||||
|
||||
if (err != AMX_ERR_NONE)
|
||||
throw runtime_error("PAWN runtime error (" + to_string(err) + "): \"" + string(aux_StrError(err)) + "\".");
|
||||
|
||||
unsigned int len = strlen(argl);
|
||||
vector<cell> args_amx;
|
||||
|
||||
for (unsigned int i = 0; i < len; ++i)
|
||||
{
|
||||
switch (argl[i])
|
||||
{
|
||||
case 'i':
|
||||
args_amx.emplace_back(va_arg(args, unsigned
|
||||
int));
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
args_amx.emplace_back(va_arg(args, signed
|
||||
int));
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
args_amx.emplace_back(va_arg(args, unsigned
|
||||
long
|
||||
long));
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
args_amx.emplace_back(va_arg(args, signed
|
||||
long
|
||||
long));
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
{
|
||||
double value = va_arg(args, double);
|
||||
args_amx.emplace_back(amx_ftoc(value));
|
||||
break;
|
||||
}
|
||||
|
||||
case 'p':
|
||||
args_amx.emplace_back(reinterpret_cast<uintptr_t>(va_arg(args, void*)));
|
||||
break;
|
||||
|
||||
case 's':
|
||||
args_amx.emplace_back(reinterpret_cast<uintptr_t>(va_arg(args, char*)));
|
||||
break;
|
||||
|
||||
default:
|
||||
throw runtime_error("PAWN call: Unknown argument identifier " + argl[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int i = len; i; --i)
|
||||
{
|
||||
switch (argl[i - 1])
|
||||
{
|
||||
case 's':
|
||||
{
|
||||
char *string = reinterpret_cast<char *>(static_cast<unsigned int>(args_amx[i - 1]));
|
||||
cell *store;
|
||||
amx_PushString(amx, &store, string, 1, 0);
|
||||
strings.emplace_back(store, string);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
amx_Push(amx, args_amx[i - 1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
err = amx_Exec(amx, &ret, idx);
|
||||
|
||||
if (err != AMX_ERR_NONE)
|
||||
throw runtime_error("PAWN runtime error (" + to_string(err) + "): \"" + string(aux_StrError(err)) + "\".");
|
||||
|
||||
if (buf != 0)
|
||||
for (const auto &str : strings)
|
||||
amx_GetString(str.second, str.first, 0, strlen(str.second) + 1);
|
||||
|
||||
if (!strings.empty())
|
||||
amx_Release(amx, strings[0].first);
|
||||
}
|
||||
|
||||
catch (...)
|
||||
{
|
||||
va_end(args);
|
||||
|
||||
if (!strings.empty())
|
||||
amx_Release(amx, strings[0].first);
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
return boost::any(ret);
|
||||
}
|
||||
|
||||
boost::any LangPAWN::Call(const char *name, const char *argl, const std::vector<boost::any> &args)
|
||||
{
|
||||
cell ret = 0;
|
||||
cell *str = nullptr;
|
||||
|
||||
try
|
||||
{
|
||||
int idx = 0;
|
||||
int err = 0;
|
||||
|
||||
err = amx_FindPublic(amx, name, &idx);
|
||||
|
||||
if (err != AMX_ERR_NONE)
|
||||
throw runtime_error("PAWN runtime error (" + to_string(err) + "): \"" + string(aux_StrError(err)) + "\".");
|
||||
|
||||
for (intptr_t i = strlen(argl) - 1; i >= 0; i--)
|
||||
{
|
||||
switch (argl[i])
|
||||
{
|
||||
case 'i':
|
||||
{
|
||||
cell value = (cell) boost::any_cast<unsigned int>(args.at(i));
|
||||
amx_Push(amx, value);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'q':
|
||||
{
|
||||
cell value = (cell) boost::any_cast<signed int>(args.at(i));
|
||||
amx_Push(amx, value);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'l':
|
||||
{
|
||||
cell value = (cell) boost::any_cast<unsigned long long>(args.at(i));
|
||||
amx_Push(amx, value);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'w':
|
||||
{
|
||||
cell value = (cell) boost::any_cast<signed long long>(args.at(i));
|
||||
amx_Push(amx, value);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'f':
|
||||
{
|
||||
double value = boost::any_cast<double>(args.at(i));
|
||||
amx_Push(amx, amx_ftoc(value));
|
||||
break;
|
||||
}
|
||||
|
||||
case 'p':
|
||||
{
|
||||
cell value = (cell) boost::any_cast<void *>(args.at(i));
|
||||
amx_Push(amx, value);
|
||||
break;
|
||||
}
|
||||
|
||||
case 's':
|
||||
{
|
||||
string string_ = boost::any_cast<string>(args.at(i));
|
||||
cell *store;
|
||||
amx_PushString(amx, &store, string_.c_str(), 1, 0);
|
||||
|
||||
if (!str)
|
||||
str = store;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw runtime_error("PAWN call: Unknown argument identifier " + argl[i]);
|
||||
}
|
||||
}
|
||||
|
||||
err = amx_Exec(amx, &ret, idx);
|
||||
|
||||
if (err != AMX_ERR_NONE)
|
||||
throw runtime_error("PAWN runtime error (" + to_string(err) + "): \"" + string(aux_StrError(err)) + "\".");
|
||||
|
||||
if (str)
|
||||
amx_Release(amx, str);
|
||||
}
|
||||
|
||||
catch (...)
|
||||
{
|
||||
if (str)
|
||||
amx_Release(amx, str);
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<size_t... Indices>
|
||||
inline AMX_NATIVE_INFO *LangPAWN::functions(indices<Indices...>)
|
||||
{
|
||||
|
||||
static AMX_NATIVE_INFO functions_[sizeof...(Indices)]{
|
||||
F_<Indices>::F...
|
||||
};
|
||||
|
||||
static_assert(
|
||||
sizeof(functions_) / sizeof(functions_[0]) == sizeof(ScriptFunctions::functions) / sizeof(ScriptFunctions::functions[0]),
|
||||
"Not all functions have been mapped to PAWN");
|
||||
|
||||
return functions_;
|
||||
}
|
||||
|
||||
|
||||
lib_t LangPAWN::GetInterface()
|
||||
{
|
||||
return reinterpret_cast<lib_t>(amx);
|
||||
}
|
||||
|
||||
LangPAWN::LangPAWN()
|
||||
{
|
||||
//throw std::runtime_error("Pawn is no longer supported, use Terra/Lua!");
|
||||
amx = new AMX();
|
||||
}
|
||||
|
||||
|
||||
LangPAWN::LangPAWN(AMX *amx)
|
||||
{
|
||||
this->amx = amx;
|
||||
}
|
||||
|
||||
|
||||
LangPAWN::~LangPAWN()
|
||||
{
|
||||
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
//
|
||||
// Created by koncord on 08.05.16.
|
||||
//
|
||||
|
||||
#ifndef PLUGINSYSTEM3_LANGPAWN_HPP
|
||||
#define PLUGINSYSTEM3_LANGPAWN_HPP
|
||||
|
||||
#include "Language.hpp"
|
||||
#include <amx.h>
|
||||
|
||||
class LangPAWN: public Language
|
||||
{
|
||||
private:
|
||||
template<std::size_t... Is>
|
||||
struct indices {};
|
||||
template<std::size_t N, std::size_t... Is>
|
||||
struct build_indices : build_indices<N-1, N-1, Is...> {};
|
||||
template<std::size_t... Is>
|
||||
struct build_indices<0, Is...> : indices<Is...> {};
|
||||
template<std::size_t N>
|
||||
using IndicesFor = build_indices<N>;
|
||||
|
||||
public:
|
||||
virtual lib_t GetInterface() override;
|
||||
template<std::size_t... Indices>
|
||||
static AMX_NATIVE_INFO* functions(indices<Indices...>);
|
||||
|
||||
AMX *amx;
|
||||
public:
|
||||
LangPAWN();
|
||||
LangPAWN(AMX *amx);
|
||||
~LangPAWN();
|
||||
static cell MakePublic(AMX *amx, const cell *params) noexcept;
|
||||
static cell CallPublic(AMX *amx, const cell *params) noexcept;
|
||||
static cell CreateTimer(AMX *amx, const cell *params) noexcept;
|
||||
static cell CreateTimerEx(AMX *amx, const cell *params) noexcept;
|
||||
|
||||
virtual void LoadProgram(const char *filename) override;
|
||||
virtual int FreeProgram() override;
|
||||
virtual bool IsCallbackPresent(const char *name) override;
|
||||
virtual boost::any Call(const char *name, const char *argl, int buf, ...) override;
|
||||
virtual boost::any Call(const char *name, const char *argl, const std::vector<boost::any> &args) override;
|
||||
};
|
||||
|
||||
|
||||
#endif //PLUGINSYSTEM3_LANGPAWN_HPP
|
@ -1,154 +0,0 @@
|
||||
//
|
||||
// Created by koncord on 09.05.16.
|
||||
//
|
||||
|
||||
#include <API/PublicFnAPI.hpp>
|
||||
#include "LangPAWN.hpp"
|
||||
#include "API/TimerAPI.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
cell LangPAWN::MakePublic(AMX *amx, const cell *params) noexcept
|
||||
{
|
||||
int len;
|
||||
cell* source;
|
||||
|
||||
source = amx_Address(amx, params[1]);
|
||||
amx_StrLen(source, &len);
|
||||
vector<char> real;
|
||||
real.reserve(len + 1);
|
||||
|
||||
amx_GetString(&real[0], source, 0, UNLIMITED);
|
||||
|
||||
source = amx_Address(amx, params[2]);
|
||||
amx_StrLen(source, &len);
|
||||
vector<char> name;
|
||||
name.reserve(len + 1);
|
||||
|
||||
amx_GetString(&name[0], source, 0, UNLIMITED);
|
||||
|
||||
cell *ret_addr = amx_Address(amx, params[3]);
|
||||
char ret_type = static_cast<char>(*reinterpret_cast<cell*>(&ret_addr));
|
||||
|
||||
source = amx_Address(amx, params[4]);
|
||||
amx_StrLen(source, &len);
|
||||
vector<char> def;
|
||||
def.reserve(len + 1);
|
||||
|
||||
amx_GetString(&def[0], source, 0, UNLIMITED);
|
||||
|
||||
|
||||
|
||||
Public::MakePublic(&real[0], amx, &name[0], ret_type, &def[0]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
cell LangPAWN::CallPublic(AMX *amx, const cell *params) noexcept
|
||||
{
|
||||
int len;
|
||||
cell* source;
|
||||
|
||||
source = amx_Address(amx, params[1]);
|
||||
amx_StrLen(source, &len);
|
||||
vector<char> name;
|
||||
name.reserve(len + 1);
|
||||
|
||||
amx_GetString(&name[0], source, 0, UNLIMITED);
|
||||
|
||||
string def;
|
||||
|
||||
try
|
||||
{
|
||||
def = Public::GetDefinition(&name[0]);
|
||||
}
|
||||
catch (...) { return 0; }
|
||||
|
||||
vector<boost::any> args;
|
||||
unsigned int count = (params[0] / sizeof(cell)) - 1;
|
||||
|
||||
if (count != def.length())
|
||||
throw runtime_error("Script call: Number of arguments does not match definition");
|
||||
|
||||
for (unsigned int i = 0; i < count; ++i)
|
||||
{
|
||||
cell* data = amx_Address(amx, params[i + 2]);
|
||||
|
||||
switch (def[i])
|
||||
{
|
||||
case 'i':
|
||||
{
|
||||
args.emplace_back((unsigned int) *data);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'q':
|
||||
{
|
||||
args.emplace_back((signed int) *data);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'l':
|
||||
{
|
||||
args.emplace_back((unsigned long long) *data);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'w':
|
||||
{
|
||||
args.emplace_back((signed long long) *data);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'f':
|
||||
{
|
||||
args.emplace_back((double) amx_ctof(*data));
|
||||
break;
|
||||
}
|
||||
|
||||
case 'p':
|
||||
{
|
||||
args.emplace_back((void*) data);
|
||||
break;
|
||||
}
|
||||
|
||||
case 's':
|
||||
{
|
||||
amx_StrLen(data, &len);
|
||||
vector<char> str;
|
||||
str.reserve(len + 1);
|
||||
amx_GetString(&str[0], data, 0, UNLIMITED);
|
||||
args.emplace_back(string(&str[0]).c_str());
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw runtime_error("PAWN call: Unknown argument identifier " + def[i]);
|
||||
}
|
||||
}
|
||||
|
||||
boost::any result = Public::Call(&name[0], args);
|
||||
if (result.empty())
|
||||
return 0;
|
||||
|
||||
cell ret = 0;
|
||||
|
||||
if (result.type().hash_code() == typeid(signed int).hash_code())
|
||||
ret = boost::any_cast<signed int>(result);
|
||||
else if (result.type().hash_code() == typeid(unsigned int).hash_code())
|
||||
ret = boost::any_cast<unsigned int>(result);
|
||||
else if (result.type().hash_code() == typeid(double).hash_code())
|
||||
ret = amx_ftoc(result);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
cell LangPAWN::CreateTimer(AMX *amx, const cell *params) noexcept
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
cell LangPAWN::CreateTimerEx(AMX *amx, const cell *params) noexcept
|
||||
{
|
||||
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
include_directories(./linux)
|
||||
|
||||
add_definitions(-DPAWN_CELL_SIZE=64)
|
||||
|
||||
set(source_amx
|
||||
amxexec_gcc.c
|
||||
amxfile.c
|
||||
fpattern.c
|
||||
minIni.c
|
||||
amxcons.c
|
||||
amxcore.c
|
||||
amxstring.c
|
||||
amxtime.c
|
||||
amxfloat.c
|
||||
amxaux.c
|
||||
amx.c
|
||||
linux/binreloc.c
|
||||
linux/getch.c
|
||||
)
|
||||
|
||||
source_group(amx FILES ${source_amx})
|
||||
|
||||
add_library(amx STATIC ${source_amx} )
|
File diff suppressed because it is too large
Load Diff
@ -1,545 +0,0 @@
|
||||
/* Pawn Abstract Machine (for the Pawn language)
|
||||
*
|
||||
* Copyright (c) ITB CompuPhase, 1997-2015
|
||||
*
|
||||
* 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: amx.h 5181 2015-01-21 09:44:28Z thiadmer $
|
||||
*/
|
||||
|
||||
#ifndef AMX_H_INCLUDED
|
||||
#define AMX_H_INCLUDED
|
||||
|
||||
#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__
|
||||
#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;
|
||||
#else
|
||||
typedef int32_t intptr_t;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#if defined _LP64 || defined WIN64 || defined _WIN64
|
||||
#if !defined __64BIT__
|
||||
#define __64BIT__
|
||||
#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
|
||||
#include <alloca.h>
|
||||
#elif defined __BORLANDC__
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32 /* || defined __MSDOS__ */
|
||||
#if !defined alloca
|
||||
#define alloca(n) _alloca(n)
|
||||
#endif
|
||||
#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
|
||||
#endif
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined PAWN_DLL
|
||||
#if !defined AMX_NATIVE_CALL
|
||||
#define AMX_NATIVE_CALL __stdcall
|
||||
#endif
|
||||
#if !defined AMXAPI
|
||||
#define AMXAPI __stdcall
|
||||
#endif
|
||||
#if !defined AMXEXPORT
|
||||
#define AMXEXPORT __declspec(dllexport)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* calling convention for native functions */
|
||||
#if !defined AMX_NATIVE_CALL
|
||||
#define AMX_NATIVE_CALL
|
||||
#endif
|
||||
/* calling convention for all interface functions and callback functions */
|
||||
#if !defined AMXAPI
|
||||
#if defined STDECL
|
||||
#define AMXAPI __stdcall
|
||||
#elif defined CDECL
|
||||
#define AMXAPI __cdecl
|
||||
#elif defined GCC_HASCLASSVISIBILITY
|
||||
#define AMXAPI __attribute__((visibility("default")))
|
||||
#else
|
||||
#define AMXAPI
|
||||
#endif
|
||||
#endif
|
||||
#if !defined AMXEXPORT
|
||||
#define AMXEXPORT
|
||||
#endif
|
||||
|
||||
/* File format version (in CUR_FILE_VERSION)
|
||||
* 0 original version
|
||||
* 1 opcodes JUMP.pri, SWITCH and CASETBL
|
||||
* 2 compressed files
|
||||
* 3 public variables
|
||||
* 4 opcodes SWAP.pri/alt and PUSHADDR
|
||||
* 5 tagnames table
|
||||
* 6 reformatted header
|
||||
* 7 name table, opcodes SYMTAG & SYSREQ.D
|
||||
* 8 opcode BREAK, renewed debug interface
|
||||
* 9 macro opcodes
|
||||
* 10 position-independent code, overlays, packed instructions
|
||||
* 11 relocating instructions for the native interface, reorganized instruction set
|
||||
* MIN_FILE_VERSION is the lowest file version number that the current AMX
|
||||
* implementation supports. If the AMX file header gets new fields, this number
|
||||
* often needs to be incremented. MIN_AMX_VERSION is the lowest AMX version that
|
||||
* is needed to support the current file version. When there are new opcodes,
|
||||
* this number needs to be incremented.
|
||||
* The file version supported by the JIT may run behind MIN_AMX_VERSION. So
|
||||
* there is an extra constant for it: MAX_FILE_VER_JIT.
|
||||
*/
|
||||
|
||||
#define CUR_FILE_VERSION 11 /* current file version; also the current AMX version */
|
||||
#define MIN_FILE_VERSION 11 /* lowest supported file format version for the current AMX version */
|
||||
#define MIN_AMX_VERSION 11 /* minimum AMX version needed to support the current file format */
|
||||
#define MAX_FILE_VER_JIT 11 /* file version supported by the JIT */
|
||||
#define MIN_AMX_VER_JIT 11 /* AMX version supported by the JIT */
|
||||
|
||||
#if !defined PAWN_CELL_SIZE
|
||||
#define PAWN_CELL_SIZE 32 /* by default, use 32-bit cells */
|
||||
#endif
|
||||
#if PAWN_CELL_SIZE==16
|
||||
typedef uint16_t ucell;
|
||||
typedef int16_t cell;
|
||||
#elif PAWN_CELL_SIZE==32
|
||||
typedef uint32_t ucell;
|
||||
typedef int32_t cell;
|
||||
#elif PAWN_CELL_SIZE==64
|
||||
typedef uint64_t ucell;
|
||||
typedef int64_t cell;
|
||||
#define HAVE_I64
|
||||
#else
|
||||
#error Unsupported cell size (PAWN_CELL_SIZE)
|
||||
#endif
|
||||
|
||||
#define UNPACKEDMAX (((cell)1 << (sizeof(cell)-1)*8) - 1)
|
||||
#define UNLIMITED (~1u >> 1)
|
||||
|
||||
struct tagAMX;
|
||||
typedef cell (AMX_NATIVE_CALL *AMX_NATIVE)(struct tagAMX *amx, const cell *params);
|
||||
typedef int (AMXAPI *AMX_CALLBACK)(struct tagAMX *amx, cell index,
|
||||
cell *result, const cell *params);
|
||||
typedef int (AMXAPI *AMX_DEBUG)(struct tagAMX *amx);
|
||||
typedef int (AMXAPI *AMX_OVERLAY)(struct tagAMX *amx, int index);
|
||||
typedef int (AMXAPI *AMX_IDLE)(struct tagAMX *amx, int AMXAPI Exec(struct tagAMX *, cell *, int));
|
||||
#if !defined _FAR
|
||||
#define _FAR
|
||||
#endif
|
||||
|
||||
#if defined _MSC_VER
|
||||
#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 */
|
||||
#endif
|
||||
|
||||
/* Some compilers do not support the #pragma align, which should be fine. Some
|
||||
* compilers give a warning on unknown #pragmas, which is not so fine...
|
||||
*/
|
||||
#if (defined SN_TARGET_PS2 || defined __GNUC__) && !defined AMX_NO_ALIGN
|
||||
#define AMX_NO_ALIGN
|
||||
#endif
|
||||
|
||||
#if defined __GNUC__
|
||||
#define PACKED __attribute__((packed))
|
||||
#else
|
||||
#define PACKED
|
||||
#endif
|
||||
|
||||
#if !defined AMX_NO_ALIGN
|
||||
#if defined __LINUX__ || defined __FreeBSD__ || defined __APPLE__
|
||||
#pragma pack(1) /* structures must be packed (byte-aligned) */
|
||||
#elif defined MACOS && defined __MWERKS__
|
||||
#pragma options align=mac68k
|
||||
#else
|
||||
#pragma pack(push)
|
||||
#pragma pack(1) /* structures must be packed (byte-aligned) */
|
||||
#if defined __TURBOC__
|
||||
#pragma option -a- /* "pack" pragma for older Borland compilers */
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef struct tagAMX_NATIVE_INFO {
|
||||
const char _FAR *name;
|
||||
AMX_NATIVE func;
|
||||
} PACKED AMX_NATIVE_INFO;
|
||||
|
||||
#if !defined AMX_USERNUM
|
||||
#define AMX_USERNUM 4
|
||||
#endif
|
||||
#define sEXPMAX 19 /* maximum name length for file version <= 6 */
|
||||
#define sNAMEMAX 31 /* maximum name length of symbol name */
|
||||
|
||||
typedef struct tagFUNCSTUB {
|
||||
uint32_t address;
|
||||
uint32_t nameofs;
|
||||
} PACKED AMX_FUNCSTUB;
|
||||
|
||||
typedef struct tagOVERLAYINFO {
|
||||
int32_t offset; /* offset relative to the start of the code block */
|
||||
int32_t size; /* size in bytes */
|
||||
} PACKED AMX_OVERLAYINFO;
|
||||
|
||||
/* The AMX structure is the internal structure for many functions. Not all
|
||||
* fields are valid at all times; many fields are cached in local variables.
|
||||
*/
|
||||
typedef struct tagAMX {
|
||||
unsigned char _FAR *base; /* points to the AMX header, perhaps followed by P-code and data */
|
||||
unsigned char _FAR *code; /* points to P-code block, possibly in ROM or in an overlay pool */
|
||||
unsigned char _FAR *data; /* points to separate data+stack+heap, may be NULL */
|
||||
AMX_CALLBACK callback; /* native function callback */
|
||||
AMX_DEBUG debug; /* debug callback */
|
||||
AMX_OVERLAY overlay; /* overlay reader callback */
|
||||
/* for external functions a few registers must be accessible from the outside */
|
||||
cell cip; /* instruction pointer: relative to base + amxhdr->cod */
|
||||
cell frm; /* stack frame base: relative to base + amxhdr->dat */
|
||||
cell hea; /* top of the heap: relative to base + amxhdr->dat */
|
||||
cell hlw; /* bottom of the heap: relative to base + amxhdr->dat */
|
||||
cell stk; /* stack pointer: relative to base + amxhdr->dat */
|
||||
cell stp; /* top of the stack: relative to base + amxhdr->dat */
|
||||
int flags; /* current status, see amx_Flags() */
|
||||
/* user data */
|
||||
#if AMX_USERNUM > 0
|
||||
long usertags[AMX_USERNUM];
|
||||
void _FAR *userdata[AMX_USERNUM];
|
||||
#endif
|
||||
/* native functions can raise an error */
|
||||
int error;
|
||||
/* passing parameters requires a "count" field */
|
||||
int paramcount;
|
||||
/* the sleep opcode needs to store the full AMX status */
|
||||
cell pri;
|
||||
cell alt;
|
||||
cell reset_stk;
|
||||
cell reset_hea;
|
||||
/* extra fields for increased performance */
|
||||
cell sysreq_d; /* relocated address/value for the SYSREQ.D opcode */
|
||||
/* fields for overlay support and JIT support */
|
||||
int ovl_index; /* current overlay index */
|
||||
long codesize; /* size of the overlay, or estimated memory footprint of the native code */
|
||||
#if defined AMX_JIT
|
||||
/* support variables for the JIT */
|
||||
int reloc_size; /* required temporary buffer for relocations */
|
||||
#endif
|
||||
} PACKED AMX;
|
||||
|
||||
/* The AMX_HEADER structure is both the memory format as the file format. The
|
||||
* structure is used internaly.
|
||||
*/
|
||||
typedef struct tagAMX_HEADER {
|
||||
int32_t size; /* size of the "file" */
|
||||
uint16_t magic; /* signature */
|
||||
char file_version; /* file format version */
|
||||
char amx_version; /* required version of the AMX */
|
||||
int16_t flags;
|
||||
int16_t defsize; /* size of a definition record */
|
||||
int32_t cod; /* initial value of COD - code block */
|
||||
int32_t dat; /* initial value of DAT - data block */
|
||||
int32_t hea; /* initial value of HEA - start of the heap */
|
||||
int32_t stp; /* initial value of STP - stack top */
|
||||
int32_t cip; /* initial value of CIP - the instruction pointer */
|
||||
int32_t publics; /* offset to the "public functions" table */
|
||||
int32_t natives; /* offset to the "native functions" table */
|
||||
int32_t libraries; /* offset to the table of libraries */
|
||||
int32_t pubvars; /* offset to the "public variables" table */
|
||||
int32_t tags; /* offset to the "public tagnames" table */
|
||||
int32_t nametable; /* offset to the name table */
|
||||
int32_t overlays; /* offset to the overlay table */
|
||||
} PACKED 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
|
||||
#elif PAWN_CELL_SIZE==32
|
||||
#define AMX_MAGIC AMX_MAGIC_32
|
||||
#elif PAWN_CELL_SIZE==64
|
||||
#define AMX_MAGIC AMX_MAGIC_64
|
||||
#endif
|
||||
|
||||
enum {
|
||||
AMX_ERR_NONE,
|
||||
/* reserve the first 15 error codes for exit codes of the abstract machine */
|
||||
AMX_ERR_EXIT, /* forced exit */
|
||||
AMX_ERR_ASSERT, /* assertion failed */
|
||||
AMX_ERR_STACKERR, /* stack/heap collision */
|
||||
AMX_ERR_BOUNDS, /* index out of bounds */
|
||||
AMX_ERR_MEMACCESS, /* invalid memory access */
|
||||
AMX_ERR_INVINSTR, /* invalid instruction */
|
||||
AMX_ERR_STACKLOW, /* stack underflow */
|
||||
AMX_ERR_HEAPLOW, /* heap underflow */
|
||||
AMX_ERR_CALLBACK, /* no callback, or invalid callback */
|
||||
AMX_ERR_NATIVE, /* native function failed */
|
||||
AMX_ERR_DIVIDE, /* divide by zero */
|
||||
AMX_ERR_SLEEP, /* go into sleepmode - code can be restarted */
|
||||
AMX_ERR_INVSTATE, /* no implementation for this state, no fall-back */
|
||||
|
||||
AMX_ERR_MEMORY = 16, /* out of memory */
|
||||
AMX_ERR_FORMAT, /* invalid file format */
|
||||
AMX_ERR_VERSION, /* file is for a newer version of the AMX */
|
||||
AMX_ERR_NOTFOUND, /* function not found */
|
||||
AMX_ERR_INDEX, /* invalid index parameter (bad entry point) */
|
||||
AMX_ERR_DEBUG, /* debugger cannot run */
|
||||
AMX_ERR_INIT, /* AMX not initialized (or doubly initialized) */
|
||||
AMX_ERR_USERDATA, /* unable to set user data field (table full) */
|
||||
AMX_ERR_INIT_JIT, /* cannot initialize the JIT */
|
||||
AMX_ERR_PARAMS, /* parameter error */
|
||||
AMX_ERR_DOMAIN, /* domain error, expression result does not fit in range */
|
||||
AMX_ERR_GENERAL, /* general error (unknown or unspecific error) */
|
||||
AMX_ERR_OVERLAY, /* overlays are unsupported (JIT) or uninitialized */
|
||||
};
|
||||
|
||||
#define AMX_FLAG_OVERLAY 0x01 /* all function calls use overlays */
|
||||
#define AMX_FLAG_DEBUG 0x02 /* symbolic info. available */
|
||||
#define AMX_FLAG_NOCHECKS 0x04 /* no array bounds checking; no BREAK opcodes */
|
||||
#define AMX_FLAG_SLEEP 0x08 /* script uses the sleep instruction (possible re-entry or power-down mode) */
|
||||
#define AMX_FLAG_CRYPT 0x10 /* file is encrypted */
|
||||
#define AMX_FLAG_DSEG_INIT 0x20 /* data section is explicitly initialized */
|
||||
#define AMX_FLAG_SYSREQN 0x800 /* script uses new (optimized) version of SYSREQ opcode */
|
||||
#define AMX_FLAG_NTVREG 0x1000 /* all native functions are registered */
|
||||
#define AMX_FLAG_JITC 0x2000 /* abstract machine is JIT compiled */
|
||||
#define AMX_FLAG_VERIFY 0x4000 /* busy verifying P-code */
|
||||
#define AMX_FLAG_INIT 0x8000 /* AMX has been initialized */
|
||||
|
||||
#define AMX_EXEC_MAIN (-1) /* start at program entry point */
|
||||
#define AMX_EXEC_CONT (-2) /* continue from last address */
|
||||
|
||||
#define AMX_USERTAG(a,b,c,d) ((a) | ((b)<<8) | ((long)(c)<<16) | ((long)(d)<<24))
|
||||
|
||||
/* for native functions that use floating point parameters, the following
|
||||
* two macros are convenient for casting a "cell" into a "float" type _without_
|
||||
* changing the bit pattern
|
||||
*/
|
||||
#if PAWN_CELL_SIZE==32
|
||||
#define amx_ftoc(f) ( * ((cell*)&f) ) /* float to cell */
|
||||
#define amx_ctof(c) ( * ((float*)&c) ) /* cell to float */
|
||||
#elif PAWN_CELL_SIZE==64
|
||||
#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
|
||||
#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) ((void)(amx),(cell*)(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) \
|
||||
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); \
|
||||
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);
|
||||
#if defined _I64_MAX || defined INT64_MAX || defined HAVE_I64
|
||||
uint64_t * AMXAPI amx_Align64(uint64_t *v);
|
||||
#endif
|
||||
int AMXAPI amx_Allot(AMX *amx, int cells, cell **address);
|
||||
int AMXAPI amx_Callback(AMX *amx, cell index, cell *result, const cell *params);
|
||||
int AMXAPI amx_Cleanup(AMX *amx);
|
||||
int AMXAPI amx_Clone(AMX *amxClone, AMX *amxSource, void *data);
|
||||
int AMXAPI amx_Exec(AMX *amx, cell *retval, int index);
|
||||
int AMXAPI amx_FindNative(AMX *amx, const char *name, int *index);
|
||||
int AMXAPI amx_FindPublic(AMX *amx, const char *name, int *index);
|
||||
int AMXAPI amx_FindPubVar(AMX *amx, const char *name, cell **address);
|
||||
int AMXAPI amx_FindTagId(AMX *amx, cell tag_id, char *tagname);
|
||||
int AMXAPI amx_Flags(AMX *amx,uint16_t *flags);
|
||||
int AMXAPI amx_GetNative(AMX *amx, int index, char *name);
|
||||
int AMXAPI amx_GetPublic(AMX *amx, int index, char *name, ucell *address);
|
||||
int AMXAPI amx_GetPubVar(AMX *amx, int index, char *name, cell **address);
|
||||
int AMXAPI amx_GetString(char *dest,const cell *source, int use_wchar, size_t size);
|
||||
int AMXAPI amx_GetTag(AMX *amx, int index, char *tagname, cell *tag_id);
|
||||
int AMXAPI amx_GetUserData(AMX *amx, long tag, void **ptr);
|
||||
int AMXAPI amx_Init(AMX *amx, void *program);
|
||||
int AMXAPI amx_InitJIT(AMX *amx, void *reloc_table, void *native_code);
|
||||
int AMXAPI amx_MemInfo(AMX *amx, long *codesize, long *datasize, long *stackheap);
|
||||
int AMXAPI amx_NameLength(AMX *amx, int *length);
|
||||
AMX_NATIVE_INFO * AMXAPI amx_NativeInfo(const char *name, AMX_NATIVE func);
|
||||
int AMXAPI amx_NumNatives(AMX *amx, int *number);
|
||||
int AMXAPI amx_NumPublics(AMX *amx, int *number);
|
||||
int AMXAPI amx_NumPubVars(AMX *amx, int *number);
|
||||
int AMXAPI amx_NumTags(AMX *amx, int *number);
|
||||
int AMXAPI amx_Push(AMX *amx, cell value);
|
||||
int AMXAPI amx_PushAddress(AMX *amx, cell *address);
|
||||
int AMXAPI amx_PushArray(AMX *amx, cell **address, const cell array[], int numcells);
|
||||
int AMXAPI amx_PushString(AMX *amx, cell **address, const char *string, int pack, int use_wchar);
|
||||
int AMXAPI amx_RaiseError(AMX *amx, int error);
|
||||
int AMXAPI amx_Register(AMX *amx, const AMX_NATIVE_INFO *nativelist, int number);
|
||||
int AMXAPI amx_Release(AMX *amx, cell *address);
|
||||
int AMXAPI amx_SetCallback(AMX *amx, AMX_CALLBACK callback);
|
||||
int AMXAPI amx_SetDebugHook(AMX *amx, AMX_DEBUG debug);
|
||||
int AMXAPI amx_SetString(cell *dest, const char *source, int pack, int use_wchar, size_t size);
|
||||
int AMXAPI amx_SetUserData(AMX *amx, long tag, void *ptr);
|
||||
int AMXAPI amx_StrLen(const cell *cstring, int *length);
|
||||
int AMXAPI amx_UTF8Check(const char *string, int *length);
|
||||
int AMXAPI amx_UTF8Get(const char *string, const char **endptr, cell *value);
|
||||
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))
|
||||
#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))
|
||||
#else
|
||||
#error Unsupported cell size
|
||||
#endif
|
||||
|
||||
#define amx_RegisterFunc(amx, name, func) \
|
||||
amx_Register((amx), amx_NativeInfo((name),(func)), 1);
|
||||
|
||||
#if !defined AMX_NO_ALIGN
|
||||
#if defined __LINUX__ || defined __FreeBSD__ || defined __APPLE__
|
||||
#pragma pack() /* reset default packing */
|
||||
#elif defined MACOS && defined __MWERKS__
|
||||
#pragma options align=reset
|
||||
#else
|
||||
#pragma pack(pop) /* reset previous packing */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AMX_H_INCLUDED */
|
@ -1,164 +0,0 @@
|
||||
/* Support routines for the Pawn Abstract Machine
|
||||
*
|
||||
* Copyright (c) ITB CompuPhase, 2003-2011
|
||||
*
|
||||
* 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: amxaux.c 4523 2011-06-21 15:03:47Z thiadmer $
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "amx.h"
|
||||
#include "amxaux.h"
|
||||
|
||||
size_t AMXAPI aux_ProgramSize(const char *filename)
|
||||
{
|
||||
FILE *fp;
|
||||
AMX_HEADER hdr;
|
||||
|
||||
if ((fp=fopen(filename,"rb")) == NULL)
|
||||
return 0;
|
||||
fread(&hdr, sizeof hdr, 1, fp);
|
||||
fclose(fp);
|
||||
|
||||
amx_Align16(&hdr.magic);
|
||||
amx_Align32((uint32_t *)&hdr.stp);
|
||||
return (hdr.magic==AMX_MAGIC) ? (size_t)hdr.stp : 0;
|
||||
}
|
||||
|
||||
int AMXAPI aux_LoadProgram(AMX *amx, const char *filename, void *memblock)
|
||||
{
|
||||
FILE *fp;
|
||||
AMX_HEADER hdr;
|
||||
int result, didalloc;
|
||||
|
||||
/* open the file, read and check the header */
|
||||
if ((fp = fopen(filename, "rb")) == NULL)
|
||||
return AMX_ERR_NOTFOUND;
|
||||
fread(&hdr, sizeof hdr, 1, fp);
|
||||
amx_Align16(&hdr.magic);
|
||||
amx_Align32((uint32_t *)&hdr.size);
|
||||
amx_Align32((uint32_t *)&hdr.stp);
|
||||
if (hdr.magic != AMX_MAGIC) {
|
||||
fclose(fp);
|
||||
return AMX_ERR_FORMAT;
|
||||
} /* if */
|
||||
|
||||
/* allocate the memblock if it is NULL */
|
||||
didalloc = 0;
|
||||
if (memblock == NULL) {
|
||||
if ((memblock = malloc(hdr.stp)) == NULL) {
|
||||
fclose(fp);
|
||||
return AMX_ERR_MEMORY;
|
||||
} /* if */
|
||||
didalloc = 1;
|
||||
/* after amx_Init(), amx->base points to the memory block */
|
||||
} /* if */
|
||||
|
||||
/* read in the file */
|
||||
rewind(fp);
|
||||
fread(memblock, 1, (size_t)hdr.size, fp);
|
||||
fclose(fp);
|
||||
|
||||
/* initialize the abstract machine */
|
||||
memset(amx, 0, sizeof *amx);
|
||||
result = amx_Init(amx, memblock);
|
||||
|
||||
/* free the memory block on error, if it was allocated here */
|
||||
if (result != AMX_ERR_NONE && didalloc) {
|
||||
free(memblock);
|
||||
amx->base = NULL; /* avoid a double free */
|
||||
} /* if */
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int AMXAPI aux_FreeProgram(AMX *amx)
|
||||
{
|
||||
if (amx->base!=NULL) {
|
||||
amx_Cleanup(amx);
|
||||
free(amx->base);
|
||||
memset(amx, 0, sizeof(AMX));
|
||||
} /* if */
|
||||
return AMX_ERR_NONE;
|
||||
}
|
||||
|
||||
char * AMXAPI aux_StrError(int errnum)
|
||||
{
|
||||
static char *messages[] = {
|
||||
/* AMX_ERR_NONE */ "(none)",
|
||||
/* AMX_ERR_EXIT */ "Forced exit",
|
||||
/* AMX_ERR_ASSERT */ "Assertion failed",
|
||||
/* AMX_ERR_STACKERR */ "Stack/heap collision (insufficient stack size)",
|
||||
/* AMX_ERR_BOUNDS */ "Array index out of bounds",
|
||||
/* AMX_ERR_MEMACCESS */ "Invalid memory access",
|
||||
/* AMX_ERR_INVINSTR */ "Invalid instruction",
|
||||
/* AMX_ERR_STACKLOW */ "Stack underflow",
|
||||
/* AMX_ERR_HEAPLOW */ "Heap underflow",
|
||||
/* AMX_ERR_CALLBACK */ "No (valid) native function callback",
|
||||
/* AMX_ERR_NATIVE */ "Native function failed",
|
||||
/* AMX_ERR_DIVIDE */ "Divide by zero",
|
||||
/* AMX_ERR_SLEEP */ "(sleep mode)",
|
||||
/* AMX_ERR_INVSTATE */ "Invalid state",
|
||||
/* 14 */ "(reserved)",
|
||||
/* 15 */ "(reserved)",
|
||||
/* AMX_ERR_MEMORY */ "Out of memory",
|
||||
/* AMX_ERR_FORMAT */ "Invalid/unsupported P-code file format",
|
||||
/* AMX_ERR_VERSION */ "File is for a newer version of the AMX",
|
||||
/* AMX_ERR_NOTFOUND */ "File or function is not found",
|
||||
/* AMX_ERR_INDEX */ "Invalid index parameter (bad entry point)",
|
||||
/* AMX_ERR_DEBUG */ "Debugger cannot run",
|
||||
/* AMX_ERR_INIT */ "AMX not initialized (or doubly initialized)",
|
||||
/* AMX_ERR_USERDATA */ "Unable to set user data field (table full)",
|
||||
/* AMX_ERR_INIT_JIT */ "Cannot initialize the JIT",
|
||||
/* AMX_ERR_PARAMS */ "Parameter error",
|
||||
/* AMX_ERR_DOMAIN */ "Domain error, expression result does not fit in range",
|
||||
/* AMX_ERR_GENERAL */ "General error (unknown or unspecific error)",
|
||||
/* AMX_ERR_OVERLAY */ "Overlays are unsupported (JIT) or uninitialized",
|
||||
};
|
||||
if (errnum < 0 || errnum >= sizeof messages / sizeof messages[0])
|
||||
return "(unknown)";
|
||||
return messages[errnum];
|
||||
}
|
||||
|
||||
int AMXAPI aux_GetSection(const AMX *amx, int section, cell **start, size_t *size)
|
||||
{
|
||||
AMX_HEADER *hdr;
|
||||
|
||||
if (amx == NULL || start == NULL || size == NULL)
|
||||
return AMX_ERR_PARAMS;
|
||||
|
||||
hdr = (AMX_HEADER*)amx->base;
|
||||
switch(section) {
|
||||
case CODE_SECTION:
|
||||
*start = (cell *)(amx->base + hdr->cod);
|
||||
*size = hdr->dat - hdr->cod;
|
||||
break;
|
||||
case DATA_SECTION:
|
||||
*start = (cell *)(amx->data);
|
||||
*size = hdr->hea - hdr->dat;
|
||||
break;
|
||||
case HEAP_SECTION:
|
||||
*start = (cell *)(amx->data + hdr->hea);
|
||||
*size = amx->hea - hdr->hea;
|
||||
break;
|
||||
case STACK_SECTION:
|
||||
*start = (cell *)(amx->data + amx->stk);
|
||||
*size = amx->stp - amx->stk;
|
||||
break;
|
||||
default:
|
||||
return AMX_ERR_PARAMS;
|
||||
} /* switch */
|
||||
return AMX_ERR_NONE;
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
/* Support routines for the Pawn Abstract Machine
|
||||
*
|
||||
* Copyright (c) ITB CompuPhase, 2003-2011
|
||||
*
|
||||
* 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: amxaux.h 4523 2011-06-21 15:03:47Z thiadmer $
|
||||
*/
|
||||
#ifndef AMXAUX_H_INCLUDED
|
||||
#define AMXAUX_H_INCLUDED
|
||||
|
||||
#include "amx.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* loading and freeing programs */
|
||||
size_t AMXAPI aux_ProgramSize(const char *filename);
|
||||
int AMXAPI aux_LoadProgram(AMX *amx, const char *filename, void *memblock);
|
||||
int AMXAPI aux_FreeProgram(AMX *amx);
|
||||
|
||||
/* a readable error message from an error code */
|
||||
char * AMXAPI aux_StrError(int errnum);
|
||||
|
||||
enum {
|
||||
CODE_SECTION,
|
||||
DATA_SECTION,
|
||||
HEAP_SECTION,
|
||||
STACK_SECTION,
|
||||
/* ----- */
|
||||
NUM_SECTIONS
|
||||
};
|
||||
int AMXAPI aux_GetSection(const AMX *amx, int section, cell **start, size_t *size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AMXAUX_H_INCLUDED */
|
File diff suppressed because it is too large
Load Diff
@ -1,18 +0,0 @@
|
||||
#ifndef AMXCONS_H_INCLUDED
|
||||
#ifndef AMXCONS_H_INCLUDED
|
||||
#define AMXCONS_H_INCLUDED
|
||||
|
||||
typedef struct tagFMTINFO {
|
||||
const cell *params;
|
||||
int numparams;
|
||||
int skip; /* number of characters to skip from the beginning */
|
||||
int length; /* number of characters to print */
|
||||
/* helper functions */
|
||||
int (*f_putstr)(void *dest,const TCHAR *);
|
||||
int (*f_putchar)(void *dest,TCHAR);
|
||||
void *user; /* user data */
|
||||
} AMX_FMTINFO;
|
||||
|
||||
int amx_printstring(AMX *amx,cell *cstr,AMX_FMTINFO *info);
|
||||
|
||||
#endif /* AMXCONS_H_INCLUDED */
|
@ -1,500 +0,0 @@
|
||||
/* Core module for the Pawn AMX
|
||||
*
|
||||
* Copyright (c) ITB CompuPhase, 1997-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: amxcore.c 4708 2012-05-18 12:52:49Z $
|
||||
*/
|
||||
#if defined _UNICODE || defined __UNICODE__ || defined UNICODE
|
||||
# if !defined UNICODE /* for Windows */
|
||||
# define UNICODE
|
||||
# endif
|
||||
# if !defined _UNICODE /* for C library */
|
||||
# define _UNICODE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#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
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32 || defined _Windows
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
/* A few compilers do not provide the ANSI C standard "time" functions */
|
||||
#if !defined SN_TARGET_PS2 && !defined _WIN32_WCE && !defined __ICC430__
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#if defined _UNICODE
|
||||
# include <tchar.h>
|
||||
#elif !defined __T
|
||||
typedef char TCHAR;
|
||||
# define __T(string) string
|
||||
# define _tcschr strchr
|
||||
# define _tcscpy strcpy
|
||||
# define _tcsdup strdup
|
||||
# define _tcslen strlen
|
||||
#endif
|
||||
|
||||
|
||||
#define CHARBITS (8*sizeof(char))
|
||||
typedef unsigned char uchar;
|
||||
|
||||
#if !defined AMX_NOPROPLIST
|
||||
typedef struct _property_list {
|
||||
struct _property_list *next;
|
||||
cell id;
|
||||
char *name;
|
||||
cell value;
|
||||
} proplist;
|
||||
|
||||
static proplist proproot = { NULL, 0, NULL, 0 };
|
||||
|
||||
static proplist *list_additem(proplist *root)
|
||||
{
|
||||
proplist *item;
|
||||
|
||||
assert(root!=NULL);
|
||||
if ((item=(proplist *)malloc(sizeof(proplist)))==NULL)
|
||||
return NULL;
|
||||
item->name=NULL;
|
||||
item->id=0;
|
||||
item->value=0;
|
||||
item->next=root->next;
|
||||
root->next=item;
|
||||
return item;
|
||||
}
|
||||
static void list_delete(proplist *pred,proplist *item)
|
||||
{
|
||||
assert(pred!=NULL);
|
||||
assert(item!=NULL);
|
||||
pred->next=item->next;
|
||||
assert(item->name!=NULL);
|
||||
free(item->name);
|
||||
free(item);
|
||||
}
|
||||
static void list_setitem(proplist *item,cell id,char *name,cell value)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
assert(item!=NULL);
|
||||
if ((ptr=(char *)malloc(strlen(name)+1))==NULL)
|
||||
return;
|
||||
if (item->name!=NULL)
|
||||
free(item->name);
|
||||
strcpy(ptr,name);
|
||||
item->name=ptr;
|
||||
item->id=id;
|
||||
item->value=value;
|
||||
}
|
||||
static proplist *list_finditem(proplist *root,cell id,char *name,cell value,
|
||||
proplist **pred)
|
||||
{
|
||||
proplist *item=root->next;
|
||||
proplist *prev=root;
|
||||
|
||||
/* check whether to find by name or by value */
|
||||
assert(name!=NULL);
|
||||
if (strlen(name)>0) {
|
||||
/* find by name */
|
||||
while (item!=NULL && (item->id!=id || stricmp(item->name,name)!=0)) {
|
||||
prev=item;
|
||||
item=item->next;
|
||||
} /* while */
|
||||
} else {
|
||||
/* find by value */
|
||||
while (item!=NULL && (item->id!=id || item->value!=value)) {
|
||||
prev=item;
|
||||
item=item->next;
|
||||
} /* while */
|
||||
} /* if */
|
||||
if (pred!=NULL)
|
||||
*pred=prev;
|
||||
return item;
|
||||
}
|
||||
#endif
|
||||
|
||||
static cell AMX_NATIVE_CALL numargs(AMX *amx,const cell *params)
|
||||
{
|
||||
AMX_HEADER *hdr;
|
||||
uchar *data;
|
||||
cell bytes;
|
||||
|
||||
(void)params;
|
||||
hdr=(AMX_HEADER *)amx->base;
|
||||
data=amx->data ? amx->data : amx->base+(int)hdr->dat;
|
||||
/* the number of bytes is on the stack, at "frm + 2*cell" */
|
||||
bytes= * (cell *)(data+(int)amx->frm+2*sizeof(cell));
|
||||
/* the number of arguments is the number of bytes divided
|
||||
* by the size of a cell */
|
||||
return bytes/sizeof(cell);
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL getarg(AMX *amx,const cell *params)
|
||||
{
|
||||
AMX_HEADER *hdr;
|
||||
uchar *data;
|
||||
cell value;
|
||||
|
||||
hdr=(AMX_HEADER *)amx->base;
|
||||
data=amx->data ? amx->data : amx->base+(int)hdr->dat;
|
||||
/* get the base value */
|
||||
value= * (cell *)(data+(int)amx->frm+((int)params[1]+3)*sizeof(cell));
|
||||
/* adjust the address in "value" in case of an array access */
|
||||
value+=params[2]*sizeof(cell);
|
||||
/* get the value indirectly */
|
||||
value= * (cell *)(data+(int)value);
|
||||
return value;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL setarg(AMX *amx,const cell *params)
|
||||
{
|
||||
AMX_HEADER *hdr;
|
||||
uchar *data;
|
||||
cell value;
|
||||
|
||||
hdr=(AMX_HEADER *)amx->base;
|
||||
data=amx->data ? amx->data : amx->base+(int)hdr->dat;
|
||||
/* get the base value */
|
||||
value= * (cell *)(data+(int)amx->frm+((int)params[1]+3)*sizeof(cell));
|
||||
/* adjust the address in "value" in case of an array access */
|
||||
value+=params[2]*sizeof(cell);
|
||||
/* verify the address */
|
||||
if (value<0 || value>=amx->hea && value<amx->stk)
|
||||
return 0;
|
||||
/* set the value indirectly */
|
||||
* (cell *)(data+(int)value) = params[3];
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL heapspace(AMX *amx,const cell *params)
|
||||
{
|
||||
(void)params;
|
||||
return amx->stk - amx->hea;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL funcidx(AMX *amx,const cell *params)
|
||||
{
|
||||
char name[64];
|
||||
cell *cstr;
|
||||
int index,err;
|
||||
|
||||
cstr=amx_Address(amx,params[1]);
|
||||
amx_GetString(name,cstr,0,sizeof name);
|
||||
err=amx_FindPublic(amx,name,&index);
|
||||
if (err!=AMX_ERR_NONE)
|
||||
index=-1; /* this is not considered a fatal error */
|
||||
return index;
|
||||
}
|
||||
|
||||
void amx_swapcell(cell *pc)
|
||||
{
|
||||
union {
|
||||
cell c;
|
||||
#if PAWN_CELL_SIZE==16
|
||||
uchar b[2];
|
||||
#elif PAWN_CELL_SIZE==32
|
||||
uchar b[4];
|
||||
#elif PAWN_CELL_SIZE==64
|
||||
uchar b[8];
|
||||
#else
|
||||
#error Unsupported cell size
|
||||
#endif
|
||||
} value;
|
||||
uchar t;
|
||||
|
||||
assert(pc!=NULL);
|
||||
value.c = *pc;
|
||||
#if PAWN_CELL_SIZE==16
|
||||
t = value.b[0];
|
||||
value.b[0] = value.b[1];
|
||||
value.b[1] = t;
|
||||
#elif PAWN_CELL_SIZE==32
|
||||
t = value.b[0];
|
||||
value.b[0] = value.b[3];
|
||||
value.b[3] = t;
|
||||
t = value.b[1];
|
||||
value.b[1] = value.b[2];
|
||||
value.b[2] = t;
|
||||
#elif PAWN_CELL_SIZE==64
|
||||
t = value.b[0];
|
||||
value.b[0] = value.b[7];
|
||||
value.b[7] = t;
|
||||
t = value.b[1];
|
||||
value.b[1] = value.b[6];
|
||||
value.b[6] = t;
|
||||
t = value.b[2];
|
||||
value.b[2] = value.b[5];
|
||||
value.b[5] = t;
|
||||
t = value.b[3];
|
||||
value.b[3] = value.b[4];
|
||||
value.b[4] = t;
|
||||
#else
|
||||
#error Unsupported cell size
|
||||
#endif
|
||||
*pc = value.c;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL swapchars(AMX *amx,const cell *params)
|
||||
{
|
||||
cell c;
|
||||
|
||||
(void)amx;
|
||||
assert((size_t)params[0]==sizeof(cell));
|
||||
|
||||
c=params[1];
|
||||
amx_swapcell(&c);
|
||||
return c;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL core_tolower(AMX *amx,const cell *params)
|
||||
{
|
||||
(void)amx;
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32
|
||||
return (cell)CharLower((LPTSTR)params[1]);
|
||||
#elif defined _Windows
|
||||
return (cell)AnsiLower((LPSTR)params[1]);
|
||||
#else
|
||||
if ((unsigned)(params[1]-'A')<26u)
|
||||
return params[1]+'a'-'A';
|
||||
return params[1];
|
||||
#endif
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL core_toupper(AMX *amx,const cell *params)
|
||||
{
|
||||
(void)amx;
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32
|
||||
return (cell)CharUpper((LPTSTR)params[1]);
|
||||
#elif defined _Windows
|
||||
return (cell)AnsiUpper((LPSTR)params[1]);
|
||||
#else
|
||||
if ((unsigned)(params[1]-'a')<26u)
|
||||
return params[1]+'A'-'a';
|
||||
return params[1];
|
||||
#endif
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL core_min(AMX *amx,const cell *params)
|
||||
{
|
||||
(void)amx;
|
||||
return params[1] <= params[2] ? params[1] : params[2];
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL core_max(AMX *amx,const cell *params)
|
||||
{
|
||||
(void)amx;
|
||||
return params[1] >= params[2] ? params[1] : params[2];
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL core_clamp(AMX *amx,const cell *params)
|
||||
{
|
||||
cell value = params[1];
|
||||
if (params[2] > params[3]) /* minimum value > maximum value ! */
|
||||
amx_RaiseError(amx,AMX_ERR_NATIVE);
|
||||
if (value < params[2])
|
||||
value = params[2];
|
||||
else if (value > params[3])
|
||||
value = params[3];
|
||||
return value;
|
||||
}
|
||||
|
||||
#if !defined AMX_NOPROPLIST
|
||||
static char *MakePackedString(cell *cptr)
|
||||
{
|
||||
int len;
|
||||
char *dest;
|
||||
|
||||
amx_StrLen(cptr,&len);
|
||||
dest=(char *)malloc(len+sizeof(cell));
|
||||
amx_GetString(dest,cptr,0,len+sizeof(cell));
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* getproperty(id=0, const name[]="", value=cellmin, string[]="", size=sizeof string) */
|
||||
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]);
|
||||
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]);
|
||||
} /* 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;
|
||||
cell *cstr;
|
||||
char *name;
|
||||
proplist *item;
|
||||
|
||||
cstr=amx_Address(amx,params[2]);
|
||||
name=MakePackedString(cstr);
|
||||
item=list_finditem(&proproot,params[1],name,params[3],NULL);
|
||||
if (item==NULL)
|
||||
item=list_additem(&proproot);
|
||||
if (item==NULL) {
|
||||
amx_RaiseError(amx,AMX_ERR_MEMORY);
|
||||
} else {
|
||||
prev=item->value;
|
||||
if (strlen(name)==0) {
|
||||
free(name);
|
||||
cstr=amx_Address(amx,params[4]);
|
||||
name=MakePackedString(cstr);
|
||||
} /* if */
|
||||
list_setitem(item,params[1],name,params[3]);
|
||||
} /* if */
|
||||
free(name);
|
||||
return prev;
|
||||
}
|
||||
|
||||
/* deleteproperty(id=0, const name[]="", value=cellmin) */
|
||||
static cell AMX_NATIVE_CALL delproperty(AMX *amx,const cell *params)
|
||||
{
|
||||
cell prev=0;
|
||||
cell *cstr;
|
||||
char *name;
|
||||
proplist *item,*pred;
|
||||
|
||||
(void)amx;
|
||||
cstr=amx_Address(amx,params[2]);
|
||||
name=MakePackedString(cstr);
|
||||
item=list_finditem(&proproot,params[1],name,params[3],&pred);
|
||||
if (item!=NULL) {
|
||||
prev=item->value;
|
||||
list_delete(pred,item);
|
||||
} /* if */
|
||||
free(name);
|
||||
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]);
|
||||
name=MakePackedString(cstr);
|
||||
item=list_finditem(&proproot,params[1],name,params[3],NULL);
|
||||
free(name);
|
||||
return (item!=NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined AMX_NORANDOM
|
||||
/* This routine comes from the book "Inner Loops" by Rick Booth, Addison-Wesley
|
||||
* (ISBN 0-201-47960-5). This is a "multiplicative congruential random number
|
||||
* generator" that has been extended to 31-bits (the standard C version returns
|
||||
* only 15-bits).
|
||||
*/
|
||||
#define INITIAL_SEED 0xcaa938dbL
|
||||
static unsigned long IL_StandardRandom_seed = INITIAL_SEED; /* always use a non-zero seed */
|
||||
#define IL_RMULT 1103515245L
|
||||
#if defined __BORLANDC__ || defined __WATCOMC__
|
||||
#pragma argsused
|
||||
#endif
|
||||
static cell AMX_NATIVE_CALL core_random(AMX *amx,const cell *params)
|
||||
{
|
||||
unsigned long lo, hi, ll, lh, hh, hl;
|
||||
unsigned long result;
|
||||
|
||||
/* one-time initialization (or, mostly one-time) */
|
||||
#if !defined SN_TARGET_PS2 && !defined _WIN32_WCE && !defined __ICC430__
|
||||
if (IL_StandardRandom_seed == INITIAL_SEED)
|
||||
IL_StandardRandom_seed=(unsigned long)time(NULL);
|
||||
#endif
|
||||
|
||||
(void)amx;
|
||||
|
||||
lo = IL_StandardRandom_seed & 0xffff;
|
||||
hi = IL_StandardRandom_seed >> 16;
|
||||
IL_StandardRandom_seed = IL_StandardRandom_seed * IL_RMULT + 12345;
|
||||
ll = lo * (IL_RMULT & 0xffff);
|
||||
lh = lo * (IL_RMULT >> 16 );
|
||||
hl = hi * (IL_RMULT & 0xffff);
|
||||
hh = hi * (IL_RMULT >> 16 );
|
||||
result = ((ll + 12345) >> 16) + lh + hl + (hh << 16);
|
||||
result &= ~LONG_MIN; /* remove sign bit */
|
||||
if (params[1]!=0)
|
||||
result %= params[1];
|
||||
return (cell)result;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
const AMX_NATIVE_INFO core_Natives[] = {
|
||||
{ "numargs", numargs },
|
||||
{ "getarg", getarg },
|
||||
{ "setarg", setarg },
|
||||
{ "heapspace", heapspace },
|
||||
{ "funcidx", funcidx },
|
||||
{ "swapchars", swapchars },
|
||||
{ "tolower", core_tolower },
|
||||
{ "toupper", core_toupper },
|
||||
{ "min", core_min },
|
||||
{ "max", core_max },
|
||||
{ "clamp", core_clamp },
|
||||
#if !defined AMX_NORANDOM
|
||||
{ "random", core_random },
|
||||
#endif
|
||||
#if !defined AMX_NOPROPLIST
|
||||
{ "getproperty", getproperty },
|
||||
{ "setproperty", setproperty },
|
||||
{ "deleteproperty",delproperty },
|
||||
{ "existproperty", existproperty },
|
||||
#endif
|
||||
{ NULL, NULL } /* terminator */
|
||||
};
|
||||
|
||||
int AMXEXPORT AMXAPI amx_CoreInit(AMX *amx)
|
||||
{
|
||||
return amx_Register(amx, core_Natives, -1);
|
||||
}
|
||||
|
||||
int AMXEXPORT AMXAPI amx_CoreCleanup(AMX *amx)
|
||||
{
|
||||
(void)amx;
|
||||
#if !defined AMX_NOPROPLIST
|
||||
while (proproot.next!=NULL)
|
||||
list_delete(&proproot,proproot.next);
|
||||
#endif
|
||||
return AMX_ERR_NONE;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,379 +0,0 @@
|
||||
/* Float arithmetic for the Pawn Abstract Machine
|
||||
*
|
||||
* Copyright (c) Artran, Inc. 1999
|
||||
* Written by Greg Garner (gmg@artran.com)
|
||||
* This file may be freely used. No warranties of any kind.
|
||||
*
|
||||
* CHANGES -
|
||||
* 2002-08-27: Basic conversion of source from C++ to C by Adam D. Moss
|
||||
* <adam@gimp.org> <aspirin@icculus.org>
|
||||
* 2003-08-29: Removal of the dynamic memory allocation and replacing two
|
||||
* type conversion functions by macros, by Thiadmer Riemersma
|
||||
* 2003-09-22: Moved the type conversion macros to AMX.H, and simplifications
|
||||
* of some routines, by Thiadmer Riemersma
|
||||
* 2003-11-24: A few more native functions (geometry), plus minor modifications,
|
||||
* mostly to be compatible with dynamically loadable extension
|
||||
* modules, by Thiadmer Riemersma
|
||||
* 2004-01-09: Adaptions for 64-bit cells (using "double precision"), by
|
||||
* Thiadmer Riemersma
|
||||
*/
|
||||
#include <stdlib.h> /* for atof() */
|
||||
#include <stdio.h> /* for NULL */
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include "amx.h"
|
||||
|
||||
/*
|
||||
#if defined __BORLANDC__
|
||||
#pragma resource "amxFloat.res"
|
||||
#endif
|
||||
*/
|
||||
|
||||
#if PAWN_CELL_SIZE==32
|
||||
#define REAL float
|
||||
#elif PAWN_CELL_SIZE==64
|
||||
#define REAL double
|
||||
#else
|
||||
#error Unsupported cell size
|
||||
#endif
|
||||
|
||||
#define PI 3.1415926535897932384626433832795
|
||||
|
||||
/******************************************************************/
|
||||
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
|
||||
*/
|
||||
REAL fValue;
|
||||
|
||||
(void)amx;
|
||||
/* Convert to a float. Calls the compilers long to float conversion. */
|
||||
fValue = (REAL) params[1];
|
||||
|
||||
/* Return the cell. */
|
||||
return amx_ftoc(fValue);
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
static cell AMX_NATIVE_CALL n_strfloat(AMX *amx,const cell *params)
|
||||
{
|
||||
/*
|
||||
* params[0] = number of bytes
|
||||
* params[1] = virtual string address to convert to a float
|
||||
*/
|
||||
char szSource[60];
|
||||
cell *pString;
|
||||
REAL fNum;
|
||||
int nLen;
|
||||
|
||||
(void)amx;
|
||||
/* They should have sent us 1 cell. */
|
||||
assert(params[0]/sizeof(cell)==1);
|
||||
|
||||
/* Get the real address of the string. */
|
||||
pString=amx_Address(amx,params[1]);
|
||||
|
||||
/* Find out how long the string is in characters. */
|
||||
amx_StrLen(pString, &nLen);
|
||||
if (nLen == 0 || nLen >= sizeof szSource)
|
||||
return 0;
|
||||
|
||||
/* Now convert the Pawn string into a C type null terminated string */
|
||||
amx_GetString(szSource, pString, 0, sizeof szSource);
|
||||
|
||||
/* Now convert this to a float. */
|
||||
fNum = (REAL)atof(szSource);
|
||||
|
||||
return amx_ftoc(fNum);
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
static cell AMX_NATIVE_CALL n_floatmul(AMX *amx,const cell *params)
|
||||
{
|
||||
/*
|
||||
* params[0] = number of bytes
|
||||
* params[1] = float operand 1
|
||||
* params[2] = float operand 2
|
||||
*/
|
||||
REAL fRes = amx_ctof(params[1]) * amx_ctof(params[2]);
|
||||
(void)amx;
|
||||
return amx_ftoc(fRes);
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
static cell AMX_NATIVE_CALL n_floatdiv(AMX *amx,const cell *params)
|
||||
{
|
||||
/*
|
||||
* params[0] = number of bytes
|
||||
* params[1] = float dividend (top)
|
||||
* params[2] = float divisor (bottom)
|
||||
*/
|
||||
REAL fRes = amx_ctof(params[1]) / amx_ctof(params[2]);
|
||||
(void)amx;
|
||||
return amx_ftoc(fRes);
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
static cell AMX_NATIVE_CALL n_floatadd(AMX *amx,const cell *params)
|
||||
{
|
||||
/*
|
||||
* params[0] = number of bytes
|
||||
* params[1] = float operand 1
|
||||
* params[2] = float operand 2
|
||||
*/
|
||||
REAL fRes = amx_ctof(params[1]) + amx_ctof(params[2]);
|
||||
(void)amx;
|
||||
return amx_ftoc(fRes);
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
static cell AMX_NATIVE_CALL n_floatsub(AMX *amx,const cell *params)
|
||||
{
|
||||
/*
|
||||
* params[0] = number of bytes
|
||||
* params[1] = float operand 1
|
||||
* params[2] = float operand 2
|
||||
*/
|
||||
REAL fRes = amx_ctof(params[1]) - amx_ctof(params[2]);
|
||||
(void)amx;
|
||||
return amx_ftoc(fRes);
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
/* Return fractional part of float */
|
||||
static cell AMX_NATIVE_CALL n_floatfract(AMX *amx,const cell *params)
|
||||
{
|
||||
/*
|
||||
* params[0] = number of bytes
|
||||
* params[1] = float operand
|
||||
*/
|
||||
REAL fA = amx_ctof(params[1]);
|
||||
fA = fA - (REAL)(floor((double)fA));
|
||||
(void)amx;
|
||||
return amx_ftoc(fA);
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
/* Return integer part of float, rounded */
|
||||
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)
|
||||
*/
|
||||
REAL fA = amx_ctof(params[1]);
|
||||
|
||||
(void)amx;
|
||||
switch (params[2])
|
||||
{
|
||||
case 1: /* round downwards */
|
||||
fA = (REAL)(floor((double)fA));
|
||||
break;
|
||||
case 2: /* round upwards */
|
||||
fA = (REAL)(ceil((double)fA));
|
||||
break;
|
||||
case 3: /* round towards zero (truncate) */
|
||||
if ( fA>=0.0 )
|
||||
fA = (REAL)(floor((double)fA));
|
||||
else
|
||||
fA = (REAL)(ceil((double)fA));
|
||||
break;
|
||||
default: /* standard, round to nearest */
|
||||
fA = (REAL)(floor((double)fA+.5));
|
||||
break;
|
||||
}
|
||||
|
||||
return (cell)fA;
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
static cell AMX_NATIVE_CALL n_floatcmp(AMX *amx,const cell *params)
|
||||
{
|
||||
/*
|
||||
* params[0] = number of bytes
|
||||
* params[1] = float operand 1
|
||||
* params[2] = float operand 2
|
||||
*/
|
||||
REAL fA, fB;
|
||||
|
||||
(void)amx;
|
||||
fA = amx_ctof(params[1]);
|
||||
fB = amx_ctof(params[2]);
|
||||
if (fA == fB)
|
||||
return 0;
|
||||
else if (fA>fB)
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
static cell AMX_NATIVE_CALL n_floatsqroot(AMX *amx,const cell *params)
|
||||
{
|
||||
/*
|
||||
* params[0] = number of bytes
|
||||
* params[1] = float operand
|
||||
*/
|
||||
REAL fA = amx_ctof(params[1]);
|
||||
fA = (REAL)sqrt(fA);
|
||||
if (fA < 0)
|
||||
return amx_RaiseError(amx, AMX_ERR_DOMAIN);
|
||||
return amx_ftoc(fA);
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
static cell AMX_NATIVE_CALL n_floatpower(AMX *amx,const cell *params)
|
||||
{
|
||||
/*
|
||||
* params[0] = number of bytes
|
||||
* params[1] = float operand 1 (base)
|
||||
* params[2] = float operand 2 (exponent)
|
||||
*/
|
||||
REAL fA = amx_ctof(params[1]);
|
||||
REAL fB = amx_ctof(params[2]);
|
||||
fA = (REAL)pow(fA, fB);
|
||||
(void)amx;
|
||||
return amx_ftoc(fA);
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
static cell AMX_NATIVE_CALL n_floatlog(AMX *amx,const cell *params)
|
||||
{
|
||||
/*
|
||||
* params[0] = number of bytes
|
||||
* params[1] = float operand 1 (value)
|
||||
* params[2] = float operand 2 (base)
|
||||
*/
|
||||
REAL fValue = amx_ctof(params[1]);
|
||||
REAL fBase = amx_ctof(params[2]);
|
||||
(void)amx;
|
||||
if (fValue <= 0.0 || fBase <= 0)
|
||||
return amx_RaiseError(amx, AMX_ERR_DOMAIN);
|
||||
if (fBase == 10.0) // ??? epsilon
|
||||
fValue = (REAL)log10(fValue);
|
||||
else
|
||||
fValue = (REAL)(log(fValue) / log(fBase));
|
||||
return amx_ftoc(fValue);
|
||||
}
|
||||
|
||||
static REAL ToRadians(REAL angle, int radix)
|
||||
{
|
||||
switch (radix)
|
||||
{
|
||||
case 1: /* degrees, sexagesimal system (technically: degrees/minutes/seconds) */
|
||||
return (REAL)(angle * PI / 180.0);
|
||||
case 2: /* grades, centesimal system */
|
||||
return (REAL)(angle * PI / 200.0);
|
||||
default: /* assume already radian */
|
||||
return angle;
|
||||
} /* switch */
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
static cell AMX_NATIVE_CALL n_floatsin(AMX *amx,const cell *params)
|
||||
{
|
||||
/*
|
||||
* params[0] = number of bytes
|
||||
* params[1] = float operand 1 (angle)
|
||||
* params[2] = float operand 2 (radix)
|
||||
*/
|
||||
REAL fA = amx_ctof(params[1]);
|
||||
fA = ToRadians(fA, params[2]);
|
||||
fA = (float)sin(fA);
|
||||
(void)amx;
|
||||
return amx_ftoc(fA);
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
static cell AMX_NATIVE_CALL n_floatcos(AMX *amx,const cell *params)
|
||||
{
|
||||
/*
|
||||
* params[0] = number of bytes
|
||||
* params[1] = float operand 1 (angle)
|
||||
* params[2] = float operand 2 (radix)
|
||||
*/
|
||||
REAL fA = amx_ctof(params[1]);
|
||||
fA = ToRadians(fA, params[2]);
|
||||
fA = (float)cos(fA);
|
||||
(void)amx;
|
||||
return amx_ftoc(fA);
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
static cell AMX_NATIVE_CALL n_floattan(AMX *amx,const cell *params)
|
||||
{
|
||||
/*
|
||||
* params[0] = number of bytes
|
||||
* params[1] = float operand 1 (angle)
|
||||
* params[2] = float operand 2 (radix)
|
||||
*/
|
||||
REAL fA = amx_ctof(params[1]);
|
||||
fA = ToRadians(fA, params[2]);
|
||||
fA = (float)tan(fA);
|
||||
(void)amx;
|
||||
return amx_ftoc(fA);
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
static cell AMX_NATIVE_CALL n_floatabs(AMX *amx,const cell *params)
|
||||
{
|
||||
REAL fA = amx_ctof(params[1]);
|
||||
fA = (fA >= 0) ? fA : -fA;
|
||||
(void)amx;
|
||||
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
|
||||
const AMX_NATIVE_INFO float_Natives[] = {
|
||||
{ "float", n_float },
|
||||
{ "strfloat", n_strfloat },
|
||||
{ "floatmul", n_floatmul },
|
||||
{ "floatdiv", n_floatdiv },
|
||||
{ "floatadd", n_floatadd },
|
||||
{ "floatsub", n_floatsub },
|
||||
{ "floatfract", n_floatfract },
|
||||
{ "floatround", n_floatround },
|
||||
{ "floatcmp", n_floatcmp },
|
||||
{ "floatsqroot", n_floatsqroot},
|
||||
{ "floatpower", n_floatpower },
|
||||
{ "floatlog", n_floatlog },
|
||||
{ "floatsin", n_floatsin },
|
||||
{ "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)
|
||||
{
|
||||
return amx_Register(amx,float_Natives,-1);
|
||||
}
|
||||
|
||||
int AMXEXPORT AMXAPI amx_FloatCleanup(AMX *amx)
|
||||
{
|
||||
(void)amx;
|
||||
return AMX_ERR_NONE;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,480 +0,0 @@
|
||||
/* Date/time module for the Pawn Abstract Machine
|
||||
*
|
||||
* Copyright (c) ITB CompuPhase, 2001-2013
|
||||
*
|
||||
* 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: amxtime.c 4983 2013-10-21 07:32:57Z $
|
||||
*/
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
#include "amx.h"
|
||||
#if defined __WIN32__ || defined _WIN32 || defined _Windows
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
#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
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32
|
||||
static int timerset = 0;
|
||||
/* timeGetTime() is more accurate on WindowsNT if timeBeginPeriod(1) is set */
|
||||
#define INIT_TIMER() \
|
||||
if (!timerset) { \
|
||||
timeBeginPeriod(1); \
|
||||
timerset=1; \
|
||||
}
|
||||
#else
|
||||
#define INIT_TIMER()
|
||||
#endif
|
||||
static unsigned long timestamp;
|
||||
static unsigned long timelimit;
|
||||
static int timerepeat;
|
||||
|
||||
static const unsigned char monthdays[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
|
||||
static int wrap(int value, int min, int max)
|
||||
{
|
||||
if (value<min)
|
||||
value=max;
|
||||
else if (value>max)
|
||||
value=min;
|
||||
return value;
|
||||
}
|
||||
|
||||
static unsigned long gettimestamp(void)
|
||||
{
|
||||
unsigned long value;
|
||||
|
||||
#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
|
||||
/* 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));
|
||||
#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)
|
||||
{
|
||||
(void)amx;
|
||||
settime(params[1],params[2],params[3]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* gettime(&hour, &minute, &second)
|
||||
* The return value is the number of seconds since 1 January 1970 (Unix system
|
||||
* time).
|
||||
*/
|
||||
static cell AMX_NATIVE_CALL n_gettime(AMX *amx, const cell *params)
|
||||
{
|
||||
time_t sec1970;
|
||||
struct tm gtm;
|
||||
cell *cptr;
|
||||
|
||||
assert(params[0]==(int)(3*sizeof(cell)));
|
||||
|
||||
time(&sec1970);
|
||||
|
||||
/* on DOS/Windows, the timezone is usually not set for the C run-time
|
||||
* 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;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* setdate(year, month, day)
|
||||
* Always returns 0
|
||||
*/
|
||||
static cell AMX_NATIVE_CALL n_setdate(AMX *amx, const cell *params)
|
||||
{
|
||||
(void)amx;
|
||||
setdate(params[1],params[2],params[3]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* getdate(&year, &month, &day)
|
||||
* The return value is the number of days since the start of the year. January
|
||||
* 1 is day 1 of the year.
|
||||
*/
|
||||
static cell AMX_NATIVE_CALL n_getdate(AMX *amx, const cell *params)
|
||||
{
|
||||
time_t sec1970;
|
||||
struct tm gtm;
|
||||
cell *cptr;
|
||||
|
||||
assert(params[0]==(int)(3*sizeof(cell)));
|
||||
|
||||
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;
|
||||
|
||||
return gtm.tm_yday+1;
|
||||
}
|
||||
|
||||
/* tickcount(&granularity)
|
||||
* Returns the number of milliseconds since start-up. For a 32-bit cell, this
|
||||
* count overflows after approximately 24 days of continuous operation.
|
||||
*/
|
||||
static cell AMX_NATIVE_CALL n_tickcount(AMX *amx, const cell *params)
|
||||
{
|
||||
cell *cptr;
|
||||
|
||||
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 */
|
||||
#else
|
||||
*cptr=(cell)CLOCKS_PER_SEC; /* in Unix/Linux, this is often 100 */
|
||||
#endif
|
||||
return gettimestamp() & 0x7fffffff;
|
||||
}
|
||||
|
||||
/* delay(milliseconds)
|
||||
* Pauses for (at least) the requested number of milliseconds.
|
||||
*/
|
||||
static cell AMX_NATIVE_CALL n_delay(AMX *amx, const cell *params)
|
||||
{
|
||||
unsigned long stamp;
|
||||
|
||||
(void)amx;
|
||||
assert(params[0]==(int)sizeof(cell));
|
||||
|
||||
INIT_TIMER();
|
||||
stamp=gettimestamp();
|
||||
while (gettimestamp()-stamp < (unsigned long)params[1])
|
||||
/* nothing */;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* settimer(milliseconds, bool: singleshot = false)
|
||||
* Sets the delay until the @timer() callback is called. The timer may either
|
||||
* be single-shot or repetitive.
|
||||
*/
|
||||
static cell AMX_NATIVE_CALL n_settimer(AMX *amx, const cell *params)
|
||||
{
|
||||
(void)amx;
|
||||
assert(params[0]==(int)(2*sizeof(cell)));
|
||||
timestamp=gettimestamp();
|
||||
timelimit=params[1];
|
||||
timerepeat=(int)(params[2]==0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* bool: gettimer(&milliseconds, bool: &singleshot = false)
|
||||
* Retrieves the timer set with settimer(); returns true if a timer
|
||||
* was set up, or false otherwise.
|
||||
*/
|
||||
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;
|
||||
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;
|
||||
static int idxTimer = -1;
|
||||
|
||||
static int AMXAPI amx_TimeIdle(AMX *amx, int AMXAPI Exec(AMX *, cell *, int))
|
||||
{
|
||||
int err=0;
|
||||
|
||||
assert(idxTimer >= 0);
|
||||
|
||||
if (PrevIdle != NULL)
|
||||
PrevIdle(amx, Exec);
|
||||
|
||||
if (timelimit>0 && (gettimestamp()-timestamp)>=timelimit) {
|
||||
if (timerepeat)
|
||||
timestamp+=timelimit;
|
||||
else
|
||||
timelimit=0; /* do not repeat single-shot timer */
|
||||
err = Exec(amx, NULL, idxTimer);
|
||||
while (err == AMX_ERR_SLEEP)
|
||||
err = Exec(amx, NULL, AMX_EXEC_CONT);
|
||||
} /* if */
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined __cplusplus
|
||||
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 },
|
||||
{ NULL, NULL } /* terminator */
|
||||
};
|
||||
|
||||
int AMXEXPORT AMXAPI amx_TimeInit(AMX *amx)
|
||||
{
|
||||
#if !defined AMXTIME_NOIDLE
|
||||
/* see whether there is a @timer() function */
|
||||
if (amx_FindPublic(amx,"@timer",&idxTimer) == AMX_ERR_NONE) {
|
||||
if (amx_GetUserData(amx, AMX_USERTAG('I','d','l','e'), (void**)&PrevIdle) != AMX_ERR_NONE)
|
||||
PrevIdle = NULL;
|
||||
amx_SetUserData(amx, AMX_USERTAG('I','d','l','e'), amx_TimeIdle);
|
||||
} /* if */
|
||||
#endif
|
||||
|
||||
return amx_Register(amx, time_Natives, -1);
|
||||
}
|
||||
|
||||
int AMXEXPORT AMXAPI amx_TimeCleanup(AMX *amx)
|
||||
{
|
||||
(void)amx;
|
||||
#if !defined AMXTIME_NOIDLE
|
||||
PrevIdle = NULL;
|
||||
#endif
|
||||
return AMX_ERR_NONE;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,778 +0,0 @@
|
||||
/*
|
||||
* BinReloc - a library for creating relocatable executables
|
||||
* Written by: Hongli Lai <h.lai@chello.nl>
|
||||
* http://autopackage.org/
|
||||
*
|
||||
* This source code is public domain. You can relicense this code
|
||||
* under whatever license you want.
|
||||
*
|
||||
* See http://autopackage.org/docs/binreloc/ for
|
||||
* more information and how to use this.
|
||||
*/
|
||||
|
||||
#ifndef __BINRELOC_C__
|
||||
#define __BINRELOC_C__
|
||||
|
||||
#ifdef ENABLE_BINRELOC
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#endif /* ENABLE_BINRELOC */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include "binreloc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
/** @internal
|
||||
* Find the canonical filename of the executable. Returns the filename
|
||||
* (which must be freed) or NULL on error. If the parameter 'error' is
|
||||
* not NULL, the error code will be stored there, if an error occured.
|
||||
*/
|
||||
static char *
|
||||
_br_find_exe(BrInitError *error)
|
||||
{
|
||||
#ifndef ENABLE_BINRELOC
|
||||
if (error)
|
||||
*error = BR_INIT_ERROR_DISABLED;
|
||||
return NULL;
|
||||
#else
|
||||
char *path, *path2, *line, *result;
|
||||
size_t buf_size;
|
||||
ssize_t size;
|
||||
struct stat stat_buf;
|
||||
FILE *f;
|
||||
|
||||
/* Read from /proc/self/exe (symlink) */
|
||||
if (sizeof (path) > SSIZE_MAX)
|
||||
buf_size = SSIZE_MAX - 1;
|
||||
else
|
||||
buf_size = PATH_MAX - 1;
|
||||
path = (char *) malloc (buf_size);
|
||||
if (path == NULL) {
|
||||
/* Cannot allocate memory. */
|
||||
if (error)
|
||||
*error = BR_INIT_ERROR_NOMEM;
|
||||
return NULL;
|
||||
}
|
||||
path2 = (char *) malloc (buf_size);
|
||||
if (path2 == NULL) {
|
||||
/* Cannot allocate memory. */
|
||||
if (error)
|
||||
*error = BR_INIT_ERROR_NOMEM;
|
||||
free (path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strncpy (path2, "/proc/self/exe", buf_size - 1);
|
||||
|
||||
while (1) {
|
||||
int i;
|
||||
|
||||
size = readlink (path2, path, buf_size - 1);
|
||||
if (size == -1) {
|
||||
/* Error. */
|
||||
free (path2);
|
||||
break;
|
||||
}
|
||||
|
||||
/* readlink() success. */
|
||||
path[size] = '\0';
|
||||
|
||||
/* Check whether the symlink's target is also a symlink.
|
||||
* We want to get the final target. */
|
||||
i = stat (path, &stat_buf);
|
||||
if (i == -1) {
|
||||
/* Error. */
|
||||
free (path2);
|
||||
break;
|
||||
}
|
||||
|
||||
/* stat() success. */
|
||||
if (!S_ISLNK (stat_buf.st_mode)) {
|
||||
/* path is not a symlink. Done. */
|
||||
free (path2);
|
||||
return path;
|
||||
}
|
||||
|
||||
/* path is a symlink. Continue loop and resolve this. */
|
||||
strncpy (path, path2, buf_size - 1);
|
||||
}
|
||||
|
||||
|
||||
/* readlink() or stat() failed; this can happen when the program is
|
||||
* running in Valgrind 2.2. Read from /proc/self/maps as fallback. */
|
||||
|
||||
buf_size = PATH_MAX + 128;
|
||||
line = (char *) realloc (path, buf_size);
|
||||
if (line == NULL) {
|
||||
/* Cannot allocate memory. */
|
||||
free (path);
|
||||
if (error)
|
||||
*error = BR_INIT_ERROR_NOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f = fopen ("/proc/self/maps", "r");
|
||||
if (f == NULL) {
|
||||
free (line);
|
||||
if (error)
|
||||
*error = BR_INIT_ERROR_OPEN_MAPS;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* The first entry should be the executable name. */
|
||||
result = fgets (line, (int) buf_size, f);
|
||||
if (result == NULL) {
|
||||
fclose (f);
|
||||
free (line);
|
||||
if (error)
|
||||
*error = BR_INIT_ERROR_READ_MAPS;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get rid of newline character. */
|
||||
buf_size = strlen (line);
|
||||
if (buf_size <= 0) {
|
||||
/* Huh? An empty string? */
|
||||
fclose (f);
|
||||
free (line);
|
||||
if (error)
|
||||
*error = BR_INIT_ERROR_INVALID_MAPS;
|
||||
return NULL;
|
||||
}
|
||||
if (line[buf_size - 1] == 10)
|
||||
line[buf_size - 1] = 0;
|
||||
|
||||
/* Extract the filename; it is always an absolute path. */
|
||||
path = strchr (line, '/');
|
||||
|
||||
/* Sanity check. */
|
||||
if (strstr (line, " r-xp ") == NULL || path == NULL) {
|
||||
fclose (f);
|
||||
free (line);
|
||||
if (error)
|
||||
*error = BR_INIT_ERROR_INVALID_MAPS;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
path = strdup (path);
|
||||
free (line);
|
||||
fclose (f);
|
||||
return path;
|
||||
#endif /* ENABLE_BINRELOC */
|
||||
}
|
||||
|
||||
|
||||
/** @internal
|
||||
* Find the canonical filename of the executable which owns symbol.
|
||||
* Returns a filename which must be freed, or NULL on error.
|
||||
*/
|
||||
static char *
|
||||
_br_find_exe_for_symbol(const void *symbol, BrInitError *error)
|
||||
{
|
||||
#ifndef ENABLE_BINRELOC
|
||||
if (error)
|
||||
*error = BR_INIT_ERROR_DISABLED;
|
||||
return (char *) NULL;
|
||||
#else
|
||||
#define SIZE PATH_MAX + 100
|
||||
FILE *f;
|
||||
size_t address_string_len;
|
||||
char *address_string, line[SIZE], *found;
|
||||
|
||||
if (symbol == NULL)
|
||||
return (char *) NULL;
|
||||
|
||||
f = fopen ("/proc/self/maps", "r");
|
||||
if (f == NULL)
|
||||
return (char *) NULL;
|
||||
|
||||
address_string_len = 4;
|
||||
address_string = (char *) malloc (address_string_len);
|
||||
found = (char *) NULL;
|
||||
|
||||
while (!feof (f)) {
|
||||
char *start_addr, *end_addr, *end_addr_end, *file;
|
||||
void *start_addr_p, *end_addr_p;
|
||||
size_t len;
|
||||
|
||||
if (fgets (line, SIZE, f) == NULL)
|
||||
break;
|
||||
|
||||
/* Sanity check. */
|
||||
if (strstr (line, " r-xp ") == NULL || strchr (line, '/') == NULL)
|
||||
continue;
|
||||
|
||||
/* Parse line. */
|
||||
start_addr = line;
|
||||
end_addr = strchr (line, '-');
|
||||
file = strchr (line, '/');
|
||||
|
||||
/* More sanity check. */
|
||||
if (!(file > end_addr && end_addr != NULL && end_addr[0] == '-'))
|
||||
continue;
|
||||
|
||||
end_addr[0] = '\0';
|
||||
end_addr++;
|
||||
end_addr_end = strchr (end_addr, ' ');
|
||||
if (end_addr_end == NULL)
|
||||
continue;
|
||||
|
||||
end_addr_end[0] = '\0';
|
||||
len = strlen (file);
|
||||
if (len == 0)
|
||||
continue;
|
||||
if (file[len - 1] == '\n')
|
||||
file[len - 1] = '\0';
|
||||
|
||||
/* Get rid of "(deleted)" from the filename. */
|
||||
len = strlen (file);
|
||||
if (len > 10 && strcmp (file + len - 10, " (deleted)") == 0)
|
||||
file[len - 10] = '\0';
|
||||
|
||||
/* I don't know whether this can happen but better safe than sorry. */
|
||||
len = strlen (start_addr);
|
||||
if (len != strlen (end_addr))
|
||||
continue;
|
||||
|
||||
|
||||
/* Transform the addresses into a string in the form of 0xdeadbeef,
|
||||
* then transform that into a pointer. */
|
||||
if (address_string_len < len + 3) {
|
||||
address_string_len = len + 3;
|
||||
address_string = (char *) realloc (address_string, address_string_len);
|
||||
}
|
||||
|
||||
memcpy (address_string, "0x", 2);
|
||||
memcpy (address_string + 2, start_addr, len);
|
||||
address_string[2 + len] = '\0';
|
||||
sscanf (address_string, "%p", &start_addr_p);
|
||||
|
||||
memcpy (address_string, "0x", 2);
|
||||
memcpy (address_string + 2, end_addr, len);
|
||||
address_string[2 + len] = '\0';
|
||||
sscanf (address_string, "%p", &end_addr_p);
|
||||
|
||||
|
||||
if (symbol >= start_addr_p && symbol < end_addr_p) {
|
||||
found = file;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free (address_string);
|
||||
fclose (f);
|
||||
|
||||
if (found == NULL)
|
||||
return (char *) NULL;
|
||||
else
|
||||
return strdup (found);
|
||||
#endif /* ENABLE_BINRELOC */
|
||||
}
|
||||
|
||||
|
||||
#ifndef BINRELOC_RUNNING_DOXYGEN
|
||||
#undef NULL
|
||||
#define NULL ((void *) 0) /* typecasted as char* for C++ type safeness */
|
||||
#endif
|
||||
|
||||
static char *exe = (char *) NULL;
|
||||
|
||||
|
||||
/** Initialize the BinReloc library (for applications).
|
||||
*
|
||||
* This function must be called before using any other BinReloc functions.
|
||||
* It attempts to locate the application's canonical filename.
|
||||
*
|
||||
* @note If you want to use BinReloc for a library, then you should call
|
||||
* br_init_lib() instead.
|
||||
*
|
||||
* @param error If BinReloc failed to initialize, then the error code will
|
||||
* be stored in this variable. Set to NULL if you want to
|
||||
* ignore this. See #BrInitError for a list of error codes.
|
||||
*
|
||||
* @returns 1 on success, 0 if BinReloc failed to initialize.
|
||||
*/
|
||||
int
|
||||
br_init(BrInitError *error)
|
||||
{
|
||||
exe = _br_find_exe(error);
|
||||
return exe != NULL;
|
||||
}
|
||||
|
||||
|
||||
/** Initialize the BinReloc library (for libraries).
|
||||
*
|
||||
* This function must be called before using any other BinReloc functions.
|
||||
* It attempts to locate the calling library's canonical filename.
|
||||
*
|
||||
* @note The BinReloc source code MUST be included in your library, or this
|
||||
* function won't work correctly.
|
||||
*
|
||||
* @param error If BinReloc failed to initialize, then the error code will
|
||||
* be stored in this variable. Set to NULL if you want to
|
||||
* ignore this. See #BrInitError for a list of error codes.
|
||||
*
|
||||
* @returns 1 on success, 0 if a filename cannot be found.
|
||||
*/
|
||||
int
|
||||
br_init_lib(BrInitError *error)
|
||||
{
|
||||
exe = _br_find_exe_for_symbol((const void *) "", error);
|
||||
return exe != NULL;
|
||||
}
|
||||
|
||||
|
||||
/** Find the canonical filename of the current application.
|
||||
*
|
||||
* @param default_exe A default filename which will be used as fallback.
|
||||
* @returns A string containing the application's canonical filename,
|
||||
* which must be freed when no longer necessary. If BinReloc is
|
||||
* not initialized, or if br_init() failed, then a copy of
|
||||
* default_exe will be returned. If default_exe is NULL, then
|
||||
* NULL will be returned.
|
||||
*/
|
||||
char *
|
||||
br_find_exe(const char *default_exe)
|
||||
{
|
||||
if (exe == (char *) NULL)
|
||||
{
|
||||
/* BinReloc is not initialized. */
|
||||
if (default_exe != (const char *) NULL)
|
||||
return strdup(default_exe);
|
||||
else
|
||||
return (char *) NULL;
|
||||
}
|
||||
return strdup(exe);
|
||||
}
|
||||
|
||||
|
||||
/** Locate the directory in which the current application is installed.
|
||||
*
|
||||
* The prefix is generated by the following pseudo-code evaluation:
|
||||
* \code
|
||||
* dirname(exename)
|
||||
* \endcode
|
||||
*
|
||||
* @param default_dir A default directory which will used as fallback.
|
||||
* @return A string containing the directory, which must be freed when no
|
||||
* longer necessary. If BinReloc is not initialized, or if the
|
||||
* initialization function failed, then a copy of default_dir
|
||||
* will be returned. If default_dir is NULL, then NULL will be
|
||||
* returned.
|
||||
*/
|
||||
char *
|
||||
br_find_exe_dir(const char *default_dir)
|
||||
{
|
||||
if (exe == NULL)
|
||||
{
|
||||
/* BinReloc not initialized. */
|
||||
if (default_dir != NULL)
|
||||
return strdup(default_dir);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return br_dirname(exe);
|
||||
}
|
||||
|
||||
|
||||
/** Locate the prefix in which the current application is installed.
|
||||
*
|
||||
* The prefix is generated by the following pseudo-code evaluation:
|
||||
* \code
|
||||
* dirname(dirname(exename))
|
||||
* \endcode
|
||||
*
|
||||
* @param default_prefix A default prefix which will used as fallback.
|
||||
* @return A string containing the prefix, which must be freed when no
|
||||
* longer necessary. If BinReloc is not initialized, or if
|
||||
* the initialization function failed, then a copy of default_prefix
|
||||
* will be returned. If default_prefix is NULL, then NULL will be returned.
|
||||
*/
|
||||
char *
|
||||
br_find_prefix(const char *default_prefix)
|
||||
{
|
||||
char *dir1, *dir2;
|
||||
|
||||
if (exe == (char *) NULL)
|
||||
{
|
||||
/* BinReloc not initialized. */
|
||||
if (default_prefix != (const char *) NULL)
|
||||
return strdup(default_prefix);
|
||||
else
|
||||
return (char *) NULL;
|
||||
}
|
||||
|
||||
dir1 = br_dirname(exe);
|
||||
dir2 = br_dirname(dir1);
|
||||
free(dir1);
|
||||
return dir2;
|
||||
}
|
||||
|
||||
|
||||
/** Locate the application's binary folder.
|
||||
*
|
||||
* The path is generated by the following pseudo-code evaluation:
|
||||
* \code
|
||||
* prefix + "/bin"
|
||||
* \endcode
|
||||
*
|
||||
* @param default_bin_dir A default path which will used as fallback.
|
||||
* @return A string containing the bin folder's path, which must be freed when
|
||||
* no longer necessary. If BinReloc is not initialized, or if
|
||||
* the initialization function failed, then a copy of default_bin_dir will
|
||||
* be returned. If default_bin_dir is NULL, then NULL will be returned.
|
||||
*/
|
||||
char *
|
||||
br_find_bin_dir(const char *default_bin_dir)
|
||||
{
|
||||
char *prefix, *dir;
|
||||
|
||||
prefix = br_find_prefix((const char *) NULL);
|
||||
if (prefix == (char *) NULL)
|
||||
{
|
||||
/* BinReloc not initialized. */
|
||||
if (default_bin_dir != (const char *) NULL)
|
||||
return strdup(default_bin_dir);
|
||||
else
|
||||
return (char *) NULL;
|
||||
}
|
||||
|
||||
dir = br_build_path(prefix, "bin");
|
||||
free(prefix);
|
||||
return dir;
|
||||
}
|
||||
|
||||
|
||||
/** Locate the application's superuser binary folder.
|
||||
*
|
||||
* The path is generated by the following pseudo-code evaluation:
|
||||
* \code
|
||||
* prefix + "/sbin"
|
||||
* \endcode
|
||||
*
|
||||
* @param default_sbin_dir A default path which will used as fallback.
|
||||
* @return A string containing the sbin folder's path, which must be freed when
|
||||
* no longer necessary. If BinReloc is not initialized, or if the
|
||||
* initialization function failed, then a copy of default_sbin_dir will
|
||||
* be returned. If default_bin_dir is NULL, then NULL will be returned.
|
||||
*/
|
||||
char *
|
||||
br_find_sbin_dir(const char *default_sbin_dir)
|
||||
{
|
||||
char *prefix, *dir;
|
||||
|
||||
prefix = br_find_prefix((const char *) NULL);
|
||||
if (prefix == (char *) NULL)
|
||||
{
|
||||
/* BinReloc not initialized. */
|
||||
if (default_sbin_dir != (const char *) NULL)
|
||||
return strdup(default_sbin_dir);
|
||||
else
|
||||
return (char *) NULL;
|
||||
}
|
||||
|
||||
dir = br_build_path(prefix, "sbin");
|
||||
free(prefix);
|
||||
return dir;
|
||||
}
|
||||
|
||||
|
||||
/** Locate the application's data folder.
|
||||
*
|
||||
* The path is generated by the following pseudo-code evaluation:
|
||||
* \code
|
||||
* prefix + "/share"
|
||||
* \endcode
|
||||
*
|
||||
* @param default_data_dir A default path which will used as fallback.
|
||||
* @return A string containing the data folder's path, which must be freed when
|
||||
* no longer necessary. If BinReloc is not initialized, or if the
|
||||
* initialization function failed, then a copy of default_data_dir
|
||||
* will be returned. If default_data_dir is NULL, then NULL will be
|
||||
* returned.
|
||||
*/
|
||||
char *
|
||||
br_find_data_dir(const char *default_data_dir)
|
||||
{
|
||||
char *prefix, *dir;
|
||||
|
||||
prefix = br_find_prefix((const char *) NULL);
|
||||
if (prefix == (char *) NULL)
|
||||
{
|
||||
/* BinReloc not initialized. */
|
||||
if (default_data_dir != (const char *) NULL)
|
||||
return strdup(default_data_dir);
|
||||
else
|
||||
return (char *) NULL;
|
||||
}
|
||||
|
||||
dir = br_build_path(prefix, "share");
|
||||
free(prefix);
|
||||
return dir;
|
||||
}
|
||||
|
||||
|
||||
/** Locate the application's localization folder.
|
||||
*
|
||||
* The path is generated by the following pseudo-code evaluation:
|
||||
* \code
|
||||
* prefix + "/share/locale"
|
||||
* \endcode
|
||||
*
|
||||
* @param default_locale_dir A default path which will used as fallback.
|
||||
* @return A string containing the localization folder's path, which must be freed when
|
||||
* no longer necessary. If BinReloc is not initialized, or if the
|
||||
* initialization function failed, then a copy of default_locale_dir will be returned.
|
||||
* If default_locale_dir is NULL, then NULL will be returned.
|
||||
*/
|
||||
char *
|
||||
br_find_locale_dir(const char *default_locale_dir)
|
||||
{
|
||||
char *data_dir, *dir;
|
||||
|
||||
data_dir = br_find_data_dir((const char *) NULL);
|
||||
if (data_dir == (char *) NULL)
|
||||
{
|
||||
/* BinReloc not initialized. */
|
||||
if (default_locale_dir != (const char *) NULL)
|
||||
return strdup(default_locale_dir);
|
||||
else
|
||||
return (char *) NULL;
|
||||
}
|
||||
|
||||
dir = br_build_path(data_dir, "locale");
|
||||
free(data_dir);
|
||||
return dir;
|
||||
}
|
||||
|
||||
|
||||
/** Locate the application's library folder.
|
||||
*
|
||||
* The path is generated by the following pseudo-code evaluation:
|
||||
* \code
|
||||
* prefix + "/lib"
|
||||
* \endcode
|
||||
*
|
||||
* @param default_lib_dir A default path which will used as fallback.
|
||||
* @return A string containing the library folder's path, which must be freed when
|
||||
* no longer necessary. If BinReloc is not initialized, or if the initialization
|
||||
* function failed, then a copy of default_lib_dir will be returned.
|
||||
* If default_lib_dir is NULL, then NULL will be returned.
|
||||
*/
|
||||
char *
|
||||
br_find_lib_dir(const char *default_lib_dir)
|
||||
{
|
||||
char *prefix, *dir;
|
||||
|
||||
prefix = br_find_prefix((const char *) NULL);
|
||||
if (prefix == (char *) NULL)
|
||||
{
|
||||
/* BinReloc not initialized. */
|
||||
if (default_lib_dir != (const char *) NULL)
|
||||
return strdup(default_lib_dir);
|
||||
else
|
||||
return (char *) NULL;
|
||||
}
|
||||
|
||||
dir = br_build_path(prefix, "lib");
|
||||
free(prefix);
|
||||
return dir;
|
||||
}
|
||||
|
||||
|
||||
/** Locate the application's libexec folder.
|
||||
*
|
||||
* The path is generated by the following pseudo-code evaluation:
|
||||
* \code
|
||||
* prefix + "/libexec"
|
||||
* \endcode
|
||||
*
|
||||
* @param default_libexec_dir A default path which will used as fallback.
|
||||
* @return A string containing the libexec folder's path, which must be freed when
|
||||
* no longer necessary. If BinReloc is not initialized, or if the initialization
|
||||
* function failed, then a copy of default_libexec_dir will be returned.
|
||||
* If default_libexec_dir is NULL, then NULL will be returned.
|
||||
*/
|
||||
char *
|
||||
br_find_libexec_dir(const char *default_libexec_dir)
|
||||
{
|
||||
char *prefix, *dir;
|
||||
|
||||
prefix = br_find_prefix((const char *) NULL);
|
||||
if (prefix == (char *) NULL)
|
||||
{
|
||||
/* BinReloc not initialized. */
|
||||
if (default_libexec_dir != (const char *) NULL)
|
||||
return strdup(default_libexec_dir);
|
||||
else
|
||||
return (char *) NULL;
|
||||
}
|
||||
|
||||
dir = br_build_path(prefix, "libexec");
|
||||
free(prefix);
|
||||
return dir;
|
||||
}
|
||||
|
||||
|
||||
/** Locate the application's configuration files folder.
|
||||
*
|
||||
* The path is generated by the following pseudo-code evaluation:
|
||||
* \code
|
||||
* prefix + "/etc"
|
||||
* \endcode
|
||||
*
|
||||
* @param default_etc_dir A default path which will used as fallback.
|
||||
* @return A string containing the etc folder's path, which must be freed when
|
||||
* no longer necessary. If BinReloc is not initialized, or if the initialization
|
||||
* function failed, then a copy of default_etc_dir will be returned.
|
||||
* If default_etc_dir is NULL, then NULL will be returned.
|
||||
*/
|
||||
char *
|
||||
br_find_etc_dir(const char *default_etc_dir)
|
||||
{
|
||||
char *prefix, *dir;
|
||||
|
||||
prefix = br_find_prefix((const char *) NULL);
|
||||
if (prefix == (char *) NULL)
|
||||
{
|
||||
/* BinReloc not initialized. */
|
||||
if (default_etc_dir != (const char *) NULL)
|
||||
return strdup(default_etc_dir);
|
||||
else
|
||||
return (char *) NULL;
|
||||
}
|
||||
|
||||
dir = br_build_path(prefix, "etc");
|
||||
free(prefix);
|
||||
return dir;
|
||||
}
|
||||
|
||||
|
||||
/***********************
|
||||
* Utility functions
|
||||
***********************/
|
||||
|
||||
/** Concatenate str1 and str2 to a newly allocated string.
|
||||
*
|
||||
* @param str1 A string.
|
||||
* @param str2 Another string.
|
||||
* @returns A newly-allocated string. This string should be freed when no longer needed.
|
||||
*/
|
||||
char *
|
||||
br_strcat(const char *str1, const char *str2)
|
||||
{
|
||||
char *result;
|
||||
size_t len1, len2;
|
||||
|
||||
if (str1 == NULL)
|
||||
str1 = "";
|
||||
if (str2 == NULL)
|
||||
str2 = "";
|
||||
|
||||
len1 = strlen(str1);
|
||||
len2 = strlen(str2);
|
||||
|
||||
result = (char *) malloc(len1 + len2 + 1);
|
||||
memcpy(result, str1, len1);
|
||||
memcpy(result + len1, str2, len2);
|
||||
result[len1 + len2] = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
br_build_path(const char *dir, const char *file)
|
||||
{
|
||||
char *dir2, *result;
|
||||
size_t len;
|
||||
int must_free = 0;
|
||||
|
||||
len = strlen(dir);
|
||||
if (len > 0 && dir[len - 1] != '/')
|
||||
{
|
||||
dir2 = br_strcat(dir, "/");
|
||||
must_free = 1;
|
||||
} else
|
||||
dir2 = (char *) dir;
|
||||
|
||||
result = br_strcat(dir2, file);
|
||||
if (must_free)
|
||||
free(dir2);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* Emulates glibc's strndup() */
|
||||
static char *
|
||||
br_strndup(const char *str, size_t size)
|
||||
{
|
||||
char *result = (char *) NULL;
|
||||
size_t len;
|
||||
|
||||
if (str == (const char *) NULL)
|
||||
return (char *) NULL;
|
||||
|
||||
len = strlen(str);
|
||||
if (len == 0)
|
||||
return strdup("");
|
||||
if (size > len)
|
||||
size = len;
|
||||
|
||||
result = (char *) malloc(len + 1);
|
||||
memcpy(result, str, size);
|
||||
result[size] = '\0';
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/** Extracts the directory component of a path.
|
||||
*
|
||||
* Similar to g_dirname() or the dirname commandline application.
|
||||
*
|
||||
* Example:
|
||||
* \code
|
||||
* br_dirname ("/usr/local/foobar"); --> Returns: "/usr/local"
|
||||
* \endcode
|
||||
*
|
||||
* @param path A path.
|
||||
* @returns A directory name. This string should be freed when no longer needed.
|
||||
*/
|
||||
char *
|
||||
br_dirname(const char *path)
|
||||
{
|
||||
char *end, *result;
|
||||
|
||||
if (path == (const char *) NULL)
|
||||
return (char *) NULL;
|
||||
|
||||
end = strrchr(path, '/');
|
||||
if (end == (const char *) NULL)
|
||||
return strdup(".");
|
||||
|
||||
while (end > path && *end == '/')
|
||||
end--;
|
||||
result = br_strndup(path, end - path + 1);
|
||||
if (result[0] == 0)
|
||||
{
|
||||
free(result);
|
||||
return strdup("/");
|
||||
} else
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __BINRELOC_C__ */
|
@ -1,80 +0,0 @@
|
||||
/*
|
||||
* BinReloc - a library for creating relocatable executables
|
||||
* Written by: Hongli Lai <h.lai@chello.nl>
|
||||
* http://autopackage.org/
|
||||
*
|
||||
* This source code is public domain. You can relicense this code
|
||||
* under whatever license you want.
|
||||
*
|
||||
* See http://autopackage.org/docs/binreloc/ for
|
||||
* more information and how to use this.
|
||||
*/
|
||||
|
||||
#ifndef __BINRELOC_H__
|
||||
#define __BINRELOC_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
/** These error codes can be returned by br_init(), br_init_lib(), gbr_init() or gbr_init_lib(). */
|
||||
typedef enum {
|
||||
/** Cannot allocate memory. */
|
||||
BR_INIT_ERROR_NOMEM,
|
||||
/** Unable to open /proc/self/maps; see errno for details. */
|
||||
BR_INIT_ERROR_OPEN_MAPS,
|
||||
/** Unable to read from /proc/self/maps; see errno for details. */
|
||||
BR_INIT_ERROR_READ_MAPS,
|
||||
/** The file format of /proc/self/maps is invalid; kernel bug? */
|
||||
BR_INIT_ERROR_INVALID_MAPS,
|
||||
/** BinReloc is disabled (the ENABLE_BINRELOC macro is not defined). */
|
||||
BR_INIT_ERROR_DISABLED
|
||||
} BrInitError;
|
||||
|
||||
|
||||
#ifndef BINRELOC_RUNNING_DOXYGEN
|
||||
/* Mangle symbol names to avoid symbol collisions with other ELF objects. */
|
||||
#define br_init SbCJ22537442193159_br_init
|
||||
#define br_init_lib SbCJ22537442193159_br_init_lib
|
||||
#define br_find_exe SbCJ22537442193159_br_find_exe
|
||||
#define br_find_exe_dir SbCJ22537442193159_br_find_exe_dir
|
||||
#define br_find_prefix SbCJ22537442193159_br_find_prefix
|
||||
#define br_find_bin_dir SbCJ22537442193159_br_find_bin_dir
|
||||
#define br_find_sbin_dir SbCJ22537442193159_br_find_sbin_dir
|
||||
#define br_find_data_dir SbCJ22537442193159_br_find_data_dir
|
||||
#define br_find_locale_dir SbCJ22537442193159_br_find_locale_dir
|
||||
#define br_find_lib_dir SbCJ22537442193159_br_find_lib_dir
|
||||
#define br_find_libexec_dir SbCJ22537442193159_br_find_libexec_dir
|
||||
#define br_find_etc_dir SbCJ22537442193159_br_find_etc_dir
|
||||
#define br_strcat SbCJ22537442193159_br_strcat
|
||||
#define br_build_path SbCJ22537442193159_br_build_path
|
||||
#define br_dirname SbCJ22537442193159_br_dirname
|
||||
|
||||
|
||||
#endif
|
||||
int br_init (BrInitError *error);
|
||||
int br_init_lib (BrInitError *error);
|
||||
|
||||
char *br_find_exe (const char *default_exe);
|
||||
char *br_find_exe_dir (const char *default_dir);
|
||||
char *br_find_prefix (const char *default_prefix);
|
||||
char *br_find_bin_dir (const char *default_bin_dir);
|
||||
char *br_find_sbin_dir (const char *default_sbin_dir);
|
||||
char *br_find_data_dir (const char *default_data_dir);
|
||||
char *br_find_locale_dir (const char *default_locale_dir);
|
||||
char *br_find_lib_dir (const char *default_lib_dir);
|
||||
char *br_find_libexec_dir (const char *default_libexec_dir);
|
||||
char *br_find_etc_dir (const char *default_etc_dir);
|
||||
|
||||
/* Utility functions */
|
||||
char *br_strcat (const char *str1, const char *str2);
|
||||
char *br_build_path (const char *dir, const char *file);
|
||||
char *br_dirname (const char *path);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __BINRELOC_H__ */
|
@ -1,104 +0,0 @@
|
||||
/* Extremely inefficient but portable POSIX getch() */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <termios.h> /* for tcgetattr() and tcsetattr() */
|
||||
#include <unistd.h> /* for read() */
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include "getch.h"
|
||||
|
||||
#ifndef STDIN_FILENO
|
||||
# define STDIN_FILENO 0
|
||||
#endif
|
||||
|
||||
int
|
||||
getch (void)
|
||||
{
|
||||
struct termios save_termios;
|
||||
struct termios ios;
|
||||
unsigned char b;
|
||||
int c = 0;
|
||||
|
||||
if (!isatty (STDIN_FILENO))
|
||||
return EOF;
|
||||
|
||||
if (tcgetattr (STDIN_FILENO, &save_termios) < 0)
|
||||
return EOF;
|
||||
|
||||
ios = save_termios;
|
||||
ios.c_lflag &= ~(ICANON | ECHO | ISIG);
|
||||
ios.c_cc[VMIN] = 1; /* read() will return with one char */
|
||||
ios.c_cc[VTIME] = 0; /* read() blocks forever */
|
||||
|
||||
if (tcsetattr (STDIN_FILENO, TCSANOW, &ios) < 0)
|
||||
return EOF;
|
||||
|
||||
if (read (STDIN_FILENO, &b, 1) == 1)
|
||||
c = (int)(0xff & b);
|
||||
else
|
||||
c = EOF;
|
||||
|
||||
tcsetattr (STDIN_FILENO, TCSANOW, &save_termios);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
int
|
||||
kbhit (void)
|
||||
{
|
||||
struct termios save_termios;
|
||||
struct termios ios;
|
||||
fd_set inp;
|
||||
struct timeval timeout = {0, 0};
|
||||
int result;
|
||||
|
||||
if (!isatty (STDIN_FILENO))
|
||||
return 0;
|
||||
|
||||
if (tcgetattr (STDIN_FILENO, &save_termios) < 0)
|
||||
return 0;
|
||||
|
||||
ios = save_termios;
|
||||
ios.c_lflag &= ~(ICANON | ECHO | ISIG);
|
||||
ios.c_cc[VMIN] = 1; /* read() will return with one char */
|
||||
ios.c_cc[VTIME] = 0; /* read() blocks forever */
|
||||
|
||||
if (tcsetattr (STDIN_FILENO, TCSANOW, &ios) < 0)
|
||||
return 0;
|
||||
|
||||
/* set up select() args */
|
||||
FD_ZERO(&inp);
|
||||
FD_SET(STDIN_FILENO, &inp);
|
||||
|
||||
result = select (STDIN_FILENO+1, &inp, NULL, NULL, &timeout) == 1;
|
||||
|
||||
tcsetattr (STDIN_FILENO, TCSANOW, &save_termios);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#if defined TEST_GETCH
|
||||
int
|
||||
main ()
|
||||
{
|
||||
int i;
|
||||
char c[4];
|
||||
|
||||
printf("Enter %d keys to continue: ", sizeof c - 1);
|
||||
fflush (stdout);
|
||||
|
||||
memset(c, 0, sizeof c);
|
||||
for (i=0; i<sizeof c - 1; i++)
|
||||
c[i] = getch ();
|
||||
|
||||
printf("Your input: [%s]\n", c);
|
||||
|
||||
printf("Now hit any key to abort: ");
|
||||
while (!kbhit())
|
||||
printf(".");
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
@ -1,15 +0,0 @@
|
||||
/* Extremely inefficient but portable POSIX getch(), see getch.c */
|
||||
#ifndef GETCH_H
|
||||
#define GETCH_H
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
int getch(void);
|
||||
int kbhit(void);
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GETCH_H */
|
@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Things needed to compile under linux.
|
||||
*
|
||||
* Should be reworked totally to use GNU's 'configure'
|
||||
*/
|
||||
#ifndef SCLINUX_H
|
||||
#define SCLINUX_H
|
||||
|
||||
/* getchar() is not a 'cool' replacement for MSDOS getch: Linux/unix depends on the features activated or not about the
|
||||
* controlling terminal's tty. This means that ioctl(2) calls must be performed, for instance to have the controlling
|
||||
* terminal tty's in 'raw' mode, if we want to be able to fetch a single character. This also means that everything must
|
||||
* be put back correctly when the function ends. See GETCH.C for an implementation.
|
||||
*
|
||||
* For interactive use of PawnRun/PawnDbg if would be much better to use GNU's readline package: the user would be able to
|
||||
* have a complete emacs/vi like line editing system.
|
||||
*/
|
||||
#if !defined getch && !defined kbhit
|
||||
#include "getch.h"
|
||||
#endif
|
||||
|
||||
#define stricmp(a,b) strcasecmp(a,b)
|
||||
#define strnicmp(a,b,c) strncasecmp(a,b,c)
|
||||
|
||||
/*
|
||||
* WinWorld wants '\'. Unices do not.
|
||||
*/
|
||||
#define DIRECTORY_SEP_CHAR '/'
|
||||
#define DIRECTORY_SEP_STR "/"
|
||||
|
||||
/*
|
||||
* SC assumes that a computer is Little Endian unless told otherwise. It uses
|
||||
* (and defines) the macros BYTE_ORDER and BIG_ENDIAN.
|
||||
* For Linux, we must overrule these settings with those defined in glibc.
|
||||
*/
|
||||
#if !defined __BYTE_ORDER
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#if defined __OpenBSD__ || defined __FreeBSD__ || defined __APPLE__
|
||||
# define __BYTE_ORDER BYTE_ORDER
|
||||
# define __LITTLE_ENDIAN LITTLE_ENDIAN
|
||||
# define __BIG_ENDIAN BIG_ENDIAN
|
||||
#endif
|
||||
|
||||
#if !defined __BYTE_ORDER
|
||||
# error "Can't figure computer byte order (__BYTE_ORDER macro not found)"
|
||||
#endif
|
||||
|
||||
#endif /* SCLINUX_H */
|
@ -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,877 +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-2015
|
||||
*
|
||||
* 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 5181 2015-01-21 09:44:28Z 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
|
||||
#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
|
||||
#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)
|
||||
{
|
||||
register int c1, c2;
|
||||
|
||||
while (n-- != 0 && (*s1 || *s2)) {
|
||||
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) {
|
||||
idx = -1;
|
||||
do {
|
||||
if (!ini_read(LocalBuffer, INI_BUFFERSIZE, fp))
|
||||
return 0;
|
||||
sp = skipleading(LocalBuffer);
|
||||
ep = _tcschr(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 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
|
||||
*
|
||||
* 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 = _tcschr(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 */
|
||||
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 = _tcschr(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);
|
||||
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) {
|
||||
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 */
|
||||
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;
|
||||
int n;
|
||||
|
||||
/* generate digits in reverse order */
|
||||
do {
|
||||
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 */
|
@ -1,159 +0,0 @@
|
||||
/*
|
||||
* Platform
|
||||
* __MSDOS__ set when compiling for DOS (not Windows)
|
||||
* _Windows set when compiling for any version of Microsoft Windows
|
||||
* __WIN32__ set when compiling for Windows95 or WindowsNT (32 bit mode)
|
||||
* __32BIT__ set when compiling in 32-bit "flat" mode (DOS, Windows, ARM)
|
||||
* __64BIT__ set when compiling in 64-bit mode
|
||||
* __ECOS__ set if Pawn was included with the eCos with configtool
|
||||
* __LINUX__ set when compiling for Linux
|
||||
*
|
||||
* Copyright 1998-2011, ITB CompuPhase, The Netherlands.
|
||||
* No usage restrictions, no warranties.
|
||||
*/
|
||||
|
||||
#ifndef _OSDEFS_H
|
||||
#define _OSDEFS_H
|
||||
|
||||
/* Every compiler uses different "default" macros to indicate the mode
|
||||
* it is in. Throughout the source, we use the Borland C++ macros, so
|
||||
* the macros of Watcom C/C++ and Microsoft Visual C/C++ are mapped to
|
||||
* those of Borland C++.
|
||||
*/
|
||||
#if defined(__WATCOMC__)
|
||||
#if defined(__WINDOWS__) || defined(__NT__)
|
||||
#define _Windows 1
|
||||
#endif
|
||||
#if defined(__386__) || defined(__NT__)
|
||||
#define __32BIT__ 1
|
||||
#endif
|
||||
#if defined(_Windows) && defined(__32BIT__)
|
||||
#define __WIN32__ 1
|
||||
#endif
|
||||
#elif defined(_MSC_VER)
|
||||
#if defined(_WINDOWS) || defined(_WIN32)
|
||||
#define _Windows 1
|
||||
#endif
|
||||
#if defined(_WIN32)
|
||||
#define __WIN32__ 1
|
||||
#define __32BIT__ 1
|
||||
#endif
|
||||
#elif defined __arm__
|
||||
#define __32BIT__ 1
|
||||
#elif defined __AVR__
|
||||
#define __16BIT__ 1
|
||||
#endif
|
||||
#if !defined __16BIT__ && !defined __32BIT__ && !defined __64BIT__
|
||||
#define __32BIT__ 1
|
||||
#endif
|
||||
|
||||
|
||||
#if (defined __linux || defined __linux__) && !defined __LINUX__
|
||||
#define __LINUX__
|
||||
#endif
|
||||
/* To be able to eventually set __ECOS__, we have to find a symbol
|
||||
* defined in a common place (so including the header file won't break
|
||||
* anything for other platforms). <sys/types.h> includes
|
||||
* <pkgconf/system.h> and in this later file we can find CYGPKG_PAWN
|
||||
* if the Pawn package was included with configtool and so we know
|
||||
* that we are compiling for eCos.
|
||||
*/
|
||||
#if defined CCSINFO
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#if defined CYGPKG_PAWN
|
||||
#define __ECOS__ 1
|
||||
#define HAVE_ALLOCA_H 0
|
||||
#endif
|
||||
|
||||
|
||||
#if defined __FreeBSD__
|
||||
#include <sys/endian.h>
|
||||
#elif defined __LINUX__
|
||||
#include <endian.h>
|
||||
#elif defined __ECOS__
|
||||
#include <cyg/hal/hal_endian.h>
|
||||
#define BIG_ENDIAN 4321
|
||||
#define LITTLE_ENDIAN 1234
|
||||
#if (CYG_BYTEORDER == CYG_LSBFIRST)
|
||||
#define BYTE_ORDER LITTLE_ENDIAN
|
||||
#else
|
||||
#define BYTE_ORDER BIG_ENDIAN
|
||||
#endif
|
||||
/*
|
||||
* eCos option management.
|
||||
*/
|
||||
#include <pkgconf/pawn.h>
|
||||
#if CYGPKG_PAWN_AMX_ANSIONLY==1
|
||||
#define AMX_ANSIONLY
|
||||
#endif
|
||||
#define PAWN_CELL_SIZE CYGPKG_PAWN_AMX_CELLSIZE
|
||||
#if CYGPKG_PAWN_CORE_RANDOM==0
|
||||
#define AMX_NORANDOM
|
||||
#endif
|
||||
#if CYGPKG_PAWN_CORE_PROPERTY==0
|
||||
#define AMX_NOPROPLIST
|
||||
#endif
|
||||
#if CYGPKG_PAWN_AMX_CONS_FIXEDPOINT==1
|
||||
#define FIXEDPOINT
|
||||
#endif
|
||||
#if CYGPKG_PAWN_AMX_CONS_FLOATPOINT==1
|
||||
#define FLOATPOINT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Linux now has these */
|
||||
#if !defined BIG_ENDIAN
|
||||
#define BIG_ENDIAN 4321
|
||||
#endif
|
||||
#if !defined LITTLE_ENDIAN
|
||||
#define LITTLE_ENDIAN 1234
|
||||
#endif
|
||||
|
||||
/* educated guess, BYTE_ORDER is undefined, i386 is common => little endian */
|
||||
#if !defined BYTE_ORDER
|
||||
#if defined UCLINUX
|
||||
#define BYTE_ORDER BIG_ENDIAN
|
||||
#else
|
||||
#define BYTE_ORDER LITTLE_ENDIAN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined __MSDOS__ || defined __WIN32__ || defined _Windows
|
||||
#define DIRSEP_CHAR '\\'
|
||||
#elif defined macintosh /* only the original Macintosh uses ':', OSX uses the '/' */
|
||||
#define DIRSEP_CHAR ':'
|
||||
#else
|
||||
#define DIRSEP_CHAR '/'
|
||||
#endif
|
||||
|
||||
/* _MAX_PATH is sometimes called differently and it may be in limits.h or
|
||||
* stdlib.h instead of stdio.h.
|
||||
*/
|
||||
#if !defined _MAX_PATH
|
||||
/* not defined, perhaps stdio.h was not included */
|
||||
#if !defined PATH_MAX
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#if !defined _MAX_PATH && !defined PATH_MAX
|
||||
/* no _MAX_PATH and no MAX_PATH, perhaps it is in limits.h */
|
||||
#include <limits.h>
|
||||
#endif
|
||||
#if !defined _MAX_PATH && !defined PATH_MAX
|
||||
/* no _MAX_PATH and no MAX_PATH, perhaps it is in stdlib.h */
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
/* if _MAX_PATH is undefined, try common alternative names */
|
||||
#if !defined _MAX_PATH
|
||||
#if defined MAX_PATH
|
||||
#define _MAX_PATH MAX_PATH
|
||||
#elif defined _POSIX_PATH_MAX
|
||||
#define _MAX_PATH _POSIX_PATH_MAX
|
||||
#else
|
||||
/* everything failed, actually we have a problem here... */
|
||||
#define _MAX_PATH 1024
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* _OSDEFS_H */
|
@ -1,23 +0,0 @@
|
||||
forward OnCreate(ID);
|
||||
forward OnDestroy(ID);
|
||||
forward OnSpawn(ID);
|
||||
forward OnActivate(ID, actor);
|
||||
forward OnCellChange(ID, cell);
|
||||
forward OnItemCountChange(ID, count);
|
||||
forward OnItemConditionChange(ID, Float:condition);
|
||||
forward OnItemEquippedChange(ID, Bool:equipped);
|
||||
forward OnActorValueChange(ID, ActorValue:index, Float:value);
|
||||
forward OnActorBaseValueChange(ID, ActorValue:index, Float:value);
|
||||
forward OnActorSneak(ID, Bool:sneaking);
|
||||
forward OnActorDeath(ID, killer, cause);
|
||||
forward OnActorAttack(victim, attacker, weapon, damage);
|
||||
forward OnPlayerDisconnect(ID, reason);
|
||||
forward OnPlayerRequestGame(ID);
|
||||
forward OnPlayerChat(ID, message{});
|
||||
|
||||
forward OnClientAuthenticate(const name{}, const pwd{});
|
||||
forward OnGameTimeChange(year, month, day, hour);
|
||||
forward OnServerInit();
|
||||
forward OnServerExit(Bool:error);
|
||||
|
||||
forward OnCharGen(ID);
|
@ -1,30 +0,0 @@
|
||||
const Sex: {
|
||||
Male = 0,
|
||||
Female = 1,
|
||||
}
|
||||
|
||||
const Race: {
|
||||
Argoninan = "Argonian",
|
||||
Breton = "Breton",
|
||||
DarkElf = "Dark Elf",
|
||||
HighElf = "High Elf",
|
||||
Imperial = "Imperial",
|
||||
Khajiit = "Khajiit",
|
||||
Nord = "Nord",
|
||||
Orc = "Orc",
|
||||
Redguard = "Redguard",
|
||||
WoodElf = "Wood Elf"
|
||||
}
|
||||
|
||||
native Bool:Kick(ID);
|
||||
native SetRespawnTime(interval);
|
||||
native GetRespawnTime();
|
||||
native SetSpawnCell(cell);
|
||||
native GetSpawnCell();
|
||||
|
||||
native Bool:IsPlayer(ID);
|
||||
|
||||
native GetBaseName(ID, message);
|
||||
native SetBaseName(ID);
|
||||
|
||||
native CharGen(ID);
|
@ -1,10 +0,0 @@
|
||||
native Bool:IsCell(cell);
|
||||
native Bool:IsInterior(cell);
|
||||
|
||||
native GetPosition(ID, Float:x, Float:y, Float:z);
|
||||
native SetPosition(ID, Float:x, Float:y, Float:z);
|
||||
native GetRotation(ID, Float:x, Float:y, Float:z);
|
||||
native SetRotation(ID, Float:x, Float:y, Float:z);
|
||||
native SetCell(ID, cell);
|
||||
native GetCell(ID);
|
||||
|
@ -1,15 +0,0 @@
|
||||
native SetGameWeather(weather);
|
||||
native SetGameTime(time);
|
||||
native SetGameYear(year);
|
||||
native SetGameMonth(month);
|
||||
native SetGameDay(day);
|
||||
native SetGameHour(hour);
|
||||
native SetTimeScale(Float:scale);
|
||||
|
||||
native GetGameWeather();
|
||||
native GetGameTime();
|
||||
native GetGameYear();
|
||||
native GetGameMonth();
|
||||
native GetGameDay();
|
||||
native GetGameHour();
|
||||
native Float:GetTimeScale();
|
Loading…
Reference in New Issue