1 /*
2 * Copyright (C) 2011 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 #include "EntryPoint.h"
17
18 #include "Parser.h"
19 #include "TypeFactory.h"
20 #include "strUtils.h"
21
22 #include <sstream>
23 #include <string>
24
25 #include <stdio.h>
26
EntryPoint()27 EntryPoint::EntryPoint()
28 {
29 reset();
30 }
31
~EntryPoint()32 EntryPoint::~EntryPoint()
33 {
34 }
35
reset()36 void EntryPoint::reset()
37 {
38 m_unsupported = false;
39 m_customDecoder = false;
40 m_notApi = false;
41 m_flushOnEncode = false;
42 m_vars.empty();
43 }
44
45 // return true for valid line (need to get into the entry points list)
parse(unsigned int lc,const std::string & str)46 bool EntryPoint::parse(unsigned int lc, const std::string & str)
47 {
48 size_t pos, last;
49 std::string field;
50
51 reset();
52 std::string linestr = trim(str);
53
54 if (linestr.size() == 0) return false;
55 if (linestr.at(0) == '#') return false;
56
57 // skip PREFIX
58 field = getNextToken(linestr, 0, &last, "(");
59 pos = last + 1;
60 // return type
61 field = getNextToken(linestr, pos, &last, ",)");
62
63 std::string error;
64 std::string retTypeName;
65 if (!parseTypeDeclaration(field, &retTypeName, &error)) {
66 fprintf(stderr,
67 "line: %d: Parsing error in field <%s>: %s\n",
68 lc,
69 field.c_str(),
70 error.c_str());
71 return false;
72 }
73 pos = last + 1;
74 const VarType *theType = TypeFactory::instance()->getVarTypeByName(retTypeName);
75 if (theType->name() == "UNKNOWN") {
76 fprintf(stderr, "UNKNOWN retval: %s\n", linestr.c_str());
77 }
78
79 m_retval.init(std::string(""),
80 theType,
81 std::string(""),
82 Var::POINTER_OUT,
83 std::string(""),
84 std::string(""),
85 std::string(""));
86
87 // function name
88 m_name = getNextToken(linestr, pos, &last, ",)");
89 pos = last + 1;
90
91 // parameters;
92 int nvars = 0;
93 while (pos < linestr.size() - 1) {
94 field = getNextToken(linestr, pos, &last, ",)");
95 if (field == "void") {
96 // 'void' is used as a special case for functions that don't take
97 // parameters at all.
98 break;
99 }
100 std::string vartype, varname;
101 if (!parseParameterDeclaration(field, &vartype, &varname, &error)) {
102 fprintf(stderr,
103 "line: %d: Parsing error in field <%s> (%s)\n",
104 lc,
105 field.c_str(),
106 error.c_str());
107 return false;
108 }
109 nvars++;
110 const VarType *v = TypeFactory::instance()->getVarTypeByName(vartype);
111 if (v->id() == 0) {
112 fprintf(stderr, "%d: Unknown type: %s\n", lc, vartype.c_str());
113 } else {
114 if (varname == "" &&
115 !(v->name() == "void" && !v->isPointer())) {
116 std::ostringstream oss;
117 oss << "var" << nvars;
118 varname = oss.str();
119 }
120
121 m_vars.push_back(Var(varname, v, std::string(""), Var::POINTER_IN, "", "", ""));
122 }
123 pos = last + 1;
124 }
125 return true;
126 }
127
print(FILE * fp,bool newline,const std::string & name_suffix,const std::string & name_prefix,const std::string & ctx_param) const128 void EntryPoint::print(FILE *fp, bool newline,
129 const std::string & name_suffix,
130 const std::string & name_prefix,
131 const std::string & ctx_param ) const
132 {
133 fprintf(fp, "%s %s%s%s(",
134 m_retval.type()->name().c_str(),
135 name_prefix.c_str(),
136 m_name.c_str(),
137 name_suffix.c_str());
138
139 if (ctx_param != "") fprintf(fp, "%s ", ctx_param.c_str());
140
141 for (size_t i = 0; i < m_vars.size(); i++) {
142 if (m_vars[i].isVoid()) continue;
143 if (i != 0 || ctx_param != "") fprintf(fp, ", ");
144 fprintf(fp, "%s %s", m_vars[i].type()->name().c_str(),
145 m_vars[i].name().c_str());
146 }
147 fprintf(fp, ")%s", newline? "\n" : "");
148 }
149
var(const std::string & name)150 Var * EntryPoint::var(const std::string & name)
151 {
152 Var *v = NULL;
153 for (size_t i = 0; i < m_vars.size(); i++) {
154 if (m_vars[i].name() == name) {
155 v = &m_vars[i];
156 break;
157 }
158 }
159 return v;
160 }
161
var(const std::string & name) const162 const Var * EntryPoint::var(const std::string & name) const
163 {
164 const Var *v = NULL;
165 for (size_t i = 0; i < m_vars.size(); i++) {
166 if (m_vars[i].name() == name) {
167 v = &m_vars[i];
168 break;
169 }
170 }
171 return v;
172 }
173
hasPointers()174 bool EntryPoint::hasPointers()
175 {
176 bool pointers = false;
177 if (m_retval.isPointer()) pointers = true;
178 if (!pointers) {
179 for (size_t i = 0; i < m_vars.size(); i++) {
180 if (m_vars[i].isPointer()) {
181 pointers = true;
182 break;
183 }
184 }
185 }
186 return pointers;
187 }
188
validateVarAttr(const std::string & varname,size_t lc) const189 int EntryPoint::validateVarAttr(const std::string& varname, size_t lc) const {
190 if (varname.size() == 0) {
191 fprintf(stderr, "ERROR: %u: Missing variable name in attribute\n", (unsigned int)lc);
192 return -1;
193 }
194 const Var * v = var(varname);
195 if (v == NULL) {
196 fprintf(stderr, "ERROR: %u: variable %s is not a parameter of %s\n",
197 (unsigned int)lc, varname.c_str(), name().c_str());
198 return -2;
199 }
200 return 0;
201 }
202
setAttribute(const std::string & line,size_t lc)203 int EntryPoint::setAttribute(const std::string &line, size_t lc)
204 {
205 size_t pos = 0;
206 size_t last;
207 std::string token = getNextToken(line, 0, &last, WHITESPACE);
208 int err = 0;
209 Var* v = nullptr;
210
211 if (token == "len") {
212 pos = last;
213 std::string varname = getNextToken(line, pos, &last, WHITESPACE);
214 err = validateVarAttr(varname, lc);
215 if (err < 0) return err;
216
217 // set the size expression into var
218 v = var(varname);
219 pos = last;
220 v->setLenExpression(line.substr(pos));
221 } else if (token == "param_check") {
222 pos = last;
223 std::string varname = getNextToken(line, pos, &last, WHITESPACE);
224 err = validateVarAttr(varname, lc);
225 if (err < 0) return err;
226
227 v = var(varname);
228 pos = last;
229 v->setParamCheckExpression(line.substr(pos));
230
231 } else if (token == "dir") {
232 pos = last;
233 std::string varname = getNextToken(line, pos, &last, WHITESPACE);
234 err = validateVarAttr(varname, lc);
235 if (err < 0) return err;
236
237 v = var(varname);
238 pos = last;
239
240 std::string pointerDirStr = getNextToken(line, pos, &last, WHITESPACE);
241 if (pointerDirStr.size() == 0) {
242 fprintf(stderr, "ERROR: %u: missing pointer directions\n", (unsigned int)lc);
243 return -3;
244 }
245
246 if (pointerDirStr == "out") {
247 v->setPointerDir(Var::POINTER_OUT);
248 } else if (pointerDirStr == "inout") {
249 v->setPointerDir(Var::POINTER_INOUT);
250 } else if (pointerDirStr == "in") {
251 v->setPointerDir(Var::POINTER_IN);
252 } else {
253 fprintf(stderr, "ERROR: %u: unknown pointer direction %s\n",
254 (unsigned int)lc, pointerDirStr.c_str());
255 }
256 } else if (token == "var_flag") {
257 pos = last;
258 std::string varname = getNextToken(line, pos, &last, WHITESPACE);
259 err = validateVarAttr(varname, lc);
260 if (err < 0) return err;
261
262 v = var(varname);
263 int count = 0;
264 for (;;) {
265 pos = last;
266 std::string flag = getNextToken(line, pos, &last, WHITESPACE);
267 if (flag.size() == 0) {
268 if (count == 0) {
269 fprintf(stderr, "ERROR: %u: missing flag\n", (unsigned int) lc);
270 return -3;
271 }
272 break;
273 }
274 count++;
275
276 if (flag == "nullAllowed") {
277 if (v->isPointer()) {
278 v->setNullAllowed(true);
279 } else {
280 fprintf(stderr, "WARNING: %u: setting nullAllowed for non-pointer variable %s\n",
281 (unsigned int) lc, v->name().c_str());
282 }
283 } else if (flag == "isLarge") {
284 if (v->isPointer()) {
285 v->setIsLarge(true);
286 } else {
287 fprintf(stderr, "WARNING: %u: setting isLarge flag for a non-pointer variable %s\n",
288 (unsigned int) lc, v->name().c_str());
289 }
290 } else if (flag == "DMA") {
291 v->setDMA(true);
292 } else {
293 fprintf(stderr, "WARNING: %u: unknow flag %s\n", (unsigned int)lc, flag.c_str());
294 }
295 }
296 } else if (token == "custom_pack") {
297 pos = last;
298 std::string varname = getNextToken(line, pos, &last, WHITESPACE);
299 err = validateVarAttr(varname, lc);
300 if (err < 0) return err;
301
302 v = var(varname);
303 pos = last;
304 v->setPackExpression(line.substr(pos));
305 } else if (token == "custom_unpack") {
306 pos = last;
307 std::string varname = getNextToken(line, pos, &last, WHITESPACE);
308
309 err = validateVarAttr(varname, lc);
310 if (err < 0) return err;
311
312 v = var(varname);
313 pos = last;
314 v->setUnpackExpression(line.substr(pos));
315 } else if (token == "custom_host_pack_tmp_alloc") {
316 pos = last;
317 std::string varname = getNextToken(line, pos, &last, WHITESPACE);
318 err = validateVarAttr(varname, lc);
319 if (err < 0) return err;
320
321 v = var(varname);
322 if (v->pointerDir() == Var::POINTER_IN) {
323 fprintf(stderr, "ERROR: %u: variable %s is not an output or inout\n",
324 (unsigned int)lc, varname.c_str());
325 return -2;
326 }
327
328 pos = last;
329 v->setHostPackTmpAllocExpression(line.substr(pos));
330 } else if (token == "custom_host_pack") {
331 pos = last;
332 std::string varname = getNextToken(line, pos, &last, WHITESPACE);
333 err = validateVarAttr(varname, lc);
334 if (err < 0) return err;
335
336 v = var(varname);
337 if (v->pointerDir() == Var::POINTER_IN) {
338 fprintf(stderr, "ERROR: %u: variable %s is not an output or inout\n",
339 (unsigned int)lc, varname.c_str());
340 return -2;
341 }
342
343 pos = last;
344 v->setHostPackExpression(line.substr(pos));
345 } else if (token == "custom_guest_unpack") {
346 pos = last;
347 std::string varname = getNextToken(line, pos, &last, WHITESPACE);
348 err = validateVarAttr(varname, lc);
349 if (err < 0) return err;
350
351 v = var(varname);
352 if (v->pointerDir() == Var::POINTER_IN) {
353 fprintf(stderr, "ERROR: %u: variable %s is not an output or inout\n",
354 (unsigned int)lc, varname.c_str());
355 return -2;
356 }
357
358 pos = last;
359 v->setGuestUnpackExpression(line.substr(pos));
360 } else if (token == "custom_write") {
361 pos = last;
362 std::string varname = getNextToken(line, pos, &last, WHITESPACE);
363 err = validateVarAttr(varname, lc);
364 if (err < 0) return err;
365
366 // set the size expression into var
367 v = var(varname);
368 pos = last;
369 v->setWriteExpression(line.substr(pos));
370 } else if (token == "flag") {
371 pos = last;
372 std::string flag = getNextToken(line, pos, &last, WHITESPACE);
373 if (flag.size() == 0) {
374 fprintf(stderr, "ERROR: %u: missing flag\n", (unsigned int) lc);
375 return -4;
376 }
377
378 if (flag == "unsupported") {
379 setUnsupported(true);
380 } else if (flag == "custom_decoder") {
381 setCustomDecoder(true);
382 } else if (flag == "not_api") {
383 setNotApi(true);
384 } else if (flag == "flushOnEncode") {
385 setFlushOnEncode(true);
386 } else {
387 fprintf(stderr, "WARNING: %u: unknown flag %s\n", (unsigned int)lc, flag.c_str());
388 }
389 } else {
390 fprintf(stderr, "WARNING: %u: unknown attribute %s\n", (unsigned int)lc, token.c_str());
391 }
392
393 return 0;
394 }
395