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