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 + */