src/SDL_log.c
changeset 8477 ad08f0d710f3
parent 8460 f483e8bdae3c
parent 7614 af0bd07212bd
child 8478 337b5dc0797b
     1.1 --- a/src/SDL_log.c	Sat Jun 08 14:34:09 2013 -0400
     1.2 +++ b/src/SDL_log.c	Mon Aug 12 22:29:55 2013 -0400
     1.3 @@ -39,6 +39,9 @@
     1.4  #define DEFAULT_APPLICATION_PRIORITY    SDL_LOG_PRIORITY_INFO
     1.5  #define DEFAULT_TEST_PRIORITY           SDL_LOG_PRIORITY_VERBOSE
     1.6  
     1.7 +/* Forward definition of error function */
     1.8 +extern int SDL_SetError(const char *fmt, ...);
     1.9 +
    1.10  typedef struct SDL_LogLevel
    1.11  {
    1.12      int category;
    1.13 @@ -138,7 +141,7 @@
    1.14      }
    1.15  
    1.16      if (category == SDL_LOG_CATEGORY_TEST) {
    1.17 -        return SDL_test_priority;    
    1.18 +        return SDL_test_priority;
    1.19      } else if (category == SDL_LOG_CATEGORY_APPLICATION) {
    1.20          return SDL_application_priority;
    1.21      } else if (category == SDL_LOG_CATEGORY_ASSERT) {
    1.22 @@ -263,6 +266,7 @@
    1.23  SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va_list ap)
    1.24  {
    1.25      char *message;
    1.26 +    size_t len;
    1.27  
    1.28      /* Nothing to do if we don't have an output function */
    1.29      if (!SDL_log_function) {
    1.30 @@ -283,27 +287,91 @@
    1.31      if (!message) {
    1.32          return;
    1.33      }
    1.34 +
    1.35      SDL_vsnprintf(message, SDL_MAX_LOG_MESSAGE, fmt, ap);
    1.36 +
    1.37 +    /* Chop off final endline. */
    1.38 +    len = SDL_strlen(message);
    1.39 +    if ((len > 0) && (message[len-1] == '\n')) {
    1.40 +        message[--len] = '\0';
    1.41 +        if ((len > 0) && (message[len-1] == '\r')) {  /* catch "\r\n", too. */
    1.42 +            message[--len] = '\0';
    1.43 +        }
    1.44 +    }
    1.45 +
    1.46      SDL_log_function(SDL_log_userdata, category, priority, message);
    1.47      SDL_stack_free(message);
    1.48  }
    1.49  
    1.50 +#if defined(__WIN32__)
    1.51 +/* Flag tracking the attachment of the console: 0=unattached, 1=attached, -1=error */
    1.52 +static int consoleAttached = 0;
    1.53 +
    1.54 +/* Handle to stderr output of console. */
    1.55 +static HANDLE stderrHandle = NULL;
    1.56 +#endif
    1.57 +
    1.58  static void
    1.59  SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
    1.60                const char *message)
    1.61  {
    1.62  #if defined(__WIN32__) || defined(__WINRT__)
    1.63      /* Way too many allocations here, urgh */
    1.64 +    /* Note: One can't call SDL_SetError here, since that function itself logs. */
    1.65      {
    1.66          char *output;
    1.67          size_t length;
    1.68          LPTSTR tstr;
    1.69 +        BOOL attachResult;
    1.70 +        DWORD attachError;
    1.71 +        unsigned long charsWritten; 
    1.72  
    1.73 -        length = SDL_strlen(SDL_priority_prefixes[priority]) + 2 + SDL_strlen(message) + 1;
    1.74 +        /* Maybe attach console and get stderr handle */
    1.75 +        if (consoleAttached == 0) {
    1.76 +            attachResult = AttachConsole(ATTACH_PARENT_PROCESS);
    1.77 +            if (!attachResult) {
    1.78 +                    attachError = GetLastError();
    1.79 +                    if (attachError == ERROR_INVALID_HANDLE) {
    1.80 +                        OutputDebugString(TEXT("Parent process has no console"));
    1.81 +                        consoleAttached = -1;
    1.82 +                    } else if (attachError == ERROR_GEN_FAILURE) {
    1.83 +                         OutputDebugString(TEXT("Could not attach to console of parent process"));
    1.84 +                         consoleAttached = -1;
    1.85 +                    } else if (attachError == ERROR_ACCESS_DENIED) {  
    1.86 +                         /* Already attached */
    1.87 +                        consoleAttached = 1;
    1.88 +                    } else {
    1.89 +                        OutputDebugString(TEXT("Error attaching console"));
    1.90 +                        consoleAttached = -1;
    1.91 +                    }
    1.92 +                } else {
    1.93 +                    /* Newly attached */
    1.94 +                    consoleAttached = 1;
    1.95 +                }
    1.96 +			
    1.97 +                if (consoleAttached == 1) {
    1.98 +                        stderrHandle = GetStdHandle(STD_ERROR_HANDLE);
    1.99 +                }
   1.100 +        }
   1.101 +
   1.102 +        length = SDL_strlen(SDL_priority_prefixes[priority]) + 2 + SDL_strlen(message) + 1 + 1;
   1.103          output = SDL_stack_alloc(char, length);
   1.104 -        SDL_snprintf(output, length, "%s: %s", SDL_priority_prefixes[priority], message);
   1.105 +        SDL_snprintf(output, length, "%s: %s\n", SDL_priority_prefixes[priority], message);
   1.106          tstr = WIN_UTF8ToString(output);
   1.107 +        
   1.108 +        /* Output to debugger */
   1.109          OutputDebugString(tstr);
   1.110 +       
   1.111 +        /* Screen output to stderr, if console was attached. */
   1.112 +        if (consoleAttached == 1) {
   1.113 +                if (!WriteConsole(stderrHandle, tstr, lstrlen(tstr), &charsWritten, NULL)) {
   1.114 +                    OutputDebugString(TEXT("Error calling WriteConsole"));
   1.115 +                }
   1.116 +                if (charsWritten == ERROR_NOT_ENOUGH_MEMORY) {
   1.117 +                    OutputDebugString(TEXT("Insufficient heap memory to write message"));
   1.118 +                }
   1.119 +        }
   1.120 +
   1.121          SDL_free(tstr);
   1.122          SDL_stack_free(output);
   1.123      }
   1.124 @@ -314,7 +382,9 @@
   1.125          SDL_snprintf(tag, SDL_arraysize(tag), "SDL/%s", GetCategoryPrefix(category));
   1.126          __android_log_write(SDL_android_priority[priority], tag, message);
   1.127      }
   1.128 -#elif defined(__APPLE__)
   1.129 +#elif defined(__APPLE__) && defined(SDL_VIDEO_DRIVER_COCOA)
   1.130 +    /* Technically we don't need SDL_VIDEO_DRIVER_COCOA, but that's where this function is defined for now.
   1.131 +    */
   1.132      extern void SDL_NSLog(const char *text);
   1.133      {
   1.134          char *text;
   1.135 @@ -328,19 +398,12 @@
   1.136          }
   1.137      }
   1.138  #elif defined(__PSP__)
   1.139 -//Simple Log System for PSP
   1.140 -	{
   1.141 -		unsigned int length;
   1.142 -		char*		 output;
   1.143 -		FILE*		 pFile;
   1.144 -		length = SDL_strlen(SDL_priority_prefixes[priority]) + 2 + SDL_strlen(message) + 1;
   1.145 -        output = SDL_stack_alloc(char, length);
   1.146 -		SDL_snprintf(output, length, "%s: %s", SDL_priority_prefixes[priority], message);
   1.147 -		pFile = fopen ("SDL_Log.txt", "a");
   1.148 -		fwrite (output, strlen (output), 1, pFile);
   1.149 -		SDL_stack_free(output);
   1.150 -		fclose (pFile);
   1.151 -	}
   1.152 +    {
   1.153 +        FILE*        pFile;
   1.154 +        pFile = fopen ("SDL_Log.txt", "a");
   1.155 +        fprintf(pFile, "%s: %s\n", SDL_priority_prefixes[priority], message);
   1.156 +        fclose (pFile);
   1.157 +    }
   1.158  #endif
   1.159  #if HAVE_STDIO_H
   1.160      fprintf(stderr, "%s: %s\n", SDL_priority_prefixes[priority], message);