• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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