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>
* Version: 1.1.0

View file

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

View file

@ -192,12 +192,26 @@ static NSMutableSet *textNodes = nil;
s = base;
}
else if (u == nil)
{
if (category == nil)
{
u = unit;
}
else
{
u = classname;
}
s = [localRefs unitRef: r type: t unit: &u];
if (s == nil)
{
if (category == nil)
{
u = unit;
}
else
{
u = classname;
}
s = [globalRefs unitRef: r type: t unit: &u];
}
}
@ -264,65 +278,127 @@ static NSMutableSet *textNodes = nil;
title: (NSString*)title
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)
{
dict = [globalRefs refs];
refs = [globalRefs refs];
}
else if (projectRefs != nil && [scope isEqual: @"project"] == YES)
{
dict = [projectRefs refs];
refs = [projectRefs refs];
}
dict = [dict objectForKey: type];
if ([dict count] > 1
|| ([dict count] > 0 && [type isEqual: @"title"] == NO))
if ([type isEqualToString: @"method"] == YES)
{
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 *u = unit;
BOOL isInUnit = NO;
if (unit != nil)
{
if ([type isEqual: @"method"] || [type isEqual: @"ivariable"])
{
isInUnit = YES;
if ([type isEqual: @"ivariable"])
{
sep = @"*";
sep = @"*"; // List ivars in class
}
else if (unit != nil)
else if (category != nil)
{
/*
* Create a mutable set containing the unit name.
*/
unitNames = [NSMutableSet setWithObject: unit];
/*
* if the unit is a class, add all its categories to the set.
*/
if ([unit hasSuffix: @")"] == NO)
u = classname; // List methods in category
}
else if (classname != nil)
{
NSArray *categoryNames;
unsigned l = [unit length];
NSArray *catNames;
categoryNames = [[dict objectForKey: @"category"] allKeys];
i = [categoryNames count];
while (i-- > 0)
/*
* For a clss, we want to list methods in any associated
* 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
&& [n characterAtIndex: i] == '(')
unitDict = [refs objectForKey: @"unitmethods"];
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 appendFormat: @"<b>%@</b>\n", title];
@ -330,75 +406,25 @@ static NSMutableSet *textNodes = nil;
[buf appendString: @"<ul>\n"];
[self incIndent];
a = [dict allKeys];
a = [a sortedArrayUsingSelector: @selector(compare:)];
c = [a count];
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 *file = [dict objectForKey: 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: @"<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",
file, type, ref, text];
}
@ -466,20 +492,22 @@ static NSMutableSet *textNodes = nil;
}
else if ([name isEqual: @"category"] == YES)
{
NSString *name = [prop objectForKey: @"name"];
NSString *cls = [prop objectForKey: @"class"];
NSString *s;
category = [prop objectForKey: @"name"];
classname = [prop objectForKey: @"class"];
unit = [NSString stringWithFormat: @"%@(%@)", classname, category];
[buf appendString: indent];
[buf appendString: @"<h2>"];
[buf appendString: [self typeRef: cls]];
[buf appendString: [self typeRef: classname]];
[buf appendString: @"("];
unit = [NSString stringWithFormat: @"%@(%@)", cls, name];
s = [self makeAnchor: unit ofType: @"category" name: name];
s = [self makeAnchor: unit ofType: @"category" name: category];
[buf appendString: s];
[buf appendString: @")</h2>\n"];
[self outputUnit: node to: buf];
unit = nil;
classname = nil;
category = nil;
}
else if ([name isEqual: @"chapter"] == YES)
{
@ -492,14 +520,14 @@ static NSMutableSet *textNodes = nil;
}
else if ([name isEqual: @"class"] == YES)
{
NSString *name = [prop objectForKey: @"name"];
NSString *sup = [prop objectForKey: @"super"];
unit = name;
classname = [prop objectForKey: @"name"];
unit = classname;
[buf appendString: indent];
[buf appendString: @"<h2>"];
[buf appendString:
[self makeAnchor: name ofType: @"class" name: name]];
[self makeAnchor: classname ofType: @"class" name: classname]];
sup = [self typeRef: sup];
if (sup != nil)
{
@ -509,6 +537,7 @@ static NSMutableSet *textNodes = nil;
[buf appendString: @"</h2>\n"];
[self outputUnit: node to: buf];
unit = nil;
classname = nil;
}
else if ([name isEqual: @"code"] == YES)
{
@ -919,9 +948,50 @@ static NSMutableSet *textNodes = nil;
}
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
{
@ -1532,7 +1602,7 @@ NSLog(@"Element '%@' not implemented", name); // FIXME
- (void) outputUnit: (GSXMLNode*)node to: (NSMutableString*)buf
{
GSXMLNode *t;
NSMutableArray *a;
NSArray *a;
node = [node children];
if (node != nil && [[node name] isEqual: @"declared"] == YES)
@ -1607,6 +1677,19 @@ NSLog(@"Element '%@' not implemented", name); // FIXME
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];
if ([a count] > 0)
{
@ -1614,13 +1697,14 @@ NSLog(@"Element '%@' not implemented", name); // FIXME
scope: @"global"
title: @"Method summary"
to: buf];
[buf appendString: indent];
[buf appendString: @"<hr width=\"50%\" align=\"left\" />\n"];
}
while (node != nil && [[node name] isEqual: @"method"] == YES)
{
[self outputNode: node to: buf];
node = [node next];
}
}
}
/**

View file

@ -29,6 +29,8 @@
NSMutableDictionary *refs;
NSString *base; // Not retained
NSString *unit; // Not retained
NSString *classname; // Not retained
NSString *category; // Not retained
unsigned chap;
unsigned sect;
unsigned ssect;
@ -37,10 +39,11 @@
- (NSString*) globalRef: (NSString*)ref type: (NSString*)type;
- (void) makeRefs: (GSXMLNode*)node;
- (void) mergeRefs: (NSDictionary*)more override: (BOOL)flag;
- (NSMutableArray*) methodsInUnit: (NSString*)aUnit;
- (NSArray*) methodsInUnit: (NSString*)aUnit;
- (NSMutableDictionary*) refs;
- (void) setDirectory: (NSString*)path;
- (void) setGlobalRef: (NSString*)ref type: (NSString*)type;
- (void) setRelationship: (NSString*)r from: (NSString*)from to: (NSString*)to;
- (void) setUnitRef: (NSString*)ref type: (NSString*)type;
- (NSDictionary*) unitRef: (NSString*)ref type: (NSString*)type;
- (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
* with strings at the leaves -<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 />
* ivariable variable-name 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 />
* contents ref text<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 />
*/
@implementation AGSIndex
@ -202,9 +204,14 @@ setDirectory(NSMutableDictionary *dict, NSString *path)
if ([name isEqual: @"category"] == YES)
{
newUnit = YES;
unit = [NSString stringWithFormat: @"%@(%@)",
[prop objectForKey: @"class"], [prop objectForKey: @"name"]];
classname = [prop objectForKey: @"class"];
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"];
}
else if ([name isEqual: @"chapter"] == YES)
@ -219,20 +226,12 @@ setDirectory(NSMutableDictionary *dict, NSString *path)
NSString *tmp;
newUnit = YES;
unit = [prop objectForKey: @"name"];
classname = [prop objectForKey: @"name"];
unit = classname;
tmp = [prop objectForKey: @"super"];
if (tmp != nil)
{
NSMutableDictionary *t;
t = [refs objectForKey: @"super"];
if (t == nil)
{
t = [NSMutableDictionary new];
[refs setObject: t forKey: @"super"];
RELEASE(t);
}
[t setObject: tmp forKey: unit];
[self setRelationship: @"super" from: unit to: tmp];
}
[self setGlobalRef: unit type: @"class"];
}
@ -267,7 +266,8 @@ setDirectory(NSMutableDictionary *dict, NSString *path)
{
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"])
{
@ -348,7 +348,8 @@ setDirectory(NSMutableDictionary *dict, NSString *path)
}
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)
@ -413,6 +414,8 @@ setDirectory(NSMutableDictionary *dict, NSString *path)
if (newUnit == YES)
{
unit = nil;
category = nil;
classname = nil;
}
if (next != nil)
{
@ -430,23 +433,12 @@ setDirectory(NSMutableDictionary *dict, NSString *path)
mergeDictionaries(refs, more, flag);
}
- (NSMutableArray*) methodsInUnit: (NSString*)aUnit
- (NSArray*) methodsInUnit: (NSString*)aUnit
{
NSDictionary *d = [refs objectForKey: @"method"];
NSEnumerator *e = [d keyEnumerator];
NSMutableArray *a = [NSMutableArray array];
NSString *k;
NSDictionary *d = [refs objectForKey: @"unitmethods"];
while ((k = [e nextObject]) != nil)
{
NSDictionary *m = [d objectForKey: k];
if ([m objectForKey: aUnit] != nil)
{
[a addObject: k];
}
}
return a;
d = [d objectForKey: aUnit];
return [d allKeys];
}
- (NSMutableDictionary*) refs
@ -486,13 +478,50 @@ setDirectory(NSMutableDictionary *dict, NSString *path)
[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
type: (NSString*)type
{
NSMutableDictionary *t;
NSMutableDictionary *r;
NSString *u = unit;
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];
if (t == nil)
{
@ -507,13 +536,13 @@ setDirectory(NSMutableDictionary *dict, NSString *path)
[t setObject: r forKey: ref];
RELEASE(r);
}
old = [r objectForKey: unit];
old = [r objectForKey: u];
if (old != nil && [old isEqual: base] == NO)
{
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;
- (NSString*) output: (NSDictionary*)d;
- (BOOL) output: (NSDictionary*)d file: (NSString*)name;
- (void) outputInstanceVariable: (NSDictionary*)d to: (NSMutableString*)str;
- (void) outputMethod: (NSDictionary*)d to: (NSMutableString*)str;
- (void) outputUnit: (NSDictionary*)d to: (NSMutableString*)str;
- (unsigned) reformat: (NSString*)str

View file

@ -409,6 +409,42 @@ static BOOL snuggleStart(NSString *t)
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:.
* Also has fun with YES, NO, and nil.
@ -583,6 +619,7 @@ static BOOL snuggleStart(NSString *t)
NSString *name = [d objectForKey: @"Name"];
NSString *type = [d objectForKey: @"Type"];
NSDictionary *methods = [d objectForKey: @"Methods"];
NSDictionary *ivars = [d objectForKey: @"InstanceVariables"];
NSString *comment = [d objectForKey: @"Comment"];
NSArray *names;
NSArray *protocols;
@ -757,6 +794,14 @@ static BOOL snuggleStart(NSString *t)
for (j = 0; j < ind; j++) [str appendString: @" "];
[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:)];
for (i = 0; i < [names count]; i++)
{

View file

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

View file

@ -122,6 +122,263 @@
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
{
NSString *token;
@ -481,59 +738,6 @@ fail:
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
{
unsigned start;
@ -558,11 +762,14 @@ fail:
- (NSMutableDictionary*) parseInstanceVariables
{
enum { IsPrivate, IsProtected, IsPublic } visibility = IsPrivate;
NSString *visibility = @"private";
NSMutableDictionary *ivars;
BOOL shouldDocument = documentAllInstanceVariables;
DESTROY(comment);
inInstanceVariables = YES;
ivars = [NSMutableDictionary dictionaryWithCapacity: 8];
pos++;
while ([self skipWhiteSpace] < length && buffer[pos] != '}')
@ -576,24 +783,27 @@ fail:
|| [self skipWhiteSpace] >= length)
{
[self log: @"interface with bad visibility directive"];
return nil;
goto fail;
}
if ([token isEqual: @"private"] == YES)
{
visibility = IsPrivate;
ASSIGN(visibility, token);
shouldDocument = documentAllInstanceVariables;
}
else if ([token isEqual: @"protected"] == YES)
{
visibility = IsProtected;
ASSIGN(visibility, token);
shouldDocument = YES;
}
else if ([token isEqual: @"public"] == YES)
{
visibility = IsPublic;
ASSIGN(visibility, token);
shouldDocument = YES;
}
else
{
[self log: @"interface with bad visibility (%@)", token];
return nil;
goto fail;
}
}
else if (buffer[pos] == '#')
@ -601,11 +811,24 @@ fail:
[self skipPreprocessor]; // Ignore preprocessor directive.
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
{
[self skipStatement]; /* FIXME - currently we ignore ivars */
[self skipStatement];
}
}
inInstanceVariables = NO;
if (pos >= length)
{
[self log: @"interface with bad instance variables"];
@ -613,6 +836,10 @@ fail:
}
pos++; // Step past closing bracket.
return ivars;
fail:
DESTROY(comment);
inInstanceVariables = NO;
return nil;
}
- (NSMutableDictionary*) parseMethodIsDeclaration: (BOOL)flag
@ -1274,6 +1501,17 @@ fail:
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
* indicating the standards complied with. When this is turned on, we

View file

@ -174,11 +174,12 @@
<br />eg. [ NSObject-init],
will create a reference to the init method of NSObject, while
<br />[ (NSCopying)-copyWithZone:], creates a
reference to a method in the NSCopyIng protocol, and
<br />[ NSObject(TimedPerformers)-performSelector:withObject:afterDelay:],
creates a reference to a method in the TimedPerformers category.
reference to a method in the NSCopyIng protocol.
<br />Note that no spaces must appear between the square brackets
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>
</list>
<p>
@ -199,6 +200,11 @@
would result in the documentation saying that NSString is declared
in <code>Foundation/NSString.h</code>
</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>
May be used to specify the directory in which generated
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];
}
if ([defs boolForKey: @"DocumentAllInstanceVariables"] == YES)
{
[parser setDocumentAllInstanceVariables: YES];
}
for (i = 0; i < count; i++)
{

View file

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