Work on the train.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@14654 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-Macdonald 2002-10-05 17:47:54 +00:00
parent 209f46ae7e
commit f05b58bc61
17 changed files with 477 additions and 198 deletions

View file

@ -519,6 +519,7 @@ static NSMutableSet *textNodes = nil;
ssect = 0;
sssect = 0;
[self outputNodeList: children to: buf];
heading = nil;
}
else if ([name isEqual: @"class"] == YES)
{
@ -1086,16 +1087,23 @@ static NSMutableSet *textNodes = nil;
}
else if ([name isEqual: @"heading"] == YES)
{
[buf appendString: indent];
[buf appendString: @"<"];
[buf appendString: heading];
[buf appendString: @">"];
[buf appendFormat: @"<a name=\"%03u%03u%03u%03u\">",
chap, sect, ssect, sssect];
[self outputText: children to: buf];
[buf appendString: @"</a></"];
[buf appendString: heading];
[buf appendString: @">\n"];
if (heading == nil)
{
}
else
{
[buf appendString: indent];
[buf appendString: @"<"];
[buf appendString: heading];
[buf appendString: @">"];
[buf appendFormat: @"<a name=\"%03u%03u%03u%03u\">",
chap, sect, ssect, sssect];
[self outputText: children to: buf];
[buf appendString: @"</a></"];
[buf appendString: heading];
[buf appendString: @">\n"];
heading = nil;
}
}
else if ([name isEqual: @"index"] == YES)
{
@ -1394,6 +1402,7 @@ static NSMutableSet *textNodes = nil;
ssect = 0;
sssect = 0;
[self outputNodeList: children to: buf];
heading = @"h1";
}
else if ([name isEqual: @"site"] == YES)
{
@ -1442,12 +1451,14 @@ static NSMutableSet *textNodes = nil;
ssect++;
sssect = 0;
[self outputNodeList: children to: buf];
heading = @"h2";
}
else if ([name isEqual: @"subsubsect"] == YES)
{
heading = @"h4";
sssect++;
[self outputNodeList: children to: buf];
heading = @"h3";
}
else if ([name isEqual: @"type"] == YES)
{
@ -1593,14 +1604,28 @@ NSLog(@"Element '%@' not implemented", name); // FIXME
RELEASE(arp);
}
/**
* Output all the nodes from this one onwards ... try to output
* as text first, if not possible, call the main method to output
* each node.
*/
- (void) outputNodeList: (GSXMLNode*)node to: (NSMutableString*)buf
{
while (node != nil)
{
GSXMLNode *next = [node nextElement];
GSXMLNode *tmp;
[self outputNode: node to: buf];
node = next;
tmp = [self outputText: node to: buf];
if (tmp == node)
{
[self outputNode: node to: buf];
node = next;
}
else
{
node = tmp;
}
}
}

View file

@ -33,6 +33,7 @@
NSCharacterSet *spacenl; // Blanks excluding newline
NSArray *args; // Not retained.
BOOL verbose;
BOOL warn;
}
- (NSString*) checkComment: (NSString*)comment
@ -58,7 +59,6 @@
- (unsigned) reformat: (NSString*)str
withIndent: (unsigned)ind
to: (NSMutableString*)buf;
- (void) setVerbose: (BOOL)flag;
- (NSArray*) split: (NSString*)str;
@end
#endif

View file

@ -81,24 +81,24 @@ static BOOL snuggleStart(NSString *t)
if ([comment length] == 0)
{
comment = @"<em>Description forthcoming.</em>";
if (verbose == YES)
if (warn == YES)
{
NSString *name = [d objectForKey: @"Name"];
NSString *type = [d objectForKey: @"Type"];
if (unit == nil)
{
NSLog(@"No comments for %@ %@", type, name);
NSLog(@"Warning - No comments for %@ %@", type, name);
}
else
{
if ([d objectForKey: @"ReturnType"] != nil)
{
NSLog(@"No comments for [%@ %@]", unit, name);
NSLog(@"Warning - No comments for [%@ %@]", unit, name);
}
else
{
NSLog(@"No comments for instance variable %@ in %@",
NSLog(@"Warning - No comments for instance variable %@ in %@",
name, unit);
}
}
@ -213,6 +213,8 @@ static BOOL snuggleStart(NSString *t)
@"_0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"]);
identStart = RETAIN([NSCharacterSet characterSetWithCharactersInString:
@"_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"]);
verbose = [[NSUserDefaults standardUserDefaults] boolForKey: @"Verbose"];
warn = [[NSUserDefaults standardUserDefaults] boolForKey: @"Warn"];
return self;
}
@ -629,7 +631,7 @@ static BOOL snuggleStart(NSString *t)
NSString *declared = [d objectForKey: @"Declared"];
NSString *standards = nil;
if ([[d objectForKey: @"Implemented"] isEqual: @"YES"] == NO)
if (warn == YES && [[d objectForKey: @"Implemented"] isEqual: @"YES"] == NO)
{
NSLog(@"Warning ... %@ %@ is not implemented where expected", kind, name);
}
@ -680,7 +682,7 @@ static BOOL snuggleStart(NSString *t)
NSString *standards = nil;
unsigned i = [aa count];
if ([[d objectForKey: @"Implemented"] isEqual: @"YES"] == NO)
if (warn == YES && [[d objectForKey: @"Implemented"] isEqual: @"YES"] == NO)
{
NSLog(@"Warning ... function %@ is not implemented where expected", name);
}
@ -861,7 +863,8 @@ static BOOL snuggleStart(NSString *t)
NSString *override = nil;
NSString *standards = nil;
if (unit != nil && [[d objectForKey: @"Implemented"] isEqual: @"YES"] == NO)
if (warn == YES && unit != nil
&& [[d objectForKey: @"Implemented"] isEqual: @"YES"] == NO)
{
NSLog(@"Warning ... method %@ %@ is not implemented where expected",
unit, name);
@ -1056,7 +1059,7 @@ static BOOL snuggleStart(NSString *t)
[m setObject: @"YES" forKey: @"Implemented"];
}
}
else
else if (warn == YES)
{
NSLog(@"Warning ... unit %@ is not implemented where expected", name);
}
@ -1393,11 +1396,6 @@ static BOOL snuggleStart(NSString *t)
return ind;
}
- (void) setVerbose: (BOOL)flag
{
verbose = flag;
}
- (NSArray*) split: (NSString*)str
{
NSMutableArray *a = [NSMutableArray arrayWithCapacity: 128];

View file

@ -61,6 +61,7 @@
BOOL inArgList;
BOOL documentAllInstanceVariables;
BOOL verbose;
BOOL warn;
NSDictionary *wordMap;
NSString *declared; /** Where classes were declared. */
NSMutableArray *ifStack; /** Track preprocessor conditionals. */
@ -93,7 +94,6 @@
- (void) setDocumentAllInstanceVariables: (BOOL)flag;
- (void) setGenerateStandards: (BOOL)flag;
- (void) setStandards: (NSMutableDictionary*)dict;
- (void) setVerbose: (BOOL)flag;
- (void) setWordMap: (NSDictionary*)map;
- (void) setupBuffer;
- (unsigned) skipArray;

View file

@ -24,6 +24,83 @@
@implementation AGSParser
/**
* Method to add the comment from the main() function to the end
* of the initial chapter in the output document. We do this to
* support the use of autogsdoc to document tools.
*/
- (void) addMain: (NSString*)c
{
NSString *chap;
NSMutableString *m;
NSRange r;
chap = [info objectForKey: @"chapter"];
if (chap == nil)
{
chap = [NSString stringWithFormat:
@"<chapter><heading>%@</heading></chapter>",
[[fileName lastPathComponent] stringByDeletingPathExtension]];
}
m = [chap mutableCopy];
r = [m rangeOfString: @"</chapter>"];
r.length = 0;
[m replaceCharactersInRange: r withString: @"</section>\n"];
[m replaceCharactersInRange: r withString: c];
[m replaceCharactersInRange: r withString:
@"<section>\n<heading>The main() function</heading>\n"];
[info setObject: m forKey: @"chapter"];
RELEASE(m);
}
/**
* Append a comment (with leading and trailing space stripped)
* to an information dictionary.<br />
* If the dictionary is nil, accumulate in the comment ivar instead.<br />
* If the comment is empty, ignore it.<br />
* If there is no comment in the dictionary, simply set the new value.<br />
* If a comment already exists then the new comment text is appended to
* it with a separating line break inserted if necessary.<br />
*/
- (void) appendComment: (NSString*)s to: (NSMutableDictionary*)d
{
s = [s stringByTrimmingSpaces];
if ([s length] > 0)
{
NSString *old;
if (d == nil)
{
old = comment;
}
else
{
old = [d objectForKey: @"Comment"];
}
if (old != nil)
{
if ([old hasSuffix: @"</p>"] == NO
&& [old hasSuffix: @"<br />"] == NO
&& [old hasSuffix: @"<br/>"] == NO)
{
s = [old stringByAppendingFormat: @"<br />%@", s];
}
else
{
s = [old stringByAppendingString: s];
}
}
if (d == nil)
{
ASSIGN(comment, s);
}
else
{
[d setObject: s forKey: @"Comment"];
}
}
}
- (void) dealloc
{
DESTROY(wordMap);
@ -60,6 +137,8 @@
@"_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"]);
info = [[NSMutableDictionary alloc] initWithCapacity: 6];
source = [NSMutableArray new];
verbose = [[NSUserDefaults standardUserDefaults] boolForKey: @"Verbose"];
warn = [[NSUserDefaults standardUserDefaults] boolForKey: @"Warn"];
return self;
}
@ -731,7 +810,7 @@
}
if (comment != nil)
{
[d setObject: comment forKey: @"Comment"];
[self appendComment: comment to: d];
}
DESTROY(comment);
}
@ -750,7 +829,7 @@
/*
* Don't bother to warn about nameless enumerations.
*/
if ([t isEqual: @"enum ..."] == NO)
if (verbose == YES && [t isEqual: @"enum ..."] == NO)
{
[self log: @"parse declaration with no name - %@", d];
}
@ -919,19 +998,20 @@ fail:
if (oDecl != nil)
{
NSString *tmp = [nDecl objectForKey: @"Comment"];
NSString *oc = [oDecl objectForKey: @"Comment"];
NSString *nc = [nDecl objectForKey: @"Comment"];
if (tmp != nil)
/*
* If the old comment from the header parsing is
* the same as the new comment from the source
* parsing, assume we parsed the same file as both
* source and header ... otherwise append the new
* comment.
*/
if ([oc isEqual: nc] == NO)
{
NSString *old = [oDecl objectForKey: @"Comment"];
if (old != nil)
{
tmp = [old stringByAppendingString: tmp];
}
[oDecl setObject: tmp forKey: @"Comment"];
[self appendComment: nc to: oDecl];
}
[oDecl setObject: @"YES" forKey: @"Implemented"];
if ([kind isEqualToString: @"Functions"] == YES)
@ -944,6 +1024,23 @@ fail:
[self log: @"Function %@ args missmatch - "
@"%@ %@", name, a1, a2];
}
/*
* A main function is not documented as a
* function, but as a special case its
* comments are added to the 'front'
* section of the documentation.
*/
if ([name isEqual: @"main"] == YES)
{
NSString *c;
c = [oDecl objectForKey: @"Comment"];
if (c != nil)
{
[self addMain: c];
}
[dict removeObjectForKey: name];
}
}
}
}
@ -1036,16 +1133,7 @@ fail:
/*
* Append any comment we have for this
*/
if (tmp != nil)
{
NSString *old = [dict objectForKey: @"Comment"];
if (old != nil)
{
tmp = [old stringByAppendingString: tmp];
}
[dict setObject: tmp forKey: @"Comment"];
}
[self appendComment: tmp to: dict];
/*
* Update base class if necessary.
*/
@ -1096,7 +1184,7 @@ fail:
*/
if (comment != nil)
{
[dict setObject: comment forKey: @"Comment"];
[self appendComment: comment to: dict];
DESTROY(comment);
}
@ -1584,18 +1672,7 @@ fail:
*/
if (comment != nil)
{
NSString *old;
old = [method objectForKey: @"Comment"];
if (old != nil)
{
[method setObject: [old stringByAppendingString: comment]
forKey: @"Comment"];
}
else
{
[method setObject: comment forKey: @"Comment"];
}
[self appendComment: comment to: method];
DESTROY(comment);
}
@ -1716,17 +1793,8 @@ fail:
}
}
token = [method objectForKey: @"Comment"];
if (token != nil)
{
NSString *old = [exist objectForKey: @"Comment"];
if (old != nil)
{
token = [old stringByAppendingString: token];
}
[exist setObject: token forKey: @"Comment"];
}
[self appendComment: [method objectForKey: @"Comment"]
to: exist];
[exist setObject: @"YES" forKey: @"Implemented"];
}
break;
@ -2099,14 +2167,6 @@ fail:
}
}
/**
* Control boolean option to do verbose logging of the parsing process.
*/
- (void) setVerbose: (BOOL)flag
{
verbose = flag;
}
/**
* Sets up a dictionary used for mapping identifiers/keywords to other
* words. This is used to help cope with cases where C preprocessor
@ -2447,11 +2507,7 @@ fail:
NSString *tmp;
tmp = [NSString stringWithCharacters: start length: end - start];
if (comment != nil)
{
tmp = [comment stringByAppendingFormat: @"<br />\n%@", tmp];
}
ASSIGN(comment, tmp);
[self appendComment: tmp to: nil];
}
if (commentsRead == NO && comment != nil)

View file

@ -32,7 +32,7 @@
parse corresponding source files in the same directory as the
headers (or the current directory, or the directory specified
using the DocumentationDirectory default), and produce gsdoc
files as output.
and html files as output.
</p>
<p>
Even without any human assistance, this tool will produce skeleton
@ -44,7 +44,18 @@
Any comment beginning with slash and <em>two</em> asterisks rather than
the common slash and single asterisk, is taken to be gsdoc markup, to
be use as the description of the class or method following it. This
comment text is reformatted and then inserted into the output.
comment text is reformatted and then inserted into the output.<br />
Where multiple comments are associatd with the same item, they are
joined together with a line break (&lt;br /&gt;) between each if
necessary.
</p>
<p>
The tool can easily be used to document programs as well as libraries,
simply by giving it the name of the source file containing the main()
function of the program - it takes the special comments from that
function and handles them specially, inserting them as a section at
the end of the first chapter of the document (it creates the first
chapter if necessary).
</p>
<p>
There are some cases where special extra processing is performed,
@ -90,7 +101,9 @@
<item><strong>&lt;chapter&gt;</strong>
Placed immediately before any generated class documentation ...
intended to be used to provide overall description of how the
code being documented works.<br />
code being documented works.<br />Any documentation for the main()
function of a program is inserted as a section at the end of this
chapter.
</item>
<item><strong>&lt;copy&gt;</strong>
Copyright of the content of the document ... placed in the head
@ -112,7 +125,7 @@
<item><strong>&lt;title&gt;</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.
title of its own - so you should include this markup manually.
</item>
<item>
<strong>NB</strong>This markup may be used within
@ -178,13 +191,14 @@
</item>
<item>Method specifiers including class names (beginning and ending with
square brackets) are enclosed in &lt;ref...&gt; ... &lt;/ref&gt; markup.
<br />eg. [ NSObject-init],
will create a reference to the init method of NSObject, while
<br />[ (NSCopying)-copyWithZone:], creates a
<br />eg. <code>[</code>NSObject-init<code>]</code>,
will create a reference to the init method of NSObject (either the
class proper, or any of its categories), while
<br /><code>[</code>(NSCopying)-copyWithZone:<code>]</code>, creates a
reference to a method in the NSCopyIng protocol.
<br />Note that no spaces must appear between the square brackets
in these specifiers.
<br />Protocol namnes are enclosed in round brackets rather than
<br />Protocol names are enclosed in round brackets rather than
the customary angle brackets, because gsdoc is an XML language, and
XML treats angle brackets specially.
</item>
@ -197,16 +211,16 @@
<item><strong>ConstantsTemplate</strong>
Specify the name of a template document into which documentation
about constants should be inserted from all files in the project.<br />
This is useful if constanr in the source code are scattered around many
This is useful if constants in the source code are scattered around many
files, and you need to group them into one place.<br />
You are responsible for ensuring that the basic template document
(into which individual constant documentation is inserted) contains
all the other information you want, but as a conveniencem autogsdoc
all the other information you want, but as a convenience autogsdoc
will generate a simple template (which you may then edit) for you
if the file does not exist.
<br />Insertion takes place immediately before the <em>back</em>
element (or if that does not exist, immediately before the end
of the <em>body</em> lement) in the template.
of the <em>body</em> element) in the template.
</item>
<item><strong>Declared</strong>
Specify where headers are to be documented as being found.<br />
@ -239,7 +253,7 @@
files, and you need to group it into one place.<br />
You are responsible for ensuring that the basic template document
(into which individual function documentation is inserted) contains
all the other information you want, but as a conveniencem autogsdoc
all the other information you want, but as a convenience autogsdoc
will generate a simple template (which you may then edit) for you
if the file does not exist.
<br />Insertion takes place immediately before the <em>back</em>
@ -336,7 +350,7 @@
files, and you need to group it into one place.<br />
You are responsible for ensuring that the basic template document
(into which individual typedef documentation is inserted) contains
all the other information you want, but as a conveniencem autogsdoc
all the other information you want, but as a convenience autogsdoc
will generate a simple template (which you may then edit) for you
if the file does not exist.
<br />Insertion takes place immediately before the <em>back</em>
@ -357,13 +371,21 @@
files, and you need to group it into one place.<br />
You are responsible for ensuring that the basic template document
(into which individual variable documentation is inserted) contains
all the other information you want, but as a conveniencem autogsdoc
all the other information you want, but as a convenience autogsdoc
will generate a simple template (which you may then edit) for you
if the file does not exist.
<br />Insertion takes place immediately before the <em>back</em>
element (or if that does not exist, immediately before the end
of the <em>body</em> lement) in the template.
</item>
<item><strong>Verbose</strong>
A boolean used to specify whether you want verbose debug/warning
output to be produced.
</item>
<item><strong>Warn</strong>
A boolean used to specify whether you want standard warning
output (eg report of undocumented methods) produced.
</item>
<item><strong>WordMap</strong>
This value is a dictionary used to map identifiers/keywords found
in the source files to other words. Generally you will not have
@ -443,6 +465,7 @@ main(int argc, char **argv, char **env)
BOOL ignoreDependencies = NO;
BOOL showDependencies = NO;
BOOL verbose = NO;
BOOL warn = NO;
NSArray *files;
NSMutableArray *sFiles = nil; // Source
NSMutableArray *gFiles = nil; // GSDOC
@ -469,6 +492,7 @@ main(int argc, char **argv, char **env)
nil]];
verbose = [defs boolForKey: @"Verbose"];
warn = [defs boolForKey: @"Warn"];
ignoreDependencies = [defs boolForKey: @"IgnoreDependencies"];
showDependencies = [defs boolForKey: @"ShowDependencies"];
if (ignoreDependencies == YES)
@ -607,9 +631,7 @@ main(int argc, char **argv, char **env)
parser = [AGSParser new];
[parser setWordMap: [defs dictionaryForKey: @"WordMap"]];
[parser setVerbose: verbose];
output = [AGSOutput new];
[output setVerbose: verbose];
if ([defs boolForKey: @"Standards"] == YES)
{
[parser setGenerateStandards: YES];

View file

@ -3854,7 +3854,8 @@ nameServer(const char* name, const char* host, int op, int ptype, struct sockadd
rval = tryHost(GDO_SERVERS, 0, 0, ptype, &sin, &num, (uptr*)&b);
if (rval != 0 && host == local_hostname)
{
sprintf(ebuf, "failed to contact gdomap (%s)\n", strerror(errno));
sprintf(ebuf, "failed to contact gdomap on %s(%s) - %s",
local_hostname, inet_ntoa(sin.sin_addr), strerror(errno));
gdomap_log(LOG_ERR);
return -1;
}
@ -3907,7 +3908,8 @@ nameServer(const char* name, const char* host, int op, int ptype, struct sockadd
rval = tryHost(op, len, name, ptype, &sin, &port, 0);
if (rval != 0 && host == local_hostname)
{
sprintf(ebuf, "failed to contact gdomap (%s)", strerror(errno));
sprintf(ebuf, "failed to contact gdomap on %s(%s) - %s",
local_hostname, inet_ntoa(sin.sin_addr), strerror(errno));
gdomap_log(LOG_ERR);
return -1;
}
@ -3956,7 +3958,7 @@ lookup(const char *name, const char *host, int ptype)
}
static void
donames()
donames(const char *host)
{
struct sockaddr_in sin;
struct servent* sp;
@ -3966,7 +3968,6 @@ donames()
int rval;
uptr b;
char *first_dot;
const char *host;
#ifdef __MINGW__
char local_hostname[INTERNET_MAX_HOST_NAME_LENGTH];
#else
@ -3986,23 +3987,25 @@ donames()
}
#endif
/*
* If no host name is given, we use the name of the local host.
* NB. This should always be the case for operations other than lookup.
*/
if (host == 0 || *host == '\0')
{
/*
* If no host name is given, we use the name of the local host.
*/
if (gethostname(local_hostname, sizeof(local_hostname)) < 0)
{
sprintf(ebuf, "gethostname() failed: %s", strerror(errno));
gdomap_log(LOG_ERR);
return;
if (gethostname(local_hostname, sizeof(local_hostname)) < 0)
{
sprintf(ebuf, "gethostname() failed: %s", strerror(errno));
gdomap_log(LOG_ERR);
return;
}
first_dot = strchr(local_hostname, '.');
if (first_dot)
{
*first_dot = '\0';
}
host = local_hostname;
}
first_dot = strchr(local_hostname, '.');
if (first_dot)
{
*first_dot = '\0';
}
host = local_hostname;
if ((hp = gethostbyname(host)) == 0)
{
sprintf(ebuf, "gethostbyname() failed: %s", strerror(errno));
@ -4024,7 +4027,8 @@ donames()
rval = tryHost(GDO_NAMES, 0, 0, 0, &sin, &num, (uptr*)&b);
if (rval != 0)
{
sprintf(ebuf, "failed to contact gdomap (%s)", strerror(errno));
sprintf(ebuf, "failed to contact gdomap on %s(%s) - %s",
local_hostname, inet_ntoa(sin.sin_addr), strerror(errno));
gdomap_log(LOG_ERR);
return;
}
@ -4099,11 +4103,13 @@ int
main(int argc, char** argv)
{
extern char *optarg;
char *options = "CHI:L:M:NP:R:T:U:a:bc:dfi:p";
char *options = "-CHI:L:M:NP:R:T:U:a:bc:dfi:p";
int c;
int ptype = GDO_TCP_GDO;
int port = 0;
const char *machine = 0;
const char *lookupf = 0;
int donamesf = 0;
#ifdef HAVE_SYSLOG
/* Initially, gdomap_log errors to stderr as well as to syslogd. */
@ -4154,8 +4160,8 @@ main(int argc, char** argv)
printf("-H general help\n");
printf("-I pid file to write pid\n");
printf("-L name perform lookup for name then quit.\n");
printf("-M name machine name for L (default local)\n");
printf("-N list all names registered on this host\n");
printf("-M name machine name for -L and -N\n");
printf("-N list all names registered on host\n");
printf("-P number port number required for R option.\n");
printf("-R name register name locally then quit.\n");
printf("-T type port type for L, R and U options -\n");
@ -4220,16 +4226,16 @@ printf(
exit(0);
case 'L':
lookup(optarg, machine, ptype);
exit(0);
lookupf = optarg;
break;
case 'M':
machine = optarg;
break;
case 'N':
donames();
exit(0);
donamesf = 1;
break;
case 'P':
port = atoi(optarg);
@ -4415,6 +4421,18 @@ printf(
exit(0);
}
}
if (donamesf || lookupf)
{
if (donamesf)
{
donames(machine);
}
if (lookupf)
{
lookup(lookupf, machine, ptype);
}
exit (0);
}
#ifdef __MINGW__ /* On Win32, we don't fork */
if (nofork == 0)