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