2001-10-15 14:42:56 +00:00
|
|
|
/**
|
|
|
|
|
|
|
|
<title>AGSIndex ... a class to create references for a gsdoc file</title>
|
2001-12-16 13:36:06 +00:00
|
|
|
Copyright (C) 2001 Free Software Foundation, Inc.
|
2001-10-15 14:42:56 +00:00
|
|
|
|
2001-12-16 13:36:06 +00:00
|
|
|
Written by: Richard Frith-Macdonald <richard@brainstorm.co.uk>
|
2001-10-15 14:42:56 +00:00
|
|
|
Created: October 2001
|
|
|
|
|
|
|
|
This file is part of the GNUstep Project
|
|
|
|
|
2001-12-18 11:09:38 +00:00
|
|
|
This program is free software; you can redistribute it and/or
|
2001-10-15 14:42:56 +00:00
|
|
|
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
|
2001-12-18 11:09:38 +00:00
|
|
|
License along with this program; see the file COPYING.LIB.
|
2001-10-15 14:42:56 +00:00
|
|
|
If not, write to the Free Software Foundation,
|
|
|
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <Foundation/Foundation.h>
|
|
|
|
#include "AGSIndex.h"
|
2003-07-31 23:49:32 +00:00
|
|
|
#include "GNUstepBase/GNUstep.h"
|
|
|
|
#include "GNUstepBase/GSCategories.h"
|
2003-08-24 02:21:08 +00:00
|
|
|
|
2001-10-15 14:42:56 +00:00
|
|
|
static int XML_ELEMENT_NODE;
|
|
|
|
static int XML_TEXT_NODE;
|
|
|
|
|
|
|
|
static void
|
2001-12-15 09:05:19 +00:00
|
|
|
mergeDictionaries(NSMutableDictionary *dst, NSDictionary *src, BOOL override)
|
2001-10-15 14:42:56 +00:00
|
|
|
{
|
|
|
|
static NSMutableArray *stack = nil;
|
|
|
|
NSEnumerator *e = [src keyEnumerator];
|
|
|
|
NSString *k;
|
2001-12-17 22:36:30 +00:00
|
|
|
id s;
|
|
|
|
id d;
|
2001-10-15 14:42:56 +00:00
|
|
|
|
|
|
|
if (stack == nil)
|
|
|
|
{
|
|
|
|
stack = [[NSMutableArray alloc] initWithCapacity: 8];
|
|
|
|
}
|
|
|
|
while ((k = [e nextObject]) != nil)
|
|
|
|
{
|
2001-12-17 22:36:30 +00:00
|
|
|
if ([k isEqualToString: @"contents"] == YES)
|
|
|
|
{
|
|
|
|
continue; // Makes no sense to merge file contents.
|
|
|
|
}
|
|
|
|
s = [src objectForKey: k];
|
|
|
|
d = [dst objectForKey: k];
|
2001-10-15 14:42:56 +00:00
|
|
|
|
|
|
|
[stack addObject: k];
|
|
|
|
if (d == nil)
|
|
|
|
{
|
|
|
|
if ([s isKindOfClass: [NSString class]] == YES)
|
|
|
|
{
|
|
|
|
[dst setObject: s forKey: k];
|
|
|
|
}
|
2002-02-26 17:36:33 +00:00
|
|
|
else if ([s isKindOfClass: [NSArray class]] == YES)
|
|
|
|
{
|
|
|
|
[dst setObject: s forKey: k];
|
|
|
|
}
|
2001-10-15 14:42:56 +00:00
|
|
|
else if ([s isKindOfClass: [NSDictionary class]] == YES)
|
|
|
|
{
|
|
|
|
d = [[NSMutableDictionary alloc] initWithCapacity: [s count]];
|
|
|
|
[dst setObject: d forKey: k];
|
|
|
|
RELEASE(d);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NSLog(@"Unexpected class in merge %@ ignored", stack);
|
|
|
|
d = nil;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (d != nil)
|
|
|
|
{
|
2001-12-15 09:05:19 +00:00
|
|
|
if ([d isKindOfClass: [NSString class]] == YES)
|
2001-10-15 14:42:56 +00:00
|
|
|
{
|
2001-12-15 09:05:19 +00:00
|
|
|
if ([s isKindOfClass: [NSString class]] == NO)
|
2001-10-15 14:42:56 +00:00
|
|
|
{
|
2001-12-15 09:05:19 +00:00
|
|
|
NSLog(@"Class missmatch in merge for %@.", stack);
|
|
|
|
}
|
|
|
|
else if ([d isEqual: s] == NO)
|
|
|
|
{
|
|
|
|
if (override == YES)
|
|
|
|
{
|
|
|
|
[dst setObject: s forKey: k];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NSLog(@"String missmatch in merge for %@. S:%@, D:%@",
|
|
|
|
stack, s, d);
|
2002-05-15 11:29:52 +00:00
|
|
|
[dst setObject: s forKey: k];
|
2001-12-15 09:05:19 +00:00
|
|
|
}
|
2001-10-15 14:42:56 +00:00
|
|
|
}
|
|
|
|
}
|
2002-02-26 17:36:33 +00:00
|
|
|
else if ([d isKindOfClass: [NSArray class]] == YES)
|
|
|
|
{
|
|
|
|
if ([s isKindOfClass: [NSArray class]] == NO)
|
|
|
|
{
|
|
|
|
NSLog(@"Class missmatch in merge for %@.", stack);
|
|
|
|
}
|
|
|
|
else if ([d isEqual: s] == NO)
|
|
|
|
{
|
|
|
|
if (override == YES)
|
|
|
|
{
|
|
|
|
[dst setObject: s forKey: k];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NSLog(@"Array missmatch in merge for %@. S:%@, D:%@",
|
|
|
|
stack, s, d);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2001-10-15 14:42:56 +00:00
|
|
|
else if ([d isKindOfClass: [NSDictionary class]] == YES)
|
|
|
|
{
|
2001-12-15 09:05:19 +00:00
|
|
|
if ([s isKindOfClass: [NSDictionary class]] == NO)
|
|
|
|
{
|
|
|
|
NSLog(@"Class missmatch in merge for %@.", stack);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mergeDictionaries(d, s, override);
|
|
|
|
}
|
2001-10-15 14:42:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
[stack removeLastObject];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-11-29 07:38:04 +00:00
|
|
|
static void
|
|
|
|
setDirectory(NSMutableDictionary *dict, NSString *path)
|
|
|
|
{
|
|
|
|
NSArray *a = [dict allKeys];
|
|
|
|
NSEnumerator *e = [a objectEnumerator];
|
|
|
|
NSString *k;
|
|
|
|
|
|
|
|
while ((k = [e nextObject]) != nil)
|
|
|
|
{
|
|
|
|
id o = [dict objectForKey: k];
|
|
|
|
|
|
|
|
if ([o isKindOfClass: [NSString class]] == YES)
|
|
|
|
{
|
|
|
|
o = [path stringByAppendingPathComponent: [o lastPathComponent]];
|
|
|
|
[dict setObject: o forKey: k];
|
|
|
|
}
|
|
|
|
else if ([o isKindOfClass: [NSDictionary class]] == YES)
|
|
|
|
{
|
|
|
|
setDirectory(o, path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-12-18 08:39:00 +00:00
|
|
|
/**
|
|
|
|
* This class is used to build and manipulate a dictionary of
|
|
|
|
* cross-reference information.<br />
|
|
|
|
* The references are held in a tree consisting of dictionaries
|
|
|
|
* with strings at the leaves -<br />
|
|
|
|
* method method-name class-name file-name<br />
|
|
|
|
* method method-name protocol-name file-name<br />
|
|
|
|
* ivariable variable-name class-name file-name<br />
|
|
|
|
* class class-name file-name<br />
|
|
|
|
* category category-name file-name<br />
|
|
|
|
* protocol protocol-name file-name<br />
|
|
|
|
* function function-name file-name<br />
|
|
|
|
* type type-name file-name<br />
|
|
|
|
* constant constant-name file-name<br />
|
|
|
|
* variable variable-name file-name<br />
|
|
|
|
* entry entry-name file-name ref<br />
|
|
|
|
* label label-name file-name ref<br />
|
|
|
|
* contents ref text<br />
|
|
|
|
* super class-name superclass-name<br />
|
2002-01-08 17:31:38 +00:00
|
|
|
* categories class-name category-name file-name<br />
|
|
|
|
* unitmethods unit-name method-name<br />
|
|
|
|
* classvars class-name variables-name<br />
|
2001-12-18 08:39:00 +00:00
|
|
|
* title file-name text<br />
|
2002-02-26 17:36:33 +00:00
|
|
|
* source file-name array-of-source-files<br />
|
2001-12-18 08:39:00 +00:00
|
|
|
*/
|
2001-10-15 14:42:56 +00:00
|
|
|
@implementation AGSIndex
|
|
|
|
|
|
|
|
+ (void) initialize
|
|
|
|
{
|
|
|
|
if (self == [AGSIndex class])
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Cache XML node information.
|
|
|
|
*/
|
|
|
|
XML_ELEMENT_NODE = [GSXMLNode typeFromDescription: @"XML_ELEMENT_NODE"];
|
|
|
|
XML_TEXT_NODE = [GSXMLNode typeFromDescription: @"XML_TEXT_NODE"];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) dealloc
|
|
|
|
{
|
|
|
|
RELEASE(refs);
|
|
|
|
[super dealloc];
|
|
|
|
}
|
|
|
|
|
2001-11-21 17:10:22 +00:00
|
|
|
- (NSString*) globalRef: (NSString*)ref type: (NSString*)type
|
|
|
|
{
|
|
|
|
NSDictionary *t;
|
|
|
|
|
|
|
|
t = [refs objectForKey: type];
|
|
|
|
return [t objectForKey: ref];
|
|
|
|
}
|
|
|
|
|
2001-10-15 14:42:56 +00:00
|
|
|
- (id) init
|
|
|
|
{
|
|
|
|
refs = [[NSMutableDictionary alloc] initWithCapacity: 8];
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Given the root node of a gsdoc document, we traverse the tree
|
2001-12-18 08:39:00 +00:00
|
|
|
* looking for interesting nodes, and recording their names in a
|
|
|
|
* dictionary of references.
|
2001-10-15 14:42:56 +00:00
|
|
|
*/
|
|
|
|
- (void) makeRefs: (GSXMLNode*)node
|
|
|
|
{
|
2002-05-22 14:23:17 +00:00
|
|
|
GSXMLNode *children = [node firstChild];
|
2001-10-15 14:42:56 +00:00
|
|
|
GSXMLNode *next = [node next];
|
|
|
|
BOOL newUnit = NO;
|
|
|
|
|
|
|
|
if ([node type] == XML_ELEMENT_NODE)
|
|
|
|
{
|
|
|
|
NSString *name = [node name];
|
2002-05-23 15:58:15 +00:00
|
|
|
NSDictionary *prop = [node attributes];
|
2001-10-15 14:42:56 +00:00
|
|
|
|
|
|
|
if ([name isEqual: @"category"] == YES)
|
|
|
|
{
|
|
|
|
newUnit = YES;
|
2002-01-08 17:31:38 +00:00
|
|
|
classname = [prop objectForKey: @"class"];
|
|
|
|
category = [prop objectForKey: @"name"];
|
|
|
|
unit = classname;
|
|
|
|
/*
|
|
|
|
* Add this category to the list of those for the class.
|
|
|
|
*/
|
|
|
|
[self setUnitRef: category type: @"categories"];
|
|
|
|
unit = [NSString stringWithFormat: @"%@(%@)", classname, category];
|
2002-01-03 20:17:28 +00:00
|
|
|
[self setGlobalRef: unit type: @"category"];
|
2001-10-15 14:42:56 +00:00
|
|
|
}
|
2001-12-17 22:36:30 +00:00
|
|
|
else if ([name isEqual: @"chapter"] == YES)
|
|
|
|
{
|
|
|
|
chap++;
|
|
|
|
sect = 0;
|
|
|
|
ssect = 0;
|
|
|
|
sssect = 0;
|
|
|
|
}
|
2001-10-15 14:42:56 +00:00
|
|
|
else if ([name isEqual: @"class"] == YES)
|
|
|
|
{
|
2002-01-02 10:24:28 +00:00
|
|
|
NSString *tmp;
|
2001-10-15 14:42:56 +00:00
|
|
|
|
|
|
|
newUnit = YES;
|
2002-01-08 17:31:38 +00:00
|
|
|
classname = [prop objectForKey: @"name"];
|
|
|
|
unit = classname;
|
2001-10-15 14:42:56 +00:00
|
|
|
tmp = [prop objectForKey: @"super"];
|
|
|
|
if (tmp != nil)
|
|
|
|
{
|
2002-01-08 17:31:38 +00:00
|
|
|
[self setRelationship: @"super" from: unit to: tmp];
|
2001-10-15 14:42:56 +00:00
|
|
|
}
|
2002-01-03 20:17:28 +00:00
|
|
|
[self setGlobalRef: unit type: @"class"];
|
2001-10-15 14:42:56 +00:00
|
|
|
}
|
|
|
|
else if ([name isEqual: @"gsdoc"] == YES)
|
|
|
|
{
|
|
|
|
base = [prop objectForKey: @"base"];
|
|
|
|
if (base == nil)
|
|
|
|
{
|
|
|
|
NSLog(@"No 'base' document name supplied in gsdoc element");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2001-12-17 22:36:30 +00:00
|
|
|
else if ([name isEqual: @"heading"] == YES)
|
|
|
|
{
|
|
|
|
NSMutableDictionary *d;
|
|
|
|
NSString *k;
|
2003-03-23 07:06:27 +00:00
|
|
|
NSString *c;
|
2001-12-17 22:36:30 +00:00
|
|
|
|
|
|
|
d = [refs objectForKey: @"contents"];
|
|
|
|
if (d == nil)
|
|
|
|
{
|
|
|
|
d = [[NSMutableDictionary alloc] initWithCapacity: 8];
|
|
|
|
[refs setObject: d forKey: @"contents"];
|
|
|
|
RELEASE(d);
|
|
|
|
}
|
|
|
|
|
|
|
|
k = [NSString stringWithFormat: @"%03u%03u%03u%03u",
|
|
|
|
chap, sect, ssect, sssect];
|
2003-03-23 07:06:27 +00:00
|
|
|
c = [[children content] stringByTrimmingSpaces];
|
|
|
|
if (c == nil) c = @"";
|
|
|
|
[d setObject: c forKey: k];
|
2001-12-17 22:36:30 +00:00
|
|
|
children = nil;
|
|
|
|
}
|
2001-10-15 14:42:56 +00:00
|
|
|
else if ([name isEqual: @"ivariable"] == YES)
|
|
|
|
{
|
|
|
|
NSString *tmp = [prop objectForKey: @"name"];
|
|
|
|
|
2002-01-08 17:31:38 +00:00
|
|
|
[self setUnitRef: tmp type: @"ivariable"];
|
|
|
|
[self setUnitRef: tmp type: @"classvars"];
|
2001-10-15 14:42:56 +00:00
|
|
|
}
|
|
|
|
else if ([name isEqual: @"entry"] || [name isEqual: @"label"])
|
|
|
|
{
|
|
|
|
NSMutableDictionary *all;
|
|
|
|
NSMutableDictionary *byFile;
|
|
|
|
NSString *text;
|
|
|
|
NSString *val;
|
|
|
|
|
2001-12-17 22:36:30 +00:00
|
|
|
text = [[children content] stringByTrimmingSpaces];
|
2003-03-23 07:06:27 +00:00
|
|
|
if (text == nil) text = @"";
|
2001-10-15 14:42:56 +00:00
|
|
|
children = nil;
|
|
|
|
all = [refs objectForKey: name];
|
|
|
|
if (all == nil)
|
|
|
|
{
|
|
|
|
all = [[NSMutableDictionary alloc] initWithCapacity: 8];
|
|
|
|
[refs setObject: all forKey: name];
|
|
|
|
RELEASE(all);
|
|
|
|
}
|
|
|
|
byFile = [all objectForKey: base];
|
|
|
|
if (byFile == nil)
|
|
|
|
{
|
|
|
|
byFile = [[NSMutableDictionary alloc] initWithCapacity: 2];
|
|
|
|
[all setObject: byFile forKey: base];
|
|
|
|
RELEASE(byFile);
|
|
|
|
}
|
|
|
|
val = [prop objectForKey: @"id"];
|
|
|
|
if (val == nil)
|
|
|
|
{
|
|
|
|
val = text;
|
|
|
|
}
|
|
|
|
[byFile setObject: val forKey: @"text"];
|
|
|
|
}
|
|
|
|
else if ([name isEqual: @"method"] == YES)
|
|
|
|
{
|
|
|
|
NSString *sel = @"";
|
|
|
|
GSXMLNode *tmp = children;
|
|
|
|
|
|
|
|
sel = [prop objectForKey: @"factory"];
|
|
|
|
if (sel != nil && [sel boolValue] == YES)
|
|
|
|
{
|
|
|
|
sel = @"+";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sel = @"-";
|
|
|
|
}
|
|
|
|
children = nil;
|
|
|
|
while (tmp != nil)
|
|
|
|
{
|
|
|
|
if ([tmp type] == XML_ELEMENT_NODE)
|
|
|
|
{
|
|
|
|
if ([[tmp name] isEqual: @"sel"] == YES)
|
|
|
|
{
|
2002-05-22 14:23:17 +00:00
|
|
|
GSXMLNode *t = [tmp firstChild];
|
2001-10-15 14:42:56 +00:00
|
|
|
|
|
|
|
while (t != nil)
|
|
|
|
{
|
|
|
|
if ([t type] == XML_TEXT_NODE)
|
|
|
|
{
|
2003-03-23 07:06:27 +00:00
|
|
|
NSString *s;
|
|
|
|
|
|
|
|
s = [[t content] stringByTrimmingSpaces];
|
|
|
|
if (s == nil) s = @"";
|
|
|
|
sel = [sel stringByAppendingString: s];
|
2001-10-15 14:42:56 +00:00
|
|
|
}
|
|
|
|
t = [t next];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ([[tmp name] isEqual: @"vararg"] == YES)
|
|
|
|
{
|
|
|
|
sel = [sel stringByAppendingString: @",..."];
|
|
|
|
children = [tmp next];
|
|
|
|
break;
|
|
|
|
}
|
2002-12-17 10:04:46 +00:00
|
|
|
else if ([[tmp name] isEqual: @"arg"] == NO)
|
|
|
|
{
|
|
|
|
children = tmp;
|
|
|
|
break;
|
|
|
|
}
|
2001-10-15 14:42:56 +00:00
|
|
|
}
|
|
|
|
tmp = [tmp next];
|
|
|
|
}
|
|
|
|
if ([sel length] > 1)
|
|
|
|
{
|
2002-01-08 17:31:38 +00:00
|
|
|
[self setUnitRef: sel type: @"method"];
|
|
|
|
[self setUnitRef: sel type: @"unitmethods"];
|
2001-10-15 14:42:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ([name isEqual: @"protocol"] == YES)
|
|
|
|
{
|
|
|
|
newUnit = YES;
|
2001-11-21 17:10:22 +00:00
|
|
|
unit = [NSString stringWithFormat: @"(%@)",
|
|
|
|
[prop objectForKey: @"name"]];
|
2002-01-03 20:17:28 +00:00
|
|
|
[self setGlobalRef: unit type: @"protocol"];
|
2001-10-15 14:42:56 +00:00
|
|
|
}
|
|
|
|
else if ([name isEqual: @"constant"] == YES
|
|
|
|
|| [name isEqual: @"EOEntity"] == YES
|
|
|
|
|| [name isEqual: @"EOModel"] == YES
|
|
|
|
|| [name isEqual: @"function"] == YES
|
|
|
|
|| [name isEqual: @"macro"] == YES
|
|
|
|
|| [name isEqual: @"type"] == YES
|
|
|
|
|| [name isEqual: @"variable"] == YES)
|
|
|
|
{
|
|
|
|
NSString *tmp = [prop objectForKey: @"name"];
|
|
|
|
|
|
|
|
[self setGlobalRef: tmp type: name];
|
2002-02-04 20:20:07 +00:00
|
|
|
children = nil;
|
2001-10-15 14:42:56 +00:00
|
|
|
}
|
2001-12-17 22:36:30 +00:00
|
|
|
else if ([name isEqual: @"section"] == YES)
|
|
|
|
{
|
|
|
|
sect++;
|
|
|
|
ssect = 0;
|
|
|
|
sssect = 0;
|
|
|
|
}
|
|
|
|
else if ([name isEqual: @"subsect"] == YES)
|
|
|
|
{
|
|
|
|
ssect++;
|
|
|
|
sssect = 0;
|
|
|
|
}
|
|
|
|
else if ([name isEqual: @"subsubsect"] == YES)
|
|
|
|
{
|
|
|
|
sssect++;
|
|
|
|
}
|
2001-12-18 08:39:00 +00:00
|
|
|
else if ([name isEqual: @"title"] == YES)
|
|
|
|
{
|
|
|
|
NSMutableDictionary *d;
|
2003-03-23 07:06:27 +00:00
|
|
|
NSString *s;
|
2001-12-18 08:39:00 +00:00
|
|
|
|
|
|
|
d = [refs objectForKey: @"title"];
|
|
|
|
if (d == nil)
|
|
|
|
{
|
|
|
|
d = [[NSMutableDictionary alloc] initWithCapacity: 8];
|
|
|
|
[refs setObject: d forKey: @"title"];
|
|
|
|
RELEASE(d);
|
|
|
|
}
|
|
|
|
|
2003-03-23 07:06:27 +00:00
|
|
|
s = [[children content] stringByTrimmingSpaces];
|
|
|
|
if (s == nil) s = @"";
|
|
|
|
[d setObject: s forKey: base];
|
2001-12-18 08:39:00 +00:00
|
|
|
children = nil;
|
|
|
|
}
|
2001-10-15 14:42:56 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (children != nil)
|
|
|
|
{
|
|
|
|
[self makeRefs: children];
|
|
|
|
}
|
|
|
|
if (newUnit == YES)
|
|
|
|
{
|
|
|
|
unit = nil;
|
2002-01-08 17:31:38 +00:00
|
|
|
category = nil;
|
|
|
|
classname = nil;
|
2001-10-15 14:42:56 +00:00
|
|
|
}
|
|
|
|
if (next != nil)
|
|
|
|
{
|
|
|
|
[self makeRefs: next];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-12-15 09:05:19 +00:00
|
|
|
/**
|
|
|
|
* Merge a dictionary containing references into the current
|
|
|
|
* index. The flag may be used to specify that references
|
|
|
|
* being merged in should override any pre-existing values.
|
|
|
|
*/
|
|
|
|
- (void) mergeRefs: (NSDictionary*)more override: (BOOL)flag
|
2001-10-15 14:42:56 +00:00
|
|
|
{
|
2001-12-15 09:05:19 +00:00
|
|
|
mergeDictionaries(refs, more, flag);
|
2001-10-15 14:42:56 +00:00
|
|
|
}
|
|
|
|
|
2002-01-08 17:31:38 +00:00
|
|
|
- (NSArray*) methodsInUnit: (NSString*)aUnit
|
2001-12-17 08:27:49 +00:00
|
|
|
{
|
2002-01-08 17:31:38 +00:00
|
|
|
NSDictionary *d = [refs objectForKey: @"unitmethods"];
|
2001-12-17 08:27:49 +00:00
|
|
|
|
2002-01-08 17:31:38 +00:00
|
|
|
d = [d objectForKey: aUnit];
|
|
|
|
return [d allKeys];
|
2001-12-17 08:27:49 +00:00
|
|
|
}
|
|
|
|
|
2002-05-13 21:24:13 +00:00
|
|
|
/**
|
|
|
|
* Return a list of output files for the header
|
|
|
|
*/
|
|
|
|
- (NSMutableArray*) outputsForHeader: (NSString*)h
|
|
|
|
{
|
|
|
|
NSDictionary *dict = [refs objectForKey: @"output"];
|
|
|
|
NSArray *array = [dict objectForKey: h];
|
|
|
|
|
|
|
|
if (array == nil)
|
|
|
|
{
|
|
|
|
return [NSMutableArray arrayWithCapacity: 2];
|
|
|
|
}
|
|
|
|
return AUTORELEASE([array mutableCopy]);
|
|
|
|
}
|
|
|
|
|
2001-10-15 14:42:56 +00:00
|
|
|
- (NSMutableDictionary*) refs
|
|
|
|
{
|
|
|
|
return refs;
|
|
|
|
}
|
|
|
|
|
2001-11-29 07:38:04 +00:00
|
|
|
- (void) setDirectory: (NSString*)path
|
|
|
|
{
|
|
|
|
if (path != nil)
|
|
|
|
{
|
|
|
|
CREATE_AUTORELEASE_POOL(pool);
|
|
|
|
setDirectory(refs, path);
|
|
|
|
RELEASE(pool);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-10-15 14:42:56 +00:00
|
|
|
- (void) setGlobalRef: (NSString*)ref
|
|
|
|
type: (NSString*)type
|
|
|
|
{
|
|
|
|
NSMutableDictionary *t;
|
|
|
|
NSString *old;
|
|
|
|
|
|
|
|
t = [refs objectForKey: type];
|
|
|
|
if (t == nil)
|
|
|
|
{
|
|
|
|
t = [NSMutableDictionary new];
|
|
|
|
[refs setObject: t forKey: type];
|
|
|
|
RELEASE(t);
|
|
|
|
}
|
|
|
|
old = [t objectForKey: ref];
|
|
|
|
if (old != nil && [old isEqual: base] == NO)
|
|
|
|
{
|
|
|
|
NSLog(@"Warning ... %@ %@ appears in %@ and %@ ... using the latter",
|
|
|
|
type, ref, old, base);
|
|
|
|
}
|
|
|
|
[t setObject: base forKey: ref];
|
|
|
|
}
|
|
|
|
|
2002-05-13 21:24:13 +00:00
|
|
|
/**
|
|
|
|
* Set up an array listing the output files for a particular header.
|
|
|
|
*/
|
|
|
|
- (void) setOutputs: (NSArray*)a forHeader: (NSString*)h
|
|
|
|
{
|
|
|
|
NSMutableDictionary *dict;
|
|
|
|
|
|
|
|
dict = [refs objectForKey: @"output"];
|
|
|
|
if (dict == nil)
|
|
|
|
{
|
|
|
|
dict = [NSMutableDictionary new];
|
|
|
|
[refs setObject: dict forKey: @"output"];
|
|
|
|
RELEASE(dict);
|
|
|
|
}
|
|
|
|
[dict setObject: a forKey: h];
|
|
|
|
}
|
|
|
|
|
2002-01-08 17:31:38 +00:00
|
|
|
- (void) setRelationship: (NSString*)r from: (NSString*)from to: (NSString*)to
|
|
|
|
{
|
|
|
|
NSMutableDictionary *dict;
|
|
|
|
|
|
|
|
dict = [refs objectForKey: r];
|
|
|
|
if (dict == nil)
|
|
|
|
{
|
|
|
|
dict = [NSMutableDictionary new];
|
|
|
|
[refs setObject: dict forKey: r];
|
|
|
|
RELEASE(dict);
|
|
|
|
}
|
|
|
|
[dict setObject: to forKey: from];
|
|
|
|
}
|
|
|
|
|
2002-02-26 17:36:33 +00:00
|
|
|
/**
|
|
|
|
* Set up an array listing the source files for a particular header.
|
|
|
|
*/
|
2002-03-06 18:11:55 +00:00
|
|
|
- (void) setSources: (NSArray*)a forHeader: (NSString*)h
|
2002-02-26 17:36:33 +00:00
|
|
|
{
|
|
|
|
NSMutableDictionary *dict;
|
|
|
|
|
|
|
|
dict = [refs objectForKey: @"source"];
|
|
|
|
if (dict == nil)
|
|
|
|
{
|
|
|
|
dict = [NSMutableDictionary new];
|
|
|
|
[refs setObject: dict forKey: @"source"];
|
|
|
|
RELEASE(dict);
|
|
|
|
}
|
2002-03-06 18:11:55 +00:00
|
|
|
[dict setObject: a forKey: h];
|
2002-02-26 17:36:33 +00:00
|
|
|
}
|
|
|
|
|
2002-01-08 17:31:38 +00:00
|
|
|
/**
|
|
|
|
* Set up a reference for something inside a unit (class, category or protocol)
|
|
|
|
* We store 'method' and 'ivariable' by ref then unit (class),
|
|
|
|
* but we store 'unitmethods' * and 'classvars' by unit then ref.
|
|
|
|
*/
|
2001-10-15 14:42:56 +00:00
|
|
|
- (void) setUnitRef: (NSString*)ref
|
|
|
|
type: (NSString*)type
|
|
|
|
{
|
|
|
|
NSMutableDictionary *t;
|
|
|
|
NSMutableDictionary *r;
|
2002-01-08 17:31:38 +00:00
|
|
|
NSString *u = unit;
|
2001-10-15 14:42:56 +00:00
|
|
|
NSString *old;
|
|
|
|
|
2002-01-08 17:31:38 +00:00
|
|
|
if ([type isEqualToString: @"method"] || [type isEqualToString: @"ivariable"])
|
|
|
|
{
|
|
|
|
if (category != nil)
|
|
|
|
{
|
|
|
|
u = classname; // Store category methods by classname.
|
|
|
|
}
|
|
|
|
// type ... ref ... unit ... file
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-02-12 12:33:57 +00:00
|
|
|
u = ref;
|
|
|
|
ref = unit;
|
2002-01-08 17:31:38 +00:00
|
|
|
}
|
|
|
|
|
2001-10-15 14:42:56 +00:00
|
|
|
t = [refs objectForKey: type];
|
|
|
|
if (t == nil)
|
|
|
|
{
|
|
|
|
t = [NSMutableDictionary new];
|
|
|
|
[refs setObject: t forKey: type];
|
|
|
|
RELEASE(t);
|
|
|
|
}
|
|
|
|
r = [t objectForKey: ref];
|
|
|
|
if (r == nil)
|
|
|
|
{
|
|
|
|
r = [NSMutableDictionary new];
|
|
|
|
[t setObject: r forKey: ref];
|
|
|
|
RELEASE(r);
|
|
|
|
}
|
2002-01-08 17:31:38 +00:00
|
|
|
old = [r objectForKey: u];
|
2001-10-15 14:42:56 +00:00
|
|
|
if (old != nil && [old isEqual: base] == NO)
|
|
|
|
{
|
|
|
|
NSLog(@"Warning ... %@ %@ %@ appears in %@ and %@ ... using the latter",
|
2002-01-08 17:31:38 +00:00
|
|
|
type, ref, u, old, base);
|
2001-10-15 14:42:56 +00:00
|
|
|
}
|
2002-01-08 17:31:38 +00:00
|
|
|
[r setObject: base forKey: u];
|
2001-10-15 14:42:56 +00:00
|
|
|
}
|
|
|
|
|
2002-02-26 17:36:33 +00:00
|
|
|
/**
|
2002-05-13 21:24:13 +00:00
|
|
|
* Return a list of source files for the header.
|
2002-02-26 17:36:33 +00:00
|
|
|
*/
|
|
|
|
- (NSArray*) sourcesForHeader: (NSString*)h
|
|
|
|
{
|
|
|
|
NSDictionary *dict = [refs objectForKey: @"source"];
|
2002-05-13 21:24:13 +00:00
|
|
|
NSArray *array = [dict objectForKey: h];
|
2002-02-26 17:36:33 +00:00
|
|
|
|
2002-05-13 21:24:13 +00:00
|
|
|
if (array == nil)
|
|
|
|
{
|
|
|
|
return [NSMutableArray arrayWithCapacity: 2];
|
|
|
|
}
|
|
|
|
return AUTORELEASE([array mutableCopy]);
|
2002-02-26 17:36:33 +00:00
|
|
|
}
|
|
|
|
|
2002-01-03 20:17:28 +00:00
|
|
|
/**
|
|
|
|
* Return a dictionary containing info on all the units containing the
|
|
|
|
* specified method or instance variable.
|
|
|
|
*/
|
2001-11-21 17:10:22 +00:00
|
|
|
- (NSDictionary*) unitRef: (NSString*)ref type: (NSString*)type
|
|
|
|
{
|
|
|
|
NSDictionary *t;
|
|
|
|
|
|
|
|
t = [refs objectForKey: type];
|
|
|
|
return [t objectForKey: ref];
|
|
|
|
}
|
|
|
|
|
2002-01-03 20:17:28 +00:00
|
|
|
/**
|
|
|
|
* Return the name of the file containing the ref and return
|
|
|
|
* the unit name in which it was found. If not found, return nil for both.
|
|
|
|
*/
|
|
|
|
- (NSString*) unitRef: (NSString*)ref type: (NSString*)type unit: (NSString**)u
|
2001-11-21 17:10:22 +00:00
|
|
|
{
|
2002-01-03 20:17:28 +00:00
|
|
|
NSString *s;
|
2001-11-21 17:10:22 +00:00
|
|
|
NSDictionary *t;
|
|
|
|
|
2002-01-03 20:17:28 +00:00
|
|
|
/**
|
|
|
|
* If ref does not occur in the index, this method returns nil.
|
|
|
|
*/
|
|
|
|
t = [self unitRef: ref type: type];
|
|
|
|
if (t == nil)
|
|
|
|
{
|
|
|
|
*u = nil;
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
if (*u == nil)
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* If the method was given no unit to look in, then it will succeed
|
|
|
|
* and return a value if (and only if) the required reference is
|
|
|
|
* defined only in one unit.
|
|
|
|
*/
|
|
|
|
if ([t count] == 1)
|
|
|
|
{
|
|
|
|
*u = [[t allKeys] lastObject];
|
|
|
|
return [t objectForKey: *u];
|
|
|
|
}
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If ref exists in the unit specified, the method will succeed and
|
|
|
|
* return the name of the file in which the reference is located.
|
|
|
|
*/
|
|
|
|
s = [t objectForKey: *u];
|
|
|
|
if (s != nil)
|
|
|
|
{
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If the unit that the method has been asked to look in is a
|
|
|
|
* category or protocol which is not found, the lookup must fail.
|
|
|
|
*/
|
|
|
|
if ([t objectForKey: *u] == nil
|
|
|
|
&& ([*u length] == 0 || [*u characterAtIndex: [*u length] - 1] == ')'))
|
|
|
|
{
|
|
|
|
*u = nil;
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If the unit is a class, and ref was not found in it, then this
|
|
|
|
* method will succeed if ref can be found in any superclass of the class.
|
|
|
|
*/
|
|
|
|
while (*u != nil)
|
|
|
|
{
|
|
|
|
*u = [self globalRef: *u type: @"super"];
|
|
|
|
if (*u != nil)
|
|
|
|
{
|
2002-11-04 15:39:43 +00:00
|
|
|
*u = [*u lastPathComponent];
|
2002-01-03 20:17:28 +00:00
|
|
|
s = [t objectForKey: *u];
|
|
|
|
if (s != nil)
|
|
|
|
{
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil;
|
2001-11-21 17:10:22 +00:00
|
|
|
}
|
|
|
|
|
2001-10-15 14:42:56 +00:00
|
|
|
@end
|
|
|
|
|