Preliminary C language constructs added.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@12407 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-Macdonald 2002-02-04 20:20:07 +00:00
parent 0f247c5d5b
commit 5526098238
9 changed files with 647 additions and 51 deletions

View file

@ -2,6 +2,11 @@
* Tools/gsdoc.m: loader() if entity id is missing, try to load url as
a file.
* Tools/AGSParser.m: Fixes for handling typedefs, constants, varibales
and functions.
* Tools/AGSOutput.[hm]: ditto
* Tools/AGSHtml.m: ditto
Preliminary support for C language added.
2002-02-03 Richard Frith-Macdonald <rfm@gnu.org>

View file

@ -46,27 +46,27 @@ typedef void* NSHashTable;
*/
typedef struct { void *map; void *node; } NSHashEnumerator;
/* Callback functions. */
typedef struct _NSHashTableCallBacks NSHashTableCallBacks;
struct _NSHashTableCallBacks
/** Callback functions. <br />*/
typedef struct _NSHashTableCallBacks
{
/* Hashing function. NOTE: Elements with equal values must have
* equal hash function values. */
/** hash() ... Hashing function. NOTE: Elements with equal values must have
* equal hash function values. <br />*/
unsigned int (*hash)(NSHashTable *, const void *);
/* Comparison function. */
/** isEqual() ... Comparison function. <br />*/
BOOL (*isEqual)(NSHashTable *, const void *, const void *);
/* Retaining function called when adding elements to table. */
/** retain() ... Retaining function called when adding elements
* to the table. <br />*/
void (*retain)(NSHashTable *, const void *);
/* Releasing function called when a data element is
* removed from the table. */
/** release() ... Releasing function called when a data element is
* removed from the table. <br />*/
void (*release)(NSHashTable *, const void *);
/* Description function. */
/** describe() ... Description function. <br />*/
NSString *(*describe)(NSHashTable *, const void *);
};
} NSHashTableCallBacks;
/* For sets of pointer-sized or smaller quantities. */
GS_EXPORT const NSHashTableCallBacks NSIntHashCallBacks;

View file

@ -46,8 +46,7 @@ typedef void *NSMapTable;
typedef struct { void *map; void *node; } NSMapEnumerator;
/* Callback functions for a key. */
typedef struct _NSMapTableKeyCallBacks NSMapTableKeyCallBacks;
struct _NSMapTableKeyCallBacks
typedef struct _NSMapTableKeyCallBacks
{
/* Hashing function. NOTE: Elements with equal values must
* have equal hash function values. */
@ -68,7 +67,7 @@ struct _NSMapTableKeyCallBacks
/* Quantity that is not a key to the map table. */
const void *notAKeyMarker;
};
} NSMapTableKeyCallBacks;
/* Callback functions for a value. */
typedef struct _NSMapTableValueCallBacks NSMapTableValueCallBacks;

View file

@ -545,6 +545,59 @@ static NSMutableSet *textNodes = nil;
[self outputText: children to: buf];
[buf appendString: @"</code>"];
}
else if ([name isEqual: @"constant"] == YES)
{
NSString *nam;
NSString *str;
NSString *s;
nam = [prop objectForKey: @"name"];
str = [prop objectForKey: @"type"];
str = [str stringByAppendingFormat: @" %@;", nam];
/*
* Output function heading.
*/
[buf appendString: indent];
[buf appendString: @"<h3>"];
s = [self makeLink: nam ofType: @"constant" isRef: NO];
if (s != nil)
{
[buf appendString: s];
[buf appendString: nam];
[buf appendString: @"</a>"];
}
else
{
[buf appendString: nam];
}
[buf appendString: @"</h3>\n"];
[buf appendString: indent];
[buf appendString: str];
[buf appendString: @";<br />\n"];
node = firstElement(children);
if ([[node name] isEqual: @"declared"] == YES)
{
[self outputNode: node to: buf];
node = firstElement(node);
}
children = firstElement(node);
if ([[children name] isEqual: @"standards"])
{
[self outputNode: children to: buf];
}
if ([[node name] isEqual: @"desc"])
{
[self outputNode: node to: buf];
}
[buf appendString: indent];
[buf appendString: @"<hr width=\"25%\" align=\"left\" />\n"];
}
else if ([name isEqual: @"contents"] == YES)
{
NSDictionary *dict;
@ -745,6 +798,115 @@ static NSMutableSet *textNodes = nil;
[buf appendString: indent];
[buf appendString: @"</div>\n"];
}
else if ([name isEqual: @"function"] == YES)
{
NSString *fun;
NSString *str;
NSString *s;
GSXMLNode *tmp = children;
BOOL hadArg = NO;
fun = [prop objectForKey: @"name"];
str = [prop objectForKey: @"type"];
str = [str stringByAppendingFormat: @" %@(", fun];
children = nil;
while (tmp != nil)
{
if ([tmp type] == XML_ELEMENT_NODE)
{
if ([[tmp name] isEqual: @"arg"] == YES)
{
GSXMLNode *t = [tmp children];
NSString *s;
if (hadArg == YES)
{
str = [str stringByAppendingString: @", "];
}
s = [[tmp propertiesAsDictionary] objectForKey: @"type"];
s = [self typeRef: s];
str = [str stringByAppendingString: s];
str = [str stringByAppendingString: @" <b>"];
while (t != nil)
{
if ([t type] == XML_TEXT_NODE)
{
NSString *content = [t content];
str = [str stringByAppendingString: content];
}
t = [t next];
}
str = [str stringByAppendingString: @"</b>"];
hadArg = YES;
}
else if ([[tmp name] isEqual: @"vararg"] == YES)
{
if (hadArg == YES)
{
str = [str stringByAppendingString: @"<b>,...</b>"];
}
else
{
str = [str stringByAppendingString: @"<b>,...</b>"];
}
children = [tmp next];
break;
}
else
{
children = tmp;
break;
}
}
tmp = [tmp next];
}
/*
* Output function heading.
*/
[buf appendString: indent];
[buf appendString: @"<h3>"];
s = [self makeLink: fun ofType: @"function" isRef: NO];
if (s != nil)
{
[buf appendString: s];
[buf appendString: fun];
[buf appendString: @"</a>"];
}
else
{
[buf appendString: fun];
}
[buf appendString: @"</h3>\n"];
[buf appendString: indent];
[buf appendString: str];
[buf appendString: @");<br />\n"];
node = firstElement(children);
if ([[node name] isEqual: @"declared"] == YES)
{
[self outputNode: node to: buf];
node = firstElement(node);
}
children = firstElement(node);
if ([[children name] isEqual: @"standards"])
{
[self outputNode: children to: buf];
}
if ([[node name] isEqual: @"desc"])
{
[self outputNode: node to: buf];
}
[buf appendString: indent];
[buf appendString: @"<hr width=\"25%\" align=\"left\" />\n"];
}
else if ([name isEqual: @"gsdoc"] == YES)
{
base = [prop objectForKey: @"base"];
@ -1112,12 +1274,13 @@ static NSMutableSet *textNodes = nil;
[buf appendString: indent];
[buf appendString: str];
[buf appendString: @";<br />\n"];
node = children;
node = firstElement(children);
/*
* List standards with which method complies
*/
children = [node next];
children = firstElement(node);
if ([[children name] isEqual: @"standards"])
{
[self outputNode: children to: buf];
@ -1198,12 +1361,9 @@ static NSMutableSet *textNodes = nil;
[self outputUnit: node to: buf];
unit = nil;
}
else if ([name isEqual: @"constant"] == YES
|| [name isEqual: @"EOEntity"] == YES
else if ([name isEqual: @"EOEntity"] == YES
|| [name isEqual: @"EOModel"] == YES
|| [name isEqual: @"function"] == YES
|| [name isEqual: @"macro"] == YES
|| [name isEqual: @"type"] == YES)
|| [name isEqual: @"macro"] == YES)
{
NSString *tmp = [prop objectForKey: @"name"];
@ -1273,33 +1433,57 @@ static NSMutableSet *textNodes = nil;
}
else if ([name isEqual: @"type"] == YES)
{
NSString *n = [prop objectForKey: @"name"];
NSString *nam;
NSString *str;
NSString *s;
node = [node children];
s = [NSString stringWithFormat: @"typedef %@ %@", [node content], n];
nam = [prop objectForKey: @"name"];
str = [prop objectForKey: @"type"];
str = [NSString stringWithFormat: @"typedef %@ %@", str, nam];
/*
* Output typedef heading.
*/
[buf appendString: indent];
[buf appendString: @"<h3>"];
[buf appendString:
[self makeAnchor: n ofType: @"type" name: s]];
s = [self makeLink: nam ofType: @"type" isRef: NO];
if (s != nil)
{
[buf appendString: s];
[buf appendString: nam];
[buf appendString: @"</a>"];
}
else
{
[buf appendString: nam];
}
[buf appendString: @"</h3>\n"];
node = [node next];
[buf appendString: indent];
[buf appendString: str];
[buf appendString: @";<br />\n"];
node = firstElement(children);
if (node != nil && [[node name] isEqual: @"declared"] == YES)
{
[self outputNode: node to: buf];
node = [node next];
node = firstElement(node);
}
children = firstElement(node);
if ([[children name] isEqual: @"standards"])
{
[self outputNode: children to: buf];
}
if (node != nil && [[node name] isEqual: @"desc"] == YES)
{
[self outputNode: node to: buf];
node = [node next];
}
if (node != nil && [[node name] isEqual: @"standards"] == YES)
{
[self outputNode: node to: buf];
node = [node next];
node = firstElement(node);
}
[buf appendString: indent];
[buf appendString: @"<hr width=\"25%\" align=\"left\" />\n"];
}
else if ([name isEqual: @"uref"] == YES)
{
@ -1321,7 +1505,56 @@ NSLog(@"Element '%@' not implemented", name); // FIXME
}
else if ([name isEqual: @"variable"] == YES)
{
NSLog(@"Element '%@' not implemented", name); // FIXME
NSString *nam;
NSString *str;
NSString *s;
nam = [prop objectForKey: @"name"];
str = [prop objectForKey: @"type"];
str = [str stringByAppendingFormat: @" %@", nam];
/*
* Output variable heading.
*/
[buf appendString: indent];
[buf appendString: @"<h3>"];
s = [self makeLink: nam ofType: @"variable" isRef: NO];
if (s != nil)
{
[buf appendString: s];
[buf appendString: nam];
[buf appendString: @"</a>"];
}
else
{
[buf appendString: nam];
}
[buf appendString: @"</h3>\n"];
[buf appendString: indent];
[buf appendString: str];
[buf appendString: @";<br />\n"];
node = firstElement(children);
if ([[node name] isEqual: @"declared"] == YES)
{
[self outputNode: node to: buf];
node = firstElement(node);
}
children = firstElement(node);
if ([[children name] isEqual: @"standards"])
{
[self outputNode: children to: buf];
}
if ([[node name] isEqual: @"desc"])
{
[self outputNode: node to: buf];
}
[buf appendString: indent];
[buf appendString: @"<hr width=\"25%\" align=\"left\" />\n"];
}
else
{

View file

@ -370,6 +370,7 @@ setDirectory(NSMutableDictionary *dict, NSString *path)
NSString *tmp = [prop objectForKey: @"name"];
[self setGlobalRef: tmp type: name];
children = nil;
}
else if ([name isEqual: @"section"] == YES)
{

View file

@ -41,6 +41,10 @@
output: (NSMutableString*)buf;
- (NSString*) output: (NSDictionary*)d;
- (BOOL) output: (NSDictionary*)d file: (NSString*)name;
- (void) outputDecl: (NSDictionary*)d
kind: (NSString*)kind
to: (NSMutableString*)str;
- (void) outputFunction: (NSDictionary*)d to: (NSMutableString*)str;
- (void) outputInstanceVariable: (NSDictionary*)d to: (NSMutableString*)str;
- (void) outputMethod: (NSDictionary*)d to: (NSMutableString*)str;
- (void) outputUnit: (NSDictionary*)d to: (NSMutableString*)str;

View file

@ -179,12 +179,20 @@ static BOOL snuggleStart(NSString *t)
return self;
}
/**
* Return a string containing a gsdoc document generated from d (the
* parse tree)
*/
- (NSString*) output: (NSDictionary*)d
{
NSMutableString *str = [NSMutableString stringWithCapacity: 10240];
NSDictionary *classes;
NSDictionary *categories;
NSDictionary *protocols;
NSDictionary *functions;
NSDictionary *types;
NSDictionary *variables;
NSDictionary *constants;
NSArray *authors;
NSString *tmp;
unsigned chapters = 0;
@ -194,6 +202,10 @@ static BOOL snuggleStart(NSString *t)
classes = [info objectForKey: @"Classes"];
categories = [info objectForKey: @"Categories"];
protocols = [info objectForKey: @"Protocols"];
functions = [info objectForKey: @"Functions"];
types = [info objectForKey: @"Types"];
variables = [info objectForKey: @"Variables"];
constants = [info objectForKey: @"Constants"];
[str appendString: @"<?xml version=\"1.0\"?>\n"];
[str appendString: @"<!DOCTYPE gsdoc PUBLIC "];
@ -380,6 +392,106 @@ static BOOL snuggleStart(NSString *t)
}
}
if ([types count] > 0)
{
NSArray *names;
unsigned i;
unsigned c = [types count];
[str appendString: @" <chapter>\n"];
[str appendString:
@" <heading>Types</heading>\n"];
[str appendString: @" <p></p>\n"];
chapters++;
names = [types allKeys];
names = [names sortedArrayUsingSelector: @selector(compare:)];
for (i = 0; i < c; i++)
{
NSString *name = [names objectAtIndex: i];
NSDictionary *d = [types objectForKey: name];
[self outputDecl: d kind: @"type" to: str];
}
[str appendString: @" </chapter>\n"];
}
if ([constants count] > 0)
{
NSArray *names;
unsigned i;
unsigned c = [constants count];
[str appendString: @" <chapter>\n"];
[str appendString:
@" <heading>Constants</heading>\n"];
[str appendString: @" <p></p>\n"];
chapters++;
names = [constants allKeys];
names = [names sortedArrayUsingSelector: @selector(compare:)];
for (i = 0; i < c; i++)
{
NSString *name = [names objectAtIndex: i];
NSDictionary *d = [constants objectForKey: name];
[self outputDecl: d kind: @"constant" to: str];
}
[str appendString: @" </chapter>\n"];
}
if ([variables count] > 0)
{
NSArray *names;
unsigned i;
unsigned c = [variables count];
[str appendString: @" <chapter>\n"];
[str appendString:
@" <heading>Variables</heading>\n"];
[str appendString: @" <p></p>\n"];
chapters++;
names = [variables allKeys];
names = [names sortedArrayUsingSelector: @selector(compare:)];
for (i = 0; i < c; i++)
{
NSString *name = [names objectAtIndex: i];
NSDictionary *d = [variables objectForKey: name];
[self outputDecl: d kind: @"variable" to: str];
}
[str appendString: @" </chapter>\n"];
}
if ([functions count] > 0)
{
NSArray *names;
unsigned i;
unsigned c = [functions count];
[str appendString: @" <chapter>\n"];
[str appendString:
@" <heading>Functions</heading>\n"];
[str appendString: @" <p></p>\n"];
chapters++;
names = [functions allKeys];
names = [names sortedArrayUsingSelector: @selector(compare:)];
for (i = 0; i < c; i++)
{
NSString *name = [names objectAtIndex: i];
NSDictionary *d = [functions objectForKey: name];
[self outputFunction: d to: str];
}
[str appendString: @" </chapter>\n"];
}
if (chapters == 0)
{
// We must have at least one chapter!
@ -409,6 +521,197 @@ static BOOL snuggleStart(NSString *t)
return [str writeToFile: name atomically: YES];
}
/**
* Uses -split: and -reformat:withIndent:to:.
*/
- (void) outputDecl: (NSDictionary*)d
kind: (NSString*)kind
to: (NSMutableString*)str
{
NSString *pref = [d objectForKey: @"Prefix"];
NSString *type = [d objectForKey: @"BaseType"];
NSString *name = [d objectForKey: @"Name"];
NSString *comment = [d objectForKey: @"Comment"];
NSString *declared = [d objectForKey: @"Declared"];
NSString *standards = nil;
if (standards == nil)
{
standards = [d objectForKey: @"Standards"];
}
[str appendFormat: @" <%@ type=\"", kind];
[str appendString: escapeType(type)];
if ([pref length] > 0)
{
[str appendString: pref];
}
[str appendString: @"\" name=\""];
[str appendString: name];
[str appendString: @"\">\n"];
if (declared != nil)
{
[str appendString: @" <declared>"];
[str appendString: declared];
[str appendString: @"</declared>\n"];
}
[str appendString: @" <desc>\n"];
if ([comment length] == 0)
{
comment = @"<em>Description forthcoming.</em>";
}
[self reformat: comment withIndent: 10 to: str];
[str appendString: @" </desc>\n"];
if (standards != nil)
{
[self reformat: standards withIndent: 8 to: str];
}
[str appendFormat: @" </%@>\n", kind];
}
/**
* Uses -split: and -reformat:withIndent:to:.
*/
- (void) outputFunction: (NSDictionary*)d to: (NSMutableString*)str
{
NSArray *aa = [d objectForKey: @"Args"];
NSString *pref = [d objectForKey: @"Prefix"];
NSString *type = [d objectForKey: @"BaseType"];
NSString *name = [d objectForKey: @"Name"];
NSString *comment = [d objectForKey: @"Comment"];
NSString *declared = [d objectForKey: @"Declared"];
NSString *standards = nil;
unsigned i = [aa count];
/**
* Place the names of function arguments in a temporary array 'args'
* so that they will be highlighted if they appear in the function
* description.
*/
if (i > 0)
{
NSMutableArray *tmp = [NSMutableArray arrayWithCapacity: i];
while (i-- > 0)
{
NSString *n = [[aa objectAtIndex: i] objectForKey: @"Name"];
if (n != nil)
{
[tmp addObject: n];
}
}
if ([tmp count] > 0)
{
args = tmp;
}
}
/**
* Check special markup which should be removed from the text
* actually placed in the gsdoc method documentation ... the
* special markup is included in the gsdoc markup differently.
*/
if (comment != nil)
{
NSMutableString *m = nil;
NSRange r;
r = [comment rangeOfString: @"<standards>"];
if (r.length > 0)
{
unsigned i = r.location;
r = NSMakeRange(i, [comment length] - i);
r = [comment rangeOfString: @"</standards>"
options: NSLiteralSearch
range: r];
if (r.length > 0)
{
r = NSMakeRange(i, NSMaxRange(r) - i);
standards = [comment substringWithRange: r];
if (m == nil)
{
m = [comment mutableCopy];
}
[m deleteCharactersInRange: r];
comment = m;
}
else
{
NSLog(@"unterminated <standards> in comment for %@", name);
}
}
if (m != nil)
{
AUTORELEASE(m);
}
}
if (standards == nil)
{
standards = [d objectForKey: @"Standards"];
}
[str appendString: @" <function type=\""];
[str appendString: escapeType(type)];
if ([pref length] > 0)
{
[str appendString: pref];
}
[str appendString: @"\" name=\""];
[str appendString: name];
[str appendString: @"\">\n"];
for (i = 0; i < [aa count]; i++)
{
NSDictionary *a = [aa objectAtIndex: i];
NSString *s = [a objectForKey: @"BaseType"];
[str appendString: @" <arg type=\""];
[str appendString: s];
s = [a objectForKey: @"Prefix"];
if (s != nil)
{
[str appendString: s];
}
s = [a objectForKey: @"Suffix"];
if (s != nil)
{
[str appendString: s];
}
[str appendString: @"\">"];
[str appendString: [a objectForKey: @"Name"]];
[str appendString: @"</arg>\n"];
}
if ([[d objectForKey: @"VarArgs"] boolValue] == YES)
{
[str appendString: @"<vararg />\n"];
}
if (declared != nil)
{
[str appendString: @" <declared>"];
[str appendString: declared];
[str appendString: @"</declared>\n"];
}
[str appendString: @" <desc>\n"];
if ([comment length] == 0)
{
comment = @"<em>Description forthcoming.</em>";
}
[self reformat: comment withIndent: 10 to: str];
[str appendString: @" </desc>\n"];
if (standards != nil)
{
[self reformat: standards withIndent: 8 to: str];
}
[str appendString: @" </function>\n"];
args = nil;
}
/**
* Output the gsdoc code for an instance variable.
*/
@ -594,7 +897,7 @@ static BOOL snuggleStart(NSString *t)
[str appendString: @"</arg>\n"];
}
}
if ([[d objectForKey: @"VarArg"] boolValue] == YES)
if ([[d objectForKey: @"VarArgs"] boolValue] == YES)
{
[str appendString: @"<vararg />\n"];
}

View file

@ -145,7 +145,7 @@
else if (buffer[pos] == '.')
{
pos += 3; // Skip '...'
[d setObject: @"YES" forKey: @"Varargs"];
[d setObject: @"YES" forKey: @"VarArgs"];
}
else
{
@ -477,21 +477,21 @@
RELEASE(t);
/*
* Set the 'Kind' of declaration ... one of 'typedef', 'function',
* 'variable', or 'constant'
* We may ovrride this later.
* Set the 'Kind' of declaration ... one of 'Types', 'Functions',
* 'Variables', or 'Constants'
* We may override this later.
*/
if (isTypedef == YES)
{
[d setObject: @"typedef" forKey: @"Kind"];
[d setObject: @"Types" forKey: @"Kind"];
}
else if (baseConstant == YES)
{
[d setObject: @"constant" forKey: @"Kind"];
[d setObject: @"Constants" forKey: @"Kind"];
}
else
{
[d setObject: @"variable" forKey: @"Kind"];
[d setObject: @"Variables" forKey: @"Kind"];
}
if (s == nil)
@ -523,7 +523,7 @@
options: NSBackwardsSearch|NSLiteralSearch];
if (r.length > 0 && r.location >= p)
{
[d setObject: @"constant" forKey: @"Kind"];
[d setObject: @"Constants" forKey: @"Kind"];
}
}
}
@ -575,7 +575,7 @@
*/
if (isPointer == NO || [d objectForKey: @"Suffix"] == nil)
{
[d setObject: @"function" forKey: @"Kind"];
[d setObject: @"Functions" forKey: @"Kind"];
isFunction = YES;
}
}
@ -689,7 +689,8 @@ fail:
- (NSMutableDictionary*) parseFile: (NSString*)name isSource: (BOOL)isSource
{
NSString *token;
NSString *token;
NSMutableDictionary *nDecl;
commentsRead = NO;
fileName = name;
@ -772,8 +773,59 @@ fail:
* Must be some sort of declaration ...
*/
pos--;
[self parseDeclaration];
// [self skipStatementLine];
nDecl = [self parseDeclaration];
if (nDecl != nil)
{
NSString *name = [nDecl objectForKey: @"Name"];
NSString *kind = [nDecl objectForKey: @"Kind"];
NSMutableDictionary *dict = [info objectForKey: kind];
if (isSource == NO)
{
/*
* Ensure that we have an entry for this declaration.
*/
if (dict == nil)
{
dict = [NSMutableDictionary new];
[info setObject: dict forKey: kind];
RELEASE(dict);
}
[dict setObject: nDecl forKey: name];
}
else
{
NSMutableDictionary *oDecl = [dict objectForKey: name];
if (oDecl != nil)
{
NSString *tmp = [nDecl objectForKey: @"Comment"];
if (tmp != nil)
{
NSString *old = [oDecl objectForKey: @"Comment"];
if (old != nil)
{
tmp = [old stringByAppendingString: tmp];
}
[oDecl setObject: tmp forKey: @"Comment"];
}
if ([kind isEqualToString: @"Functions"] == YES)
{
NSArray *a1 = [oDecl objectForKey: @"Args"];
NSArray *a2 = [nDecl objectForKey: @"Args"];
if ([a1 isEqual: a2] == NO)
{
[self log: @"Function %@ args missmatch - "
@"%@ %@", name, a1, a2];
}
}
}
}
}
break;
}
}

View file

@ -258,12 +258,11 @@
name CDATA #REQUIRED
>
<!ELEMENT typespec (#PCDATA)*>
<!-- A type definition. -->
<!ELEMENT type (typespec, declared?, desc?, standards?)>
<!ELEMENT type (declared?, desc?, standards?)>
<!ATTLIST type
name CDATA #REQUIRED
type CDATA #REQUIRED
>
<!-- Variable definition.