libs-base/Tools/gsdoc.m
CaS 4aabe798ba Some string mnethod tidyups
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@14448 72102866-910b-0410-8b05-ffd578937521
2002-09-15 18:26:56 +00:00

5042 lines
124 KiB
Objective-C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* This tool converts documentation in gsdoc format to another format
At present (and for the forseeable future), the only format supported
is HTML.
Copyright (C) 2000 Free Software Foundation, Inc.
Written by: Richard Frith-Macdonald <richard@brainstorm.co.uk>
Created: February 2000
This file is part of the GNUstep Project
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
You should have received a copy of the GNU General Public
License along with this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
Before doing anything else - you need to install the Gnome xml parser library!
You need at least version 2.0.0 of the parser.
You can find out how to get this from http: //www.xmlsoft.org
Once you have installed the xml parser library, you can build gsdoc
and install it.
Run gsdoc giving it the name of a gsdoc file as an argument, and it will
produce an html output file.
This is an alpha release of the software - please send fixes and improvements
to rfm@gnu.org
Volunteers to write gsdoc->info or gsdoc->TeX or any other translators are
very welcome.
*/
/*
Parameters:
--makeRefs = ReferencesFileName
With this option, gsdoc reads gsdoc files and creates
ReferencesFileName.gsdocrefs files which can be used
as --refs to make links between elements
--projectName = TheProjectName
Sets the project name to "TheProjectName"
It is used for index titles, ...
--refs = ARefFile (or --refs = ARefDirectory)
Use ARefFile.gsdocrefs (or files whith extensions .gsdocrefs
in ARefDirectory directory) as references files.
It enables you to make links between documentations
--makeIndex = MyIndexFileName
Create an index of the parsed files and save it as MyIndexName.gsdoc
You have to set --makeIndexTemplate option
--makeIndexTemplate = MyIndexTemplateFileName
The file used as index template for makeIndex option
--define-XXX = YYY
Used to define a constant named XXX with value YYY
in .gsdoc file, all [[infoDictionary.XXX]] texts are replaced with YYY
--verbose = X
Level of traces from 0 to ...
--location = file: //usr/doc/gnustep/MyProject
(or --location = http: //www.gnustep.org/gnustep/MyProject)
Location of the installed documentation (it helps to make links
between projects)
file1 file2
.gsdoc files
*/
#include <config.h>
#include <Foundation/Foundation.h>
#ifdef HAVE_LIBXML
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <libxml/parser.h>
NSString *pathExtension_GSDocRefs = @"gsdocrefs";
NSString *pathExtension_GSDoc = @"gsdoc";
NSString *pathExtension_HTML = @"html";
int verbose = 0;
NSString *location = nil;
/*
* In text, replace keys from variables with their values
*variables is like something like this
* {
* "[[key1]]" = "value1";
* "[[key2]]" = "value2";
* }
*/
static NSString *
textByReplacingVariablesInText(NSString *text, NSDictionary *variables)
{
NSEnumerator *variablesEnum = [variables keyEnumerator];
id key = nil;
while ((key = [variablesEnum nextObject]) != nil)
{
id value = [[variables objectForKey: key] description];
text = [text stringByReplacingString: key withString: value];
}
return text;
}
/*
* GSDocParser
*/
@interface GSDocParser : NSObject
{
NSString *baseName;
NSString *currName;
NSString *fileName;
NSString *nextName; //"Next" Link filename
NSString *prevName; //"Previous" Link filename
NSString *upName; //"Up" Link filename
NSString *styleSheetURL; // Style sheet
NSMutableDictionary *indexes;
NSUserDefaults *defs;
NSFileManager *mgr;
xmlDocPtr doc;
}
- (NSString *) getProp: (const char *)name fromNode: (xmlNodePtr)node;
- (NSMutableDictionary *) indexForType: (NSString *)type;
- (id) initWithFileName: (NSString *)name;
- (NSString *) parseText: (xmlNodePtr)node;
- (NSString *) parseText: (xmlNodePtr)node end: (xmlNodePtr *)endNode;
@end
static xmlParserInputPtr
loader(const char *url, const char *eid, xmlParserCtxtPtr *ctxt)
{
extern xmlParserInputPtr xmlNewInputFromFile();
xmlParserInputPtr ret = 0;
if (url == 0)
{
url = "";
}
if (eid == 0)
{
ret = xmlNewInputFromFile(ctxt, url);
}
else if (strncmp(eid, "-//GNUstep//DTD ", 16) == 0)
{
char buf[BUFSIZ];
char *ptr;
NSString *name;
NSString *file;
strcpy(buf, &eid[16]);
for (ptr = buf; *ptr != '\0' && *ptr != '/'; ptr++)
{
if (*ptr == '.')
{
*ptr = '_';
}
else if (isspace(*ptr))
{
*ptr = '-';
}
}
*ptr = '\0';
name = [NSString stringWithCString: buf];
file = [NSBundle pathForGNUstepResource: name
ofType: @"dtd"
inDirectory: @"DTDs"];
if (file == nil)
{
NSLog(@"unable to find GNUstep DTD - '%@' for '%s'", name, eid);
}
else
{
ret = xmlNewInputFromFile(ctxt, [file cString]);
}
}
else
{
NSLog(@"don't know how to load entity '%s' id '%s'", url, eid);
}
return ret;
}
@implementation GSDocParser
- (void) dealloc
{
if (doc != 0)
{
xmlFreeDoc(doc);
doc = 0;
}
DESTROY(defs);
DESTROY(indexes);
DESTROY(baseName);
DESTROY(nextName);
DESTROY(prevName);
DESTROY(upName);
DESTROY(styleSheetURL);
DESTROY(currName);
DESTROY(fileName);
[super dealloc];
}
- (NSString *) getProp: (const char *)name fromNode: (xmlNodePtr)node
{
xmlAttrPtr attr = node->properties;
while (attr != 0 && strcmp(attr->name, name) != 0)
{
attr = attr->next;
}
if (attr == 0 || attr->children == 0)
{
return nil;
}
return [self parseText: attr->children];
}
- (NSMutableDictionary *) indexForType: (NSString *)type
{
NSMutableDictionary *dict = [indexes objectForKey: type];
if (dict == nil)
{
dict = [NSMutableDictionary new];
[indexes setObject: dict forKey: type];
RELEASE(dict);
}
return dict;
}
- (id) initWithFileName: (NSString *)name
{
if ((self = [self init]) != nil)
{
xmlNodePtr cur;
extern int xmlDoValidityCheckingDefaultValue;
xmlExternalEntityLoader ldr;
NSString *s;
NSFileManager *m;
xmlKeepBlanksDefault(0);
xmlDoValidityCheckingDefaultValue = 1;
ldr = xmlGetExternalEntityLoader();
if (ldr != (xmlExternalEntityLoader)loader)
{
xmlSetExternalEntityLoader((xmlExternalEntityLoader)loader);
}
/*
* Ensure we have a valid file name.
*/
s = [name pathExtension];
m = [NSFileManager defaultManager];
if ([m fileExistsAtPath: name] == NO && [s length] == 0)
{
s = [name stringByAppendingPathExtension: pathExtension_GSDoc];
if ([m fileExistsAtPath: s] == NO)
{
NSLog(@"No such document - %@", name);
[self dealloc];
return nil;
}
name = s;
}
fileName = [name copy];
/*
* Build an XML tree from the file.
*/
doc = xmlParseFile([name cString]);
if (doc == NULL)
{
NSLog(@"unparseable document - %@", fileName);
[self dealloc];
return nil;
}
/*
* Check that the document is of the right kind
*/
cur = doc->children;
if (cur == NULL)
{
NSLog(@"empty document - %@", fileName);
[self dealloc];
return nil;
}
cur = cur->next;
if (strcmp(cur->name, "gsdoc") != 0)
{
NSLog(@"document of the wrong type, root node != gsdoc");
[self dealloc];
return nil;
}
baseName = [self getProp: "base" fromNode: cur];
if (baseName == nil)
{
//baseName = @"gsdoc";
ASSIGN(baseName, [fileName stringByDeletingPathExtension]);
}
else
{
RETAIN(baseName);
}
nextName = RETAIN([self getProp: "next" fromNode: cur]);
prevName = RETAIN([self getProp: "prev" fromNode: cur]);
upName = RETAIN([self getProp: "up" fromNode: cur]);
styleSheetURL = RETAIN([self getProp: "stylesheeturl" fromNode: cur]);
defs = RETAIN([NSUserDefaults standardUserDefaults]);
s = [defs stringForKey: @"BaseName"];
if (s != nil)
{
ASSIGN(baseName, s);
}
currName = [baseName copy];
indexes = [NSMutableDictionary new];
}
return self;
}
- (NSString *) parseText: (xmlNodePtr)node
{
xmlNodePtr endNode;
NSString *result;
result = [self parseText: node end: &endNode];
if (endNode != 0)
{
NSLog(@"Unexpected node type in text node - %d", endNode->type);
result = nil;
}
return result;
}
- (NSString *) parseText: (xmlNodePtr)node end: (xmlNodePtr *)endNode
{
return nil;
}
@end
@interface GSDocHtml : GSDocParser
{
NSMutableDictionary *refToFile;
NSMutableArray *contents;
NSMutableArray *footnotes;
unsigned labelIndex;
unsigned footnoteIndex;
unsigned contentsIndex;
NSString *projectName;
NSMutableDictionary *fileReferences;
NSMutableDictionary *generalReferences;
NSMutableDictionary *variablesDictionary;
NSString *currentClassName;
NSString *currentCategoryName;
NSString *currentProtocolName;
NSString *currentEOModel;
NSString *currentEOEntity;
NSString *currentEORelationship;
NSString *currentEORelationshipDestinationEntity;
NSArray *typesTypes;
NSArray *classesTypes;
NSArray *protocolsTypes;
NSArray *filesTypes;
NSArray *adaptorsTypes;
NSArray *EOModelsTypes;
NSArray *EOEntitiesTypes;
NSArray *EOClassPropertiesTypes;
NSArray *EORelationshipsTypes;
BOOL writeFlag;
BOOL processFileReferencesFlag;
}
- (NSString *) addLink: (NSString *)ref withText: (NSString *)text;
- (void) appendContents: (NSArray *)array toString: (NSMutableString *)text;
- (void) appendFootnotesToString: (NSMutableString *)text;
- (void) appendIndex: (NSString *)type toString: (NSMutableString *)text;
- (NSArray *) contents;
- (NSDictionary *) fileReferences;
- (NSDictionary *) findSymbolForKey: (NSString *)key
ofTypes: (NSArray *)types;
- (NSString *) linkForSymbol: (NSDictionary *)symbol
withText: (NSString *)text;
- (NSString *) linkForSymbolKey: (NSString *)key
ofTypes: (NSArray *)types
withText: (NSString *)text;
- (NSString *) linkedItem: (NSString *)item
ofTypes: (NSArray *)types;
- (NSString *) parseAuthor: (xmlNodePtr)node;
- (NSString *) parseBlock: (xmlNodePtr)node;
- (NSString *) parseBody: (xmlNodePtr)node;
- (NSString *) parseChapter: (xmlNodePtr)node contents: (NSMutableArray *)array;
- (NSString *) parseDef: (xmlNodePtr)node;
- (NSString *) parseDesc: (xmlNodePtr)node;
- (NSString *) parseDocument;
- (NSString *) parseEmbed: (xmlNodePtr)node;
- (NSString *) parseExample: (xmlNodePtr)node;
- (NSString *) parseFunction: (xmlNodePtr)node;
- (NSString *) parseHead: (xmlNodePtr)node;
- (NSString *) parseItem: (xmlNodePtr)node;
- (NSString *) parseList: (xmlNodePtr)node;
- (NSString *) parseVariable: (xmlNodePtr)node;
- (NSString *) parseIVariable: (xmlNodePtr)node;
- (NSString *) parseConstant: (xmlNodePtr)node;
- (NSString *) parseMacro: (xmlNodePtr)node;
- (NSString *) parseMethod: (xmlNodePtr)node;
- (NSArray *) parseStandards: (xmlNodePtr)node;
- (NSString *) parseText: (xmlNodePtr)node end: (xmlNodePtr *)endNode;
- (NSString *) parseDictionary: (xmlNodePtr)node;
- (NSString *) parseEOModel: (xmlNodePtr)node;
- (NSString *) parseEOEntity: (xmlNodePtr)node;
- (NSString *) parseEOAttribute: (xmlNodePtr)node;
- (NSString *) parseEOAttributeRef: (xmlNodePtr)node;
- (NSString *) parseEORelationship: (xmlNodePtr)node;
- (NSString *) parseEORelationshipComponent: (xmlNodePtr)node;
- (NSString *) parseEOJoin: (xmlNodePtr)node;
- (void) setEntry: (NSString *)entry
withExternalCompleteRef: (NSString *)externalCompleteRef
withExternalRef: (NSString *)externalRef
withRef: (NSString *)ref
inIndexOfType: (NSString *)type;
- (void) setGeneralReferences: (NSDictionary *)dict;
- (void) setProcessFileReferencesFlag: (BOOL)flag;
- (void) setProjectName: (NSString *)projectName;
- (void) setVariablesDictionary: (NSDictionary *)dict;
- (void) setWriteFlag: (BOOL)flag;
@end
// ====================================================================
@implementation GSDocHtml
- (id) init
{
if ((self = [super init]) == nil)
{
writeFlag = YES;
processFileReferencesFlag = YES;
typesTypes
= [NSArray arrayWithObjects: @"type", @"class", @"define", nil];
RETAIN(typesTypes);
classesTypes = [NSArray arrayWithObjects: @"class", @"define", nil];
RETAIN(classesTypes);
protocolsTypes = [NSArray arrayWithObjects: @"protocol", @"define", nil];
RETAIN(protocolsTypes);
filesTypes = [NSArray arrayWithObjects: @"file", nil];
RETAIN(filesTypes);
adaptorsTypes = [NSArray arrayWithObjects: @"db-adaptor", nil];
RETAIN(adaptorsTypes);
EOModelsTypes = [NSArray arrayWithObjects: @"EOModel", nil];
RETAIN(EOModelsTypes);
EOEntitiesTypes = [NSArray arrayWithObjects: @"EOEntity", nil];
RETAIN(EOEntitiesTypes);
EOClassPropertiesTypes
= [NSArray arrayWithObjects: @"EOAttribute", @"EORelationship", nil];
RETAIN(EOClassPropertiesTypes);
EORelationshipsTypes = [NSArray arrayWithObjects: @"EORelationship", nil];
RETAIN(EORelationshipsTypes);
}
return self;
}
- (NSString *) addLink: (NSString *)ref withText: (NSString *)text
{
NSString *file = [refToFile objectForKey: ref];
if (file == nil)
{
return [NSString stringWithFormat: @"<a href =\"#%@\">%@</a>", ref, text];
}
else
{
return [NSString stringWithFormat: @"<a href =\"%@#%@\">%@</a>",
file, ref, text];
}
}
- (void) appendContents: (NSArray *)array toString: (NSMutableString *)text
{
unsigned count = [array count];
if (count> 0)
{
unsigned i;
[text appendString: @"<ul>\r\n"];
for (i = 0; i < count; i++)
{
NSDictionary *dict = [array objectAtIndex: i];
NSString *title = [dict objectForKey: @"Title"];
NSString *ref = [dict objectForKey: @"Ref"];
NSArray *sub = [dict objectForKey: @"Contents"];
[text appendFormat: @"<li >%@\r\n",
[self addLink: ref withText: title]];
[self appendContents: sub toString: text];
}
[text appendString: @"</ul>\r\n"];
}
}
- (void) appendFootnotesToString: (NSMutableString *)text
{
unsigned count = [footnotes count];
if (count> 0)
{
unsigned i;
[text appendString: @"<h2>Footnotes </h2>\r\n"];
for (i = 0; i < count; i++)
{
NSString *note = [footnotes objectAtIndex: i];
NSString *ref = [NSString stringWithFormat: @"foot-%u", i];
[text appendFormat:
@"<a name =\"%@\">footnote %u </a> -\r\n", ref, i];
[text appendString: note];
[text appendString: @"<hr>\r\n"];
}
}
}
- (void) appendIndex: (NSString *)type toString: (NSMutableString *)text
{
NSDictionary *dict = [self indexForType: type];
NSEnumerator *enumerator;
NSArray *keys;
NSString *key;
keys = [dict keysSortedByValueUsingSelector: @selector(compare:)];
enumerator = [keys objectEnumerator];
[text appendString: @"<ul>\r\n"];
while ((key = [enumerator nextObject]) != nil)
{
NSString *name = [dict objectForKey: key];
[text appendFormat: @"<li >%@\r\n",
[self addLink: key withText: name]];
}
[text appendString: @"</ul>\r\n"];
}
- (void) dealloc
{
DESTROY(contents);
DESTROY(footnotes);
DESTROY(projectName);
DESTROY(fileReferences);
DESTROY(generalReferences);
DESTROY(variablesDictionary);
DESTROY(currentClassName);
DESTROY(currentCategoryName);
DESTROY(currentProtocolName);
DESTROY(currentEOModel);
DESTROY(currentEOEntity);
DESTROY(currentEORelationship);
DESTROY(currentEORelationshipDestinationEntity);
DESTROY(typesTypes);
DESTROY(classesTypes);
DESTROY(protocolsTypes);
DESTROY(filesTypes);
DESTROY(adaptorsTypes);
DESTROY(EOModelsTypes);
DESTROY(EOEntitiesTypes);
DESTROY(EOClassPropertiesTypes);
DESTROY(EORelationshipsTypes);
[super dealloc];
}
- (id) initWithFileName: (NSString *)name
{
self = [super initWithFileName: name];
if (self != nil)
{
mgr = RETAIN([NSFileManager defaultManager]);
refToFile = [NSMutableDictionary new];
contents = [NSMutableArray new];
footnotes = [NSMutableArray new];
if ([defs boolForKey: @"Monolithic"] == YES)
{
ASSIGN(currName,
[baseName stringByAppendingPathExtension: pathExtension_HTML]);
}
else
{
BOOL flag = NO;
if ([mgr fileExistsAtPath: baseName isDirectory: &flag] == NO)
{
if ([mgr createDirectoryAtPath: baseName attributes: nil] == NO)
{
NSLog(@"Unable to create directory '%@'", baseName);
RELEASE(self);
return nil;
}
}
else if (flag == NO)
{
NSLog(@"The file '%@' is not a directory", baseName);
RELEASE(self);
return nil;
}
ASSIGN(currName,
[baseName stringByAppendingPathComponent: @"index.html"]);
}
}
return self;
}
- (NSString *) parseAuthor: (xmlNodePtr)node
{
NSMutableString *text = [NSMutableString string];
NSString *name = [self getProp: "name" fromNode: node];
NSString *email = nil;
NSString *ename = nil;
NSString *url = nil;
NSString *desc = nil;
if (name == nil)
{
NSLog(@"Missing or illegal author name");
return nil;
}
NSDebugMLLog(@"debug", @"Start parsing Author name: %@", name);
node = node->children;
if (node != 0 && strcmp(node->name, "email") == 0)
{
email = [self getProp: "email" fromNode: node];
ename = [self parseText: node->children];
node = node->next;
}
if (node != 0 && strcmp(node->name, "url") == 0)
{
url = [self getProp: "url" fromNode: node];
node = node->next;
}
if (node != 0 && strcmp(node->name, "desc") == 0)
{
desc = [self parseDesc: node];
node = node->next;
}
[text appendString: @"<dt>"];
if (url == nil)
{
[text appendFormat: @"%@\r\n", name];
}
else
{
[text appendFormat: @"<a href =\"%@\">%@</a>\r\n", url, name];
}
if (email != nil)
{
if ([ename length] == 0)
{
ename = email;
}
[text appendFormat: @" (<a href =\"mailto: %@\"><code>%@</code></a>)\r\n",
email, ename];
}
[text appendString: @"<dd>\r\n"];
if (desc != nil)
{
[text appendString: desc];
}
NSDebugMLLog(@"debug", @"Stop parsing Author name: %@", name);
return text;
}
- (NSString *) parseBlock: (xmlNodePtr)node
{
if (node == 0)
{
NSLog(@"nul node when expecting block");
return nil;
}
NSDebugMLLog(@"debug", @"Start parsing block node->name: %s", node->name);
if (strcmp(node->name, "class") == 0
|| strcmp(node->name, "jclass") == 0
|| strcmp(node->name, "category") == 0
|| strcmp(node->name, "protocol") == 0
|| strcmp(node->name, "function") == 0
|| strcmp(node->name, "macro") == 0
|| strcmp(node->name, "type") == 0
|| strcmp(node->name, "variable") == 0
|| strcmp(node->name, "ivariable") == 0
|| strcmp(node->name, "constant") == 0
|| strcmp(node->name, "EOModel") == 0
|| strcmp(node->name, "EOEntity") == 0)
{
return [self parseDef: node];
}
if (strcmp(node->name, "list") == 0
|| strcmp(node->name, "enum") == 0
|| strcmp(node->name, "deflist") == 0
|| strcmp(node->name, "qalist") == 0)
{
return [self parseList: node];
}
if (strcmp(node->name, "p") == 0)
{
NSString *elem = [self parseText: node->children];
if (elem == nil)
{
return nil;
}
return [NSString stringWithFormat: @"<p>\r\n%@</p>\r\n", elem];
}
if (strcmp(node->name, "example") == 0)
{
return [self parseExample: node];
}
if (strcmp(node->name, "embed") == 0)
{
return [self parseEmbed: node];
}
if (strcmp(node->name, "dictionary") == 0)
{
return [self parseDictionary: node];
}
NSLog(@"unknown block type - %s", node->name);
return nil;
}
- (NSString *) parseBody: (xmlNodePtr)node
{
NSMutableString *text = [NSMutableString string];
#if GS_WITH_GC == 0
CREATE_AUTORELEASE_POOL(arp);
#endif
BOOL needContents = NO;
NSMutableArray *back = [NSMutableArray arrayWithCapacity: 2];
NSMutableArray *body = [NSMutableArray arrayWithCapacity: 4];
NSMutableArray *front = [NSMutableArray arrayWithCapacity: 2];
NSString *chapter;
unsigned count;
unsigned i;
NSDebugMLLog(@"debug", @"Start parsing body");
node = node->children;
/*
* Parse the front (unnumbered chapters) storing the html for each
*chapter as a separate string in the 'front' array.
*/
if (node != 0 && strcmp(node->name, "front") == 0)
{
xmlNodePtr f = node->children;
if (f != 0 && strcmp(f->name, "contents") == 0)
{
needContents = YES;
f = f->next;
}
while (f != 0 && strcmp(f->name, "chapter") == 0)
{
chapter = [self parseChapter: f contents: contents];
if (chapter == nil)
{
return nil;
}
[front addObject: chapter];
f = f->next;
}
node = node->next;
}
/*
* Parse the main body of the document, storing the html for each
*chapter as a separate string in the 'body' array.
*/
while (node != 0 && strcmp(node->name, "chapter") == 0)
{
chapter = [self parseChapter: node contents: contents];
if (chapter == nil)
{
return nil;
}
[body addObject: chapter];
node = node->next;
}
/*
* Parse the back unnumbered part of the document, storing the html for each
*chapter as a separate string in the 'back' array.
*/
if (node != 0 && strcmp(node->name, "back") == 0)
{
node = node->children;
while (node != 0 && strcmp(node->name, "chapter") == 0)
{
chapter = [self parseChapter: node contents: contents];
if (chapter == nil)
{
return nil;
}
[back addObject: chapter];
node = node->next;
}
}
/*
* Ok - parsed all the chapters of the document, so we have stored the
*document structure and can output a contents list.
*/
if (needContents)
{
[text appendString: @"<h1>Contents </h1>\r\n"];
[self appendContents: contents toString: text];
}
/*
* Now output all the chapters.
*/
count = [front count];
for (i = 0; i < count; i++)
{
chapter = [front objectAtIndex: i];
[text appendString: chapter];
}
count = [body count];
for (i = 0; i < count; i++)
{
chapter = [body objectAtIndex: i];
[text appendString: chapter];
}
count = [back count];
for (i = 0; i < count; i++)
{
chapter = [back objectAtIndex: i];
[text appendString: chapter];
}
/*
* Now output any indices requested.
*/
while (node != 0 && strcmp(node->name, "index") == 0)
{
NSString *type = [self getProp: "type" fromNode: node];
if (type != nil)
{
[text appendFormat: @"<h1>%@ index </h1>\r\n", type];
[self appendIndex: type toString: text];
}
node = node->next;
}
[self appendFootnotesToString: text];
[text appendString: @"</body>\r\n"];
NSDebugMLLog(@"debug", @"Stop parsing body");
RELEASE(arp);
return text;
}
- (NSString *) parseChapter: (xmlNodePtr)node contents: (NSMutableArray *)array
{
#if GS_WITH_GC == 0
CREATE_AUTORELEASE_POOL(arp);
#endif
NSMutableString *text = [NSMutableString string];
const char *type = node->name;
const char *next;
const char *h;
NSString *head;
NSString *ref;
NSString *nodeId = nil;
NSMutableDictionary *dict;
NSMutableArray *subs;
NSDebugMLLog(@"debug", @"Start parsing chapter");
nodeId = [self getProp: "id" fromNode: node];
ref = nodeId;
if (ref == nil)
{
ref = [NSString stringWithFormat: @"cont-%u", contentsIndex++];
}
node = node->children;
if (node == 0 || strcmp(node->name, "heading") != 0)
{
NSLog(@"%s without heading", type);
return nil;
}
head = [self parseText: node->children];
node = node->next;
if (strcmp(type, "chapter") == 0)
{
next = "section";
h = "h2";
}
else if (strcmp(type, "section") == 0)
{
next = "subsect";
h = "h3";
}
else if (strcmp(type, "subsect") == 0)
{
next = "subsubsect";
h = "h4";
}
else
{
next = "";
h = "h5";
}
if (!nodeId || ([nodeId length] > 0 && ![nodeId isEqual: @"#"]))
{
NSString *ref;
ref = [NSString stringWithFormat: @"%@##%@##%@",
projectName, currName, head];
[self setEntry: head
withExternalCompleteRef: ref
withExternalRef: head
withRef: ref
inIndexOfType: [NSString stringWithCString: type]];
}
/*
* Build content information and add it to the array at this level.
*/
subs = [NSMutableArray new];
dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
head, @"Title", ref, @"Ref", subs, @"Contents", nil];
RELEASE(subs);
[array addObject: dict];
/*
* Put heading in string.
*/
[text appendFormat: @"<%s><a name =\"%@\">%@</a></%s>\r\n", h, ref, head, h];
/*
* Try to parse block data up to the next subsection.
*/
while (node != 0 && strcmp(node->name, next) != 0)
{
NSString *block = [self parseBlock: node];
if (block == nil)
{
return nil;
}
[text appendString: block];
node = node->next;
}
while (node != 0 && strcmp(node->name, next) == 0)
{
NSString *chapter = [self parseChapter: node contents: subs];
if (chapter == nil)
{
return nil;
}
[text appendString: chapter];
node = node->next;
}
[dict setObject: text forKey: @"Text"];
NSDebugMLLog(@"debug", @"Stop parsing chapter");
RELEASE(arp);
return text;
}
- (NSString *) parseDef: (xmlNodePtr)node
{
NSMutableString *text = [NSMutableString string];
NSDebugMLLog(@"debug", @"Start parsing def");
if ((strcmp(node->name, "class") == 0)
|| (strcmp(node->name, "jclass") == 0))
{
NSString *className = [self getProp: "name" fromNode: node];
NSString *superName = [self getProp: "super" fromNode: node];
NSString *ref = [self getProp: "id" fromNode: node];
NSString *declared = nil;
NSString *desc = nil;
NSMutableArray *conform = [NSMutableArray array];
NSMutableArray *ivariables = [NSMutableArray array];
NSMutableArray *factoryMethods = [NSMutableArray array];
NSMutableArray *instanceMethods = [NSMutableArray array];
NSMutableArray *standards = [NSMutableArray array];
if (className == nil)
{
NSLog(@"Missing class name");
return nil;
}
if (ref == nil)
{
ref = className;
}
// We're working on "className"
ASSIGN(currentClassName, className);
/*
* Clear the methods index so it will contain only values from this class.
*/
[[self indexForType: @"method"] removeAllObjects];
node = node->children;
if (node != 0 && strcmp(node->name, "declared") == 0)
{
declared = [self parseText: node->children];
node = node->next;
}
while (node != 0 && strcmp(node->name, "conform") == 0)
{
NSString *s = [self parseText: node->children];
if (s != nil)
{
[conform addObject: s];
}
node = node->next;
}
if (node != 0 && strcmp(node->name, "desc") == 0)
{
desc = [self parseDesc: node];
node = node->next;
}
while (node != 0 && strcmp(node->name, "ivariable") == 0)
{
NSString *s = [self parseIVariable: node];
if (s != nil)
{
[ivariables addObject: s];
}
node = node->next;
}
while (node != 0 && ((strcmp(node->name, "method") == 0)
|| (strcmp(node->name, "jmethod") == 0)))
{
BOOL factoryMethod;
NSString *s;
factoryMethod = [[self getProp: "factory" fromNode: node] boolValue];
s = [self parseMethod: node];
if (s != nil)
{
if (factoryMethod)
[factoryMethods addObject: s];
else
[instanceMethods addObject: s];
}
node = node->next;
}
while (node != 0 && strcmp(node->name, "standard") == 0)
{
NSString *s = [self parseText: node->children];
if (s != nil)
{
[standards addObject: s];
}
node = node->next;
}
[self setEntry: className
withExternalCompleteRef: className
withExternalRef: className
withRef: ref
inIndexOfType: @"class"];
[text appendFormat: @"<h2><a name =\"%@\">%@</a></h2>\r\n",
ref, className];
if (declared != nil)
{
[text appendFormat: @"<p><b>Declared in: </b> %@</p>\r\n", declared];
}
if (superName != nil)
{
[text appendFormat: @"<p><b>Inherits from: </b> %@</p>\r\n",
[self linkedItem: superName ofTypes: classesTypes]];
}
if ([conform count] > 0)
{
unsigned i;
[text appendString: @"<p><b>Conforms to: </b>"];
for (i = 0; i < [conform count]; i++)
{
NSString *conformItem = [conform objectAtIndex: i];
conformItem = [self linkedItem: conformItem
ofTypes: protocolsTypes];
[text appendFormat: @"%@ %@\r\n", (i > 0 ? @", " : @""),
conformItem];
}
[text appendString: @"</p>\r\n"];
}
if ([standards count] > 0)
{
unsigned i;
[text appendFormat: @"<p><b>Standards: </b> %@\r\n",
[standards objectAtIndex: 0]];
for (i = 1; i < [standards count]; i++)
{
[text appendFormat: @", %@\r\n", [standards objectAtIndex: i]];
}
[text appendString: @"</p>\r\n"];
}
if (desc != nil)
{
[text appendFormat: @"<hr>\r\n%@\r\n", desc];
}
[text appendString: @"<h2>Instance Variables </h2>\r\n"];
[self appendIndex: @"ivariable" toString: text];
[text appendString: @"<h2>Methods </h2>\r\n"];
[self appendIndex: @"method" toString: text];
if ([ivariables count] > 0)
{
unsigned i;
[text appendString: @"<hr><h2>Instance Variables </h2>\r\n"];
for (i = 0; i < [ivariables count]; i++)
{
[text appendString: [ivariables objectAtIndex: i]];
}
}
if ([factoryMethods count] > 0)
{
unsigned i;
[text appendString: @"<hr><h2>Class Methods </h2>\r\n"];
for (i = 0; i < [factoryMethods count]; i++)
{
[text appendString: [factoryMethods objectAtIndex: i]];
}
}
if ([instanceMethods count] > 0)
{
unsigned i;
[text appendString: @"<hr><h2>Instances Methods </h2>\r\n"];
for (i = 0; i < [instanceMethods count]; i++)
{
[text appendString: [instanceMethods objectAtIndex: i]];
}
}
// We've finished working on "className"
ASSIGN(currentClassName, nil);
return text;
}
else if (strcmp(node->name, "category") == 0)
{
NSString *className = [self getProp: "class" fromNode: node];
NSString *catName = [self getProp: "name" fromNode: node];
NSString *ref = [self getProp: "id" fromNode: node];
NSString *declared = nil;
NSString *desc = nil;
NSMutableArray *conform = [NSMutableArray array];
NSMutableArray *factoryMethods = [NSMutableArray array];
NSMutableArray *instanceMethods = [NSMutableArray array];
NSMutableArray *standards = [NSMutableArray array];
NSString *name;
NSString *eref;
if (className == nil || catName == nil)
{
NSLog(@"Missing category or class name");
return nil;
}
name = [NSString stringWithFormat: @"%@ (%@)", className, catName];
if (ref == nil)
{
ref = name;
}
// We works on a class & category
ASSIGN(currentClassName, className);
ASSIGN(currentCategoryName, catName);
/*
* Clear the methods index so it will contain only values from this class.
*/
[[self indexForType: @"method"] removeAllObjects];
node = node->children;
if (node != 0 && strcmp(node->name, "declared") == 0)
{
declared = [self parseText: node->children];
node = node->next;
}
while (node != 0 && strcmp(node->name, "conform") == 0)
{
NSString *s = [self parseText: node->children];
if (s != nil)
{
[conform addObject: s];
}
node = node->next;
}
if (node != 0 && strcmp(node->name, "desc") == 0)
{
desc = [self parseDesc: node];
node = node->next;
}
while (node != 0 && strcmp(node->name, "method") == 0)
{
BOOL factoryMethod;
NSString *s;
factoryMethod = [[self getProp: "factory" fromNode: node] boolValue];
s = [self parseMethod: node];
if (s != nil)
{
if (factoryMethod)
[factoryMethods addObject: s];
else
[instanceMethods addObject: s];
}
node = node->next;
}
while (node != 0 && strcmp(node->name, "standard") == 0)
{
NSString *s = [self parseText: node->children];
if (s != nil)
{
[standards addObject: s];
}
node = node->next;
}
eref = [NSString stringWithFormat: @"%@(%@)", className, catName];
[self setEntry: name
withExternalCompleteRef: eref
withExternalRef: eref
withRef: ref
inIndexOfType: @"category"];
[text appendFormat: @"<h2>%@ <a name =\"%@\">(%@) </a></h2>\r\n",
[self linkedItem: className ofTypes: classesTypes], ref, catName];
if (declared != nil)
{
[text appendFormat: @"<p><b>Declared in: </b> %@</p>\r\n", declared];
}
if ([conform count] > 0)
{
unsigned i;
[text appendString: @"<p><b>Conforms to: </b>\r\n"];
for (i = 0; i < [conform count]; i++)
{
NSString *conformItem = [conform objectAtIndex: i];
conformItem = [self linkedItem: conformItem
ofTypes: protocolsTypes];
[text appendFormat: @"%@ %@\r\n", (i > 0 ? @", " : @""),
conformItem];
}
[text appendString: @"</p>\r\n"];
}
if ([standards count] > 0)
{
unsigned i;
[text appendFormat: @"<p><b>Standards: </b> %@\r\n",
[standards objectAtIndex: 0]];
for (i = 1; i < [standards count]; i++)
{
[text appendFormat: @", %@\r\n", [standards objectAtIndex: i]];
}
[text appendString: @"</p>\r\n"];
}
if (desc != nil)
{
[text appendFormat: @"<hr>\r\n%@\r\n", desc];
}
[text appendString: @"<h2>Methods </h2>\r\n"];
[self appendIndex: @"method" toString: text];
if ([factoryMethods count] > 0)
{
unsigned i;
[text appendString: @"<hr><h2>Class Methods </h2>\r\n"];
for (i = 0; i < [factoryMethods count]; i++)
{
[text appendString: [factoryMethods objectAtIndex: i]];
}
}
if ([instanceMethods count] > 0)
{
unsigned i;
[text appendString: @"<hr><h2>Instances Methods </h2>\r\n"];
for (i = 0; i < [instanceMethods count]; i++)
{
[text appendString: [instanceMethods objectAtIndex: i]];
}
}
// We've finished working on this class/category
ASSIGN(currentClassName, nil);
ASSIGN(currentCategoryName, nil);
return text;
}
else if (strcmp(node->name, "protocol") == 0)
{
NSString *protName = [self getProp: "name" fromNode: node];
NSString *ref = [self getProp: "id" fromNode: node];
NSString *declared = nil;
NSString *desc = nil;
NSMutableArray *methods = [NSMutableArray array];
NSMutableArray *standards = [NSMutableArray array];
if (protName == nil)
{
NSLog(@"Missing protocol name");
return nil;
}
if (ref == nil)
{
ref = protName;
}
// Works on "protName"
ASSIGN(currentProtocolName, protName);
/*
* Clear the methods index so it will contain only values from this class.
*/
[[self indexForType: @"method"] removeAllObjects];
node = node->children;
if (node != 0 && strcmp(node->name, "declared") == 0)
{
declared = [self parseText: node->children];
node = node->next;
}
if (node != 0 && strcmp(node->name, "desc") == 0)
{
desc = [self parseDesc: node];
node = node->next;
}
while (node != 0 && strcmp(node->name, "method") == 0)
{
NSString *s = [self parseMethod: node];
if (s != nil)
{
[methods addObject: s];
}
node = node->next;
}
while (node != 0 && strcmp(node->name, "standard") == 0)
{
NSString *s = [self parseText: node->children];
if (s != nil)
{
[standards addObject: s];
}
node = node->next;
}
[self setEntry: protName
withExternalCompleteRef: protName
withExternalRef: protName
withRef: ref
inIndexOfType: @"protocol"];
[text appendFormat: @"<h2><a name =\"%@\">%@ Protocol </a></h2>\r\n",
ref, protName];
if (declared != nil)
{
[text appendFormat: @"<p><b>Declared in: </b> %@</p>\r\n", declared];
}
if ([standards count] > 0)
{
unsigned i;
[text appendFormat: @"<p><b>Standards: </b> %@\r\n",
[standards objectAtIndex: 0]];
for (i = 1; i < [standards count]; i++)
{
[text appendFormat: @", %@\r\n", [standards objectAtIndex: i]];
}
[text appendString: @"</p>\r\n"];
}
if (desc != nil)
{
[text appendFormat: @"<hr>\r\n%@\r\n", desc];
}
[self appendIndex: @"method" toString: text];
if ([methods count] > 0)
{
unsigned i;
[text appendString: @"<hr>\r\n"];
for (i = 0; i < [methods count]; i++)
{
[text appendString: [methods objectAtIndex: i]];
}
}
// Finished working on "protName"
ASSIGN(currentProtocolName, nil);
return text;
}
else if (strcmp(node->name, "function") == 0)
{
return [self parseFunction: node];
}
else if (strcmp(node->name, "macro") == 0)
{
return [self parseMacro: node];
}
else if (strcmp(node->name, "type") == 0)
{
NSString *typeName = [self getProp: "name" fromNode: node];
NSString *ref = [self getProp: "id" fromNode: node];
NSString *declared = nil;
NSString *desc = nil;
NSString *spec = nil;
NSMutableArray *standards = [NSMutableArray array];
if (typeName == nil)
{
NSLog(@"Missing type name");
return nil;
}
if (ref == nil)
{
ref = typeName;
}
node = node->children;
if (node != 0 && strcmp(node->name, "typespec") == 0)
{
spec = [self parseText: node->children];
node = node->next;
}
if (spec == nil)
{
NSLog(@"Missing type specification");
return nil;
}
if (node != 0 && strcmp(node->name, "declared") == 0)
{
declared = [self parseText: node->children];
node = node->next;
}
if (node != 0 && strcmp(node->name, "desc") == 0)
{
desc = [self parseDesc: node];
node = node->next;
}
while (node != 0 && strcmp(node->name, "standard") == 0)
{
NSString *s = [self parseText: node->children];
if (s != nil)
{
[standards addObject: s];
}
node = node->next;
}
[self setEntry: typeName
withExternalCompleteRef: typeName
withExternalRef: typeName
withRef: ref inIndexOfType: @"type"];
[text appendFormat: @"<h3><a name =\"%@\">%@</a></h3>\r\n",
ref, typeName];
if (declared != nil)
{
[text appendFormat: @"<p><b>Declared in: </b> %@</p>\r\n", declared];
}
if ([standards count] > 0)
{
unsigned i;
[text appendFormat: @"<p><b>Standards: </b> %@\r\n",
[standards objectAtIndex: 0]];
for (i = 1; i < [standards count]; i++)
{
[text appendFormat: @", %@\r\n", [standards objectAtIndex: i]];
}
[text appendString: @"</p>\r\n"];
}
[text appendFormat: @"<b>typedef </b> %@ %@<br>\r\n", spec, typeName];
if (desc != nil)
{
[text appendFormat: @"\r\n%@\r\n <hr>\r\n", desc];
}
return text;
}
else if (strcmp(node->name, "variable") == 0)
{
return [self parseVariable: node];
}
else if (strcmp(node->name, "constant") == 0)
{
return [self parseConstant: node];
}
else if (strcmp(node->name, "EOModel") == 0)
{
return [self parseEOModel: node];
}
else if (strcmp(node->name, "EOEntity") == 0)
{
return [self parseEOEntity: node];
}
else
{
NSLog(@"Definition of unknown type - %s", node->name);
return nil;
}
}
- (NSString *) parseDesc: (xmlNodePtr)node
{
NSMutableString *text = [NSMutableString string];
NSDebugMLLog(@"debug", @"Start parsing desc");
node = node->children;
if (node == 0)
{
return @"";
}
while (node != 0)
{
if (strcmp(node->name, "list") == 0
|| strcmp(node->name, "enum") == 0
|| strcmp(node->name, "deflist") == 0
|| strcmp(node->name, "qalist") == 0)
{
[text appendString: [self parseList: node]];
}
else if (strcmp(node->name, "p") == 0)
{
NSString *elem = [self parseText: node->children];
if (elem != nil)
{
[text appendFormat: @"<p>\r\n%@</p>\r\n", elem];
}
}
else if (strcmp(node->name, "example") == 0)
{
[text appendString: [self parseExample: node]];
}
else if (strcmp(node->name, "embed") == 0)
{
[text appendString: [self parseEmbed: node]];
}
else
{
xmlNodePtr old = node;
[text appendString: [self parseText: node end: &node]];
/*
* If we found text, the node will have been advanced, but if
*it failed we need to advance ourselves.
*/
if (node == old)
node = node->next;
continue;
}
node = node->next;
}
return text;
}
- (NSString *) parseDocument
{
xmlNodePtr cur = doc->children->next->children;
NSString *text;
NSString *body;
NSString *head;
if (cur == 0 || strcmp(cur->name, "head") != 0)
{
NSLog(@"head missing from document");
return nil;
}
if ((head = [self parseHead: cur]) == nil)
{
return nil;
}
cur = cur->next;
if (cur == 0 || strcmp(cur->name, "body") != 0)
{
NSLog(@"body missing from document");
return nil;
}
if ((body = [self parseBody: cur]) == nil)
{
return nil;
}
text = [NSString stringWithFormat: @"<html>%@%@\r\n </html>\r\n", head, body];
// Don't write result if !writeFlag
if (writeFlag && [defs boolForKey: @"Monolithic"] == YES)
{
// Replace "UserVariables" in text
text = textByReplacingVariablesInText(text, variablesDictionary);
// Write the result
[text writeToFile: currName atomically: YES];
}
return text;
}
- (NSString *) parseEmbed: (xmlNodePtr)node
{
return @"An Embed";
}
- (NSString *) parseExample: (xmlNodePtr)node
{
NSMutableString *text = [NSMutableString string];
NSString *elem = [self parseText: node->children];
NSString *ref = [self getProp: "id" fromNode: node];
NSString *cap = [self getProp: "caption" fromNode: node];
NSDebugMLLog(@"debug", @"Start parsing example");
if (ref == nil)
{
ref = [NSString stringWithFormat: @"label-%u", labelIndex++];
}
if (elem == nil)
{
return nil;
}
if (cap == nil)
{
[self setEntry: @"example"
withExternalCompleteRef: nil
withExternalRef: nil
withRef: ref
inIndexOfType: @"label"];
[text appendFormat: @"<a name =\"%@\">example </a>\r\n", ref];
}
else
{
[self setEntry: cap
withExternalCompleteRef: nil
withExternalRef: nil
withRef: ref
inIndexOfType: @"label"];
[text appendFormat: @"<a name =\"%@\">%@</a>\r\n", ref, cap];
}
[text appendFormat: @"<pre>\r\n%@\r\n </pre>\r\n", elem];
return text;
}
- (NSString *) parseFunction: (xmlNodePtr)node
{
NSMutableString *text = [NSMutableString string];
NSString *ref = [self getProp: "id" fromNode: node];
NSString *type = [self getProp: "type" fromNode: node];
NSString *name = [self getProp: "name" fromNode: node];
NSString *desc = nil;
NSString *declared = nil;
NSMutableString *args = [NSMutableString stringWithString: @"("];
NSDebugMLLog(@"debug", @"Start parsing function");
if (ref == nil)
{
ref = [NSString stringWithFormat: @"function-%u", labelIndex++];
}
if (type == nil)
{
type = @"int";
}
//Avoid ((xxx))
else if ([type hasPrefix: @"("] && [type hasSuffix: @")"])
{
type = [[type stringByDeletingPrefix: @"("] stringByDeletingSuffix: @")"];
}
type = [self linkedItem: type ofTypes: typesTypes];
node = node->children;
while (node != 0 && strcmp(node->name, "arg") == 0)
{
NSString *arg = [self parseText: node->children];
NSString *typ = [self getProp: "type" fromNode: node];
if (arg == nil)
return nil;
if ([args length] > 1)
{
[args appendString: @", "];
}
if (typ != nil)
{
//Avoid ((xxx))
if ([typ hasPrefix: @"("] && [typ hasSuffix: @")"])
{
typ = [[typ stringByDeletingPrefix: @"("]
stringByDeletingSuffix: @")"];
}
typ = [self linkedItem: typ ofTypes: typesTypes];
[args appendString: typ];
[args appendString: @" "];
}
[args appendString: arg];
node = node->next;
}
if (node != 0 && strcmp(node->name, "vararg") == 0)
{
if ([args length] > 1)
{
[args appendString: @", ..."];
}
else
{
[args appendString: @"..."];
}
node = node->next;
}
[args appendString: @")"];
if (node != 0 && strcmp(node->name, "declared") == 0)
{
declared = [self parseText: node->children];
node = node->next;
}
if (node != 0)
{
if (strcmp(node->name, "desc") == 0)
{
desc = [self parseDesc: node];
}
else
{
NSLog(@"Unexpected node in function definition - %s", node->name);
return nil;
}
}
[self setEntry: name
withExternalCompleteRef: name
withExternalRef: name
withRef: ref
inIndexOfType: @"function"];
[text appendFormat: @"<h2><a name =\"%@\">%@</a></h2>\r\n", ref, name];
if (declared != nil)
{
[text appendFormat: @"<p><b>Declared in: </b> %@</p>\r\n", declared];
}
[text appendFormat: @"<b>Prototype: </b> %@ %@%@<br>\r\n", type, name, args];
if (desc != nil)
{
[text appendString: desc];
}
[text appendString: @"\r\n <hr>\r\n"];
return text;
}
- (NSString *) parseHead: (xmlNodePtr)node
{
NSMutableString *text = [NSMutableString string];
NSString *abstract;
NSString *title;
NSString *copyright;
NSString *date;
NSString *version;
BOOL hadAuthor = NO;
NSDebugMLLog(@"debug", @"Start parsing head");
node = node->children;
if (node == 0 || strcmp(node->name, "title") != 0
|| (title = [self parseText: node->children]) == nil)
{
NSLog(@"head without title");
return nil;
}
[text appendFormat: @"<head>\r\n <title>%@</title>\r\n", title];
[self setEntry: title
withExternalCompleteRef: [currName stringByDeletingPathExtension]
withExternalRef: [currName stringByDeletingPathExtension]
withRef: [currName stringByDeletingPathExtension]
inIndexOfType: @"file"];
if ([styleSheetURL length] > 0)
{
[text appendFormat:
@"<link rel = stylesheet type =\"text/css\" href =\"%@\">\r\n",
styleSheetURL];
}
[text appendString: @"</head>\r\n"];
[text appendString: @"<body>\r\n"];
if ([prevName length] > 0)
{
//Avoid empty link
NSString *test;
test = textByReplacingVariablesInText(prevName, variablesDictionary);
if ([test length] > 0)
{
if ([[prevName pathExtension] isEqual: pathExtension_HTML] == YES)
{
[text appendFormat: @"<a href =\"%@\">[Previous] </a>\n",
prevName];
}
else
{
[text appendFormat: @"<a href =\"%@.html\">[Previous] </a>\n",
prevName];
}
}
}
if ([upName length] > 0)
{
NSString *test;
test = textByReplacingVariablesInText(upName, variablesDictionary);
if ([test length] > 0)
{
if ([[upName pathExtension] isEqual: pathExtension_HTML] == YES)
{
[text appendFormat: @"<a href =\"%@\">[Up] </a>\n", upName];
}
else
{
[text appendFormat: @"<a href =\"%@.html\">[Up] </a>\n", upName];
}
}
}
if ([nextName length] > 0)
{
//Avoid empty link
NSString *test;
test = textByReplacingVariablesInText(nextName, variablesDictionary);
if ([test length] > 0)
{
if ([[nextName pathExtension] isEqual: pathExtension_HTML] == YES)
{
[text appendFormat: @"<a href =\"%@\">[Next] </a>\n", nextName];
}
else
{
[text appendFormat: @"<a href =\"%@.html\">[Next] </a>\n",
nextName];
}
}
}
[text appendFormat: @"<h1>%@</h1>\r\n", title];
node = node->next;
while (node != 0 && strcmp(node->name, "author") == 0)
{
NSString *author = [self parseAuthor: node];
if (author == nil)
{
return nil;
}
if (hadAuthor == NO)
{
hadAuthor = YES;
[text appendString: @"<h3>Authors </h3>\r\n <dl>\r\n"];
}
[text appendString: author];
node = node->next;
}
if (hadAuthor == YES)
{
[text appendString: @"</dl>\r\n"];
}
if (node != 0 && strcmp(node->name, "version") == 0)
{
version = [self parseText: node->children];
node = node->next;
[text appendFormat: @"<p>Version: %@</p>\r\n", version];
}
if (node != 0 && strcmp(node->name, "date") == 0)
{
date = [self parseText: node->children];
node = node->next;
[text appendFormat: @"<p>Date: %@</p>\r\n", date];
}
if (node != 0 && strcmp(node->name, "abstract") == 0)
{
abstract = [self parseText: node->children];
node = node->next;
[text appendFormat: @"<blockquote>%@</blockquote>\r\n", abstract];
}
if (node != 0 && strcmp(node->name, "copy") == 0)
{
copyright = [self parseText: node->children];
node = node->next;
[text appendFormat: @"<p>Copyright: %@</p>\r\n", copyright];
}
return text;
}
- (NSString *) parseItem: (xmlNodePtr)node
{
NSMutableString *text = [NSMutableString string];
NSDebugMLLog(@"debug", @"Start parsing item");
node = node->children;
while (node != 0)
{
BOOL step = YES;
if (strcmp(node->name, "class") == 0
|| strcmp(node->name, "category") == 0
|| strcmp(node->name, "protocol") == 0
|| strcmp(node->name, "function") == 0
|| strcmp(node->name, "macro") == 0
|| strcmp(node->name, "type") == 0
|| strcmp(node->name, "variable") == 0
|| strcmp(node->name, "ivariable") == 0
|| strcmp(node->name, "constant") == 0)
{
[text appendString: [self parseDef: node]];
}
else if (strcmp(node->name, "list") == 0
|| strcmp(node->name, "enum") == 0
|| strcmp(node->name, "deflist") == 0
|| strcmp(node->name, "qalist") == 0)
{
[text appendString: [self parseList: node]];
}
else if (strcmp(node->name, "p") == 0)
{
NSString *elem = [self parseText: node->children];
if (elem != nil)
{
[text appendFormat: @"<p>\r\n%@</p>\r\n", elem];
}
}
else if (strcmp(node->name, "example") == 0)
{
[text appendString: [self parseExample: node]];
}
else if (strcmp(node->name, "embed") == 0)
{
[text appendString: [self parseEmbed: node]];
}
else
{
[text appendString: [self parseText: node end: &node]];
step = NO;
}
if (step == YES)
node = node->next;
}
return text;
}
- (NSString *) parseList: (xmlNodePtr)node
{
NSMutableString *text = [NSMutableString string];
if (strcmp(node->name, "list") == 0)
{
[text appendString: @"<ul>\r\n"];
node = node->children;
while (node != 0 && strcmp(node->name, "item") == 0)
{
[text appendFormat: @"<li >%@\r\n", [self parseItem: node]];
node = node->next;
}
[text appendString: @"</ul>\r\n"];
}
else if (strcmp(node->name, "enum") == 0)
{
[text appendString: @"<ol>\r\n"];
node = node->children;
while (node != 0 && strcmp(node->name, "item") == 0)
{
[text appendFormat: @"<li >%@\r\n", [self parseItem: node]];
node = node->next;
}
[text appendString: @"</ol>\r\n"];
}
else if (strcmp(node->name, "deflist") == 0)
{
[text appendString: @"<dl>\r\n"];
node = node->children;
while (node != 0)
{
if (strcmp(node->name, "term") == 0)
{
[text appendFormat: @"<dt>%@\r\n",
[self parseText: node->children]];
node = node->next;
}
if (node == 0 || strcmp(node->name, "desc") != 0)
{
NSLog(@"term without desc");
return nil;
}
[text appendFormat: @"<dd>%@\r\n", [self parseDesc: node]];
node = node->next;
}
[text appendString: @"</dl>\r\n"];
}
else
{
[text appendString: @"<dl>\r\n"];
node = node->children;
while (node != 0)
{
if (strcmp(node->name, "question") == 0)
{
[text appendFormat: @"<dt>%@\r\n",
[self parseText: node->children]];
node = node->next;
}
if (node == 0 || strcmp(node->name, "answer") != 0)
{
NSLog(@"term without desc");
return nil;
}
[text appendFormat: @"<dt>%@\r\n", [self parseBlock: node->children]];
node = node->next;
}
[text appendString: @"</dl>\r\n"];
}
return text;
}
// Parse Variable, IVariable or constant
- (NSString *) parseVariable: (xmlNodePtr)variableNode
orConstant: (xmlNodePtr)constantNode
ofType: (NSString *)indexType
{
xmlNodePtr node = (variableNode ? variableNode : constantNode);
NSMutableString *text = [NSMutableString string];
NSString *name = [self getProp: "name" fromNode: node];
NSString *type
= variableNode ? [self getProp: "type" fromNode: node] : nil;
NSString *posttype
= variableNode ? [self getProp: "posttype" fromNode: node] : nil;
NSString *value = [self getProp: "value" fromNode: node];
NSString *role = [self getProp: "role" fromNode: node];
NSString *ref = [self getProp: "id" fromNode: node];
NSString *declared = nil;
NSString *desc = nil;
NSMutableArray *standards = [NSMutableArray array];
NSString *completeRefName = nil;
NSString *linkedType = nil;
NSDebugMLLog(@"debug", @"Start parsing variable/constant");
if (name == nil)
{
NSLog(@"Missing variable/constant name");
return nil;
}
if (variableNode!=NULL && type == nil)
{
NSLog(@"Missing variable type");
return nil;
}
if (type)
{
linkedType = [self linkedItem: type ofTypes: typesTypes];
}
if (ref == nil)
{
ref = name;
}
node = node->children;
if (node != 0 && strcmp(node->name, "declared") == 0)
{
declared = [self parseText: node->children];
node = node->next;
}
if (node != 0 && strcmp(node->name, "desc") == 0)
{
desc = [self parseDesc: node];
node = node->next;
}
while (node != 0 && strcmp(node->name, "standard") == 0)
{
NSString *s = [self parseText: node->children];
if (s != nil)
{
[standards addObject: s];
}
node = node->next;
}
if (currentClassName)
{
completeRefName
= [NSString stringWithFormat: @"%@::%@", currentClassName, name];
}
else
{
completeRefName = name;
}
[self setEntry: name
withExternalCompleteRef: completeRefName
withExternalRef: name
withRef: ref
inIndexOfType: indexType];
[text appendFormat: @"<h2><a name =\"%@\">%@</a></h2>\r\n", ref, name];
if (declared != nil)
{
[text appendFormat: @"<p><b>Declared in: </b> %@</p>\r\n", declared];
}
if ([standards count] > 0)
{
unsigned i;
[text appendFormat: @"<p><b>Standards: </b> %@\r\n",
[standards objectAtIndex: 0]];
for (i = 1; i < [standards count]; i++)
{
[text appendFormat: @", %@\r\n", [standards objectAtIndex: i]];
}
[text appendString: @"</p>\r\n"];
}
if ([role isEqual: @"except"])
{
[text appendString: @"<p>Exception name </p>\r\n"];
}
else if ([role isEqual: @"defaults"])
{
[text appendString: @"<p>Defaults system key </p>\r\n"];
}
else if ([role isEqual: @"notify"])
{
[text appendString: @"<p>Notification name </p>\r\n"];
}
else if ([role isEqual: @"key"])
{
[text appendString: @"<p>Dictionary key </p>\r\n"];
}
if (value == nil)
{
[text appendFormat: @"%@ <b>%@</b>%@<br>\r\n",
linkedType ? linkedType : @"", name, (posttype ? posttype : @"")];
}
else
{
[text appendFormat: @"%@ <b>%@</b>%@ = %@<br>\r\n",
linkedType ? linkedType : @"", name, (posttype ? posttype : @""),
value];
}
if (desc != nil)
{
[text appendFormat: @"\r\n%@\r\n", desc];
}
return text;
}
//Parse Variable
- (NSString *) parseVariable: (xmlNodePtr)node
{
NSDebugMLLog(@"debug", @"Start parsing variable");
return [self parseVariable: node
orConstant: NULL
ofType: @"variable"];
}
//Parse Instance Variable
- (NSString *) parseIVariable: (xmlNodePtr)node
{
NSDebugMLLog(@"debug", @"Start parsing ivar");
return [self parseVariable: node
orConstant: NULL
ofType: @"ivariable"];
}
// Parse Constant
- (NSString *) parseConstant: (xmlNodePtr)node
{
NSDebugMLLog(@"debug", @"Start parsing constant");
return [self parseVariable: NULL
orConstant: node
ofType: @"constant"];
}
- (NSString *) parseMacro: (xmlNodePtr)node
{
NSMutableString *text = [NSMutableString string];
NSString *ref = [self getProp: "id" fromNode: node];
NSString *name = [self getProp: "name" fromNode: node];
NSString *desc = nil;
NSString *declared = nil;
NSMutableString *args = [NSMutableString stringWithString: @"("];
NSDebugMLLog(@"debug", @"Start parsing macro");
if (ref == nil)
{
ref = [NSString stringWithFormat: @"macro-%u", labelIndex++];
}
node = node->children;
while (node != 0 && strcmp(node->name, "arg") == 0)
{
NSString *arg = [self parseText: node->children];
NSString *typ = [self getProp: "type" fromNode: node];
if (arg == nil)
{
return nil;
}
if ([args length] > 1)
{
[args appendString: @", "];
}
if (typ != nil)
{
[args appendString: typ];
[args appendString: @" "];
}
[args appendString: arg];
node = node->next;
}
if (node != 0 && strcmp(node->name, "vararg") == 0)
{
if ([args length] > 1)
{
[args appendString: @", ..."];
}
else
{
[args appendString: @"..."];
}
node = node->next;
}
if ([args length] == 1)
{
args = nil;
}
else
{
[args appendString: @")"];
}
if (node != 0 && strcmp(node->name, "declared") == 0)
{
declared = [self parseText: node->children];
node = node->next;
}
if (node != 0)
{
if (strcmp(node->name, "desc") == 0)
{
desc = [self parseDesc: node];
}
else
{
NSLog(@"Unexpected node in function definition - %s", node->name);
return nil;
}
}
[self setEntry: name
withExternalCompleteRef: name
withExternalRef: name
withRef: ref
inIndexOfType: @"macro"];
[text appendFormat: @"<h3><a name =\"%@\">%@</a></h3>\r\n", ref, name];
if (declared != nil)
{
[text appendFormat: @"<p><b>Declared in: </b> %@</p>\r\n", declared];
}
if (args == nil)
{
[text appendFormat: @"<b>Declaration: </b> %@<br>\r\n", name];
}
else
{
[text appendFormat: @"<b>Declaration: </b> %@%@<br>\r\n", name, args];
}
if (desc != nil)
{
[text appendString: desc];
}
[text appendString: @"\r\n <hr>\r\n"];
return text;
}
- (NSString *) parseMethod: (xmlNodePtr)node
{
NSMutableString *text = [NSMutableString string];
NSString *ref = [self getProp: "id" fromNode: node];
NSString *type = [self getProp: "type" fromNode: node];
NSString *over = [self getProp: "override" fromNode: node];
BOOL factory
= [[self getProp: "factory" fromNode: node] boolValue];
BOOL desInit
= [[self getProp: "init" fromNode: node] boolValue];
NSMutableString *lText = [NSMutableString string];
NSMutableString *sText = [NSMutableString string];
BOOL isJava = (strcmp(node->name, "jmethod") == 0);
NSString *desc = nil;
NSArray *standards = nil;
NSString *methodBlockName = nil;
NSDebugMLLog(@"debug", @"Start parsing method");
if (currentCategoryName)
{
NSAssert(currentClassName, @"No Class Name");
methodBlockName = currentClassName;
}
else if (currentClassName)
{
methodBlockName = currentClassName;
}
else if (currentProtocolName)
{
methodBlockName = currentProtocolName;
}
else
{
methodBlockName = @"unknown";
}
NSAssert(methodBlockName, @"No methodBlockName");
if (ref == nil)
{
ref = [NSString stringWithFormat: @"method-%u",
labelIndex++];
}
if (isJava)
{
NSMutableString *decl = [NSMutableString string];
NSMutableString *args = [NSMutableString stringWithString: @"("];
NSString *name = [self getProp: "name" fromNode: node];
if (factory)
{
[decl appendString: @"static "];
}
if (type == nil)
{
type = @"Object";
}
//Avoid ((xxx))
else if ([type hasPrefix: @"("] && [type hasSuffix: @")"])
{
type = [[type stringByDeletingPrefix: @"("]
stringByDeletingSuffix: @")"];
}
type = [self linkedItem: type ofTypes: typesTypes];
[decl appendString: type];
[decl appendString: @" "];
node = node->children;
while (node != 0 && strcmp(node->name, "arg") == 0)
{
NSString *arg = [self parseText: node->children];
NSString *typ = [self getProp: "type" fromNode: node];
if (arg == nil)
{
break;
}
if ([args length] > 1)
{
[args appendString: @", "];
}
if (typ != nil)
{
//Avoid ((xxx))
if ([typ hasPrefix: @"("] && [typ hasSuffix: @")"])
{
typ = [typ stringByDeletingPrefix: @"("];
typ = [typ stringByDeletingSuffix: @")"];
}
typ = [self linkedItem: typ ofTypes: typesTypes];
[args appendString: typ];
[args appendString: @" "];
}
[args appendString: arg];
node = node->next;
}
if (node != 0 && strcmp(node->name, "vararg") == 0)
{
if ([args length] > 1)
{
[args appendString: @", ..."];
}
else
{
[args appendString: @"..."];
}
node = node->next;
}
[args appendString: @")"];
[lText appendString: decl];
[lText appendString: @"<b>"];
[lText appendString: name];
[lText appendString: @"</b>"];
[lText appendString: args];
[sText appendString: decl];
[sText appendString: name];
[sText appendString: args];
}
else
{
if (factory)
{
[lText appendString: @"+ ("];
}
else
{
[lText appendString: @"- ("];
}
if (type == nil)
{
type = @"id";
}
//Avoid ((xxx))
else if ([type hasPrefix: @"("] && [type hasSuffix: @")"])
{
type = [type stringByDeletingPrefix: @"("];
type = [type stringByDeletingSuffix: @")"];
}
type = [self linkedItem: type ofTypes: typesTypes];
[lText appendString: type];
[lText appendString: @")"];
node = node->children;
while (node != 0 && strcmp(node->name, "sel") == 0)
{
NSString *sel = [self parseText: node->children];
if (sel == nil)
{
return nil;
}
[sText appendString: sel];
[lText appendFormat: @" <b>%@</b>", sel];
node = node->next;
if (node != 0 && strcmp(node->name, "arg") == 0)
{
NSString *arg = [self parseText: node->children];
NSString *typ = [self getProp: "type" fromNode: node];
if (arg == nil)
{
return nil;
}
if (typ != nil)
{
//Avoid ((xxx))
if ([typ hasPrefix: @"("] && [typ hasSuffix: @")"])
{
typ = [typ stringByDeletingPrefix: @"("];
typ = [typ stringByDeletingSuffix: @")"];
}
typ = [self linkedItem: typ ofTypes: typesTypes];
[lText appendFormat: @" (%@)%@", typ, arg];
}
else
{
[lText appendString: @" "];
[lText appendString: arg];
}
node = node->next;
if (node != 0 && strcmp(node->name, "vararg") == 0)
{
[lText appendString: @", ..."];
node = node->next;
break;
}
}
else
{
break; /* Just a selector */
}
}
}
if (node != 0 && strcmp(node->name, "desc") == 0)
{
desc = [self parseDesc: node];
node = node->next;
}
if (node != 0)
{
standards = [self parseStandards: node];
}
if (isJava)
{
NSString *eref;
eref = [NSString stringWithFormat: @"%@::%@", methodBlockName, sText];
[self setEntry: sText
withExternalCompleteRef: eref
withExternalRef: eref
withRef: ref
inIndexOfType: @"method"];
}
else
{
if (factory)
{
NSString *s = [@"+" stringByAppendingString: sText];
NSString *eref;
eref
= [NSString stringWithFormat: @"+%@::%@", methodBlockName, sText];
[self setEntry: s
withExternalCompleteRef: eref
withExternalRef: eref
withRef: ref
inIndexOfType: @"method"];
}
else
{
NSString *s = [@"-" stringByAppendingString: sText];
NSString *eref;
eref
= [NSString stringWithFormat: @"-%@::%@", methodBlockName, sText];
[self setEntry: s
withExternalCompleteRef: eref
withExternalRef: eref
withRef: ref
inIndexOfType: @"method"];
}
}
[text appendFormat: @"<h3><a name =\"%@\">%@</a></h3>\r\n", ref, sText];
if (desInit)
{
[text
appendString: @"<b>This is the designated initialiser </b><br>\r\n"];
}
[text appendFormat: @"%@;<br>\r\n", lText];
if ([over isEqual: @"subclass"])
{
[text appendString: @"Your subclass <em>must </em> override this "
@"abstract method.<br>\r\n"];
}
else if ([over isEqual: @"never"])
{
[text appendString: @"Your subclass must <em>not </em> override this "
@"method.<br>\r\n"];
}
if ([standards count] > 0)
{
unsigned i;
[text appendString: @"Standards: "];
for (i = 0; i < [standards count]; i++)
{
[text appendString: @" "];
[text appendString: [standards objectAtIndex: i]];
}
[text appendString: @"<br>\r\n"];
}
if (desc != nil)
{
[text appendString: desc];
}
[text appendString: @"\r\n <hr>\r\n"];
return text;
}
- (NSArray *) parseStandards: (xmlNodePtr)node
{
if (node != 0)
{
if (strcmp(node->name, "standards") == 0)
{
NSMutableArray *a = [NSMutableArray array];
node = node->children;
while (node != 0 && node->name != 0)
{
[a addObject: [NSString stringWithCString: node->name]];
node = node->next;
}
return a;
}
else
{
NSLog(@"Unexpected node in method definition - %s", node->name);
}
}
return nil;
}
- (NSString *) parseText: (xmlNodePtr)node end: (xmlNodePtr *)endNode
{
NSMutableString *text = [NSMutableString string];
NSDebugMLLog(@"debug", @"Start parsing text");
*endNode = node;
while (node != 0)
{
switch (node->type)
{
case XML_TEXT_NODE:
[text appendFormat: @"%s", node->content];
break;
case XML_ENTITY_REF_NODE:
[text appendFormat: @"%s", node->content];
break;
case XML_ELEMENT_NODE:
if (strcmp(node->name, "br") == 0)
{
[text appendString: @"<br>"];
}
else if (strcmp(node->name, "code") == 0
|| strcmp(node->name, "em") == 0
|| strcmp(node->name, "file") == 0
|| strcmp(node->name, "site") == 0
|| strcmp(node->name, "strong") == 0
|| strcmp(node->name, "var") == 0)
{
NSString *elem = [self parseText: node->children];
[text appendFormat: @"<%s>%@</%s>",
node->name, elem, node->name];
}
else if (strcmp(node->name, "entry") == 0
|| strcmp(node->name, "label") == 0)
{
NSString *elem;
NSString *ref;
elem = [self parseText: node->children];
ref = [self getProp: "id" fromNode: node];
if (ref == nil)
{
ref = [NSString stringWithFormat: @"label-%u",
labelIndex++];
}
[self setEntry: elem
withExternalCompleteRef:
[NSString stringWithFormat: @"%@::%@", @"***unknown", elem]
withExternalRef:
[NSString stringWithFormat: @"%@::%@", @"***unknown", elem]
withRef: ref
inIndexOfType: @"label"];
if (strcmp(node->name, "label") == 0)
{
[text appendFormat: @"<a name =\"%@\">%@</a>", ref, elem];
}
else
{
[text appendFormat: @"<a name =\"%@\"></a>", ref];
}
}
else if (strcmp(node->name, "footnote") == 0)
{
NSString *elem;
NSString *ref;
elem = [self parseText: node->children];
ref = [NSString stringWithFormat: @"foot-%u",
[footnotes count]];
[self setEntry: elem
withExternalCompleteRef:
[NSString stringWithFormat: @"%@::%@", @"***unknown", elem]
withExternalRef:
[NSString stringWithFormat: @"%@::%@", @"***unknown", elem]
withRef: ref
inIndexOfType: @"footnote"];
[footnotes addObject: elem];
[text appendFormat: @" %@ ",
[self addLink: ref withText: @"see footnote"]];
}
else if (strcmp(node->name, "ref") == 0)
{
NSString *elem = [self parseText: node->children];
// NSString *typ = [self getProp: "type" fromNode: node];
// NSString *cls = [self getProp: "class" fromNode: node];
NSString *ref = [self getProp: "id" fromNode: node];
if ([elem length] == 0)
{
elem = ref;
}
[text appendString: [self addLink: ref withText: elem]];
}
else if (strcmp(node->name, "uref") == 0)
{
NSString *elem = [self parseText: node->children];
NSString *ref = [self getProp: "url" fromNode: node];
if ([elem length] == 0)
{
elem = ref;
}
[text appendFormat: @"<a href =\"%@\">%@</a>", ref, elem];
}
else if (strcmp(node->name, "prjref") == 0)
{
NSString *elem = [self parseText: node->children];
NSString *prjName = [self getProp: "prjname" fromNode: node];
NSString *prjFile = [self getProp: "file" fromNode: node];
NSString *symbolKey = nil;
NSString *link = nil;
if ([prjName length]== 0)
{
prjName = projectName;
}
if ([elem length] == 0)
{
elem = prjName;
}
symbolKey = [NSString stringWithFormat: @"%@##%@",
prjName, ([prjFile length] ? prjFile : @"index")];
link = [self linkForSymbolKey: symbolKey
ofTypes: filesTypes
withText: elem];
[text appendString: link];
}
else
{
return text;
}
break;
default:
return text;
}
node = node->next;
*endNode = node;
}
return text;
}
- (NSString *) parseDictionaryItem: (xmlNodePtr)node
{
NSMutableString *text = [NSMutableString string];
NSString *key = [self getProp: "key" fromNode: node];
NSString *value = [self getProp: "value" fromNode: node];
NSDebugMLLog(@"debug", @"Start parsing dictionaryItem");
if (key == nil)
{
NSLog(@"dictionaryItem must have a key");
return nil;
}
[text appendFormat: @"<LI><b>%@</b> = ", key];
if (value == nil)
{
node = node->children;
while (node != 0)
{
value = [self parseBlock: node];
node = node->next;
}
}
[text appendFormat: @"%@</LI>\n", value];
return text;
}
- (NSString *) parseDictionary: (xmlNodePtr)node
{
NSMutableString *text = [NSMutableString string];
NSDebugMLLog(@"debug", @"Start parsing dictionary");
node = node->children;
[text appendString: @"<UL>\n"];
while (node && strcmp(node->name, "dictionaryItem") == 0)
{
NSString *itemString = [self parseDictionaryItem: node];
[text appendString: itemString];
node = node->next;
}
[text appendString: @"</UL>\n"];
return text;
}
- (NSString *) parseEOModel: (xmlNodePtr)node
{
NSMutableString *text = [NSMutableString string];
NSString *ref = [self getProp: "id" fromNode: node];
NSString *modelName = [self getProp: "name" fromNode: node];
NSString *version = [self getProp: "version" fromNode: node];
NSString *adaptorName = [self getProp: "adaptorName" fromNode: node];
NSString *adaptorClassName
= [self getProp: "adaptorClassName" fromNode: node];
NSString *desc = nil;
NSString *connectionDictionary = nil;
NSString *userDictionary = nil;
NSMutableArray *entities = [NSMutableArray array];
NSString *entitiesRefsList = nil;
NSDebugMLLog(@"debug", @"Start parsing EOModel");
if (modelName == nil)
{
NSLog(@"Missing model name");
return nil;
}
// We're working on EOModel
ASSIGN(currentEOModel, modelName);
if (ref == nil)
{
ref = modelName;
}
node = node->children;
if (node != 0 && strcmp(node->name, "EOConnectionDictionary") == 0)
{
connectionDictionary = [self parseDictionary: node];
node = node->next;
}
if (node != 0 && strcmp(node->name, "list") == 0)
{
entitiesRefsList = [self parseList: node];
node = node->next;
}
else
{
while (node && strcmp(node->name, "EOEntity") == 0)
{
NSString *s = [self parseEOEntity: node];
if (s != nil)
{
[entities addObject: s];
}
node = node->next;
}
}
if (node != 0 && strcmp(node->name, "EOUserDictionary") == 0)
{
userDictionary = [self parseDictionary: node];
node = node->next;
}
if (node != 0 && strcmp(node->name, "desc") == 0)
{
desc = [self parseDesc: node];
node = node->next;
}
[self setEntry: modelName
withExternalCompleteRef: modelName
withExternalRef: modelName
withRef: ref
inIndexOfType: @"EOModel"];
[text appendFormat: @"<h2><a name =\"%@\">%@</a></h2>\r\n",
ref, modelName];
if (version != nil)
{
[text appendFormat: @"<p><b>Version: </b> %@</p>\r\n", version];
}
if (adaptorName != nil)
{
[text appendFormat: @"<p><b>Adaptor: </b> %@</p>\r\n",
[self linkedItem: adaptorName ofTypes: adaptorsTypes]];
}
if (adaptorClassName != nil)
{
[text appendFormat: @"<p><b>Adaptor Class: </b> %@</p>\r\n",
[self linkedItem: adaptorClassName ofTypes: classesTypes]];
}
if (desc != nil)
{
[text appendFormat: @"<hr>\r\n%@\r\n", desc];
}
[text appendString: @"<h2>Entities </h2>\r\n"];
[self appendIndex: @"EOEntities"
toString: text];
[text appendString: @"<h2>User Dictionary </h2>\r\n"];
[self appendIndex: @"UserDictionary"
toString: text];
if (desc != nil)
{
[text appendFormat: @"<hr>\r\n%@\r\n", desc];
}
if (entitiesRefsList != nil)
{
[text appendString: @"<hr><h2>Entities </h2>\r\n"];
[text appendString: entitiesRefsList];
}
else
{
if ([entities count] > 0)
{
unsigned i = 0;
[text appendString: @"<hr><h2>Entities </h2>\r\n"];
for (i = 0; i < [entities count]; i++)
[text appendString: [entities objectAtIndex: i]];
}
}
if (userDictionary != nil)
{
[text appendFormat: @"<hr><h2>UserDictionary </h2>\r\n%@",
userDictionary];
}
// Stop working on EOModel
ASSIGN(currentEOModel, nil);
return text;
}
- (NSString *) parseEOEntity: (xmlNodePtr)node
{
NSMutableString *text = [NSMutableString string];
NSString *ref = [self getProp: "id" fromNode: node];
NSString *entityName = [self getProp: "name" fromNode: node];
NSString *externalName
= [self getProp: "externalName" fromNode: node];
NSString *className = [self getProp: "className" fromNode: node];
NSString *modelName = [self getProp: "modelName" fromNode: node];
NSString *isReadOnly
= [self getProp: "isReadOnly" fromNode: node];
NSString *desc = nil;
NSString *userDictionary = nil;
NSMutableArray *attributes = [NSMutableArray array];
NSMutableArray *attributesUsedForLocking = [NSMutableArray array];
NSMutableArray *classProperties = [NSMutableArray array];
NSMutableArray *primaryKeyAttributes = [NSMutableArray array];
NSMutableArray *relationships = [NSMutableArray array];
NSDebugMLLog(@"debug", @"Start parsing EOEntity");
if (!entityName)
{
NSLog(@"Missing entity name");
return nil;
}
// We're working on EOEntity
ASSIGN(currentEOEntity, entityName);
if (!ref)
{
ref = entityName;
}
node = node->children;
while (node != 0 && strcmp(node->name, "EOAttribute") == 0)
{
NSString *s = [self parseEOAttribute: node];
if (s != nil)
{
[attributes addObject: s];
}
node = node->next;
}
if (node != 0 && strcmp(node->name, "EOAttributesUsedForLocking") == 0)
{
xmlNodePtr attributeNode = node->children;
while (attributeNode != 0
&& strcmp(attributeNode->name, "EOAttributeRef") == 0)
{
NSString *s = [self parseEOAttributeRef: attributeNode];
if (s != nil)
{
[attributesUsedForLocking addObject: s];
}
attributeNode = attributeNode->next;
}
node = node->next;
}
if (node != 0 && strcmp(node->name, "EOClassProperties") == 0)
{
xmlNodePtr attributeNode = node->children;
while (attributeNode != 0
&& strcmp(attributeNode->name, "EOAttributeRef") == 0)
{
NSString *s = [self parseEOAttributeRef: attributeNode];
if (s != nil)
{
[classProperties addObject: s];
}
attributeNode = attributeNode->next;
}
node = node->next;
}
if (node != 0 && strcmp(node->name, "EOPrimaryKeyAttributes") == 0)
{
xmlNodePtr attributeNode = node->children;
while (attributeNode != 0
&& strcmp(attributeNode->name, "EOAttributeRef") == 0)
{
NSString *s = [self parseEOAttributeRef: attributeNode];
if (s != nil)
{
[primaryKeyAttributes addObject: s];
}
attributeNode = attributeNode->next;
}
node = node->next;
}
while (node != 0 && strcmp(node->name, "EORelationship") == 0)
{
NSString *s = [self parseEORelationship: node];
if (s != nil)
{
[relationships addObject: s];
}
node = node->next;
}
if (node != 0 && strcmp(node->name, "EOUserDictionary") == 0)
{
userDictionary = [self parseDictionary: node];
node = node->next;
}
if (node != 0 && strcmp(node->name, "desc") == 0)
{
desc = [self parseDesc: node];
node = node->next;
}
[self setEntry: entityName
withExternalCompleteRef: entityName
withExternalRef: entityName
withRef: ref
inIndexOfType: @"EOEntity"];
[text appendFormat: @"<hr><h2><a name =\"%@\">%@</a></h2>\r\n",
ref, entityName];
if (modelName != nil)
{
[text appendFormat: @"<p><b>Model: </b> %@</p>\r\n",
[self linkedItem: modelName ofTypes: EOModelsTypes]];
}
if (externalName != nil)
{
[text appendFormat: @"<p><b>External Name: </b> %@</p>\r\n",
externalName];
}
if (className != nil)
{
[text appendFormat: @"<p><b>Class: </b> %@</p>\r\n",
[self linkedItem: className ofTypes: classesTypes]];
}
if (isReadOnly != nil)
{
[text appendFormat: @"<p><b>Read Only: </b> %@</p>\r\n",
isReadOnly];
}
if (desc != nil)
{
[text appendFormat: @"<hr>\r\n%@\r\n", desc];
}
[text appendString: @"<hr>\r\n <UL>\r\n"];
if ([attributes count] > 0)
{
[text appendFormat:
@"<LI><A HREF=\"#%@__Attributes\">Attributes </A></LI>\r\n",
entityName];
}
if ([attributesUsedForLocking count] > 0)
{
[text appendFormat:
@"<LI><A HREF=\"#%@__AttributesUsedForLocking\">Attributes "
@"Used For Locking </A></LI>\r\n",
entityName];
}
if ([classProperties count] > 0)
{
[text appendFormat:
@"<LI><A HREF=\"#%@__ClassProperties\">Class Properties </A></LI>\r\n",
entityName];
}
if ([primaryKeyAttributes count] > 0)
{
[text appendFormat:
@"<LI><A HREF=\"#%@__PrimaryKeyAttributes\">Primary Key "
@"Attributes </A></LI>\r\n", entityName];
}
if ([relationships count] > 0)
{
[text appendFormat:
@"<LI><A HREF=\"#%@__Relationships\">Relationships </A></LI>\r\n",
entityName];
}
if (userDictionary != nil)
{
[text appendFormat:
@"<LI><A HREF=\"#%@__UserDictionary\">User Dictionary </A></LI>\r\n",
entityName];
}
[text appendString: @"</UL>\r\n"];
if ([attributes count] > 0)
{
unsigned i = 0;
[text appendFormat:
@"<hr><h3><A NAME=\"%@__Attributes\">Attributes </A></h3>\r\n",
entityName];
[text appendString:
@"<TABLE BORDER= 1>\n <TR><TH>Name </TH><TH>Entity </TH><TH>Class "
@"Name </TH><TH>Type </TH><TH>DB Column Name / Definition </TH><TH>DB "
@"Type </TH><TH>Properties </TH><TH>UserDictionary </TH><TH>"
@"Description </TH></TR>\r\n"];
for (i = 0; i < [attributes count]; i++)
{
[text appendFormat: @"<TR>%@</TR>\r\n",
[attributes objectAtIndex: i]];
}
[text appendString: @"</TABLE>\r\n"];
}
if ([attributesUsedForLocking count] > 0)
{
unsigned i = 0;
[text appendFormat: @"<hr><H3><A NAME=\"%@__AttributesUsedForLocking\">"
@"Attributes Used For Locking </A></H3>\r\n",
entityName];
[text appendString: @"<TABLE BORDER=\"1\">\r\n"];
for (i = 0; i < [attributesUsedForLocking count]; i++)
{
NSString *elem = [attributesUsedForLocking objectAtIndex: i];
[text appendFormat: @"<TR><TD>%@</TD></TR>\r\n",
[self linkForSymbolKey:
[NSString stringWithFormat: @"%@##%@", currentEOEntity, elem]
ofTypes: EOClassPropertiesTypes
withText: elem]];
}
[text appendString: @"</TABLE>\r\n"];
}
if ([classProperties count] > 0)
{
unsigned i = 0;
[text appendFormat:
@"<hr><H3><A NAME=\"%@__ClassProperties\">"
@"Class Properties </A></h3>\r\n",
entityName];
[text appendString: @"<TABLE BORDER=\"1\">\r\n"];
for (i = 0; i < [classProperties count]; i++)
{
NSString *elem = [classProperties objectAtIndex: i];
[text appendFormat: @"<TR><TD>%@</TD></TR>\r\n",
[self linkForSymbolKey:
[NSString stringWithFormat: @"%@##%@", currentEOEntity, elem]
ofTypes: EOClassPropertiesTypes
withText: elem]];
}
[text appendString: @"</TABLE>\r\n"];
}
if ([primaryKeyAttributes count] > 0)
{
unsigned i = 0;
[text appendFormat: @"<hr><H3><A NAME=\"%@__PrimaryKeyAttributes\">"
@"Primary Key Attributes </A></h3>\r\n",
entityName];
[text appendString: @"<TABLE BORDER=\"1\">\r\n"];
for (i = 0; i < [primaryKeyAttributes count]; i++)
{
NSString *elem = [classProperties objectAtIndex: i];
[text appendFormat: @"<TR><TD>%@</TD></TR>\r\n",
[self linkForSymbolKey:
[NSString stringWithFormat: @"%@##%@", currentEOEntity, elem]
ofTypes: EOClassPropertiesTypes
withText: elem]];
}
[text appendString: @"</TABLE>\r\n"];
}
if ([relationships count] > 0)
{
unsigned i = 0;
[text appendFormat: @"<hr><H3><A NAME=\"%@__Relationships\">"
@"Relationships </A></h3>\r\n", entityName];
[text appendString: @"<TABLE BORDER=\"1\">\r\n <TR><TH>Name </TH>"
@"<TH>Entity </TH><TH>Destination Entity </TH><TH>Properties </TH>"
@"<TH>Definition/Join(s) </TH><TH>User Dictionary </TH>"
@"<TH>Description </TH></TR>\r\n"];
for (i = 0; i < [relationships count]; i++)
{
[text appendFormat: @"<TR>%@</TR>\r\n",
[relationships objectAtIndex: i]];
}
[text appendString: @"</TABLE>\r\n"];
}
if (userDictionary != nil)
{
[text appendFormat: @"<hr><H3><A NAME=\"%@__UserDictionary\">"
@"User Dictionary </A></h3>\r\n",
entityName];
[text appendString: userDictionary];
}
// Stop working on EOEntity
ASSIGN(currentEOEntity, nil);
return text;
}
- (NSString *) parseEOAttribute: (xmlNodePtr)node
{
NSMutableString *text = [NSMutableString string];
NSString *ref = [self getProp: "id" fromNode: node];
NSString *columnName
= [self getProp: "columnName" fromNode: node];
NSString *definition
= [self getProp: "definition" fromNode: node];
NSString *externalType
= [self getProp: "externalType" fromNode: node];
NSString *attributeName = [self getProp: "name" fromNode: node];
NSString *valueClassName
= [self getProp: "valueClassName" fromNode: node];
NSString *valueType = [self getProp: "valueType" fromNode: node];
NSString *entityName
= [self getProp: "entityName" fromNode: node];
NSString *isReadOnly
= [self getProp: "isReadOnly" fromNode: node];
NSString *isDerived = [self getProp: "isDerived" fromNode: node];
NSString *isFlattened
= [self getProp: "isFlattened" fromNode: node];
NSString *desc = nil;
NSString *userDictionary = nil;
NSString *completeRef = nil;
NSDebugMLLog(@"debug", @"Start parsing EOAttribute");
if (!attributeName)
{
NSLog(@"Missing attribute name");
return nil;
}
completeRef
= [NSString stringWithFormat: @"%@##%@", currentEOEntity, attributeName];
if (ref == nil)
{
ref = completeRef;
}
node = node->children;
if (node && strcmp(node->name, "EOUserDictionary") == 0)
{
userDictionary = [self parseDictionary: node];
node = node->next;
}
if (node && strcmp(node->name, "desc") == 0)
{
desc = [self parseDesc: node];
node = node->next;
}
[self setEntry: attributeName
withExternalCompleteRef: completeRef
withExternalRef: completeRef
withRef: ref
inIndexOfType: @"EOAttribute"];
[text appendFormat: @"<TD><b><a name =\"%@\">%@</a></b></TD>",
ref, attributeName];
if (entityName)
{
[text appendFormat: @"<TD>%@</TD>",
[self linkedItem: entityName ofTypes: EOEntitiesTypes]];
}
else
{
[text appendString: @"<TD></TD>"];
}
if (valueClassName)
{
[text appendFormat: @"<TD>%@</TD>",
[self linkedItem: valueClassName ofTypes: classesTypes]];
}
else
{
[text appendString: @"<TD></TD>"];
}
if (valueType)
{
[text appendFormat: @"<TD>%@</TD>", valueType];
}
else
{
[text appendString: @"<TD></TD>"];
}
if (columnName)
{
[text appendFormat: @"<TD>%@</TD>", columnName];
}
else if (definition)
{
[text appendFormat: @"<TD>%@</TD>", definition];
}
else
{
[text appendString: @"<TD></TD>"];
}
if (externalType)
{
[text appendFormat: @"<TD>%@</TD>", externalType];
}
else
{
[text appendString: @"<TD></TD>"];
}
[text appendString: @"<TD>"];
if (isReadOnly)
{
[text appendFormat: @"Read Only: %@<BR>", isReadOnly];
}
if (isDerived)
{
[text appendFormat: @"Derived: %@<BR>", isDerived];
}
if (isFlattened)
{
[text appendFormat: @"Flattened: %@<BR", isFlattened];
}
[text appendString: @"</TD>"];
if (userDictionary)
{
[text appendFormat: @"<TD>%@</TD>", userDictionary];
}
else
{
[text appendString: @"<TD></TD>"];
}
if (desc)
{
[text appendFormat: @"<TD>%@</TD>", desc];
}
else
{
[text appendString: @"<TD></TD>"];
}
return text;
}
- (NSString *) parseEOAttributeRef: (xmlNodePtr)node
{
NSString *attributeName = [self getProp: "name" fromNode: node];
NSDebugMLLog(@"debug", @"Start parsing EOAttributeRef");
return attributeName;
}
- (NSString *) parseEORelationship: (xmlNodePtr)node
{
NSMutableString *text = [NSMutableString string];
NSString *ref = [self getProp: "id" fromNode: node];
NSString *entityName = [self getProp: "entityName" fromNode: node];
NSString *destinationEntityName
= [self getProp: "destinationEntityName" fromNode: node];
NSString *relationshipName = [self getProp: "name" fromNode: node];
NSString *isToMany = [self getProp: "isToMany" fromNode: node];
NSString *desc = nil;
NSString *userDictionary = nil;
NSString *definition = nil;
NSMutableArray *joins = [NSMutableArray array];
NSString *completeRef = nil;
NSDebugMLLog(@"debug", @"Start parsing EORelationship");
if (!relationshipName)
{
NSLog(@"Missing relationship name");
return nil;
}
completeRef
= [NSString stringWithFormat: @"%@##%@", currentEOEntity, relationshipName];
// We're working on EORelationship
ASSIGN(currentEORelationship, relationshipName);
ASSIGN(currentEORelationshipDestinationEntity, destinationEntityName);
if (ref == nil)
ref = completeRef;
node = node->children;
if (node && strcmp(node->name, "EORelationshipComponent") == 0)
{
definition = [self parseEORelationshipComponent: node];
node = node->next;
}
else
{
while (node && strcmp(node->name, "EOJoin") == 0)
{
NSString *s = [self parseEOJoin: node];
if (s)
{
[joins addObject: s];
}
node = node->next;
}
}
if (node && strcmp(node->name, "EOUserDictionary") == 0)
{
userDictionary = [self parseDictionary: node->children];
node = node->next;
}
if (node != 0 && strcmp(node->name, "desc") == 0)
{
desc = [self parseDesc: node];
node = node->next;
}
[self setEntry: relationshipName
withExternalCompleteRef: completeRef
withExternalRef: completeRef
withRef: ref
inIndexOfType: @"EORelationship"];
[text appendFormat: @"<TD><a name =\"%@\">%@</a></TD>",
completeRef,
relationshipName];
if (entityName)
{
[text appendFormat: @"<TD>%@</TD>",
[self linkedItem: entityName ofTypes: EOEntitiesTypes]];
}
else
{
[text appendString: @"<TD></TD>"];
}
if (destinationEntityName)
{
[text appendFormat: @"<TD>%@</TD>",
[self linkedItem: destinationEntityName ofTypes: EOEntitiesTypes]];
}
else
{
[text appendString: @"<TD></TD>"];
}
[text appendString: @"<TD>"];
if (isToMany)
{
[text appendFormat: @"to many: %@<BR>", isToMany];
}
[text appendString: @"</TD>"];
if (definition)
{
[text appendFormat: @"<TD>%@</TD>", definition];
}
else if ([joins count] > 0)
{
unsigned int i = 0;
[text appendString:
@"<TD>\r\n <TABLE BORDER=\"1\">\r\n <TR><TH>Source attribute</TH>"
@"<TH>Destination Attribute </TH><TH>Operator </TH>"
@"<TH>Semantic </TH><TH>user Dictionary </TH>"
@"<TH>Description </TH></TR>"];
for (i = 0; i < [joins count]; i++)
{
[text appendFormat: @"<TR>%@</TR>", [joins objectAtIndex: i]];
}
[text appendString: @"</TABLE>\r\n </TD>\r\n"];
}
else
{
[text appendString: @"<TD></TD>"];
}
if (userDictionary)
{
[text appendFormat: @"<TD>%@</TD>", userDictionary];
}
else
[text appendString: @"<TD></TD>"];
if (desc)
[text appendFormat: @"<TD>%@</TD>", desc];
else
[text appendString: @"<TD></TD>"];
// Stop working on EORelationship
ASSIGN(currentEORelationshipDestinationEntity, nil);
ASSIGN(currentEORelationship, nil);
return text;
}
- (NSString *) parseEORelationshipComponent: (xmlNodePtr)node
{
NSMutableString *text = [NSMutableString string];
NSString *definition;
NSDebugMLLog(@"debug", @"Start parsing EORelationshipComponent");
definition = [self getProp: "definition" fromNode: node];
node = node->children;
[text appendString:
[self linkForSymbolKey:
[NSString stringWithFormat: @"%@##%@", currentEOEntity, definition]
ofTypes: EOClassPropertiesTypes
withText: definition]];
while (node && strcmp(node->name, "EORelationshipComponent") == 0)
{
NSString *s = [self parseEORelationshipComponent: node];
if (s)
[text appendFormat: @".%@", s];
node = node->next;
}
return text;
}
- (NSString *) parseEOJoin: (xmlNodePtr)node
{
NSMutableString *text = [NSMutableString string];
NSString *ref = [self getProp: "id" fromNode: node];
NSString *relationshipName
= [self getProp: "relationshipName" fromNode: node];
NSString *joinOperator = [self getProp: "joinOperator" fromNode: node];
NSString *joinSemantic = [self getProp: "joinSemantic" fromNode: node];
NSString *sourceAttribute = [self getProp: "sourceAttribute" fromNode: node];
NSString *destinationAttribute
= [self getProp: "destinationAttribute" fromNode: node];
NSString *desc = nil;
NSString *userDictionary = nil;
NSDebugMLLog(@"debug", @"Start parsing EOJoin");
/*
if (!ref)
ref = relationshipName;
[self setEntry: relationshipName
withExternalCompleteRef: relationshipName
withExternalRef: relationshipName
withRef: ref
inIndexOfType: @"EOJoin"];
*/
/* [text appendFormat: @"<h2><a name =\"%@\">%@</a></h2>\r\n",
ref,
relationshipName];
*/
/*
if (relationshipName)
{
[text appendFormat: @"<TD>%@</TD>",
[self linkedItem: relationshipName ofTypes: EORelationshipsTypes]];
}
else
{
[text appendString: @"<TD></TD>"];
}
*/
if (sourceAttribute)
{
[text appendFormat: @"<TD>%@</TD>",
[self linkForSymbolKey:
[NSString stringWithFormat: @"%@##%@",
currentEOEntity, sourceAttribute]
ofTypes: EOClassPropertiesTypes
withText: sourceAttribute]];
}
else
[text appendString: @"<TD></TD>"];
if (destinationAttribute)
{
[text appendFormat: @"<TD>%@</TD>\r\n",
[self linkForSymbolKey:
[NSString stringWithFormat: @"%@##%@",
currentEORelationshipDestinationEntity, destinationAttribute]
ofTypes: EOClassPropertiesTypes
withText: destinationAttribute]];
}
else
[text appendString: @"<TD></TD>"];
if (joinOperator)
{
[text appendFormat: @"<TD>%@</TD>\r\n", joinOperator];
}
else
[text appendString: @"<TD></TD>"];
if (joinSemantic)
{
[text appendFormat: @"<TD>%@</TD>\r\n", joinSemantic];
}
else
[text appendString: @"<TD></TD>"];
if (userDictionary)
[text appendString: userDictionary];
else
[text appendString: @"<TD></TD>"];
if (desc)
[text appendFormat: @"<TD>%@</TD>", desc];
else
[text appendString: @"<TD></TD>"];
return text;
}
- (void) setEntry: (NSString *)entry
withExternalCompleteRef: (NSString *)externalCompleteRef
withExternalRef: (NSString *)externalRef
withRef: (NSString *)ref
inIndexOfType: (NSString *)type
{
NSMutableDictionary *index = nil;
NSAssert(entry, @"No entry");
NSAssert1(ref, @"No ref for %@", entry);
NSAssert1(type, @"No type for %@", entry);
index = [self indexForType: type];
[index setObject: entry forKey: ref];
[refToFile setObject: currName forKey: ref];
if (processFileReferencesFlag && externalCompleteRef && externalRef)
{
NSMutableDictionary *typeDict = [fileReferences objectForKey: type];
if (!fileReferences)
{
fileReferences = [NSMutableDictionary new];
}
if (!typeDict)
{
typeDict = [NSMutableDictionary dictionary];
[fileReferences setObject: typeDict
forKey: type];
}
if (![typeDict objectForKey: externalCompleteRef])
{
NSMutableDictionary *thisEntry
= [NSMutableDictionary dictionaryWithObjectsAndKeys:
entry, @"title",
externalRef, @"ref",
externalCompleteRef, @"completeRef",
ref, @"fragment",
type, @"type",
[currName stringByDeletingPathExtension], @"fileName",
nil];
[typeDict setObject: thisEntry
forKey: externalCompleteRef];
}
}
}
- (NSArray *) contents
{
return contents;
}
- (NSDictionary *) fileReferences
{
return fileReferences;
}
- (void) setGeneralReferences: (NSDictionary *)dict
{
ASSIGN(generalReferences, dict);
}
- (void) setVariablesDictionary: (NSDictionary *)dict
{
DESTROY(variablesDictionary);
variablesDictionary = [dict mutableCopy];
}
//Return a link for item (something like: <A HREF="TheFile.html#fragment">TheItem </A>) of type types
- (NSString *) linkedItem: (NSString *)item
ofTypes: (NSArray *)types
{
NSString *linked = nil;
NSRange foundRange;
foundRange = [item rangeOfCharacterFromSet:
[NSCharacterSet alphanumericCharacterSet]];
if (foundRange.length> 0)
{
NSString *goodItem = nil;
NSDictionary *symbol = nil;
NSRange goodRange = NSMakeRange(foundRange.location, 1);
while (foundRange.length> 0 && NSMaxRange(foundRange) < [item length])
{
foundRange = [item rangeOfCharacterFromSet:
[NSCharacterSet alphanumericCharacterSet]
options: 0
range: NSMakeRange(foundRange.location+1, 1)];
if (foundRange.length> 0)
goodRange.length++;
}
goodItem = [item substringWithRange: goodRange];
symbol = [self findSymbolForKey: goodItem
ofTypes: types];
if (symbol)
{
linked = [self linkForSymbol: symbol
withText: goodItem];
if (goodRange.location> 0)
{
linked = [NSString stringWithFormat: @"%@%@",
[item substringWithRange: NSMakeRange(0, goodRange.location-1)],
linked];
}
if (goodRange.location+goodRange.length < [item length])
{
linked = [NSString stringWithFormat: @"%@%@", linked,
[item substringWithRange:
NSMakeRange(goodRange.location+goodRange.length,
[item length]-(goodRange.location+goodRange.length))]];
}
}
}
if (!linked)
linked = item;
return linked;
}
- (NSString *) linkForSymbolKey: (NSString *)key_
ofTypes: (NSArray *)types
withText: (NSString *)text
{
NSDictionary *symbol = [self findSymbolForKey: key_ ofTypes: types];
if (symbol)
return [self linkForSymbol: symbol withText: text];
else
return text;
}
//Return the symbol for key
- (NSDictionary *) findSymbolForKey: (NSString *)key_ ofTypes: (NSArray *)types
{
NSDictionary *symbol = nil;
unsigned i;
for (i = 0; symbol == nil && i < [types count]; i++)
{
id type = [types objectAtIndex: i];
symbol = [[generalReferences objectForKey: type] objectForKey: key_];
}
return symbol;
}
//Return a link for symbol with label text
- (NSString *) linkForSymbol: (NSDictionary *)symbol
withText: (NSString *)text
{
NSString *symbolLocation
= [[symbol objectForKey: @"project"] objectForKey: @"location"];
NSString *locationTmp = location;
NSString *common = nil;
NSString *prefix = @"";
NSString *fragment = nil;
if ([locationTmp length] > 0)
{
//Equal: no prefix
if ([locationTmp isEqual: symbolLocation] == NO)
{
if ([locationTmp hasSuffix: @"/"] == NO)
locationTmp = [locationTmp stringByAppendingString: @"/"];
if ([symbolLocation length] > 0 && ![symbolLocation hasSuffix: @"/"])
symbolLocation = [symbolLocation stringByAppendingString: @"/"];
common = [symbolLocation commonPrefixWithString: location
options: 0];
if ([common length] > 0)
{
int i = 0;
NSMutableArray *locationParts;
NSMutableArray *symbolLocationParts;
locationParts
= [[locationTmp componentsSeparatedByString: @"/"]
mutableCopy];
AUTORELEASE(locationParts);
symbolLocationParts
= [[symbolLocation componentsSeparatedByString: @"/"]
mutableCopy];
AUTORELEASE(symbolLocationParts);
[locationParts removeLastObject];
[symbolLocationParts removeLastObject];
while ([locationParts count] > 0
&& [symbolLocationParts count] > 0
&& [[locationParts objectAtIndex: 0] isEqual:
[symbolLocationParts objectAtIndex: 0]])
{
[locationParts removeObjectAtIndex: 0];
[symbolLocationParts removeObjectAtIndex: 0];
}
prefix = [NSString string];
for (i = 0; i < [locationParts count]; i++)
{
prefix = [@".." stringByAppendingPathComponent: prefix];
}
for (i = 0; i < [symbolLocationParts count]; i++)
{
prefix = [prefix stringByAppendingPathComponent:
[symbolLocationParts objectAtIndex: i]];
}
}
else
prefix = ([symbolLocation length] > 0 ? symbolLocation : @"");
}
}
else
// No Project Location ==> take symbol location
prefix = ([symbolLocation length] > 0 ? symbolLocation : @"");
fragment = [symbol objectForKey: @"fragment"];
return [NSString stringWithFormat: @"<A HREF=\"%@%@%@\">%@</A>",
[[prefix stringByAppendingPathComponent: [symbol objectForKey: @"fileName"]]
stringByAppendingPathExtension: pathExtension_HTML],
([fragment length] > 0 ? @"#" : @""),
(fragment ? fragment : @""),
text];
}
- (void) setWriteFlag: (BOOL)flag
{
writeFlag = flag;
}
- (void) setProcessFileReferencesFlag: (BOOL)flag
{
processFileReferencesFlag = flag;
}
- (void) setProjectName: (NSString *)projectName_
{
ASSIGN(projectName, projectName_);
}
@end
//--------------------------------------------------------------------
// Return files list of files in symbols
//
// symbols:
// {
// class =
// {
// "NSString" = { fileName = "NSString.gsdoc"; ...}
// "NSArray" = { fileName = "NSArray.gsdoc"; ... }
// ...
// }
// type = {
// ...
// }
// ...
// }
//
// Return:
// ( NSString.gsdoc, NSArray.gsdoc, ... )
NSArray *
FilesFromSymbols(NSDictionary *symbols)
{
NSArray *sortedFiles = nil;
NSMutableArray *files = [NSMutableArray arrayWithCapacity: 2];
NSEnumerator *typesEnumerator = [symbols keyEnumerator];
id typeKey = nil;
while ((typeKey = [typesEnumerator nextObject]) != nil)
{
NSDictionary *type = [symbols objectForKey: typeKey];
NSEnumerator *symbolsEnumerator = [type keyEnumerator];
id symbolKey = nil;
while ((symbolKey = [symbolsEnumerator nextObject]) != nil)
{
NSDictionary *symbol = [type objectForKey: symbolKey];
id file = [symbol objectForKey: @"fileName"];
if (![files containsObject: file])
[files addObject: file];
}
}
sortedFiles = [files sortedArrayUsingSelector: @selector(compare:)];
return sortedFiles;
}
/*
* Return list of files found in dir (deep search) which have
* extension extension
*/
NSArray *
FilesInPathWithExtension(NSString *dir, NSString *extension)
{
NSMutableArray *files = [NSMutableArray array];
NSString *file = nil;
NSFileManager *fm = [NSFileManager defaultManager];
NSDirectoryEnumerator *enumerator = [fm enumeratorAtPath: dir];
while ((file = [enumerator nextObject]) != nil)
{
file = [dir stringByAppendingPathComponent: file];
if ([[file pathExtension] isEqual: extension])
{
BOOL isDirectory = NO;
if ([fm fileExistsAtPath: file isDirectory: &isDirectory])
{
if (isDirectory == NO)
{
[files addObject: file];
}
}
}
}
return files;
}
//--------------------------------------------------------------------
void
AddSymbolsToReferencesWithProjectInfo(NSDictionary *symbols,
NSMutableDictionary *references, NSDictionary *projectInfo, BOOL override)
{
NSString *projectName = [projectInfo objectForKey: @"projectName"];
if (symbols)
{
NSEnumerator *typesEnumerator = nil;
id typeKey = nil;
NSCAssert1([symbols isKindOfClass: [NSDictionary class]],
@"%@ is not a dictionary", symbols);
typesEnumerator = [symbols keyEnumerator];
while ((typeKey = [typesEnumerator nextObject]) != nil)
{
NSDictionary *type = [symbols objectForKey: typeKey];
if ([type isKindOfClass: [NSDictionary class]] == NO)
{
NSLog(@"Warning: Type %@ is not a dictionary", type);
}
else
{
NSEnumerator *symbolsEnumerator;
id symbolKey = nil;
NSMutableDictionary *referencesType;
symbolsEnumerator = [type keyEnumerator];
referencesType = [references objectForKey: typeKey];
if (referencesType == nil)
{
referencesType = [NSMutableDictionary dictionary];
[references setObject: referencesType
forKey: typeKey];
}
while ((symbolKey = [symbolsEnumerator nextObject]) != nil)
{
NSDictionary *symbol = [type objectForKey: symbolKey];
if (![symbol isKindOfClass: [NSDictionary class]])
{
NSLog(@"Warning: Symbol %@ is not a dictionary", symbol);
}
else
{
NSMutableDictionary *symbolNew;
symbolNew = [NSMutableDictionary
dictionaryWithDictionary: symbol];
if (verbose >= 4)
{
NSLog(@"Project %@ Processing reference %@",
projectName, symbolKey);
}
if (projectInfo)
[symbolNew setObject: projectInfo
forKey: @"project"];
NSCAssert(symbolKey, @"No symbolKey");
if (override || ![referencesType objectForKey: symbolKey])
[referencesType setObject: symbolNew
forKey: symbolKey];
NSCAssert1([symbolNew objectForKey: @"ref"],
@"No ref for symbol %@", symbolKey);
if (override || ![referencesType objectForKey:
[symbolNew objectForKey: @"ref"]])
{
[referencesType setObject: symbolNew
forKey: [symbolNew objectForKey:
@"ref"]];
}
if (projectName)
{
NSString *symbolType
= [symbolNew objectForKey: @"type"];
if ([symbolType isEqual: @"file"])
{
NSString *fileName
= [symbolNew objectForKey: @"fileName"];
if (fileName)
{
NSString *fileRef = nil;
fileName
= [fileName stringByDeletingPathExtension];
fileRef
= [NSString stringWithFormat: @"%@##%@",
projectName, fileName];
[symbolNew setObject: fileRef
forKey: @"completeRef"];
if (override
|| ![referencesType objectForKey: fileRef])
{
[referencesType setObject: symbolNew
forKey: fileRef];
}
}
}
}
}
}
}
}
}
if (projectName)
{
NSString *fileName
= [[projectInfo objectForKey: @"indexfileName"]
stringByDeletingPathExtension];
NSString *fileRef = nil;
NSMutableDictionary *referencesType = [references objectForKey: @"file"];
if (!referencesType)
{
referencesType = [NSMutableDictionary dictionary];
[references setObject: referencesType
forKey: @"file"];
}
if (!fileName)
{
fileName = @"index";
}
fileRef = [NSString stringWithFormat: @"%@##%@", projectName, fileName];
if (override || ![referencesType objectForKey: fileRef])
{
NSMutableDictionary *symbol
= [NSMutableDictionary dictionaryWithObjectsAndKeys:
fileRef, @"completeRef",
fileName, @"fileName",
fileName, @"ref",
@"file", @"type",
nil];
if (projectInfo)
{
[symbol setObject: projectInfo
forKey: @"project"];
}
[referencesType setObject: symbol
forKey: fileRef];
}
}
}
int
main(int argc, char **argv, char **env)
{
NSProcessInfo *proc;
NSArray *args;
unsigned i;
NSUserDefaults *defs;
NSString *makeRefsFileName = nil;
NSString *projectName = nil;
NSMutableArray *files = nil;
NSMutableArray *references = nil;
NSMutableDictionary *generalReferences = nil;
NSMutableDictionary *projectReferences = nil;
NSString *makeIndexBaseFileName = nil;
NSString *makeIndexFileNameGSDoc = nil;
NSString *makeIndexTemplateFileName = nil;
NSMutableDictionary *infoDictionary = nil;
NSDictionary *variablesDictionary = nil;
NSMutableDictionary *projectInfo = nil;
BOOL goOn = YES;
NSFileManager *fileManager = nil;
CREATE_AUTORELEASE_POOL(pool);
#ifdef GS_PASS_ARGUMENTS
[NSProcessInfo initializeWithArguments: argv count: argc environment: env];
#endif
NSLog(@"WARNING ... gsdoc is deprecated. please use autogsdoc instead");
defs = [NSUserDefaults standardUserDefaults];
[defs registerDefaults: [NSDictionary dictionaryWithObjectsAndKeys:
@"Yes", @"Monolithic", nil]];
proc = [NSProcessInfo processInfo];
if (proc == nil)
{
NSLog(@"unable to get process information!");
goOn = NO;
}
fileManager = [NSFileManager defaultManager];
if (goOn == YES)
{
args = [proc arguments];
// First, process arguments
for (i = 1; goOn && i < [args count]; i++)
{
NSString *arg = [args objectAtIndex: i];
// is this an option ?
if ([arg hasPrefix: @"--"])
{
NSString *argWithoutPrefix;
NSString *value;
NSString *key;
NSArray *parts;
argWithoutPrefix = [arg stringByDeletingPrefix: @"--"];
parts = [argWithoutPrefix componentsSeparatedByString: @"="];
key = [parts objectAtIndex: 0];
if ([parts count] > 1)
{
NSRange r = NSMakeRange(1, [parts count]-1);
NSArray *sub = [parts subarrayWithRange: r];
value = [sub componentsJoinedByString: @"="];
}
else
{
value = nil;
}
// makeRefs option
if ([key isEqualToString: @"makeRefs"])
{
makeRefsFileName = value;
if (makeRefsFileName != nil)
{
NSString *ext = [makeRefsFileName pathExtension];
if ([ext isEqual: pathExtension_GSDocRefs] == NO)
{
makeRefsFileName = [makeRefsFileName
stringByAppendingPathExtension:
pathExtension_GSDocRefs];
}
}
else
{
makeRefsFileName = @"";
}
}
else if ([key isEqualToString: @"projectName"])
{
projectName = value;
NSCAssert([projectName length], @"No project name");
}
else if ([key isEqualToString: @"refs"])
{
if (references == nil)
{
references = [NSMutableArray arrayWithCapacity: 4];
}
NSCAssert([value length], @"No index");
[references addObject: value];
}
else if ([key isEqualToString: @"makeIndex"])
{
makeIndexBaseFileName = value;
if (makeIndexBaseFileName != nil)
{
makeIndexBaseFileName
= [makeIndexBaseFileName stringByDeletingPathExtension];
}
else
{
makeIndexBaseFileName = @"index";
}
}
else if ([key isEqualToString: @"makeIndexTemplate"])
{
makeIndexTemplateFileName = value;
NSCAssert([makeIndexTemplateFileName length],
@"No makeIndexTemplate filename");
}
else if ([key hasPrefix: @"verbose"])
{
NSCAssert1(value, @"No value for %@", key);
verbose = [value intValue];
if (verbose > 0)
{
NSMutableSet *debugSet = [proc debugSet];
[debugSet addObject: @"dflt"];
}
}
else if ([key hasPrefix: @"location"])
{
NSCAssert1(value, @"No value for %@", key);
location = value;
}
else if ([key hasPrefix: @"define-"])
{
if (infoDictionary == nil)
{
infoDictionary = [NSMutableDictionary dictionary];
}
NSCAssert1(value, @"No value for %@", key);
[infoDictionary setObject: value
forKey: [key stringByDeletingPrefix: @"define-"]];
}
else
{
NSLog(@"Unknown option %@", arg);
goOn = NO;
}
}
else
{
if (files == nil)
files = [NSMutableArray array];
/*
* FIXME
* Dirty Hack to handle *.gsdoc and *
* We need this because sometimes, there are too many files
* for commande line
*/
if ([[arg lastPathComponent] hasSuffix:
[NSString stringWithFormat: @"*.%@", pathExtension_GSDoc]]
|| [[arg lastPathComponent]hasSuffix: @"*"])
{
NSArray *dirContent = nil;
int ifile = 0;
arg = [arg stringByDeletingLastPathComponent];
if ([arg length] == 0)
{
arg = [fileManager currentDirectoryPath];
}
dirContent = [fileManager directoryContentsAtPath: arg];
for (ifile = 0; ifile < [dirContent count]; ifile++)
{
NSString *file = [dirContent objectAtIndex: ifile];
if ([[file pathExtension] isEqual: pathExtension_GSDoc])
{
[files addObject: file];
}
}
}
else
{
[files addObject: arg];
}
}
}
}
//Default Values
if (goOn)
{
if (projectName == nil)
{
projectName = @"unknown";
}
if ([makeRefsFileName length]== 0)
{
makeRefsFileName = [projectName
stringByAppendingPathExtension: pathExtension_GSDocRefs];
}
if (makeIndexBaseFileName != nil)
{
makeIndexFileNameGSDoc = [makeIndexBaseFileName
stringByAppendingPathExtension: pathExtension_GSDoc];
}
}
// Verify option compatibilities
if (goOn)
{
}
// Construct project references
if (goOn)
{
BOOL addedSymbols = NO;
NSDictionary *previousProjectReferences = nil;
NSDebugFLLog(@"debug", @"Construct project references");
projectReferences = [NSMutableDictionary dictionaryWithCapacity: 2];
[projectReferences
setObject: [NSMutableDictionary dictionaryWithCapacity: 2]
forKey: @"symbols"];
projectInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
projectName, @"projectName", nil];
if (location != nil)
{
[projectInfo setObject: location forKey: @"location"];
}
if (makeIndexBaseFileName != nil)
{
[projectInfo setObject: makeIndexBaseFileName
forKey: @"indexfileName"];
}
//Read project existing references
if (makeRefsFileName != nil)
{
BOOL isDirectory = NO;
if ([fileManager fileExistsAtPath: makeRefsFileName
isDirectory: &isDirectory])
{
if (isDirectory == NO)
{
previousProjectReferences = [NSDictionary
dictionaryWithContentsOfFile: makeRefsFileName];
if ([previousProjectReferences objectForKey: @"symbols"])
{
AddSymbolsToReferencesWithProjectInfo(
[previousProjectReferences objectForKey: @"symbols"],
[projectReferences objectForKey: @"symbols"],
projectInfo, NO);
addedSymbols = YES;
}
}
}
}
if (addedSymbols == NO)
{
AddSymbolsToReferencesWithProjectInfo(nil,
[projectReferences objectForKey: @"symbols"], projectInfo, NO);
}
}
// Process references (construct a dictionary of all references)
if (goOn)
{
NSDebugFLLog(@"debug", @"Process references");
generalReferences = [NSMutableDictionary dictionaryWithCapacity: 2];
if ([references count] > 0)
{
/*
* From last to first so references are taken in
* first to last priority
*/
while (goOn && [references count] > 0)
{
NSString *file = [references lastObject];
BOOL isDirectory = NO;
if (![fileManager fileExistsAtPath: file
isDirectory: &isDirectory])
{
NSLog(@"Index File %@ doesn't exist", file);
[references removeLastObject];
}
else
{
if (isDirectory)
{
NSArray *tmpReferences;
tmpReferences = FilesInPathWithExtension(file,
pathExtension_GSDocRefs);
if (verbose >= 3)
{
NSLog(@"Processing references directory %@", file);
}
[references removeLastObject];
[references addObjectsFromArray: tmpReferences];
}
else
{
NSDictionary *generalIndexTmp = nil;
if (verbose >= 2)
{
NSLog(@"Processing references file %@", file);
}
generalIndexTmp = [NSDictionary
dictionaryWithContentsOfFile: file];
if (!generalIndexTmp)
{
NSLog(@"File %@ isn't a dictionary", file);
goOn = NO;
}
else
{
NSDictionary *fileProjectInfo;
NSDictionary *symbols;
fileProjectInfo
= [generalIndexTmp objectForKey: @"project"];
symbols = [generalIndexTmp objectForKey: @"symbols"];
NSCAssert1(fileProjectInfo,
@"No Project Info in %@", file);
NSCAssert1(symbols, @"No symbols %@", file);
AddSymbolsToReferencesWithProjectInfo(symbols,
generalReferences, fileProjectInfo, YES);
}
[references removeLastObject];
}
}
}
}
}
//Variables
if (goOn)
{
NSMutableDictionary *variablesMutableDictionary;
NSEnumerator *enumer;
id key = nil;
variablesMutableDictionary = [NSMutableDictionary dictionary];
enumer = [infoDictionary keyEnumerator];
NSDebugFLLog(@"debug", @"Variables");
while ((key = [enumer nextObject]))
{
id v;
NSString *k;
v = [infoDictionary objectForKey: key];
k = [NSString stringWithFormat: @"[[infoDictionary.%@]]", key];
[variablesMutableDictionary setObject: v forKey: k];
}
[variablesMutableDictionary setObject: [NSCalendarDate calendarDate]
forKey: @"[[timestampString]]"];
if (makeIndexBaseFileName)
{
[variablesMutableDictionary setObject: makeIndexFileNameGSDoc
forKey: @"[[indexFileName]]"];
[variablesMutableDictionary setObject: makeIndexBaseFileName
forKey: @"[[indexBaseFileName]]"];
}
if (projectName != nil)
{
[variablesMutableDictionary setObject: projectName
forKey: @"[[projectName]]"];
}
variablesDictionary = [variablesMutableDictionary copy];
AUTORELEASE(variablesDictionary);
if (verbose >= 3)
{
NSEnumerator *enumer = [variablesDictionary keyEnumerator];
id key = nil;
while ((key = [enumer nextObject]))
{
NSLog(@"Variables: %@=%@",
key, [variablesDictionary objectForKey: key]);
}
}
}
// Find Files to parse
if (goOn)
{
NSDebugFLLog(@"debug", @"Find Files to parse");
if ([files count] < 1)
{
NSLog(@"No file names given to parse.");
goOn = NO;
}
else
{
NSMutableArray *tmpNewFiles = [NSMutableArray array];
for (i = 0; goOn && i < [files count]; i++)
{
NSString *file = [files objectAtIndex: i];
BOOL isDirectory = NO;
if (![fileManager fileExistsAtPath: file
isDirectory: &isDirectory])
{
NSLog(@"File %@ doesn't exist", file);
goOn = NO;
}
else
{
if (isDirectory)
{
NSArray *tmpFiles;
tmpFiles
= FilesInPathWithExtension(file, pathExtension_GSDoc);
[tmpNewFiles addObjectsFromArray: tmpFiles];
}
else
{
[tmpNewFiles addObject: file];
}
}
}
files = [[tmpNewFiles sortedArrayUsingSelector: @selector(compare:)]
mutableCopy];
AUTORELEASE(files);
}
}
if (goOn)
{
int pass = 0;
NSDebugFLLog(@"debug", @"Parse Files");
/*
* 1st pass: don't write file, just parse them and
* construct project references
* 2nd pass: parse and write files
*/
for (pass = 0; goOn && pass < 2; pass++)
{
for (i = 0; goOn && i < [files count]; i++)
{
NSString *file = [files objectAtIndex: i];
NSString *base = [file stringByDeletingPathExtension];
CREATE_AUTORELEASE_POOL(arp);
// Don't process generated index file
if ([base isEqual: makeIndexBaseFileName])
{
if (verbose >= 1)
{
NSLog(@"Pass %d/2 File %d/%d - Ignoring Index File "
@"%@ (Process it later)",
(pass+1), (i+1), [files count], file);
}
}
else
{
if (verbose >= 1)
{
NSLog(@"Pass %d/2 File %d/%d - Processing %@",
(pass+1), (i+1), [files count], file);
}
NS_DURING
{
GSDocHtml *p = nil;
p = [GSDocHtml alloc];
p = [p initWithFileName: file];
if (p != nil)
{
NSString *previousFile;
NSString *nextFile;
NSMutableDictionary *vmDictionary;
NSString *result;
previousFile = ((i > 0) ? [files objectAtIndex: i-1]
: @"");
nextFile = (((i+1) < [files count])
? [files objectAtIndex: i+1] : @"");
vmDictionary = nil;
result = nil;
[p setProjectName: projectName];
[p setGeneralReferences: generalReferences];
vmDictionary = [variablesDictionary mutableCopy];
[vmDictionary setObject:
[previousFile stringByDeletingPathExtension]
forKey: @"[[prev]]"];
[vmDictionary setObject:
[nextFile stringByDeletingPathExtension]
forKey: @"[[next]]"];
if (makeIndexBaseFileName)
{
[vmDictionary setObject:
makeIndexBaseFileName forKey: @"[[up]]"];
}
[p setVariablesDictionary: vmDictionary];
[p setWriteFlag: (pass == 1)];
[p setProcessFileReferencesFlag: (pass == 0)];
result = [p parseDocument];
if (result == nil)
{
NSLog(@"Pass %d/2 File %d/%d - Error parsing %@",
(pass+1), (i+1), [files count], file);
goOn = NO;
}
else
{
if (verbose >= 1)
{
NSLog(@"Pass %d/2 File %d/%d"
@" - Parsed %@ - OK",
(pass+1), (i+1), [files count], file);
}
if (pass == 0)
{
NSDebugFLLog(@"debug",
@"AddSymbolsToReferencesWithProjectInfo ->"
@" projectRefernce");
AddSymbolsToReferencesWithProjectInfo(
[p fileReferences],
[projectReferences
objectForKey: @"symbols"],
nil, NO);
NSDebugFLLog(@"debug",
@"AddSymbolsToReferencesWithProjectInfo ->"
@" generalReference");
AddSymbolsToReferencesWithProjectInfo(
[p fileReferences], generalReferences,
projectInfo, YES);
NSDebugFLLog(@"debug",
@"AddSymbolsToReferencesWithProjectInfo "
@"finished");
}
}
RELEASE(p);
}
}
NS_HANDLER
{
NSLog(@"Pass %d/2 File %d/%d - Parsing '%@' - %@",
(pass+1), (i+1), [files count], file,
[localException reason]);
goOn = NO;
}
NS_ENDHANDLER
}
#if GS_WITH_GC == 0
DESTROY(arp);
#endif
}
}
}
// Process Project References to generate Project Reference File
if (goOn)
{
if (makeRefsFileName)
{
[projectReferences setObject: projectInfo forKey: @"project"];
if (verbose >= 1)
{
NSLog(@"Writing References File %@", makeRefsFileName);
}
if ([projectReferences writeToFile: makeRefsFileName
atomically: YES] == NO)
{
NSLog(@"Error creating %@", makeRefsFileName);
goOn = NO;
}
}
}
// Process Project References to generate Index File
if (goOn)
{
if (makeIndexBaseFileName)
{
NSString *textTemplate
= [NSString stringWithContentsOfFile: makeIndexTemplateFileName];
NSMutableString *textStart = [NSMutableString string];
NSMutableString *textChapters = [NSMutableString string];
NSMutableString *textClasses = [NSMutableString string];
NSMutableString *textCategories = [NSMutableString string];
NSMutableString *textProtocols = [NSMutableString string];
NSMutableString *textFunctions = [NSMutableString string];
NSMutableString *textTypes = [NSMutableString string];
NSMutableString *textConstants = [NSMutableString string];
NSMutableString *textVariables = [NSMutableString string];
NSMutableString *textOthers = [NSMutableString string];
NSMutableString *textFiles = [NSMutableString string];
NSMutableString *textStop = [NSMutableString string];
NSMutableString *text = nil;
NSMutableDictionary *variablesMutableDictionary = nil;
NSString *typeTitle = nil;
NSString *finalText = nil;
NSDictionary *symbolsByType
= [projectReferences objectForKey: @"symbols"];
NSString *firstFileName = nil;
NSEnumerator *typesEnumerator
= [symbolsByType keyEnumerator];
id typeKey = nil;
if (verbose >= 1)
{
NSLog(@"Making Index");
}
[textStart appendFormat:
@"<chapter>\n <heading>%@</heading>\n", projectName];
while ((typeKey = [typesEnumerator nextObject]))
{
if (verbose >= 2)
{
NSLog(@"Making Index for type %@", typeKey);
}
text = nil;
if ([typeKey isEqual: @"ivariable"])
{
text = nil;
typeTitle = @"Instance Variables";
}
else if ([typeKey isEqual: @"method"])
{
text = nil;
typeTitle = @"Methods";
}
else if ([typeKey isEqual: @"file"])
{
text = textFiles;
typeTitle = @"Files";
}
else if ([typeKey isEqual: @"chapter"])
{
text = textChapters;
typeTitle = @"Chapters";
}
else if ([typeKey isEqual: @"section"])
{
text = nil;
typeTitle = @"Section";
}
else if ([typeKey isEqual: @"ubsect"])
{
text = nil;
typeTitle = @"Subsections";
}
else if ([typeKey isEqual: @"class"]
|| [typeKey isEqual: @"jclass"])
{
text = textClasses;
typeTitle = @"Classes";
}
else if ([typeKey isEqual: @"protocol"])
{
text = textProtocols;
typeTitle = @"Protocols";
}
else if ([typeKey isEqual: @"category"])
{
text = textProtocols;
typeTitle = @"Categories";
}
else if ([typeKey isEqual: @"function"])
{
text = textFunctions;
typeTitle = @"Functions";
}
else if ([typeKey isEqual: @"macro"])
{
text = textFunctions;
typeTitle = @"Macros";
}
else if ([typeKey isEqual: @"constant"])
{
text = textConstants;
typeTitle = @"Constants";
}
else if ([typeKey isEqual: @"variable"])
{
text = textVariables;
typeTitle = @"Global Variables";
}
else
{
text = textOthers;
typeTitle = @"Others";
}
if (text != nil)
{
NSArray *symbolKeys = nil;
NSEnumerator *symbolsEnumerator = nil;
id symbolKey = nil;
NSDictionary *typeDict;
typeDict = [symbolsByType objectForKey: typeKey];
[text appendFormat:
@"<section>\n <heading>%@</heading>\n <list>\n", typeTitle];
symbolKeys = [[typeDict allKeys]
sortedArrayUsingSelector: @selector(compare:)];
symbolsEnumerator = [symbolKeys objectEnumerator];
while ((symbolKey = [symbolsEnumerator nextObject]))
{
NSString *fragment = nil;
NSDictionary *symbol = [typeDict objectForKey: symbolKey];
if (text == textFiles && !firstFileName)
firstFileName = [symbol objectForKey: @"fileName"];
if (verbose >= 4)
{
NSLog(@"Making Index for symbol %@",
[symbol objectForKey: @"title"]);
}
fragment = [symbol objectForKey: @"fragment"];
[text appendFormat:
@"<item><uref url =\"%@%@%@\">%@</uref></item>\n",
[[symbol objectForKey: @"fileName"]
stringByAppendingPathExtension: pathExtension_HTML],
([fragment length] > 0 ? @"#" : @""),
(fragment ? fragment : @""),
[symbol objectForKey: @"title"]];
}
[text appendString: @"</list>\n </section>\n"];
}
}
[textStop appendString: @"</chapter>\n"];
finalText = [NSString stringWithFormat:
@"%@\n%@\n%@\n%@\n%@\n%@\n%@\n%@\n%@\n%@\n%@\n%@\n",
textStart, textChapters, textClasses, textCategories,
textProtocols, textFunctions, textTypes, textConstants,
textVariables, textOthers, textFiles, textStop];
variablesMutableDictionary = [variablesDictionary mutableCopy];
[variablesMutableDictionary setObject: finalText
forKey: @"[[content]]"];
[variablesMutableDictionary setObject: [firstFileName stringByDeletingPathExtension]
forKey: @"[[next]]"];
finalText = textByReplacingVariablesInText(textTemplate,
variablesMutableDictionary);
if (verbose >= 1)
{
NSLog(@"Writing Index %@", makeIndexFileNameGSDoc);
}
if (![finalText writeToFile: makeIndexFileNameGSDoc
atomically: YES])
{
NSLog(@"Error creating %@", makeIndexFileNameGSDoc);
goOn = NO;
}
}
}
// Finally, parse index
if (goOn)
{
if (makeIndexBaseFileName)
{
if (verbose >= 1)
{
NSLog(@"Processing %@", makeIndexFileNameGSDoc);
}
NS_DURING
{
GSDocHtml *p = nil;
p = [GSDocHtml alloc];
p = [p initWithFileName: makeIndexFileNameGSDoc];
if (p != nil)
{
NSString *result = nil;
[p setVariablesDictionary: variablesDictionary];
result = [p parseDocument];
if (result == nil)
{
NSLog(@"Error parsing %@", makeIndexFileNameGSDoc);
goOn = NO;
}
else
{
if (verbose >= 1)
{
NSLog(@"Parsed %@ - OK", makeIndexFileNameGSDoc);
}
}
RELEASE(p);
}
}
NS_HANDLER
{
NSLog(@"Parsing '%@' - %@",
makeIndexFileNameGSDoc, [localException reason]);
goOn = NO;
}
NS_ENDHANDLER;
}
}
RELEASE(pool);
return (goOn ? 0 : 1);
}
#else
int
main()
{
NSLog(@"No libxml available");
return 0;
}
#endif