2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #include "hphp/compiler/option.h"
24 #include "hphp/compiler/analysis/analysis_result.h"
25 #include "hphp/compiler/analysis/class_scope.h"
26 #include "hphp/compiler/analysis/file_scope.h"
28 #include "hphp/parser/scanner.h"
30 #include "hphp/runtime/base/config.h"
31 #include "hphp/runtime/base/ini-setting.h"
32 #include "hphp/runtime/base/preg.h"
33 #include "hphp/runtime/base/variable-unserializer.h"
35 #include "hphp/util/hdf.h"
36 #include "hphp/util/logger.h"
37 #include "hphp/util/process.h"
38 #include "hphp/util/text-util.h"
40 #include "hphp/hhbbc/hhbbc.h"
43 ///////////////////////////////////////////////////////////////////////////////
45 std::string
Option::RootDirectory
;
46 std::set
<std::string
> Option::PackageDirectories
;
47 std::set
<std::string
> Option::PackageFiles
;
48 std::set
<std::string
> Option::PackageExcludeDirs
;
49 std::set
<std::string
> Option::PackageExcludeFiles
;
50 std::set
<std::string
> Option::PackageExcludePatterns
;
51 std::set
<std::string
> Option::PackageExcludeStaticDirs
;
52 std::set
<std::string
> Option::PackageExcludeStaticFiles
;
53 std::set
<std::string
> Option::PackageExcludeStaticPatterns
;
54 bool Option::CachePHPFile
= false;
56 std::vector
<std::string
> Option::ParseOnDemandDirs
;
58 std::vector
<std::string
> Option::IncludeSearchPaths
;
60 std::set
<std::string
> Option::VolatileClasses
;
61 std::map
<std::string
,std::string
,stdltistr
> Option::AutoloadClassMap
;
62 std::map
<std::string
,std::string
,stdltistr
> Option::AutoloadFuncMap
;
63 std::map
<std::string
,std::string
> Option::AutoloadConstMap
;
64 std::string
Option::AutoloadRoot
;
66 std::vector
<std::string
> Option::APCProfile
;
68 bool Option::GenerateTextHHBC
= false;
69 bool Option::GenerateHhasHHBC
= false;
70 bool Option::GenerateBinaryHHBC
= false;
71 std::string
Option::RepoCentralPath
;
73 std::string
Option::IdPrefix
= "$$";
75 std::string
Option::LambdaPrefix
= "df_";
76 std::string
Option::Tab
= " ";
78 const char *Option::UserFilePrefix
= "php/";
80 bool Option::KeepStatementsWithNoEffect
= false;
82 std::string
Option::ProgramName
;
84 bool Option::ParseTimeOpts
= true;
85 bool Option::EnableHipHopExperimentalSyntax
= false;
86 bool Option::EnableShortTags
= true;
87 bool Option::EnableAspTags
= false;
88 int Option::ParserThreadCount
= 0;
90 int Option::GetScannerType() {
92 if (EnableShortTags
) type
|= Scanner::AllowShortTags
;
93 if (EnableAspTags
) type
|= Scanner::AllowAspTags
;
94 if (RuntimeOption::EnableXHP
) type
|= Scanner::AllowXHPSyntax
;
95 if (RuntimeOption::EnableHipHopSyntax
) type
|= Scanner::AllowHipHopSyntax
;
99 bool Option::DumpAst
= false;
100 bool Option::WholeProgram
= true;
101 bool Option::RecordErrors
= true;
103 bool Option::AllVolatile
= false;
105 ///////////////////////////////////////////////////////////////////////////////
106 // load from HDF file
108 void Option::LoadRootHdf(const IniSetting::Map
& ini
,
110 const std::string
& name
,
111 std::map
<std::string
, std::string
> &map
) {
112 auto root_map_callback
= [&](const IniSetting::Map
& ini_rm
, const Hdf
& hdf_rm
,
113 const std::string
& /*ini_rm_key*/) {
114 map
[Config::GetString(ini_rm
, hdf_rm
, "root", "", false)] =
115 Config::GetString(ini_rm
, hdf_rm
, "path", "", false);
117 Config::Iterate(root_map_callback
, ini
, roots
, name
);
120 void Option::Load(const IniSetting::Map
& ini
, Hdf
&config
) {
121 LoadRootHdf(ini
, config
, "IncludeRoots", RuntimeOption::IncludeRoots
);
122 LoadRootHdf(ini
, config
, "AutoloadRoots", RuntimeOption::AutoloadRoots
);
124 Config::Bind(PackageFiles
, ini
, config
, "PackageFiles", PackageFiles
);
125 Config::Bind(IncludeSearchPaths
, ini
, config
, "IncludeSearchPaths");
126 Config::Bind(PackageDirectories
, ini
, config
, "PackageDirectories");
127 Config::Bind(PackageExcludeDirs
, ini
, config
, "PackageExcludeDirs");
128 Config::Bind(PackageExcludeFiles
, ini
, config
, "PackageExcludeFiles");
129 Config::Bind(PackageExcludePatterns
, ini
, config
, "PackageExcludePatterns");
130 Config::Bind(PackageExcludeStaticDirs
, ini
,
131 config
, "PackageExcludeStaticDirs");
132 Config::Bind(PackageExcludeStaticFiles
, ini
,
133 config
, "PackageExcludeStaticFiles");
134 Config::Bind(PackageExcludeStaticFiles
, ini
,
135 config
, "PackageExcludeStaticPatterns");
136 Config::Bind(CachePHPFile
, ini
, config
, "CachePHPFile");
138 Config::Bind(RuntimeOption::EvalDisableReturnByReference
,
139 ini
, config
, "DisableReturnByReference",
140 RuntimeOption::EvalDisableReturnByReference
);
142 Config::Bind(ParseOnDemandDirs
, ini
, config
, "ParseOnDemandDirs");
144 Config::Bind(IdPrefix
, ini
, config
, "CodeGeneration.IdPrefix", IdPrefix
);
145 Config::Bind(LambdaPrefix
, ini
, config
,
146 "CodeGeneration.LambdaPrefix", LambdaPrefix
);
148 Config::Bind(RuntimeOption::DynamicInvokeFunctions
,
149 ini
, config
, "DynamicInvokeFunctions",
150 RuntimeOption::DynamicInvokeFunctions
);
151 Config::Bind(VolatileClasses
, ini
, config
, "VolatileClasses");
153 Config::GetBool(ini
, config
, "FlattenTraits");
155 for (auto& str
: Config::GetStrVector(ini
, config
, "ConstantFunctions")) {
158 if (folly::split('|', str
, func
, value
)) {
159 VariableUnserializer uns
{
160 value
.data(), value
.size(),
161 VariableUnserializer::Type::Internal
,
165 auto v
= uns
.unserialize();
167 RuntimeOption::ConstantFunctions
[func
] = *v
.toCell();
169 } catch (const Exception
& e
) {
170 // fall through and log
173 Logger::FError("Invalid ConstantFunction: '{}'\n", str
);
180 Config::Bind(RepoCentralPath
, ini
, config
, "Repo.Central.Path");
182 Config::Bind(RuntimeOption::RepoDebugInfo
,
183 ini
, config
, "Repo.DebugInfo",
184 RuntimeOption::RepoDebugInfo
);
189 Config::Bind(AutoloadClassMap
, ini
, config
, "AutoloadMap.class");
190 Config::Bind(AutoloadFuncMap
, ini
, config
, "AutoloadMap.function");
191 Config::Bind(AutoloadConstMap
, ini
, config
, "AutoloadMap.constant");
192 Config::Bind(AutoloadRoot
, ini
, config
, "AutoloadMap.root");
195 Config::Bind(RuntimeOption::EvalHardTypeHints
, ini
, config
,
196 "HardTypeHints", RuntimeOption::EvalHardTypeHints
);
198 static bool HardReturnTypeHints
;
199 Config::Bind(HardReturnTypeHints
, ini
, config
, "HardReturnTypeHints", true);
201 Config::Bind(RuntimeOption::EvalCheckPropTypeHints
, ini
, config
,
202 "CheckPropTypeHints", RuntimeOption::EvalCheckPropTypeHints
);
204 // This option takes precedence over RuntimeOption. We test to see if the
205 // option has been set (by the user) or not.
206 auto is_set
= [&](const std::string
& key
) {
207 auto a
= Config::GetBool(ini
, config
, key
, true);
208 auto b
= Config::GetBool(ini
, config
, key
, false);
212 if (!is_set("CheckReturnTypeHints") || is_set("HardReturnTypeHints")) {
213 // Note that the actual value does not matter, since HHBBC only cares about
214 // whether the value is 3 or not.
215 RuntimeOption::EvalCheckReturnTypeHints
= HardReturnTypeHints
? 3 : 2;
218 Config::Bind(HHBBC::options
.HardConstProp
, ini
, config
,
219 "HardConstProp", HHBBC::options
.HardConstProp
);
220 Config::Bind(HHBBC::options
.ElideAutoloadInvokes
, ini
, config
,
221 "ElideAutoloadInvokes", HHBBC::options
.ElideAutoloadInvokes
);
223 Config::Bind(APCProfile
, ini
, config
, "APCProfile");
225 Config::Bind(RuntimeOption::EvalThisTypeHintLevel
, ini
, config
,
226 "ThisTypeHintLevel", RuntimeOption::EvalThisTypeHintLevel
);
228 Config::Bind(RuntimeOption::EnableHipHopSyntax
,
229 ini
, config
, "EnableHipHopSyntax",
230 RuntimeOption::EnableHipHopSyntax
);
231 Config::Bind(RuntimeOption::EvalPromoteEmptyObject
,
232 ini
, config
, "PromoteEmptyObject",
233 RuntimeOption::EvalPromoteEmptyObject
);
234 Config::Bind(RuntimeOption::EvalJitEnableRenameFunction
,
235 ini
, config
, "JitEnableRenameFunction",
236 RuntimeOption::EvalJitEnableRenameFunction
);
237 Config::Bind(EnableHipHopExperimentalSyntax
, ini
,
238 config
, "EnableHipHopExperimentalSyntax");
239 Config::Bind(EnableShortTags
, ini
, config
, "EnableShortTags", true);
241 #define BIND_HAC_OPTION(Name, Def) \
242 Config::Bind(RuntimeOption::EvalHackArrCompat##Name, \
243 ini, config, "HackArrCompat" #Name, \
244 RuntimeOption::EvalHackArrCompat##Def);
246 #define BIND_HAC_OPTION_SELF(Name) BIND_HAC_OPTION(Name, Name)
248 BIND_HAC_OPTION_SELF(Notices
)
249 BIND_HAC_OPTION(CheckIntishCast
, Notices
)
250 BIND_HAC_OPTION(CheckRefBind
, Notices
)
251 BIND_HAC_OPTION(CheckFalseyPromote
, Notices
)
252 BIND_HAC_OPTION(CheckCompare
, Notices
)
253 BIND_HAC_OPTION(CheckArrayKeyCast
, Notices
)
254 BIND_HAC_OPTION(CheckArrayPlus
, Notices
)
255 BIND_HAC_OPTION_SELF(IsArrayNotices
)
256 BIND_HAC_OPTION_SELF(PromoteNotices
)
257 BIND_HAC_OPTION_SELF(TypeHintNotices
)
258 BIND_HAC_OPTION_SELF(DVCmpNotices
)
259 BIND_HAC_OPTION_SELF(SerializeNotices
)
260 BIND_HAC_OPTION_SELF(CompactSerializeNotices
)
262 #undef BIND_HAC_OPTION_SELF
263 #undef BIND_HAC_OPTION
265 Config::Bind(RuntimeOption::EvalHackArrDVArrs
,
266 ini
, config
, "HackArrDVArrs",
267 RuntimeOption::EvalHackArrDVArrs
);
269 Config::Bind(RuntimeOption::EvalForbidDynamicCalls
,
270 ini
, config
, "ForbidDynamicCalls",
271 RuntimeOption::EvalForbidDynamicCalls
);
272 Config::Bind(RuntimeOption::EvalNoticeOnBuiltinDynamicCalls
,
273 ini
, config
, "NoticeOnBuiltinDynamicCalls",
274 RuntimeOption::EvalNoticeOnBuiltinDynamicCalls
);
275 Config::Bind(RuntimeOption::EvalAllowObjectDestructors
,
276 ini
, config
, "AllowObjectDestructors",
277 RuntimeOption::EvalAllowObjectDestructors
);
278 Config::Bind(RuntimeOption::EvalAbortBuildOnVerifyError
,
279 ini
, config
, "AbortBuildOnVerifyError",
280 RuntimeOption::EvalAbortBuildOnVerifyError
);
284 Config::Bind(RuntimeOption::IntsOverflowToInts
, ini
, config
,
285 "Hack.Lang.IntsOverflowToInts",
286 RuntimeOption::IntsOverflowToInts
);
287 Config::Bind(RuntimeOption::StrictArrayFillKeys
, ini
, config
,
288 "Hack.Lang.StrictArrayFillKeys",
289 RuntimeOption::StrictArrayFillKeys
);
290 Config::Bind(RuntimeOption::DisallowDynamicVarEnvFuncs
, ini
, config
,
291 "Hack.Lang.DisallowDynamicVarEnvFuncs",
292 RuntimeOption::DisallowDynamicVarEnvFuncs
);
295 Config::Bind(EnableAspTags
, ini
, config
, "EnableAspTags");
297 Config::Bind(RuntimeOption::EnableXHP
, ini
, config
, "EnableXHP",
298 RuntimeOption::EnableXHP
);
300 if (RuntimeOption::EnableHipHopSyntax
) {
301 // If EnableHipHopSyntax is true, it forces EnableXHP to true
302 // regardless of how it was set in the config
303 RuntimeOption::EnableXHP
= true;
306 Config::Bind(ParserThreadCount
, ini
, config
, "ParserThreadCount", 0);
307 if (ParserThreadCount
<= 0) {
308 ParserThreadCount
= Process::GetCPUCount();
311 // Just to silence warnings until we remove them from various config files
312 (void)Config::GetByte(ini
, config
, "EnableEval", 0);
313 (void)Config::GetBool(ini
, config
, "AllDynamic", true);
315 Config::Bind(AllVolatile
, ini
, config
, "AllVolatile");
317 Config::Bind(RuntimeOption::EvalGenerateDocComments
, ini
, config
,
318 "GenerateDocComments", RuntimeOption::EvalGenerateDocComments
);
319 Config::Bind(DumpAst
, ini
, config
, "DumpAst", false);
320 Config::Bind(WholeProgram
, ini
, config
, "WholeProgram", true);
321 Config::Bind(RuntimeOption::EvalUseHHBBC
, ini
, config
, "UseHHBBC",
322 RuntimeOption::EvalUseHHBBC
);
324 // Temporary, during file-cache migration.
325 Config::Bind(FileCache::UseNewCache
, ini
, config
, "UseNewCache", false);
328 void Option::Load() {
331 ///////////////////////////////////////////////////////////////////////////////
333 std::string
Option::MangleFilename(const std::string
&name
, bool id
) {
334 std::string ret
= UserFilePrefix
;
338 replaceAll(ret
, "/", "$");
339 replaceAll(ret
, "-", "_");
340 replaceAll(ret
, ".", "_");
345 bool Option::IsFileExcluded(const std::string
&file
,
346 const std::set
<std::string
> &patterns
) {
347 String
sfile(file
.c_str(), file
.size(), CopyString
);
348 for (auto const& pattern
: patterns
) {
350 Variant ret
= preg_match(String(pattern
.c_str(), pattern
.size(),
351 CopyString
), sfile
, &matches
);
352 if (ret
.toInt64() > 0) {
359 void Option::FilterFiles(std::vector
<std::string
> &files
,
360 const std::set
<std::string
> &patterns
) {
361 auto const it
= std::remove_if(
364 [&](const std::string
& file
) { return IsFileExcluded(file
, patterns
); });
365 files
.erase(it
, files
.end());
368 //////////////////////////////////////////////////////////////////////