[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / compiler-rt / lib / scudo / standalone / flags_parser.cpp
blobbe39fcd4f8879ba9fc23462f5a5f00a7743ed05a
1 //===-- flags_parser.cpp ----------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "flags_parser.h"
10 #include "common.h"
11 #include "report.h"
13 #include <stdlib.h>
14 #include <string.h>
16 namespace scudo {
18 class UnknownFlagsRegistry {
19 static const u32 MaxUnknownFlags = 16;
20 const char *UnknownFlagsNames[MaxUnknownFlags];
21 u32 NumberOfUnknownFlags;
23 public:
24 void add(const char *Name) {
25 CHECK_LT(NumberOfUnknownFlags, MaxUnknownFlags);
26 UnknownFlagsNames[NumberOfUnknownFlags++] = Name;
29 void report() {
30 if (!NumberOfUnknownFlags)
31 return;
32 Printf("Scudo WARNING: found %d unrecognized flag(s):\n",
33 NumberOfUnknownFlags);
34 for (u32 I = 0; I < NumberOfUnknownFlags; ++I)
35 Printf(" %s\n", UnknownFlagsNames[I]);
36 NumberOfUnknownFlags = 0;
39 static UnknownFlagsRegistry UnknownFlags;
41 void reportUnrecognizedFlags() { UnknownFlags.report(); }
43 void FlagParser::printFlagDescriptions() {
44 Printf("Available flags for Scudo:\n");
45 for (u32 I = 0; I < NumberOfFlags; ++I)
46 Printf("\t%s\n\t\t- %s\n", Flags[I].Name, Flags[I].Desc);
49 static bool isSeparator(char C) {
50 return C == ' ' || C == ',' || C == ':' || C == '\n' || C == '\t' ||
51 C == '\r';
54 static bool isSeparatorOrNull(char C) { return !C || isSeparator(C); }
56 void FlagParser::skipWhitespace() {
57 while (isSeparator(Buffer[Pos]))
58 ++Pos;
61 void FlagParser::parseFlag() {
62 const uptr NameStart = Pos;
63 while (Buffer[Pos] != '=' && !isSeparatorOrNull(Buffer[Pos]))
64 ++Pos;
65 if (Buffer[Pos] != '=')
66 reportError("expected '='");
67 const char *Name = Buffer + NameStart;
68 const uptr ValueStart = ++Pos;
69 const char *Value;
70 if (Buffer[Pos] == '\'' || Buffer[Pos] == '"') {
71 const char Quote = Buffer[Pos++];
72 while (Buffer[Pos] != 0 && Buffer[Pos] != Quote)
73 ++Pos;
74 if (Buffer[Pos] == 0)
75 reportError("unterminated string");
76 Value = Buffer + ValueStart + 1;
77 ++Pos; // consume the closing quote
78 } else {
79 while (!isSeparatorOrNull(Buffer[Pos]))
80 ++Pos;
81 Value = Buffer + ValueStart;
83 if (!runHandler(Name, Value))
84 reportError("flag parsing failed.");
87 void FlagParser::parseFlags() {
88 while (true) {
89 skipWhitespace();
90 if (Buffer[Pos] == 0)
91 break;
92 parseFlag();
96 void FlagParser::parseString(const char *S) {
97 if (!S)
98 return;
99 // Backup current parser state to allow nested parseString() calls.
100 const char *OldBuffer = Buffer;
101 const uptr OldPos = Pos;
102 Buffer = S;
103 Pos = 0;
105 parseFlags();
107 Buffer = OldBuffer;
108 Pos = OldPos;
111 inline bool parseBool(const char *Value, bool *b) {
112 if (strncmp(Value, "0", 1) == 0 || strncmp(Value, "no", 2) == 0 ||
113 strncmp(Value, "false", 5) == 0) {
114 *b = false;
115 return true;
117 if (strncmp(Value, "1", 1) == 0 || strncmp(Value, "yes", 3) == 0 ||
118 strncmp(Value, "true", 4) == 0) {
119 *b = true;
120 return true;
122 return false;
125 bool FlagParser::runHandler(const char *Name, const char *Value) {
126 for (u32 I = 0; I < NumberOfFlags; ++I) {
127 const uptr Len = strlen(Flags[I].Name);
128 if (strncmp(Name, Flags[I].Name, Len) != 0 || Name[Len] != '=')
129 continue;
130 bool Ok = false;
131 switch (Flags[I].Type) {
132 case FlagType::FT_bool:
133 Ok = parseBool(Value, reinterpret_cast<bool *>(Flags[I].Var));
134 if (!Ok)
135 reportInvalidFlag("bool", Value);
136 break;
137 case FlagType::FT_int:
138 char *ValueEnd;
139 *reinterpret_cast<int *>(Flags[I].Var) =
140 static_cast<int>(strtol(Value, &ValueEnd, 10));
141 Ok =
142 *ValueEnd == '"' || *ValueEnd == '\'' || isSeparatorOrNull(*ValueEnd);
143 if (!Ok)
144 reportInvalidFlag("int", Value);
145 break;
147 return Ok;
149 // Unrecognized flag. This is not a fatal error, we may print a warning later.
150 UnknownFlags.add(Name);
151 return true;
154 void FlagParser::registerFlag(const char *Name, const char *Desc, FlagType Type,
155 void *Var) {
156 CHECK_LT(NumberOfFlags, MaxFlags);
157 Flags[NumberOfFlags].Name = Name;
158 Flags[NumberOfFlags].Desc = Desc;
159 Flags[NumberOfFlags].Type = Type;
160 Flags[NumberOfFlags].Var = Var;
161 ++NumberOfFlags;
164 } // namespace scudo