src/SDL_log.c
changeset 8477 ad08f0d710f3
parent 8460 f483e8bdae3c
parent 7614 af0bd07212bd
child 8478 337b5dc0797b
--- a/src/SDL_log.c	Sat Jun 08 14:34:09 2013 -0400
+++ b/src/SDL_log.c	Mon Aug 12 22:29:55 2013 -0400
@@ -39,6 +39,9 @@
 #define DEFAULT_APPLICATION_PRIORITY    SDL_LOG_PRIORITY_INFO
 #define DEFAULT_TEST_PRIORITY           SDL_LOG_PRIORITY_VERBOSE
 
+/* Forward definition of error function */
+extern int SDL_SetError(const char *fmt, ...);
+
 typedef struct SDL_LogLevel
 {
     int category;
@@ -138,7 +141,7 @@
     }
 
     if (category == SDL_LOG_CATEGORY_TEST) {
-        return SDL_test_priority;    
+        return SDL_test_priority;
     } else if (category == SDL_LOG_CATEGORY_APPLICATION) {
         return SDL_application_priority;
     } else if (category == SDL_LOG_CATEGORY_ASSERT) {
@@ -263,6 +266,7 @@
 SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va_list ap)
 {
     char *message;
+    size_t len;
 
     /* Nothing to do if we don't have an output function */
     if (!SDL_log_function) {
@@ -283,27 +287,91 @@
     if (!message) {
         return;
     }
+
     SDL_vsnprintf(message, SDL_MAX_LOG_MESSAGE, fmt, ap);
+
+    /* Chop off final endline. */
+    len = SDL_strlen(message);
+    if ((len > 0) && (message[len-1] == '\n')) {
+        message[--len] = '\0';
+        if ((len > 0) && (message[len-1] == '\r')) {  /* catch "\r\n", too. */
+            message[--len] = '\0';
+        }
+    }
+
     SDL_log_function(SDL_log_userdata, category, priority, message);
     SDL_stack_free(message);
 }
 
+#if defined(__WIN32__)
+/* Flag tracking the attachment of the console: 0=unattached, 1=attached, -1=error */
+static int consoleAttached = 0;
+
+/* Handle to stderr output of console. */
+static HANDLE stderrHandle = NULL;
+#endif
+
 static void
 SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
               const char *message)
 {
 #if defined(__WIN32__) || defined(__WINRT__)
     /* Way too many allocations here, urgh */
+    /* Note: One can't call SDL_SetError here, since that function itself logs. */
     {
         char *output;
         size_t length;
         LPTSTR tstr;
+        BOOL attachResult;
+        DWORD attachError;
+        unsigned long charsWritten; 
 
-        length = SDL_strlen(SDL_priority_prefixes[priority]) + 2 + SDL_strlen(message) + 1;
+        /* Maybe attach console and get stderr handle */
+        if (consoleAttached == 0) {
+            attachResult = AttachConsole(ATTACH_PARENT_PROCESS);
+            if (!attachResult) {
+                    attachError = GetLastError();
+                    if (attachError == ERROR_INVALID_HANDLE) {
+                        OutputDebugString(TEXT("Parent process has no console"));
+                        consoleAttached = -1;
+                    } else if (attachError == ERROR_GEN_FAILURE) {
+                         OutputDebugString(TEXT("Could not attach to console of parent process"));
+                         consoleAttached = -1;
+                    } else if (attachError == ERROR_ACCESS_DENIED) {  
+                         /* Already attached */
+                        consoleAttached = 1;
+                    } else {
+                        OutputDebugString(TEXT("Error attaching console"));
+                        consoleAttached = -1;
+                    }
+                } else {
+                    /* Newly attached */
+                    consoleAttached = 1;
+                }
+			
+                if (consoleAttached == 1) {
+                        stderrHandle = GetStdHandle(STD_ERROR_HANDLE);
+                }
+        }
+
+        length = SDL_strlen(SDL_priority_prefixes[priority]) + 2 + SDL_strlen(message) + 1 + 1;
         output = SDL_stack_alloc(char, length);
-        SDL_snprintf(output, length, "%s: %s", SDL_priority_prefixes[priority], message);
+        SDL_snprintf(output, length, "%s: %s\n", SDL_priority_prefixes[priority], message);
         tstr = WIN_UTF8ToString(output);
+        
+        /* Output to debugger */
         OutputDebugString(tstr);
+       
+        /* Screen output to stderr, if console was attached. */
+        if (consoleAttached == 1) {
+                if (!WriteConsole(stderrHandle, tstr, lstrlen(tstr), &charsWritten, NULL)) {
+                    OutputDebugString(TEXT("Error calling WriteConsole"));
+                }
+                if (charsWritten == ERROR_NOT_ENOUGH_MEMORY) {
+                    OutputDebugString(TEXT("Insufficient heap memory to write message"));
+                }
+        }
+
         SDL_free(tstr);
         SDL_stack_free(output);
     }
@@ -314,7 +382,9 @@
         SDL_snprintf(tag, SDL_arraysize(tag), "SDL/%s", GetCategoryPrefix(category));
         __android_log_write(SDL_android_priority[priority], tag, message);
     }
-#elif defined(__APPLE__)
+#elif defined(__APPLE__) && defined(SDL_VIDEO_DRIVER_COCOA)
+    /* Technically we don't need SDL_VIDEO_DRIVER_COCOA, but that's where this function is defined for now.
+    */
     extern void SDL_NSLog(const char *text);
     {
         char *text;
@@ -328,19 +398,12 @@
         }
     }
 #elif defined(__PSP__)
-//Simple Log System for PSP
-	{
-		unsigned int length;
-		char*		 output;
-		FILE*		 pFile;
-		length = SDL_strlen(SDL_priority_prefixes[priority]) + 2 + SDL_strlen(message) + 1;
-        output = SDL_stack_alloc(char, length);
-		SDL_snprintf(output, length, "%s: %s", SDL_priority_prefixes[priority], message);
-		pFile = fopen ("SDL_Log.txt", "a");
-		fwrite (output, strlen (output), 1, pFile);
-		SDL_stack_free(output);
-		fclose (pFile);
-	}
+    {
+        FILE*        pFile;
+        pFile = fopen ("SDL_Log.txt", "a");
+        fprintf(pFile, "%s: %s\n", SDL_priority_prefixes[priority], message);
+        fclose (pFile);
+    }
 #endif
 #if HAVE_STDIO_H
     fprintf(stderr, "%s: %s\n", SDL_priority_prefixes[priority], message);