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 24 EntryPoint::EntryPoint() 25 { 26 reset(); 27 } 28 29 EntryPoint::~EntryPoint() 30 { 31 } 32 33 void EntryPoint::reset() 34 { 35 m_unsupported = false; 36 m_customDecoder = false; 37 m_notApi = false; 38 m_vars.empty(); 39 } 40 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) 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 156 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 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 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 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