1*e5dd7070Spatrick //===----- FormatStringParsing.h - Format String Parsing --------*- C++ -*-===//
2*e5dd7070Spatrick //
3*e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5*e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*e5dd7070Spatrick //
7*e5dd7070Spatrick //===----------------------------------------------------------------------===//
8*e5dd7070Spatrick //
9*e5dd7070Spatrick // This provides some shared functions between printf and scanf format string
10*e5dd7070Spatrick // parsing code.
11*e5dd7070Spatrick //
12*e5dd7070Spatrick //===----------------------------------------------------------------------===//
13*e5dd7070Spatrick 
14*e5dd7070Spatrick #ifndef LLVM_CLANG_LIB_ANALYSIS_FORMATSTRINGPARSING_H
15*e5dd7070Spatrick #define LLVM_CLANG_LIB_ANALYSIS_FORMATSTRINGPARSING_H
16*e5dd7070Spatrick 
17*e5dd7070Spatrick #include "clang/AST/ASTContext.h"
18*e5dd7070Spatrick #include "clang/AST/Type.h"
19*e5dd7070Spatrick #include "clang/AST/FormatString.h"
20*e5dd7070Spatrick 
21*e5dd7070Spatrick namespace clang {
22*e5dd7070Spatrick 
23*e5dd7070Spatrick class LangOptions;
24*e5dd7070Spatrick 
25*e5dd7070Spatrick template <typename T>
26*e5dd7070Spatrick class UpdateOnReturn {
27*e5dd7070Spatrick   T &ValueToUpdate;
28*e5dd7070Spatrick   const T &ValueToCopy;
29*e5dd7070Spatrick public:
UpdateOnReturn(T & valueToUpdate,const T & valueToCopy)30*e5dd7070Spatrick   UpdateOnReturn(T &valueToUpdate, const T &valueToCopy)
31*e5dd7070Spatrick     : ValueToUpdate(valueToUpdate), ValueToCopy(valueToCopy) {}
32*e5dd7070Spatrick 
~UpdateOnReturn()33*e5dd7070Spatrick   ~UpdateOnReturn() {
34*e5dd7070Spatrick     ValueToUpdate = ValueToCopy;
35*e5dd7070Spatrick   }
36*e5dd7070Spatrick };
37*e5dd7070Spatrick 
38*e5dd7070Spatrick namespace analyze_format_string {
39*e5dd7070Spatrick 
40*e5dd7070Spatrick OptionalAmount ParseAmount(const char *&Beg, const char *E);
41*e5dd7070Spatrick OptionalAmount ParseNonPositionAmount(const char *&Beg, const char *E,
42*e5dd7070Spatrick                                       unsigned &argIndex);
43*e5dd7070Spatrick 
44*e5dd7070Spatrick OptionalAmount ParsePositionAmount(FormatStringHandler &H,
45*e5dd7070Spatrick                                    const char *Start, const char *&Beg,
46*e5dd7070Spatrick                                    const char *E, PositionContext p);
47*e5dd7070Spatrick 
48*e5dd7070Spatrick bool ParseFieldWidth(FormatStringHandler &H,
49*e5dd7070Spatrick                      FormatSpecifier &CS,
50*e5dd7070Spatrick                      const char *Start, const char *&Beg, const char *E,
51*e5dd7070Spatrick                      unsigned *argIndex);
52*e5dd7070Spatrick 
53*e5dd7070Spatrick bool ParseArgPosition(FormatStringHandler &H,
54*e5dd7070Spatrick                       FormatSpecifier &CS, const char *Start,
55*e5dd7070Spatrick                       const char *&Beg, const char *E);
56*e5dd7070Spatrick 
57*e5dd7070Spatrick bool ParseVectorModifier(FormatStringHandler &H,
58*e5dd7070Spatrick                          FormatSpecifier &FS, const char *&Beg, const char *E,
59*e5dd7070Spatrick                          const LangOptions &LO);
60*e5dd7070Spatrick 
61*e5dd7070Spatrick /// Returns true if a LengthModifier was parsed and installed in the
62*e5dd7070Spatrick /// FormatSpecifier& argument, and false otherwise.
63*e5dd7070Spatrick bool ParseLengthModifier(FormatSpecifier &FS, const char *&Beg, const char *E,
64*e5dd7070Spatrick                          const LangOptions &LO, bool IsScanf = false);
65*e5dd7070Spatrick 
66*e5dd7070Spatrick /// Returns true if the invalid specifier in \p SpecifierBegin is a UTF-8
67*e5dd7070Spatrick /// string; check that it won't go further than \p FmtStrEnd and write
68*e5dd7070Spatrick /// up the total size in \p Len.
69*e5dd7070Spatrick bool ParseUTF8InvalidSpecifier(const char *SpecifierBegin,
70*e5dd7070Spatrick                                const char *FmtStrEnd, unsigned &Len);
71*e5dd7070Spatrick 
72*e5dd7070Spatrick template <typename T> class SpecifierResult {
73*e5dd7070Spatrick   T FS;
74*e5dd7070Spatrick   const char *Start;
75*e5dd7070Spatrick   bool Stop;
76*e5dd7070Spatrick public:
77*e5dd7070Spatrick   SpecifierResult(bool stop = false)
Start(nullptr)78*e5dd7070Spatrick   : Start(nullptr), Stop(stop) {}
SpecifierResult(const char * start,const T & fs)79*e5dd7070Spatrick   SpecifierResult(const char *start,
80*e5dd7070Spatrick                   const T &fs)
81*e5dd7070Spatrick   : FS(fs), Start(start), Stop(false) {}
82*e5dd7070Spatrick 
getStart()83*e5dd7070Spatrick   const char *getStart() const { return Start; }
shouldStop()84*e5dd7070Spatrick   bool shouldStop() const { return Stop; }
hasValue()85*e5dd7070Spatrick   bool hasValue() const { return Start != nullptr; }
getValue()86*e5dd7070Spatrick   const T &getValue() const {
87*e5dd7070Spatrick     assert(hasValue());
88*e5dd7070Spatrick     return FS;
89*e5dd7070Spatrick   }
getValue()90*e5dd7070Spatrick   const T &getValue() { return FS; }
91*e5dd7070Spatrick };
92*e5dd7070Spatrick 
93*e5dd7070Spatrick } // end analyze_format_string namespace
94*e5dd7070Spatrick } // end clang namespace
95*e5dd7070Spatrick 
96*e5dd7070Spatrick #endif
97