diff --git a/CMakeLists.txt b/CMakeLists.txt index 15f27a1fe..43db3dcfb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -292,6 +292,7 @@ include(CheckIncludeFiles) check_function_exists(strdup HAVE_STRDUP) check_function_exists(strndup HAVE_STRNDUP) check_function_exists(strlcpy HAVE_STRLCPY) +check_function_exists(vasprintf HAVE_VASPRINTF) if(NOT DEFINED PSP2) check_function_exists(localtime_r HAVE_LOCALTIME_R) endif() @@ -374,6 +375,10 @@ if(HAVE_STRLCPY) list(APPEND FUNCTION_DEFINES HAVE_STRLCPY) endif() +if(HAVE_VASPRINTF) + list(APPEND FUNCTION_DEFINES HAVE_VASPRINTF) +endif() + if(HAVE_LOCALTIME_R) list(APPEND FUNCTION_DEFINES HAVE_LOCALTIME_R) endif() diff --git a/src/platform/test/cinema-main.c b/src/platform/test/cinema-main.c index 228cde08d..719720a21 100644 --- a/src/platform/test/cinema-main.c +++ b/src/platform/test/cinema-main.c @@ -85,6 +85,11 @@ DEFINE_VECTOR(CInemaTestList, struct CInemaTest) DECLARE_VECTOR(ImageList, void*) DEFINE_VECTOR(ImageList, void*) +struct StringBuilder { + struct StringList out; + struct StringList err; +}; + static bool showVersion = false; static bool showUsage = false; static char base[PATH_MAX] = {0}; @@ -102,6 +107,7 @@ static size_t jobIndex = 0; static Mutex jobMutex; static Thread jobThreads[MAX_JOBS]; static int jobStatus; +static ThreadLocal stringBuilder; bool CInemaTestInit(struct CInemaTest*, const char* directory, const char* filename); void CInemaTestRun(struct CInemaTest*); @@ -117,7 +123,16 @@ ATTRIBUTE_FORMAT(printf, 2, 3) void CIlog(int minlevel, const char* format, ...) } va_list args; va_start(args, format); +#ifdef HAVE_VASPRINTF + struct StringBuilder* builder = ThreadLocalGetValue(stringBuilder); + if (!builder) { + vprintf(format, args); + } else { + vasprintf(StringListAppend(&builder->out), format, args); + } +#else vprintf(format, args); +#endif va_end(args); } @@ -127,10 +142,39 @@ ATTRIBUTE_FORMAT(printf, 2, 3) void CIerr(int minlevel, const char* format, ...) } va_list args; va_start(args, format); +#ifdef HAVE_VASPRINTF + struct StringBuilder* builder = ThreadLocalGetValue(stringBuilder); + if (!builder) { + vfprintf(stderr, format, args); + } else { + vasprintf(StringListAppend(&builder->err), format, args); + } +#else vfprintf(stderr, format, args); +#endif va_end(args); } +void CIflush(struct StringList* list, FILE* out) { + size_t len = 0; + size_t i; + for (i = 0; i < StringListSize(list); ++i) { + len += strlen(*StringListGetPointer(list, i)); + } + char* string = calloc(len + 1, sizeof(char)); + char* cur = string; + for (i = 0; i < StringListSize(list); ++i) { + char* brick = *StringListGetPointer(list, i); + size_t portion = strlen(brick); + memcpy(cur, brick, portion); + free(brick); + cur += portion; + } + fputs(string, out); + free(string); + StringListClear(list); +} + static bool parseCInemaArgs(int argc, char* const* argv) { int ch; int index = 0; @@ -886,6 +930,11 @@ static bool CInemaTask(struct CInemaTestList* tests, size_t i) { static THREAD_ENTRY CInemaJob(void* context) { struct CInemaTestList* tests = context; + struct StringBuilder builder; + StringListInit(&builder.out, 0); + StringListInit(&builder.err, 0); + ThreadLocalSetKey(stringBuilder, &builder); + bool success = true; while (true) { size_t i; @@ -899,12 +948,20 @@ static THREAD_ENTRY CInemaJob(void* context) { if (!CInemaTask(tests, i)) { success = false; } + CIflush(&builder.out, stdout); + CIflush(&builder.err, stderr); } MutexLock(&jobMutex); if (!success) { jobStatus = 1; } MutexUnlock(&jobMutex); + + CIflush(&builder.out, stdout); + StringListDeinit(&builder.out); + + CIflush(&builder.err, stderr); + StringListDeinit(&builder.err); } void _log(struct mLogger* log, int category, enum mLogLevel level, const char* format, va_list args) { @@ -935,6 +992,9 @@ void _log(struct mLogger* log, int category, enum mLogLevel level, const char* f } int main(int argc, char** argv) { + ThreadLocalInitKey(&stringBuilder); + ThreadLocalSetKey(stringBuilder, NULL); + int status = 0; if (!parseCInemaArgs(argc, argv)) { status = 1;