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