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;
}
Exemple #4
0
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;
}