Logging.m
changeset 20 5a71993a1a70
parent 1 e55a17cdabd2
child 19 5ade3e09a827
     1.1 --- a/Logging.m	Thu Mar 20 09:05:58 2008 -0700
     1.2 +++ b/Logging.m	Sat Mar 28 09:36:46 2009 -0700
     1.3 @@ -7,9 +7,12 @@
     1.4  //
     1.5  
     1.6  #import "Logging.h"
     1.7 -#import <unistd.h>
     1.8 +#import "CollectionUtils.h"
     1.9 +
    1.10 +#include <unistd.h>
    1.11  #include <fcntl.h>
    1.12  #include <sys/param.h>
    1.13 +#include <termios.h>
    1.14  
    1.15  
    1.16  NSString* LOC( NSString *key )     // Localized string lookup
    1.17 @@ -23,19 +26,35 @@
    1.18  }
    1.19  
    1.20  
    1.21 +typedef enum {
    1.22 +    kLoggingToOther,
    1.23 +    kLoggingToFile,
    1.24 +    kLoggingToTTY,
    1.25 +    kLoggingToColorTTY
    1.26 +} MYLoggingTo;
    1.27 +
    1.28 +
    1.29  int _gShouldLog = -1;
    1.30 -static BOOL sConsole;
    1.31 +static MYLoggingTo sLoggingTo;
    1.32  static NSMutableSet *sEnabledDomains;
    1.33  
    1.34  
    1.35 -static BOOL isConsole( int fd )
    1.36 +/** Does the file descriptor connect to console output, i.e. a terminal or Xcode? */
    1.37 +static MYLoggingTo getLoggingMode( int fd )
    1.38  {
    1.39 -    if( isatty(fd) )
    1.40 -        return YES;
    1.41 -    char path[MAXPATHLEN];
    1.42 -    if( fcntl(fd, F_GETPATH, path) == -1 )
    1.43 -        return NO;
    1.44 -    return YES;
    1.45 +    if( isatty(fd) ) {
    1.46 +        const char *term = getenv("TERM");
    1.47 +        if( term && (strstr(term,"ANSI") || strstr(term,"ansi") || strstr(term,"color")) )
    1.48 +            return kLoggingToColorTTY;
    1.49 +        else
    1.50 +            return kLoggingToTTY;
    1.51 +    } else {
    1.52 +        char path[MAXPATHLEN];
    1.53 +        if( fcntl(fd, F_GETPATH, path) == 0 )
    1.54 +            return kLoggingToFile;
    1.55 +        else
    1.56 +            return kLoggingToOther;
    1.57 +    }
    1.58  }
    1.59  
    1.60  
    1.61 @@ -57,9 +76,10 @@
    1.62                  [sEnabledDomains addObject: [key substringFromIndex: 3]];
    1.63          }
    1.64      }
    1.65 -    sConsole = isConsole(STDERR_FILENO);
    1.66 +    sLoggingTo = getLoggingMode(STDERR_FILENO);
    1.67      
    1.68 -    Log(@"Logging enabled in domains: {%@}", 
    1.69 +    Log(@"Logging mode %i enabled in domains: {%@}", 
    1.70 +        sLoggingTo,
    1.71          [[[sEnabledDomains allObjects] sortedArrayUsingSelector: @selector(caseInsensitiveCompare:)] 
    1.72                  componentsJoinedByString: @", "]);
    1.73      [pool drain];
    1.74 @@ -95,9 +115,14 @@
    1.75  }
    1.76  
    1.77  
    1.78 +#define kWarningPrefix @"\007WARNING*** "
    1.79 +            
    1.80 +#define COLOR(STR)     (sLoggingTo==kLoggingToColorTTY ?@"\033["#STR"m" :@"")
    1.81 +
    1.82 +
    1.83  static void _Logv( NSString *prefix, NSString *msg, va_list args )
    1.84  {
    1.85 -    if( sConsole ) {
    1.86 +    if( sLoggingTo > kLoggingToOther ) {
    1.87          NSAutoreleasePool *pool = [NSAutoreleasePool new];
    1.88          static NSDateFormatter *sTimestampFormat;
    1.89          if( ! sTimestampFormat ) {
    1.90 @@ -109,14 +134,21 @@
    1.91          [now release];
    1.92          NSString *separator = prefix.length ?@": " :@"";
    1.93          msg = [[NSString alloc] initWithFormat: msg arguments: args];
    1.94 -        NSString *finalMsg = [[NSString alloc] initWithFormat: @"%@| %@%@%@\n", 
    1.95 -                              timestamp,prefix,separator,msg];
    1.96 +        NSString *prefixColor = (prefix==kWarningPrefix) ?COLOR(91) :COLOR(93);
    1.97 +        NSString *msgColor = (prefix==kWarningPrefix) ?@"" :COLOR(0);
    1.98 +        NSString *finalMsg = [[NSString alloc] initWithFormat: @"%@%@| %@%@%@%@%@\n", 
    1.99 +                              COLOR(30),timestamp,
   1.100 +                              prefixColor,prefix,separator,
   1.101 +                              msgColor,msg];
   1.102          fputs([finalMsg UTF8String], stderr);
   1.103          [finalMsg release];
   1.104          [msg release];
   1.105          [pool drain];
   1.106 -    } else
   1.107 +    } else {
   1.108 +        if( prefix.length )
   1.109 +            msg = $sprintf(@"%@: %@", prefix,msg);
   1.110          NSLogv(msg,args);
   1.111 +    }
   1.112  }
   1.113  
   1.114  
   1.115 @@ -159,8 +191,31 @@
   1.116  {
   1.117      va_list args;
   1.118      va_start(args,msg);
   1.119 -    _Logv(@"WARNING*** ",msg,args);
   1.120 +    _Logv(kWarningPrefix,msg,args);
   1.121      va_end(args);
   1.122  }
   1.123  
   1.124  
   1.125 +
   1.126 +
   1.127 +/*
   1.128 + Copyright (c) 2008, Jens Alfke <jens@mooseyard.com>. All rights reserved.
   1.129 + 
   1.130 + Redistribution and use in source and binary forms, with or without modification, are permitted
   1.131 + provided that the following conditions are met:
   1.132 + 
   1.133 + * Redistributions of source code must retain the above copyright notice, this list of conditions
   1.134 + and the following disclaimer.
   1.135 + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
   1.136 + and the following disclaimer in the documentation and/or other materials provided with the
   1.137 + distribution.
   1.138 + 
   1.139 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
   1.140 + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
   1.141 + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
   1.142 + BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   1.143 + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
   1.144 +  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   1.145 + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 
   1.146 + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   1.147 + */