Home | History | Annotate | Download | only in rs
      1 
      2 #include "spec.h"
      3 #include <stdio.h>
      4 #include <string.h>
      5 
      6 void printFileHeader(FILE *f) {
      7     fprintf(f, "/*\n");
      8     fprintf(f, " * Copyright (C) 2011 The Android Open Source Project\n");
      9     fprintf(f, " *\n");
     10     fprintf(f, " * Licensed under the Apache License, Version 2.0 (the \"License\");\n");
     11     fprintf(f, " * you may not use this file except in compliance with the License.\n");
     12     fprintf(f, " * You may obtain a copy of the License at\n");
     13     fprintf(f, " *\n");
     14     fprintf(f, " *      http://www.apache.org/licenses/LICENSE-2.0\n");
     15     fprintf(f, " *\n");
     16     fprintf(f, " * Unless required by applicable law or agreed to in writing, software\n");
     17     fprintf(f, " * distributed under the License is distributed on an \"AS IS\" BASIS,\n");
     18     fprintf(f, " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n");
     19     fprintf(f, " * See the License for the specific language governing permissions and\n");
     20     fprintf(f, " * limitations under the License.\n");
     21     fprintf(f, " */\n\n");
     22 }
     23 
     24 void printVarType(FILE *f, const VarType *vt) {
     25     int ct;
     26     if (vt->isConst) {
     27         fprintf(f, "const ");
     28     }
     29 
     30     switch (vt->type) {
     31     case 0:
     32         fprintf(f, "void");
     33         break;
     34     case 1:
     35         fprintf(f, "int%i_t", vt->bits);
     36         break;
     37     case 2:
     38         fprintf(f, "uint%i_t", vt->bits);
     39         break;
     40     case 3:
     41         if (vt->bits == 32)
     42             fprintf(f, "float");
     43         else
     44             fprintf(f, "double");
     45         break;
     46     case 4:
     47         fprintf(f, "%s", vt->typeName);
     48         break;
     49     }
     50 
     51     if (vt->ptrLevel) {
     52         fprintf(f, " ");
     53         for (ct=0; ct < vt->ptrLevel; ct++) {
     54             fprintf(f, "*");
     55         }
     56     }
     57 }
     58 
     59 void printVarTypeAndName(FILE *f, const VarType *vt) {
     60     printVarType(f, vt);
     61 
     62     if (vt->name[0]) {
     63         fprintf(f, " %s", vt->name);
     64     }
     65 }
     66 
     67 void printArgList(FILE *f, const ApiEntry * api, int assumePrevious) {
     68     int ct;
     69     for (ct=0; ct < api->paramCount; ct++) {
     70         if (ct || assumePrevious) {
     71             fprintf(f, ", ");
     72         }
     73         printVarTypeAndName(f, &api->params[ct]);
     74     }
     75 }
     76 
     77 void printStructures(FILE *f) {
     78     int ct;
     79     int ct2;
     80 
     81     for (ct=0; ct < apiCount; ct++) {
     82         fprintf(f, "typedef struct RS_CMD_%s_rec RS_CMD_%s;\n", apis[ct].name, apis[ct].name);
     83     }
     84     fprintf(f, "\n");
     85 
     86     for (ct=0; ct < apiCount; ct++) {
     87         const ApiEntry * api = &apis[ct];
     88         fprintf(f, "#define RS_CMD_ID_%s %i\n", api->name, ct+1);
     89         fprintf(f, "struct __attribute__((packed)) RS_CMD_%s_rec {\n", api->name);
     90         //fprintf(f, "    RsCommandHeader _hdr;\n");
     91 
     92         for (ct2=0; ct2 < api->paramCount; ct2++) {
     93             fprintf(f, "    ");
     94             printVarTypeAndName(f, &api->params[ct2]);
     95             fprintf(f, ";\n");
     96         }
     97         fprintf(f, "};\n\n");
     98     }
     99 }
    100 
    101 void printFuncDecl(FILE *f, const ApiEntry *api, const char *prefix, int addContext, int isFnPtr) {
    102     printVarTypeAndName(f, &api->ret);
    103     if (isFnPtr) {
    104         char t[1024];
    105         strcpy(t, api->name);
    106         if (strlen(prefix) == 0) {
    107             if (t[0] > 'A' && t[0] < 'Z') {
    108                 t[0] -= 'A' - 'a';
    109             }
    110         }
    111         fprintf(f, " (* %s%s) (", prefix, api->name);
    112     } else {
    113         fprintf(f, " %s%s (", prefix, api->name);
    114     }
    115     if (!api->nocontext) {
    116         if (addContext) {
    117             fprintf(f, "Context *");
    118         } else {
    119             fprintf(f, "RsContext rsc");
    120         }
    121     }
    122     printArgList(f, api, !api->nocontext);
    123     fprintf(f, ")");
    124 }
    125 
    126 void printFuncDecls(FILE *f, const char *prefix, int addContext, int externC) {
    127     int ct;
    128     for (ct=0; ct < apiCount; ct++) {
    129         if (externC) {
    130             fprintf(f, "extern \"C\" ");
    131         }
    132         printFuncDecl(f, &apis[ct], prefix, addContext, 0);
    133         fprintf(f, ";\n");
    134     }
    135     fprintf(f, "\n\n");
    136 }
    137 
    138 void printFuncPointers(FILE *f, int addContext) {
    139     fprintf(f, "\n");
    140     fprintf(f, "typedef struct RsApiEntrypoints {\n");
    141     int ct;
    142     for (ct=0; ct < apiCount; ct++) {
    143         fprintf(f, "    ");
    144         printFuncDecl(f, &apis[ct], "", addContext, 1);
    145         fprintf(f, ";\n");
    146     }
    147     fprintf(f, "} RsApiEntrypoints_t;\n\n");
    148 }
    149 
    150 void printPlaybackFuncs(FILE *f, const char *prefix) {
    151     int ct;
    152     for (ct=0; ct < apiCount; ct++) {
    153         if (apis[ct].direct) {
    154             continue;
    155         }
    156 
    157         fprintf(f, "void %s%s (Context *, const void *);\n", prefix, apis[ct].name);
    158     }
    159 }
    160 
    161 static int hasInlineDataPointers(const ApiEntry * api) {
    162     int ret = 0;
    163     int ct;
    164     if (api->sync || api->ret.typeName[0]) {
    165         return 0;
    166     }
    167     for (ct=0; ct < api->paramCount; ct++) {
    168         const VarType *vt = &api->params[ct];
    169 
    170         if (!vt->isConst && vt->ptrLevel) {
    171             // Non-const pointers cannot be inlined.
    172             return 0;
    173         }
    174         if (vt->ptrLevel > 1) {
    175             // not handled yet.
    176             return 0;
    177         }
    178 
    179         if (vt->isConst && vt->ptrLevel) {
    180             // Non-const pointers cannot be inlined.
    181             ret = 1;
    182         }
    183     }
    184     return ret;
    185 }
    186 
    187 void printApiCpp(FILE *f) {
    188     int ct;
    189     int ct2;
    190 
    191     fprintf(f, "#include \"rsDevice.h\"\n");
    192     fprintf(f, "#include \"rsContext.h\"\n");
    193     fprintf(f, "#include \"rsThreadIO.h\"\n");
    194     fprintf(f, "#include \"rsgApiStructs.h\"\n");
    195     fprintf(f, "#include \"rsgApiFuncDecl.h\"\n");
    196     fprintf(f, "#include \"rsFifo.h\"\n");
    197     fprintf(f, "\n");
    198     fprintf(f, "using namespace android;\n");
    199     fprintf(f, "using namespace android::renderscript;\n");
    200     fprintf(f, "\n");
    201 
    202     printFuncPointers(f, 0);
    203 
    204     // Generate RS funcs for local fifo
    205     for (ct=0; ct < apiCount; ct++) {
    206         int needFlush = 0;
    207         const ApiEntry * api = &apis[ct];
    208 
    209         fprintf(f, "static ");
    210         printFuncDecl(f, api, "LF_", 0, 0);
    211         fprintf(f, "\n{\n");
    212         if (api->direct) {
    213             fprintf(f, "    ");
    214             if (api->ret.typeName[0]) {
    215                 fprintf(f, "return ");
    216             }
    217             fprintf(f, "rsi_%s(", api->name);
    218             if (!api->nocontext) {
    219                 fprintf(f, "(Context *)rsc");
    220             }
    221             for (ct2=0; ct2 < api->paramCount; ct2++) {
    222                 const VarType *vt = &api->params[ct2];
    223                 if (ct2 > 0 || !api->nocontext) {
    224                     fprintf(f, ", ");
    225                 }
    226                 fprintf(f, "%s", vt->name);
    227             }
    228             fprintf(f, ");\n");
    229         } else if (api->handcodeApi) {
    230             // handle handcode path
    231             fprintf(f, "    LF_%s_handcode(", api->name);
    232             if (!api->nocontext) {
    233                 fprintf(f, "(Context *)rsc");
    234             }
    235             for (ct2=0; ct2 < api->paramCount; ct2++) {
    236                 const VarType *vt = &api->params[ct2];
    237                 if (ct2 > 0 || !api->nocontext) {
    238                     fprintf(f, ", ");
    239                 }
    240                 fprintf(f, "%s", vt->name);
    241             }
    242             fprintf(f, ");\n");
    243 
    244         } else {
    245             // handle synchronous path
    246             fprintf(f, "    if (((Context *)rsc)->isSynchronous()) {\n");
    247             fprintf(f, "        ");
    248             if (api->ret.typeName[0]) {
    249                 fprintf(f, "return ");
    250             }
    251             fprintf(f, "rsi_%s(", api->name);
    252             if (!api->nocontext) {
    253                 fprintf(f, "(Context *)rsc");
    254             }
    255             for (ct2=0; ct2 < api->paramCount; ct2++) {
    256                 const VarType *vt = &api->params[ct2];
    257                 if (ct2 > 0 || !api->nocontext) {
    258                     fprintf(f, ", ");
    259                 }
    260                 fprintf(f, "%s", vt->name);
    261             }
    262             fprintf(f, ");\n");
    263             if (!api->ret.typeName[0]) {
    264                 fprintf(f, "    return;");
    265             }
    266             fprintf(f, "    }\n\n");
    267 
    268             fprintf(f, "    ThreadIO *io = &((Context *)rsc)->mIO;\n");
    269             fprintf(f, "    const size_t size = sizeof(RS_CMD_%s);\n", api->name);
    270             if (hasInlineDataPointers(api)) {
    271                 fprintf(f, "    size_t dataSize = 0;\n");
    272                 for (ct2=0; ct2 < api->paramCount; ct2++) {
    273                     const VarType *vt = &api->params[ct2];
    274                     if (vt->isConst && vt->ptrLevel) {
    275                         fprintf(f, "    dataSize += %s_length;\n", vt->name);
    276                     }
    277                 }
    278             }
    279 
    280             //fprintf(f, "    ALOGE(\"add command %s\\n\");\n", api->name);
    281             if (hasInlineDataPointers(api)) {
    282                 fprintf(f, "    RS_CMD_%s *cmd = NULL;\n", api->name);
    283                 fprintf(f, "    if (dataSize < io->getMaxInlineSize()) {;\n");
    284                 fprintf(f, "        cmd = static_cast<RS_CMD_%s *>(io->coreHeader(RS_CMD_ID_%s, dataSize + size));\n", api->name, api->name);
    285                 fprintf(f, "    } else {\n");
    286                 fprintf(f, "        cmd = static_cast<RS_CMD_%s *>(io->coreHeader(RS_CMD_ID_%s, size));\n", api->name, api->name);
    287                 fprintf(f, "    }\n");
    288                 fprintf(f, "    uint8_t *payload = (uint8_t *)&cmd[1];\n");
    289             } else {
    290                 fprintf(f, "    RS_CMD_%s *cmd = static_cast<RS_CMD_%s *>(io->coreHeader(RS_CMD_ID_%s, size));\n", api->name, api->name, api->name);
    291             }
    292 
    293             for (ct2=0; ct2 < api->paramCount; ct2++) {
    294                 const VarType *vt = &api->params[ct2];
    295                 needFlush += vt->ptrLevel;
    296                 if (vt->ptrLevel && hasInlineDataPointers(api)) {
    297                     fprintf(f, "    if (dataSize < io->getMaxInlineSize()) {\n");
    298                     fprintf(f, "        memcpy(payload, %s, %s_length);\n", vt->name, vt->name);
    299                     fprintf(f, "        cmd->%s = (", vt->name);
    300                     printVarType(f, vt);
    301                     fprintf(f, ")(payload - ((uint8_t *)&cmd[1]));\n");
    302                     fprintf(f, "        payload += %s_length;\n", vt->name);
    303                     fprintf(f, "    } else {\n");
    304                     fprintf(f, "        cmd->%s = %s;\n", vt->name, vt->name);
    305                     fprintf(f, "    }\n");
    306 
    307                 } else {
    308                     fprintf(f, "    cmd->%s = %s;\n", vt->name, vt->name);
    309                 }
    310             }
    311             if (api->ret.typeName[0] || api->sync) {
    312                 needFlush = 1;
    313             }
    314 
    315             fprintf(f, "    io->coreCommit();\n");
    316             if (hasInlineDataPointers(api)) {
    317                 fprintf(f, "    if (dataSize >= io->getMaxInlineSize()) {\n");
    318                 fprintf(f, "        io->coreGetReturn(NULL, 0);\n");
    319                 fprintf(f, "    }\n");
    320             } else if (api->ret.typeName[0]) {
    321                 fprintf(f, "\n    ");
    322                 printVarType(f, &api->ret);
    323                 fprintf(f, " ret;\n");
    324                 fprintf(f, "    io->coreGetReturn(&ret, sizeof(ret));\n");
    325                 fprintf(f, "    return ret;\n");
    326             } else if (needFlush) {
    327                 fprintf(f, "    io->coreGetReturn(NULL, 0);\n");
    328             }
    329         }
    330         fprintf(f, "};\n\n");
    331 
    332 
    333         // Generate a remote sender function
    334         const char * str = "core";
    335         if (api->direct) {
    336             str = "async";
    337         }
    338 
    339         fprintf(f, "static ");
    340         printFuncDecl(f, api, "RF_", 0, 0);
    341         fprintf(f, "\n{\n");
    342         fprintf(f, "    ThreadIO *io = &((Context *)rsc)->mIO;\n");
    343         fprintf(f, "    const uint32_t cmdID = RS_CMD_ID_%s;\n", api->name);
    344         fprintf(f, "    io->%sWrite(&cmdID, sizeof(cmdID));\n\n", str);
    345 
    346         for (ct2=0; ct2 < api->paramCount; ct2++) {
    347             const VarType *vt = &api->params[ct2];
    348             if (vt->ptrLevel == 0) {
    349                 fprintf(f, "    io->%sWrite(& %s, sizeof(%s));\n", str, vt->name, vt->name);
    350             }
    351         }
    352         fprintf(f, "\n");
    353 
    354         for (ct2=0; ct2 < api->paramCount; ct2++) {
    355             const VarType *vt = &api->params[ct2];
    356             if ((vt->ptrLevel == 1) && (vt->isConst)) {
    357                 fprintf(f, "    io->%sWrite(%s, %s_length);\n", str, vt->name, vt->name);
    358             }
    359         }
    360         fprintf(f, "\n");
    361 
    362         for (ct2=0; ct2 < api->paramCount; ct2++) {
    363             const VarType *vt = &api->params[ct2];
    364             if ((vt->ptrLevel == 2) && (vt->isConst)) {
    365                 fprintf(f, "    for (size_t ct = 0; ct < (%s_length_length / sizeof(%s_length)); ct++) {\n", vt->name, vt->name);
    366                 fprintf(f, "        io->%sWrite(%s[ct], %s_length[ct]);\n", str, vt->name, vt->name);
    367                 fprintf(f, "    }\n");
    368             }
    369         }
    370         fprintf(f, "\n");
    371 
    372         for (ct2=0; ct2 < api->paramCount; ct2++) {
    373             const VarType *vt = &api->params[ct2];
    374             if ((vt->ptrLevel == 1) && (!vt->isConst)) {
    375                 fprintf(f, "    io->%sGetReturn(%s, %s_length);\n", str, vt->name, vt->name);
    376             }
    377         }
    378         fprintf(f, "\n");
    379 
    380         for (ct2=0; ct2 < api->paramCount; ct2++) {
    381             const VarType *vt = &api->params[ct2];
    382             if ((vt->ptrLevel == 2) && (!vt->isConst)) {
    383                 fprintf(f, "    for (size_t ct = 0; ct < (%s_length_length / sizeof(%s_length)); ct++) {\n", vt->name, vt->name);
    384                 fprintf(f, "        io->%sGetReturn(%s[ct], %s_length[ct]);\n", str, vt->name, vt->name);
    385                 fprintf(f, "    }\n");
    386             }
    387         }
    388         fprintf(f, "\n");
    389 
    390         if (api->ret.typeName[0]) {
    391             fprintf(f, "    ");
    392             printVarType(f, &api->ret);
    393             fprintf(f, " retValue;\n");
    394             fprintf(f, "    io->%sGetReturn(&retValue, sizeof(retValue));\n", str);
    395             fprintf(f, "    return retValue;\n");
    396         } else /*if (api->sync)*/ {
    397             fprintf(f, "    io->%sGetReturn(NULL, 0);\n", str);
    398         }
    399         fprintf(f, "}\n\n");
    400     }
    401 
    402     fprintf(f, "\n");
    403     fprintf(f, "static RsApiEntrypoints_t s_LocalTable = {\n");
    404     for (ct=0; ct < apiCount; ct++) {
    405         fprintf(f, "    LF_%s,\n", apis[ct].name);
    406     }
    407     fprintf(f, "};\n");
    408 
    409     fprintf(f, "\n");
    410     fprintf(f, "static RsApiEntrypoints_t s_RemoteTable = {\n");
    411     for (ct=0; ct < apiCount; ct++) {
    412         fprintf(f, "    RF_%s,\n", apis[ct].name);
    413     }
    414     fprintf(f, "};\n");
    415 
    416     fprintf(f, "static RsApiEntrypoints_t *s_CurrentTable = &s_LocalTable;\n\n");
    417     for (ct=0; ct < apiCount; ct++) {
    418         int needFlush = 0;
    419         const ApiEntry * api = &apis[ct];
    420 
    421         fprintf(f, "extern \"C\" ");
    422 
    423         printFuncDecl(f, api, "rs", 0, 0);
    424         fprintf(f, "\n{\n");
    425         fprintf(f, "    ");
    426         if (api->ret.typeName[0]) {
    427             fprintf(f, "return ");
    428         }
    429         fprintf(f, "s_CurrentTable->%s(", api->name);
    430 
    431         if (!api->nocontext) {
    432             fprintf(f, "(Context *)rsc");
    433         }
    434 
    435         for (ct2=0; ct2 < api->paramCount; ct2++) {
    436             const VarType *vt = &api->params[ct2];
    437             if (ct2 > 0 || !api->nocontext) {
    438                 fprintf(f, ", ");
    439             }
    440             fprintf(f, "%s", vt->name);
    441         }
    442         fprintf(f, ");\n");
    443         fprintf(f, "}\n\n");
    444     }
    445 
    446 }
    447 
    448 void printPlaybackCpp(FILE *f) {
    449     int ct;
    450     int ct2;
    451 
    452     fprintf(f, "#include \"rsDevice.h\"\n");
    453     fprintf(f, "#include \"rsContext.h\"\n");
    454     fprintf(f, "#include \"rsThreadIO.h\"\n");
    455     fprintf(f, "#include \"rsgApiStructs.h\"\n");
    456     fprintf(f, "#include \"rsgApiFuncDecl.h\"\n");
    457     fprintf(f, "\n");
    458     fprintf(f, "namespace android {\n");
    459     fprintf(f, "namespace renderscript {\n");
    460     fprintf(f, "\n");
    461 
    462     for (ct=0; ct < apiCount; ct++) {
    463         const ApiEntry * api = &apis[ct];
    464         int needFlush = 0;
    465 
    466         if (api->direct) {
    467             continue;
    468         }
    469 
    470         fprintf(f, "void rsp_%s(Context *con, const void *vp, size_t cmdSizeBytes) {\n", api->name);
    471         fprintf(f, "    const RS_CMD_%s *cmd = static_cast<const RS_CMD_%s *>(vp);\n", api->name, api->name);
    472 
    473         if (hasInlineDataPointers(api)) {
    474             fprintf(f, "    const uint8_t *baseData = 0;\n");
    475             fprintf(f, "    if (cmdSizeBytes != sizeof(RS_CMD_%s)) {\n", api->name);
    476             fprintf(f, "        baseData = &((const uint8_t *)vp)[sizeof(*cmd)];\n");
    477             fprintf(f, "    }\n");
    478         }
    479 
    480         fprintf(f, "    ");
    481         if (api->ret.typeName[0]) {
    482             fprintf(f, "\n    ");
    483             printVarType(f, &api->ret);
    484             fprintf(f, " ret = ");
    485         }
    486         fprintf(f, "rsi_%s(con", api->name);
    487         for (ct2=0; ct2 < api->paramCount; ct2++) {
    488             const VarType *vt = &api->params[ct2];
    489             needFlush += vt->ptrLevel;
    490 
    491             if (hasInlineDataPointers(api) && vt->ptrLevel) {
    492                 fprintf(f, ",\n           (const %s *)&baseData[(intptr_t)cmd->%s]", vt->typeName, vt->name);
    493             } else {
    494                 fprintf(f, ",\n           cmd->%s", vt->name);
    495             }
    496         }
    497         fprintf(f, ");\n");
    498 
    499         if (hasInlineDataPointers(api)) {
    500             fprintf(f, "    size_t totalSize = 0;\n");
    501             for (ct2=0; ct2 < api->paramCount; ct2++) {
    502                 if (api->params[ct2].ptrLevel) {
    503                     fprintf(f, "    totalSize += cmd->%s_length;\n", api->params[ct2].name);
    504                 }
    505             }
    506 
    507             fprintf(f, "    if ((totalSize != 0) && (cmdSizeBytes == sizeof(RS_CMD_%s))) {\n", api->name);
    508             fprintf(f, "        con->mIO.coreSetReturn(NULL, 0);\n");
    509             fprintf(f, "    }\n");
    510         } else if (api->ret.typeName[0]) {
    511             fprintf(f, "    con->mIO.coreSetReturn(&ret, sizeof(ret));\n");
    512         } else if (api->sync || needFlush) {
    513             fprintf(f, "    con->mIO.coreSetReturn(NULL, 0);\n");
    514         }
    515 
    516         fprintf(f, "};\n\n");
    517     }
    518 
    519     for (ct=0; ct < apiCount; ct++) {
    520         const ApiEntry * api = &apis[ct];
    521         int needFlush = 0;
    522 
    523         fprintf(f, "void rspr_%s(Context *con, ThreadIO *io) {\n", api->name);
    524         fprintf(f, "    RS_CMD_%s cmd;\n", api->name);
    525 
    526         for (ct2=0; ct2 < api->paramCount; ct2++) {
    527             const VarType *vt = &api->params[ct2];
    528             if (vt->ptrLevel == 0) {
    529                 fprintf(f, "    io->coreRead(&cmd.%s, sizeof(cmd.%s));\n", vt->name, vt->name);
    530             }
    531         }
    532         fprintf(f, "\n");
    533 
    534         for (ct2=0; ct2 < api->paramCount; ct2++) {
    535             const VarType *vt = &api->params[ct2];
    536             if (vt->ptrLevel == 1) {
    537                 fprintf(f, "    cmd.%s = (", vt->name);
    538                 printVarType(f, vt);
    539                 fprintf(f, ")malloc(cmd.%s_length);\n", vt->name);
    540 
    541                 if (vt->isConst) {
    542                     fprintf(f, "    if (cmd.%s_length) io->coreRead((void *)cmd.%s, cmd.%s_length);\n", vt->name, vt->name, vt->name);
    543                 }
    544             }
    545         }
    546         fprintf(f, "\n");
    547 
    548         for (ct2=0; ct2 < api->paramCount; ct2++) {
    549             const VarType *vt = &api->params[ct2];
    550             if (vt->ptrLevel == 2) {
    551                 fprintf(f, "    for (size_t ct = 0; ct < (cmd.%s_length_length / sizeof(cmd.%s_length)); ct++) {\n", vt->name, vt->name);
    552                 fprintf(f, "        cmd.%s = (", vt->name);
    553                 printVarType(f, vt);
    554                 fprintf(f, ")malloc(cmd.%s_length[ct]);\n", vt->name);
    555                 fprintf(f, "        io->coreRead(& cmd.%s, cmd.%s_length[ct]);\n", vt->name, vt->name);
    556                 fprintf(f, "    }\n");
    557             }
    558         }
    559         fprintf(f, "\n");
    560 
    561         if (api->ret.typeName[0]) {
    562             fprintf(f, "    ");
    563             printVarType(f, &api->ret);
    564             fprintf(f, " ret =\n");
    565         }
    566 
    567         fprintf(f, "    rsi_%s(", api->name);
    568         if (!api->nocontext) {
    569             fprintf(f, "con");
    570         }
    571         for (ct2=0; ct2 < api->paramCount; ct2++) {
    572             const VarType *vt = &api->params[ct2];
    573             if (ct2 > 0 || !api->nocontext) {
    574                 fprintf(f, ",\n");
    575             }
    576             fprintf(f, "           cmd.%s", vt->name);
    577         }
    578         fprintf(f, ");\n");
    579 
    580         for (ct2=0; ct2 < api->paramCount; ct2++) {
    581             const VarType *vt = &api->params[ct2];
    582             if ((vt->ptrLevel == 1) && (!vt->isConst)) {
    583                 fprintf(f, "    io->coreSetReturn((void *)cmd.%s, cmd.%s_length);\n", vt->name, vt->name);
    584             }
    585         }
    586 
    587         for (ct2=0; ct2 < api->paramCount; ct2++) {
    588             const VarType *vt = &api->params[ct2];
    589             if ((vt->ptrLevel == 2) && (!vt->isConst)) {
    590                 fprintf(f, "    for (size_t ct = 0; ct < (cmd.%s_length_length / sizeof(cmd.%s_length)); ct++) {\n", vt->name, vt->name);
    591                 fprintf(f, "        io->coreSetReturn((void *)cmd.%s[ct], cmd.%s_length[ct]);\n", vt->name, vt->name);
    592                 fprintf(f, "    }\n");
    593             }
    594         }
    595         fprintf(f, "\n");
    596 
    597         if (api->ret.typeName[0]) {
    598             fprintf(f, "    io->coreSetReturn(&ret, sizeof(ret));\n");
    599         } else /*if (needFlush)*/ {
    600             fprintf(f, "    io->coreSetReturn(NULL, 0);\n");
    601         }
    602 
    603         for (ct2=0; ct2 < api->paramCount; ct2++) {
    604             const VarType *vt = &api->params[ct2];
    605             if (vt->ptrLevel == 1) {
    606                 fprintf(f, "    free((void *)cmd.%s);\n", vt->name);
    607             }
    608         }
    609         for (ct2=0; ct2 < api->paramCount; ct2++) {
    610             const VarType *vt = &api->params[ct2];
    611             if (vt->ptrLevel == 2) {
    612                 fprintf(f, "    for (size_t ct = 0; ct < (cmd.%s_length_length / sizeof(cmd.%s_length)); ct++) {\n", vt->name, vt->name);
    613                 fprintf(f, "        free((void *)cmd.%s);\n", vt->name);
    614                 fprintf(f, "    }\n");
    615             }
    616         }
    617 
    618         fprintf(f, "};\n\n");
    619     }
    620 
    621     fprintf(f, "RsPlaybackLocalFunc gPlaybackFuncs[%i] = {\n", apiCount + 1);
    622     fprintf(f, "    NULL,\n");
    623     for (ct=0; ct < apiCount; ct++) {
    624         if (apis[ct].direct) {
    625             fprintf(f, "    NULL,\n");
    626         } else {
    627             fprintf(f, "    %s%s,\n", "rsp_", apis[ct].name);
    628         }
    629     }
    630     fprintf(f, "};\n");
    631 
    632     fprintf(f, "RsPlaybackRemoteFunc gPlaybackRemoteFuncs[%i] = {\n", apiCount + 1);
    633     fprintf(f, "    NULL,\n");
    634     for (ct=0; ct < apiCount; ct++) {
    635         fprintf(f, "    %s%s,\n", "rspr_", apis[ct].name);
    636     }
    637     fprintf(f, "};\n");
    638 
    639     fprintf(f, "};\n");
    640     fprintf(f, "};\n");
    641 }
    642 
    643 void yylex();
    644 
    645 int main(int argc, char **argv) {
    646     if (argc != 3) {
    647         fprintf(stderr, "usage: %s commandFile outFile\n", argv[0]);
    648         return 1;
    649     }
    650     const char* rsgFile = argv[1];
    651     const char* outFile = argv[2];
    652     FILE* input = fopen(rsgFile, "r");
    653 
    654     char choice = fgetc(input);
    655     fclose(input);
    656 
    657     if (choice < '0' || choice > '3') {
    658         fprintf(stderr, "Uknown command: \'%c\'\n", choice);
    659         return -2;
    660     }
    661 
    662     yylex();
    663     // printf("# of lines = %d\n", num_lines);
    664 
    665     FILE *f = fopen(outFile, "w");
    666 
    667     printFileHeader(f);
    668     switch (choice) {
    669         case '0': // rsgApiStructs.h
    670         {
    671             fprintf(f, "\n");
    672             fprintf(f, "#include \"rsContext.h\"\n");
    673             fprintf(f, "#include \"rsFifo.h\"\n");
    674             fprintf(f, "\n");
    675             fprintf(f, "namespace android {\n");
    676             fprintf(f, "namespace renderscript {\n");
    677             printStructures(f);
    678             printFuncDecls(f, "rsi_", 1, 0);
    679             printPlaybackFuncs(f, "rsp_");
    680             fprintf(f, "\n\ntypedef struct RsPlaybackRemoteHeaderRec {\n");
    681             fprintf(f, "    uint32_t command;\n");
    682             fprintf(f, "    size_t size;\n");
    683             fprintf(f, "} RsPlaybackRemoteHeader;\n\n");
    684             fprintf(f, "typedef void (*RsPlaybackLocalFunc)(Context *, const void *, size_t sizeBytes);\n");
    685             fprintf(f, "typedef void (*RsPlaybackRemoteFunc)(Context *, ThreadIO *);\n");
    686             fprintf(f, "extern RsPlaybackLocalFunc gPlaybackFuncs[%i];\n", apiCount + 1);
    687             fprintf(f, "extern RsPlaybackRemoteFunc gPlaybackRemoteFuncs[%i];\n", apiCount + 1);
    688 
    689             fprintf(f, "}\n");
    690             fprintf(f, "}\n");
    691         }
    692         break;
    693 
    694         case '1': // rsgApiFuncDecl.h
    695         {
    696             printFuncDecls(f, "rs", 0, 1);
    697         }
    698         break;
    699 
    700         case '2': // rsgApi.cpp
    701         {
    702             printApiCpp(f);
    703         }
    704         break;
    705 
    706         case '3': // rsgApiReplay.cpp
    707         {
    708             printFileHeader(f);
    709             printPlaybackCpp(f);
    710         }
    711         break;
    712     }
    713     fclose(f);
    714     return 0;
    715 }
    716