Home | History | Annotate | Download | only in emugen
      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