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