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