1*a7dea167SDimitry Andric //===----- FormatStringParsing.h - Format String Parsing --------*- C++ -*-===// 2*a7dea167SDimitry Andric // 3*a7dea167SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*a7dea167SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*a7dea167SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*a7dea167SDimitry Andric // 7*a7dea167SDimitry Andric //===----------------------------------------------------------------------===// 8*a7dea167SDimitry Andric // 9*a7dea167SDimitry Andric // This provides some shared functions between printf and scanf format string 10*a7dea167SDimitry Andric // parsing code. 11*a7dea167SDimitry Andric // 12*a7dea167SDimitry Andric //===----------------------------------------------------------------------===// 13*a7dea167SDimitry Andric 140b57cec5SDimitry Andric #ifndef LLVM_CLANG_LIB_ANALYSIS_FORMATSTRINGPARSING_H 150b57cec5SDimitry Andric #define LLVM_CLANG_LIB_ANALYSIS_FORMATSTRINGPARSING_H 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric #include "clang/AST/ASTContext.h" 180b57cec5SDimitry Andric #include "clang/AST/Type.h" 190b57cec5SDimitry Andric #include "clang/AST/FormatString.h" 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric namespace clang { 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric class LangOptions; 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric template <typename T> 260b57cec5SDimitry Andric class UpdateOnReturn { 270b57cec5SDimitry Andric T &ValueToUpdate; 280b57cec5SDimitry Andric const T &ValueToCopy; 290b57cec5SDimitry Andric public: UpdateOnReturn(T & valueToUpdate,const T & valueToCopy)300b57cec5SDimitry Andric UpdateOnReturn(T &valueToUpdate, const T &valueToCopy) 310b57cec5SDimitry Andric : ValueToUpdate(valueToUpdate), ValueToCopy(valueToCopy) {} 320b57cec5SDimitry Andric ~UpdateOnReturn()330b57cec5SDimitry Andric ~UpdateOnReturn() { 340b57cec5SDimitry Andric ValueToUpdate = ValueToCopy; 350b57cec5SDimitry Andric } 360b57cec5SDimitry Andric }; 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric namespace analyze_format_string { 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric OptionalAmount ParseAmount(const char *&Beg, const char *E); 410b57cec5SDimitry Andric OptionalAmount ParseNonPositionAmount(const char *&Beg, const char *E, 420b57cec5SDimitry Andric unsigned &argIndex); 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric OptionalAmount ParsePositionAmount(FormatStringHandler &H, 450b57cec5SDimitry Andric const char *Start, const char *&Beg, 460b57cec5SDimitry Andric const char *E, PositionContext p); 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric bool ParseFieldWidth(FormatStringHandler &H, 490b57cec5SDimitry Andric FormatSpecifier &CS, 500b57cec5SDimitry Andric const char *Start, const char *&Beg, const char *E, 510b57cec5SDimitry Andric unsigned *argIndex); 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric bool ParseArgPosition(FormatStringHandler &H, 540b57cec5SDimitry Andric FormatSpecifier &CS, const char *Start, 550b57cec5SDimitry Andric const char *&Beg, const char *E); 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric bool ParseVectorModifier(FormatStringHandler &H, 580b57cec5SDimitry Andric FormatSpecifier &FS, const char *&Beg, const char *E, 590b57cec5SDimitry Andric const LangOptions &LO); 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric /// Returns true if a LengthModifier was parsed and installed in the 620b57cec5SDimitry Andric /// FormatSpecifier& argument, and false otherwise. 630b57cec5SDimitry Andric bool ParseLengthModifier(FormatSpecifier &FS, const char *&Beg, const char *E, 640b57cec5SDimitry Andric const LangOptions &LO, bool IsScanf = false); 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric /// Returns true if the invalid specifier in \p SpecifierBegin is a UTF-8 670b57cec5SDimitry Andric /// string; check that it won't go further than \p FmtStrEnd and write 680b57cec5SDimitry Andric /// up the total size in \p Len. 690b57cec5SDimitry Andric bool ParseUTF8InvalidSpecifier(const char *SpecifierBegin, 700b57cec5SDimitry Andric const char *FmtStrEnd, unsigned &Len); 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric template <typename T> class SpecifierResult { 730b57cec5SDimitry Andric T FS; 740b57cec5SDimitry Andric const char *Start; 750b57cec5SDimitry Andric bool Stop; 760b57cec5SDimitry Andric public: 770b57cec5SDimitry Andric SpecifierResult(bool stop = false) Start(nullptr)780b57cec5SDimitry Andric : Start(nullptr), Stop(stop) {} SpecifierResult(const char * start,const T & fs)790b57cec5SDimitry Andric SpecifierResult(const char *start, 800b57cec5SDimitry Andric const T &fs) 810b57cec5SDimitry Andric : FS(fs), Start(start), Stop(false) {} 820b57cec5SDimitry Andric getStart()830b57cec5SDimitry Andric const char *getStart() const { return Start; } shouldStop()840b57cec5SDimitry Andric bool shouldStop() const { return Stop; } hasValue()850b57cec5SDimitry Andric bool hasValue() const { return Start != nullptr; } getValue()860b57cec5SDimitry Andric const T &getValue() const { 870b57cec5SDimitry Andric assert(hasValue()); 880b57cec5SDimitry Andric return FS; 890b57cec5SDimitry Andric } getValue()900b57cec5SDimitry Andric const T &getValue() { return FS; } 910b57cec5SDimitry Andric }; 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric } // end analyze_format_string namespace 940b57cec5SDimitry Andric } // end clang namespace 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric #endif 97