1 // Copyright (C) 2018 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef VERSION_SCRIPT_PARSER_H_
16 #define VERSION_SCRIPT_PARSER_H_
17 
18 #include "repr/ir_representation.h"
19 #include "repr/symbol/exported_symbol_set.h"
20 #include "utils/api_level.h"
21 
22 #include <functional>
23 #include <set>
24 #include <string>
25 
26 
27 namespace header_checker {
28 namespace repr {
29 
30 
31 class VersionScriptParser {
32  private:
33   enum class LineScope {
34     GLOBAL,
35     LOCAL,
36   };
37 
38 
39   struct ParsedTags {
40    public:
41     unsigned has_arch_tags_ : 1;
42     unsigned has_current_arch_tag_ : 1;
43     unsigned has_introduced_tags_ : 1;
44     unsigned has_excluded_tags_ : 1;
45     unsigned has_future_tag_ : 1;
46     unsigned has_var_tag_ : 1;
47     unsigned has_weak_tag_ : 1;
48     utils::ApiLevel introduced_;
49 
50 
51    public:
ParsedTagsParsedTags52     ParsedTags()
53         : has_arch_tags_(0), has_current_arch_tag_(0), has_introduced_tags_(0),
54           has_excluded_tags_(0), has_future_tag_(0), has_var_tag_(0),
55           introduced_(-1) {}
56   };
57 
58 
59  public:
60   class ErrorHandler {
61    public:
62     virtual ~ErrorHandler();
63 
64     virtual void OnError(int line_no, const std::string &error_msg) = 0;
65   };
66 
67 
68  public:
69   VersionScriptParser();
70 
71   void SetArch(const std::string &arch);
72 
SetApiLevel(utils::ApiLevel api_level)73   void SetApiLevel(utils::ApiLevel api_level) {
74     api_level_ = api_level;
75   }
76 
AddExcludedSymbolVersion(const std::string & version)77   void AddExcludedSymbolVersion(const std::string &version) {
78     excluded_symbol_versions_.insert(version);
79   }
80 
AddExcludedSymbolTag(const std::string & tag)81   void AddExcludedSymbolTag(const std::string &tag) {
82     excluded_symbol_tags_.insert(tag);
83   }
84 
SetErrorHandler(std::unique_ptr<ErrorHandler> error_handler)85   void SetErrorHandler(std::unique_ptr<ErrorHandler> error_handler) {
86     error_handler_ = std::move(error_handler);
87   }
88 
89   std::unique_ptr<ExportedSymbolSet> Parse(std::istream &version_script_stream);
90 
91 
92  private:
93   bool ReadLine(std::string &line);
94 
95   bool ParseVersionBlock(bool ignore_symbols);
96 
97   bool ParseSymbolLine(const std::string &line, bool is_cpp_symbol);
98 
99   ParsedTags ParseSymbolTags(const std::string &line);
100 
101   bool IsSymbolExported(const ParsedTags &tags);
102 
103 
104  private:
ReportError(const std::string & error_msg)105   void ReportError(const std::string &error_msg) {
106     if (error_handler_) {
107       error_handler_->OnError(line_no_, error_msg);
108     }
109   }
110 
111 
112  private:
113   std::unique_ptr<ErrorHandler> error_handler_;
114 
115   std::string arch_;
116   std::string introduced_arch_tag_;
117   utils::ApiLevel api_level_;
118 
119   std::set<std::string, std::less<>> excluded_symbol_versions_;
120   std::set<std::string, std::less<>> excluded_symbol_tags_;
121 
122   std::istream *stream_;
123   int line_no_;
124 
125   std::unique_ptr<ExportedSymbolSet> exported_symbols_;
126 };
127 
128 
129 }  // namespace repr
130 }  // namespace header_checker
131 
132 
133 #endif  // VERSION_SCRIPT_PARSER_H_
134