Clean up VectorEffects::init
[hiphop-php.git] / hphp / runtime / ext / ext_misc.cpp
blob43b6f2ef4d8f6ec58e7cb826497373e2956ad660
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
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"
34 namespace HPHP {
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) {
59 Class* cls = nullptr;
60 // translate "self" or "parent"
61 if (len == 4 && !memcmp(name, "self", 4)) {
62 cls = g_vmContext->getContextClass();
63 if (!cls) {
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();
69 if (!cls) {
70 throw FatalErrorException("Cannot access parent");
72 } else if (len == 6 && !memcmp(name, "static", 6)) {
73 CallerFrame cf;
74 auto ar = cf();
75 if (ar) {
76 if (ar->hasThis()) {
77 cls = ar->getThis()->getVMClass();
78 } else if (ar->hasClass()) {
79 cls = ar->getClass();
82 if (!cls) {
83 throw FatalErrorException("Cannot access static:: "
84 "when no class scope is active");
86 } else {
87 String className(name, len, CopyString);
88 cls = Unit::loadClass(className.get());
90 return cls;
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] == '\\') {
101 data += 1;
102 len -= 1;
103 hadInitialBackslash = true;
106 char *colon;
107 if ((colon = (char*)memchr(data, ':', len)) && colon[1] == ':') {
108 // class constant
109 int classNameLen = colon - data;
110 char *constantName = colon + 2;
111 Class* cls = getClassByName(data, classNameLen);
112 if (cls) {
113 String cnsName(constantName, data + len - constantName, CopyString);
114 TypedValue* tv = cls->clsCnsGet(cnsName.get());
115 if (tv) {
116 return tvAsCVarRef(tv);
119 raise_warning("Couldn't find constant %s", data);
120 } else {
121 TypedValue* cns;
122 if (hadInitialBackslash) {
123 String s(data, len, CopyString);
124 cns = Unit::loadCns(s.get());
125 } else {
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] == '\\') {
150 data += 1;
151 len -= 1;
152 hadInitialBackslash = true;
155 char *colon;
156 if ((colon = (char*)memchr(data, ':', len)) && colon[1] == ':') {
157 // class constant
158 int classNameLen = colon - data;
159 char *constantName = colon + 2;
160 Class* cls = getClassByName(data, classNameLen);
161 if (cls) {
162 String cnsName(constantName, data + len - constantName, CopyString);
163 return cls->clsCnsGet(cnsName.get());
165 return false;
166 } else {
167 auto* cb = autoload ? Unit::loadCns : Unit::lookupCns;
168 if (hadInitialBackslash) {
169 String s(data, len, CopyString);
170 return cb(s.get());
171 } else {
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());
192 TypedValue retVal;
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() {
203 // do nothing
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 */) {
219 return 0;
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");
236 sleep(seconds);
237 return 0;
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) {
249 if (seconds < 0) {
250 throw_invalid_argument("seconds: cannot be negative");
251 return false;
253 if (nanoseconds < 0 || nanoseconds > 999999999) {
254 throw_invalid_argument("nanoseconds: has to be 0 to 999999999");
255 return false;
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)) {
264 return true;
266 if (errno == EINTR) {
267 return CREATE_MAP2(s_seconds, (int64_t)rem.tv_sec,
268 s_nanoseconds, (int64_t)rem.tv_nsec);
270 return false;
273 bool f_time_sleep_until(double timestamp) {
274 struct timeval tm;
275 if (gettimeofday((struct timeval *)&tm, NULL) != 0) {
276 return false;
279 double c_ts = (double)(timestamp - tm.tv_sec - tm.tv_usec / 1000000.0);
280 if (c_ts < 0) {
281 throw_invalid_argument
282 ("timestamp: Sleep until to time is less than current time");
283 return false;
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;
297 return true;
300 String f_uniqid(CStrRef prefix /* = null_string */,
301 bool more_entropy /* = false */) {
302 if (!more_entropy) {
303 usleep(1);
306 struct timeval tv;
307 gettimeofday((struct timeval *)&tv, NULL);
308 int sec = (int)tv.tv_sec;
309 int usec = (int)(tv.tv_usec % 0x100000);
311 char uniqid[256];
312 if (more_entropy) {
313 snprintf(uniqid, sizeof(uniqid), "%s%08x%05x%.8F",
314 prefix.c_str(), sec, usec, math_combined_lcg() * 10);
315 } else {
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() {
327 double load[3];
328 getloadavg(load, 3);
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);
336 ScannerToken tok;
337 Location loc;
338 int tokid;
339 Array res;
340 while ((tokid = scanner.getNextToken(tok, loc))) {
341 if (tokid < 256) {
342 res.append(String::FromChar((char)tokid));
343 } else {
344 Array p = CREATE_VECTOR3(tokid, String(tok.text()), loc.line0);
345 res.append(p);
348 return res;
351 String f_token_name(int64_t token) {
353 #undef YYTOKENTYPE
354 #ifdef YYTOKEN_MAP
355 #undef YYTOKEN_MAP
356 #undef YYTOKEN
357 #endif
358 #define YYTOKEN(num, name) #name
359 #define YYTOKEN_MAP static const char *names[] =
360 #include "hphp/util/parser/hphp.tab.hpp"
361 #undef YYTOKEN_MAP
362 #undef YYTOKEN
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)) {
367 return name;
370 return "UNKNOWN";
373 String f_hphp_to_string(CVarRef v) {
374 return v.toString();
377 ///////////////////////////////////////////////////////////////////////////////