| 533 | }; |
| 534 | |
| 535 | static void OutputThread(void* param) |
| 536 | { |
| 537 | OutputContext* context = (OutputContext*)param; |
| 538 | |
| 539 | String queuedStr; |
| 540 | |
| 541 | while (true) |
| 542 | { |
| 543 | char data[1024]; |
| 544 | |
| 545 | BfpFileResult result; |
| 546 | int bytesRead = (int)BfpFile_Read(context->mFile, data, 1023, -1, &result); |
| 547 | if ((result != BfpFileResult_Ok) && (result != BfpFileResult_PartialData)) |
| 548 | return; |
| 549 | |
| 550 | data[bytesRead] = 0; |
| 551 | if (context->mIsError) |
| 552 | { |
| 553 | std::cerr << data; |
| 554 | std::cerr.flush(); |
| 555 | } |
| 556 | else |
| 557 | { |
| 558 | std::cout << data; |
| 559 | std::cout.flush(); |
| 560 | } |
| 561 | |
| 562 | if (gApp->mLogFile.IsOpen()) |
| 563 | { |
| 564 | // This is to ensure that error and output lines are not merged together, though they may interleave |
| 565 | queuedStr.Append(data, bytesRead); |
| 566 | while (true) |
| 567 | { |
| 568 | int crPos = (int)queuedStr.IndexOf('\n'); |
| 569 | if (crPos == -1) |
| 570 | break; |
| 571 | |
| 572 | AutoCrit autoCrit(gApp->mLogCritSect); |
| 573 | if (context->mIsError) |
| 574 | gApp->mLogFile.WriteSNZ("err> "); |
| 575 | else |
| 576 | gApp->mLogFile.WriteSNZ("out> "); |
| 577 | |
| 578 | int endPos = crPos; |
| 579 | if ((endPos > 0) && (queuedStr[endPos - 1] == '\r')) |
| 580 | endPos--; |
| 581 | gApp->mLogFile.Write((void*)queuedStr.c_str(), endPos); |
| 582 | gApp->mLogFile.WriteSNZ("\n"); |
| 583 | queuedStr.Remove(0, crPos + 1); |
| 584 | } |
| 585 | } |
| 586 | } |
| 587 | } |
| 588 | |
| 589 | bool BootApp::QueueRun(const String& fileName, const String& args, const String& workingDir, BfpSpawnFlags extraFlags) |
| 590 | { |