Arquivos
hhvm/hphp/runtime/ext/ext_misc.cpp
T
Paul Tarjan 99fcd4295e canonicalize \print_r to print_r at runtime
builds on D795509.

This copies all the callsites where we autoload.
2013-05-20 13:52:26 -07:00

388 linhas
11 KiB
C++

/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 1997-2010 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "hphp/runtime/ext/ext_misc.h"
#include "hphp/runtime/base/server/server_stats.h"
#include "hphp/runtime/base/util/exceptions.h"
#include "hphp/runtime/base/zend/zend_pack.h"
#include "hphp/runtime/base/hphp_system.h"
#include "hphp/runtime/base/runtime_option.h"
#include "hphp/runtime/base/strings.h"
#include "hphp/runtime/ext/ext_class.h"
#include "hphp/runtime/ext/ext_math.h"
#include "hphp/runtime/vm/bytecode.h"
#include "hphp/util/parser/scanner.h"
#include "hphp/runtime/base/class_info.h"
#include "hphp/runtime/vm/translator/translator.h"
#include "hphp/runtime/vm/translator/translator-inline.h"
namespace HPHP {
using Transl::CallerFrame;
// Make sure "tokenizer" gets added to the list of extensions
IMPLEMENT_DEFAULT_EXTENSION(tokenizer);
const double k_INF = std::numeric_limits<double>::infinity();
const double k_NAN = std::numeric_limits<double>::quiet_NaN();
///////////////////////////////////////////////////////////////////////////////
int64_t f_connection_aborted() {
return f_connection_status() == k_CONNECTION_ABORTED;
}
int64_t f_connection_status() {
return k_CONNECTION_NORMAL;
}
int64_t f_connection_timeout() {
return f_connection_status() == k_CONNECTION_TIMEOUT;
}
static Class* getClassByName(const char* name, int len) {
Class* cls = nullptr;
// translate "self" or "parent"
if (len == 4 && !memcmp(name, "self", 4)) {
cls = g_vmContext->getContextClass();
if (!cls) {
throw FatalErrorException("Cannot access self:: "
"when no class scope is active");
}
} else if (len == 6 && !memcmp(name, "parent", 6)) {
cls = g_vmContext->getParentContextClass();
if (!cls) {
throw FatalErrorException("Cannot access parent");
}
} else if (len == 6 && !memcmp(name, "static", 6)) {
CallerFrame cf;
auto ar = cf();
if (ar) {
if (ar->hasThis()) {
cls = ar->getThis()->getVMClass();
} else if (ar->hasClass()) {
cls = ar->getClass();
}
}
if (!cls) {
throw FatalErrorException("Cannot access static:: "
"when no class scope is active");
}
} else {
String className(name, len, CopyString);
cls = Unit::loadClass(className.get());
}
return cls;
}
Variant f_constant(CStrRef name) {
if (!name.get()) return uninit_null();
const char *data = name.data();
int len = name.length();
// slice off starting backslash
bool hadInitialBackslash = false;
if (len > 0 && data[0] == '\\') {
data += 1;
len -= 1;
hadInitialBackslash = true;
}
char *colon;
if ((colon = (char*)memchr(data, ':', len)) && colon[1] == ':') {
// class constant
int classNameLen = colon - data;
char *constantName = colon + 2;
Class* cls = getClassByName(data, classNameLen);
if (cls) {
String cnsName(constantName, data + len - constantName, CopyString);
TypedValue* tv = cls->clsCnsGet(cnsName.get());
if (tv) {
return tvAsCVarRef(tv);
}
}
raise_warning("Couldn't find constant %s", data);
} else {
TypedValue* cns;
if (hadInitialBackslash) {
String s(data, len, CopyString);
cns = Unit::loadCns(s.get());
} else {
cns = Unit::loadCns(name.get());
}
if (cns) return tvAsVariant(cns);
}
return uninit_null();
}
bool f_define(CStrRef name, CVarRef value,
bool case_insensitive /* = false */) {
if (case_insensitive) {
raise_warning(Strings::CONSTANTS_CASE_SENSITIVE);
}
return Unit::defCns(name.get(), value.getTypedAccessor());
}
bool f_defined(CStrRef name, bool autoload /* = true */) {
if (!name.get()) return false;
const char *data = name.data();
int len = name.length();
// slice off starting backslash
bool hadInitialBackslash = false;
if (len > 0 && data[0] == '\\') {
data += 1;
len -= 1;
hadInitialBackslash = true;
}
char *colon;
if ((colon = (char*)memchr(data, ':', len)) && colon[1] == ':') {
// class constant
int classNameLen = colon - data;
char *constantName = colon + 2;
Class* cls = getClassByName(data, classNameLen);
if (cls) {
String cnsName(constantName, data + len - constantName, CopyString);
return cls->clsCnsGet(cnsName.get());
}
return false;
} else {
auto* cb = autoload ? Unit::loadCns : Unit::lookupCns;
if (hadInitialBackslash) {
String s(data, len, CopyString);
return cb(s.get());
} else {
return cb(name.get());
}
}
}
Variant f_die(CVarRef status /* = null_variant */) {
return f_exit(status);
}
Variant f_exit(CVarRef status /* = null_variant */) {
if (status.isString()) {
echo(status.toString());
throw ExitException(0);
}
throw ExitException(status.toInt32());
}
Variant f_eval(CStrRef code_str) {
String prefixedCode = concat("<?php ", code_str);
Unit* unit = g_vmContext->compileEvalString(prefixedCode.get());
TypedValue retVal;
g_vmContext->invokeUnit(&retVal, unit);
return tvAsVariant(&retVal);
}
Variant f_get_browser(CStrRef user_agent /* = null_string */,
bool return_array /* = false */) {
throw NotSupportedException(__func__, "bad idea");
}
void f___halt_compiler() {
// do nothing
}
Variant f_highlight_file(CStrRef filename, bool ret /* = false */) {
throw NotSupportedException(__func__, "PHP specific");
}
Variant f_show_source(CStrRef filename, bool ret /* = false */) {
throw NotSupportedException(__func__, "PHP specific");
}
Variant f_highlight_string(CStrRef str, bool ret /* = false */) {
throw NotSupportedException(__func__, "PHP specific");
}
int64_t f_ignore_user_abort(bool setting /* = false */) {
return 0;
}
Variant f_pack(int _argc, CStrRef format, CArrRef _argv /* = null_array */) {
return ZendPack().pack(format, _argv);
}
bool f_php_check_syntax(CStrRef filename, VRefParam error_message /* = null */) {
throw NotSupportedException(__func__, "PHP specific");
}
String f_php_strip_whitespace(CStrRef filename) {
throw NotSupportedException(__func__, "PHP specific");
}
int64_t f_sleep(int seconds) {
IOStatusHelper io("sleep");
sleep(seconds);
return 0;
}
void f_usleep(int micro_seconds) {
IOStatusHelper io("usleep");
usleep(micro_seconds);
}
static const StaticString s_seconds("seconds");
static const StaticString s_nanoseconds("nanoseconds");
Variant f_time_nanosleep(int seconds, int nanoseconds) {
if (seconds < 0) {
throw_invalid_argument("seconds: cannot be negative");
return false;
}
if (nanoseconds < 0 || nanoseconds > 999999999) {
throw_invalid_argument("nanoseconds: has to be 0 to 999999999");
return false;
}
struct timespec req, rem;
req.tv_sec = (time_t)seconds;
req.tv_nsec = nanoseconds;
IOStatusHelper io("nanosleep");
if (!nanosleep(&req, &rem)) {
return true;
}
if (errno == EINTR) {
return CREATE_MAP2(s_seconds, (int64_t)rem.tv_sec,
s_nanoseconds, (int64_t)rem.tv_nsec);
}
return false;
}
bool f_time_sleep_until(double timestamp) {
struct timeval tm;
if (gettimeofday((struct timeval *)&tm, NULL) != 0) {
return false;
}
double c_ts = (double)(timestamp - tm.tv_sec - tm.tv_usec / 1000000.0);
if (c_ts < 0) {
throw_invalid_argument
("timestamp: Sleep until to time is less than current time");
return false;
}
struct timespec req, rem;
req.tv_sec = (time_t)c_ts;
req.tv_nsec = (long)((c_ts - req.tv_sec) * 1000000000.0);
IOStatusHelper io("nanosleep");
while (nanosleep(&req, &rem)) {
if (errno != EINTR) return false;
req.tv_sec = rem.tv_sec;
req.tv_nsec = rem.tv_nsec;
}
return true;
}
String f_uniqid(CStrRef prefix /* = null_string */,
bool more_entropy /* = false */) {
if (!more_entropy) {
usleep(1);
}
struct timeval tv;
gettimeofday((struct timeval *)&tv, NULL);
int sec = (int)tv.tv_sec;
int usec = (int)(tv.tv_usec % 0x100000);
char uniqid[256];
if (more_entropy) {
snprintf(uniqid, sizeof(uniqid), "%s%08x%05x%.8F",
prefix.c_str(), sec, usec, math_combined_lcg() * 10);
} else {
snprintf(uniqid, sizeof(uniqid), "%s%08x%05x",
prefix.c_str(), sec, usec);
}
return String(uniqid, CopyString);
}
Variant f_unpack(CStrRef format, CStrRef data) {
return ZendPack().unpack(format, data);
}
Array f_sys_getloadavg() {
double load[3];
getloadavg(load, 3);
return CREATE_VECTOR3(load[0], load[1], load[2]);
}
Array f_token_get_all(CStrRef source) {
Scanner scanner(source.data(), source.size(),
RuntimeOption::GetScannerType() | Scanner::ReturnAllTokens);
ScannerToken tok;
Location loc;
int tokid;
Array res;
while ((tokid = scanner.getNextToken(tok, loc))) {
if (tokid < 256) {
res.append(String::FromChar((char)tokid));
} else {
Array p = CREATE_VECTOR3(tokid, String(tok.text()), loc.line0);
res.append(p);
}
}
return res;
}
String f_token_name(int64_t token) {
#undef YYTOKENTYPE
#ifdef YYTOKEN_MAP
#undef YYTOKEN_MAP
#undef YYTOKEN
#endif
#define YYTOKEN(num, name) #name
#define YYTOKEN_MAP static const char *names[] =
#include "hphp/util/parser/hphp.tab.hpp"
#undef YYTOKEN_MAP
#undef YYTOKEN
if (token >= YYTOKEN_MIN && token <= YYTOKEN_MAX) {
const char *name = names[token - YYTOKEN_MIN];
if (strncmp(name, "T_HPHP_", sizeof("T_HPHP_") - 1)) {
return name;
}
}
return "UNKNOWN";
}
static const StaticString s_marauder("I solemnly swear that I am up to no good.");
Variant f_hphp_process_abort(CVarRef magic) {
if (magic.equal(s_marauder)) {
*((int*)0) = 0xdead;
}
return null_variant;
}
String f_hphp_to_string(CVarRef v) {
return v.toString();
}
///////////////////////////////////////////////////////////////////////////////
}