2001-10-11 17:04:22 +00:00
|
|
|
/** This tool produces gsdoc files from source files.
|
|
|
|
|
|
|
|
<title>Autogsdoc ... a tool to make documentation from source code</title>
|
2001-12-16 13:36:06 +00:00
|
|
|
Copyright (C) 2001 Free Software Foundation, Inc.
|
2001-10-11 17:04:22 +00:00
|
|
|
|
2001-12-16 13:36:06 +00:00
|
|
|
Written by: Richard Frith-Macdonald <richard@brainstorm.co.uk>
|
2001-10-11 17:04:22 +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-11 17:04:22 +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-11 17:04:22 +00:00
|
|
|
If not, write to the Free Software Foundation,
|
|
|
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
|
|
|
|
<chapter>
|
|
|
|
<heading>The autogsdoc tool</heading>
|
|
|
|
<p>
|
|
|
|
The autogsdoc tool is a command-line utility for parsing ObjectiveC
|
|
|
|
source code (header files and optionally source files) in order to
|
|
|
|
generate documentation covering the public interface of the various
|
2001-11-21 17:10:22 +00:00
|
|
|
classes, categories, and protocols in the source.
|
2001-10-11 17:04:22 +00:00
|
|
|
</p>
|
|
|
|
<p>
|
|
|
|
The simple way to use this is to run the command with one or more
|
|
|
|
header file names as arguments ... the tool will automatically
|
2001-11-21 17:10:22 +00:00
|
|
|
parse corresponding source files in the same directory, and produce
|
|
|
|
gsdoc files as output. You may also supply source file names
|
|
|
|
(in which case documentation will be produced for the private
|
|
|
|
methods within the source files), and the names of existing gsdoc
|
|
|
|
documentation files (in which case their contents will be indexed).
|
2001-10-11 17:04:22 +00:00
|
|
|
</p>
|
|
|
|
<p>
|
|
|
|
Even without any human assistance, this tool will produce skeleton
|
|
|
|
documents listing the methods in the classes found in the source
|
|
|
|
files, but more importantly it can take specially formatted comments
|
|
|
|
from the source files and insert those comments into the gsdoc output.
|
|
|
|
</p>
|
|
|
|
<p>
|
2001-11-21 17:10:22 +00:00
|
|
|
Any comment beginning with slash and <em>two</em> asterisks rather than
|
|
|
|
the common slash and single asterisk, is taken to be gsdoc markup, to
|
2001-10-11 17:04:22 +00:00
|
|
|
be use as the description of the class or method following it. This
|
|
|
|
comment text is reformatted and then inserted into the output.
|
|
|
|
</p>
|
|
|
|
<p>
|
|
|
|
There are some cases where special extra processing is performed,
|
|
|
|
predominantly in the first comment found in the source file,
|
|
|
|
from which various chunks of gsdoc markup may be extracted and
|
|
|
|
placed into appropriate locations in the output document -
|
|
|
|
</p>
|
|
|
|
<list>
|
|
|
|
<item><strong><abstract></strong>
|
|
|
|
An abstract of the content of the document ... placed in the head
|
|
|
|
of the gsdoc output.
|
|
|
|
</item>
|
|
|
|
<item><strong><author></strong>
|
|
|
|
A description of the author of the code - may be repeated to handle
|
|
|
|
the case where a document has multiple authors. Placed in the
|
2001-12-16 13:36:06 +00:00
|
|
|
head of the gsdoc output.<br />
|
|
|
|
As an aid to readability of the source, some special additional
|
|
|
|
processing is performed related to the document author -<br />
|
|
|
|
Any line of the form 'Author: name <email-address>', or
|
|
|
|
'By: name <email-address>', or 'Author: name' or 'By: name'
|
|
|
|
will be recognised and converted to an <em>author</em> element,
|
|
|
|
possibly containing an <em>email</em> element.
|
2001-10-11 17:04:22 +00:00
|
|
|
</item>
|
|
|
|
<item><strong><back></strong>
|
|
|
|
Placed in the gsdoc output just before the end of the body of the
|
|
|
|
document - intended to be used for appendices, index etc.
|
|
|
|
</item>
|
|
|
|
<item><strong><chapter></strong>
|
|
|
|
Placed immediately before any generated class documentation ...
|
|
|
|
intended to be used to provide overall description of how the
|
2001-10-15 06:38:25 +00:00
|
|
|
code being documented works.<br />
|
2001-10-11 17:04:22 +00:00
|
|
|
</item>
|
|
|
|
<item><strong><copy></strong>
|
|
|
|
Copyright of the content of the document ... placed in the head
|
2001-12-16 13:36:06 +00:00
|
|
|
of the gsdoc output.<br />
|
|
|
|
As an aid to readability of the source, some special additional
|
|
|
|
processing is performed -<br />
|
|
|
|
Any line of the form 'Copyright (C) text' will be recognised and
|
|
|
|
converted to a <em>copy</em> element.
|
2001-10-11 17:04:22 +00:00
|
|
|
</item>
|
|
|
|
<item><strong><date></strong>
|
2001-11-21 17:10:22 +00:00
|
|
|
Date of the revision of the document ... placed in the head
|
2001-10-11 17:04:22 +00:00
|
|
|
of the gsdoc output. If this is omitted the tool will try to
|
|
|
|
construct a value from the RCS Date tag (if available).
|
|
|
|
</item>
|
|
|
|
<item><strong><front></strong>
|
|
|
|
Inserted into the document at the start of the body ... intended
|
|
|
|
to provide for introduction or contents pages etc.
|
|
|
|
</item>
|
|
|
|
<item><strong><title></strong>
|
|
|
|
Title of the document ... placed in the head of the gsdoc output.
|
|
|
|
If this is omitted the tool will generate a (probably poor)
|
|
|
|
title of its own.
|
|
|
|
</item>
|
2001-10-15 06:38:25 +00:00
|
|
|
<item>
|
|
|
|
<strong>NB</strong>This markup may be used within
|
|
|
|
class, category, or protocol documentation ... if so, it is
|
|
|
|
extracted and wrapped round the rest of the documentation for
|
|
|
|
the class as the classes chapter.
|
|
|
|
The rest of the class documentation is normally
|
|
|
|
inserted at the end of the chapter, but may instead be sbstituted
|
|
|
|
in in place of the <unit /> pseudo-element within the
|
|
|
|
<chapter> element.
|
|
|
|
</item>
|
2001-10-11 17:04:22 +00:00
|
|
|
<item><strong><version></strong>
|
|
|
|
Version identifier of the document ... placed in the head
|
|
|
|
of the gsdoc output. If this is omitted the tool will try to
|
|
|
|
construct a value from the RCS Revision tag (if available).
|
|
|
|
</item>
|
|
|
|
</list>
|
|
|
|
<p>
|
|
|
|
In comments being used to provide text for a method description, the
|
|
|
|
following markup is removed from the text and handled specially -
|
|
|
|
</p>
|
|
|
|
<list>
|
2001-10-15 14:42:56 +00:00
|
|
|
<item><strong><init /></strong>
|
2001-10-11 17:04:22 +00:00
|
|
|
The method is marked as being the designated initialiser for the class.
|
|
|
|
</item>
|
2001-10-15 14:42:56 +00:00
|
|
|
<item><strong><override-subclass /></strong>
|
2001-10-11 17:04:22 +00:00
|
|
|
The method is marked as being one which subclasses must override
|
|
|
|
(eg an abstract method).
|
|
|
|
</item>
|
2001-10-15 14:42:56 +00:00
|
|
|
<item><strong><override-never /></strong>
|
2001-10-11 17:04:22 +00:00
|
|
|
The method is marked as being one which subclasses should <em>NOT</em>
|
|
|
|
override.
|
|
|
|
</item>
|
|
|
|
<item><strong><standards> ... </standards></strong>
|
|
|
|
The markup is removed from the description and placed <em>after</em>
|
|
|
|
it in the gsdoc output - so that the method is described as
|
|
|
|
conforming (or not conforming) to the specified standards.
|
|
|
|
</item>
|
|
|
|
</list>
|
2001-10-13 18:52:54 +00:00
|
|
|
<p>
|
|
|
|
Generally, the text in comments is reformatted to standardise and
|
|
|
|
indent it nicely ... the reformatting is <em>not</em> performed on
|
|
|
|
any text inside an <example> element.<br />
|
|
|
|
When the text is reformatted, it is broken into whitespace separated
|
|
|
|
'words' which are then subjected to some extra processing ...
|
|
|
|
</p>
|
|
|
|
<list>
|
|
|
|
<item>Certain well known constants such as YES, NO, and nil are
|
|
|
|
enclosed in <code> ... </code> markup.
|
|
|
|
</item>
|
2001-10-14 10:39:23 +00:00
|
|
|
<item>The names of method arguments within method descriptions are
|
|
|
|
enclosed in <var> ... </var> markup.
|
|
|
|
</item>
|
2001-10-13 18:52:54 +00:00
|
|
|
<item>Method names (beginning with a plus or minus) are enclosed
|
2001-11-21 17:10:22 +00:00
|
|
|
in <ref...> ... </ref> markup.<br />
|
2001-12-17 07:11:23 +00:00
|
|
|
eg. "-init" (without the quotes) would be wrapped in a gsdoc
|
|
|
|
reference element to point to the init method of the current
|
|
|
|
class or, if only one known class had an init method, it
|
|
|
|
would refer to the method of that class.
|
|
|
|
<br />Note the fact that the method name must be surrounded by
|
|
|
|
whitespace (though a comma, fullstop, or semicolon at the end
|
|
|
|
of the specifier will also act as a whitespace terminator).
|
2001-11-21 17:10:22 +00:00
|
|
|
</item>
|
|
|
|
<item>Method specifiers including class names (beginning and ending with
|
|
|
|
square brackets) are enclosed in <ref...> ... </ref> markup.
|
2001-12-17 07:11:23 +00:00
|
|
|
<br />eg. [ NSObject-init],
|
|
|
|
will create a reference to the init method of NSObject, while
|
|
|
|
<br />[ (NSCopying)-copyWithZone:], creates a
|
|
|
|
reference to a method in the NSCopyIng protocol, and
|
|
|
|
<br />[ NSObject(TimedPerformers)-performSelector:withObject:afterDelay:],
|
|
|
|
creates a reference to a method in the TimedPerformers category.
|
|
|
|
<br />Note that no spaces must appear between the square brackets
|
|
|
|
in these specifiers.
|
2001-10-13 18:52:54 +00:00
|
|
|
</item>
|
|
|
|
</list>
|
2001-10-11 17:04:22 +00:00
|
|
|
<p>
|
|
|
|
The tools accepts certain user defaults (which can of course be
|
|
|
|
supplied as command-line arguments as usual) -
|
|
|
|
</p>
|
|
|
|
<list>
|
2001-12-26 11:32:46 +00:00
|
|
|
<item><strong>AutoIndex</strong>
|
|
|
|
A boolean value which may be used to specify that the program should
|
|
|
|
generate an index file for the project automatically. This defaults
|
|
|
|
to NO.
|
|
|
|
</item>
|
2001-11-21 17:10:22 +00:00
|
|
|
<item><strong>Declared</strong>
|
|
|
|
Specify where headers are to be documented as being found.<br />
|
|
|
|
The actual name produced in the documentation is formed by appending
|
|
|
|
the last component of the header file name to the value of this
|
|
|
|
default.<br />
|
|
|
|
If this default is not specified, the full name of the header file
|
|
|
|
(as supplied on the command line), with the HeaderDirectory
|
2001-11-29 14:26:24 +00:00
|
|
|
default prepended, is used.<br />
|
|
|
|
A typical usage of this might be <code>-Declared Foundation</code>
|
|
|
|
when generating documentation for the GNUstep base library. This
|
|
|
|
would result in the documentation saying that NSString is declared
|
|
|
|
in <code>Foundation/NSString.h</code>
|
2001-11-21 17:10:22 +00:00
|
|
|
</item>
|
2001-10-11 17:04:22 +00:00
|
|
|
<item><strong>DocumentationDirectory</strong>
|
|
|
|
May be used to specify the directory in which generated
|
2001-11-21 17:10:22 +00:00
|
|
|
documentation is to be placed. If this is not set, output
|
|
|
|
is placed in the current directory.
|
|
|
|
</item>
|
2001-12-26 11:32:46 +00:00
|
|
|
<item><strong>GenerateHtml</strong>
|
|
|
|
May be used to specify if HTML output is to be generated.
|
|
|
|
Defaults to YES.
|
|
|
|
</item>
|
2001-11-21 17:10:22 +00:00
|
|
|
<item><strong>HeaderDirectory</strong>
|
|
|
|
May be used to specify the directory to be searched for header files.
|
|
|
|
If this is not specified, headers are looked for relative to the
|
|
|
|
current directory or using absolute path names if given.
|
|
|
|
</item>
|
2001-12-26 11:32:46 +00:00
|
|
|
<item><strong>IgnoreDependencies</strong>
|
|
|
|
A boolean value which may be used to specify that the program should
|
|
|
|
ignore file modification times and regenerate files anyway. Provided
|
|
|
|
for use in conjunction with the <code>make</code> system, which is
|
|
|
|
expected to manage dependency checking itsself.
|
|
|
|
</item>
|
2001-11-29 07:38:04 +00:00
|
|
|
<item><strong>LocalProjects</strong>
|
|
|
|
This value is used to control the automatic inclusion of local
|
|
|
|
external projects into the indexing system for generation of
|
|
|
|
cross-references in final document output.<br />
|
|
|
|
If set to 'None', then no local project references are done,
|
|
|
|
otherwise, the 'Local' GNUstep documentation directory is recursively
|
|
|
|
searched for files with a <code>.igsdoc</code> extension, and the
|
|
|
|
indexing information from those files is used.<br />
|
|
|
|
The value of this string is also used to generate the filenames in
|
|
|
|
the cross reference ... if it is an empty string, the path to use
|
|
|
|
is assumed to be a file in the same directory where the igsdoc
|
|
|
|
file was found, otherwise it is used as a prefix to the name in
|
|
|
|
the index.
|
|
|
|
</item>
|
|
|
|
<item><strong>Project</strong>
|
2001-11-21 17:10:22 +00:00
|
|
|
May be used to specify the name of this project ... determines the
|
|
|
|
name of the index reference file produced as part of the documentation
|
|
|
|
to provide information enabling other projects to cross-reference to
|
|
|
|
items in this project.
|
2001-10-11 17:04:22 +00:00
|
|
|
</item>
|
2001-11-29 07:38:04 +00:00
|
|
|
<item><strong>Projects</strong>
|
|
|
|
This value may be supplies as a dictionary containing the paths to
|
|
|
|
the igsdoc index/reference files used by external projects, along
|
|
|
|
with values to be used to map the filenames found in the indexes.<br />
|
|
|
|
For example, if a project index (igsdoc) file says that the class
|
|
|
|
<code>Foo</code> is found in the file <code>Foo</code>, and the
|
|
|
|
path associated with that project index is <code>/usr/doc/proj</code>,
|
|
|
|
Then generated html output may reference the class as being in
|
|
|
|
<code>/usr/doc/prj/Foo.html</code>
|
|
|
|
</item>
|
2001-12-17 11:54:54 +00:00
|
|
|
<item><strong>ShowDependencies</strong>
|
|
|
|
A boolean value which may be used to specify that the program should
|
|
|
|
log which files are being regenerated because of their dependencies
|
|
|
|
on other files.
|
|
|
|
</item>
|
2002-01-02 06:50:30 +00:00
|
|
|
<item><strong>Standards</strong>
|
|
|
|
A boolean value used to specify whether the program should insert
|
|
|
|
information about standards complience into ythe documentation.
|
|
|
|
This should only be used when documenting the GNUstep libraries
|
|
|
|
and tools themselves as it assumes that the code being documented
|
|
|
|
is part of GNUstep and possibly complies with the OpenStep standard
|
|
|
|
or implements MacOS-X compatible methods.
|
|
|
|
</item>
|
2001-10-11 17:04:22 +00:00
|
|
|
<item><strong>SourceDirectory</strong>
|
2001-12-18 06:48:20 +00:00
|
|
|
May be used to specify the directory to be searched for source
|
|
|
|
(anything other than <code>.h</code> files ... which are controlled
|
|
|
|
by the HeaderDirectory default).<br />
|
|
|
|
If this is not specified, sources are looked for relative to the
|
2001-11-21 17:10:22 +00:00
|
|
|
current directory or using absolute path names if given.
|
2001-10-11 17:04:22 +00:00
|
|
|
</item>
|
2001-11-29 07:38:04 +00:00
|
|
|
<item><strong>SystemProjects</strong>
|
|
|
|
This value is used to control the automatic inclusion of system
|
|
|
|
external projects into the indexing system for generation of
|
|
|
|
cross-references in final document output.<br />
|
|
|
|
If set to 'None', then no system project references are done,
|
|
|
|
otherwise, the 'System' GNUstep documentation directory is recursively
|
|
|
|
searched for files with a <code>.igsdoc</code> extension, and the
|
|
|
|
indexing information from those files is used.<br />
|
|
|
|
The value of this string is also used to generate the filenames in
|
|
|
|
the cross reference ... if it is an empty string, the path to use
|
|
|
|
is assumed to be a file in the same directory where the igsdoc
|
|
|
|
file was found, otherwise it is used as a prefix to the name in
|
|
|
|
the index.
|
|
|
|
</item>
|
2001-12-26 11:32:46 +00:00
|
|
|
<item><strong>Up</strong>
|
|
|
|
A string used to supply the name to be used in the 'up' link from
|
|
|
|
generated gsdoc documents. This should normally be the name of a
|
|
|
|
file which contains an index of the contents of a project.<br />
|
|
|
|
If this is explicitly set to an empty string, then no 'up' link
|
|
|
|
will be provided in the documents.
|
|
|
|
</item>
|
2001-10-11 17:04:22 +00:00
|
|
|
</list>
|
2001-10-15 14:42:56 +00:00
|
|
|
<section>
|
|
|
|
<heading>Inter-document linkage</heading>
|
2001-12-26 11:32:46 +00:00
|
|
|
<p>
|
|
|
|
Normally, the 'Up' default is used to specify the name of a document
|
|
|
|
which should be used as the 'up' link for any other documents used.
|
|
|
|
However, if this default is omitted, the tool will make certain
|
|
|
|
assumptions about linkage as follows -
|
|
|
|
</p>
|
2001-10-15 14:42:56 +00:00
|
|
|
<p>
|
2001-12-18 11:09:38 +00:00
|
|
|
If the first file listed on the command line is a gsdoc document,
|
|
|
|
it will be assumed to be the 'top' document and will be referenced
|
|
|
|
in the 'up' link for all subsequent documents.<br />
|
|
|
|
Otherwise, autogsdoc will generate an index file called 'index.gsdoc'
|
|
|
|
which will be used as the 'top' file.
|
2001-10-15 14:42:56 +00:00
|
|
|
</p>
|
|
|
|
<p>
|
2001-12-22 17:48:15 +00:00
|
|
|
Where autogsdoc is used with only a single file name, the
|
2001-12-26 11:32:46 +00:00
|
|
|
above assumed linkage is <em>not</em> set up.
|
2001-12-22 06:38:29 +00:00
|
|
|
</p>
|
2001-10-15 14:42:56 +00:00
|
|
|
</section>
|
2001-10-11 17:04:22 +00:00
|
|
|
</chapter>
|
2001-12-18 09:31:32 +00:00
|
|
|
<back>
|
2001-12-18 09:57:11 +00:00
|
|
|
<index type="title" scope="project" />
|
2001-12-18 09:31:32 +00:00
|
|
|
<index type="class" scope="project" />
|
|
|
|
</back>
|
2001-10-11 17:04:22 +00:00
|
|
|
*/
|
|
|
|
|
2001-10-13 08:51:54 +00:00
|
|
|
#include <config.h>
|
|
|
|
|
2001-10-15 14:42:56 +00:00
|
|
|
#include "AGSParser.h"
|
|
|
|
#include "AGSOutput.h"
|
|
|
|
#include "AGSIndex.h"
|
2001-10-17 20:58:12 +00:00
|
|
|
#include "AGSHtml.h"
|
2001-10-11 17:04:22 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
main(int argc, char **argv, char **env)
|
|
|
|
{
|
|
|
|
NSProcessInfo *proc;
|
|
|
|
unsigned i;
|
|
|
|
NSUserDefaults *defs;
|
|
|
|
NSFileManager *mgr;
|
2001-11-29 14:26:24 +00:00
|
|
|
NSMutableDictionary *projects;
|
2001-10-11 17:04:22 +00:00
|
|
|
NSString *documentationDirectory;
|
2001-11-21 17:10:22 +00:00
|
|
|
NSString *declared;
|
|
|
|
NSString *headerDirectory;
|
2001-10-11 17:04:22 +00:00
|
|
|
NSString *sourceDirectory;
|
2001-11-29 07:38:04 +00:00
|
|
|
NSString *project;
|
2001-12-26 11:32:46 +00:00
|
|
|
NSString *up;
|
2001-11-21 17:10:22 +00:00
|
|
|
NSString *refsFile;
|
2001-11-29 07:38:04 +00:00
|
|
|
NSString *systemProjects;
|
|
|
|
NSString *localProjects;
|
2001-11-21 17:10:22 +00:00
|
|
|
AGSIndex *prjRefs;
|
2001-10-15 14:42:56 +00:00
|
|
|
AGSIndex *indexer;
|
2001-10-11 17:04:22 +00:00
|
|
|
AGSParser *parser;
|
|
|
|
AGSOutput *output;
|
2001-12-26 11:32:46 +00:00
|
|
|
id obj;
|
|
|
|
BOOL generateHtml = YES;
|
|
|
|
BOOL ignoreDependencies = NO;
|
|
|
|
BOOL showDependencies = NO;
|
|
|
|
BOOL autoIndex = NO;
|
2001-12-19 13:20:14 +00:00
|
|
|
BOOL modifiedRefs = NO;
|
2002-01-02 06:50:30 +00:00
|
|
|
BOOL standards = NO;
|
2001-12-19 13:20:14 +00:00
|
|
|
NSDate *rDate = nil;
|
2001-12-22 06:38:29 +00:00
|
|
|
NSMutableArray *files = nil;
|
2001-11-27 20:55:12 +00:00
|
|
|
CREATE_AUTORELEASE_POOL(outer);
|
2001-10-11 17:04:22 +00:00
|
|
|
CREATE_AUTORELEASE_POOL(pool);
|
|
|
|
|
2001-12-19 13:20:14 +00:00
|
|
|
RELEASE(pool);
|
|
|
|
|
2001-10-11 17:04:22 +00:00
|
|
|
#ifdef GS_PASS_ARGUMENTS
|
|
|
|
[NSProcessInfo initializeWithArguments: argv count: argc environment: env];
|
|
|
|
#endif
|
|
|
|
|
|
|
|
defs = [NSUserDefaults standardUserDefaults];
|
|
|
|
[defs registerDefaults: [NSDictionary dictionaryWithObjectsAndKeys:
|
2001-11-29 07:38:04 +00:00
|
|
|
@"Untitled", @"Project",
|
2001-11-21 17:10:22 +00:00
|
|
|
nil]];
|
|
|
|
|
2001-12-26 11:32:46 +00:00
|
|
|
autoIndex = [defs boolForKey: @"AutoIndex"];
|
2002-01-02 06:50:30 +00:00
|
|
|
standards = [defs boolForKey: @"Standards"];
|
2001-12-26 11:32:46 +00:00
|
|
|
ignoreDependencies = [defs boolForKey: @"IgnoreDependencies"];
|
2001-12-17 11:54:54 +00:00
|
|
|
showDependencies = [defs boolForKey: @"ShowDependencies"];
|
2001-12-26 11:32:46 +00:00
|
|
|
if (ignoreDependencies == YES)
|
|
|
|
{
|
|
|
|
if (showDependencies == YES)
|
|
|
|
{
|
|
|
|
showDependencies = NO;
|
|
|
|
NSLog(@"ShowDependencies(YES) used with IgnoreDependencies(YES)");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
obj = [defs objectForKey: @"GenerateHtml"];
|
|
|
|
if (obj != nil)
|
|
|
|
{
|
|
|
|
generateHtml = [defs boolForKey: @"GenerateHtml"];
|
|
|
|
}
|
|
|
|
|
2001-11-21 17:10:22 +00:00
|
|
|
declared = [defs stringForKey: @"Declared"];
|
2001-11-29 07:38:04 +00:00
|
|
|
project = [defs stringForKey: @"Project"];
|
2001-12-26 11:32:46 +00:00
|
|
|
up = [defs stringForKey: @"Up"];
|
|
|
|
if ([up isEqual: @""] && autoIndex == YES)
|
|
|
|
{
|
|
|
|
autoIndex = NO;
|
|
|
|
NSLog(@"Up(\"\") used with AutoIndex(YES)");
|
|
|
|
}
|
2001-12-19 13:20:14 +00:00
|
|
|
|
2001-11-29 07:38:04 +00:00
|
|
|
localProjects = [defs stringForKey: @"LocalProjects"];
|
|
|
|
if (localProjects == nil)
|
|
|
|
{
|
|
|
|
localProjects = @"";
|
|
|
|
}
|
|
|
|
systemProjects = [defs stringForKey: @"SystemProjects"];
|
|
|
|
if (systemProjects == nil)
|
|
|
|
{
|
|
|
|
systemProjects = @"";
|
|
|
|
}
|
2001-11-29 14:26:24 +00:00
|
|
|
projects = [[defs dictionaryForKey: @"Projects"] mutableCopy];
|
|
|
|
AUTORELEASE(projects);
|
2001-11-27 20:55:12 +00:00
|
|
|
|
2001-11-21 17:10:22 +00:00
|
|
|
headerDirectory = [defs stringForKey: @"HeaderDirectory"];
|
|
|
|
if (headerDirectory == nil)
|
|
|
|
{
|
2001-12-17 11:54:54 +00:00
|
|
|
headerDirectory = @"";
|
2001-11-21 17:10:22 +00:00
|
|
|
}
|
2001-10-11 17:04:22 +00:00
|
|
|
|
|
|
|
sourceDirectory = [defs stringForKey: @"SourceDirectory"];
|
2001-11-21 17:10:22 +00:00
|
|
|
if (sourceDirectory == nil)
|
|
|
|
{
|
2001-12-17 11:54:54 +00:00
|
|
|
sourceDirectory = @"";
|
2001-11-21 17:10:22 +00:00
|
|
|
}
|
|
|
|
|
2001-10-11 17:04:22 +00:00
|
|
|
documentationDirectory = [defs stringForKey: @"DocumentationDirectory"];
|
2001-11-21 17:10:22 +00:00
|
|
|
if (documentationDirectory == nil)
|
|
|
|
{
|
2001-12-17 11:54:54 +00:00
|
|
|
documentationDirectory = @"";
|
2001-11-21 17:10:22 +00:00
|
|
|
}
|
2001-10-11 17:04:22 +00:00
|
|
|
|
2001-12-19 13:20:14 +00:00
|
|
|
refsFile = [documentationDirectory stringByAppendingPathComponent: project];
|
|
|
|
refsFile = [refsFile stringByAppendingPathExtension: @"igsdoc"];
|
|
|
|
|
|
|
|
|
2001-10-11 17:04:22 +00:00
|
|
|
proc = [NSProcessInfo processInfo];
|
|
|
|
if (proc == nil)
|
|
|
|
{
|
|
|
|
NSLog(@"unable to get process information!");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2001-12-22 06:38:29 +00:00
|
|
|
/*
|
|
|
|
* Build an array of files to be processed.
|
|
|
|
*/
|
|
|
|
files = AUTORELEASE([[proc arguments] mutableCopy]);
|
|
|
|
[files removeObjectAtIndex: 0];
|
|
|
|
for (i = 0; i < [files count]; i++)
|
|
|
|
{
|
|
|
|
NSString *arg = [files objectAtIndex: i];
|
|
|
|
|
|
|
|
if ([arg hasPrefix: @"-"])
|
|
|
|
{
|
|
|
|
// Skip this and next value ... it is a default.
|
|
|
|
[files removeObjectAtIndex: i];
|
|
|
|
[files removeObjectAtIndex: i];
|
2001-12-22 17:48:15 +00:00
|
|
|
i--;
|
2001-12-22 06:38:29 +00:00
|
|
|
}
|
|
|
|
else if ([arg hasSuffix: @".h"] == NO
|
|
|
|
&& [arg hasSuffix: @".m"] == NO
|
|
|
|
&& [arg hasSuffix: @".gsdoc"] == NO)
|
|
|
|
{
|
|
|
|
// Skip this value ... not a known file type.
|
|
|
|
NSLog(@"Unknown argument '%@' ... ignored", arg);
|
|
|
|
[files removeObjectAtIndex: i];
|
2001-12-22 17:48:15 +00:00
|
|
|
i--;
|
2001-12-22 06:38:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if ([files count] < 1)
|
|
|
|
{
|
|
|
|
NSLog(@"No filename arguments found ... giving up");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2001-10-11 17:04:22 +00:00
|
|
|
mgr = [NSFileManager defaultManager];
|
|
|
|
|
2001-11-21 17:10:22 +00:00
|
|
|
prjRefs = [AGSIndex new];
|
2001-10-15 14:42:56 +00:00
|
|
|
indexer = [AGSIndex new];
|
2001-10-11 17:04:22 +00:00
|
|
|
parser = [AGSParser new];
|
2002-01-02 06:50:30 +00:00
|
|
|
[parser setGenerateStandards: standards];
|
2001-10-11 17:04:22 +00:00
|
|
|
output = [AGSOutput new];
|
|
|
|
|
2001-12-19 13:20:14 +00:00
|
|
|
/*
|
|
|
|
* Load any old project indexing information.
|
|
|
|
*/
|
|
|
|
if ([mgr isReadableFileAtPath: refsFile] == YES)
|
|
|
|
{
|
|
|
|
NSDictionary *dict;
|
|
|
|
|
|
|
|
dict = [[NSDictionary alloc] initWithContentsOfFile: refsFile];
|
|
|
|
if (dict == nil)
|
|
|
|
{
|
|
|
|
NSLog(@"Unable to read project file '%@'", refsFile);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
[prjRefs mergeRefs: dict override: NO];
|
|
|
|
RELEASE(dict);
|
|
|
|
dict = [mgr fileAttributesAtPath: refsFile traverseLink: YES];
|
|
|
|
rDate = [dict objectForKey: NSFileModificationDate];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (rDate == nil)
|
|
|
|
{
|
|
|
|
rDate = [NSDate distantPast];
|
|
|
|
}
|
|
|
|
|
2001-11-29 07:38:04 +00:00
|
|
|
/*
|
|
|
|
* Merge any external project references into the
|
|
|
|
* main cross reference index.
|
|
|
|
*/
|
|
|
|
|
2001-12-19 13:20:14 +00:00
|
|
|
pool = [NSAutoreleasePool new];
|
2001-11-29 07:38:04 +00:00
|
|
|
if ([systemProjects caseInsensitiveCompare: @"None"] != NSOrderedSame)
|
|
|
|
{
|
|
|
|
NSString *base = [NSSearchPathForDirectoriesInDomains(
|
|
|
|
NSDocumentationDirectory, NSSystemDomainMask, NO) lastObject];
|
|
|
|
|
|
|
|
base = [base stringByStandardizingPath];
|
|
|
|
if (base != nil)
|
|
|
|
{
|
|
|
|
NSDirectoryEnumerator *enumerator = [mgr enumeratorAtPath: base];
|
|
|
|
NSString *file;
|
|
|
|
|
|
|
|
if ([systemProjects isEqual: @""] == YES)
|
|
|
|
{
|
|
|
|
systemProjects = base; // Absolute path
|
|
|
|
}
|
|
|
|
while ((file = [enumerator nextObject]) != nil)
|
|
|
|
{
|
|
|
|
NSString *ext = [file pathExtension];
|
|
|
|
|
|
|
|
if ([ext isEqualToString: @"igsdoc"] == YES)
|
|
|
|
{
|
|
|
|
NSString *key;
|
|
|
|
NSString *val;
|
|
|
|
|
|
|
|
if (projects == nil)
|
|
|
|
{
|
|
|
|
projects = [NSMutableDictionary dictionary];
|
|
|
|
}
|
|
|
|
key = [base stringByAppendingPathComponent: file];
|
|
|
|
val = [file stringByDeletingLastPathComponent];
|
|
|
|
val = [systemProjects stringByAppendingPathComponent: val];
|
|
|
|
[projects setObject: val forKey: key];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ([localProjects caseInsensitiveCompare: @"None"] != NSOrderedSame)
|
|
|
|
{
|
|
|
|
NSString *base = [NSSearchPathForDirectoriesInDomains(
|
|
|
|
NSDocumentationDirectory, NSLocalDomainMask, NO) lastObject];
|
|
|
|
|
|
|
|
base = [base stringByStandardizingPath];
|
|
|
|
if (base != nil)
|
|
|
|
{
|
|
|
|
NSDirectoryEnumerator *enumerator = [mgr enumeratorAtPath: base];
|
|
|
|
NSString *file;
|
|
|
|
|
|
|
|
if ([localProjects isEqual: @""] == YES)
|
|
|
|
{
|
|
|
|
localProjects = base; // Absolute path
|
|
|
|
}
|
|
|
|
while ((file = [enumerator nextObject]) != nil)
|
|
|
|
{
|
|
|
|
NSString *ext = [file pathExtension];
|
|
|
|
|
|
|
|
if ([ext isEqualToString: @"igsdoc"] == YES)
|
|
|
|
{
|
|
|
|
NSString *key;
|
|
|
|
NSString *val;
|
|
|
|
|
|
|
|
if (projects == nil)
|
|
|
|
{
|
|
|
|
projects = [NSMutableDictionary dictionary];
|
|
|
|
}
|
|
|
|
key = [base stringByAppendingPathComponent: file];
|
|
|
|
val = [file stringByDeletingLastPathComponent];
|
|
|
|
val = [localProjects stringByAppendingPathComponent: val];
|
|
|
|
[projects setObject: val forKey: key];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (projects != nil)
|
|
|
|
{
|
|
|
|
NSEnumerator *e = [projects keyEnumerator];
|
|
|
|
NSString *k;
|
|
|
|
|
|
|
|
while ((k = [e nextObject]) != nil)
|
|
|
|
{
|
|
|
|
NSDictionary *dict;
|
|
|
|
|
|
|
|
if ([mgr isReadableFileAtPath: k] == NO
|
|
|
|
|| (dict = [[NSDictionary alloc] initWithContentsOfFile: k]) == nil)
|
|
|
|
{
|
|
|
|
NSLog(@"Unable to read project file '%@'", k);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
AGSIndex *tmp;
|
|
|
|
NSString *p;
|
|
|
|
|
|
|
|
tmp = [AGSIndex new];
|
2001-12-15 09:05:19 +00:00
|
|
|
[tmp mergeRefs: dict override: NO];
|
2001-11-29 07:38:04 +00:00
|
|
|
RELEASE(dict);
|
|
|
|
/*
|
|
|
|
* Adjust path to external project files ...
|
|
|
|
*/
|
|
|
|
p = [projects objectForKey: k];
|
|
|
|
if ([p isEqual: @""] == YES)
|
|
|
|
{
|
|
|
|
p = [k stringByDeletingLastPathComponent];
|
|
|
|
}
|
|
|
|
[tmp setDirectory: p];
|
2001-12-17 11:54:54 +00:00
|
|
|
[indexer mergeRefs: [tmp refs] override: YES];
|
2001-11-29 07:38:04 +00:00
|
|
|
RELEASE(tmp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2001-12-19 13:20:14 +00:00
|
|
|
RELEASE(pool);
|
2001-11-29 07:38:04 +00:00
|
|
|
|
2001-12-19 13:20:14 +00:00
|
|
|
pool = [NSAutoreleasePool new];
|
2001-12-22 06:38:29 +00:00
|
|
|
for (i = 0; i < [files count]; i++)
|
2001-10-11 17:04:22 +00:00
|
|
|
{
|
2001-12-22 06:38:29 +00:00
|
|
|
NSString *arg = [files objectAtIndex: i];
|
|
|
|
NSString *gsdocfile;
|
|
|
|
NSString *hfile;
|
|
|
|
NSString *sfile;
|
|
|
|
NSString *ddir;
|
|
|
|
NSString *hdir;
|
|
|
|
NSString *sdir;
|
|
|
|
NSString *file;
|
|
|
|
NSString *generated;
|
|
|
|
BOOL isSource = [arg hasSuffix: @".m"];
|
|
|
|
BOOL isDocumentation = [arg hasSuffix: @".gsdoc"];
|
|
|
|
NSDictionary *attrs;
|
2001-12-26 11:32:46 +00:00
|
|
|
NSDate *sDate = nil;
|
|
|
|
NSDate *gDate = nil;
|
2001-12-22 06:38:29 +00:00
|
|
|
|
|
|
|
if (pool != nil)
|
2001-10-11 17:04:22 +00:00
|
|
|
{
|
2001-12-22 06:38:29 +00:00
|
|
|
RELEASE(pool);
|
|
|
|
pool = [NSAutoreleasePool new];
|
2001-11-27 20:55:12 +00:00
|
|
|
}
|
2001-12-22 06:38:29 +00:00
|
|
|
file = [[arg lastPathComponent] stringByDeletingPathExtension];
|
|
|
|
hdir = [arg stringByDeletingLastPathComponent];
|
|
|
|
if ([hdir length] == 0)
|
2001-11-27 20:55:12 +00:00
|
|
|
{
|
2001-12-22 06:38:29 +00:00
|
|
|
hdir = headerDirectory;
|
|
|
|
sdir = sourceDirectory;
|
|
|
|
}
|
|
|
|
else if ([hdir isAbsolutePath] == YES)
|
|
|
|
{
|
|
|
|
sdir = hdir;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sdir = [sourceDirectory stringByAppendingPathComponent: hdir];
|
|
|
|
hdir = [headerDirectory stringByAppendingPathComponent: hdir];
|
|
|
|
}
|
|
|
|
ddir = documentationDirectory;
|
|
|
|
|
|
|
|
hfile = [hdir stringByAppendingPathComponent: file];
|
|
|
|
hfile = [hfile stringByAppendingPathExtension: @"h"];
|
|
|
|
sfile = [sdir stringByAppendingPathComponent: file];
|
|
|
|
sfile = [sfile stringByAppendingPathExtension: @"m"];
|
|
|
|
gsdocfile = [ddir stringByAppendingPathComponent: file];
|
|
|
|
gsdocfile = [gsdocfile stringByAppendingPathExtension: @"gsdoc"];
|
|
|
|
|
2001-12-26 11:32:46 +00:00
|
|
|
if (ignoreDependencies == NO)
|
2001-12-22 06:38:29 +00:00
|
|
|
{
|
2001-12-26 11:32:46 +00:00
|
|
|
/*
|
|
|
|
* When were the files last modified?
|
|
|
|
*/
|
|
|
|
attrs = [mgr fileAttributesAtPath: hfile traverseLink: YES];
|
|
|
|
sDate = [attrs objectForKey: NSFileModificationDate];
|
|
|
|
AUTORELEASE(RETAIN(sDate));
|
|
|
|
attrs = [mgr fileAttributesAtPath: sfile traverseLink: YES];
|
|
|
|
if (attrs != nil)
|
2001-11-27 20:55:12 +00:00
|
|
|
{
|
2001-12-26 11:32:46 +00:00
|
|
|
NSDate *d;
|
|
|
|
|
|
|
|
d = [attrs objectForKey: NSFileModificationDate];
|
|
|
|
if (sDate == nil || [d earlierDate: sDate] == sDate)
|
|
|
|
{
|
|
|
|
sDate = d;
|
|
|
|
AUTORELEASE(RETAIN(sDate));
|
|
|
|
}
|
2001-11-27 20:55:12 +00:00
|
|
|
}
|
2001-12-22 06:38:29 +00:00
|
|
|
}
|
|
|
|
|
2001-12-26 11:32:46 +00:00
|
|
|
if (up == nil && [files count] > 1)
|
2001-12-22 06:38:29 +00:00
|
|
|
{
|
2001-12-26 11:32:46 +00:00
|
|
|
/*
|
|
|
|
* If we have multiple files to process, we want one to point to all
|
|
|
|
* the others and be an 'up' link for them ... if the first file is
|
|
|
|
* '.gsdoc' file, we assume it performs that indexing function,
|
|
|
|
* otherwise we use a default name.
|
|
|
|
*/
|
2001-12-22 06:38:29 +00:00
|
|
|
if (isDocumentation == YES)
|
2001-11-27 20:55:12 +00:00
|
|
|
{
|
2001-12-22 06:38:29 +00:00
|
|
|
ASSIGN(up, file);
|
2001-11-27 20:55:12 +00:00
|
|
|
}
|
|
|
|
else
|
2001-10-11 17:04:22 +00:00
|
|
|
{
|
2001-12-22 06:38:29 +00:00
|
|
|
ASSIGN(up, @"index");
|
2001-12-26 11:32:46 +00:00
|
|
|
autoIndex = YES; // Generate it if needed.
|
2001-12-18 11:09:38 +00:00
|
|
|
}
|
2001-12-22 06:38:29 +00:00
|
|
|
}
|
2001-12-18 11:09:38 +00:00
|
|
|
|
2001-12-22 06:38:29 +00:00
|
|
|
if (isDocumentation == NO)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* The file we are processing is not a gsdoc file ... so
|
|
|
|
* we need to try to generate the gsdoc from source code.
|
|
|
|
*/
|
2001-12-26 11:32:46 +00:00
|
|
|
if (ignoreDependencies == NO)
|
|
|
|
{
|
|
|
|
attrs = [mgr fileAttributesAtPath: gsdocfile traverseLink: YES];
|
|
|
|
gDate = [attrs objectForKey: NSFileModificationDate];
|
|
|
|
AUTORELEASE(RETAIN(gDate));
|
|
|
|
}
|
2001-11-27 20:55:12 +00:00
|
|
|
|
2001-12-22 06:38:29 +00:00
|
|
|
if (gDate == nil || [sDate earlierDate: gDate] == gDate)
|
|
|
|
{
|
|
|
|
if (showDependencies == YES)
|
2001-11-21 17:10:22 +00:00
|
|
|
{
|
2001-12-22 06:38:29 +00:00
|
|
|
NSLog(@"%@: source %@, gsdoc %@ ==> regenerate",
|
|
|
|
file, sDate, gDate);
|
|
|
|
}
|
|
|
|
[parser reset];
|
2001-12-18 06:48:20 +00:00
|
|
|
|
2001-12-22 06:38:29 +00:00
|
|
|
if (isSource == NO)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Try to parse header to see what needs documenting.
|
|
|
|
*/
|
|
|
|
if ([mgr isReadableFileAtPath: hfile] == NO)
|
2001-11-27 20:55:12 +00:00
|
|
|
{
|
2001-12-22 06:38:29 +00:00
|
|
|
NSLog(@"No readable header at '%@' ... skipping",
|
|
|
|
hfile);
|
|
|
|
continue;
|
2001-11-27 20:55:12 +00:00
|
|
|
}
|
2001-12-22 06:38:29 +00:00
|
|
|
if (declared != nil)
|
2001-11-27 20:55:12 +00:00
|
|
|
{
|
2001-12-22 06:38:29 +00:00
|
|
|
[parser setDeclared:
|
|
|
|
[declared stringByAppendingPathComponent:
|
|
|
|
[hfile lastPathComponent]]];
|
2001-11-27 20:55:12 +00:00
|
|
|
}
|
2001-12-22 06:38:29 +00:00
|
|
|
[parser parseFile: hfile isSource: NO];
|
|
|
|
}
|
|
|
|
else if (isSource == YES)
|
|
|
|
{
|
2001-11-21 17:10:22 +00:00
|
|
|
/*
|
2001-12-22 06:38:29 +00:00
|
|
|
* Try to parse source *as-if-it-was-a-header*
|
|
|
|
* to see what needs documenting.
|
2001-11-21 17:10:22 +00:00
|
|
|
*/
|
2001-12-22 06:38:29 +00:00
|
|
|
if ([mgr isReadableFileAtPath: sfile] == NO)
|
|
|
|
{
|
|
|
|
NSLog(@"No readable source at '%@' ... skipping",
|
|
|
|
sfile);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (declared != nil)
|
2001-11-27 20:55:12 +00:00
|
|
|
{
|
2001-12-22 06:38:29 +00:00
|
|
|
[parser setDeclared:
|
|
|
|
[declared stringByAppendingPathComponent:
|
|
|
|
[sfile lastPathComponent]]];
|
2001-11-27 20:55:12 +00:00
|
|
|
}
|
2001-12-22 06:38:29 +00:00
|
|
|
[parser parseFile: sfile isSource: NO];
|
|
|
|
}
|
2001-10-15 14:42:56 +00:00
|
|
|
|
2001-12-22 06:38:29 +00:00
|
|
|
/*
|
|
|
|
* If we can read a source file, parse it for any
|
|
|
|
* additional information on items found in the header.
|
|
|
|
*/
|
|
|
|
if ([mgr isReadableFileAtPath: sfile] == YES)
|
|
|
|
{
|
|
|
|
[parser parseFile: sfile isSource: YES];
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set up linkage for this file.
|
|
|
|
*/
|
|
|
|
[[parser info] setObject: file forKey: @"base"];
|
2001-12-26 11:32:46 +00:00
|
|
|
|
2001-12-22 06:38:29 +00:00
|
|
|
/*
|
2001-12-26 11:32:46 +00:00
|
|
|
* Only produce linkage if the up link is not empty.
|
|
|
|
* Don't add an up link if this *is* the up link document.
|
2001-12-22 06:38:29 +00:00
|
|
|
*/
|
2001-12-26 11:32:46 +00:00
|
|
|
if ([up length] > 0 && [up isEqual: file] == NO)
|
2001-12-22 06:38:29 +00:00
|
|
|
{
|
2001-12-18 11:09:38 +00:00
|
|
|
[[parser info] setObject: up forKey: @"up"];
|
2001-12-22 06:38:29 +00:00
|
|
|
}
|
2001-11-21 17:10:22 +00:00
|
|
|
|
2001-12-22 06:38:29 +00:00
|
|
|
generated = [output output: [parser info]];
|
2001-11-21 17:10:22 +00:00
|
|
|
|
2001-12-22 06:38:29 +00:00
|
|
|
if ([generated writeToFile: gsdocfile
|
|
|
|
atomically: YES] == NO)
|
|
|
|
{
|
|
|
|
NSLog(@"Sorry unable to write %@", gsdocfile);
|
2001-11-21 17:10:22 +00:00
|
|
|
}
|
2001-12-22 06:38:29 +00:00
|
|
|
else
|
2001-12-18 06:48:20 +00:00
|
|
|
{
|
2001-12-22 06:38:29 +00:00
|
|
|
gDate = [NSDate date]; // Just generated.
|
2001-12-18 06:48:20 +00:00
|
|
|
}
|
|
|
|
}
|
2001-12-22 06:38:29 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2001-12-18 06:48:20 +00:00
|
|
|
/*
|
2001-12-22 06:38:29 +00:00
|
|
|
* Our source file is a gsdoc file ... so it may be located
|
|
|
|
* in the source (input) directory rather than the documentation
|
|
|
|
* (output) directory.
|
2001-12-18 06:48:20 +00:00
|
|
|
*/
|
2001-12-22 06:38:29 +00:00
|
|
|
if ([mgr isReadableFileAtPath: gsdocfile] == NO)
|
2001-11-27 20:55:12 +00:00
|
|
|
{
|
2001-12-22 06:38:29 +00:00
|
|
|
gsdocfile = [sdir stringByAppendingPathComponent: file];
|
|
|
|
gsdocfile = [gsdocfile stringByAppendingPathExtension:
|
|
|
|
@"gsdoc"];
|
|
|
|
}
|
2001-12-26 11:32:46 +00:00
|
|
|
if (ignoreDependencies == NO)
|
|
|
|
{
|
|
|
|
attrs = [mgr fileAttributesAtPath: gsdocfile traverseLink: YES];
|
|
|
|
gDate = [attrs objectForKey: NSFileModificationDate];
|
|
|
|
AUTORELEASE(RETAIN(gDate));
|
|
|
|
}
|
2001-12-22 06:38:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now we try to process the gsdoc data to make index info
|
|
|
|
* unless the project index is already more up to date than
|
|
|
|
* this file.
|
|
|
|
*/
|
2001-12-26 11:32:46 +00:00
|
|
|
if (gDate == nil || [gDate earlierDate: rDate] == rDate)
|
2001-12-22 06:38:29 +00:00
|
|
|
{
|
|
|
|
if (showDependencies == YES)
|
|
|
|
{
|
|
|
|
NSLog(@"%@: gsdoc %@, index %@ ==> regenerate",
|
|
|
|
file, sDate, gDate);
|
|
|
|
}
|
|
|
|
if ([mgr isReadableFileAtPath: gsdocfile] == YES)
|
|
|
|
{
|
|
|
|
GSXMLParser *parser;
|
|
|
|
AGSIndex *locRefs;
|
|
|
|
|
|
|
|
parser = [GSXMLParser parserWithContentsOfFile: gsdocfile];
|
|
|
|
[parser substituteEntities: NO];
|
|
|
|
[parser doValidityChecking: YES];
|
|
|
|
[parser keepBlanks: NO];
|
|
|
|
if ([parser parse] == NO)
|
2001-11-27 20:55:12 +00:00
|
|
|
{
|
2001-12-22 06:38:29 +00:00
|
|
|
NSLog(@"WARNING %@ is not a valid document", gsdocfile);
|
2001-11-27 20:55:12 +00:00
|
|
|
}
|
2001-12-22 06:38:29 +00:00
|
|
|
if (![[[[parser doc] root] name] isEqualToString: @"gsdoc"])
|
2001-10-15 14:42:56 +00:00
|
|
|
{
|
2001-12-22 06:38:29 +00:00
|
|
|
NSLog(@"not a gsdoc document - because name node is %@",
|
|
|
|
[[[parser doc] root] name]);
|
|
|
|
return 1;
|
|
|
|
}
|
2001-11-27 20:55:12 +00:00
|
|
|
|
2001-12-22 06:38:29 +00:00
|
|
|
locRefs = AUTORELEASE([AGSIndex new]);
|
|
|
|
[locRefs makeRefs: [[parser doc] root]];
|
2001-11-27 20:55:12 +00:00
|
|
|
|
2001-12-22 06:38:29 +00:00
|
|
|
/*
|
|
|
|
* accumulate index info in project references
|
|
|
|
*/
|
|
|
|
[prjRefs mergeRefs: [locRefs refs] override: NO];
|
|
|
|
modifiedRefs = YES;
|
|
|
|
}
|
|
|
|
else if (isDocumentation)
|
|
|
|
{
|
|
|
|
NSLog(@"No readable documentation at '%@' ... skipping",
|
|
|
|
gsdocfile);
|
2001-11-27 20:55:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2001-12-26 11:32:46 +00:00
|
|
|
|
2001-11-29 07:38:04 +00:00
|
|
|
/*
|
2001-12-26 11:32:46 +00:00
|
|
|
* Make sure auto-generation of index file is done.
|
2001-11-29 07:38:04 +00:00
|
|
|
*/
|
2001-12-26 11:32:46 +00:00
|
|
|
if (autoIndex == YES)
|
2001-11-27 20:55:12 +00:00
|
|
|
{
|
2001-12-26 11:32:46 +00:00
|
|
|
if ([files containsObject: up] == YES)
|
|
|
|
{
|
|
|
|
NSLog(@"AutoIndex(YES) set, but Up(%@) listed in source files", up);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NSString *upFile = documentationDirectory;
|
2001-12-22 06:38:29 +00:00
|
|
|
|
2001-12-26 11:32:46 +00:00
|
|
|
upFile = [upFile stringByAppendingPathComponent: up];
|
|
|
|
upFile = [upFile stringByAppendingPathExtension: @"gsdoc"];
|
|
|
|
|
|
|
|
if ([mgr isReadableFileAtPath: upFile] == NO)
|
|
|
|
{
|
|
|
|
NSString *upString = [NSString stringWithFormat:
|
|
|
|
@"<?xml version=\"1.0\"?>\n"
|
|
|
|
@"<!DOCTYPE gsdoc PUBLIC "
|
|
|
|
@"\"-//GNUstep//DTD gsdoc 0.6.7//EN\" "
|
|
|
|
@"\"http://www.gnustep.org/gsdoc-0_6_7.xml\">\n"
|
|
|
|
@"<gsdoc base=\"index\">\n"
|
|
|
|
@" <head>\n"
|
|
|
|
@" <title>%@ project reference</title>\n"
|
|
|
|
@" <author name=\"autogsdoc\"></author>\n"
|
|
|
|
@" </head>\n"
|
|
|
|
@" <body>\n"
|
|
|
|
@" <chapter>\n"
|
|
|
|
@" <heading>%@ project reference</heading>\n"
|
|
|
|
@" </chapter>\n"
|
|
|
|
@" <back>\n"
|
|
|
|
@" <index scope=\"project\" type=\"title\" />\n"
|
|
|
|
@" </back>\n"
|
|
|
|
@" </body>\n"
|
|
|
|
@"</gsdoc>\n",
|
|
|
|
project, project];
|
|
|
|
|
|
|
|
if ([upString writeToFile: upFile atomically: YES] == NO)
|
|
|
|
{
|
|
|
|
NSLog(@"Unable to write %@", upFile);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
[files insertObject: upFile atIndex: 0];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DESTROY(up);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Save project references.
|
|
|
|
*/
|
|
|
|
if (modifiedRefs == YES)
|
|
|
|
{
|
|
|
|
if ([[prjRefs refs] writeToFile: refsFile atomically: YES] == NO)
|
2001-12-18 11:09:38 +00:00
|
|
|
{
|
2001-12-26 11:32:46 +00:00
|
|
|
NSLog(@"Sorry unable to write %@", refsFile);
|
2001-12-18 11:09:38 +00:00
|
|
|
}
|
2001-12-26 11:32:46 +00:00
|
|
|
}
|
2001-11-27 20:55:12 +00:00
|
|
|
|
2001-12-26 11:32:46 +00:00
|
|
|
RELEASE(pool);
|
2001-12-22 06:38:29 +00:00
|
|
|
|
2001-12-26 11:32:46 +00:00
|
|
|
if (generateHtml == YES)
|
|
|
|
{
|
2001-12-22 06:38:29 +00:00
|
|
|
/*
|
2001-12-26 11:32:46 +00:00
|
|
|
* Second pass ... generate html output from gsdoc files.
|
2001-12-22 06:38:29 +00:00
|
|
|
*/
|
2001-12-26 11:32:46 +00:00
|
|
|
pool = [NSAutoreleasePool new];
|
2001-12-22 06:38:29 +00:00
|
|
|
|
2001-12-26 11:32:46 +00:00
|
|
|
/*
|
|
|
|
* Accumulate project index info into global index
|
|
|
|
*/
|
|
|
|
[indexer mergeRefs: [prjRefs refs] override: YES];
|
|
|
|
|
|
|
|
for (i = 0; i < [files count]; i++)
|
|
|
|
{
|
|
|
|
NSString *arg = [files objectAtIndex: i];
|
|
|
|
NSString *gsdocfile;
|
|
|
|
NSString *htmlfile;
|
|
|
|
NSString *ddir;
|
|
|
|
NSString *file;
|
|
|
|
NSString *generated;
|
|
|
|
NSDictionary *attrs;
|
|
|
|
NSDate *gDate = nil;
|
|
|
|
NSDate *hDate = nil;
|
|
|
|
|
|
|
|
if (pool != nil)
|
2001-12-22 06:38:29 +00:00
|
|
|
{
|
2001-12-26 11:32:46 +00:00
|
|
|
RELEASE(pool);
|
|
|
|
pool = [NSAutoreleasePool new];
|
2001-12-22 06:38:29 +00:00
|
|
|
}
|
2001-12-26 11:32:46 +00:00
|
|
|
file = [[arg lastPathComponent] stringByDeletingPathExtension];
|
|
|
|
ddir = documentationDirectory;
|
|
|
|
|
|
|
|
gsdocfile = [ddir stringByAppendingPathComponent: file];
|
2001-11-27 20:55:12 +00:00
|
|
|
gsdocfile = [gsdocfile stringByAppendingPathExtension: @"gsdoc"];
|
2001-12-26 11:32:46 +00:00
|
|
|
htmlfile = [ddir stringByAppendingPathComponent: file];
|
|
|
|
htmlfile = [htmlfile stringByAppendingPathExtension: @"html"];
|
2001-11-27 20:55:12 +00:00
|
|
|
|
2001-12-26 11:32:46 +00:00
|
|
|
/*
|
|
|
|
* If the gsdoc file name was specified as a source file,
|
|
|
|
* it may be in the source directory rather than the documentation
|
|
|
|
* directory.
|
|
|
|
*/
|
|
|
|
if ([mgr isReadableFileAtPath: gsdocfile] == NO
|
|
|
|
&& [arg hasSuffix: @".gsdoc"] == YES)
|
2001-12-18 06:48:20 +00:00
|
|
|
{
|
2001-12-26 11:32:46 +00:00
|
|
|
NSString *sdir = [arg stringByDeletingLastPathComponent];
|
2001-12-18 06:48:20 +00:00
|
|
|
|
2001-12-26 11:32:46 +00:00
|
|
|
if ([sdir length] == 0)
|
2001-12-18 06:48:20 +00:00
|
|
|
{
|
2001-12-26 11:32:46 +00:00
|
|
|
sdir = sourceDirectory;
|
2001-12-18 06:48:20 +00:00
|
|
|
}
|
2001-12-26 11:32:46 +00:00
|
|
|
else if ([sdir isAbsolutePath] == NO)
|
2001-12-18 06:48:20 +00:00
|
|
|
{
|
2001-12-26 11:32:46 +00:00
|
|
|
sdir = [sourceDirectory stringByAppendingPathComponent: sdir];
|
2001-12-18 06:48:20 +00:00
|
|
|
}
|
2001-12-26 11:32:46 +00:00
|
|
|
gsdocfile = [sdir stringByAppendingPathComponent: file];
|
|
|
|
gsdocfile = [gsdocfile stringByAppendingPathExtension: @"gsdoc"];
|
|
|
|
}
|
2001-11-21 17:10:22 +00:00
|
|
|
|
2001-12-26 11:32:46 +00:00
|
|
|
if (ignoreDependencies == NO)
|
|
|
|
{
|
2001-12-22 06:38:29 +00:00
|
|
|
/*
|
2001-12-26 11:32:46 +00:00
|
|
|
* When were the files last modified?
|
2001-12-22 06:38:29 +00:00
|
|
|
*/
|
2001-12-26 11:32:46 +00:00
|
|
|
attrs = [mgr fileAttributesAtPath: gsdocfile traverseLink: YES];
|
|
|
|
gDate = [attrs objectForKey: NSFileModificationDate];
|
|
|
|
AUTORELEASE(RETAIN(gDate));
|
|
|
|
attrs = [mgr fileAttributesAtPath: htmlfile traverseLink: YES];
|
|
|
|
hDate = [attrs objectForKey: NSFileModificationDate];
|
|
|
|
AUTORELEASE(RETAIN(hDate));
|
2001-10-17 20:58:12 +00:00
|
|
|
}
|
2001-11-21 17:10:22 +00:00
|
|
|
|
2001-12-26 11:32:46 +00:00
|
|
|
if ([mgr isReadableFileAtPath: gsdocfile] == YES)
|
|
|
|
{
|
|
|
|
if (hDate == nil || [gDate earlierDate: hDate] == hDate)
|
|
|
|
{
|
|
|
|
GSXMLParser *parser;
|
|
|
|
AGSIndex *locRefs;
|
|
|
|
AGSHtml *html;
|
2001-11-27 20:55:12 +00:00
|
|
|
|
2001-12-26 11:32:46 +00:00
|
|
|
if (showDependencies == YES)
|
|
|
|
{
|
|
|
|
NSLog(@"%@: gsdoc %@, html %@ ==> regenerate",
|
|
|
|
file, gDate, hDate);
|
|
|
|
}
|
|
|
|
parser = [GSXMLParser parserWithContentsOfFile: gsdocfile];
|
|
|
|
[parser substituteEntities: NO];
|
|
|
|
[parser doValidityChecking: YES];
|
|
|
|
[parser keepBlanks: NO];
|
|
|
|
if ([parser parse] == NO)
|
|
|
|
{
|
|
|
|
NSLog(@"WARNING %@ is not a valid document", gsdocfile);
|
|
|
|
}
|
|
|
|
if (![[[[parser doc] root] name] isEqualToString: @"gsdoc"])
|
|
|
|
{
|
|
|
|
NSLog(@"not a gsdoc document - because name node is %@",
|
|
|
|
[[[parser doc] root] name]);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
locRefs = AUTORELEASE([AGSIndex new]);
|
|
|
|
[locRefs makeRefs: [[parser doc] root]];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We perform final output
|
|
|
|
*/
|
|
|
|
html = AUTORELEASE([AGSHtml new]);
|
|
|
|
[html setGlobalRefs: indexer];
|
|
|
|
[html setProjectRefs: prjRefs];
|
|
|
|
[html setLocalRefs: locRefs];
|
|
|
|
generated = [html outputDocument: [[parser doc] root]];
|
|
|
|
if ([generated writeToFile: htmlfile atomically: YES] == NO)
|
|
|
|
{
|
|
|
|
NSLog(@"Sorry unable to write %@", htmlfile);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NSLog(@"No readable documentation at '%@' ... skipping",
|
|
|
|
gsdocfile);
|
|
|
|
}
|
2001-12-19 13:20:14 +00:00
|
|
|
}
|
2001-12-26 11:32:46 +00:00
|
|
|
RELEASE(pool);
|
2001-10-11 17:04:22 +00:00
|
|
|
}
|
|
|
|
|
2001-11-27 20:55:12 +00:00
|
|
|
RELEASE(outer);
|
2001-10-11 17:04:22 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|