1 /*
2 * Copyright 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "code_gen/CodeGenBase.h"
18
19 #include <limits.h>
20 #include <stdlib.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24
25 #include <cstdint>
26 #include <fstream>
27 #include <iostream>
28 #include <sstream>
29 #include <string>
30
31 #include <hidl-util/Formatter.h>
32
33 #include "specification_parser/InterfaceSpecificationParser.h"
34 #include "utils/InterfaceSpecUtil.h"
35
36 #include "test/vts/proto/ComponentSpecificationMessage.pb.h"
37
38 #include "VtsCompilerUtils.h"
39 #include "code_gen/driver/HalCodeGen.h"
40 #include "code_gen/driver/HalSubmoduleCodeGen.h"
41 #include "code_gen/driver/HalHidlCodeGen.h"
42 #include "code_gen/driver/LegacyHalCodeGen.h"
43 #include "code_gen/driver/LibSharedCodeGen.h"
44 #include "code_gen/fuzzer/FuzzerCodeGenBase.h"
45 #include "code_gen/fuzzer/HalHidlFuzzerCodeGen.h"
46 #include "code_gen/profiler/ProfilerCodeGenBase.h"
47 #include "code_gen/profiler/HalHidlProfilerCodeGen.h"
48
49 using namespace std;
50
51 namespace android {
52 namespace vts {
53
CodeGenBase(const char * input_vts_file_path,const string & vts_name)54 CodeGenBase::CodeGenBase(const char* input_vts_file_path, const string& vts_name)
55 : input_vts_file_path_(input_vts_file_path), vts_name_(vts_name) {}
56
~CodeGenBase()57 CodeGenBase::~CodeGenBase() {}
58
59 // TODO(yim): deprecate this function after type specific translate functions
60 // are used.
Translate(VtsCompileMode mode,const char * input_vts_file_path,const char * output_header_dir_path,const char * output_cpp_file_path)61 void Translate(VtsCompileMode mode,
62 const char* input_vts_file_path,
63 const char* output_header_dir_path,
64 const char* output_cpp_file_path) {
65 string output_cpp_file_path_str = string(output_cpp_file_path);
66
67 size_t found;
68 found = output_cpp_file_path_str.find_last_of("/");
69 string vts_name = output_cpp_file_path_str
70 .substr(found + 1, output_cpp_file_path_str.length() - found - 5);
71
72 ComponentSpecificationMessage message;
73 if (!InterfaceSpecificationParser::parse(input_vts_file_path, &message)) {
74 cerr << "can't parse " << input_vts_file_path << endl;
75 exit(-1);
76 }
77
78 string output_header_file_path = string(output_header_dir_path) + "/"
79 + string(input_vts_file_path);
80 output_header_file_path = output_header_file_path + ".h";
81
82 vts_fs_mkdirs(&output_header_file_path[0], 0777);
83
84 FILE* header_file = fopen(output_header_file_path.c_str(), "w");
85 if (header_file == NULL) {
86 cerr << "could not open file " << output_header_file_path;
87 exit(-1);
88 }
89 Formatter header_out(header_file);
90
91 FILE* source_file = fopen(output_cpp_file_path, "w");
92 if (source_file == NULL) {
93 cerr << "could not open file " << output_cpp_file_path;
94 exit(-1);
95 }
96 Formatter source_out(source_file);
97
98 if (mode == kDriver) {
99 unique_ptr<CodeGenBase> code_generator;
100 switch (message.component_class()) {
101 case HAL_CONVENTIONAL:
102 code_generator.reset(new HalCodeGen(input_vts_file_path, vts_name));
103 break;
104 case HAL_CONVENTIONAL_SUBMODULE:
105 code_generator.reset(
106 new HalSubmoduleCodeGen(input_vts_file_path, vts_name));
107 break;
108 case HAL_LEGACY:
109 code_generator.reset(
110 new LegacyHalCodeGen(input_vts_file_path, vts_name));
111 break;
112 case LIB_SHARED:
113 code_generator.reset(
114 new LibSharedCodeGen(input_vts_file_path, vts_name));
115 break;
116 case HAL_HIDL:
117 code_generator.reset(new HalHidlCodeGen(input_vts_file_path, vts_name));
118 break;
119 default:
120 cerr << "not yet supported component_class "
121 << message.component_class();
122 exit(-1);
123 }
124 code_generator->GenerateAll(header_out, source_out, message);
125 } else if (mode == kFuzzer) {
126 unique_ptr<FuzzerCodeGenBase> fuzzer_generator;
127 switch (message.component_class()) {
128 case HAL_HIDL:
129 fuzzer_generator = make_unique<HalHidlFuzzerCodeGen>(message);
130 break;
131 default:
132 cerr << "not yet supported component_class "
133 << message.component_class();
134 exit(-1);
135 }
136 fuzzer_generator->GenerateAll(header_out, source_out);
137 } else if (mode == kProfiler) {
138 unique_ptr<ProfilerCodeGenBase> profiler_generator;
139 switch (message.component_class()) {
140 case HAL_HIDL:
141 profiler_generator.reset(
142 new HalHidlProfilerCodeGen(input_vts_file_path));
143 break;
144 default:
145 cerr << "not yet supported component_class "
146 << message.component_class();
147 exit(-1);
148 }
149 profiler_generator->GenerateAll(header_out, source_out, message);
150 }
151 }
152
TranslateToFile(VtsCompileMode mode,const char * input_vts_file_path,const char * output_file_path,VtsCompileFileType file_type)153 void TranslateToFile(VtsCompileMode mode,
154 const char* input_vts_file_path,
155 const char* output_file_path,
156 VtsCompileFileType file_type) {
157 string output_cpp_file_path_str = string(output_file_path);
158
159 size_t found;
160 found = output_cpp_file_path_str.find_last_of("/");
161 string vts_name = output_cpp_file_path_str
162 .substr(found + 1, output_cpp_file_path_str.length() - found - 5);
163
164 ComponentSpecificationMessage message;
165 if (!InterfaceSpecificationParser::parse(input_vts_file_path, &message)) {
166 cerr << __func__ << " can't parse " << input_vts_file_path << endl;
167 }
168
169 FILE* output_file = fopen(output_file_path, "w");
170 if (output_file == NULL) {
171 cerr << __func__ << " could not open file " << output_file_path << endl;
172 exit(-1);
173 }
174 Formatter out(output_file);
175
176 if (mode == kDriver) {
177 unique_ptr<CodeGenBase> code_generator;
178 switch (message.component_class()) {
179 case HAL_CONVENTIONAL:
180 code_generator.reset(new HalCodeGen(input_vts_file_path, vts_name));
181 break;
182 case HAL_CONVENTIONAL_SUBMODULE:
183 code_generator.reset(
184 new HalSubmoduleCodeGen(input_vts_file_path, vts_name));
185 break;
186 case HAL_LEGACY:
187 code_generator.reset(
188 new LegacyHalCodeGen(input_vts_file_path, vts_name));
189 break;
190 case LIB_SHARED:
191 code_generator.reset(
192 new LibSharedCodeGen(input_vts_file_path, vts_name));
193 break;
194 case HAL_HIDL:
195 code_generator.reset(new HalHidlCodeGen(input_vts_file_path, vts_name));
196 break;
197 default:
198 cerr << "not yet supported component_class "
199 << message.component_class();
200 exit(-1);
201 }
202 if (file_type == kHeader) {
203 code_generator->GenerateHeaderFile(out, message);
204 } else if (file_type == kSource){
205 code_generator->GenerateSourceFile(out, message);
206 } else {
207 cerr << __func__ << " doesn't support file_type = kBoth." << endl;
208 exit(-1);
209 }
210 } else if (mode == kFuzzer) {
211 unique_ptr<FuzzerCodeGenBase> fuzzer_generator;
212 switch (message.component_class()) {
213 case HAL_HIDL:
214 {
215 fuzzer_generator = make_unique<HalHidlFuzzerCodeGen>(message);
216 break;
217 }
218 default:
219 cerr << "not yet supported component_class "
220 << message.component_class();
221 exit(-1);
222 }
223 if (file_type == kHeader) {
224 fuzzer_generator->GenerateHeaderFile(out);
225 } else if (file_type == kSource){
226 fuzzer_generator->GenerateSourceFile(out);
227 } else {
228 cerr << __func__ << " doesn't support file_type = kBoth." << endl;
229 exit(-1);
230 }
231 } else if (mode == kProfiler) {
232 unique_ptr<ProfilerCodeGenBase> profiler_generator;
233 switch (message.component_class()) {
234 case HAL_HIDL:
235 profiler_generator.reset(
236 new HalHidlProfilerCodeGen(input_vts_file_path));
237 break;
238 default:
239 cerr << "not yet supported component_class "
240 << message.component_class();
241 exit(-1);
242 }
243 if (file_type == kHeader) {
244 profiler_generator->GenerateHeaderFile(out, message);
245 } else if (file_type == kSource){
246 profiler_generator->GenerateSourceFile(out, message);
247 } else {
248 cerr << __func__ << " doesn't support file_type = kBoth." << endl;
249 exit(-1);
250 }
251 }
252 }
253
254 } // namespace vts
255 } // namespace android
256