mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-30 16:30:41 +00:00
Rewritten to use a different better link system which is also compatible
with the current autogsdoc link systme git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@12012 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
18503e9b22
commit
e626c6fab9
1 changed files with 378 additions and 253 deletions
|
@ -31,15 +31,22 @@ static NSFileManager *fileManager = nil;
|
||||||
/* [[NSFileManager defaulManager] currentDirectoryPath] */
|
/* [[NSFileManager defaulManager] currentDirectoryPath] */
|
||||||
static NSString *currentPath = nil;
|
static NSString *currentPath = nil;
|
||||||
|
|
||||||
/* Enumerate all .html files in a directory and subdirectories. */
|
/* Enumerate all .html (or .htmlink) files in a directory and
|
||||||
|
subdirectories. */
|
||||||
@interface HTMLDirectoryEnumerator : NSEnumerator
|
@interface HTMLDirectoryEnumerator : NSEnumerator
|
||||||
{
|
{
|
||||||
NSDirectoryEnumerator *e;
|
NSDirectoryEnumerator *e;
|
||||||
NSString *basePath;
|
NSString *basePath;
|
||||||
|
BOOL looksForHTMLLinkFiles;
|
||||||
|
BOOL returnsAbsolutePaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithBasePath: (NSString *)path;
|
- (id)initWithBasePath: (NSString *)path;
|
||||||
|
|
||||||
|
- (void)setReturnsAbsolutePaths: (BOOL)flag;
|
||||||
|
|
||||||
|
- (void)setLooksForHTMLLinkFiles: (BOOL)flag;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation HTMLDirectoryEnumerator : NSEnumerator
|
@implementation HTMLDirectoryEnumerator : NSEnumerator
|
||||||
|
@ -58,22 +65,52 @@ static NSString *currentPath = nil;
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setReturnsAbsolutePaths: (BOOL)flag
|
||||||
|
{
|
||||||
|
returnsAbsolutePaths = flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setLooksForHTMLLinkFiles: (BOOL)flag
|
||||||
|
{
|
||||||
|
looksForHTMLLinkFiles = YES;
|
||||||
|
}
|
||||||
|
|
||||||
- (id)nextObject
|
- (id)nextObject
|
||||||
{
|
{
|
||||||
NSString *s;
|
NSString *s;
|
||||||
|
|
||||||
while ((s = [e nextObject]) != nil)
|
while ((s = [e nextObject]) != nil)
|
||||||
{
|
{
|
||||||
|
BOOL found = NO;
|
||||||
NSString *extension = [s pathExtension];
|
NSString *extension = [s pathExtension];
|
||||||
|
|
||||||
if ([extension isEqualToString: @"html"]
|
if (looksForHTMLLinkFiles)
|
||||||
|| [extension isEqualToString: @"HTML"]
|
|
||||||
|| [extension isEqualToString: @"htm"]
|
|
||||||
|| [extension isEqualToString: @"HTM"])
|
|
||||||
{
|
{
|
||||||
/* NSDirectoryEnumerator returns the relative path, we
|
if ([extension isEqualToString: @"htmlink"])
|
||||||
return the absolute. */
|
{
|
||||||
return [basePath stringByAppendingPathComponent: s];
|
found = YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ([extension isEqualToString: @"html"]
|
||||||
|
|| [extension isEqualToString: @"HTML"]
|
||||||
|
|| [extension isEqualToString: @"htm"]
|
||||||
|
|| [extension isEqualToString: @"HTM"])
|
||||||
|
{
|
||||||
|
found = YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found)
|
||||||
|
{
|
||||||
|
if (returnsAbsolutePaths)
|
||||||
|
{
|
||||||
|
/* NSDirectoryEnumerator returns the relative path, we
|
||||||
|
return the absolute. */
|
||||||
|
return [basePath stringByAppendingPathComponent: s];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,65 +119,31 @@ static NSString *currentPath = nil;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
/*
|
|
||||||
* An object representing a file which can be a destination of links.
|
|
||||||
*/
|
|
||||||
@interface DestinationFile : NSObject
|
|
||||||
{
|
|
||||||
/* Full name to be used when fixing up links to this file. */
|
|
||||||
NSString *fullName;
|
|
||||||
|
|
||||||
/* Path on disk needed to read the file from disk - needed only when
|
|
||||||
performing link checking. pathOnDisk might be different from
|
|
||||||
fullName, for example for a file on a web server. In that case,
|
|
||||||
fullName is the URI to the file on the web server, while
|
|
||||||
pathOnDisk is the path to the file on disk. */
|
|
||||||
NSString *pathOnDisk;
|
|
||||||
|
|
||||||
/* If the file has already been read to perform link checking, names
|
|
||||||
is the array of all names (for any <a name="xxx"> in the file,
|
|
||||||
xxx is put in the names array for that file) in the file. If it
|
|
||||||
hasn't yet been read, it's nil. We read the file and parse it
|
|
||||||
lazily, only if needed. */
|
|
||||||
NSArray *names;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the full name. */
|
|
||||||
- (NSString *)fullName;
|
|
||||||
|
|
||||||
/* Checks that the file on disk contains <a name="xxx"> where xxx is
|
|
||||||
name, lazily loading and parsing the file if needed. Return YES if
|
|
||||||
the file contains name, NO if it doesn't. */
|
|
||||||
- (BOOL)checkAnchorName: (NSString *)name;
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
/* The HTMLLinker class is very simple and is the core of the linker.
|
/* The HTMLLinker class is very simple and is the core of the linker.
|
||||||
It just keeps a table of the available destination files, and is
|
It just keeps a relocation, and is able to fixup a link by using
|
||||||
able to fixup a link to point to one of those files. */
|
the relocation table. */
|
||||||
@interface HTMLLinker : NSObject
|
@interface HTMLLinker : NSObject
|
||||||
{
|
{
|
||||||
BOOL verbose;
|
BOOL warn;
|
||||||
BOOL checkLinks;
|
BOOL hasPathMappings;
|
||||||
NSMutableDictionary *files;
|
|
||||||
NSMutableDictionary *pathMappings;
|
NSMutableDictionary *pathMappings;
|
||||||
|
NSMutableDictionary *relocationTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithVerboseFlag: (BOOL)v
|
- (id)initWithWarnFlag: (BOOL)v;
|
||||||
checkLinksFlag: (BOOL)f;
|
|
||||||
|
|
||||||
/* Register the file as available for resolving references. */
|
- (void)registerRelocationFile: (NSString *)pathOnDisk;
|
||||||
- (void)registerFile: (NSString *)pathOnDisk;
|
|
||||||
|
- (void)registerDestinationFile: (NSString *)pathOnDisk;
|
||||||
|
|
||||||
/* Register a new path mapping. */
|
/* Register a new path mapping. */
|
||||||
- (void)registerPathMappings: (NSDictionary *)dict;
|
- (void)registerPathMappings: (NSDictionary *)dict;
|
||||||
|
|
||||||
/* Resolve the link 'link' by fixing it up using the registered
|
/* Resolve the link 'link' by fixing it up using the relocation table.
|
||||||
destination files. Return the resolved link. 'logFile' is only
|
Return the resolved link. 'logFile' is only used to print error
|
||||||
used to print error messages. It is the file in which the link is
|
messages. It is the file in which the link is originally found; if
|
||||||
originally found; if there is problem resolving the link, the
|
there is problem resolving the link, the warning message printed
|
||||||
warning message printed out states that the problem is in file
|
out states that the problem is in file 'logFile'. */
|
||||||
'logFile'. */
|
|
||||||
- (NSString *)resolveLink: (NSString *)link
|
- (NSString *)resolveLink: (NSString *)link
|
||||||
logFile: (NSString *)logFile;
|
logFile: (NSString *)logFile;
|
||||||
|
|
||||||
|
@ -156,7 +159,8 @@ static NSString *currentPath = nil;
|
||||||
library, so you can use the HTML linker on any system. This class
|
library, so you can use the HTML linker on any system. This class
|
||||||
was written in order to perform its trivial, mechanical duty /very
|
was written in order to perform its trivial, mechanical duty /very
|
||||||
fast/. You want to be able to run the linker often and on a lot of
|
fast/. You want to be able to run the linker often and on a lot of
|
||||||
files and still be happy. */
|
files and still be happy. FIXME - Need to implement support for
|
||||||
|
newer HTML where you can use id="name" in any tag. */
|
||||||
@interface HTMLParser : NSObject
|
@interface HTMLParser : NSObject
|
||||||
{
|
{
|
||||||
/* The HTML code that we work on. */
|
/* The HTML code that we work on. */
|
||||||
|
@ -172,15 +176,14 @@ static NSString *currentPath = nil;
|
||||||
|
|
||||||
/* Fix up all the links in the HTML code by feeding each of them to
|
/* Fix up all the links in the HTML code by feeding each of them to
|
||||||
the provided HTMLLinker; return the fixed up HTML code. If
|
the provided HTMLLinker; return the fixed up HTML code. If
|
||||||
fixupAllLinks is 'NO', only fixup links with rel="dynamical"; if
|
linksMarker is nil, attempts to fix up all links in the HTML code;
|
||||||
fixupAllLinks is 'YES', attempt to fixup all links in the HTML
|
if it is not-nil, only attempt to fixup links with rel=marker.
|
||||||
code. logFile is the file we are fixing up; it's only used when a
|
logFile is the file we are fixing up; it's only used when a warning
|
||||||
warning is issued because there is problem in the linking - the
|
is issued because there is problem in the linking - the warning
|
||||||
warning message is displayed as being about links in the file
|
message is displayed as being about links in the file logFile. */
|
||||||
logFile. */
|
|
||||||
- (NSString *)resolveLinksUsingHTMLLinker: (HTMLLinker *)linker
|
- (NSString *)resolveLinksUsingHTMLLinker: (HTMLLinker *)linker
|
||||||
logFile: (NSString *)logFile
|
logFile: (NSString *)logFile
|
||||||
fixupAllLinks: (BOOL)fixupAllLinks;
|
linksMarker: (NSString *)marker;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
@ -358,12 +361,10 @@ static NSString *currentPath = nil;
|
||||||
{
|
{
|
||||||
name = [NSString stringWithCharacters: &chars[s]
|
name = [NSString stringWithCharacters: &chars[s]
|
||||||
length: (i - s)];
|
length: (i - s)];
|
||||||
/* Per HTML specs we lowercase name. */
|
|
||||||
name = [name lowercaseString];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name != nil)
|
if (name != nil)
|
||||||
{
|
{
|
||||||
[names addObject: name];
|
[names addObject: name];
|
||||||
|
@ -378,7 +379,7 @@ static NSString *currentPath = nil;
|
||||||
|
|
||||||
- (NSString *)resolveLinksUsingHTMLLinker: (HTMLLinker *)linker
|
- (NSString *)resolveLinksUsingHTMLLinker: (HTMLLinker *)linker
|
||||||
logFile: (NSString *)logFile
|
logFile: (NSString *)logFile
|
||||||
fixupAllLinks: (BOOL)fixupAllLinks
|
linksMarker: (NSString *)marker
|
||||||
{
|
{
|
||||||
/* We represent the output as a linked list. Each element in the
|
/* We represent the output as a linked list. Each element in the
|
||||||
linked list represents a string; concatenating all the strings in
|
linked list represents a string; concatenating all the strings in
|
||||||
|
@ -638,8 +639,8 @@ static NSString *currentPath = nil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (href != nil && (fixupAllLinks
|
if (href != nil && ((marker == nil)
|
||||||
|| [rel isEqualToString: @"dynamical"]))
|
|| [rel isEqualToString: marker]))
|
||||||
{
|
{
|
||||||
/* Ok - fixup the link. */
|
/* Ok - fixup the link. */
|
||||||
NSString *link;
|
NSString *link;
|
||||||
|
@ -727,78 +728,109 @@ static NSString *currentPath = nil;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
@implementation DestinationFile
|
|
||||||
|
|
||||||
- (id)initWithFullName: (NSString *)f
|
|
||||||
pathOnDisk: (NSString *)p
|
|
||||||
{
|
|
||||||
ASSIGN (fullName, f);
|
|
||||||
ASSIGN (pathOnDisk, p);
|
|
||||||
|
|
||||||
return [super init];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
- (void)dealloc
|
|
||||||
{
|
|
||||||
RELEASE (fullName);
|
|
||||||
RELEASE (pathOnDisk);
|
|
||||||
RELEASE (names);
|
|
||||||
[super dealloc];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *)fullName
|
|
||||||
{
|
|
||||||
return fullName;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)checkAnchorName: (NSString *)name
|
|
||||||
{
|
|
||||||
/* No anchor. */
|
|
||||||
if (name == nil || [name isEqualToString: @""])
|
|
||||||
{
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (names == nil)
|
|
||||||
{
|
|
||||||
/* Load the file and parse it, saving the result in names. */
|
|
||||||
NSString *file = [NSString stringWithContentsOfFile: pathOnDisk];
|
|
||||||
HTMLParser *parser = [[HTMLParser alloc] initWithCode: file];
|
|
||||||
|
|
||||||
ASSIGN (names, [parser names]);
|
|
||||||
RELEASE (parser);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [names containsObject: name];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
|
|
||||||
@implementation HTMLLinker
|
@implementation HTMLLinker
|
||||||
|
|
||||||
- (id)initWithVerboseFlag: (BOOL)v
|
- (id)initWithWarnFlag: (BOOL)v
|
||||||
checkLinksFlag: (BOOL)f
|
|
||||||
{
|
{
|
||||||
verbose = v;
|
warn = v;
|
||||||
checkLinks = f;
|
relocationTable = [NSMutableDictionary new];
|
||||||
files = [NSMutableDictionary new];
|
|
||||||
pathMappings = [NSMutableDictionary new];
|
pathMappings = [NSMutableDictionary new];
|
||||||
return [super init];
|
return [super init];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
RELEASE (files);
|
RELEASE (relocationTable);
|
||||||
RELEASE (pathMappings);
|
RELEASE (pathMappings);
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)registerFile: (NSString *)pathOnDisk
|
- (void)registerRelocationFile: (NSString *)pathOnDisk
|
||||||
|
{
|
||||||
|
/* We only accept absolute paths. */
|
||||||
|
if (![pathOnDisk isAbsolutePath])
|
||||||
|
{
|
||||||
|
pathOnDisk = [currentPath stringByAppendingPathComponent: pathOnDisk];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if it's a directory; if it is, enumerate all .htmlink files
|
||||||
|
inside it, and add all of them. */
|
||||||
|
{
|
||||||
|
BOOL isDir;
|
||||||
|
|
||||||
|
if (![fileManager fileExistsAtPath: pathOnDisk isDirectory: &isDir])
|
||||||
|
{
|
||||||
|
NSLog (@"Warning - relocation file '%@' not found - ignored",
|
||||||
|
pathOnDisk);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (isDir)
|
||||||
|
{
|
||||||
|
HTMLDirectoryEnumerator *e;
|
||||||
|
NSString *filename;
|
||||||
|
|
||||||
|
e = [HTMLDirectoryEnumerator alloc];
|
||||||
|
e = [e initWithBasePath: pathOnDisk];
|
||||||
|
[e setLooksForHTMLLinkFiles: YES];
|
||||||
|
[e setReturnsAbsolutePaths: YES];
|
||||||
|
|
||||||
|
while ((filename = [e nextObject]) != nil)
|
||||||
|
{
|
||||||
|
[self registerRelocationFile: filename];
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now, read the mappings in the file. */
|
||||||
|
{
|
||||||
|
NSString *file = [NSString stringWithContentsOfFile: pathOnDisk];
|
||||||
|
NSString *path = [pathOnDisk stringByDeletingLastPathComponent];
|
||||||
|
NSDictionary *d = [file propertyList];
|
||||||
|
NSEnumerator *e = [d keyEnumerator];
|
||||||
|
NSString *name;
|
||||||
|
|
||||||
|
while ((name = [e nextObject]) != nil)
|
||||||
|
{
|
||||||
|
NSString *v = [d objectForKey: name];
|
||||||
|
NSString *filePath;
|
||||||
|
|
||||||
|
filePath = [path stringByAppendingPathComponent: v];
|
||||||
|
|
||||||
|
if (hasPathMappings)
|
||||||
|
{
|
||||||
|
/* Manage pathMappings: try to match any of the
|
||||||
|
pathMappings against pathOnDisk, and perform the path
|
||||||
|
mapping if we can match. */
|
||||||
|
NSEnumerator *en = [pathMappings keyEnumerator];
|
||||||
|
NSString *key;
|
||||||
|
|
||||||
|
while ((key = [en nextObject]))
|
||||||
|
{
|
||||||
|
if ([filePath hasPrefix: key])
|
||||||
|
{
|
||||||
|
NSString *value = [pathMappings objectForKey: key];
|
||||||
|
|
||||||
|
filePath = [filePath substringFromIndex: [key length]];
|
||||||
|
filePath = [value stringByAppendingPathComponent:
|
||||||
|
filePath];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[relocationTable setObject: filePath forKey: name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (void)registerDestinationFile: (NSString *)pathOnDisk
|
||||||
{
|
{
|
||||||
NSString *fullPath = pathOnDisk;
|
NSString *fullPath = pathOnDisk;
|
||||||
DestinationFile *file;
|
|
||||||
|
|
||||||
/* We only accept absolute paths. */
|
/* We only accept absolute paths. */
|
||||||
if (![pathOnDisk isAbsolutePath])
|
if (![pathOnDisk isAbsolutePath])
|
||||||
|
@ -813,13 +845,8 @@ static NSString *currentPath = nil;
|
||||||
|
|
||||||
if (![fileManager fileExistsAtPath: pathOnDisk isDirectory: &isDir])
|
if (![fileManager fileExistsAtPath: pathOnDisk isDirectory: &isDir])
|
||||||
{
|
{
|
||||||
if (verbose)
|
NSLog (@"Warning - destination file '%@' not found - ignored",
|
||||||
{
|
pathOnDisk);
|
||||||
/* FIXME - Perhaps we should not actually ignore it but
|
|
||||||
act as if it were there. */
|
|
||||||
NSLog (@"Warning - destination file '%@' not found - ignored",
|
|
||||||
pathOnDisk);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -831,41 +858,55 @@ static NSString *currentPath = nil;
|
||||||
|
|
||||||
e = [HTMLDirectoryEnumerator alloc];
|
e = [HTMLDirectoryEnumerator alloc];
|
||||||
e = [e initWithBasePath: pathOnDisk];
|
e = [e initWithBasePath: pathOnDisk];
|
||||||
|
[e setReturnsAbsolutePaths: YES];
|
||||||
|
|
||||||
while ((filename = [e nextObject]) != nil)
|
while ((filename = [e nextObject]) != nil)
|
||||||
{
|
{
|
||||||
[self registerFile: filename];
|
[self registerDestinationFile: filename];
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Manage pathMappings: try to match any of the pathMappings against
|
if (hasPathMappings)
|
||||||
pathOnDisk, and perform the path mapping if we can match. */
|
{
|
||||||
|
/* Manage pathMappings: try to match any of the pathMappings
|
||||||
|
against pathOnDisk, and perform the path mapping if we can
|
||||||
|
match. */
|
||||||
|
NSEnumerator *e = [pathMappings keyEnumerator];
|
||||||
|
NSString *key;
|
||||||
|
|
||||||
|
while ((key = [e nextObject]))
|
||||||
|
{
|
||||||
|
if ([pathOnDisk hasPrefix: key])
|
||||||
|
{
|
||||||
|
NSString *value = [pathMappings objectForKey: key];
|
||||||
|
|
||||||
|
fullPath = [pathOnDisk substringFromIndex: [key length]];
|
||||||
|
fullPath = [value stringByAppendingPathComponent: fullPath];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now, read all the names from the file. */
|
||||||
{
|
{
|
||||||
NSEnumerator *e = [pathMappings keyEnumerator];
|
NSString *file = [NSString stringWithContentsOfFile: pathOnDisk];
|
||||||
NSString *key;
|
HTMLParser *p = [[HTMLParser alloc] initWithCode: file];
|
||||||
|
NSArray *names = [p names];
|
||||||
|
unsigned i, count;
|
||||||
|
|
||||||
while ((key = [e nextObject]))
|
RELEASE (p);
|
||||||
|
|
||||||
|
count = [names count];
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
if ([pathOnDisk hasPrefix: key])
|
NSString *name = [names objectAtIndex: i];
|
||||||
{
|
[relocationTable setObject: fullPath forKey: name];
|
||||||
NSString *value = [pathMappings objectForKey: key];
|
|
||||||
|
|
||||||
fullPath = [pathOnDisk substringFromIndex: [key length]];
|
|
||||||
fullPath = [value stringByAppendingPathComponent: fullPath];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save the file properly prepared into our dictionary of
|
|
||||||
destination files. */
|
|
||||||
file = [[DestinationFile alloc] initWithFullName: fullPath
|
|
||||||
pathOnDisk: pathOnDisk];
|
|
||||||
[files setObject: file forKey: [pathOnDisk lastPathComponent]];
|
|
||||||
RELEASE (file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)registerPathMappings: (NSDictionary *)dict
|
- (void)registerPathMappings: (NSDictionary *)dict
|
||||||
|
@ -878,6 +919,7 @@ static NSString *currentPath = nil;
|
||||||
NSString *value = [dict objectForKey: key];
|
NSString *value = [dict objectForKey: key];
|
||||||
[pathMappings setObject: value forKey: key];
|
[pathMappings setObject: value forKey: key];
|
||||||
}
|
}
|
||||||
|
hasPathMappings = YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)resolveLink: (NSString *)link
|
- (NSString *)resolveLink: (NSString *)link
|
||||||
|
@ -886,7 +928,7 @@ static NSString *currentPath = nil;
|
||||||
NSString *fileLink;
|
NSString *fileLink;
|
||||||
NSString *nameLink;
|
NSString *nameLink;
|
||||||
NSString *relocatedFileLink;
|
NSString *relocatedFileLink;
|
||||||
DestinationFile *file;
|
NSString *file;
|
||||||
|
|
||||||
/* Do nothing if this is evidently *not* a dynamical link to fixup. */
|
/* Do nothing if this is evidently *not* a dynamical link to fixup. */
|
||||||
if ([link hasPrefix: @"mailto:"] || [link hasPrefix: @"news:"])
|
if ([link hasPrefix: @"mailto:"] || [link hasPrefix: @"news:"])
|
||||||
|
@ -924,40 +966,28 @@ static NSString *currentPath = nil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now lookup fileLink. */
|
/* Now lookup nameLink. */
|
||||||
|
|
||||||
/* If it's "", it means a reference to something inside the same
|
/* If it's "", it is not something we can fixup. */
|
||||||
file. Leave it untouched - no fixup needed. Normally these
|
if (nameLink == nil || [nameLink isEqualToString: @""])
|
||||||
should not be marked as need linker fixup anyway. */
|
|
||||||
if ([fileLink isEqualToString: @""])
|
|
||||||
{
|
{
|
||||||
if (checkLinks)
|
|
||||||
{
|
|
||||||
/* FIXME - not really the linker's task, but we might want
|
|
||||||
to add checking of intra-document links. */
|
|
||||||
}
|
|
||||||
|
|
||||||
relocatedFileLink = fileLink;
|
relocatedFileLink = fileLink;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* First, extract the path-less filename, because it might have
|
/* Now simply look it up in our relocation table. */
|
||||||
already been fixed up by a previous run of the linker. */
|
file = [relocationTable objectForKey: nameLink];
|
||||||
fileLink = [fileLink lastPathComponent];
|
|
||||||
|
|
||||||
/* Now simply look it up in our list of files. */
|
|
||||||
file = [files objectForKey: fileLink];
|
|
||||||
|
|
||||||
/* Not found - leave it unfixed. */
|
/* Not found - leave it unfixed. */
|
||||||
if (file == nil)
|
if (file == nil)
|
||||||
{
|
{
|
||||||
if (verbose || checkLinks)
|
if (warn)
|
||||||
{
|
{
|
||||||
NSString *m;
|
NSString *m;
|
||||||
|
|
||||||
m = [NSString stringWithFormat:
|
m = [NSString stringWithFormat:
|
||||||
@"%@: Unresolved reference to file '%@'\n",
|
@"%@: Unresolved reference to '%@'\n",
|
||||||
logFile, fileLink];
|
logFile, nameLink];
|
||||||
fprintf (stderr, [m lossyCString]);
|
fprintf (stderr, [m lossyCString]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -965,27 +995,14 @@ static NSString *currentPath = nil;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
relocatedFileLink = [file fullName];
|
relocatedFileLink = file;
|
||||||
|
|
||||||
if (checkLinks)
|
|
||||||
{
|
|
||||||
if (![file checkAnchorName: nameLink])
|
|
||||||
{
|
|
||||||
NSString *m;
|
|
||||||
|
|
||||||
m = [NSString stringWithFormat:
|
|
||||||
@"%@: Unresolved reference to '%@' in file '%@'\n",
|
|
||||||
logFile, nameLink, fileLink];
|
|
||||||
fprintf (stderr, [m lossyCString]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now build up the final relocated link, and return it. */
|
/* Now build up the final relocated link, and return it. */
|
||||||
if (nameLink != nil)
|
if (nameLink != nil)
|
||||||
{
|
{
|
||||||
return [NSString stringWithFormat: @"%@#%@", relocatedFileLink,
|
return [NSString stringWithFormat: @"%@#%@", relocatedFileLink,
|
||||||
nameLink];
|
nameLink];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -996,21 +1013,85 @@ static NSString *currentPath = nil;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
static NSString *build_relocation_table_for_directory (NSString *dir)
|
||||||
|
{
|
||||||
|
BOOL isDir;
|
||||||
|
|
||||||
|
/* Check if it's a directory; if it is, enumerate all HTML files
|
||||||
|
inside it, and add all of them. */
|
||||||
|
if (![fileManager fileExistsAtPath: dir isDirectory: &isDir])
|
||||||
|
{
|
||||||
|
NSLog (@"%@ does not exist - exiting", dir);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
else if (!isDir)
|
||||||
|
{
|
||||||
|
NSLog (@"%@ is not a directory - exiting", dir);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HTMLDirectoryEnumerator *e;
|
||||||
|
NSString *filename;
|
||||||
|
NSMutableDictionary *relocationTable;
|
||||||
|
|
||||||
|
relocationTable = [NSMutableDictionary new];
|
||||||
|
AUTORELEASE (relocationTable);
|
||||||
|
|
||||||
|
e = [HTMLDirectoryEnumerator alloc];
|
||||||
|
e = [e initWithBasePath: dir];
|
||||||
|
/* The relocation table for a directory is relative to the
|
||||||
|
directory top, so that the whole directory can be moved
|
||||||
|
around without having to regenerate the .htmlink file. */
|
||||||
|
[e setReturnsAbsolutePaths: NO];
|
||||||
|
|
||||||
|
while ((filename = [e nextObject]) != nil)
|
||||||
|
{
|
||||||
|
NSString *fullPath;
|
||||||
|
NSString *file;
|
||||||
|
HTMLParser *p;
|
||||||
|
NSArray *names;
|
||||||
|
unsigned i, count;
|
||||||
|
|
||||||
|
fullPath = [dir stringByAppendingPathComponent: filename];
|
||||||
|
|
||||||
|
file = [NSString stringWithContentsOfFile: fullPath];
|
||||||
|
|
||||||
|
p = [[HTMLParser alloc] initWithCode: file];
|
||||||
|
names = [p names];
|
||||||
|
RELEASE (p);
|
||||||
|
count = [names count];
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
NSString *name = [names objectAtIndex: i];
|
||||||
|
[relocationTable setObject: filename forKey: name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [relocationTable description];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void print_help_and_exit ()
|
static void print_help_and_exit ()
|
||||||
{
|
{
|
||||||
printf ("GNUstep HTMLLinker (gnustep-base version %d.%d.%d)\n",
|
printf ("GNUstep HTMLLinker (gnustep-base version %d.%d.%d)\n",
|
||||||
GNUSTEP_BASE_MAJOR_VERSION,
|
GNUSTEP_BASE_MAJOR_VERSION,
|
||||||
GNUSTEP_BASE_MINOR_VERSION,
|
GNUSTEP_BASE_MINOR_VERSION,
|
||||||
GNUSTEP_BASE_SUBMINOR_VERSION);
|
GNUSTEP_BASE_SUBMINOR_VERSION);
|
||||||
printf ("Usage: HTMLLinker [options] input_files [--Destinations destination_files]\n");
|
printf ("Usage: HTMLLinker [options] input_files [-l relocation_file] [-d destination_file]\n");
|
||||||
|
printf ("Multiple input files, and multiple -l and -d options are allowed.\n");
|
||||||
printf (" `options' include:\n");
|
printf (" `options' include:\n");
|
||||||
printf (" --help: print this message;\n");
|
printf (" --help: print this message;\n");
|
||||||
printf (" --version: print version information;\n");
|
printf (" --version: print version information;\n");
|
||||||
printf (" -Verbose YES: print verbose messages;\n");
|
printf (" -Warn NO: do not print warnings about unresolved links;\n");
|
||||||
printf (" -CheckLinks NO: do not check links as they are fixed up;\n");
|
printf (" -LinksMarker xxx: only fixup links with attribute rel=xxx;\n");
|
||||||
printf (" -FixupAllLinks YES: attempt to fixup all links (not only dynamical ones);\n");
|
printf (" -FixupAllLinks YES: attempt to fixup all links (not only ones with the marker);\n");
|
||||||
printf (" -PathMappingsFile file: read path mappings from file (a dictionary);\n");
|
printf (" -PathMappingsFile file: read path mappings from file (a dictionary);\n");
|
||||||
printf (" -PathMappings '{\"/usr/doc\"=\"/Doc\";}': use the supplied path mappings;\n");
|
printf (" -PathMappings '{\"/usr/doc\"=\"/Doc\";}': use the supplied path mappings;\n");
|
||||||
|
printf (" -BuildRelocationFileForDir yyy: build a relocation file for the dir yyy\n");
|
||||||
|
printf (" and save it into yyy/table.htmlink. This option is special\n");
|
||||||
|
printf (" and prevents any other processing by the linker.\n");
|
||||||
exit (0);
|
exit (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1030,9 +1111,9 @@ int main (int argc, char** argv, char** env)
|
||||||
NSArray *args;
|
NSArray *args;
|
||||||
NSMutableArray *inputFiles;
|
NSMutableArray *inputFiles;
|
||||||
unsigned i, count;
|
unsigned i, count;
|
||||||
BOOL verbose, checkLinks, fixupAllLinks;
|
BOOL warn, fixupAllLinks;
|
||||||
|
NSString *linksMarker;
|
||||||
HTMLLinker *linker;
|
HTMLLinker *linker;
|
||||||
BOOL destinations;
|
|
||||||
|
|
||||||
#ifdef GS_PASS_ARGUMENTS
|
#ifdef GS_PASS_ARGUMENTS
|
||||||
[NSProcessInfo initializeWithArguments:argv count:argc environment:env];
|
[NSProcessInfo initializeWithArguments:argv count:argc environment:env];
|
||||||
|
@ -1046,21 +1127,47 @@ int main (int argc, char** argv, char** env)
|
||||||
userDefs = [NSUserDefaults standardUserDefaults];
|
userDefs = [NSUserDefaults standardUserDefaults];
|
||||||
|
|
||||||
/* defaults are -
|
/* defaults are -
|
||||||
-Verbose NO
|
-Warn YES
|
||||||
-CheckLinks YES
|
-LinksMarker dynamic
|
||||||
-FixupAllLinks NO
|
-FixupAllLinks NO
|
||||||
*/
|
*/
|
||||||
[userDefs registerDefaults: [NSDictionary dictionaryWithObjectsAndKeys:
|
[userDefs registerDefaults: [NSDictionary dictionaryWithObjectsAndKeys:
|
||||||
@"YES", @"CheckLinks", nil]];
|
@"dynamic", @"LinksMarker",
|
||||||
|
@"YES", @"Warn",
|
||||||
|
nil]];
|
||||||
|
|
||||||
verbose = [userDefs boolForKey: @"Verbose"];
|
warn = [userDefs boolForKey: @"Warn"];
|
||||||
checkLinks = [userDefs boolForKey: @"CheckLinks"];
|
|
||||||
fixupAllLinks = [userDefs boolForKey: @"FixupAllLinks"];
|
fixupAllLinks = [userDefs boolForKey: @"FixupAllLinks"];
|
||||||
|
linksMarker = [userDefs stringForKey: @"LinksMarker"];
|
||||||
|
|
||||||
|
|
||||||
|
/* If -BuildRelocationFileForDir xxx is passed on the command line,
|
||||||
|
build a relocation file for the directory xxx and save it in
|
||||||
|
xxx/table.htmlink. */
|
||||||
|
{
|
||||||
|
NSString *relFile;
|
||||||
|
relFile = [userDefs stringForKey: @"BuildRelocationFileForDir"];
|
||||||
|
|
||||||
|
if (relFile != nil)
|
||||||
|
{
|
||||||
|
NSString *table;
|
||||||
|
NSString *outputFile;
|
||||||
|
|
||||||
|
outputFile = [relFile stringByAppendingPathComponent:
|
||||||
|
@"table.htmlink"];
|
||||||
|
|
||||||
|
table = build_relocation_table_for_directory (relFile);
|
||||||
|
[table writeToFile: outputFile atomically: YES];
|
||||||
|
exit (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Create the linker object. */
|
/* Create the linker object. */
|
||||||
linker = [[HTMLLinker alloc] initWithVerboseFlag: verbose
|
linker = [[HTMLLinker alloc] initWithWarnFlag: warn];
|
||||||
checkLinksFlag: checkLinks];
|
|
||||||
|
|
||||||
|
/* First, read all path mappings (before reading any destination
|
||||||
|
file / relocation file, so we can relocate properly. */
|
||||||
|
|
||||||
/* Read path mappings from PathMappingsFile if specified. */
|
/* Read path mappings from PathMappingsFile if specified. */
|
||||||
{
|
{
|
||||||
NSString *pathMapFile = [userDefs stringForKey: @"PathMappingsFile"];
|
NSString *pathMapFile = [userDefs stringForKey: @"PathMappingsFile"];
|
||||||
|
@ -1095,9 +1202,11 @@ int main (int argc, char** argv, char** env)
|
||||||
|
|
||||||
/* All non-options on the command line are:
|
/* All non-options on the command line are:
|
||||||
|
|
||||||
input files if they come before --Destinations
|
input files
|
||||||
|
|
||||||
destination files if they come after --Destinations
|
destination files if they come after a -d
|
||||||
|
|
||||||
|
relocation files if they come after a -l
|
||||||
|
|
||||||
Directories as input files or destination files means 'all .html, .htm,
|
Directories as input files or destination files means 'all .html, .htm,
|
||||||
.HTML, .HTM files in the directory and subdirectories'.
|
.HTML, .HTM files in the directory and subdirectories'.
|
||||||
|
@ -1107,7 +1216,6 @@ int main (int argc, char** argv, char** env)
|
||||||
|
|
||||||
count = [args count];
|
count = [args count];
|
||||||
|
|
||||||
destinations = NO;
|
|
||||||
inputFiles = AUTORELEASE ([NSMutableArray new]);
|
inputFiles = AUTORELEASE ([NSMutableArray new]);
|
||||||
|
|
||||||
for (i = 1; i < count; i++)
|
for (i = 1; i < count; i++)
|
||||||
|
@ -1124,13 +1232,6 @@ int main (int argc, char** argv, char** env)
|
||||||
{
|
{
|
||||||
print_version_and_exit ();
|
print_version_and_exit ();
|
||||||
}
|
}
|
||||||
else if ([arg isEqualToString: @"--Destinations"])
|
|
||||||
{
|
|
||||||
/* Next file names to be interpreted as destination
|
|
||||||
files. */
|
|
||||||
destinations = YES;
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Ignore it for future expansions. */
|
/* Ignore it for future expansions. */
|
||||||
|
@ -1138,49 +1239,73 @@ int main (int argc, char** argv, char** env)
|
||||||
}
|
}
|
||||||
else if ([arg hasPrefix: @"-"])
|
else if ([arg hasPrefix: @"-"])
|
||||||
{
|
{
|
||||||
/* A GNUstep default - skip it and the next argument. */
|
if ([arg isEqualToString: @"-d"])
|
||||||
if ((i + 1) < count)
|
|
||||||
{
|
{
|
||||||
i++;
|
if ((i + 1) < count)
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (destinations)
|
|
||||||
{
|
|
||||||
[linker registerFile: arg];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
BOOL isDir;
|
|
||||||
|
|
||||||
if (![fileManager fileExistsAtPath: arg
|
|
||||||
isDirectory: &isDir])
|
|
||||||
{
|
{
|
||||||
NSLog (@"Warning - input file '%@' not found - ignored",
|
i++;
|
||||||
arg);
|
/* Register a destination file. */
|
||||||
|
[linker registerDestinationFile: [args objectAtIndex: i]];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (isDir)
|
NSLog (@"Missing argument to -d");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ([arg isEqualToString: @"-l"])
|
||||||
|
{
|
||||||
|
if ((i + 1) < count)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
/* Register a destination file. */
|
||||||
|
[linker registerRelocationFile: [args objectAtIndex: i]];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NSLog (@"Missing argument to -l");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* A GNUstep default - skip it and the next argument. */
|
||||||
|
if ((i + 1) < count)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BOOL isDir;
|
||||||
|
|
||||||
|
if (![fileManager fileExistsAtPath: arg
|
||||||
|
isDirectory: &isDir])
|
||||||
|
{
|
||||||
|
NSLog (@"Warning - input file '%@' not found - ignored",
|
||||||
|
arg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (isDir)
|
||||||
|
{
|
||||||
|
HTMLDirectoryEnumerator *e;
|
||||||
|
NSString *filename;
|
||||||
|
|
||||||
|
e = [HTMLDirectoryEnumerator alloc];
|
||||||
|
e = [e initWithBasePath: arg];
|
||||||
|
[e setReturnsAbsolutePaths: YES];
|
||||||
|
|
||||||
|
while ((filename = [e nextObject]) != nil)
|
||||||
{
|
{
|
||||||
HTMLDirectoryEnumerator *e;
|
[inputFiles addObject: filename];
|
||||||
NSString *filename;
|
|
||||||
|
|
||||||
e = [HTMLDirectoryEnumerator alloc];
|
|
||||||
e = [e initWithBasePath: arg];
|
|
||||||
|
|
||||||
while ((filename = [e nextObject]) != nil)
|
|
||||||
{
|
|
||||||
[inputFiles addObject: filename];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
[inputFiles addObject: arg];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[inputFiles addObject: arg];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1205,7 +1330,7 @@ int main (int argc, char** argv, char** env)
|
||||||
parser = [[HTMLParser alloc] initWithCode: inputFileContents];
|
parser = [[HTMLParser alloc] initWithCode: inputFileContents];
|
||||||
inputFileContents = [parser resolveLinksUsingHTMLLinker: linker
|
inputFileContents = [parser resolveLinksUsingHTMLLinker: linker
|
||||||
logFile: inputFile
|
logFile: inputFile
|
||||||
fixupAllLinks: fixupAllLinks];
|
linksMarker: linksMarker];
|
||||||
[inputFileContents writeToFile: inputFile
|
[inputFileContents writeToFile: inputFile
|
||||||
atomically: YES];
|
atomically: YES];
|
||||||
RELEASE (parser);
|
RELEASE (parser);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue