builtins.cpp
来自「Shorthand是一个强大的脚本语言」· C++ 代码 · 共 710 行 · 第 1/2 页
CPP
710 行
///////////////////////////////////////////////////////////////////////////////
// $Header: /shorthand/src/builtins.cpp 6 2/08/03 6:40a Arm $
//-----------------------------------------------------------------------------
// Project: ShortHand interpreter
// Author: Andrei Remenchuk <andrei@remenchuk.com>
//-----------------------------------------------------------------------------
// builtins.cpp: implementations of ShortHand built-in functions
///////////////////////////////////////////////////////////////////////////////
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include "builtins.h"
#include "module.h"
#include "except.h"
#include "http.h"
#include "cookie.h"
#include "sharray.h"
#include "hash.h"
#ifndef WIN32
static int min(int x, int y) { return x < y ? x : y; }
static int max(int x, int y) { return x > y ? x : y; }
#endif
ShhBuiltinList g_builtins;
static int set_globals()
{
tzset();
return 0;
}
static int dummy = set_globals();
ShhBuiltin::ShhBuiltin(const char* name, shorthand_function_t f, int argc)
: ShhFunction(name, argc)
{
m_function = f;
g_builtins.add(this);
}
ShhValue ShhBuiltin::execute(ShhModule* module, const ShhValueList& args) const
{
int argc = args.size();
if (m_argc > 0)
{
if (m_argc == 1 && argc == 0)
throw new ShhFunctionException(9000, "function '%s' requires an argument", m_name.cstr());
else if (argc < m_argc)
throw new ShhFunctionException(9000, "function '%s' requires %d arguments", m_name.cstr(), m_argc);
}
return m_function(module, args);
}
void ShhBuiltin::paste_location(string& location)
{
location = "as built-in function";
}
const ShhBuiltin* ShhBuiltinList::find(const char* name)
{
for(int i=0,n=m_size; i<n; i++)
{
ShhBuiltin* b = get(i);
if (stricmp(b->m_name, name) == 0) return b;
}
return NULL;
}
#define SHORTHAND_BUILTIN(name, argc) \
ShhValue _shh_bi_impl_##name(ShhModule* module, const ShhValueList& args); \
ShhBuiltin _shh_bi_desc_##name(#name, _shh_bi_impl_##name, argc); \
ShhValue _shh_bi_impl_##name(ShhModule* module, const ShhValueList& args)
#define ARGC args.size()
#define ARG(i) args.get(i)
#define MAKE_STRING(s) module->scratch().strdup(s)
/**
* exit()
* stops script execution and send finish sending output
* @return none
*/
SHORTHAND_BUILTIN(exit, 0)
{
throw new ShhExitException();
}
/**
* header(name,value): sets HTTP header
* @return none
*/
SHORTHAND_BUILTIN(header, 2)
{
HttpStream* stream = module->stream();
if (stream->http_headers_sent())
{
throw new ShhFunctionException(9010, "Cannot set HTTP header value because headers have been already sent");
}
string name, value;
ARG(0)->toString(name);
ARG(1)->toString(value);
stream->http_add_header(name, value);
return ShhValue::EMPTY;
}
/**
* jump(url)
* redirects page to the supplied URL
*
* @return none
*/
SHORTHAND_BUILTIN(redirect, 1)
{
HttpStream* stream = module->stream();
if (stream->http_headers_sent())
{
throw new ShhFunctionException(9011, "Cannot perform redirection because headers have been already sent");
}
string url;
ARG(0)->toString(url);
stream->http_add_header("Location", url);
stream->http_set_response_code(302, "Moved");
throw new ShhExitException();
}
/**
* lc(s): lowercase string
*/
SHORTHAND_BUILTIN(lc, 1)
{
string s; ARG(0)->toString(s);
s.lowercase();
char* result = module->scratch().strdup(s);
return ShhValue(result);
}
/**
* uc(s): uppercase string
*/
SHORTHAND_BUILTIN(uc, 1)
{
string s; ARG(0)->toString(s);
s.uppercase();
char* result = module->scratch().strdup(s);
return ShhValue(result);
}
/**
* env(s): value of environment variable
*/
SHORTHAND_BUILTIN(env, 1)
{
string s,tmp; ARG(0)->toString(s);
const char* result = safe_getenv(s, tmp);
if (result == NULL) result = "";
return ShhValue(module->scratch().strdup(result));
}
/**
* f(s): value of POST variable
*/
SHORTHAND_BUILTIN(F, 1)
{
string name; ARG(0)->toString(name);
const char* v = module->POST(name);
return ShhValue(module->scratch().strdup(v));
}
/**
* q(s): value of GET variable
*/
SHORTHAND_BUILTIN(Q, 1)
{
string name; ARG(0)->toString(name);
const char* v = module->GET(name);
return ShhValue(module->scratch().strdup(v));
}
/**
* length(s): length of string expression
*/
SHORTHAND_BUILTIN(length, 1)
{
string value; ARG(0)->toString(value);
return value.length();
}
static int random_seed = 0;
SHORTHAND_BUILTIN(rand, 0)
{
int argc = args.size();
int lo, hi;
if (argc == 0)
{
lo = 0;
hi = 0x7FFFFFFF;
}
else if (argc == 1)
{
lo = 0;
hi = ARG(0)->toInt();
}
else if (argc >= 2)
{
lo = ARG(0)->toInt();
hi = ARG(1)->toInt();
}
#ifdef WIN32
if (random_seed == 0)
{
LARGE_INTEGER qw;
QueryPerformanceCounter(&qw);
srand( (int) qw.QuadPart );
random_seed = 1;
}
#else
if (random_seed == 0)
{
int foo = (int) alloca(4);
random_seed = getpid() ^ foo;
srand(random_seed);
}
#endif
int r = abs(rand()<<24|rand()<<12|rand());
int magnitude = hi - lo;
if (magnitude <= 0) return r;
else return lo + r%magnitude;
}
/**
* formats(f,precision)
*
* formats float number with specified precision (number of digits after decimal
* point).
*
* @return formatted string
*/
SHORTHAND_BUILTIN(format, 2)
{
double value = ARG(0)->toFloat();
int precision = ARG(1)->toInt();
string spec; spec.printf("%%.%df", precision);
ShhValue r(module->scratch().printf(spec.cstr(), value));
return r;
}
/*
* max(n1,n2,...) function
*/
SHORTHAND_BUILTIN(max, 2)
{
int result = ARG(0)->toInt();
for(int i=1,n=args.size(); i<n; i++)
{
int value = ARG(i)->toInt();
result = result > value ? result : value;
}
ShhValue r(result);
return r;
}
/*
* min(n1,n2,...) function
*/
SHORTHAND_BUILTIN(min, 2)
{
int result = ARG(0)->toInt();
for(int i=1,n=args.size(); i<n; i++)
{
int value = ARG(i)->toInt();
result = result < value ? result : value;
}
ShhValue r(result);
return r;
}
/*
* substring(s,start[,length) function
* @param s source string
* @param start starting index (from the end if negative)
* @param length length
*
*/
SHORTHAND_BUILTIN(substring, 2)
{
string s; ARG(0)->toString(s);
int start = ARG(1)->toInt();
int length = (args.size() > 2) ? ARG(2)->toInt() : -1;
if (length == -1) length = s.length();
string result;
if (start < 0)
{
start = s.length() + start;
int from = max(start, 0);
from = min(start, s.length());
int to = min(start+abs(length), s.length());
to = max(to, from);
result.set(s.cstr()+from, to-from);
}
else
{
int from = max(start, 0);
from = min(start, s.length());
int to = min(start+abs(length), s.length());
to = max(to, from);
result.set(s.cstr()+from, to-from);
}
ShhValue r(module->scratch().strdup(result));
return r;
}
/**
* strpos(haystack, needle).
*
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?