The C and C++ Include Header Files
/usr/include/nodejs/src/node_options-inl.h
$ cat -n /usr/include/nodejs/src/node_options-inl.h 1 #ifndef SRC_NODE_OPTIONS_INL_H_ 2 #define SRC_NODE_OPTIONS_INL_H_ 3 4 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 5 6 #include
7 #include "node_options.h" 8 #include "util.h" 9 10 namespace node { 11 12 PerIsolateOptions* PerProcessOptions::get_per_isolate_options() { 13 return per_isolate.get(); 14 } 15 16 EnvironmentOptions* PerIsolateOptions::get_per_env_options() { 17 return per_env.get(); 18 } 19 20 namespace options_parser { 21 22 template
23 void OptionsParser
::AddOption(const char* name, 24 const char* help_text, 25 bool Options::* field, 26 OptionEnvvarSettings env_setting) { 27 options_.emplace(name, 28 OptionInfo{kBoolean, 29 std::make_shared
>(field), 30 env_setting, 31 help_text}); 32 } 33 34 template
35 void OptionsParser
::AddOption(const char* name, 36 const char* help_text, 37 uint64_t Options::* field, 38 OptionEnvvarSettings env_setting) { 39 options_.emplace( 40 name, 41 OptionInfo{kUInteger, 42 std::make_shared
>(field), 43 env_setting, 44 help_text}); 45 } 46 47 template
48 void OptionsParser
::AddOption(const char* name, 49 const char* help_text, 50 int64_t Options::* field, 51 OptionEnvvarSettings env_setting) { 52 options_.emplace( 53 name, 54 OptionInfo{kInteger, 55 std::make_shared
>(field), 56 env_setting, 57 help_text}); 58 } 59 60 template
61 void OptionsParser
::AddOption(const char* name, 62 const char* help_text, 63 std::string Options::* field, 64 OptionEnvvarSettings env_setting) { 65 options_.emplace( 66 name, 67 OptionInfo{kString, 68 std::make_shared
>(field), 69 env_setting, 70 help_text}); 71 } 72 73 template
74 void OptionsParser
::AddOption( 75 const char* name, 76 const char* help_text, 77 std::vector
Options::* field, 78 OptionEnvvarSettings env_setting) { 79 options_.emplace(name, OptionInfo { 80 kStringList, 81 std::make_shared
>>(field), 82 env_setting, 83 help_text 84 }); 85 } 86 87 template
88 void OptionsParser
::AddOption(const char* name, 89 const char* help_text, 90 HostPort Options::* field, 91 OptionEnvvarSettings env_setting) { 92 options_.emplace( 93 name, 94 OptionInfo{kHostPort, 95 std::make_shared
>(field), 96 env_setting, 97 help_text}); 98 } 99 100 template
101 void OptionsParser
::AddOption(const char* name, 102 const char* help_text, 103 NoOp no_op_tag, 104 OptionEnvvarSettings env_setting) { 105 options_.emplace(name, OptionInfo{kNoOp, nullptr, env_setting, help_text}); 106 } 107 108 template
109 void OptionsParser
::AddOption(const char* name, 110 const char* help_text, 111 V8Option v8_option_tag, 112 OptionEnvvarSettings env_setting) { 113 options_.emplace(name, 114 OptionInfo{kV8Option, nullptr, env_setting, help_text}); 115 } 116 117 template
118 void OptionsParser
::AddAlias(const char* from, 119 const char* to) { 120 aliases_[from] = { to }; 121 } 122 123 template
124 void OptionsParser
::AddAlias(const char* from, 125 const std::vector
& to) { 126 aliases_[from] = to; 127 } 128 129 template
130 void OptionsParser
::AddAlias( 131 const char* from, 132 const std::initializer_list
& to) { 133 AddAlias(from, std::vector
(to)); 134 } 135 136 template
137 void OptionsParser
::Implies(const char* from, 138 const char* to) { 139 auto it = options_.find(to); 140 CHECK_NE(it, options_.end()); 141 CHECK_EQ(it->second.type, kBoolean); 142 implications_.emplace(from, Implication { 143 it->second.field, true 144 }); 145 } 146 147 template
148 void OptionsParser
::ImpliesNot(const char* from, 149 const char* to) { 150 auto it = options_.find(to); 151 CHECK_NE(it, options_.end()); 152 CHECK_EQ(it->second.type, kBoolean); 153 implications_.emplace(from, Implication { 154 it->second.field, false 155 }); 156 } 157 158 template
159 template
160 auto OptionsParser
::Convert( 161 std::shared_ptr
original, 162 ChildOptions* (Options::* get_child)()) { 163 // If we have a field on ChildOptions, and we want to access it from an 164 // Options instance, we call get_child() on the original Options and then 165 // access it, i.e. this class implements a kind of function chaining. 166 struct AdaptedField : BaseOptionField { 167 void* LookupImpl(Options* options) const override { 168 return original->LookupImpl((options->*get_child)()); 169 } 170 171 AdaptedField( 172 std::shared_ptr
original, 173 ChildOptions* (Options::* get_child)()) 174 : original(original), get_child(get_child) {} 175 176 std::shared_ptr
original; 177 ChildOptions* (Options::* get_child)(); 178 }; 179 180 return std::shared_ptr
( 181 new AdaptedField(original, get_child)); 182 } 183 template
184 template
185 auto OptionsParser
::Convert( 186 typename OptionsParser
::OptionInfo original, 187 ChildOptions* (Options::* get_child)()) { 188 return OptionInfo{original.type, 189 Convert(original.field, get_child), 190 original.env_setting, 191 original.help_text}; 192 } 193 194 template
195 template
196 auto OptionsParser
::Convert( 197 typename OptionsParser
::Implication original, 198 ChildOptions* (Options::* get_child)()) { 199 return Implication { 200 Convert(original.target_field, get_child), 201 original.target_value 202 }; 203 } 204 205 template
206 template
207 void OptionsParser
::Insert( 208 const OptionsParser
& child_options_parser, 209 ChildOptions* (Options::* get_child)()) { 210 aliases_.insert(std::begin(child_options_parser.aliases_), 211 std::end(child_options_parser.aliases_)); 212 213 for (const auto& pair : child_options_parser.options_) 214 options_.emplace(pair.first, Convert(pair.second, get_child)); 215 216 for (const auto& pair : child_options_parser.implications_) 217 implications_.emplace(pair.first, Convert(pair.second, get_child)); 218 } 219 220 inline std::string NotAllowedInEnvErr(const std::string& arg) { 221 return arg + " is not allowed in NODE_OPTIONS"; 222 } 223 224 inline std::string RequiresArgumentErr(const std::string& arg) { 225 return arg + " requires an argument"; 226 } 227 228 // We store some of the basic information around a single Parse call inside 229 // this struct, to separate storage of command line arguments and their 230 // handling. In particular, this makes it easier to introduce 'synthetic' 231 // arguments that get inserted by expanding option aliases. 232 struct ArgsInfo { 233 // Generally, the idea here is that the first entry in `*underlying` stores 234 // the "0th" argument (the program name), then `synthetic_args` are inserted, 235 // followed by the remainder of `*underlying`. 236 std::vector
* underlying; 237 std::vector
synthetic_args; 238 239 std::vector
* exec_args; 240 241 ArgsInfo(std::vector
* args, 242 std::vector
* exec_args) 243 : underlying(args), exec_args(exec_args) {} 244 245 size_t remaining() const { 246 // -1 to account for the program name. 247 return underlying->size() - 1 + synthetic_args.size(); 248 } 249 250 bool empty() const { return remaining() == 0; } 251 const std::string& program_name() const { return underlying->at(0); } 252 253 std::string& first() { 254 return synthetic_args.empty() ? underlying->at(1) : synthetic_args.front(); 255 } 256 257 std::string pop_first() { 258 std::string ret = std::move(first()); 259 if (synthetic_args.empty()) { 260 // Only push arguments to `exec_args` that were also originally passed 261 // on the command line (i.e. not generated through alias expansion). 262 // '--' is a special case here since its purpose is to end `exec_argv`, 263 // which is why we do not include it. 264 if (exec_args != nullptr && ret != "--") 265 exec_args->push_back(ret); 266 underlying->erase(underlying->begin() + 1); 267 } else { 268 synthetic_args.erase(synthetic_args.begin()); 269 } 270 return ret; 271 } 272 }; 273 274 template
275 void OptionsParser
::Parse( 276 std::vector
* const orig_args, 277 std::vector
* const exec_args, 278 std::vector
* const v8_args, 279 Options* const options, 280 OptionEnvvarSettings required_env_settings, 281 std::vector
* const errors) const { 282 ArgsInfo args(orig_args, exec_args); 283 284 // The first entry is the process name. Make sure it ends up in the V8 argv, 285 // since V8::SetFlagsFromCommandLine() expects that to hold true for that 286 // array as well. 287 if (v8_args->empty()) 288 v8_args->push_back(args.program_name()); 289 290 while (!args.empty() && errors->empty()) { 291 if (args.first().size() <= 1 || args.first()[0] != '-') break; 292 293 // We know that we're either going to consume this 294 // argument or fail completely. 295 const std::string arg = args.pop_first(); 296 297 if (arg == "--") { 298 if (required_env_settings == kAllowedInEnvironment) 299 errors->push_back(NotAllowedInEnvErr("--")); 300 break; 301 } 302 303 // Only allow --foo=bar notation for options starting with double dashes. 304 // (E.g. -e=a is not allowed as shorthand for --eval=a, which would 305 // otherwise be the result of alias expansion.) 306 const std::string::size_type equals_index = 307 arg[0] == '-' && arg[1] == '-' ? arg.find('=') : std::string::npos; 308 std::string name = 309 equals_index == std::string::npos ? arg : arg.substr(0, equals_index); 310 311 // Store the 'original name' of the argument. This name differs from 312 // 'name' in that it contains a possible '=' sign and is not affected 313 // by alias expansion. 314 std::string original_name = name; 315 if (equals_index != std::string::npos) 316 original_name += '='; 317 318 auto missing_argument = [&]() { 319 errors->push_back(RequiresArgumentErr(original_name)); 320 }; 321 322 // Normalize by replacing `_` with `-` in options. 323 for (std::string::size_type i = 2; i < name.size(); ++i) { 324 if (name[i] == '_') 325 name[i] = '-'; 326 } 327 328 { 329 auto it = aliases_.end(); 330 // Expand aliases: 331 // - If `name` can be found in `aliases_`. 332 // - If `name` + '=' can be found in `aliases_`. 333 // - If `name` + "
" can be found in `aliases_`, and we have 334 // a subsequent argument that does not start with '-' itself. 335 while ((it = aliases_.find(name)) != aliases_.end() || 336 (equals_index != std::string::npos && 337 (it = aliases_.find(name + '=')) != aliases_.end()) || 338 (!args.empty() && 339 !args.first().empty() && 340 args.first()[0] != '-' && 341 (it = aliases_.find(name + "
")) != aliases_.end())) { 342 const std::string prev_name = std::move(name); 343 const std::vector
& expansion = it->second; 344 345 // Use the first entry in the expansion as the new 'name'. 346 name = expansion.front(); 347 348 if (expansion.size() > 1) { 349 // The other arguments, if any, are going to be handled later. 350 args.synthetic_args.insert( 351 args.synthetic_args.begin(), 352 expansion.begin() + 1, 353 expansion.end()); 354 } 355 356 if (name == prev_name) break; 357 } 358 } 359 360 auto it = options_.find(name); 361 362 if ((it == options_.end() || 363 it->second.env_setting == kDisallowedInEnvironment) && 364 required_env_settings == kAllowedInEnvironment) { 365 errors->push_back(NotAllowedInEnvErr(original_name)); 366 break; 367 } 368 369 if (it == options_.end()) { 370 v8_args->push_back(arg); 371 continue; 372 } 373 374 { 375 auto implications = implications_.equal_range(name); 376 for (auto it = implications.first; it != implications.second; ++it) { 377 *it->second.target_field->template Lookup
(options) = 378 it->second.target_value; 379 } 380 } 381 382 const OptionInfo& info = it->second; 383 std::string value; 384 if (info.type != kBoolean && info.type != kNoOp && info.type != kV8Option) { 385 if (equals_index != std::string::npos) { 386 value = arg.substr(equals_index + 1); 387 if (value.empty()) { 388 missing_argument(); 389 break; 390 } 391 } else { 392 if (args.empty()) { 393 missing_argument(); 394 break; 395 } 396 397 value = args.pop_first(); 398 399 if (!value.empty() && value[0] == '-') { 400 missing_argument(); 401 break; 402 } else { 403 if (!value.empty() && value[0] == '\\' && value[1] == '-') 404 value = value.substr(1); // Treat \- as escaping an -. 405 } 406 } 407 } 408 409 switch (info.type) { 410 case kBoolean: 411 *Lookup
(info.field, options) = true; 412 break; 413 case kInteger: 414 *Lookup
(info.field, options) = std::atoll(value.c_str()); 415 break; 416 case kUInteger: 417 *Lookup
(info.field, options) = std::stoull(value); 418 break; 419 case kString: 420 *Lookup
(info.field, options) = value; 421 break; 422 case kStringList: 423 Lookup
>(info.field, options) 424 ->emplace_back(std::move(value)); 425 break; 426 case kHostPort: 427 Lookup
(info.field, options) 428 ->Update(SplitHostPort(value, errors)); 429 break; 430 case kNoOp: 431 break; 432 case kV8Option: 433 v8_args->push_back(arg); 434 break; 435 default: 436 UNREACHABLE(); 437 } 438 } 439 options->CheckOptions(errors); 440 } 441 442 } // namespace options_parser 443 } // namespace node 444 445 #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 446 447 #endif // SRC_NODE_OPTIONS_INL_H_
Contact us
|
About us
|
Term of use
|
Copyright © 2000-2024 MyWebUniversity.com ™