Variant f_range(CVarRef low, CVarRef high, CVarRef step /* = 1 */) { bool is_step_double = false; double dstep = 1.0; if (step.isDouble()) { dstep = step.toDouble(); is_step_double = true; } else if (step.isString()) { int64_t sn; double sd; DataType stype = step.toString()->isNumericWithVal(sn, sd, 0); if (stype == KindOfDouble) { is_step_double = true; dstep = sd; } else if (stype == KindOfInt64) { dstep = (double)sn; } else { dstep = step.toDouble(); } } else { dstep = step.toDouble(); } /* We only want positive step values. */ if (dstep < 0.0) dstep *= -1; if (low.isString() && high.isString()) { String slow = low.toString(); String shigh = high.toString(); if (slow.size() >= 1 && shigh.size() >=1) { int64_t n1, n2; double d1, d2; DataType type1 = slow->isNumericWithVal(n1, d1, 0); DataType type2 = shigh->isNumericWithVal(n2, d2, 0); if (type1 == KindOfDouble || type2 == KindOfDouble || is_step_double) { if (type1 != KindOfDouble) d1 = slow.toDouble(); if (type2 != KindOfDouble) d2 = shigh.toDouble(); return ArrayUtil::Range(d1, d2, dstep); } int64_t lstep = (int64_t) dstep; if (type1 == KindOfInt64 || type2 == KindOfInt64) { if (type1 != KindOfInt64) n1 = slow.toInt64(); if (type2 != KindOfInt64) n2 = shigh.toInt64(); return ArrayUtil::Range((double)n1, (double)n2, lstep); } return ArrayUtil::Range((unsigned char)slow.charAt(0), (unsigned char)shigh.charAt(0), lstep); } } if (low.is(KindOfDouble) || high.is(KindOfDouble) || is_step_double) { return ArrayUtil::Range(low.toDouble(), high.toDouble(), dstep); } int64_t lstep = (int64_t) dstep; return ArrayUtil::Range(low.toDouble(), high.toDouble(), lstep); }
bool BuiltinSymbols::Load(AnalysisResultPtr ar, bool extOnly /* = false */) { if (Loaded) return true; Loaded = true; // load extension functions first, so system/classes may call them ParseExtFunctions(ar, ExtensionFunctions, false); AnalysisResultPtr ar2 = AnalysisResultPtr(new AnalysisResult()); s_variables = VariableTablePtr(new VariableTable(*ar2.get())); s_constants = ConstantTablePtr(new ConstantTable(*ar2.get())); // parse all PHP files under system/classes if (!extOnly) { ar = AnalysisResultPtr(new AnalysisResult()); ar->loadBuiltinFunctions(); string slib = systemlib_path(); if (slib.empty()) { for (const char **cls = SystemClasses; *cls; cls++) { string phpBaseName = "/system/classes/"; phpBaseName += *cls; phpBaseName += ".php"; Parse(ar, phpBaseName, Option::GetSystemRoot() + phpBaseName); } } else { Parse(ar, slib, slib); } ar->analyzeProgram(true); ar->inferTypes(); const StringToFileScopePtrMap &files = ar->getAllFiles(); for (StringToFileScopePtrMap::const_iterator iterFile = files.begin(); iterFile != files.end(); iterFile++) { const StringToClassScopePtrVecMap &classes = iterFile->second->getClasses(); for (StringToClassScopePtrVecMap::const_iterator iter = classes.begin(); iter != classes.end(); ++iter) { assert(iter->second.size() == 1); iter->second[0]->setSystem(); assert(!s_classes[iter->first]); s_classes[iter->first] = iter->second[0]; } } } else { NoSuperGlobals = true; } // load extension constants, classes and dynamics ParseExtConsts(ar, ExtensionConsts, false); ParseExtClasses(ar, ExtensionClasses, false); for (unsigned int i = 0; i < Option::SepExtensions.size(); i++) { Option::SepExtensionOptions &options = Option::SepExtensions[i]; string soname = options.soname; if (soname.empty()) { soname = string("lib") + options.name + ".so"; } if (!options.lib_path.empty()) { soname = options.lib_path + "/" + soname; } if (!LoadSepExtensionSymbols(ar, options.name, soname)) { return false; } } if (!extOnly) { Array constants = ClassInfo::GetSystemConstants(); LocationPtr loc(new Location); for (ArrayIter it = constants.begin(); it; ++it) { CVarRef key = it.first(); if (!key.isString()) continue; std::string name = key.toCStrRef().data(); if (s_constants->getSymbol(name)) continue; if (name == "true" || name == "false" || name == "null") continue; CVarRef value = it.secondRef(); if (!value.isInitialized() || value.isObject()) continue; ExpressionPtr e = Expression::MakeScalarExpression(ar2, ar2, loc, value); TypePtr t = value.isNull() ? Type::Null : value.isBoolean() ? Type::Boolean : value.isInteger() ? Type::Int64 : value.isDouble() ? Type::Double : value.isArray() ? Type::Array : Type::Variant; s_constants->add(key.toCStrRef().data(), t, e, ar2, e); } s_variables = ar2->getVariables(); for (int i = 0, n = NumGlobalNames(); i < n; ++i) { s_variables->add(GlobalNames[i], Type::Variant, false, ar, ConstructPtr(), ModifierExpressionPtr()); } } s_constants->setDynamic(ar, "SID", true); return true; }
bool BuiltinSymbols::Load(AnalysisResultPtr ar) { if (Loaded) return true; Loaded = true; if (g_context.isNull()) init_thread_locals(); ClassInfo::Load(); // load extension functions first, so system/php may call them ImportExtFunctions(ar, ClassInfo::GetSystem()); ConstantTablePtr cns = ar->getConstants(); // load extension constants, classes and dynamics ImportNativeConstants(ar, cns); ImportExtConstants(ar, cns, ClassInfo::GetSystem()); ImportExtClasses(ar); Array constants = ClassInfo::GetSystemConstants(); LocationPtr loc(new Location); for (ArrayIter it = constants.begin(); it; ++it) { CVarRef key = it.first(); if (!key.isString()) continue; std::string name = key.toCStrRef().data(); if (cns->getSymbol(name)) continue; if (name == "true" || name == "false" || name == "null") continue; CVarRef value = it.secondRef(); if (!value.isInitialized() || value.isObject()) continue; ExpressionPtr e = Expression::MakeScalarExpression(ar, ar, loc, value); TypePtr t = value.isNull() ? Type::Null : value.isBoolean() ? Type::Boolean : value.isInteger() ? Type::Int64 : value.isDouble() ? Type::Double : value.isArray() ? Type::Array : Type::Variant; cns->add(key.toCStrRef().data(), t, e, ar, e); } for (int i = 0, n = NumGlobalNames(); i < n; ++i) { ar->getVariables()->add(GlobalNames[i], Type::Variant, false, ar, ConstructPtr(), ModifierExpressionPtr()); } cns->setDynamic(ar, "PHP_BINARY", true); cns->setDynamic(ar, "PHP_BINDIR", true); cns->setDynamic(ar, "PHP_OS", true); cns->setDynamic(ar, "PHP_SAPI", true); cns->setDynamic(ar, "SID", true); // Systemlib files were all parsed by hphp_process_init const StringToFileScopePtrMap &files = ar->getAllFiles(); for (const auto& file : files) { file.second->setSystem(); const auto& classes = file.second->getClasses(); for (const auto& clsVec : classes) { assert(clsVec.second.size() == 1); auto cls = clsVec.second[0]; cls->setSystem(); ar->addSystemClass(cls); for (const auto& func : cls->getFunctions()) { FunctionScope::RecordFunctionInfo(func.first, func.second); } } const auto& functions = file.second->getFunctions(); for (const auto& func : functions) { func.second->setSystem(); ar->addSystemFunction(func.second); FunctionScope::RecordFunctionInfo(func.first, func.second); } } return true; }
bool same(CVarRef v1, double d) { return v1.isDouble() && v1.getDouble() == d; }
bool BuiltinSymbols::Load(AnalysisResultPtr ar, bool extOnly /* = false */) { if (Loaded) return true; Loaded = true; if (g_context.isNull()) init_thread_locals(); ClassInfo::Load(); // load extension functions first, so system/classes may call them ImportExtFunctions(ar, s_functions, ClassInfo::GetSystem()); AnalysisResultPtr ar2 = AnalysisResultPtr(new AnalysisResult()); s_variables = VariableTablePtr(new VariableTable(*ar2.get())); s_constants = ConstantTablePtr(new ConstantTable(*ar2.get())); // parse all PHP files under system/classes if (!extOnly) { ar = AnalysisResultPtr(new AnalysisResult()); ar->loadBuiltinFunctions(); string slib = get_systemlib(); Scanner scanner(slib.c_str(), slib.size(), Option::ScannerType, "systemlib.php"); Compiler::Parser parser(scanner, "systemlib.php", ar); if (!parser.parse()) { Logger::Error("Unable to parse systemlib.php: %s", parser.getMessage().c_str()); assert(false); } ar->analyzeProgram(true); ar->inferTypes(); const StringToFileScopePtrMap &files = ar->getAllFiles(); for (StringToFileScopePtrMap::const_iterator iterFile = files.begin(); iterFile != files.end(); iterFile++) { const StringToClassScopePtrVecMap &classes = iterFile->second->getClasses(); for (StringToClassScopePtrVecMap::const_iterator iter = classes.begin(); iter != classes.end(); ++iter) { assert(iter->second.size() == 1); iter->second[0]->setSystem(); assert(!s_classes[iter->first]); s_classes[iter->first] = iter->second[0]; } } } else { NoSuperGlobals = true; } // load extension constants, classes and dynamics ImportExtConstants(ar, s_constants, ClassInfo::GetSystem()); ImportExtClasses(ar); if (!extOnly) { Array constants = ClassInfo::GetSystemConstants(); LocationPtr loc(new Location); for (ArrayIter it = constants.begin(); it; ++it) { CVarRef key = it.first(); if (!key.isString()) continue; std::string name = key.toCStrRef().data(); if (s_constants->getSymbol(name)) continue; if (name == "true" || name == "false" || name == "null") continue; CVarRef value = it.secondRef(); if (!value.isInitialized() || value.isObject()) continue; ExpressionPtr e = Expression::MakeScalarExpression(ar2, ar2, loc, value); TypePtr t = value.isNull() ? Type::Null : value.isBoolean() ? Type::Boolean : value.isInteger() ? Type::Int64 : value.isDouble() ? Type::Double : value.isArray() ? Type::Array : Type::Variant; s_constants->add(key.toCStrRef().data(), t, e, ar2, e); } s_variables = ar2->getVariables(); for (int i = 0, n = NumGlobalNames(); i < n; ++i) { s_variables->add(GlobalNames[i], Type::Variant, false, ar, ConstructPtr(), ModifierExpressionPtr()); } } s_constants->setDynamic(ar, "SID", true); return true; }