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, 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; }
bool BuiltinSymbols::Load(AnalysisResultPtr ar, bool extOnly /* = false */) { if (Loaded) return true; Loaded = true; // Build function scopes for some of the runtime helper functions // declared in "runtime/base/builtin_functions.h" const char **helper = HelperFunctions; while (*helper) { FunctionScopePtr f = ParseHelperFunction(ar, helper); ASSERT(!s_helperFunctions[f->getName()]); s_helperFunctions[f->getName()] = f; } // load extension functions first, so system/classes may call them ParseExtFunctions(ar, ExtensionFunctions, false); AnalysisResultPtr ar2; // parse all PHP files under system/classes if (!extOnly) { ar = AnalysisResultPtr(new AnalysisResult()); ar->loadBuiltinFunctions(); for (const char **cls = SystemClasses; *cls; cls++) { string phpBaseName = "/system/classes/"; phpBaseName += *cls; phpBaseName += ".php"; string phpFileName = Option::GetSystemRoot() + phpBaseName; const char *baseName = s_strings.add(phpBaseName.c_str()); const char *fileName = s_strings.add(phpFileName.c_str()); try { Scanner scanner(fileName, Option::ScannerType); Compiler::Parser parser(scanner, baseName, ar); if (!parser.parse()) { Logger::Error("Unable to parse file %s: %s", fileName, parser.getMessage().c_str()); ASSERT(false); } } catch (FileOpenException &e) { Logger::Error("%s", e.getMessage().c_str()); } } 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]; } } // parse globals/variables.php and globals/constants.php NoSuperGlobals = true; s_variables = LoadGlobalSymbols("symbols.php")->getVariables(); ar2 = LoadGlobalSymbols("constants.php"); const FileScopePtrVec &fileScopes = ar2->getAllFilesVector(); if (!fileScopes.empty()) { s_constants = fileScopes[0]->getConstants(); } else { Logger::Error("Couldn't load constants.php"); return false; } NoSuperGlobals = false; } else { ar2 = AnalysisResultPtr(new AnalysisResult()); s_variables = VariableTablePtr(new VariableTable(*ar2.get())); s_constants = ConstantTablePtr(new ConstantTable(*ar2.get())); NoSuperGlobals = true; } s_constants->setDynamic(ar, "SID", 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; } } return true; }
int process(const ProgramOptions &po) { if (po.coredump) { #if defined(__APPLE__) struct rlimit rl; getrlimit(RLIMIT_CORE, &rl); rl.rlim_cur = 80000000LL; if (rl.rlim_max < rl.rlim_cur) { rl.rlim_max = rl.rlim_cur; } setrlimit(RLIMIT_CORE, &rl); #else struct rlimit64 rl; getrlimit64(RLIMIT_CORE, &rl); rl.rlim_cur = 8000000000LL; if (rl.rlim_max < rl.rlim_cur) { rl.rlim_max = rl.rlim_cur; } setrlimit64(RLIMIT_CORE, &rl); #endif } // lint doesn't need analysis if (po.target == "lint") { return lintTarget(po); } Timer timer(Timer::WallTime); AnalysisResultPtr ar; // prepare a package Package package(po.inputDir.c_str()); ar = package.getAnalysisResult(); std::string errs; if (!AliasManager::parseOptimizations(po.optimizations, errs)) { cerr << errs << "\n"; return false; } if (po.target != "php" || po.format != "pickled") { if (!BuiltinSymbols::Load(ar, po.target == "cpp" && po.format == "sys")) { return false; } ar->loadBuiltins(); } { Timer timer(Timer::WallTime, "parsing inputs"); if (!po.inputs.empty() && po.target == "php" && po.format == "pickled") { for (unsigned int i = 0; i < po.inputs.size(); i++) { package.addSourceFile(po.inputs[i].c_str()); } if (!package.parse()) { return 1; } } else { ar->setPackage(&package); ar->setParseOnDemand(po.parseOnDemand); if (!po.parseOnDemand) { ar->setParseOnDemandDirs(Option::ParseOnDemandDirs); } if (po.modules.empty() && po.fmodules.empty() && po.ffiles.empty() && po.inputs.empty() && po.inputList.empty()) { package.addAllFiles(false); } else { for (unsigned int i = 0; i < po.modules.size(); i++) { package.addDirectory(po.modules[i], false); } for (unsigned int i = 0; i < po.fmodules.size(); i++) { package.addDirectory(po.fmodules[i], true); } for (unsigned int i = 0; i < po.ffiles.size(); i++) { package.addSourceFile(po.ffiles[i].c_str()); } for (unsigned int i = 0; i < po.cmodules.size(); i++) { package.addStaticDirectory(po.cmodules[i].c_str()); } for (unsigned int i = 0; i < po.cfiles.size(); i++) { package.addStaticFile(po.cfiles[i].c_str()); } for (unsigned int i = 0; i < po.inputs.size(); i++) { package.addSourceFile(po.inputs[i].c_str()); } if (!po.inputList.empty()) { package.addInputList(po.inputList.c_str()); } } } if (po.target != "filecache") { if (!package.parse()) { return 1; } ar->analyzeProgram(); } } // saving file cache AsyncFileCacheSaver fileCacheThread(&package, po.filecache.c_str()); if (!po.filecache.empty()) { fileCacheThread.start(); } if (po.dump) { ar->dump(); } int ret = 0; bool fatalErrorOnly = false; if (po.target == "analyze") { ret = analyzeTarget(po, ar); } else if (po.target == "php") { ret = phpTarget(po, ar); } else if (po.target == "cpp") { ret = cppTarget(po, ar); fatalErrorOnly = true; } else if (po.target == "run") { ret = runTargetCheck(po, ar); fatalErrorOnly = true; } else if (po.target == "filecache") { // do nothing } else if (po.target == "sep-ext-cpp") { ret = generateSepExtCpp(po, ar); } else { Logger::Error("Unknown target: %s", po.target.c_str()); return 1; } if (po.dump) { ar->dump(); } // saving stats if (po.target == "analyze" || po.genStats || !po.dbStats.empty()) { int seconds = timer.getMicroSeconds() / 1000000; Logger::Info("saving code errors and stats..."); Timer timer(Timer::WallTime, "saving stats"); if (!po.dbStats.empty()) { try { ServerDataPtr server = ServerData::Create(po.dbStats); int runId = package.saveStatsToDB(server, seconds, po.branch, po.revision); package.commitStats(server, runId); } catch (DatabaseException e) { Logger::Error("%s", e.what()); } } else { Compiler::SaveErrors((po.outputDir + "/CodeError.js").c_str()); package.saveStatsToFile((po.outputDir + "/Stats.js").c_str(), seconds); } } else if (Compiler::HasError()) { Logger::Info("saving code errors..."); Compiler::SaveErrors((po.outputDir + "/CodeError.js").c_str()); } if (!po.filecache.empty()) { fileCacheThread.waitForEnd(); } return ret; }