lots of autogsdoc improvements.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@12049 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
CaS 2002-01-08 17:31:38 +00:00
parent cb8c962f80
commit 16afaed1af
11 changed files with 669 additions and 237 deletions

View file

@ -1,3 +1,23 @@
2002-01-08 Richard Frith-Macdonald <rfm@gnu.org>
* Tools/AGSHtml.h:
* Tools/AGSHtml.m:
* Tools/AGSIndex.h:
* Tools/AGSIndex.m:
* Tools/AGSOutput.h:
* Tools/AGSOutput.m:
* Tools/AGSParser.h:
* Tools/AGSParser.m:
* Tools/autogsdoc.m:
* Tools/gsdoc-0_6_7.dtd:
Updated for several changes ...
Support documentation of instance variables
Index class and category method names identically
Extend index to have a listing of methods by unit
Extend index to have a listing of ivariablese by class
Use new extensions to double speed of generation of method
indexes for classes.
2002-01-07 Adam Fedor <fedor@gnu.org> 2002-01-07 Adam Fedor <fedor@gnu.org>
* Version: 1.1.0 * Version: 1.1.0

View file

@ -32,6 +32,8 @@
NSMutableString *indent; NSMutableString *indent;
NSString *base; // Not retained NSString *base; // Not retained
NSString *unit; // Not retained NSString *unit; // Not retained
NSString *category; // Not retained
NSString *classname; // Not retained
NSString *heading; // Not retained NSString *heading; // Not retained
NSString *nextFile; // Not retained NSString *nextFile; // Not retained
NSString *prevFile; // Not retained NSString *prevFile; // Not retained

View file

@ -192,12 +192,26 @@ static NSMutableSet *textNodes = nil;
s = base; s = base;
} }
else if (u == nil) else if (u == nil)
{
if (category == nil)
{ {
u = unit; u = unit;
}
else
{
u = classname;
}
s = [localRefs unitRef: r type: t unit: &u]; s = [localRefs unitRef: r type: t unit: &u];
if (s == nil) if (s == nil)
{
if (category == nil)
{ {
u = unit; u = unit;
}
else
{
u = classname;
}
s = [globalRefs unitRef: r type: t unit: &u]; s = [globalRefs unitRef: r type: t unit: &u];
} }
} }
@ -264,65 +278,127 @@ static NSMutableSet *textNodes = nil;
title: (NSString*)title title: (NSString*)title
to: (NSMutableString*)buf to: (NSMutableString*)buf
{ {
NSDictionary *dict = [localRefs refs]; NSDictionary *refs = [localRefs refs];
NSDictionary *dict;
NSArray *a;
unsigned c;
unsigned i;
if (globalRefs != nil && [scope isEqual: @"global"] == YES) if (globalRefs != nil && [scope isEqual: @"global"] == YES)
{ {
dict = [globalRefs refs]; refs = [globalRefs refs];
} }
else if (projectRefs != nil && [scope isEqual: @"project"] == YES) else if (projectRefs != nil && [scope isEqual: @"project"] == YES)
{ {
dict = [projectRefs refs]; refs = [projectRefs refs];
} }
dict = [dict objectForKey: type]; if ([type isEqualToString: @"method"] == YES)
if ([dict count] > 1 {
|| ([dict count] > 0 && [type isEqual: @"title"] == NO)) if (unit == nil)
{
refs = nil; // Can't index methods outside a unit.
}
dict = [refs objectForKey: @"unitmethods"];
dict = [dict objectForKey: unit];
}
else if ([type isEqualToString: @"ivariable"] == YES)
{
if (unit == nil)
{
refs = nil; // Can't index instance variables outside a class.
}
dict = [refs objectForKey: @"classvars"];
dict = [dict objectForKey: unit];
}
else
{
dict = [refs objectForKey: type];
}
if ([dict count] > 1 && [type isEqual: @"title"] == YES)
{
[buf appendString: indent];
[buf appendFormat: @"<b>%@</b>\n", title];
[buf appendString: indent];
[buf appendString: @"<ul>\n"];
[self incIndent];
a = [dict allKeys];
a = [a sortedArrayUsingSelector: @selector(compare:)];
c = [a count];
for (i = 0; i < c; i++)
{
NSString *ref = [a objectAtIndex: i];
NSString *text = [dict objectForKey: ref];
NSString *file = ref;
if ([file isEqual: base] == YES)
{
continue; // Don't list current file.
}
[buf appendString: indent];
[buf appendString: @"<li><a rel=\"gsdoc\" href="];
[buf appendFormat: @"\"%@.html#%@$%@\">%@</a></li>\n",
file, type, ref, text];
}
[self decIndent];
[buf appendString: indent];
[buf appendString: @"</ul>\n"];
}
else if ([dict count] > 0)
{ {
NSArray *a = [dict allKeys];
unsigned c = [a count];
NSMutableSet *unitNames = nil;
unsigned i;
NSString *sep = @""; NSString *sep = @"";
NSString *u = unit;
BOOL isInUnit = NO; BOOL isInUnit = NO;
if (unit != nil)
{
if ([type isEqual: @"method"] || [type isEqual: @"ivariable"]) if ([type isEqual: @"method"] || [type isEqual: @"ivariable"])
{ {
isInUnit = YES; isInUnit = YES;
if ([type isEqual: @"ivariable"]) if ([type isEqual: @"ivariable"])
{ {
sep = @"*"; sep = @"*"; // List ivars in class
} }
else if (unit != nil) else if (category != nil)
{ {
/* u = classname; // List methods in category
* Create a mutable set containing the unit name. }
*/ else if (classname != nil)
unitNames = [NSMutableSet setWithObject: unit];
/*
* if the unit is a class, add all its categories to the set.
*/
if ([unit hasSuffix: @")"] == NO)
{ {
NSArray *categoryNames; NSArray *catNames;
unsigned l = [unit length];
categoryNames = [[dict objectForKey: @"category"] allKeys]; /*
i = [categoryNames count]; * For a clss, we want to list methods in any associated
while (i-- > 0) * categories as well as those of the class itsself.
*/
catNames = [[[refs objectForKey: @"categories"]
objectForKey: classname] allKeys];
if ((c = [catNames count]) > 0)
{ {
NSString *n = [categoryNames objectAtIndex: i]; NSMutableDictionary *m = [dict mutableCopy];
NSDictionary *unitDict;
if ([n hasPrefix: unit] == YES && [n length] > l unitDict = [refs objectForKey: @"unitmethods"];
&& [n characterAtIndex: i] == '(') for (i = 0; i < c; i++)
{ {
[unitNames addObject: n]; NSString *catName = [catNames objectAtIndex: i];
NSDictionary *catDict;
catName = [classname stringByAppendingFormat: @"(%@)",
catName];
catDict = [unitDict objectForKey: catName];
[m addEntriesFromDictionary: catDict];
}
dict = AUTORELEASE(m);
} }
} }
} }
} }
}
a = [a sortedArrayUsingSelector: @selector(compare:)];
[buf appendString: indent]; [buf appendString: indent];
[buf appendFormat: @"<b>%@</b>\n", title]; [buf appendFormat: @"<b>%@</b>\n", title];
@ -330,75 +406,25 @@ static NSMutableSet *textNodes = nil;
[buf appendString: @"<ul>\n"]; [buf appendString: @"<ul>\n"];
[self incIndent]; [self incIndent];
a = [dict allKeys];
a = [a sortedArrayUsingSelector: @selector(compare:)];
c = [a count];
for (i = 0; i < c; i++) for (i = 0; i < c; i++)
{
if (isInUnit == YES)
{
NSString *ref = [a objectAtIndex: i];
NSDictionary *units = [dict objectForKey: ref];
NSMutableArray *b = [[units allKeys] mutableCopy];
unsigned j;
if (unitNames != nil)
{
/*
* Remove any listing for methods not in the
* current unit or in categories of the current class.
*/
for (j = 0; j < [b count]; j++)
{
NSString *u = [b objectAtIndex: j];
if ([unitNames member: u] == NO)
{
[b removeObjectAtIndex: j--];
}
}
}
[b sortUsingSelector: @selector(compare:)];
for (j = 0; j < [b count]; j++)
{
NSString *u = [b objectAtIndex: j];
NSString *file = [units objectForKey: u];
[buf appendString: indent];
[buf appendFormat: @"<li><a rel=\"gsdoc\" href="];
[buf appendFormat: @"\"%@.html#%@$%@%@%@\">",
file, type, u, sep, ref];
if ([u isEqual: unit] == YES)
{
[buf appendFormat: @"%@</a></li>\n", ref];
}
else
{
[buf appendFormat: @"%@</a> in %@</li>\n", ref, u];
}
}
RELEASE(b);
}
else
{ {
NSString *ref = [a objectAtIndex: i]; NSString *ref = [a objectAtIndex: i];
NSString *file = [dict objectForKey: ref]; NSString *file = [dict objectForKey: ref];
NSString *text = ref; NSString *text = ref;
/*
* Special case ... title listings are done
* with the name of the file being the unique key
* and the value being the title string.
*/
if ([type isEqual: @"title"] == YES)
{
text = file;
file = ref;
if ([file isEqual: base] == YES)
{
continue; // Don't list current file.
}
}
[buf appendString: indent]; [buf appendString: indent];
[buf appendString: @"<li><a rel=\"gsdoc\" href="]; [buf appendString: @"<li><a rel=\"gsdoc\" href="];
if (isInUnit == YES)
{
[buf appendFormat: @"\"%@.html#%@$%@%@%@\">%@</a></li>\n",
file, type, u, sep, ref, text];
}
else
{
[buf appendFormat: @"\"%@.html#%@$%@\">%@</a></li>\n", [buf appendFormat: @"\"%@.html#%@$%@\">%@</a></li>\n",
file, type, ref, text]; file, type, ref, text];
} }
@ -466,20 +492,22 @@ static NSMutableSet *textNodes = nil;
} }
else if ([name isEqual: @"category"] == YES) else if ([name isEqual: @"category"] == YES)
{ {
NSString *name = [prop objectForKey: @"name"];
NSString *cls = [prop objectForKey: @"class"];
NSString *s; NSString *s;
category = [prop objectForKey: @"name"];
classname = [prop objectForKey: @"class"];
unit = [NSString stringWithFormat: @"%@(%@)", classname, category];
[buf appendString: indent]; [buf appendString: indent];
[buf appendString: @"<h2>"]; [buf appendString: @"<h2>"];
[buf appendString: [self typeRef: cls]]; [buf appendString: [self typeRef: classname]];
[buf appendString: @"("]; [buf appendString: @"("];
unit = [NSString stringWithFormat: @"%@(%@)", cls, name]; s = [self makeAnchor: unit ofType: @"category" name: category];
s = [self makeAnchor: unit ofType: @"category" name: name];
[buf appendString: s]; [buf appendString: s];
[buf appendString: @")</h2>\n"]; [buf appendString: @")</h2>\n"];
[self outputUnit: node to: buf]; [self outputUnit: node to: buf];
unit = nil; unit = nil;
classname = nil;
category = nil;
} }
else if ([name isEqual: @"chapter"] == YES) else if ([name isEqual: @"chapter"] == YES)
{ {
@ -492,14 +520,14 @@ static NSMutableSet *textNodes = nil;
} }
else if ([name isEqual: @"class"] == YES) else if ([name isEqual: @"class"] == YES)
{ {
NSString *name = [prop objectForKey: @"name"];
NSString *sup = [prop objectForKey: @"super"]; NSString *sup = [prop objectForKey: @"super"];
unit = name; classname = [prop objectForKey: @"name"];
unit = classname;
[buf appendString: indent]; [buf appendString: indent];
[buf appendString: @"<h2>"]; [buf appendString: @"<h2>"];
[buf appendString: [buf appendString:
[self makeAnchor: name ofType: @"class" name: name]]; [self makeAnchor: classname ofType: @"class" name: classname]];
sup = [self typeRef: sup]; sup = [self typeRef: sup];
if (sup != nil) if (sup != nil)
{ {
@ -509,6 +537,7 @@ static NSMutableSet *textNodes = nil;
[buf appendString: @"</h2>\n"]; [buf appendString: @"</h2>\n"];
[self outputUnit: node to: buf]; [self outputUnit: node to: buf];
unit = nil; unit = nil;
classname = nil;
} }
else if ([name isEqual: @"code"] == YES) else if ([name isEqual: @"code"] == YES)
{ {
@ -919,9 +948,50 @@ static NSMutableSet *textNodes = nil;
} }
else if ([name isEqual: @"ivariable"] == YES) else if ([name isEqual: @"ivariable"] == YES)
{ {
NSString *tmp = [prop objectForKey: @"name"]; NSString *n = [prop objectForKey: @"name"];
NSString *t = [prop objectForKey: @"type"];
NSString *v = [prop objectForKey: @"validity"];
NSString *s;
GSXMLNode *tmp = children;
NSLog(@"Element '%@' not implemented", name); // FIXME [buf appendString: indent];
[buf appendString: @"<h3>"];
s = [self makeLink: n ofType: @"ivariable" inUnit: nil isRef: NO];
if (s != nil)
{
[buf appendString: s];
[buf appendString: n];
[buf appendString: @"</a>"];
}
else
{
[buf appendString: n];
}
[buf appendString: @"</h3>\n"];
if (v == nil)
{
v = @"public";
}
[buf appendFormat: @"%@@%@ %@ <b>%@</b>;<br />\n", indent, v, t, n];
if ([[children name] isEqual: @"desc"] == YES)
{
children = [children next];
}
/*
* List standards with which method complies
*/
if ([[children name] isEqual: @"standards"])
{
[self outputNode: children to: buf];
}
if ([[tmp name] isEqual: @"desc"])
{
[self outputNode: tmp to: buf];
}
[buf appendString: indent];
[buf appendString: @"<hr width=\"25%\" align=\"left\" />\n"];
} }
else if ([name isEqual: @"label"] == YES) // %anchor else if ([name isEqual: @"label"] == YES) // %anchor
{ {
@ -1532,7 +1602,7 @@ NSLog(@"Element '%@' not implemented", name); // FIXME
- (void) outputUnit: (GSXMLNode*)node to: (NSMutableString*)buf - (void) outputUnit: (GSXMLNode*)node to: (NSMutableString*)buf
{ {
GSXMLNode *t; GSXMLNode *t;
NSMutableArray *a; NSArray *a;
node = [node children]; node = [node children];
if (node != nil && [[node name] isEqual: @"declared"] == YES) if (node != nil && [[node name] isEqual: @"declared"] == YES)
@ -1607,6 +1677,19 @@ NSLog(@"Element '%@' not implemented", name); // FIXME
node = [node next]; node = [node next];
} }
if (node != nil && [[node name] isEqual: @"ivariable"] == YES)
{
[buf appendString: indent];
[buf appendString: @"<hr width=\"50%\" align=\"left\" />\n"];
[buf appendString: indent];
[buf appendString: @"<h3>Instance variables</h3>\n"];
while (node != nil && [[node name] isEqual: @"ivariable"] == YES)
{
[self outputNode: node to: buf];
node = [node next];
}
}
a = [localRefs methodsInUnit: unit]; a = [localRefs methodsInUnit: unit];
if ([a count] > 0) if ([a count] > 0)
{ {
@ -1614,14 +1697,15 @@ NSLog(@"Element '%@' not implemented", name); // FIXME
scope: @"global" scope: @"global"
title: @"Method summary" title: @"Method summary"
to: buf]; to: buf];
[buf appendString: indent];
[buf appendString: @"<hr width=\"50%\" align=\"left\" />\n"]; [buf appendString: @"<hr width=\"50%\" align=\"left\" />\n"];
}
while (node != nil && [[node name] isEqual: @"method"] == YES) while (node != nil && [[node name] isEqual: @"method"] == YES)
{ {
[self outputNode: node to: buf]; [self outputNode: node to: buf];
node = [node next]; node = [node next];
} }
} }
}
/** /**
* Try to make a link to the documentation for the supplied protocol. * Try to make a link to the documentation for the supplied protocol.

View file

@ -29,6 +29,8 @@
NSMutableDictionary *refs; NSMutableDictionary *refs;
NSString *base; // Not retained NSString *base; // Not retained
NSString *unit; // Not retained NSString *unit; // Not retained
NSString *classname; // Not retained
NSString *category; // Not retained
unsigned chap; unsigned chap;
unsigned sect; unsigned sect;
unsigned ssect; unsigned ssect;
@ -37,10 +39,11 @@
- (NSString*) globalRef: (NSString*)ref type: (NSString*)type; - (NSString*) globalRef: (NSString*)ref type: (NSString*)type;
- (void) makeRefs: (GSXMLNode*)node; - (void) makeRefs: (GSXMLNode*)node;
- (void) mergeRefs: (NSDictionary*)more override: (BOOL)flag; - (void) mergeRefs: (NSDictionary*)more override: (BOOL)flag;
- (NSMutableArray*) methodsInUnit: (NSString*)aUnit; - (NSArray*) methodsInUnit: (NSString*)aUnit;
- (NSMutableDictionary*) refs; - (NSMutableDictionary*) refs;
- (void) setDirectory: (NSString*)path; - (void) setDirectory: (NSString*)path;
- (void) setGlobalRef: (NSString*)ref type: (NSString*)type; - (void) setGlobalRef: (NSString*)ref type: (NSString*)type;
- (void) setRelationship: (NSString*)r from: (NSString*)from to: (NSString*)to;
- (void) setUnitRef: (NSString*)ref type: (NSString*)type; - (void) setUnitRef: (NSString*)ref type: (NSString*)type;
- (NSDictionary*) unitRef: (NSString*)ref type: (NSString*)type; - (NSDictionary*) unitRef: (NSString*)ref type: (NSString*)type;
- (NSString*) unitRef: (NSString*)ref type: (NSString*)type unit: (NSString**)u; - (NSString*) unitRef: (NSString*)ref type: (NSString*)type unit: (NSString**)u;

View file

@ -133,7 +133,6 @@ setDirectory(NSMutableDictionary *dict, NSString *path)
* The references are held in a tree consisting of dictionaries * The references are held in a tree consisting of dictionaries
* with strings at the leaves -<br /> * with strings at the leaves -<br />
* method method-name class-name file-name<br /> * method method-name class-name file-name<br />
* method method-name category-name file-name<br />
* method method-name protocol-name file-name<br /> * method method-name protocol-name file-name<br />
* ivariable variable-name class-name file-name<br /> * ivariable variable-name class-name file-name<br />
* class class-name file-name<br /> * class class-name file-name<br />
@ -147,6 +146,9 @@ setDirectory(NSMutableDictionary *dict, NSString *path)
* label label-name file-name ref<br /> * label label-name file-name ref<br />
* contents ref text<br /> * contents ref text<br />
* super class-name superclass-name<br /> * super class-name superclass-name<br />
* categories class-name category-name file-name<br />
* unitmethods unit-name method-name<br />
* classvars class-name variables-name<br />
* title file-name text<br /> * title file-name text<br />
*/ */
@implementation AGSIndex @implementation AGSIndex
@ -202,9 +204,14 @@ setDirectory(NSMutableDictionary *dict, NSString *path)
if ([name isEqual: @"category"] == YES) if ([name isEqual: @"category"] == YES)
{ {
newUnit = YES; newUnit = YES;
unit = [NSString stringWithFormat: @"%@(%@)", classname = [prop objectForKey: @"class"];
[prop objectForKey: @"class"], [prop objectForKey: @"name"]]; category = [prop objectForKey: @"name"];
unit = classname;
/*
* Add this category to the list of those for the class.
*/
[self setUnitRef: category type: @"categories"];
unit = [NSString stringWithFormat: @"%@(%@)", classname, category];
[self setGlobalRef: unit type: @"category"]; [self setGlobalRef: unit type: @"category"];
} }
else if ([name isEqual: @"chapter"] == YES) else if ([name isEqual: @"chapter"] == YES)
@ -219,20 +226,12 @@ setDirectory(NSMutableDictionary *dict, NSString *path)
NSString *tmp; NSString *tmp;
newUnit = YES; newUnit = YES;
unit = [prop objectForKey: @"name"]; classname = [prop objectForKey: @"name"];
unit = classname;
tmp = [prop objectForKey: @"super"]; tmp = [prop objectForKey: @"super"];
if (tmp != nil) if (tmp != nil)
{ {
NSMutableDictionary *t; [self setRelationship: @"super" from: unit to: tmp];
t = [refs objectForKey: @"super"];
if (t == nil)
{
t = [NSMutableDictionary new];
[refs setObject: t forKey: @"super"];
RELEASE(t);
}
[t setObject: tmp forKey: unit];
} }
[self setGlobalRef: unit type: @"class"]; [self setGlobalRef: unit type: @"class"];
} }
@ -267,7 +266,8 @@ setDirectory(NSMutableDictionary *dict, NSString *path)
{ {
NSString *tmp = [prop objectForKey: @"name"]; NSString *tmp = [prop objectForKey: @"name"];
[self setUnitRef: tmp type: name]; [self setUnitRef: tmp type: @"ivariable"];
[self setUnitRef: tmp type: @"classvars"];
} }
else if ([name isEqual: @"entry"] || [name isEqual: @"label"]) else if ([name isEqual: @"entry"] || [name isEqual: @"label"])
{ {
@ -348,7 +348,8 @@ setDirectory(NSMutableDictionary *dict, NSString *path)
} }
if ([sel length] > 1) if ([sel length] > 1)
{ {
[self setUnitRef: sel type: name]; [self setUnitRef: sel type: @"method"];
[self setUnitRef: sel type: @"unitmethods"];
} }
} }
else if ([name isEqual: @"protocol"] == YES) else if ([name isEqual: @"protocol"] == YES)
@ -413,6 +414,8 @@ setDirectory(NSMutableDictionary *dict, NSString *path)
if (newUnit == YES) if (newUnit == YES)
{ {
unit = nil; unit = nil;
category = nil;
classname = nil;
} }
if (next != nil) if (next != nil)
{ {
@ -430,23 +433,12 @@ setDirectory(NSMutableDictionary *dict, NSString *path)
mergeDictionaries(refs, more, flag); mergeDictionaries(refs, more, flag);
} }
- (NSMutableArray*) methodsInUnit: (NSString*)aUnit - (NSArray*) methodsInUnit: (NSString*)aUnit
{ {
NSDictionary *d = [refs objectForKey: @"method"]; NSDictionary *d = [refs objectForKey: @"unitmethods"];
NSEnumerator *e = [d keyEnumerator];
NSMutableArray *a = [NSMutableArray array];
NSString *k;
while ((k = [e nextObject]) != nil) d = [d objectForKey: aUnit];
{ return [d allKeys];
NSDictionary *m = [d objectForKey: k];
if ([m objectForKey: aUnit] != nil)
{
[a addObject: k];
}
}
return a;
} }
- (NSMutableDictionary*) refs - (NSMutableDictionary*) refs
@ -486,13 +478,50 @@ setDirectory(NSMutableDictionary *dict, NSString *path)
[t setObject: base forKey: ref]; [t setObject: base forKey: ref];
} }
- (void) setRelationship: (NSString*)r from: (NSString*)from to: (NSString*)to
{
NSMutableDictionary *dict;
dict = [refs objectForKey: r];
if (dict == nil)
{
dict = [NSMutableDictionary new];
[refs setObject: dict forKey: r];
RELEASE(dict);
}
[dict setObject: to forKey: from];
}
/**
* Set up a reference for something inside a unit (class, category or protocol)
* We store 'method' and 'ivariable' by ref then unit (class),
* but we store 'unitmethods' * and 'classvars' by unit then ref.
*/
- (void) setUnitRef: (NSString*)ref - (void) setUnitRef: (NSString*)ref
type: (NSString*)type type: (NSString*)type
{ {
NSMutableDictionary *t; NSMutableDictionary *t;
NSMutableDictionary *r; NSMutableDictionary *r;
NSString *u = unit;
NSString *old; NSString *old;
if ([type isEqualToString: @"method"] || [type isEqualToString: @"ivariable"])
{
if (category != nil)
{
u = classname; // Store category methods by classname.
}
// type ... ref ... unit ... file
}
else
{
NSString *tmp = ref;
ref = u;
u = tmp;
// type ... unit ... ref ... file
}
t = [refs objectForKey: type]; t = [refs objectForKey: type];
if (t == nil) if (t == nil)
{ {
@ -507,13 +536,13 @@ setDirectory(NSMutableDictionary *dict, NSString *path)
[t setObject: r forKey: ref]; [t setObject: r forKey: ref];
RELEASE(r); RELEASE(r);
} }
old = [r objectForKey: unit]; old = [r objectForKey: u];
if (old != nil && [old isEqual: base] == NO) if (old != nil && [old isEqual: base] == NO)
{ {
NSLog(@"Warning ... %@ %@ %@ appears in %@ and %@ ... using the latter", NSLog(@"Warning ... %@ %@ %@ appears in %@ and %@ ... using the latter",
type, ref, unit, old, base); type, ref, u, old, base);
} }
[r setObject: base forKey: unit]; [r setObject: base forKey: u];
} }
/** /**

View file

@ -41,6 +41,7 @@
output: (NSMutableString*)buf; output: (NSMutableString*)buf;
- (NSString*) output: (NSDictionary*)d; - (NSString*) output: (NSDictionary*)d;
- (BOOL) output: (NSDictionary*)d file: (NSString*)name; - (BOOL) output: (NSDictionary*)d file: (NSString*)name;
- (void) outputInstanceVariable: (NSDictionary*)d to: (NSMutableString*)str;
- (void) outputMethod: (NSDictionary*)d to: (NSMutableString*)str; - (void) outputMethod: (NSDictionary*)d to: (NSMutableString*)str;
- (void) outputUnit: (NSDictionary*)d to: (NSMutableString*)str; - (void) outputUnit: (NSDictionary*)d to: (NSMutableString*)str;
- (unsigned) reformat: (NSString*)str - (unsigned) reformat: (NSString*)str

View file

@ -409,6 +409,42 @@ static BOOL snuggleStart(NSString *t)
return [str writeToFile: name atomically: YES]; return [str writeToFile: name atomically: YES];
} }
/**
* Output the gsdoc code for an instance variable.
*/
- (void) outputInstanceVariable: (NSDictionary*)d to: (NSMutableString*)str
{
NSString *type = [d objectForKey: @"Type"];
NSString *validity = [d objectForKey: @"Validity"];
NSString *name = [d objectForKey: @"Name"];
NSString *comment = [d objectForKey: @"Comment"];
NSString *standards = [d objectForKey: @"Standards"];
[str appendString: @" <ivariable type=\""];
[str appendString: escapeType(type)];
[str appendString: @"\" name=\""];
[str appendString: name];
if (validity != nil)
{
[str appendString: @"\" validity=\""];
[str appendString: validity];
}
[str appendString: @"\">\n"];
[str appendString: @" <desc>\n"];
if ([comment length] == 0)
{
comment = @"<em>Description forthcoming.</em>";
}
[self reformat: comment withIndent: 12 to: str];
[str appendString: @" </desc>\n"];
if (standards != nil)
{
[self reformat: standards withIndent: 10 to: str];
}
[str appendString: @" </ivariable>\n"];
}
/** /**
* Uses -split: and -reformat:withIndent:to:. * Uses -split: and -reformat:withIndent:to:.
* Also has fun with YES, NO, and nil. * Also has fun with YES, NO, and nil.
@ -583,6 +619,7 @@ static BOOL snuggleStart(NSString *t)
NSString *name = [d objectForKey: @"Name"]; NSString *name = [d objectForKey: @"Name"];
NSString *type = [d objectForKey: @"Type"]; NSString *type = [d objectForKey: @"Type"];
NSDictionary *methods = [d objectForKey: @"Methods"]; NSDictionary *methods = [d objectForKey: @"Methods"];
NSDictionary *ivars = [d objectForKey: @"InstanceVariables"];
NSString *comment = [d objectForKey: @"Comment"]; NSString *comment = [d objectForKey: @"Comment"];
NSArray *names; NSArray *names;
NSArray *protocols; NSArray *protocols;
@ -757,6 +794,14 @@ static BOOL snuggleStart(NSString *t)
for (j = 0; j < ind; j++) [str appendString: @" "]; for (j = 0; j < ind; j++) [str appendString: @" "];
[str appendString: @"</desc>\n"]; [str appendString: @"</desc>\n"];
names = [[ivars allKeys] sortedArrayUsingSelector: @selector(compare:)];
for (i = 0; i < [names count]; i++)
{
NSString *vName = [names objectAtIndex: i];
[self outputInstanceVariable: [ivars objectForKey: vName] to: str];
}
names = [[methods allKeys] sortedArrayUsingSelector: @selector(compare:)]; names = [[methods allKeys] sortedArrayUsingSelector: @selector(compare:)];
for (i = 0; i < [names count]; i++) for (i = 0; i < [names count]; i++)
{ {

View file

@ -43,10 +43,10 @@
/* /*
* The following items are used for logging/debug purposes. * The following items are used for logging/debug purposes.
*/ */
NSString *fileName; // Not retained - file being parsed. NSString *fileName; /** Not retained - file being parsed. */
NSString *unitName; // Not retained - unit being parsed. NSString *unitName; /** Not retained - unit being parsed. */
NSString *itemName; // Not retained - item being parsed. NSString *itemName; /** Not retained - item being parsed. */
NSArray *lines; // Not retained - line number mapping. NSArray *lines; /** Not retained - line number mapping. */
/* /*
* The next few ivars represent the data currently being parsed. * The next few ivars represent the data currently being parsed.
@ -56,20 +56,23 @@
unsigned pos; unsigned pos;
BOOL commentsRead; BOOL commentsRead;
BOOL haveSource; BOOL haveSource;
NSString *declared; // Where classes were declared. BOOL inInstanceVariables;
NSMutableArray *ifStack; // track preprocessor conditionals. BOOL documentAllInstanceVariables;
NSString *declared; /** Where classes were declared. */
NSMutableArray *ifStack; /** Track preprocessor conditionals. */
NSString *comment; // Documentation accumulator. NSString *comment; /** Documentation accumulator. */
NSMutableDictionary *info; // All information parsed. NSMutableDictionary *info; /** All information parsed. */
NSMutableArray *source; // Names of source files. NSMutableArray *source; /** Names of source files. */
NSCharacterSet *identifier; // Legit char in identifier NSCharacterSet *identifier; /** Legit char in identifier */
NSCharacterSet *identStart; // Legit initial char of identifier NSCharacterSet *identStart; /** Legit initial char of identifier */
NSCharacterSet *spaces; // All blank characters NSCharacterSet *spaces; /** All blank characters */
NSCharacterSet *spacenl; // Blanks excluding newline NSCharacterSet *spacenl; /** Blanks excluding newline */
} }
- (NSMutableDictionary*) info; - (NSMutableDictionary*) info;
- (id) init; /** <init> Simple initialiser */ - (id) init; /** <init> Simple initialiser */
- (NSMutableDictionary*) parseDeclIsSource: (BOOL)isSource;
- (NSMutableDictionary*) parseFile: (NSString*)name isSource: (BOOL)isSource; - (NSMutableDictionary*) parseFile: (NSString*)name isSource: (BOOL)isSource;
- (NSString*) parseIdentifier; - (NSString*) parseIdentifier;
- (NSMutableDictionary*) parseImplementation; - (NSMutableDictionary*) parseImplementation;
@ -82,6 +85,7 @@
- (NSMutableArray*) parseProtocolList; - (NSMutableArray*) parseProtocolList;
- (void) reset; - (void) reset;
- (void) setDeclared: (NSString*)name; - (void) setDeclared: (NSString*)name;
- (void) setDocumentAllInstanceVariables: (BOOL)flag;
- (void) setGenerateStandards: (BOOL)flag; - (void) setGenerateStandards: (BOOL)flag;
- (void) setStandards: (NSMutableDictionary*)dict; - (void) setStandards: (NSMutableDictionary*)dict;
- (void) setupBuffer; - (void) setupBuffer;

View file

@ -122,6 +122,263 @@
va_end (ap); va_end (ap);
} }
- (NSString*) parseDeclaratorInto: (NSMutableArray*)a
{
while ([self skipWhiteSpace] < length)
{
while (buffer[pos] == '*')
{
[a addObject: @"*"];
pos++;
}
if (buffer[pos] == '(')
{
NSString *result;
[a addObject: @"("];
pos++;
result = [self parseDeclaratorInto: a];
if ([self skipWhiteSpace] < length && buffer[pos] == ')')
{
[a addObject: @")"];
pos++;
return result;
}
else
{
[self log: @"missing ')' in declarator."];
return nil;
}
}
else
{
NSString *s;
s = [self parseIdentifier];
if ([s isEqualToString: @"const"] || [s isEqualToString: @"volatile"])
{
[a addObject: s];
}
else
{
return s; // Parsed all asterisks, consts, and volatiles
}
}
}
return nil;
}
- (NSMutableDictionary*) parseDeclIsSource: (BOOL)isSource
{
CREATE_AUTORELEASE_POOL(arp);
static NSSet *qualifiers = nil;
NSString *baseType = nil;
NSString *declName = nil;
NSMutableArray *a1;
NSMutableArray *a2;
NSString *s;
BOOL isTypedef = NO;
if (qualifiers == nil)
{
qualifiers = [NSSet setWithObjects:
@"auto",
@"const",
@"extern",
@"inline",
@"long",
@"register",
@"short",
@"signed",
@"static",
@"typedef",
@"unsigned",
@"volatile",
nil];
RETAIN(qualifiers);
}
a1 = [NSMutableArray array];
a2 = [NSMutableArray array];
while ((s = [self parseIdentifier]) != nil)
{
if ([s isEqualToString: @"GS_EXTERN"] == YES)
{
s = @"extern";
}
if ([qualifiers member: s] == nil)
{
break;
}
else
{
if ([s isEqualToString: @"typedef"] == YES)
{
isTypedef = YES;
}
[a1 addObject: s];
}
}
baseType = s;
if (baseType == nil)
{
/*
* If there is no identifier here, the line must have been
* something like 'unsigned *length' so we must set the default
* base type of 'int'
*/
baseType = @"int";
}
/**
* We handle struct, union, and enum declarations by skipping the
* stuff enclosed in curly braces. If there was an identifier
* after the keyword we use it as the struct name, otherwise we
* use '...' to denote a nameless type.
*/
if ([s isEqualToString: @"struct"] == YES
|| [s isEqualToString: @"union"] == YES
|| [s isEqualToString: @"enum"] == YES)
{
s = [self parseIdentifier];
if (s == nil)
{
baseType = [NSString stringWithFormat: @"%@ ...", baseType];
}
else
{
baseType = [NSString stringWithFormat: @"%@ %@", baseType, s];
}
if ([self skipWhiteSpace] < length && buffer[pos] == '{')
{
[self skipBlock];
}
}
/*
* FIXME ... the next code should cope with bracketing and with
* pointers to functions etc. It doesn't!
*/
while ([self skipWhiteSpace] < length)
{
while (buffer[pos] == '*')
{
[a2 addObject: @"*"];
pos++;
}
if (buffer[pos] == '(')
{
}
s = [self parseIdentifier];
if ([s isEqualToString: @"const"] || [s isEqualToString: @"volatile"])
{
[a2 addObject: s];
}
else
{
break; // Parsed all asterisks, consts, and volatiles
}
}
declName = s;
if (declName == nil)
{
/*
* If there is no identifier here, the line must have been
* something like 'unsigned length' and we assumed that 'length'
* was the base type rather than the declared name.
* The fix is to set the base type to be 'int' and use the value
* we had as the declaration name.
*/
declName = baseType;
baseType = @"int";
}
[a1 addObject: baseType];
[a1 addObjectsFromArray: a2];
if ([self skipWhiteSpace] < length)
{
if (buffer[pos] == ';')
{
[self skipStatement];
}
else if (buffer[pos] == '[')
{
[self log: @"ignoring array variable ... not supported yet"];
[self skipStatement];
}
else if (buffer[pos] == '(')
{
[self log: @"parse function '%@' of type '%@'",
declName, [a1 componentsJoinedByString: @" "]];
[self skipStatement];
RELEASE(arp);
return nil;
}
else if (buffer[pos] == ',')
{
[self log: @"ignoring multiple comma separated declarations"];
[self skipStatement];
}
else if (buffer[pos] == '=')
{
[self skipStatement];
}
else
{
[self log: @"unexpected char (%c) parsing declaration", buffer[pos]];
goto fail;
}
/*
* Read in any comment on the same line in case it
* contains documentation for the declaration.
*/
if ([self skipSpaces] < length && buffer[pos] == '/')
{
[self skipComment];
}
if (inInstanceVariables == YES)
{
NSMutableDictionary *d;
NSString *t;
t = [a1 componentsJoinedByString: @" "];
d = [[NSMutableDictionary alloc] initWithCapacity: 4];
[d setObject: declName forKey: @"Name"];
[d setObject: t forKey: @"Type"];
if (comment != nil)
{
[d setObject: comment forKey: @"Comment"];
DESTROY(comment);
}
RELEASE(arp);
return AUTORELEASE(d);
}
else if (isTypedef == YES)
{
[self log: @"parse typedef '%@' of type '%@'",
declName, [a1 componentsJoinedByString: @" "]];
}
else
{
[self log: @"parse variable/constant '%@' of type '%@'",
declName, [a1 componentsJoinedByString: @" "]];
}
}
else
{
[self log: @"unexpected end of data parsing declaration"];
}
fail:
DESTROY(comment);
RELEASE(arp);
return nil;
}
- (NSMutableDictionary*) parseFile: (NSString*)name isSource: (BOOL)isSource - (NSMutableDictionary*) parseFile: (NSString*)name isSource: (BOOL)isSource
{ {
NSString *token; NSString *token;
@ -481,59 +738,6 @@ fail:
return nil; return nil;
} }
/*
- (NSString*) parseType
{
NSMutableString *m;
NSString *s;
BOOL hadName = NO;
s = [self parseIdentifier];
if (s == nil)
{
return nil;
}
m = [NSMutableString string];
[m appendString: s];
if ([qualifiers member: s] == nil)
{
hadName = YES;
}
[self skipWhiteSpace];
while (pos < length)
{
unsigned saved;
BOOL hadStar = NO;
while (pos < length && buffer[pos] == '*')
{
if (hadStar == NO)
{
[m appendString: @" "];
hadStar = YES;
}
[m appendString: @"*"];
pos++;
[self skipWhiteSpace];
}
saved = pos;
s = [self parseIdentifier];
if ([qualifiers member: s] == nil)
{
if (hadName == YES)
{
pos = saved;
break;
}
hadName = YES;
}
[m appendString: @" "];
[m appendString: s];
}
return m;
}
*/
- (NSString*) parseIdentifier - (NSString*) parseIdentifier
{ {
unsigned start; unsigned start;
@ -558,11 +762,14 @@ fail:
- (NSMutableDictionary*) parseInstanceVariables - (NSMutableDictionary*) parseInstanceVariables
{ {
enum { IsPrivate, IsProtected, IsPublic } visibility = IsPrivate; NSString *visibility = @"private";
NSMutableDictionary *ivars; NSMutableDictionary *ivars;
BOOL shouldDocument = documentAllInstanceVariables;
DESTROY(comment); DESTROY(comment);
inInstanceVariables = YES;
ivars = [NSMutableDictionary dictionaryWithCapacity: 8]; ivars = [NSMutableDictionary dictionaryWithCapacity: 8];
pos++; pos++;
while ([self skipWhiteSpace] < length && buffer[pos] != '}') while ([self skipWhiteSpace] < length && buffer[pos] != '}')
@ -576,24 +783,27 @@ fail:
|| [self skipWhiteSpace] >= length) || [self skipWhiteSpace] >= length)
{ {
[self log: @"interface with bad visibility directive"]; [self log: @"interface with bad visibility directive"];
return nil; goto fail;
} }
if ([token isEqual: @"private"] == YES) if ([token isEqual: @"private"] == YES)
{ {
visibility = IsPrivate; ASSIGN(visibility, token);
shouldDocument = documentAllInstanceVariables;
} }
else if ([token isEqual: @"protected"] == YES) else if ([token isEqual: @"protected"] == YES)
{ {
visibility = IsProtected; ASSIGN(visibility, token);
shouldDocument = YES;
} }
else if ([token isEqual: @"public"] == YES) else if ([token isEqual: @"public"] == YES)
{ {
visibility = IsPublic; ASSIGN(visibility, token);
shouldDocument = YES;
} }
else else
{ {
[self log: @"interface with bad visibility (%@)", token]; [self log: @"interface with bad visibility (%@)", token];
return nil; goto fail;
} }
} }
else if (buffer[pos] == '#') else if (buffer[pos] == '#')
@ -601,11 +811,24 @@ fail:
[self skipPreprocessor]; // Ignore preprocessor directive. [self skipPreprocessor]; // Ignore preprocessor directive.
DESTROY(comment); DESTROY(comment);
} }
else if (shouldDocument == YES)
{
NSMutableDictionary *iv = [self parseDeclIsSource: NO];
if (iv != nil)
{
[iv setObject: visibility forKey: @"Visibility"];
[ivars setObject: iv forKey: [iv objectForKey: @"Name"]];
}
}
else else
{ {
[self skipStatement]; /* FIXME - currently we ignore ivars */ [self skipStatement];
} }
} }
inInstanceVariables = NO;
if (pos >= length) if (pos >= length)
{ {
[self log: @"interface with bad instance variables"]; [self log: @"interface with bad instance variables"];
@ -613,6 +836,10 @@ fail:
} }
pos++; // Step past closing bracket. pos++; // Step past closing bracket.
return ivars; return ivars;
fail:
DESTROY(comment);
inInstanceVariables = NO;
return nil;
} }
- (NSMutableDictionary*) parseMethodIsDeclaration: (BOOL)flag - (NSMutableDictionary*) parseMethodIsDeclaration: (BOOL)flag
@ -1274,6 +1501,17 @@ fail:
ASSIGN(declared, name); ASSIGN(declared, name);
} }
/**
* This method is used to enable (or disable) documentation of all
* instance variables. If it is turned off, only those instance
* variables that are explicitly declared 'public' or 'protected'
* will be documented.
*/
- (void) setDocumentAllInstanceVariables: (BOOL)flag
{
documentAllInstanceVariables = flag;
}
/** /**
* Turn on or off parsing of preprocessor conditional compilation info * Turn on or off parsing of preprocessor conditional compilation info
* indicating the standards complied with. When this is turned on, we * indicating the standards complied with. When this is turned on, we

View file

@ -174,11 +174,12 @@
<br />eg. [ NSObject-init], <br />eg. [ NSObject-init],
will create a reference to the init method of NSObject, while will create a reference to the init method of NSObject, while
<br />[ (NSCopying)-copyWithZone:], creates a <br />[ (NSCopying)-copyWithZone:], creates a
reference to a method in the NSCopyIng protocol, and reference to a method in the NSCopyIng protocol.
<br />[ NSObject(TimedPerformers)-performSelector:withObject:afterDelay:],
creates a reference to a method in the TimedPerformers category.
<br />Note that no spaces must appear between the square brackets <br />Note that no spaces must appear between the square brackets
in these specifiers. in these specifiers.
<br />Protocol namnes are enclosed in round brackets rather than
the customary angle brackets, because gsdoc is an XML language, and
XML treats angle brackets specially.
</item> </item>
</list> </list>
<p> <p>
@ -199,6 +200,11 @@
would result in the documentation saying that NSString is declared would result in the documentation saying that NSString is declared
in <code>Foundation/NSString.h</code> in <code>Foundation/NSString.h</code>
</item> </item>
<item><strong>DocumentAllInstanceVariables</strong>
This flag permits you to generate documentation for all instance
variables. Normally, only those explicitly declared 'public' or
'protected' will be documented.
</item>
<item><strong>DocumentationDirectory</strong> <item><strong>DocumentationDirectory</strong>
May be used to specify the directory in which generated May be used to specify the directory in which generated
documentation is to be placed. If this is not set, output documentation is to be placed. If this is not set, output
@ -480,6 +486,10 @@ main(int argc, char **argv, char **env)
{ {
[parser setGenerateStandards: YES]; [parser setGenerateStandards: YES];
} }
if ([defs boolForKey: @"DocumentAllInstanceVariables"] == YES)
{
[parser setDocumentAllInstanceVariables: YES];
}
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {

View file

@ -273,21 +273,16 @@
<!ATTLIST variable <!ATTLIST variable
name CDATA #REQUIRED name CDATA #REQUIRED
type CDATA #REQUIRED type CDATA #REQUIRED
posttype CDATA #REQUIRED
value CDATA #IMPLIED value CDATA #IMPLIED
role (except|defaults|notify|key) #IMPLIED
> >
<!-- Ivariable definition. <!-- Ivariable definition.
VALUE may be set for a constant or a default value
--> -->
<!ELEMENT ivariable (declared?, desc?, standards?)> <!ELEMENT ivariable (desc?, standards?)>
<!ATTLIST ivariable <!ATTLIST ivariable
name CDATA #REQUIRED name CDATA #REQUIRED
type CDATA #REQUIRED type CDATA #REQUIRED
posttype CDATA #REQUIRED validity (public|protected|private) "public"
value CDATA #IMPLIED
role (except|defaults|notify|key) #IMPLIED
> >
<!-- Constant definition. <!-- Constant definition.
@ -296,6 +291,7 @@
<!ELEMENT constant (declared?, desc?, standards?)> <!ELEMENT constant (declared?, desc?, standards?)>
<!ATTLIST constant <!ATTLIST constant
name CDATA #REQUIRED name CDATA #REQUIRED
type CDATA #REQUIRED
value CDATA #IMPLIED value CDATA #IMPLIED
role (except|defaults|notify|key) #IMPLIED role (except|defaults|notify|key) #IMPLIED
> >