vastly improved auto generation of documentation.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@11456 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
CaS 2001-11-21 17:10:22 +00:00
parent 60d27e6499
commit e3219b3374
10 changed files with 1055 additions and 321 deletions

View file

@ -1,3 +1,20 @@
2001-11-21 Richard Frith-Macdonald <rfm@gnu.org>
* Tools/AGSOutput.m:
* Tools/AGSOutput.h:
* Tools/AGSIndex.h:
* Tools/AGSIndex.m:
* Tools/AGSParser.h:
* Tools/AGSParser.m:
* Tools/AGSHtml.h:
* Tools/AGSHtml.m:
* Tools/autogsdoc.m: Many bugfixes and enhancements ... generate
html as well as gsdoc.
2001-11-19 Richard Frith-Macdonald <rfm@gnu.org>
* Source/GSXML.m: Implement NSCopying protocol for most classes.
2001-11-19 Adam Fedor <fedor@gnu.org>
* Source/simple-load.h (__objc_dynamic_get_symbol_path): Fix

View file

@ -43,7 +43,7 @@
@class GSSAXHandler;
@interface GSXMLDocument : NSObject
@interface GSXMLDocument : NSObject <NSCopying>
{
void *lib; // pointer to xmllib pointer of xmlDoc struct
BOOL native;
@ -74,7 +74,7 @@
@interface GSXMLNamespace : NSObject
@interface GSXMLNamespace : NSObject <NSCopying>
{
void *lib; /* pointer to struct xmlNs in the gnome xmllib */
BOOL native;
@ -103,7 +103,7 @@
/* XML Node */
@interface GSXMLNode : NSObject
@interface GSXMLNode : NSObject <NSCopying>
{
void *lib; /* pointer to struct xmlNode from libxml */
BOOL native;
@ -147,7 +147,7 @@
/* Attribute */
@interface GSXMLAttribute : GSXMLNode
@interface GSXMLAttribute : GSXMLNode <NSCopying>
{
}

View file

@ -119,10 +119,9 @@ loadEntityFunction(const char *url, const char *eid, xmlParserCtxtPtr *ctxt);
@implementation GSXMLDocument : NSObject
+ (void) initialize
+ (GSXMLDocument*) documentFrom: (void*)data
{
if (cacheDone == NO)
setupCache();
return AUTORELEASE([[self alloc] initFrom: data]);
}
+ (GSXMLDocument*) documentWithVersion: (NSString*)version
@ -130,25 +129,31 @@ loadEntityFunction(const char *url, const char *eid, xmlParserCtxtPtr *ctxt);
return AUTORELEASE([[self alloc] initWithVersion: version]);
}
- (id) initWithVersion: (NSString*)version
+ (void) initialize
{
void *data = xmlNewDoc([version cString]);
if (data == 0)
{
NSLog(@"Can't create GSXMLDocument object");
DESTROY(self);
}
else if ((self = [self initFrom: data]) != nil)
{
native = YES;
}
return self;
if (cacheDone == NO)
setupCache();
}
+ (GSXMLDocument*) documentFrom: (void*)data
- (id) copyWithZone: (NSZone*)z
{
return AUTORELEASE([[self alloc] initFrom: data]);
return RETAIN(self);
}
- (void) dealloc
{
if ((native) && lib != NULL)
{
xmlFreeDoc(lib);
}
[super dealloc];
}
- (id) init
{
NSLog(@"GSXMLDocument: calling -init is not legal");
RELEASE(self);
return nil;
}
- (id) initFrom: (void*)data
@ -173,11 +178,20 @@ loadEntityFunction(const char *url, const char *eid, xmlParserCtxtPtr *ctxt);
return self;
}
- (id) init
- (id) initWithVersion: (NSString*)version
{
NSLog(@"GSXMLDocument: calling -init is not legal");
RELEASE(self);
return nil;
void *data = xmlNewDoc([version cString]);
if (data == 0)
{
NSLog(@"Can't create GSXMLDocument object");
DESTROY(self);
}
else if ((self = [self initFrom: data]) != nil)
{
native = YES;
}
return self;
}
- (GSXMLNode*) root
@ -204,15 +218,6 @@ loadEntityFunction(const char *url, const char *eid, xmlParserCtxtPtr *ctxt);
return [NSString_class stringWithCString: ((xmlDocPtr)(lib))->encoding];
}
- (void) dealloc
{
if ((native) && lib != NULL)
{
xmlFreeDoc(lib);
}
[super dealloc];
}
- (void*) lib
{
return lib;
@ -316,6 +321,11 @@ static NSMapTable *nsNames = 0;
prefix: prefix]);
}
- (id) copyWithZone: (NSZone*)z
{
return RETAIN(self);
}
- (id) initWithNode: (GSXMLNode*)node
href: (NSString*)href
prefix: (NSString*)prefix
@ -540,6 +550,11 @@ static NSMapTable *nodeNames = 0;
return AUTORELEASE([[self alloc] initWithNamespace: ns name: name]);
}
- (id) copyWithZone: (NSZone*)z
{
return RETAIN(self);
}
- (id) initWithNamespace: (GSXMLNamespace*) ns name: (NSString*) name
{
self = [super init];
@ -828,7 +843,7 @@ static NSMapTable *nodeNames = 0;
/*
*
* GSXMLAttribure
* GSXMLAttribute
*
*/
@ -892,6 +907,11 @@ static NSMapTable *attrNames = 0;
return desc;
}
- (id) copyWithZone: (NSZone*)z
{
return RETAIN(self);
}
- (int) type
{
return (int)((xmlAttrPtr)(lib))->atype;

View file

@ -41,13 +41,16 @@
- (void) incIndent;
- (NSString*) outputDocument: (GSXMLNode*)node;
- (void) outputNode: (GSXMLNode*)node to: (NSMutableString*)buf;
- (void) outputNodeList: (GSXMLNode*)node to: (NSMutableString*)buf;
- (GSXMLNode*) outputBlock: (GSXMLNode*)node
to: (NSMutableString*)buf
inPara: (BOOL)flag;
- (GSXMLNode*) outputList: (GSXMLNode*)node to: (NSMutableString*)buf;
- (GSXMLNode*) outputText: (GSXMLNode*)node to: (NSMutableString*)buf;
- (void) outputUnit: (GSXMLNode*)node to: (NSMutableString*)buf;
- (NSString*) protocolRef: (NSString*)t;
- (void) setGlobalRefs: (AGSIndex*)r;
- (void) setLocalRefs: (AGSIndex*)r;
- (NSString*) typeRef: (NSString*)t;
@end
#endif

View file

@ -27,8 +27,23 @@
static int XML_ELEMENT_NODE;
static int XML_TEXT_NODE;
static GSXMLNode *firstElement(GSXMLNode *nodes)
{
while (nodes != nil)
{
if ([nodes type] == XML_ELEMENT_NODE)
{
return nodes;
}
nodes = [nodes next];
}
return nil;
}
@implementation AGSHtml
static NSMutableSet *textNodes = nil;
+ (void) initialize
{
if (self == [AGSHtml class])
@ -38,6 +53,21 @@ static int XML_TEXT_NODE;
*/
XML_ELEMENT_NODE = [GSXMLNode typeFromDescription: @"XML_ELEMENT_NODE"];
XML_TEXT_NODE = [GSXMLNode typeFromDescription: @"XML_TEXT_NODE"];
textNodes = [NSMutableSet new];
[textNodes addObject: @"br"];
[textNodes addObject: @"code"];
[textNodes addObject: @"em"];
[textNodes addObject: @"email"];
[textNodes addObject: @"entry"];
[textNodes addObject: @"file"];
[textNodes addObject: @"label"];
[textNodes addObject: @"prjref"];
[textNodes addObject: @"ref"];
[textNodes addObject: @"site"];
[textNodes addObject: @"uref"];
[textNodes addObject: @"url"];
[textNodes addObject: @"var"];
[textNodes addObject: @"footnote"];
}
}
@ -83,7 +113,7 @@ static int XML_TEXT_NODE;
[buf appendString: @"<html>\n"];
[self incIndent];
[self outputNode: node to: buf];
[self outputNodeList: [node children] to: buf];
[self decIndent];
[buf appendString: @"</html>\n"];
@ -92,9 +122,8 @@ static int XML_TEXT_NODE;
- (void) outputNode: (GSXMLNode*)node to: (NSMutableString*)buf
{
CREATE_AUTORELEASE_POOL(arp);
GSXMLNode *children = [node children];
GSXMLNode *next = [node next];
BOOL newUnit = NO;
if ([node type] == XML_ELEMENT_NODE)
{
@ -107,8 +136,7 @@ static int XML_TEXT_NODE;
[buf appendString: indent];
[buf appendString: @"<div>\n"];
[self incIndent];
[self outputNode: children to: buf];
children = nil;
[self outputNodeList: children to: buf];
// Close back division
[self decIndent];
@ -117,35 +145,61 @@ static int XML_TEXT_NODE;
}
else if ([name isEqual: @"body"] == YES)
{
[buf appendString: indent];
[buf appendString: @"<body>\n"];
[self incIndent];
[self outputNode: children to: buf];
children = nil;
/* Should already be in html body */
[self outputNodeList: children to: buf];
[self decIndent];
[buf appendString: indent];
[buf appendString: @"</body>\n"];
}
else if ([name isEqual: @"br"] == YES)
{
[buf appendString: @"<br />"];
}
else if ([name isEqual: @"category"] == YES)
{
newUnit = YES;
unit = [NSString stringWithFormat: @"%@(%@)",
[prop objectForKey: @"class"], [prop objectForKey: @"name"]];
NSString *name = [prop objectForKey: @"name"];
NSString *cls = [prop objectForKey: @"class"];
cls = [self typeRef: cls];
unit = [NSString stringWithFormat: @"%@(%@)", cls, name];
[buf appendFormat: @"<h2>%@(<a name=\"category$%@\">%@</a>)</h2>\n",
unit, cls, name];
[self outputUnit: node to: buf];
children = nil;
unit = nil;
}
else if ([name isEqual: @"chapter"] == YES)
{
heading = @"h1";
[self outputNode: children to: buf];
children = nil;
[self outputNodeList: children to: buf];
}
else if ([name isEqual: @"class"] == YES)
{
newUnit = YES;
unit = [prop objectForKey: @"name"];
NSString *name = [prop objectForKey: @"name"];
NSString *sup = [prop objectForKey: @"super"];
unit = name;
sup = [self typeRef: sup];
if (sup == nil)
{
/*
* This is a root class.
*/
[buf appendFormat: @"<h3><a name=\"class$%@\">%@</a></h3>\n",
unit, name];
}
else
{
[buf appendFormat: @"<h3><a name=\"class$%@\">%@</a> : %@</h3>\n",
unit, name, sup];
}
[self outputUnit: node to: buf];
children = nil;
unit = nil;
}
else if ([name isEqual: @"code"] == YES)
{
[buf appendString: @"<code>"];
[self outputText: children to: buf];
[buf appendString: @"</code>"];
}
else if ([name isEqual: @"desc"] == YES)
{
@ -157,14 +211,67 @@ static int XML_TEXT_NODE;
[buf appendString: indent];
[buf appendString: @"</p>\n"];
}
else if ([name isEqual: @"em"] == YES)
{
[buf appendString: @"<em>"];
[self outputText: children to: buf];
[buf appendString: @"</em>"];
}
else if ([name isEqual: @"email"] == YES)
{
NSString *ename;
ename = [prop objectForKey: @"address"];
if (ename == nil)
{
[buf appendString: @"<code>"];
}
else
{
[buf appendFormat: @"<a href=\"%@\"><code>", ename];
}
[self outputText: [node children] to: buf];
if (ename == nil)
{
[buf appendString: @"</code>"];
}
else
{
[buf appendFormat: @"</code></a>", ename];
}
}
else if ([name isEqual: @"entry"])
{
NSString *text;
NSString *val;
text = [children content];
val = [prop objectForKey: @"id"];
if (val == nil)
{
val = text;
}
[buf appendFormat: @"<a name=\"label$%@\"></a>", val];
}
else if ([name isEqual: @"file"] == YES)
{
[buf appendString: @"<code>"];
[self outputText: children to: buf];
[buf appendString: @"</code>"];
}
else if ([name isEqual: @"footnote"] == YES)
{
[buf appendString: @"<blockquote>"];
[self outputText: children to: buf];
[buf appendString: @"</blockquote>"];
}
else if ([name isEqual: @"front"] == YES)
{
// Open front division
[buf appendString: indent];
[buf appendString: @"<div>\n"];
[self incIndent];
[self outputNode: children to: buf];
children = nil;
[self outputNodeList: children to: buf];
// Close front division
[self decIndent];
[buf appendString: indent];
@ -184,17 +291,138 @@ static int XML_TEXT_NODE;
prevFile = [prevFile stringByAppendingPathExtension: @"html"];
upFile = [prop objectForKey: @"up"];
upFile = [upFile stringByAppendingPathExtension: @"html"];
[self outputNodeList: children to: buf];
}
else if ([name isEqual: @"head"] == YES)
{
[buf appendString: indent];
[buf appendString: @"<head>\n"];
[self incIndent];
[self outputNode: children to: buf];
children = nil;
children = firstElement(children);
[buf appendString: indent];
[buf appendString: @"<title>"];
[self incIndent];
[self outputText: [children children] to: buf];
[self decIndent];
[buf appendString: @"</title>\n"];
[self decIndent];
[buf appendString: indent];
[buf appendString: @"</head>\n"];
[buf appendString: indent];
[buf appendString: @"<body>\n"];
[self incIndent];
[buf appendString: indent];
[buf appendString: @"<h1>"];
[self outputText: [children children] to: buf];
[buf appendString: @"</h1>\n"];
[buf appendString: indent];
[buf appendString: @"<h3>Authors</h3>\n"];
[buf appendString: indent];
[buf appendString: @"<dl>\n"];
[self incIndent];
children = firstElement([children next]);
while ([[children name] isEqual: @"author"] == YES)
{
GSXMLNode *author = children;
GSXMLNode *tmp;
GSXMLNode *email = nil;
GSXMLNode *url = nil;
GSXMLNode *desc = nil;
children = [children next];
children = firstElement(children);
tmp = firstElement([author children]);
if ([[tmp name] isEqual: @"email"] == YES)
{
email = tmp;
tmp = firstElement([tmp next]);
}
if ([[tmp name] isEqual: @"url"] == YES)
{
url = tmp;
tmp = firstElement([tmp next]);
}
if ([[tmp name] isEqual: @"desc"] == YES)
{
desc = tmp;
tmp = firstElement([tmp next]);
}
[buf appendString: indent];
if (url == nil)
{
[buf appendString: @"<dt>"];
[buf appendString: [[author propertiesAsDictionary]
objectForKey: @"name"]];
}
else
{
[buf appendString: @"<dt><a href=\""];
[buf appendString: [[url propertiesAsDictionary]
objectForKey: @"url"]];
[buf appendString: @"\">"];
[buf appendString: [[author propertiesAsDictionary]
objectForKey: @"name"]];
[buf appendString: @"</a>"];
}
if (email != nil)
{
[buf appendString: @"("];
[self outputNode: email to: buf];
[buf appendString: @")"];
}
[buf appendString: @"</dt>\n"];
[buf appendString: indent];
[buf appendString: @"<dd>\n"];
if (desc != nil)
{
[self incIndent];
[self outputBlock: desc to: buf inPara: NO];
[self decIndent];
}
[buf appendString: indent];
[buf appendString: @"</dd>\n"];
}
[self decIndent];
[buf appendString: indent];
[buf appendString: @"</dl>\n"];
if ([[children name] isEqual: @"version"] == YES)
{
[buf appendString: indent];
[buf appendString: @"<p>Version: "];
[self outputNode: [children children] to: buf];
[buf appendString: @"</p>\n"];
children = firstElement([children next]);
}
if ([[children name] isEqual: @"date"] == YES)
{
[buf appendString: indent];
[buf appendString: @"<p>Date: "];
[self outputNode: [children children] to: buf];
[buf appendString: @"</p>\n"];
children = firstElement([children next]);
}
if ([[children name] isEqual: @"abstract"] == YES)
{
[buf appendString: indent];
[buf appendString: @"<blockquote>\n"];
[self incIndent];
[self outputBlock: [children children] to: buf inPara: NO];
[self decIndent];
[buf appendString: indent];
[buf appendString: @"</blockquote>\n"];
children = firstElement([children next]);
}
if ([[children name] isEqual: @"copy"] == YES)
{
[buf appendString: indent];
[buf appendString: @"<p>Copyright: "];
[self outputNode: [children children] to: buf];
[buf appendString: @"</p>\n"];
children = firstElement([children next]);
}
}
else if ([name isEqual: @"heading"] == YES)
{
@ -203,7 +431,6 @@ static int XML_TEXT_NODE;
[buf appendString: heading];
[buf appendString: @">"];
[self outputText: children to: buf];
children = nil;
[buf appendString: @"</"];
[buf appendString: heading];
[buf appendString: @">\n"];
@ -212,33 +439,43 @@ static int XML_TEXT_NODE;
{
NSString *tmp = [prop objectForKey: @"name"];
NSLog(@"Element '%@' not implemented", name); // FIXME
}
else if ([name isEqual: @"entry"] || [name isEqual: @"label"])
else if ([name isEqual: @"label"] == YES) // %anchor
{
NSString *text;
NSString *val;
text = [children content];
children = nil;
val = [prop objectForKey: @"id"];
if (val == nil)
{
val = text;
}
[buf appendFormat: @"<a name=\"label$%@\">", val];
[self outputText: children to: buf];
[buf appendString: @"</a>"];
}
else if ([name isEqual: @"method"] == YES)
{
NSString *sel = @"";
NSString *sel;
NSString *str;
GSXMLNode *tmp = children;
BOOL hadArg = NO;
sel = [prop objectForKey: @"factory"];
str = [prop objectForKey: @"type"];
if (sel != nil && [sel boolValue] == YES)
{
sel = @"+";
str = [NSString stringWithFormat: @"+ (%@) ",
[self typeRef: str]];
}
else
{
sel = @"-";
str = [NSString stringWithFormat: @"- (%@)",
[self typeRef: str]];
}
children = nil;
while (tmp != nil)
@ -249,39 +486,250 @@ static int XML_TEXT_NODE;
{
GSXMLNode *t = [tmp children];
str = [str stringByAppendingString: @"<b>"];
while (t != nil)
{
if ([t type] == XML_TEXT_NODE)
{
sel = [sel stringByAppendingString: [t content]];
NSString *content = [t content];
sel = [sel stringByAppendingString: content];
if (hadArg == YES)
{
str = [str stringByAppendingString: @" "];
}
str = [str stringByAppendingString: content];
}
t = [t next];
}
str = [str stringByAppendingString: @"</b>"];
}
else if ([[tmp name] isEqual: @"arg"] == NO)
else if ([[tmp name] isEqual: @"arg"] == YES)
{
children = tmp;
break;
GSXMLNode *t = [tmp children];
NSString *s;
s = [[tmp propertiesAsDictionary] objectForKey: @"type"];
s = [self typeRef: s];
str = [str stringByAppendingFormat: @" (%@)", s];
while (t != nil)
{
if ([t type] == XML_TEXT_NODE)
{
str = [str stringByAppendingString: [t content]];
}
t = [t next];
}
hadArg = YES; // Say we have found an arg.
}
else if ([[tmp name] isEqual: @"vararg"] == YES)
{
sel = [sel stringByAppendingString: @",..."];
str = [str stringByAppendingString: @"<b>,...</b>"];
children = [tmp next];
break;
}
else
{
children = tmp;
break;
}
}
tmp = [tmp next];
}
if ([sel length] > 1)
{
/*
* Output selector heading.
*/
[buf appendString: indent];
[buf appendFormat: @"<h3><a name=\"%@%@\">%@</a></h3>\n",
unit, sel, [sel substringFromIndex: 1]];
[buf appendString: indent];
[buf appendString: str];
[buf appendString: @";<br />\n"];
node = children;
/*
* List standards with which method complies
*/
children = [node next];
if ([[children name] isEqual: @"standards"])
{
tmp = [node children];
if (tmp != nil)
{
[buf appendString: @"Standards:"];
while (tmp != nil)
{
[buf appendString: @" "];
[buf appendString: [tmp name]];
tmp = [tmp next];
}
[buf appendString: @"<br />\n"];
}
}
if ((str = [prop objectForKey: @"init"]) != nil
&& [str boolValue] == YES)
{
[buf appendString: @"This is a designated initialiser "
@"for the class.<br />\n"];
}
str = [prop objectForKey: @"override"];
if ([str isEqual: @"subclass"] == YES)
{
[buf appendString: @"Subclasses <strong>should</strong> "
@"override this method.<br />\n"];
}
else if ([str isEqual: @"never"] == YES)
{
[buf appendString: @"Subclasses should <strong>NOT</strong> "
@"override this method.<br />\n"];
}
if ([[node name] isEqual: @"desc"])
{
[self outputNode: node to: buf];
}
[buf appendString: indent];
[buf appendString: @"<hr />\n"];
}
}
else if ([name isEqual: @"prjref"] == YES)
{
NSLog(@"Element '%@' not implemented", name); // FIXME
}
else if ([name isEqual: @"ref"] == YES) // %xref
{
NSString *type = [prop objectForKey: @"type"];
NSString *r = [prop objectForKey: @"id"];
NSString *f = nil;
BOOL isLocal = YES;
if ([type isEqual: @"method"] || [type isEqual: @"variable"])
{
NSString *c = [prop objectForKey: @"class"];
/*
* No class specified ... try to infer it.
*/
if (c == nil)
{
/*
* If we are currently inside a class, category, or protocol
* we see if the required item exists in that unit and if so,
* we assume that we need a local reference.
*/
if (unit != nil)
{
f = [localRefs unitRef: r type: type unit: unit];
if (f == nil)
{
f = [globalRefs unitRef: r type: type unit: unit];
if (f != nil)
{
isLocal = NO;
c = unit;
}
}
else
{
c = unit;
}
}
/*
* If we have not found it in the current unit, we check
* all known references to see if the item is uniquely
* documented somewhere.
*/
if (c == nil)
{
NSDictionary *d;
d = [localRefs unitRef: r type: type];
if ([d count] == 0)
{
isLocal = NO;
d = [globalRefs unitRef: r type: type];
}
if ([d count] == 1)
{
/*
* Record the class where the item is documented
* and the file where that documentation occurs.
*/
c = [[d allKeys] objectAtIndex: 0];
f = [d objectForKey: c];
}
}
}
else
{
/*
* Simply look up the reference.
*/
f = [localRefs unitRef: r type: type unit: c];
if (f == nil)
{
isLocal = NO;
f = [globalRefs unitRef: r type: type unit: c];
}
}
if (f != nil)
{
f = [f stringByAppendingPathExtension: @"html"];
if (isLocal == YES)
{
[buf appendFormat: @"<a href=\"#%@%@\">", c, r];
}
else
{
[buf appendFormat: @"<a href=\"%@#%@%@\">", f, c, r];
}
}
}
else
{
f = [localRefs globalRef: r type: type];
if (f == nil)
{
isLocal = NO;
f = [globalRefs globalRef: r type: type];
}
if (f != nil)
{
f = [f stringByAppendingPathExtension: @"html"];
if (isLocal == YES)
{
[buf appendFormat: @"<a href=\"#%@$%@\">", type, r];
}
else
{
[buf appendFormat: @"<a href=\"%@#%@$%@\">", f, type, r];
}
}
}
if (f == nil)
{
NSLog(@"ref '%@' not found for %@", name, type);
}
else
{
[self outputText: [node children] to: buf];
[buf appendString: @"</a>\n"];
}
}
else if ([name isEqual: @"protocol"] == YES)
{
newUnit = YES;
unit = [prop objectForKey: @"name"];
NSString *name = [prop objectForKey: @"name"];
unit = [NSString stringWithFormat: @"(%@)", name];
[buf appendFormat:
@"<h3><a name=\"protocol$%@\">&lt;%@&gt;</a></h3>\n", unit, name];
[self outputUnit: node to: buf];
children = nil;
unit = nil;
}
else if ([name isEqual: @"constant"] == YES
|| [name isEqual: @"EOEntity"] == YES
@ -293,34 +741,75 @@ static int XML_TEXT_NODE;
{
NSString *tmp = [prop objectForKey: @"name"];
NSLog(@"Element '%@' not implemented", name); // FIXME
}
else if ([name isEqual: @"section"] == YES)
{
heading = @"h2";
[self outputNode: children to: buf];
children = nil;
}
else if ([name isEqual: @"site"] == YES)
{
[buf appendString: @"<code>"];
[self outputText: children to: buf];
[buf appendString: @"</code>"];
}
else if ([name isEqual: @"subsect"] == YES)
{
heading = @"h3";
[self outputNode: children to: buf];
children = nil;
}
else if ([name isEqual: @"subsubsect"] == YES)
{
heading = @"h4";
[self outputNode: children to: buf];
children = nil;
}
else if ([name isEqual: @"title"] == YES)
else if ([name isEqual: @"type"] == YES)
{
NSString *n = [prop objectForKey: @"name"];
node = [node children];
[buf appendString: indent];
[buf appendString: @"<title>"];
[self incIndent];
[buf appendFormat: @"<h3><a name=\"type$%@\">typedef %@ %@</a></h3>",
n, [node content], n];
node = [node next];
if (node != nil && [[node name] isEqual: @"declared"] == YES)
{
[buf appendString: indent];
[buf appendString: @"Declared: "];
[self outputText: [node children] to: buf];
[buf appendString: @"<br />\n"];
node = [node next];
}
if (node != nil && [[node name] isEqual: @"desc"] == YES)
{
[self outputNode: node to: buf];
node = [node next];
}
if (node != nil && [[node name] isEqual: @"standards"] == YES)
{
[self outputNode: node to: buf];
node = [node next];
}
}
else if ([name isEqual: @"uref"] == YES)
{
[buf appendString: @"<a href=\""];
[buf appendString: [prop objectForKey: @"url"]];
[buf appendString: @"\">"];
[self outputText: children to: buf];
children = nil;
[self decIndent];
[buf appendString: @"</title>\n"];
[buf appendString: @"</a>"];
}
else if ([name isEqual: @"url"] == YES)
{
NSLog(@"Element '%@' not implemented", name); // FIXME
}
else if ([name isEqual: @"var"] == YES) // %phrase
{
[buf appendString: @"<var>"];
[self outputText: children to: buf];
[buf appendString: @"</var>"];
}
else
{
@ -333,24 +822,19 @@ static int XML_TEXT_NODE;
{
NSLog(@"Element '%@' not implemented", name); // FIXME
}
else
{
next = tmp;
}
}
}
RELEASE(arp);
}
if (children != nil)
- (void) outputNodeList: (GSXMLNode*)node to: (NSMutableString*)buf
{
while (node != nil)
{
[self outputNode: children to: buf];
}
if (newUnit == YES)
{
unit = nil;
}
if (next != nil)
{
[self outputNode: next to: buf];
GSXMLNode *next = [node next];
[self outputNode: node to: buf];
node = next;
}
}
@ -566,80 +1050,10 @@ NSLog(@"Element '%@' not implemented", name); // FIXME
else if ([node type] == XML_ELEMENT_NODE)
{
NSString *name = [node name];
GSXMLNode *children = [node children];
NSDictionary *prop = [node propertiesAsDictionary];
if ([name isEqual: @"br"] == YES)
if ([textNodes member: name] != nil)
{
[buf appendString: @"<br />"];
}
else if ([name isEqual: @"ref"] == YES) // %xref
{
NSLog(@"Element '%@' not implemented", name); // FIXME
}
else if ([name isEqual: @"uref"] == YES)
{
[buf appendString: @"<a href=\""];
[buf appendString: [prop objectForKey: @"url"]];
[buf appendString: @"\">"];
[self outputText: children to: buf];
[buf appendString: @"</a>"];
}
else if ([name isEqual: @"url"] == YES)
{
NSLog(@"Element '%@' not implemented", name); // FIXME
}
else if ([name isEqual: @"email"] == YES)
{
NSLog(@"Element '%@' not implemented", name); // FIXME
}
else if ([name isEqual: @"prjref"] == YES)
{
NSLog(@"Element '%@' not implemented", name); // FIXME
}
else if ([name isEqual: @"label"] == YES) // %anchor
{
NSLog(@"Element '%@' not implemented", name); // FIXME
}
else if ([name isEqual: @"entry"] == YES)
{
NSLog(@"Element '%@' not implemented", name); // FIXME
}
else if ([name isEqual: @"var"] == YES) // %phrase
{
[buf appendString: @"<var>"];
[self outputText: children to: buf];
[buf appendString: @"</var>"];
}
else if ([name isEqual: @"em"] == YES)
{
[buf appendString: @"<em>"];
[self outputText: children to: buf];
[buf appendString: @"</em>"];
}
else if ([name isEqual: @"code"] == YES)
{
[buf appendString: @"<code>"];
[self outputText: children to: buf];
[buf appendString: @"</code>"];
}
else if ([name isEqual: @"file"] == YES)
{
[buf appendString: @"<code>"];
[self outputText: children to: buf];
[buf appendString: @"</code>"];
}
else if ([name isEqual: @"site"] == YES)
{
[buf appendString: @"<code>"];
[self outputText: children to: buf];
[buf appendString: @"</code>"];
}
else if ([name isEqual: @"footnote"] == YES)
{
[buf appendString: @"<blockquote>"];
[self outputText: children to: buf];
[buf appendString: @"</blockquote>"];
[self outputNode: node to: buf];
}
else
{
@ -653,8 +1067,6 @@ NSLog(@"Element '%@' not implemented", name); // FIXME
- (void) outputUnit: (GSXMLNode*)node to: (NSMutableString*)buf
{
GSXMLNode *u = node;
node = [node children];
if (node != nil && [[node name] isEqual: @"declared"] == YES)
{
@ -666,9 +1078,11 @@ NSLog(@"Element '%@' not implemented", name); // FIXME
}
while (node != nil && [[node name] isEqual: @"conform"] == YES)
{
NSString *text = [[node children] content];
[buf appendString: indent];
[buf appendString: @"Conform: "];
[self outputText: [node children] to: buf];
[buf appendString: [self protocolRef: text]];
[buf appendString: @"<br />\n"];
node = [node next];
}
@ -682,13 +1096,36 @@ NSLog(@"Element '%@' not implemented", name); // FIXME
[self outputNode: node to: buf];
node = [node next];
}
if (node != nil && [[node name] isEqual: @"standaards"] == YES)
if (node != nil && [[node name] isEqual: @"standards"] == YES)
{
[self outputNode: node to: buf];
node = [node next];
}
}
/**
* Try to make a link to the documentation for the supplied protocol.
*/
- (NSString*) protocolRef: (NSString*)t
{
NSString *n;
NSString *s;
t = [t stringByTrimmingSpaces];
n = [NSString stringWithFormat: @"(%@)", t];
if ((s = [localRefs globalRef: n type: @"protocol"]) != nil)
{
t = [NSString stringWithFormat: @"<a href=\"#protocol$%@\">%@</a>", n, t];
}
else if ((s = [globalRefs globalRef: t type: @"protocol"]) != nil)
{
s = [s stringByAppendingPathExtension: @"html"];
t = [NSString stringWithFormat: @"<a href=\"%@#protocol$%@\">%@</a>",
s, n, t];
}
return t;
}
- (void) setGlobalRefs: (AGSIndex*)r
{
ASSIGN(globalRefs, r);
@ -699,5 +1136,74 @@ NSLog(@"Element '%@' not implemented", name); // FIXME
ASSIGN(localRefs, r);
}
/**
* Assuming that the supplied string contains type information (as used
* in a method declaration or type cast), we make an attempt at extracting
* the basic type, and seeing if we can find a documented declaration for
* it. If we can, we return a modified version of the string containing
* a link to the appropriate documentation. Otherwise, we just return the
* plain type string. In all cases, we strip leading and trailing white space.
*/
- (NSString*) typeRef: (NSString*)t
{
NSString *orig = [t stringByTrimmingSpaces];
NSString *s;
unsigned end = [orig length];
unsigned start;
t = orig;
while (end > 0)
{
unichar c = [t characterAtIndex: end-1];
if (c != '*' && !isspace(c))
{
break;
}
end--;
}
start = end;
while (start > 0)
{
unichar c = [t characterAtIndex: start-1];
if (c != '_' && !isalnum(c))
{
break;
}
start--;
}
t = [orig substringWithRange: NSMakeRange(start, end - start)];
if ((s = [localRefs globalRef: t type: @"type"]) != nil)
{
s = [NSString stringWithFormat: @"<a href=\"#type$%@\">%@</a>", t, t];
}
else if ((s = [localRefs globalRef: t type: @"class"]) != nil)
{
s = [NSString stringWithFormat: @"<a href=\"#class$%@\">%@</a>", t, t];
}
else if ((s = [globalRefs globalRef: t type: @"type"]) != nil)
{
s = [s stringByAppendingPathExtension: @"html"];
s = [NSString stringWithFormat: @"<a href=\"%@#type$%@\">%@</a>",
s, t, t];
}
else if ((s = [globalRefs globalRef: t type: @"class"]) != nil)
{
s = [s stringByAppendingPathExtension: @"html"];
s = [NSString stringWithFormat: @"<a href=\"%@#class$%@\">%@</a>",
s, t, t];
}
if (s != nil)
{
if ([orig length] == [t length])
{
return s;
}
return [orig stringByReplacingString: t withString: s];
}
return orig;
}
@end

View file

@ -31,10 +31,13 @@
NSString *base; // Not retained
NSString *unit; // Not retained
}
- (NSString*) globalRef: (NSString*)ref type: (NSString*)type;
- (void) makeRefs: (GSXMLNode*)node;
- (void) mergeRefs: (NSDictionary*)more;
- (NSMutableDictionary*) refs;
- (void) setGlobalRef: (NSString*)ref type: (NSString*)type;
- (void) setUnitRef: (NSString*)ref type: (NSString*)type;
- (NSDictionary*) unitRef: (NSString*)ref type: (NSString*)type;
- (NSString*) unitRef: (NSString*)ref type: (NSString*)type unit: (NSString*)u;
@end
#endif

View file

@ -104,6 +104,14 @@ mergeDictionaries(NSMutableDictionary *dst, NSDictionary *src)
[super dealloc];
}
- (NSString*) globalRef: (NSString*)ref type: (NSString*)type
{
NSDictionary *t;
t = [refs objectForKey: type];
return [t objectForKey: ref];
}
- (id) init
{
refs = [[NSMutableDictionary alloc] initWithCapacity: 8];
@ -263,7 +271,8 @@ mergeDictionaries(NSMutableDictionary *dst, NSDictionary *src)
else if ([name isEqual: @"protocol"] == YES)
{
newUnit = YES;
unit = [prop objectForKey: @"name"];
unit = [NSString stringWithFormat: @"(%@)",
[prop objectForKey: @"name"]];
[self setGlobalRef: unit type: name];
}
else if ([name isEqual: @"constant"] == YES
@ -359,5 +368,22 @@ mergeDictionaries(NSMutableDictionary *dst, NSDictionary *src)
[r setObject: base forKey: unit];
}
- (NSDictionary*) unitRef: (NSString*)ref type: (NSString*)type
{
NSDictionary *t;
t = [refs objectForKey: type];
return [t objectForKey: ref];
}
- (NSString*) unitRef: (NSString*)ref type: (NSString*)type unit: (NSString*)u
{
NSDictionary *t;
t = [refs objectForKey: type];
t = [t objectForKey: ref];
return [t objectForKey: unit];
}
@end

View file

@ -49,6 +49,7 @@
unsigned length;
unsigned pos;
BOOL commentsRead;
NSString *declared; // Where classes were declared.
NSString *comment; // Documentation accumulator.
NSMutableDictionary *info; // All information parsed.
@ -72,6 +73,7 @@
- (NSMutableDictionary*) parseProtocol;
- (NSMutableArray*) parseProtocolList;
- (void) reset;
- (void) setDeclared: (NSString*)name;
- (void) setupBuffer;
- (unsigned) skipBlock;
- (unsigned) skipComment;

View file

@ -26,6 +26,7 @@
- (void) dealloc
{
DESTROY(declared);
DESTROY(info);
DESTROY(comment);
DESTROY(identifier);
@ -124,6 +125,10 @@
commentsRead = NO;
fileName = name;
if (declared == nil)
{
ASSIGN(declared, fileName);
}
unitName = nil;
itemName = nil;
DESTROY(comment);
@ -422,7 +427,7 @@ fail:
[dict setObject: methods forKey: @"Methods"];
}
[dict setObject: fileName forKey: @"Declared"];
[dict setObject: declared forKey: @"Declared"];
if (category == nil)
{
@ -522,6 +527,11 @@ fail:
return nil;
}
}
else if (buffer[pos] == '#')
{
[self skipRemainderOfLine]; // Ignore preprocessor directive.
DESTROY(comment);
}
else
{
[self skipStatement]; /* FIXME - currently we ignore ivars */
@ -758,7 +768,11 @@ fail:
/*
* Get a list of known methods.
*/
if ([unitName hasSuffix: @")"])
if ([unitName hasPrefix: @"("])
{
exist = nil; // A protocol ... no method implementations.
}
else if ([unitName hasSuffix: @")"])
{
exist = [info objectForKey: @"Categories"];
}
@ -770,7 +784,7 @@ fail:
exist = [exist objectForKey: @"Methods"];
/*
* If there were no methods in the interface, we can't
* document any now so we mak as well skip to the end.
* document any now so we may as well skip to the end.
*/
if (exist == nil)
{
@ -1006,7 +1020,7 @@ fail:
goto fail;
}
[dict setObject: name forKey: @"Name"];
unitName = name;
unitName = [NSString stringWithFormat: @"(%@)", name];
/*
* Protocols may themselves conform to protocols.
@ -1092,6 +1106,7 @@ fail:
- (void) reset
{
[info removeAllObjects];
DESTROY(declared);
DESTROY(comment);
fileName = nil;
unitName = nil;
@ -1102,6 +1117,11 @@ fail:
pos = 0;
}
- (void) setDeclared: (NSString*)name
{
ASSIGN(declared, name);
}
/**
* Read in the file to be parsed and store it in a temporary unicode
* buffer. Perform basic transformations on the buffer to simplify
@ -1449,7 +1469,7 @@ fail:
{
r = NSMakeRange(i, r.location - i);
author = [comment substringWithRange: r];
author = [author stringByTrimmingWhiteSpaces];
author = [author stringByTrimmingSpaces];
authors = [NSMutableArray arrayWithObject: author];
[info setObject: authors forKey: @"authors"];
}
@ -1525,7 +1545,7 @@ fail:
{
r = NSMakeRange(i, r.location - i);
date = [comment substringWithRange: r];
date = [date stringByTrimmingWhiteSpaces];
date = [date stringByTrimmingSpaces];
date = [NSString stringWithFormat:
@"<date>%@</date>", date];
[info setObject: date forKey: @"date"];
@ -1552,7 +1572,7 @@ fail:
{
r = NSMakeRange(i, r.location - i);
version = [comment substringWithRange: r];
version = [version stringByTrimmingWhiteSpaces];
version = [version stringByTrimmingSpaces];
version = [NSString stringWithFormat:
@"<version>%@</version>", version];
[info setObject: version forKey: @"version"];

View file

@ -25,13 +25,16 @@
The autogsdoc tool is a command-line utility for parsing ObjectiveC
source code (header files and optionally source files) in order to
generate documentation covering the public interface of the various
classes in the source.
classes, categories, and protocols in the source.
</p>
<p>
The simple way to use this is to run the command with one or more
header file names as arguments ... the tool will automatically
parse corresponding source files in the saem directory, and produce
gsdoc files as output.
parse corresponding source files in the same directory, and produce
gsdoc files as output. You may also supply source file names
(in which case documentation will be produced for the private
methods within the source files), and the names of existing gsdoc
documentation files (in which case their contents will be indexed).
</p>
<p>
Even without any human assistance, this tool will produce skeleton
@ -40,8 +43,8 @@
from the source files and insert those comments into the gsdoc output.
</p>
<p>
Any comment beginning with slash and <em>two</em> asterisks rathr than
the common slash and single asterisk, is taken to be gsdoc markup to
Any comment beginning with slash and <em>two</em> asterisks rather than
the common slash and single asterisk, is taken to be gsdoc markup, to
be use as the description of the class or method following it. This
comment text is reformatted and then inserted into the output.
</p>
@ -75,7 +78,7 @@
of the gsdoc output.
</item>
<item><strong>&lt;date&gt;</strong>
Date off the revision of the document ... placed in the head
Date of the revision of the document ... placed in the head
of the gsdoc output. If this is omitted the tool will try to
construct a value from the RCS Date tag (if available).
</item>
@ -141,7 +144,12 @@
enclosed in &lt;var&gt; ... &lt;/var&gt; markup.
</item>
<item>Method names (beginning with a plus or minus) are enclosed
in &lt;ref...&gt; ... &lt;/ref&gt; markup.
in &lt;ref...&gt; ... &lt;/ref&gt; markup.<br />
eg. -init
</item>
<item>Method specifiers including class names (beginning and ending with
square brackets) are enclosed in &lt;ref...&gt; ... &lt;/ref&gt; markup.
<br />eg. [NSObject -init]
</item>
</list>
<p>
@ -149,16 +157,35 @@
supplied as command-line arguments as usual) -
</p>
<list>
<item><strong>Declared</strong>
Specify where headers are to be documented as being found.<br />
The actual name produced in the documentation is formed by appending
the last component of the header file name to the value of this
default.<br />
If this default is not specified, the full name of the header file
(as supplied on the command line), with the HeaderDirectory
default prepended, is used.
</item>
<item><strong>DocumentationDirectory</strong>
May be used to specify the directory in which generated
gsdoc files are to be placed. If this is not set, output
is placed in thge same directory as the source files.
documentation is to be placed. If this is not set, output
is placed in the current directory.
</item>
<item><strong>HeaderDirectory</strong>
May be used to specify the directory to be searched for header files.
If this is not specified, headers are looked for relative to the
current directory or using absolute path names if given.
</item>
<item><string>Project</strong>
May be used to specify the name of this project ... determines the
name of the index reference file produced as part of the documentation
to provide information enabling other projects to cross-reference to
items in this project.
</item>
<item><strong>SourceDirectory</strong>
May be used to specify the directory in which the tool looks
for source files. If this is not set, the tool looks for the
source in the same directory as the header files named on the
command line.
May be used to specify the directory to be searched for header files.
If this is not specified, headers are looked for relative to the
current directory or using absolute path names if given.
</item>
</list>
<section>
@ -196,12 +223,18 @@ main(int argc, char **argv, char **env)
NSUserDefaults *defs;
NSFileManager *mgr;
NSString *documentationDirectory;
NSString *declared;
NSString *headerDirectory;
NSString *sourceDirectory;
NSString *projectName;
NSString *refsFile;
AGSIndex *prjRefs;
AGSIndex *indexer;
AGSParser *parser;
AGSOutput *output;
NSString *up = nil;
NSString *prev = nil;
unsigned pass;
CREATE_AUTORELEASE_POOL(pool);
#ifdef GS_PASS_ARGUMENTS
@ -210,10 +243,30 @@ main(int argc, char **argv, char **env)
defs = [NSUserDefaults standardUserDefaults];
[defs registerDefaults: [NSDictionary dictionaryWithObjectsAndKeys:
@"Yes", @"Monolithic", nil]];
@"Untitled", @"ProjectName",
nil]];
projectName = [defs stringForKey: @"ProjectName"];
declared = [defs stringForKey: @"Declared"];
headerDirectory = [defs stringForKey: @"HeaderDirectory"];
if (headerDirectory == nil)
{
headerDirectory = @".";
}
sourceDirectory = [defs stringForKey: @"SourceDirectory"];
if (sourceDirectory == nil)
{
sourceDirectory = headerDirectory;
}
documentationDirectory = [defs stringForKey: @"DocumentationDirectory"];
if (documentationDirectory == nil)
{
documentationDirectory = @".";
}
proc = [NSProcessInfo processInfo];
if (proc == nil)
@ -224,169 +277,253 @@ main(int argc, char **argv, char **env)
mgr = [NSFileManager defaultManager];
prjRefs = [AGSIndex new];
indexer = [AGSIndex new];
parser = [AGSParser new];
output = [AGSOutput new];
args = [proc arguments];
for (i = 1; i < [args count]; i++)
/*
* On the initial pass (pass0), we parse all files, produce indexes,
* and write gsdoc output, but not html output.
*
* On the next pass, we have all the indexing info, so we can use it
* to produce html output.
*/
for (pass = 0; pass < 2; pass++)
{
NSString *arg = [args objectAtIndex: i];
CREATE_AUTORELEASE_POOL(arp);
if ([arg hasPrefix: @"-"])
for (i = 1; i < [args count]; i++)
{
i++; // Skip next value ... it is a default.
}
else if ([arg hasSuffix: @".h"] || [arg hasSuffix: @".m"])
{
NSString *ddir;
NSString *sdir;
NSString *file;
NSString *generated;
BOOL isSource = [arg hasSuffix: @".m"];
NSString *arg = [args objectAtIndex: i];
file = [[arg lastPathComponent] stringByDeletingPathExtension];
if (isSource == YES)
if ([arg hasPrefix: @"-"])
{
sdir = arg;
i++; // Skip next value ... it is a default.
}
else
else if ([arg hasSuffix: @".h"] == YES
|| [arg hasSuffix: @".m"] == YES
|| [arg hasSuffix: @".gsdoc"]== YES)
{
if (sourceDirectory == nil)
NSString *gsdocfile;
NSString *htmlfile;
NSString *hfile;
NSString *sfile;
NSString *ddir;
NSString *hdir;
NSString *sdir;
NSString *file;
NSString *generated;
BOOL isSource = [arg hasSuffix: @".m"];
BOOL isDocumentation = [arg hasSuffix: @".gsdoc"];
file = [[arg lastPathComponent] stringByDeletingPathExtension];
hdir = [arg stringByDeletingLastPathComponent];
if ([hdir length] == 0)
{
sdir = [arg stringByDeletingLastPathComponent];
hdir = headerDirectory;
sdir = sourceDirectory;
}
else if ([hdir isAbsolutePath] == YES)
{
sdir = hdir;
}
else
{
sdir = sourceDirectory;
hdir = [headerDirectory stringByAppendingPathComponent: hdir];
sdir = [sourceDirectory stringByAppendingPathComponent: sdir];
}
sdir = [sdir stringByAppendingPathComponent: file];
sdir = [sdir stringByAppendingPathExtension: @"m"];
}
if (documentationDirectory == nil)
{
ddir = [arg stringByDeletingLastPathComponent];
}
else
{
ddir = documentationDirectory;
}
ddir = [ddir stringByAppendingPathComponent: file];
ddir = [ddir stringByAppendingPathExtension: @"gsdoc"];
if ([mgr isReadableFileAtPath: arg] == NO)
{
NSLog(@"No readable header at '%@' ... skipping", arg);
continue;
}
[parser reset];
[parser parseFile: arg isSource: NO];
hfile = [hdir stringByAppendingPathComponent: file];
hfile = [hfile stringByAppendingPathExtension: @"h"];
sfile = [sdir stringByAppendingPathComponent: file];
sfile = [sfile stringByAppendingPathExtension: @"m"];
gsdocfile = [ddir stringByAppendingPathComponent: file];
gsdocfile = [gsdocfile stringByAppendingPathExtension: @"gsdoc"];
htmlfile = [ddir stringByAppendingPathComponent: file];
htmlfile = [htmlfile stringByAppendingPathExtension: @"html"];
if ([mgr isReadableFileAtPath: sdir] == YES)
{
[parser parseFile: sdir isSource: YES];
}
[[parser info] setObject: file forKey: @"base"];
if (up == nil)
{
up = file;
}
else
{
[[parser info] setObject: up forKey: @"up"];
}
if (prev != nil)
{
[[parser info] setObject: prev forKey: @"prev"];
}
prev = file;
if (i < [args count] - 1)
{
unsigned j = i + 1;
while (j < [args count])
if (pass == 0)
{
NSString *name = [args objectAtIndex: j++];
/*
* We perform parsing of source code in pass 0 only.
*/
[parser reset];
if ([name hasSuffix: @".h"] || [name hasSuffix: @".m"])
if (isSource == NO && isDocumentation == NO)
{
name = [[name lastPathComponent]
stringByDeletingPathExtension];
[[parser info] setObject: name forKey: @"next"];
break;
/*
* Try to parse header to see what needs documenting.
*/
if ([mgr isReadableFileAtPath: hfile] == NO)
{
NSLog(@"No readable header at '%@' ... skipping",
hfile);
continue;
}
if (declared != nil)
{
[parser setDeclared:
[declared stringByAppendingPathComponent:
[hfile lastPathComponent]]];
}
[parser parseFile: hfile isSource: NO];
}
else if (isSource == YES)
{
/*
* Try to parse source *as-if-it-was-a-header*
* to see what needs documenting.
*/
if ([mgr isReadableFileAtPath: sfile] == NO)
{
NSLog(@"No readable source at '%@' ... skipping",
sfile);
continue;
}
if (declared != nil)
{
[parser setDeclared:
[declared stringByAppendingPathComponent:
[sfile lastPathComponent]]];
}
[parser parseFile: sfile isSource: NO];
}
if (isDocumentation == NO)
{
/*
* If we can read a source file, parse it for any
* additional information on items found in the header.
*/
if ([mgr isReadableFileAtPath: sfile] == YES)
{
[parser parseFile: sfile isSource: YES];
}
/*
* Set up linkage for this file.
*/
[[parser info] setObject: file forKey: @"base"];
if (up == nil)
{
up = file;
}
else
{
[[parser info] setObject: up forKey: @"up"];
}
if (prev != nil)
{
[[parser info] setObject: prev forKey: @"prev"];
}
prev = file;
if (i < [args count] - 1)
{
unsigned j = i + 1;
while (j < [args count])
{
NSString *name = [args objectAtIndex: j++];
if ([name hasSuffix: @".h"]
|| [name hasSuffix: @".m"]
|| [name hasSuffix: @".gsdoc"])
{
name = [[name lastPathComponent]
stringByDeletingPathExtension];
[[parser info] setObject: name
forKey: @"next"];
break;
}
}
}
generated = [output output: [parser info]];
if ([generated writeToFile: gsdocfile
atomically: YES] == NO)
{
NSLog(@"Sorry unable to write %@", gsdocfile);
}
}
}
}
generated = [output output: [parser info]];
if ([mgr isReadableFileAtPath: gsdocfile] == YES)
{
CREATE_AUTORELEASE_POOL(pool);
GSXMLParser *parser;
AGSIndex *locRefs;
AGSHtml *html;
NSString *result;
if ([generated writeToFile: ddir atomically: YES] == NO)
{
NSLog(@"Sorry unable to write %@", ddir);
parser = [GSXMLParser parserWithContentsOfFile: gsdocfile];
[parser substituteEntities: YES];
[parser doValidityChecking: YES];
if ([parser parse] == NO)
{
NSLog(@"WARNING %@ is not a valid document", gsdocfile);
}
if (![[[[parser doc] root] name] isEqualToString: @"gsdoc"])
{
NSLog(@"not a gsdoc document - because name node is %@",
[[[parser doc] root] name]);
return 1;
}
locRefs = AUTORELEASE([AGSIndex new]);
[locRefs makeRefs: [[parser doc] root]];
if (pass == 1)
{
/*
* We only perform final outpu in pass 1
*/
html = AUTORELEASE([AGSHtml new]);
[html setGlobalRefs: prjRefs];
[html setLocalRefs: locRefs];
result = [html outputDocument: [[parser doc] root]];
if ([result writeToFile: htmlfile atomically: YES] == NO)
{
NSLog(@"Sorry unable to write %@", htmlfile);
}
}
else
{
/*
* We only accumulate index info in pass 0
*/
[indexer mergeRefs: [locRefs refs]];
[prjRefs mergeRefs: [locRefs refs]];
}
RELEASE(pool);
}
else if (isDocumentation)
{
NSLog(@"No readable documentation at '%@' ... skipping",
gsdocfile);
}
}
else
{
CREATE_AUTORELEASE_POOL(pool);
GSXMLParser *parser;
AGSIndex *locRefs;
AGSHtml *html;
parser = [GSXMLParser parserWithContentsOfFile: ddir];
[parser substituteEntities: YES];
[parser doValidityChecking: YES];
if ([parser parse] == NO)
{
NSLog(@"WARNING %@ did not produce a valid document", arg);
}
if (![[[[parser doc] root] name] isEqualToString: @"gsdoc"])
{
NSLog(@"not a gsdoc document - because name node is %@",
[[[parser doc] root] name]);
return 1;
}
locRefs = AUTORELEASE([AGSIndex new]);
[locRefs makeRefs: [[parser doc] root]];
html = AUTORELEASE([AGSHtml new]);
[html setLocalRefs: indexer];
[html outputDocument: [[parser doc] root]];
[indexer mergeRefs: [locRefs refs]];
RELEASE(pool);
NSLog(@"Unknown argument '%@' ... ignored", arg);
}
}
else if ([arg hasSuffix: @".gsdoc"] == YES)
{
CREATE_AUTORELEASE_POOL(pool);
GSXMLParser *parser;
AGSHtml *html;
RELEASE(arp);
}
parser = [GSXMLParser parserWithContentsOfFile: arg];
[parser substituteEntities: YES];
[parser doValidityChecking: YES];
if ([parser parse] == NO)
{
NSLog(@"WARNING %@ did not produce a valid document", arg);
}
if (![[[[parser doc] root] name] isEqualToString: @"gsdoc"])
{
NSLog(@"not a gsdoc document - because name node is %@",
[[[parser doc] root] name]);
return 1;
}
html = AUTORELEASE([AGSHtml new]);
NSLog(@"%@", [html outputDocument: [[parser doc] root]]);
RELEASE(pool);
}
else
{
NSLog(@"Unknown argument '%@' ... ignored", arg);
}
/*
* Save references.
*/
refsFile = [documentationDirectory stringByAppendingPathComponent:
projectName];
refsFile = [refsFile stringByAppendingPathExtension: @"gsdocidx"];
if ([[prjRefs refs] writeToFile: refsFile atomically: YES] == NO)
{
NSLog(@"Sorry unable to write %@", refsFile);
}
RELEASE(pool);