diff --git a/Tools/AGSOutput.h b/Tools/AGSOutput.h
index 9ae40e17d..036006355 100644
--- a/Tools/AGSOutput.h
+++ b/Tools/AGSOutput.h
@@ -30,6 +30,11 @@
NSCharacterSet *spacenl; // Blanks excluding newline
}
+- (unsigned) fitWords: (NSArray*)a
+ from: (unsigned)start
+ to: (unsigned)end
+ maxSize: (unsigned)limit
+ output: (NSMutableString*)buf;
- (NSString*) output: (NSDictionary*)d;
- (BOOL) output: (NSDictionary*)d file: (NSString*)name;
- (void) outputMethod: (NSDictionary*)d to: (NSMutableString*)str;
diff --git a/Tools/AGSOutput.m b/Tools/AGSOutput.m
index 1d1cadcdb..e5a7797f1 100644
--- a/Tools/AGSOutput.m
+++ b/Tools/AGSOutput.m
@@ -22,17 +22,6 @@
#include "AGSOutput.h"
-@implementation AGSOutput
-
-- (void) dealloc
-{
- DESTROY(identifier);
- DESTROY(identStart);
- DESTROY(spaces);
- DESTROY(spacenl);
- [super dealloc];
-}
-
static BOOL snuggleEnd(NSString *t)
{
static NSCharacterSet *set = nil;
@@ -61,6 +50,18 @@ static BOOL snuggleStart(NSString *t)
return [set characterIsMember: [t characterAtIndex: [t length] - 1]];
}
+
+@implementation AGSOutput
+
+- (void) dealloc
+{
+ DESTROY(identifier);
+ DESTROY(identStart);
+ DESTROY(spaces);
+ DESTROY(spacenl);
+ [super dealloc];
+}
+
- (unsigned) fitWords: (NSArray*)a
from: (unsigned)start
to: (unsigned)end
@@ -382,8 +383,8 @@ static BOOL snuggleStart(NSString *t)
}
/**
- * Uses -split: and -reformat:withIndent:to:
- * and has fun with YES, NO, and nil.
+ * Uses -split: and -reformat:withIndent:to:.
+ * Also has fun with YES, NO, and nil.
*/
- (void) outputMethod: (NSDictionary*)d to: (NSMutableString*)str
{
@@ -744,7 +745,15 @@ static BOOL snuggleStart(NSString *t)
unichar *ptr;
unichar *end;
unichar *buf;
-
+
+ /**
+ * Phase 1 ... we take the supplied string andcheck for white space.
+ * Any white space sequence is deleted and treated as a word separator
+ * except within xml element markup. The format of element start and
+ * end marks is tidied for consistency. The resulting data is made
+ * into an array of strings, each containing either an element start
+ * or end tag, or one of the whitespace separated words.
+ */
data = [[NSMutableData alloc] initWithLength: l * sizeof(unichar)];
ptr = buf = [data mutableBytes];
[str getCharacters: buf];
@@ -876,12 +885,21 @@ static BOOL snuggleStart(NSString *t)
[a addObject: tmp];
}
+ /*
+ * Phase 2 ... the array of words is checked to see if a word contains
+ * a well known constant, or a method name specification.
+ * Where these special cases apply, the array of words is modified to
+ * insert extra gsdoc markup to highlight the constants and to create
+ * references to where the named methods are documented.
+ */
for (l = 0; l < [a count]; l++)
{
static NSArray *constants = nil;
static unsigned cCount = 0;
+ NSString *tmp = [a objectAtIndex: l];
unsigned pos;
- NSString *tmp = [a objectAtIndex: l];
+ NSRange r;
+ BOOL hadMethod = NO;
/*
* Ensure that well known constants are rendered as 'code'
@@ -895,7 +913,8 @@ static BOOL snuggleStart(NSString *t)
for (pos = 0; pos < cCount; pos++)
{
NSString *c = [constants objectAtIndex: pos];
- NSRange r = [tmp rangeOfString: c];
+
+ r = [tmp rangeOfString: c];
if (r.length > 0)
{
@@ -952,18 +971,228 @@ static BOOL snuggleStart(NSString *t)
/*
* Ensure that methods are rendered as references.
+ * First look for format with class name in square brackets.
*/
- if ([tmp length] > 1 && ([tmp hasPrefix: @"-"] || [tmp hasPrefix: @"+"]))
+ r = [tmp rangeOfString: @"["];
+ if (r.length > 0)
{
- if (l == 0 || [[a objectAtIndex: l - 1] hasPrefix: @"[", tmp];
- [a insertObject: @"]" atIndex: l + 1];
- [a insertObject: ref atIndex: l];
- l += 2;
+ r = NSMakeRange(pos, [tmp length] - pos);
+ r = [tmp rangeOfString: @"]" options: NSLiteralSearch range: r];
+ if (r.length > 0)
+ {
+ unsigned ePos = r.location;
+ NSString *cName = nil;
+ NSString *mName = nil;
+ unichar c;
+
+ if (pos < ePos
+ && [identStart characterIsMember:
+ (c = [tmp characterAtIndex: pos])] == YES)
+ {
+ pos++;
+ while (pos < ePos)
+ {
+ c = [tmp characterAtIndex: pos];
+ if ([identifier characterIsMember: c] == NO)
+ {
+ break;
+ }
+ pos++;
+ }
+ if (c == '(')
+ {
+ pos++;
+ if (pos < ePos
+ && [identStart characterIsMember:
+ (c = [tmp characterAtIndex: pos])] == YES)
+ {
+ while (pos < ePos)
+ {
+ c = [tmp characterAtIndex: pos];
+ if ([identifier characterIsMember: c] == NO)
+ {
+ break;
+ }
+ pos++;
+ }
+ if (c == ')')
+ {
+ pos++;
+ r = NSMakeRange(sPos, pos - sPos);
+ cName = [tmp substringWithRange: r];
+ if (pos < ePos)
+ {
+ c = [tmp characterAtIndex: pos];
+ }
+ }
+ }
+ if (cName == nil)
+ {
+ pos = ePos; // Bad class name!
+ }
+ }
+ else
+ {
+ r = NSMakeRange(sPos, pos - sPos);
+ cName = [tmp substringWithRange: r];
+ }
+ }
+
+ if (pos < ePos && (c == '+' || c == '-'))
+ {
+ unsigned mStart = pos;
+
+ pos++;
+ if (pos < ePos
+ && [identStart characterIsMember:
+ (c = [tmp characterAtIndex: pos])] == YES)
+ {
+ while (pos < ePos)
+ {
+ c = [tmp characterAtIndex: pos];
+ if (c != ':'
+ && [identifier characterIsMember: c] == NO)
+ {
+ break;
+ }
+ pos++;
+ }
+ /*
+ * The end of the method name should be immediately
+ * before the closing square bracket at 'ePos'
+ */
+ if (pos == ePos && pos - mStart > 1)
+ {
+ r = NSMakeRange(mStart, pos - mStart);
+ mName = [tmp substringWithRange: r];
+ }
+ }
+ }
+ if (mName != nil)
+ {
+ NSString *start;
+ NSString *end;
+ NSString *sub;
+ NSString *ref;
+
+ if (sPos > 0)
+ {
+ start = [tmp substringToIndex: sPos];
+ }
+ else
+ {
+ start = nil;
+ }
+ if (ePos < [tmp length])
+ {
+ end = [tmp substringFromIndex: ePos];
+ }
+ else
+ {
+ end = nil;
+ }
+
+ if (start != nil || end != nil)
+ {
+ sub = [tmp substringWithRange:
+ NSMakeRange(sPos, ePos - sPos)];
+ }
+ else
+ {
+ sub = nil;
+ }
+ if (start != nil)
+ {
+ [a insertObject: start atIndex: l++];
+ }
+ if (cName == nil)
+ {
+ ref = [NSString stringWithFormat:
+ @"[", mName];
+ }
+ else
+ {
+ ref = [NSString stringWithFormat:
+ @"][",
+ mName, cName];
+ }
+ [a insertObject: ref atIndex: l++];
+ if (sub != nil)
+ {
+ [a replaceObjectAtIndex: l withObject: sub];
+ }
+
+ l++;
+ [a insertObject: @"]" atIndex: l];
+ if (end != nil)
+ {
+ [a insertObject: end atIndex: ++l];
+ }
+ hadMethod = YES;
+ }
+ }
+ }
+
+ /*
+ * Now handle bare method names for current class ... outside brackets.
+ */
+ if (hadMethod == NO && ([tmp hasPrefix: @"-"] || [tmp hasPrefix: @"+"]))
+ {
+ unsigned ePos = [tmp length];
+ NSString *mName = nil;
+ unsigned c;
+
+ pos = 1;
+ if (pos < ePos
+ && [identStart characterIsMember:
+ (c = [tmp characterAtIndex: pos])] == YES)
+ {
+ while (pos < ePos)
+ {
+ c = [tmp characterAtIndex: pos];
+ if (c != ':'
+ && [identifier characterIsMember: c] == NO)
+ {
+ break;
+ }
+ pos++;
+ }
+ if (pos > 1 && (pos == ePos || c == ',' || c == '.' || c == ';'))
+ {
+ NSString *end;
+ NSString *sub;
+ NSString *ref;
+
+ mName = [tmp substringWithRange: NSMakeRange(0, pos)];
+
+ if (pos < [tmp length])
+ {
+ end = [tmp substringFromIndex: pos];
+ sub = [tmp substringToIndex: pos];
+ }
+ else
+ {
+ end = nil;
+ sub = nil;
+ }
+
+ ref = [NSString stringWithFormat:
+ @"[", mName];
+ [a insertObject: ref atIndex: l++];
+ if (sub != nil)
+ {
+ [a replaceObjectAtIndex: l withObject: sub];
+ }
+ l++;
+ [a insertObject: @"]" atIndex: l];
+ if (end != nil)
+ {
+ [a insertObject: end atIndex: ++l];
+ }
+ hadMethod = YES;
+ }
}
}
}