2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
6 | Copyright (c) 1997-2010 The PHP Group |
7 +----------------------------------------------------------------------+
8 | This source file is subject to version 3.01 of the PHP license, |
9 | that is bundled with this package in the file LICENSE, and is |
10 | available through the world-wide-web at the following url: |
11 | http://www.php.net/license/3_01.txt |
12 | If you did not receive a copy of the PHP license and are unable to |
13 | obtain it through the world-wide-web, please send a note to |
14 | license@php.net so we can mail you a copy immediately. |
15 +----------------------------------------------------------------------+
18 #include "hphp/runtime/ext/ext_misc.h"
20 #include "hphp/runtime/base/server/server_stats.h"
21 #include "hphp/runtime/base/util/exceptions.h"
22 #include "hphp/runtime/base/zend/zend_pack.h"
23 #include "hphp/runtime/base/hphp_system.h"
24 #include "hphp/runtime/base/runtime_option.h"
25 #include "hphp/runtime/base/strings.h"
26 #include "hphp/runtime/ext/ext_class.h"
27 #include "hphp/runtime/ext/ext_math.h"
28 #include "hphp/runtime/vm/bytecode.h"
29 #include "hphp/util/parser/scanner.h"
30 #include "hphp/runtime/base/class_info.h"
31 #include "hphp/runtime/vm/jit/translator.h"
32 #include "hphp/runtime/vm/jit/translator-inline.h"
36 using Transl::CallerFrame
;
38 // Make sure "tokenizer" gets added to the list of extensions
39 IMPLEMENT_DEFAULT_EXTENSION(tokenizer
);
41 const double k_INF
= std::numeric_limits
<double>::infinity();
42 const double k_NAN
= std::numeric_limits
<double>::quiet_NaN();
44 ///////////////////////////////////////////////////////////////////////////////
46 int64_t f_connection_aborted() {
47 return f_connection_status() == k_CONNECTION_ABORTED
;
50 int64_t f_connection_status() {
51 return k_CONNECTION_NORMAL
;
54 int64_t f_connection_timeout() {
55 return f_connection_status() == k_CONNECTION_TIMEOUT
;
58 static Class
* getClassByName(const char* name
, int len
) {
60 // translate "self" or "parent"
61 if (len
== 4 && !memcmp(name
, "self", 4)) {
62 cls
= g_vmContext
->getContextClass();
64 throw FatalErrorException("Cannot access self:: "
65 "when no class scope is active");
67 } else if (len
== 6 && !memcmp(name
, "parent", 6)) {
68 cls
= g_vmContext
->getParentContextClass();
70 throw FatalErrorException("Cannot access parent");
72 } else if (len
== 6 && !memcmp(name
, "static", 6)) {
77 cls
= ar
->getThis()->getVMClass();
78 } else if (ar
->hasClass()) {
83 throw FatalErrorException("Cannot access static:: "
84 "when no class scope is active");
87 String
className(name
, len
, CopyString
);
88 cls
= Unit::loadClass(className
.get());
93 Variant
f_constant(CStrRef name
) {
94 if (!name
.get()) return uninit_null();
95 const char *data
= name
.data();
96 int len
= name
.length();
98 // slice off starting backslash
99 bool hadInitialBackslash
= false;
100 if (len
> 0 && data
[0] == '\\') {
103 hadInitialBackslash
= true;
107 if ((colon
= (char*)memchr(data
, ':', len
)) && colon
[1] == ':') {
109 int classNameLen
= colon
- data
;
110 char *constantName
= colon
+ 2;
111 Class
* cls
= getClassByName(data
, classNameLen
);
113 String
cnsName(constantName
, data
+ len
- constantName
, CopyString
);
114 TypedValue
* tv
= cls
->clsCnsGet(cnsName
.get());
116 return tvAsCVarRef(tv
);
119 raise_warning("Couldn't find constant %s", data
);
122 if (hadInitialBackslash
) {
123 String
s(data
, len
, CopyString
);
124 cns
= Unit::loadCns(s
.get());
126 cns
= Unit::loadCns(name
.get());
128 if (cns
) return tvAsVariant(cns
);
131 return uninit_null();
134 bool f_define(CStrRef name
, CVarRef value
,
135 bool case_insensitive
/* = false */) {
136 if (case_insensitive
) {
137 raise_warning(Strings::CONSTANTS_CASE_SENSITIVE
);
139 return Unit::defCns(name
.get(), value
.asCell());
142 bool f_defined(CStrRef name
, bool autoload
/* = true */) {
143 if (!name
.get()) return false;
144 const char *data
= name
.data();
145 int len
= name
.length();
147 // slice off starting backslash
148 bool hadInitialBackslash
= false;
149 if (len
> 0 && data
[0] == '\\') {
152 hadInitialBackslash
= true;
156 if ((colon
= (char*)memchr(data
, ':', len
)) && colon
[1] == ':') {
158 int classNameLen
= colon
- data
;
159 char *constantName
= colon
+ 2;
160 Class
* cls
= getClassByName(data
, classNameLen
);
162 String
cnsName(constantName
, data
+ len
- constantName
, CopyString
);
163 return cls
->clsCnsGet(cnsName
.get());
167 auto* cb
= autoload
? Unit::loadCns
: Unit::lookupCns
;
168 if (hadInitialBackslash
) {
169 String
s(data
, len
, CopyString
);
172 return cb(name
.get());
177 Variant
f_die(CVarRef status
/* = null_variant */) {
178 return f_exit(status
);
181 Variant
f_exit(CVarRef status
/* = null_variant */) {
182 if (status
.isString()) {
183 echo(status
.toString());
184 throw ExitException(0);
186 throw ExitException(status
.toInt32());
189 Variant
f_eval(CStrRef code_str
) {
190 String prefixedCode
= concat("<?php ", code_str
);
191 Unit
* unit
= g_vmContext
->compileEvalString(prefixedCode
.get());
193 g_vmContext
->invokeUnit(&retVal
, unit
);
194 return tvAsVariant(&retVal
);
197 Variant
f_get_browser(CStrRef user_agent
/* = null_string */,
198 bool return_array
/* = false */) {
199 throw NotSupportedException(__func__
, "bad idea");
202 void f___halt_compiler() {
206 Variant
f_highlight_file(CStrRef filename
, bool ret
/* = false */) {
207 throw NotSupportedException(__func__
, "PHP specific");
210 Variant
f_show_source(CStrRef filename
, bool ret
/* = false */) {
211 throw NotSupportedException(__func__
, "PHP specific");
214 Variant
f_highlight_string(CStrRef str
, bool ret
/* = false */) {
215 throw NotSupportedException(__func__
, "PHP specific");
218 int64_t f_ignore_user_abort(bool setting
/* = false */) {
222 Variant
f_pack(int _argc
, CStrRef format
, CArrRef _argv
/* = null_array */) {
223 return ZendPack().pack(format
, _argv
);
226 bool f_php_check_syntax(CStrRef filename
, VRefParam error_message
/* = null */) {
227 throw NotSupportedException(__func__
, "PHP specific");
230 String
f_php_strip_whitespace(CStrRef filename
) {
231 throw NotSupportedException(__func__
, "PHP specific");
234 int64_t f_sleep(int seconds
) {
235 IOStatusHelper
io("sleep");
240 void f_usleep(int micro_seconds
) {
241 IOStatusHelper
io("usleep");
242 usleep(micro_seconds
);
245 static const StaticString
s_seconds("seconds");
246 static const StaticString
s_nanoseconds("nanoseconds");
248 Variant
f_time_nanosleep(int seconds
, int nanoseconds
) {
250 throw_invalid_argument("seconds: cannot be negative");
253 if (nanoseconds
< 0 || nanoseconds
> 999999999) {
254 throw_invalid_argument("nanoseconds: has to be 0 to 999999999");
258 struct timespec req
, rem
;
259 req
.tv_sec
= (time_t)seconds
;
260 req
.tv_nsec
= nanoseconds
;
262 IOStatusHelper
io("nanosleep");
263 if (!nanosleep(&req
, &rem
)) {
266 if (errno
== EINTR
) {
267 return CREATE_MAP2(s_seconds
, (int64_t)rem
.tv_sec
,
268 s_nanoseconds
, (int64_t)rem
.tv_nsec
);
273 bool f_time_sleep_until(double timestamp
) {
275 if (gettimeofday((struct timeval
*)&tm
, NULL
) != 0) {
279 double c_ts
= (double)(timestamp
- tm
.tv_sec
- tm
.tv_usec
/ 1000000.0);
281 throw_invalid_argument
282 ("timestamp: Sleep until to time is less than current time");
286 struct timespec req
, rem
;
287 req
.tv_sec
= (time_t)c_ts
;
288 req
.tv_nsec
= (long)((c_ts
- req
.tv_sec
) * 1000000000.0);
290 IOStatusHelper
io("nanosleep");
291 while (nanosleep(&req
, &rem
)) {
292 if (errno
!= EINTR
) return false;
293 req
.tv_sec
= rem
.tv_sec
;
294 req
.tv_nsec
= rem
.tv_nsec
;
300 String
f_uniqid(CStrRef prefix
/* = null_string */,
301 bool more_entropy
/* = false */) {
307 gettimeofday((struct timeval
*)&tv
, NULL
);
308 int sec
= (int)tv
.tv_sec
;
309 int usec
= (int)(tv
.tv_usec
% 0x100000);
313 snprintf(uniqid
, sizeof(uniqid
), "%s%08x%05x%.8F",
314 prefix
.c_str(), sec
, usec
, math_combined_lcg() * 10);
316 snprintf(uniqid
, sizeof(uniqid
), "%s%08x%05x",
317 prefix
.c_str(), sec
, usec
);
319 return String(uniqid
, CopyString
);
322 Variant
f_unpack(CStrRef format
, CStrRef data
) {
323 return ZendPack().unpack(format
, data
);
326 Array
f_sys_getloadavg() {
329 return CREATE_VECTOR3(load
[0], load
[1], load
[2]);
333 Array
f_token_get_all(CStrRef source
) {
334 Scanner
scanner(source
.data(), source
.size(),
335 RuntimeOption::GetScannerType() | Scanner::ReturnAllTokens
);
340 while ((tokid
= scanner
.getNextToken(tok
, loc
))) {
342 res
.append(String::FromChar((char)tokid
));
344 Array p
= CREATE_VECTOR3(tokid
, String(tok
.text()), loc
.line0
);
351 String
f_token_name(int64_t token
) {
358 #define YYTOKEN(num, name) #name
359 #define YYTOKEN_MAP static const char *names[] =
360 #include "hphp/util/parser/hphp.tab.hpp"
364 if (token
>= YYTOKEN_MIN
&& token
<= YYTOKEN_MAX
) {
365 const char *name
= names
[token
- YYTOKEN_MIN
];
366 if (strncmp(name
, "T_HPHP_", sizeof("T_HPHP_") - 1)) {
373 String
f_hphp_to_string(CVarRef v
) {
377 ///////////////////////////////////////////////////////////////////////////////