PageRenderTime 27ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/src/runtime/ext/ext_misc.cpp

https://github.com/kevlund/hiphop-php
C++ | 339 lines | 264 code | 46 blank | 29 comment | 59 complexity | c13720b36b9361c0d43fbde289c9ae6e MD5 | raw file
  1. /*
  2. +----------------------------------------------------------------------+
  3. | HipHop for PHP |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 2010- 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. +----------------------------------------------------------------------+
  16. */
  17. #include <runtime/ext/ext_misc.h>
  18. #include <runtime/ext/ext_class.h>
  19. #include <runtime/ext/ext_math.h>
  20. #include <runtime/base/util/exceptions.h>
  21. #include <runtime/base/zend/zend_pack.h>
  22. #include <runtime/base/hphp_system.h>
  23. #include <runtime/base/runtime_option.h>
  24. #include <runtime/base/server/server_stats.h>
  25. #include <util/parser/scanner.h>
  26. namespace HPHP {
  27. using namespace std;
  28. // Make sure "tokenizer" gets added to the list of extensions
  29. IMPLEMENT_DEFAULT_EXTENSION(tokenizer);
  30. const double k_INF = numeric_limits<double>::infinity();
  31. const double k_NAN = numeric_limits<double>::quiet_NaN();
  32. ///////////////////////////////////////////////////////////////////////////////
  33. int f_connection_aborted() {
  34. return f_connection_status() == k_CONNECTION_ABORTED;
  35. }
  36. int f_connection_status() {
  37. return k_CONNECTION_NORMAL;
  38. }
  39. int f_connection_timeout() {
  40. return f_connection_status() == k_CONNECTION_TIMEOUT;
  41. }
  42. Variant f_constant(CStrRef name) {
  43. const char *data = name.data();
  44. int len = name.length();
  45. char *colon;
  46. if ((colon = (char*)memchr(data, ':', len)) && colon[1] == ':') {
  47. // class constant
  48. int classNameLen = colon - data;
  49. char *constantName = colon + 2;
  50. String className(data, classNameLen, CopyString);
  51. // translate "self" or "parent"
  52. if (className == "self") {
  53. String this_class = FrameInjection::GetClassName(true);
  54. if (this_class.empty()) {
  55. throw FatalErrorException("Cannot access self:: "
  56. "when no class scope is active");
  57. } else {
  58. className = this_class;
  59. }
  60. } else if (className == "parent") {
  61. CStrRef parent_class = FrameInjection::GetParentClassName(true);
  62. if (parent_class.empty()) {
  63. throw FatalErrorException("Cannot access parent");
  64. } else {
  65. className = parent_class;
  66. }
  67. }
  68. // taking care of volatile class
  69. if (class_exists(className)) {
  70. return get_class_constant(className, constantName, false);
  71. } else {
  72. return null;
  73. }
  74. } else {
  75. const ClassInfo::ConstantInfo *cinfo = ClassInfo::FindConstant(name);
  76. // system/uniquely defined scalar constant (must be valid)
  77. if (cinfo) return cinfo->getValue();
  78. // dynamic/redeclared constant
  79. return ((Globals*)get_global_variables())->getConstant(name.data());
  80. }
  81. }
  82. bool f_define(CStrRef name, CVarRef value,
  83. bool case_insensitive /* = false */) {
  84. ASSERT(false); // define() should be turned into constant definition by HPHP
  85. return false;
  86. }
  87. bool f_defined(CStrRef name) {
  88. const char *data = name.data();
  89. int len = name.length();
  90. char *colon;
  91. if ((colon = (char*)memchr(data, ':', len)) && colon[1] == ':') {
  92. // class constant
  93. int classNameLen = colon - data;
  94. char *constantName = colon + 2;
  95. String className(data, classNameLen, CopyString);
  96. // translate "self" or "parent"
  97. if (className == "self") {
  98. String this_class = FrameInjection::GetClassName(true);
  99. if (this_class.empty()) {
  100. throw FatalErrorException("Cannot access self:: "
  101. "when no class scope is active");
  102. } else {
  103. className = this_class;
  104. }
  105. } else if (className == "parent") {
  106. CStrRef parent_class = FrameInjection::GetParentClassName(true);
  107. if (parent_class.empty()) {
  108. throw FatalErrorException("Cannot access parent");
  109. } else {
  110. className = parent_class;
  111. }
  112. }
  113. if (class_exists(className)) { // taking care of volatile class
  114. const ClassInfo *info;
  115. for (String parentClass = className;
  116. !parentClass.empty();
  117. parentClass = info->getParentClass()) {
  118. info = ClassInfo::FindClass(parentClass);
  119. if (!info) {
  120. ASSERT(false);
  121. }
  122. if (info->hasConstant(constantName)) return true;
  123. }
  124. return false;
  125. } else {
  126. return false;
  127. }
  128. } else {
  129. // system/uniquely defined scalar constant
  130. if (ClassInfo::FindConstant(name)) return true;
  131. // dynamic/redeclared constant
  132. return ((Globals*)get_global_variables())->defined(name);
  133. }
  134. }
  135. Variant f_die(CVarRef status /* = null_variant */) {
  136. return f_exit(status);
  137. }
  138. Variant f_exit(CVarRef status /* = null_variant */) {
  139. if (status.isString()) {
  140. echo(status.toString());
  141. throw ExitException(0);
  142. }
  143. throw ExitException(status.toInt32());
  144. }
  145. Variant f_eval(CStrRef code_str) {
  146. throw NotSupportedException(__func__, "rebuild with eval mode");
  147. }
  148. Variant f_get_browser(CStrRef user_agent /* = null_string */,
  149. bool return_array /* = false */) {
  150. throw NotSupportedException(__func__, "bad idea");
  151. }
  152. void f___halt_compiler() {
  153. // do nothing
  154. }
  155. Variant f_highlight_file(CStrRef filename, bool ret /* = false */) {
  156. throw NotSupportedException(__func__, "PHP specific");
  157. }
  158. Variant f_show_source(CStrRef filename, bool ret /* = false */) {
  159. throw NotSupportedException(__func__, "PHP specific");
  160. }
  161. Variant f_highlight_string(CStrRef str, bool ret /* = false */) {
  162. throw NotSupportedException(__func__, "PHP specific");
  163. }
  164. int f_ignore_user_abort(bool setting /* = false */) {
  165. return 0;
  166. }
  167. Variant f_pack(int _argc, CStrRef format, CArrRef _argv /* = null_array */) {
  168. return ZendPack().pack(format, _argv);
  169. }
  170. bool f_php_check_syntax(CStrRef filename, VRefParam error_message /* = null */) {
  171. throw NotSupportedException(__func__, "PHP specific");
  172. }
  173. String f_php_strip_whitespace(CStrRef filename) {
  174. throw NotSupportedException(__func__, "PHP specific");
  175. }
  176. int f_sleep(int seconds) {
  177. IOStatusHelper io("sleep");
  178. sleep(seconds);
  179. return 0;
  180. }
  181. void f_usleep(int micro_seconds) {
  182. IOStatusHelper io("usleep");
  183. usleep(micro_seconds);
  184. }
  185. Variant f_time_nanosleep(int seconds, int nanoseconds) {
  186. if (seconds < 0) {
  187. throw_invalid_argument("seconds: cannot be negative");
  188. return false;
  189. }
  190. if (nanoseconds < 0 || nanoseconds > 999999999) {
  191. throw_invalid_argument("nanoseconds: has to be 0 to 999999999");
  192. return false;
  193. }
  194. struct timespec req, rem;
  195. req.tv_sec = (time_t)seconds;
  196. req.tv_nsec = nanoseconds;
  197. IOStatusHelper io("nanosleep");
  198. if (!nanosleep(&req, &rem)) {
  199. return true;
  200. }
  201. if (errno == EINTR) {
  202. return CREATE_MAP2("seconds", (int64)rem.tv_sec,
  203. "nanoseconds", (int64)rem.tv_nsec);
  204. }
  205. return false;
  206. }
  207. bool f_time_sleep_until(double timestamp) {
  208. struct timeval tm;
  209. if (gettimeofday((struct timeval *)&tm, NULL) != 0) {
  210. return false;
  211. }
  212. double c_ts = (double)(timestamp - tm.tv_sec - tm.tv_usec / 1000000.0);
  213. if (c_ts < 0) {
  214. throw_invalid_argument
  215. ("timestamp: Sleep until to time is less than current time");
  216. return false;
  217. }
  218. struct timespec req, rem;
  219. req.tv_sec = (time_t)c_ts;
  220. req.tv_nsec = (long)((c_ts - req.tv_sec) * 1000000000.0);
  221. IOStatusHelper io("nanosleep");
  222. while (nanosleep(&req, &rem)) {
  223. if (errno != EINTR) return false;
  224. req.tv_sec = rem.tv_sec;
  225. req.tv_nsec = rem.tv_nsec;
  226. }
  227. return true;
  228. }
  229. String f_uniqid(CStrRef prefix /* = null_string */,
  230. bool more_entropy /* = false */) {
  231. if (!more_entropy) {
  232. usleep(1);
  233. }
  234. struct timeval tv;
  235. gettimeofday((struct timeval *)&tv, NULL);
  236. int sec = (int)tv.tv_sec;
  237. int usec = (int)(tv.tv_usec % 0x100000);
  238. char uniqid[256];
  239. if (more_entropy) {
  240. snprintf(uniqid, sizeof(uniqid), "%s%08x%05x%.8F",
  241. (const char *)prefix, sec, usec, math_combined_lcg() * 10);
  242. } else {
  243. snprintf(uniqid, sizeof(uniqid), "%s%08x%05x",
  244. (const char *)prefix, sec, usec);
  245. }
  246. return String(uniqid, CopyString);
  247. }
  248. Variant f_unpack(CStrRef format, CStrRef data) {
  249. return ZendPack().unpack(format, data);
  250. }
  251. Array f_sys_getloadavg() {
  252. double load[3];
  253. getloadavg(load, 3);
  254. return CREATE_VECTOR3(load[0], load[1], load[2]);
  255. }
  256. Array f_token_get_all(CStrRef source) {
  257. Scanner scanner(source.data(), source.size(),
  258. Scanner::AllowShortTags | Scanner::ReturnAllTokens);
  259. ScannerToken tok;
  260. Location loc;
  261. int tokid;
  262. Array res;
  263. while ((tokid = scanner.getNextToken(tok, loc))) {
  264. if (tokid < 256) {
  265. res.append(String::FromChar((char)tokid));
  266. } else {
  267. Array p = CREATE_VECTOR3(tokid, String(tok.text()), loc.line0);
  268. res.append(p);
  269. }
  270. }
  271. return res;
  272. }
  273. String f_token_name(int64 token) {
  274. #undef YYTOKENTYPE
  275. #ifdef YYTOKEN_MAP
  276. #undef YYTOKEN_MAP
  277. #undef YYTOKEN
  278. #endif
  279. #define YYTOKEN(num, name) #name
  280. #define YYTOKEN_MAP static const char *names[] =
  281. #include <util/parser/hphp.tab.hpp>
  282. #undef YYTOKEN_MAP
  283. #undef YYTOKEN
  284. if (token >= YYTOKEN_MIN && token <= YYTOKEN_MAX) {
  285. const char *name = names[token - YYTOKEN_MIN];
  286. if (strncmp(name, "T_HPHP_", sizeof("T_HPHP_") - 1)) {
  287. return name;
  288. }
  289. }
  290. return "UNKNOWN";
  291. }
  292. ///////////////////////////////////////////////////////////////////////////////
  293. }