104 static const struct TypeData {
106 Tracepoint::Field::Type backendType;
148 auto backendType = [](
const QString &rawType) {
149 static const size_t tableSize =
sizeof (typeTable) /
sizeof (typeTable[0]);
151 for (size_t i = 0; i < tableSize; ++i) {
152 if (rawType == QLatin1StringView(typeTable[i].type))
156 TypeData unknown = {
nullptr, Tracepoint::Field::Unknown };
160 int arrayLen = arrayLength(rawType);
162 rawType = removeBraces(rawType);
164 if (!sequenceLength(rawType).isNull())
165 return Tracepoint::Field::Sequence;
167 static const QRegularExpression constMatch(QStringLiteral(
"\\bconst\\b"));
168 rawType.remove(constMatch);
169 rawType.remove(u'&');
171 static const QRegularExpression ptrMatch(QStringLiteral(
"\\s*\\*\\s*"));
172 rawType.replace(ptrMatch, QStringLiteral(
"_ptr"));
173 rawType = rawType.trimmed();
174 rawType.replace(QStringLiteral(
" "), QStringLiteral(
"_"));
176 if (rawType ==
"char_ptr"_L1)
177 return Tracepoint::Field::String;
179 if (rawType.endsWith(
"_ptr"_L1))
180 return Tracepoint::Field::Pointer;
182 TypeData d = backendType(rawType);
183 return d.backendType;
187 const QString &fileName,
const int lineNumber)
192 auto findEnumeration = [](
const QList<
TraceEnum> &enums,
const QString &name) {
193 for (
const auto &e : enums) {
199 auto findFlags = [](
const QList<
TraceFlags> &flags,
const QString &name) {
200 for (
const auto &f : flags) {
211 auto i = args.constBegin();
212 auto end = args.constEnd();
215 static const QRegularExpression rx(QStringLiteral(
"^(.*)\\b([A-Za-z_][A-Za-z0-9_]*)$"));
218 auto match = rx.match(*i);
220 const QString type = match.captured(1).trimmed();
223 panic(
"Missing parameter type for argument %d of %s (%s:%d)",
227 const QString name = match.captured(2).trimmed();
230 panic(
"Missing parameter name for argument %d of %s (%s:%d)",
234 int arrayLen = arrayLength(type);
236 Tracepoint::Argument a;
237 a.arrayLen = arrayLen;
239 a.type = decayArrayToPointer(type);
241 t.args <<
std::move(a);
243 Tracepoint::Field field;
244 const TraceEnum &e = findEnumeration(provider.enumerations, type);
245 const TraceFlags &f = findFlags(provider.flags, type);
246 if (!e.name.isEmpty()) {
247 field.backendType = Tracepoint::Field::EnumeratedType;
249 }
else if (!f.name.isEmpty()) {
250 field.backendType = Tracepoint::Field::FlagType;
252 field.backendType = backendType(type);
254 field.paramType = removeBraces(type);
256 field.arrayLen = arrayLen;
257 field.seqLen = sequenceLength(type);
259 t.fields <<
std::move(field);
296 if (!f.open(QIODevice::ReadOnly | QIODevice::Text))
301 static const QRegularExpression tracedef(QStringLiteral(
"^([A-Za-z][A-Za-z0-9_]*)\\((.*)\\)$"));
302 static const QRegularExpression enumenddef(QStringLiteral(
"^} ?([A-Za-z][A-Za-z0-9_:]*);"));
303 static const QRegularExpression enumdef(QStringLiteral(
"^([A-Za-z][A-Za-z0-9_]*)( *= *([xabcdef0-9]*))?"));
304 static const QRegularExpression rangedef(QStringLiteral(
"^RANGE\\(([A-Za-z][A-Za-z0-9_]*) ?, ?([0-9]*) ?... ?([0-9]*) ?\\)"));
307 provider.name = QFileInfo(filename).baseName();
309 bool parsingPrefixText =
false;
310 bool parsingEnum =
false;
311 bool parsingFlags =
false;
314 int currentEnumValue = 0;
315 int minEnumValue =
std::numeric_limits<
int>::max();
316 int maxEnumValue =
std::numeric_limits<
int>::min();
317 for (
int lineNumber = 1; !s.atEnd(); ++lineNumber) {
318 QString line = s.readLine().trimmed();
320 if (line ==
"{"_L1) {
321 parsingPrefixText =
true;
323 }
else if (parsingPrefixText && line ==
"}"_L1) {
324 parsingPrefixText =
false;
326 }
else if (parsingPrefixText) {
327 provider.prefixText.append(line);
329 }
else if (line ==
"ENUM {"_L1) {
332 }
else if (line ==
"FLAGS {"_L1) {
335 }
else if (line.startsWith(
"}"_L1) && (parsingEnum || parsingFlags)) {
336 auto match = enumenddef.match(line);
337 if (match.hasMatch()) {
339 currentEnum.name = match.captured(1);
341 provider.enumerations.push_back(currentEnum);
345 currentFlags.name = match.captured(1);
346 provider.flags.push_back(currentFlags);
348 parsingFlags =
false;
351 minEnumValue =
std::numeric_limits<
int>::max();
352 maxEnumValue =
std::numeric_limits<
int>::min();
354 panic(
"Syntax error while processing '%s' line %d:\n"
355 " '%s' end of enum/flags does not match",
363 if (line.isEmpty() || line.startsWith(u'#'))
366 if (parsingEnum || parsingFlags) {
367 auto m = enumdef.match(line);
368 if (parsingEnum && line.startsWith(QStringLiteral(
"RANGE"))) {
369 auto m = rangedef.match(line);
372 value.name = m.captured(1);
373 value
.value = m.captured(2).toInt();
374 value
.range = m.captured(3).toInt();
375 currentEnumValue = value
.range + 1;
376 currentEnum.values.push_back(value);
377 maxEnumValue = qMax(maxEnumValue, value
.range);
378 minEnumValue = qMin(minEnumValue, value
.value);
380 }
else if (m.hasMatch()) {
381 if (m.hasCaptured(3)) {
384 value.name = m.captured(1);
385 value
.value = m.captured(3).toInt();
387 currentEnumValue = value
.value + 1;
388 currentEnum.values.push_back(value);
389 maxEnumValue = qMax(maxEnumValue, value
.value);
390 minEnumValue = qMin(minEnumValue, value
.value);
393 value.name = m.captured(1);
394 if (m.captured(3).startsWith(QStringLiteral(
"0x")))
395 value
.value = m.captured(3).toInt(
nullptr, 16);
397 value
.value = m.captured(3).toInt();
398 if (!isPow2OrZero(value.value)) {
399 printf(
"Warning: '%s' line %d:\n"
400 " '%s' flag value is not power of two.\n",
404 value.value = pow2Log2(value.value);
405 currentFlags.values.push_back(value);
409 maxEnumValue = qMax(maxEnumValue, currentEnumValue);
410 minEnumValue = qMin(minEnumValue, currentEnumValue);
412 currentEnum.values.push_back({m.captured(0), currentEnumValue++, 0});
414 panic(
"Syntax error while processing '%s' line %d:\n"
415 " '%s' flags value not set",
421 panic(
"Syntax error while processing '%s' line %d:\n"
422 " '%s' enum/flags does not match",
429 auto match = tracedef.match(line);
430 if (match.hasMatch()) {
431 const QString name = match.captured(1);
432 const QString argsString = match.captured(2);
433 const QStringList args = argsString.split(u',', Qt::SkipEmptyParts);
435 provider.tracepoints << parseTracepoint(provider, name, args, filename, lineNumber);
437 panic(
"Syntax error while processing '%s' line %d:\n"
438 " '%s' does not look like a tracepoint definition",
444 if (parsingPrefixText) {
445 panic(
"Syntax error while processing '%s': "
446 "no closing brace found for prefix text block",
451 qDebug() << provider.prefixText;
452 for (
auto i = provider.tracepoints.constBegin(); i != provider.tracepoints.constEnd(); ++i)