// // BJGOptionInterpreter.m // Escape // // Created by Brent Gulanowski on 11/26/05. // Copyright 2005 Bored Astronaut Software. All rights reserved. // #import "BJGOptionInterpreter.h" #import @interface BJGOptionInterpreter (BJGOptionInterpreter_private) +(NSArray *)parseOptions:(NSString *)opts; @end @implementation BJGOptionInterpreter /** inheritance tree overrides **/ #pragma mark NSObject #if 0 /* remove the guards as necessary */ +(void)initialize { } #endif -(id)init { [self release]; return nil; } /** new methods **/ #pragma mark BJGOptionInterpreter -(id)initWithOptionList:(NSString *)optList rawArguments:(NSArray *)args { NSArray *allOpts = [BJGOptionInterpreter parseOptions:optList]; NSMutableArray *opts = [NSMutableArray array]; NSMutableArray *optsArgs = [NSMutableArray array]; /* "opt_s_Args" plural: array of arrays of args */ NSMutableArray *otherArgs = [NSMutableArray array]; NSEnumerator *argsEnumerator; id arg; id nextArg; if(nil == args) { args = [[NSProcessInfo processInfo] arguments]; } argsEnumerator = [args objectEnumerator]; executable = [argsEnumerator nextObject]; arg = [argsEnumerator nextObject]; nextArg = [argsEnumerator nextObject]; while(arg) { id option; id optionWithArgs; /* If the current arg doesn't look like an option... */ if('-' != [arg characterAtIndex:0] /*|| 2 != [arg length]*/) { /* it isn't ... */ [otherArgs addObject:arg]; /* ... and none of the rest are either */ if(nextArg) { do { [otherArgs addObject:nextArg]; } while(nextArg = [argsEnumerator nextObject]); } break; } /* It may look like an option, but we have to confirm it's legitimate */ option = [arg substringWithRange:NSMakeRange(1,1)]; optionWithArgs = [option stringByAppendingString:@":"]; /* a legit option without arguments */ if(YES == [allOpts containsObject:option]) { int argLength = [arg length]; int pos = 2; if(NO == [opts containsObject:option]) { [opts addObject:option]; [optsArgs addObject:[NSArray array]]; } while(argLength - pos > 0 && YES == [allOpts containsObject:option]) { option = [arg substringWithRange:NSMakeRange(pos++,1)]; if(NO == [opts containsObject:option]) { [opts addObject:option]; [optsArgs addObject:[NSArray array]]; } } } else if(YES == [allOpts containsObject:optionWithArgs]) { /* a legit option with arguments */ NSMutableArray *optionArgs = [NSMutableArray array]; /* array of args */ if([arg length] > 2) { [optionArgs addObject:[arg substringFromIndex:2]]; } /* collect the arguments */ while(nextArg && '-' != [nextArg characterAtIndex:0]) { [optionArgs addObject:nextArg]; nextArg = [argsEnumerator nextObject]; } /* opts that require args and don't have 'em mean an error */ if(0 == [optionArgs count]) { [self release]; self = nil; break; } /* have we seen this option already? if so, coalesce arguments */ if(YES == [opts containsObject:option]) { int originalOptionIndex = [opts indexOfObject:option]; [optionArgs addObjectsFromArray:[optsArgs objectAtIndex:originalOptionIndex]]; [optsArgs replaceObjectAtIndex:originalOptionIndex withObject:optionArgs]; } else { [opts addObject:option]; [optsArgs addObject:optionArgs]; } } /* bad option; release self and return nothing; app should print usage message */ else { [self release]; self = nil; break; } arg = nextArg; nextArg = [argsEnumerator nextObject]; } /* if we got here and didn't commit suicide, collect a nice arg dictionary */ if(self) { optionList = [optList retain]; arguments = [[NSArray arrayWithArray:otherArgs] retain]; options = [[NSDictionary dictionaryWithObjects:optsArgs forKeys:opts] retain]; } return self; } -(NSString *)optionList { return [[optionList copy] autorelease]; } -(NSString *)executable { return [[executable copy] autorelease]; } -(NSDictionary *)options { return [[options copy] autorelease]; } -(NSArray *)arguments { return [[arguments copy] autorelease]; } #pragma mark BJGOptionInterpreter_private +(NSArray *)parseOptions:(NSString *)opts { int i; int length =[opts length]; NSMutableArray *options = [NSMutableArray arrayWithCapacity:length]; NSCharacterSet *lower = [NSCharacterSet lowercaseLetterCharacterSet]; for(i = 0; i