Logging.m
author Jens Alfke <jens@mooseyard.com>
Sat May 17 13:14:48 2008 -0700 (2008-05-17)
changeset 9 823e7e74088e
parent 0 d84d25d6cdbb
child 11 e5976864dfe9
permissions -rw-r--r--
* Assert macros now put the failure code in a separate segment.
* Added $string utility.
     1 //
     2 //  Logging.m
     3 //  MYUtilities
     4 //
     5 //  Created by Jens Alfke on 1/5/08.
     6 //  Copyright 2008 Jens Alfke. All rights reserved.
     7 //
     8 
     9 #import "Logging.h"
    10 #import <unistd.h>
    11 #include <fcntl.h>
    12 #include <sys/param.h>
    13 
    14 
    15 NSString* LOC( NSString *key )     // Localized string lookup
    16 {
    17     NSString *value = [[NSBundle mainBundle] localizedStringForKey:key value:nil table:nil];
    18     if( value == key ) {
    19         Warn(@"No localized string for '%@' in Localizable.strings!",key);
    20         value = [key uppercaseString];
    21     }
    22     return value;
    23 }
    24 
    25 
    26 int _gShouldLog = -1;
    27 static BOOL sConsole;
    28 static NSMutableSet *sEnabledDomains;
    29 
    30 
    31 static BOOL isConsole( int fd )
    32 {
    33     if( isatty(fd) )
    34         return YES;
    35     char path[MAXPATHLEN];
    36     if( fcntl(fd, F_GETPATH, path) == -1 )
    37         return NO;
    38     return YES;
    39 }
    40 
    41 
    42 static void InitLogging()
    43 {
    44     if( _gShouldLog != -1 )
    45         return;
    46 
    47     NSAutoreleasePool *pool = [NSAutoreleasePool new];
    48     _gShouldLog = NO;
    49     sEnabledDomains = [[NSMutableSet alloc] init];
    50     NSDictionary *dflts = [[NSUserDefaults standardUserDefaults] dictionaryRepresentation];
    51     for( NSString *key in dflts ) {
    52         if( [key hasPrefix: @"Log"] ) {
    53             BOOL value = [[NSUserDefaults standardUserDefaults] boolForKey: key];
    54             if( key.length==3 )
    55                 _gShouldLog = value;
    56             else if( value )
    57                 [sEnabledDomains addObject: [key substringFromIndex: 3]];
    58         }
    59     }
    60     sConsole = isConsole(STDERR_FILENO);
    61     
    62     Log(@"Logging enabled in domains: {%@}", 
    63         [[[sEnabledDomains allObjects] sortedArrayUsingSelector: @selector(caseInsensitiveCompare:)] 
    64                 componentsJoinedByString: @", "]);
    65     [pool drain];
    66 }
    67 
    68 
    69 BOOL EnableLog( BOOL enable )
    70 {
    71     if( _gShouldLog == -1 )
    72         InitLogging();
    73     BOOL old = _gShouldLog;
    74     _gShouldLog = enable;
    75     return old;
    76 }
    77 
    78 BOOL _WillLogTo( NSString *domain )
    79 {
    80     if( _gShouldLog == -1 )
    81         InitLogging();
    82     return _gShouldLog && [sEnabledDomains containsObject: domain];
    83 }
    84 
    85 BOOL _EnableLogTo( NSString *domain, BOOL enable )
    86 {
    87     if( _gShouldLog == -1 )
    88         InitLogging();
    89     BOOL old = [sEnabledDomains containsObject: domain];
    90     if( enable )
    91         [sEnabledDomains addObject: domain];
    92     else
    93         [sEnabledDomains removeObject: domain];
    94     return old;
    95 }
    96 
    97 
    98 static void _Logv( NSString *prefix, NSString *msg, va_list args )
    99 {
   100     if( sConsole ) {
   101         NSAutoreleasePool *pool = [NSAutoreleasePool new];
   102         static NSDateFormatter *sTimestampFormat;
   103         if( ! sTimestampFormat ) {
   104             sTimestampFormat = [[NSDateFormatter alloc] init];
   105             sTimestampFormat.dateFormat = @"HH:mm:ss.SSS";
   106         }
   107         NSDate *now = [[NSDate alloc] init];
   108         NSString *timestamp = [sTimestampFormat stringFromDate: now];
   109         [now release];
   110         NSString *separator = prefix.length ?@": " :@"";
   111         msg = [[NSString alloc] initWithFormat: msg arguments: args];
   112         NSString *finalMsg = [[NSString alloc] initWithFormat: @"%@| %@%@%@\n", 
   113                               timestamp,prefix,separator,msg];
   114         fputs([finalMsg UTF8String], stderr);
   115         [finalMsg release];
   116         [msg release];
   117         [pool drain];
   118     } else
   119         NSLogv(msg,args);
   120 }
   121 
   122 
   123 void AlwaysLog( NSString *msg, ... )
   124 {
   125     va_list args;
   126     va_start(args,msg);
   127     _Logv(@"",msg,args);
   128     va_end(args);
   129 }
   130 
   131 
   132 void _Log( NSString *msg, ... )
   133 {
   134     if( _gShouldLog == -1 )
   135         InitLogging();
   136     if( _gShouldLog ) {
   137         va_list args;
   138         va_start(args,msg);
   139         _Logv(@"",msg,args);
   140         va_end(args);
   141     }
   142 }
   143 
   144 
   145 void _LogTo( NSString *domain, NSString *msg, ... )
   146 {
   147     if( _gShouldLog == -1 )
   148         InitLogging();
   149     if( _gShouldLog && [sEnabledDomains containsObject: domain] ) {
   150         va_list args;
   151         va_start(args,msg);
   152         _Logv(domain, msg, args);
   153         va_end(args);
   154     }
   155 }
   156 
   157 
   158 void Warn( NSString *msg, ... )
   159 {
   160     va_list args;
   161     va_start(args,msg);
   162     _Logv(@"WARNING*** ",msg,args);
   163     va_end(args);
   164 }
   165 
   166