diff --git a/src/MacVim/MMAppController.m b/src/MacVim/MMAppController.m index be710e5f91..0e108ca5a9 100644 --- a/src/MacVim/MMAppController.m +++ b/src/MacVim/MMAppController.m @@ -153,6 +153,12 @@ fsEventCallback(ConstFSEventStreamRef streamRef, + (void)initialize { + static BOOL initDone = NO; + if (initDone) return; + initDone = YES; + + ASLInit(); + NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:NO], MMNoWindowKey, [NSNumber numberWithInt:64], MMTabMinWidthKey, diff --git a/src/MacVim/MacVim.h b/src/MacVim/MacVim.h index 895b4b98ad..68c74a4a6f 100644 --- a/src/MacVim/MacVim.h +++ b/src/MacVim/MacVim.h @@ -9,6 +9,7 @@ */ #import +#import // @@ -224,10 +225,18 @@ enum { NSString *debugStringForMessageQueue(NSArray *queue); +// Shared user defaults (most user defaults are in Miscellaneous.h). +// Contrary to the user defaults in Miscellaneous.h these defaults are not +// intitialized to any default values. That is, unless the user sets them +// these keys will not be present in the user default database. +extern NSString *MMLogLevelKey; +extern NSString *MMLogToStdErrKey; + // Argument used to stop MacVim from opening an empty window on startup // (techincally this is a user default but should not be used as such). extern NSString *MMNoWindowKey; + // Vim pasteboard type (holds motion type + string) extern NSString *VimPBoardType; @@ -284,3 +293,55 @@ typedef int NSInteger; typedef unsigned int NSUInteger; # endif #endif + + + +// Logging related functions and macros. +// +// This is a very simplistic logging facility built on top of ASL. Two user +// defaults allow for changing the local log filter level (MMLogLevel) and +// whether logs should be sent to stderr (MMLogToStdErr). (These user defaults +// are only checked during startup.) The default is to block level 6 (info) +// and 7 (debug) logs and _not_ to send logs to stderr. Apart from this +// "syslog" (see "man syslog") can be used to modify the ASL filters (it is +// currently not possible to change the local filter at runtime). For example: +// Enable all logs to reach the ASL database (by default 'debug' and 'info' +// are filtered out, see "man syslogd"): +// $ sudo syslog -c syslogd -d +// Reset the ASL database filter: +// $ sudo syslog -c syslogd off +// Change the master filter to block logs less severe than errors: +// $ sudo syslog -c 0 -e +// Change per-process filter for running MacVim process to block logs less +// severe than warnings: +// $ syslog -c MacVim -w +// +// Note that there are four ASL filters: +// 1) The ASL database filter (syslog -c syslogd ...) +// 2) The master filter (syslog -c 0 ...) +// 3) The per-process filter (syslog -c PID ...) +// 4) The local filter (MMLogLevel) +// +// To view the logs, either use "Console.app" or the "syslog" command: +// $ syslog -w | grep Vim +// To get the logs to show up in Xcode enable the MMLogToStdErr user default. + +extern int ASLogLevel; + +void ASLInit(); + +#define ASLog(level, fmt, ...) \ + if (level <= ASLogLevel) { \ + asl_log(NULL, NULL, level, "%s@%d %s", \ + __PRETTY_FUNCTION__, __LINE__, \ + [[NSString stringWithFormat:fmt, ##__VA_ARGS__] UTF8String]); \ + } + +// Note: These macros are used like ASLogErr(@"text num=%d", 42). Objective-C +// style specifiers (%@) are supported. +#define ASLogCrit(fmt, ...) ASLog(ASL_LEVEL_CRIT, fmt, ##__VA_ARGS__) +#define ASLogErr(fmt, ...) ASLog(ASL_LEVEL_ERR, fmt, ##__VA_ARGS__) +#define ASLogWarn(fmt, ...) ASLog(ASL_LEVEL_WARNING, fmt, ##__VA_ARGS__) +#define ASLogNotice(fmt, ...) ASLog(ASL_LEVEL_NOTICE, fmt, ##__VA_ARGS__) +#define ASLogInfo(fmt, ...) ASLog(ASL_LEVEL_INFO, fmt, ##__VA_ARGS__) +#define ASLogDebug(fmt, ...) ASLog(ASL_LEVEL_DEBUG, fmt, ##__VA_ARGS__) diff --git a/src/MacVim/MacVim.m b/src/MacVim/MacVim.m index 058ce663d4..3e59d6b378 100644 --- a/src/MacVim/MacVim.m +++ b/src/MacVim/MacVim.m @@ -13,6 +13,7 @@ #import "MacVim.h" + char *MessageStrings[] = { "INVALID MESSAGE ID", @@ -99,6 +100,9 @@ char *MessageStrings[] = +NSString *MMLogLevelKey = @"MMLogLevel"; +NSString *MMLogToStdErrKey = @"MMLogToStdErr"; + // Argument used to stop MacVim from opening an empty window on startup // (techincally this is a user default but should not be used as such). NSString *MMNoWindowKey = @"MMNoWindow"; @@ -106,6 +110,8 @@ NSString *MMNoWindowKey = @"MMNoWindow"; // Vim pasteboard type (holds motion type + string) NSString *VimPBoardType = @"VimPBoardType"; +int ASLogLevel = ASL_LEVEL_NOTICE; + // Create a string holding the labels of all messages in message queue for @@ -244,3 +250,34 @@ debugStringForMessageQueue(NSArray *queue) } @end + + + + + void +ASLInit() +{ + NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; + + // Allow for changing the log level via user defaults. If no key is found + // the default log level will be used (which for ASL is to log everything + // up to ASL_LEVEL_NOTICE). This key is an integer which corresponds to + // the ASL_LEVEL_* macros (0 is most severe, 7 is debug level). + id logLevelObj = [ud objectForKey:MMLogLevelKey]; + if (logLevelObj) { + int logLevel = [logLevelObj intValue]; + if (logLevel < 0) logLevel = 0; + if (logLevel > ASL_LEVEL_DEBUG) logLevel = ASL_LEVEL_DEBUG; + + ASLogLevel = logLevel; + asl_set_filter(NULL, ASL_FILTER_MASK_UPTO(logLevel)); + } + + // Allow for changing whether a copy of each log should be sent to stderr + // (this defaults to NO if this key is missing in the user defaults + // database). The above filter mask is applied to logs going to stderr, + // contrary to how "vanilla" ASL works. + BOOL logToStdErr = [ud boolForKey:MMLogToStdErrKey]; + if (logToStdErr) + asl_add_log_file(NULL, 2); // The file descriptor for stderr is 2 +} diff --git a/src/MacVim/gui_macvim.m b/src/MacVim/gui_macvim.m index 91ad7855de..86d332b3fa 100644 --- a/src/MacVim/gui_macvim.m +++ b/src/MacVim/gui_macvim.m @@ -42,6 +42,7 @@ vimmenu_T *menu_for_descriptor(NSArray *desc); * Parse the GUI related command-line arguments. Any arguments used are * deleted from argv, and *argc is decremented accordingly. This is called * when vim is started, whether or not the GUI has been started. + * NOTE: This function will be called twice if the Vim process forks. */ void gui_mch_prepare(int *argc, char **argv) @@ -110,6 +111,7 @@ gui_mch_init_check(void) gui_mch_init(void) { //NSLog(@"gui_mch_init()"); + ASLInit(); if (![[MMBackend sharedInstance] checkin]) { // TODO: Kill the process if there is no terminal to fall back on,