[Clang][SME2] Enable multi-vector loads & stores for SME2 (#75821)
[llvm-project.git] / compiler-rt / lib / scudo / standalone / flags_parser.cpp
blob3d8c6f3789b4ccb4707233e1cedbbc284026d956
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 <errno.h>
14 #include <limits.h>
15 #include <stdlib.h>
16 #include <string.h>
18 namespace scudo {
20 class UnknownFlagsRegistry {
21 static const u32 MaxUnknownFlags = 16;
22 const char *UnknownFlagsNames[MaxUnknownFlags];
23 u32 NumberOfUnknownFlags;
25 public:
26 void add(const char *Name) {
27 CHECK_LT(NumberOfUnknownFlags, MaxUnknownFlags);
28 UnknownFlagsNames[NumberOfUnknownFlags++] = Name;
31 void report() {
32 if (!NumberOfUnknownFlags)
33 return;
34 Printf("Scudo WARNING: found %d unrecognized flag(s):\n",
35 NumberOfUnknownFlags);
36 for (u32 I = 0; I < NumberOfUnknownFlags; ++I)
37 Printf(" %s\n", UnknownFlagsNames[I]);
38 NumberOfUnknownFlags = 0;
41 static UnknownFlagsRegistry UnknownFlags;
43 void reportUnrecognizedFlags() { UnknownFlags.report(); }
45 void FlagParser::printFlagDescriptions() {
46 Printf("Available flags for Scudo:\n");
47 for (u32 I = 0; I < NumberOfFlags; ++I)
48 Printf("\t%s\n\t\t- %s\n", Flags[I].Name, Flags[I].Desc);
51 static bool isSeparator(char C) {
52 return C == ' ' || C == ',' || C == ':' || C == '\n' || C == '\t' ||
53 C == '\r';
56 static bool isSeparatorOrNull(char C) { return !C || isSeparator(C); }
58 void FlagParser::skipWhitespace() {
59 while (isSeparator(Buffer[Pos]))
60 ++Pos;
63 void FlagParser::parseFlag() {
64 const uptr NameStart = Pos;
65 while (Buffer[Pos] != '=' && !isSeparatorOrNull(Buffer[Pos]))
66 ++Pos;
67 if (Buffer[Pos] != '=')
68 reportError("expected '='");
69 const char *Name = Buffer + NameStart;
70 const uptr ValueStart = ++Pos;
71 const char *Value;
72 if (Buffer[Pos] == '\'' || Buffer[Pos] == '"') {
73 const char Quote = Buffer[Pos++];
74 while (Buffer[Pos] != 0 && Buffer[Pos] != Quote)
75 ++Pos;
76 if (Buffer[Pos] == 0)
77 reportError("unterminated string");
78 Value = Buffer + ValueStart + 1;
79 ++Pos; // consume the closing quote
80 } else {
81 while (!isSeparatorOrNull(Buffer[Pos]))
82 ++Pos;
83 Value = Buffer + ValueStart;
85 if (!runHandler(Name, Value, '='))
86 reportError("flag parsing failed.");
89 void FlagParser::parseFlags() {
90 while (true) {
91 skipWhitespace();
92 if (Buffer[Pos] == 0)
93 break;
94 parseFlag();
98 void FlagParser::parseString(const char *S) {
99 if (!S)
100 return;
101 // Backup current parser state to allow nested parseString() calls.
102 const char *OldBuffer = Buffer;
103 const uptr OldPos = Pos;
104 Buffer = S;
105 Pos = 0;
107 parseFlags();
109 Buffer = OldBuffer;
110 Pos = OldPos;
113 inline bool parseBool(const char *Value, bool *b) {
114 if (strncmp(Value, "0", 1) == 0 || strncmp(Value, "no", 2) == 0 ||
115 strncmp(Value, "false", 5) == 0) {
116 *b = false;
117 return true;
119 if (strncmp(Value, "1", 1) == 0 || strncmp(Value, "yes", 3) == 0 ||
120 strncmp(Value, "true", 4) == 0) {
121 *b = true;
122 return true;
124 return false;
127 void FlagParser::parseStringPair(const char *Name, const char *Value) {
128 if (!runHandler(Name, Value, '\0'))
129 reportError("flag parsing failed.");
132 bool FlagParser::runHandler(const char *Name, const char *Value,
133 const char Sep) {
134 for (u32 I = 0; I < NumberOfFlags; ++I) {
135 const uptr Len = strlen(Flags[I].Name);
136 if (strncmp(Name, Flags[I].Name, Len) != 0 || Name[Len] != Sep)
137 continue;
138 bool Ok = false;
139 switch (Flags[I].Type) {
140 case FlagType::FT_bool:
141 Ok = parseBool(Value, reinterpret_cast<bool *>(Flags[I].Var));
142 if (!Ok)
143 reportInvalidFlag("bool", Value);
144 break;
145 case FlagType::FT_int:
146 char *ValueEnd;
147 errno = 0;
148 long V = strtol(Value, &ValueEnd, 10);
149 if (errno != 0 || // strtol failed (over or underflow)
150 V > INT_MAX || V < INT_MIN || // overflows integer
151 // contains unexpected characters
152 (*ValueEnd != '"' && *ValueEnd != '\'' &&
153 !isSeparatorOrNull(*ValueEnd))) {
154 reportInvalidFlag("int", Value);
155 break;
157 *reinterpret_cast<int *>(Flags[I].Var) = static_cast<int>(V);
158 Ok = true;
159 break;
161 return Ok;
163 // Unrecognized flag. This is not a fatal error, we may print a warning later.
164 UnknownFlags.add(Name);
165 return true;
168 void FlagParser::registerFlag(const char *Name, const char *Desc, FlagType Type,
169 void *Var) {
170 CHECK_LT(NumberOfFlags, MaxFlags);
171 Flags[NumberOfFlags].Name = Name;
172 Flags[NumberOfFlags].Desc = Desc;
173 Flags[NumberOfFlags].Type = Type;
174 Flags[NumberOfFlags].Var = Var;
175 ++NumberOfFlags;
178 } // namespace scudo