1
2#include "spec.h"
3#include <stdio.h>
4#include <string.h>
5
6void 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
24void 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
59void 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
67void 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
77void 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
101void 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
126void 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
138void 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
150void 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
161static 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
187void 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 (%s_length == 0) {\n", vt->name);
298                    fprintf(f, "        cmd->%s = NULL;\n", vt->name);
299                    fprintf(f, "    } else if (dataSize < io->getMaxInlineSize()) {\n");
300                    fprintf(f, "        memcpy(payload, %s, %s_length);\n", vt->name, vt->name);
301                    fprintf(f, "        cmd->%s = (", vt->name);
302                    printVarType(f, vt);
303                    fprintf(f, ")(payload - ((uint8_t *)&cmd[1]));\n");
304                    fprintf(f, "        payload += %s_length;\n", vt->name);
305                    fprintf(f, "    } else {\n");
306                    fprintf(f, "        cmd->%s = %s;\n", vt->name, vt->name);
307                    fprintf(f, "    }\n");
308
309                } else {
310                    fprintf(f, "    cmd->%s = %s;\n", vt->name, vt->name);
311                }
312            }
313            if (api->ret.typeName[0] || api->sync) {
314                needFlush = 1;
315            }
316
317            fprintf(f, "    io->coreCommit();\n");
318            if (hasInlineDataPointers(api)) {
319                fprintf(f, "    if (dataSize >= io->getMaxInlineSize()) {\n");
320                fprintf(f, "        io->coreGetReturn(NULL, 0);\n");
321                fprintf(f, "    }\n");
322            } else if (api->ret.typeName[0]) {
323                fprintf(f, "\n    ");
324                printVarType(f, &api->ret);
325                fprintf(f, " ret;\n");
326                fprintf(f, "    io->coreGetReturn(&ret, sizeof(ret));\n");
327                fprintf(f, "    return ret;\n");
328            } else if (needFlush) {
329                fprintf(f, "    io->coreGetReturn(NULL, 0);\n");
330            }
331        }
332        fprintf(f, "};\n\n");
333
334
335        // Generate a remote sender function
336        const char * str = "core";
337        if (api->direct) {
338            str = "async";
339        }
340
341        fprintf(f, "static ");
342        printFuncDecl(f, api, "RF_", 0, 0);
343        fprintf(f, "\n{\n");
344        fprintf(f, "    ThreadIO *io = &((Context *)rsc)->mIO;\n");
345        fprintf(f, "    const uint32_t cmdID = RS_CMD_ID_%s;\n", api->name);
346        fprintf(f, "    io->%sWrite(&cmdID, sizeof(cmdID));\n\n", str);
347
348        for (ct2=0; ct2 < api->paramCount; ct2++) {
349            const VarType *vt = &api->params[ct2];
350            if (vt->ptrLevel == 0) {
351                fprintf(f, "    io->%sWrite(& %s, sizeof(%s));\n", str, vt->name, vt->name);
352            }
353        }
354        fprintf(f, "\n");
355
356        for (ct2=0; ct2 < api->paramCount; ct2++) {
357            const VarType *vt = &api->params[ct2];
358            if ((vt->ptrLevel == 1) && (vt->isConst)) {
359                fprintf(f, "    io->%sWrite(%s, %s_length);\n", str, vt->name, vt->name);
360            }
361        }
362        fprintf(f, "\n");
363
364        for (ct2=0; ct2 < api->paramCount; ct2++) {
365            const VarType *vt = &api->params[ct2];
366            if ((vt->ptrLevel == 2) && (vt->isConst)) {
367                fprintf(f, "    for (size_t ct = 0; ct < (%s_length_length / sizeof(%s_length)); ct++) {\n", vt->name, vt->name);
368                fprintf(f, "        io->%sWrite(%s[ct], %s_length[ct]);\n", str, vt->name, vt->name);
369                fprintf(f, "    }\n");
370            }
371        }
372        fprintf(f, "\n");
373
374        for (ct2=0; ct2 < api->paramCount; ct2++) {
375            const VarType *vt = &api->params[ct2];
376            if ((vt->ptrLevel == 1) && (!vt->isConst)) {
377                fprintf(f, "    io->%sGetReturn(%s, %s_length);\n", str, vt->name, vt->name);
378            }
379        }
380        fprintf(f, "\n");
381
382        for (ct2=0; ct2 < api->paramCount; ct2++) {
383            const VarType *vt = &api->params[ct2];
384            if ((vt->ptrLevel == 2) && (!vt->isConst)) {
385                fprintf(f, "    for (size_t ct = 0; ct < (%s_length_length / sizeof(%s_length)); ct++) {\n", vt->name, vt->name);
386                fprintf(f, "        io->%sGetReturn(%s[ct], %s_length[ct]);\n", str, vt->name, vt->name);
387                fprintf(f, "    }\n");
388            }
389        }
390        fprintf(f, "\n");
391
392        if (api->ret.typeName[0]) {
393            fprintf(f, "    ");
394            printVarType(f, &api->ret);
395            fprintf(f, " retValue;\n");
396            fprintf(f, "    io->%sGetReturn(&retValue, sizeof(retValue));\n", str);
397            fprintf(f, "    return retValue;\n");
398        } else /*if (api->sync)*/ {
399            fprintf(f, "    io->%sGetReturn(NULL, 0);\n", str);
400        }
401        fprintf(f, "}\n\n");
402    }
403
404    fprintf(f, "\n");
405    fprintf(f, "static RsApiEntrypoints_t s_LocalTable = {\n");
406    for (ct=0; ct < apiCount; ct++) {
407        fprintf(f, "    LF_%s,\n", apis[ct].name);
408    }
409    fprintf(f, "};\n");
410
411    fprintf(f, "\n");
412    fprintf(f, "static RsApiEntrypoints_t s_RemoteTable = {\n");
413    for (ct=0; ct < apiCount; ct++) {
414        fprintf(f, "    RF_%s,\n", apis[ct].name);
415    }
416    fprintf(f, "};\n");
417
418    fprintf(f, "static RsApiEntrypoints_t *s_CurrentTable = &s_LocalTable;\n\n");
419    for (ct=0; ct < apiCount; ct++) {
420        int needFlush = 0;
421        const ApiEntry * api = &apis[ct];
422
423        fprintf(f, "extern \"C\" ");
424
425        printFuncDecl(f, api, "rs", 0, 0);
426        fprintf(f, "\n{\n");
427        fprintf(f, "    ");
428        if (api->ret.typeName[0]) {
429            fprintf(f, "return ");
430        }
431        fprintf(f, "s_CurrentTable->%s(", api->name);
432
433        if (!api->nocontext) {
434            fprintf(f, "(Context *)rsc");
435        }
436
437        for (ct2=0; ct2 < api->paramCount; ct2++) {
438            const VarType *vt = &api->params[ct2];
439            if (ct2 > 0 || !api->nocontext) {
440                fprintf(f, ", ");
441            }
442            fprintf(f, "%s", vt->name);
443        }
444        fprintf(f, ");\n");
445        fprintf(f, "}\n\n");
446    }
447
448}
449
450void printPlaybackCpp(FILE *f) {
451    int ct;
452    int ct2;
453
454    fprintf(f, "#include \"rsDevice.h\"\n");
455    fprintf(f, "#include \"rsContext.h\"\n");
456    fprintf(f, "#include \"rsThreadIO.h\"\n");
457    fprintf(f, "#include \"rsgApiStructs.h\"\n");
458    fprintf(f, "#include \"rsgApiFuncDecl.h\"\n");
459    fprintf(f, "\n");
460    fprintf(f, "namespace android {\n");
461    fprintf(f, "namespace renderscript {\n");
462    fprintf(f, "\n");
463
464    for (ct=0; ct < apiCount; ct++) {
465        const ApiEntry * api = &apis[ct];
466        int needFlush = 0;
467
468        if (api->direct) {
469            continue;
470        }
471
472        fprintf(f, "void rsp_%s(Context *con, const void *vp, size_t cmdSizeBytes) {\n", api->name);
473        fprintf(f, "    const RS_CMD_%s *cmd = static_cast<const RS_CMD_%s *>(vp);\n", api->name, api->name);
474
475        if (hasInlineDataPointers(api)) {
476            fprintf(f, "    const uint8_t *baseData = 0;\n");
477            fprintf(f, "    if (cmdSizeBytes != sizeof(RS_CMD_%s)) {\n", api->name);
478            fprintf(f, "        baseData = &((const uint8_t *)vp)[sizeof(*cmd)];\n");
479            fprintf(f, "    }\n");
480        }
481
482        fprintf(f, "    ");
483        if (api->ret.typeName[0]) {
484            fprintf(f, "\n    ");
485            printVarType(f, &api->ret);
486            fprintf(f, " ret = ");
487        }
488        fprintf(f, "rsi_%s(con", api->name);
489        for (ct2=0; ct2 < api->paramCount; ct2++) {
490            const VarType *vt = &api->params[ct2];
491            needFlush += vt->ptrLevel;
492
493            if (hasInlineDataPointers(api) && vt->ptrLevel) {
494                fprintf(f, ",\n           cmd->%s_length == 0 ? NULL : (const %s *)&baseData[(intptr_t)cmd->%s]",
495                        vt->name, vt->typeName, vt->name);
496            } else {
497                fprintf(f, ",\n           cmd->%s", vt->name);
498            }
499        }
500        fprintf(f, ");\n");
501
502        if (hasInlineDataPointers(api)) {
503            fprintf(f, "    size_t totalSize = 0;\n");
504            for (ct2=0; ct2 < api->paramCount; ct2++) {
505                if (api->params[ct2].ptrLevel) {
506                    fprintf(f, "    totalSize += cmd->%s_length;\n", api->params[ct2].name);
507                }
508            }
509
510            fprintf(f, "    if ((totalSize != 0) && (cmdSizeBytes == sizeof(RS_CMD_%s))) {\n", api->name);
511            fprintf(f, "        con->mIO.coreSetReturn(NULL, 0);\n");
512            fprintf(f, "    }\n");
513        } else if (api->ret.typeName[0]) {
514            fprintf(f, "    con->mIO.coreSetReturn(&ret, sizeof(ret));\n");
515        } else if (api->sync || needFlush) {
516            fprintf(f, "    con->mIO.coreSetReturn(NULL, 0);\n");
517        }
518
519        fprintf(f, "};\n\n");
520    }
521
522    for (ct=0; ct < apiCount; ct++) {
523        const ApiEntry * api = &apis[ct];
524        int needFlush = 0;
525
526        fprintf(f, "void rspr_%s(Context *con, ThreadIO *io) {\n", api->name);
527        fprintf(f, "    RS_CMD_%s cmd;\n", api->name);
528
529        for (ct2=0; ct2 < api->paramCount; ct2++) {
530            const VarType *vt = &api->params[ct2];
531            if (vt->ptrLevel == 0) {
532                fprintf(f, "    io->coreRead(&cmd.%s, sizeof(cmd.%s));\n", vt->name, vt->name);
533            }
534        }
535        fprintf(f, "\n");
536
537        for (ct2=0; ct2 < api->paramCount; ct2++) {
538            const VarType *vt = &api->params[ct2];
539            if (vt->ptrLevel == 1) {
540                fprintf(f, "    cmd.%s = (", vt->name);
541                printVarType(f, vt);
542                fprintf(f, ")malloc(cmd.%s_length);\n", vt->name);
543
544                if (vt->isConst) {
545                    fprintf(f, "    if (cmd.%s_length) io->coreRead((void *)cmd.%s, cmd.%s_length);\n", vt->name, vt->name, vt->name);
546                }
547            }
548        }
549        fprintf(f, "\n");
550
551        for (ct2=0; ct2 < api->paramCount; ct2++) {
552            const VarType *vt = &api->params[ct2];
553            if (vt->ptrLevel == 2) {
554                fprintf(f, "    for (size_t ct = 0; ct < (cmd.%s_length_length / sizeof(cmd.%s_length)); ct++) {\n", vt->name, vt->name);
555                fprintf(f, "        cmd.%s = (", vt->name);
556                printVarType(f, vt);
557                fprintf(f, ")malloc(cmd.%s_length[ct]);\n", vt->name);
558                fprintf(f, "        io->coreRead(& cmd.%s, cmd.%s_length[ct]);\n", vt->name, vt->name);
559                fprintf(f, "    }\n");
560            }
561        }
562        fprintf(f, "\n");
563
564        if (api->ret.typeName[0]) {
565            fprintf(f, "    ");
566            printVarType(f, &api->ret);
567            fprintf(f, " ret =\n");
568        }
569
570        fprintf(f, "    rsi_%s(", api->name);
571        if (!api->nocontext) {
572            fprintf(f, "con");
573        }
574        for (ct2=0; ct2 < api->paramCount; ct2++) {
575            const VarType *vt = &api->params[ct2];
576            if (ct2 > 0 || !api->nocontext) {
577                fprintf(f, ",\n");
578            }
579            fprintf(f, "           cmd.%s", vt->name);
580        }
581        fprintf(f, ");\n");
582
583        for (ct2=0; ct2 < api->paramCount; ct2++) {
584            const VarType *vt = &api->params[ct2];
585            if ((vt->ptrLevel == 1) && (!vt->isConst)) {
586                fprintf(f, "    io->coreSetReturn((void *)cmd.%s, cmd.%s_length);\n", vt->name, vt->name);
587            }
588        }
589
590        for (ct2=0; ct2 < api->paramCount; ct2++) {
591            const VarType *vt = &api->params[ct2];
592            if ((vt->ptrLevel == 2) && (!vt->isConst)) {
593                fprintf(f, "    for (size_t ct = 0; ct < (cmd.%s_length_length / sizeof(cmd.%s_length)); ct++) {\n", vt->name, vt->name);
594                fprintf(f, "        io->coreSetReturn((void *)cmd.%s[ct], cmd.%s_length[ct]);\n", vt->name, vt->name);
595                fprintf(f, "    }\n");
596            }
597        }
598        fprintf(f, "\n");
599
600        if (api->ret.typeName[0]) {
601            fprintf(f, "    io->coreSetReturn(&ret, sizeof(ret));\n");
602        } else /*if (needFlush)*/ {
603            fprintf(f, "    io->coreSetReturn(NULL, 0);\n");
604        }
605
606        for (ct2=0; ct2 < api->paramCount; ct2++) {
607            const VarType *vt = &api->params[ct2];
608            if (vt->ptrLevel == 1) {
609                fprintf(f, "    free((void *)cmd.%s);\n", vt->name);
610            }
611        }
612        for (ct2=0; ct2 < api->paramCount; ct2++) {
613            const VarType *vt = &api->params[ct2];
614            if (vt->ptrLevel == 2) {
615                fprintf(f, "    for (size_t ct = 0; ct < (cmd.%s_length_length / sizeof(cmd.%s_length)); ct++) {\n", vt->name, vt->name);
616                fprintf(f, "        free((void *)cmd.%s);\n", vt->name);
617                fprintf(f, "    }\n");
618            }
619        }
620
621        fprintf(f, "};\n\n");
622    }
623
624    fprintf(f, "RsPlaybackLocalFunc gPlaybackFuncs[%i] = {\n", apiCount + 1);
625    fprintf(f, "    NULL,\n");
626    for (ct=0; ct < apiCount; ct++) {
627        if (apis[ct].direct) {
628            fprintf(f, "    NULL,\n");
629        } else {
630            fprintf(f, "    %s%s,\n", "rsp_", apis[ct].name);
631        }
632    }
633    fprintf(f, "};\n");
634
635    fprintf(f, "RsPlaybackRemoteFunc gPlaybackRemoteFuncs[%i] = {\n", apiCount + 1);
636    fprintf(f, "    NULL,\n");
637    for (ct=0; ct < apiCount; ct++) {
638        fprintf(f, "    %s%s,\n", "rspr_", apis[ct].name);
639    }
640    fprintf(f, "};\n");
641
642    fprintf(f, "};\n");
643    fprintf(f, "};\n");
644}
645
646void yylex();
647
648int main(int argc, char **argv) {
649    if (argc != 3) {
650        fprintf(stderr, "usage: %s commandFile outFile\n", argv[0]);
651        return 1;
652    }
653    const char* rsgFile = argv[1];
654    const char* outFile = argv[2];
655    FILE* input = fopen(rsgFile, "r");
656
657    char choice = fgetc(input);
658    fclose(input);
659
660    if (choice < '0' || choice > '3') {
661        fprintf(stderr, "Uknown command: \'%c\'\n", choice);
662        return -2;
663    }
664
665    yylex();
666    // printf("# of lines = %d\n", num_lines);
667
668    FILE *f = fopen(outFile, "w");
669
670    printFileHeader(f);
671    switch (choice) {
672        case '0': // rsgApiStructs.h
673        {
674            fprintf(f, "\n");
675            fprintf(f, "#include \"rsContext.h\"\n");
676            fprintf(f, "#include \"rsFifo.h\"\n");
677            fprintf(f, "\n");
678            fprintf(f, "namespace android {\n");
679            fprintf(f, "namespace renderscript {\n");
680            printStructures(f);
681            printFuncDecls(f, "rsi_", 1, 0);
682            printPlaybackFuncs(f, "rsp_");
683            fprintf(f, "\n\ntypedef struct RsPlaybackRemoteHeaderRec {\n");
684            fprintf(f, "    uint32_t command;\n");
685            fprintf(f, "    size_t size;\n");
686            fprintf(f, "} RsPlaybackRemoteHeader;\n\n");
687            fprintf(f, "typedef void (*RsPlaybackLocalFunc)(Context *, const void *, size_t sizeBytes);\n");
688            fprintf(f, "typedef void (*RsPlaybackRemoteFunc)(Context *, ThreadIO *);\n");
689            fprintf(f, "extern RsPlaybackLocalFunc gPlaybackFuncs[%i];\n", apiCount + 1);
690            fprintf(f, "extern RsPlaybackRemoteFunc gPlaybackRemoteFuncs[%i];\n", apiCount + 1);
691
692            fprintf(f, "}\n");
693            fprintf(f, "}\n");
694        }
695        break;
696
697        case '1': // rsgApiFuncDecl.h
698        {
699            printFuncDecls(f, "rs", 0, 1);
700        }
701        break;
702
703        case '2': // rsgApi.cpp
704        {
705            printApiCpp(f);
706        }
707        break;
708
709        case '3': // rsgApiReplay.cpp
710        {
711            printFileHeader(f);
712            printPlaybackCpp(f);
713        }
714        break;
715    }
716    fclose(f);
717    return 0;
718}
719