OSX compatibility improvements

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@31909 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
rfm 2011-01-18 12:07:21 +00:00
parent d9fcafa8c8
commit b746f90b6e
3 changed files with 133 additions and 34 deletions

View file

@ -1,3 +1,14 @@
2011-01-18 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSPropertyList.m: For OSX compatibility we now quote strings
in property lists of they contain non-alphanumerics. We also warn
when we parse a dictionary with a missing semicolon at the end.
* Source/NSXMLParser.m: For OSX compatibility we report all character
data as characters and never as ignorable whitespace, though this
seems perverse.
Implement insertion of default attribute values into elements if we
have parsed an !ATTLIST which defines them.
2011-01-17 Richard Frith-Macdonald <rfm@gnu.org>
* Source/GSFormat.m: Print '(null)' rather than '(nil)' for a nil

View file

@ -567,9 +567,12 @@ static void setupQuotables(void)
{
NSMutableCharacterSet *s;
/* The '$', '.', '/' and '_' characters used to be OK to use in
* property lists, but OSX now quotes them, so we follow suite.
*/
s = [[NSCharacterSet characterSetWithCharactersInString:
@"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
@"abcdefghijklmnopqrstuvwxyz$./_"]
@"abcdefghijklmnopqrstuvwxyz"]
mutableCopy];
[s invert];
oldQuotables = [s copy];
@ -984,7 +987,24 @@ static id parsePlItem(pldata* pld)
{
pld->pos++;
}
else if (pld->ptr[pld->pos] != '}')
else if (pld->ptr[pld->pos] == '}')
{
if (GSPrivateDefaultsFlag(GSMacOSXCompatible))
{
pld->err = @"unexpected character '}' (wanted ';')";
RELEASE(key);
RELEASE(val);
RELEASE(dict);
return nil;
}
else
{
NSWarnFLog(
@"Missing semicolon in dictionary at line %d char %d",
pld->lin + 1, pld->pos + 1);
}
}
else
{
pld->err = @"unexpected character (wanted ';' or '}')";
RELEASE(key);
@ -2603,8 +2623,8 @@ GSPropertyListMake(id obj, NSDictionary *loc, BOOL xml,
if (_pld.err != nil)
{
errorStr = [NSString stringWithFormat:
@"Parse failed at line %d (char %d) - %@",
_pld.lin + 1, _pld.pos + 1, _pld.err];
@"Parse failed at line %d (char %d) - %@",
_pld.lin + 1, _pld.pos + 1, _pld.err];
}
}
break;

View file

@ -619,6 +619,7 @@ typedef struct NSXMLParserIvarsType
{
NSMutableArray *tagPath; // hierarchy of tags
NSMutableArray *namespaces;
NSMutableDictionary *defaults;
NSData *data;
NSError *error;
const unsigned char *cp; // character pointer
@ -633,6 +634,7 @@ typedef struct NSXMLParserIvarsType
BOOL shouldResolveExternalEntities;
BOOL acceptHTML; // be lazy with bad tag nesting
BOOL hasStarted;
BOOL hasElement;
IMP didEndElement;
IMP didEndMappingPrefix;
IMP didStartElement;
@ -711,6 +713,7 @@ static SEL foundIgnorableSel;
RELEASE(this->error);
RELEASE(this->tagPath);
RELEASE(this->namespaces);
RELEASE(this->defaults);
NSZoneFree([self zone], this);
_parser = 0;
_handler = 0;
@ -856,8 +859,15 @@ static SEL foundIgnorableSel;
if ([_del respondsToSelector: foundIgnorableSel])
{
/* It seems OX reports ignorable whitespace as characters,
* so we disable this ... FIXME can this really be right?
*/
#if 0
this->foundIgnorable
= [_del methodForSelector: foundIgnorableSel];
#else
this->foundIgnorable = 0;
#endif
}
else
{
@ -1023,13 +1033,29 @@ NSLog(@"parserDidStartDocument: ");
if ([decl isEqualToString: @"ATTLIST"])
{
NSString *elem = name;
NSString *type;
NSString *def;
NSMutableDictionary *d;
NSString *elem = name;
NSString *type;
NSString *def;
#if EXTRA_DEBUG
NSLog(@"_processDeclaration <%@%@ %@>", flag?@"/": @"", decl, name);
#endif
/* Get the dictionary of attribute defaults for this element.
*/
d = [this->defaults objectForKey: elem];
if (nil == d)
{
if (nil == this->defaults)
{
this->defaults = [NSMutableDictionary new];
}
d = [NSMutableDictionary new];
[this->defaults setObject: d forKey: elem];
[d release];
}
while (c != EOF && c != '>')
{
while (isspace(c))
@ -1091,6 +1117,13 @@ NSLog(@"type=%@ - %02x %c", type, c, isprint(c)?c: ' ');
c = cget();
}
/* Record default value (if any) for this attribute.
*/
if (nil != def)
{
[d setObject: def forKey: name];
}
if ([_del respondsToSelector: @selector(parser:foundAttributeDeclarationWithName:forElement:type:defaultValue:)])
{
[_del parser: self
@ -1223,6 +1256,7 @@ NSLog(@"_processTag <%@%@ %@>", flag?@"/": @"", tag, attributes);
NSString *uri;
NSString *qualified;
this->hasElement = YES;
while ((k = [enumerator nextObject]) != nil)
{
NSString *prefix = nil;
@ -1515,23 +1549,41 @@ NSLog(@"_processTag <%@%@ %@>", flag?@"/": @"", tag, attributes);
}
}
}
if (p - vp > 0 && this->foundCharacters != 0)
{
/* Process initial data as characters
*/
s = NewUTF8STR(vp, p - vp);
(*this->foundCharacters)(_del,
foundCharactersSel, self, s);
[s release];
}
if (p < this->cp - 1 && this->foundIgnorable != 0)
if (YES == this->hasElement)
{
/* Process data as ignorable whitespace
*/
s = NewUTF8STR(p, this->cp - p - 1);
(*this->foundIgnorable)(_del,
foundIgnorableSel, self, s);
[s release];
if (p - vp > 0)
{
if (this->foundCharacters != 0)
{
s = NewUTF8STR(vp, p - vp);
/* Process this data as characters
*/
(*this->foundCharacters)(_del,
foundCharactersSel, self, s);
[s release];
}
}
if (p < this->cp - 1)
{
if (this->foundIgnorable != 0)
{
s = NewUTF8STR(p, this->cp - p - 1);
/* Process data as ignorable whitespace
*/
(*this->foundIgnorable)(_del,
foundIgnorableSel, self, s);
[s release];
}
else if (this->foundCharacters != 0)
{
s = NewUTF8STR(p, this->cp - p - 1);
/* Process data as characters
*/
(*this->foundCharacters)(_del,
foundCharactersSel, self, s);
[s release];
}
}
}
vp = this->cp;
}
@ -1545,22 +1597,29 @@ NSLog(@"_processTag <%@%@ %@>", flag?@"/": @"", tag, attributes);
{
if (YES == this->ignorable && this->cp - vp > 1)
{
NSString *s;
/* We have accumulated ignorable whitespace ...
* push it out.
*/
if (this->foundIgnorable != 0)
{
NSString *s;
s = NewUTF8STR(vp, this->cp - vp - 1);
(*this->foundIgnorable)(_del,
foundIgnorableSel, self, s);
[s release];
}
else if (this->foundCharacters != 0)
{
s = NewUTF8STR(vp, this->cp - vp - 1);
(*this->foundCharacters)(_del,
foundCharactersSel, self, s);
[s release];
}
vp = this->cp - 1;
}
/* We have read non-space data, so whitespace is no longer
* ignorable, and the buffer no loinger contains only space.
* ignorable, and the buffer no longer contains only space.
*/
this->ignorable = NO;
this->whitespace = NO;
@ -1631,7 +1690,7 @@ NSLog(@"_processTag <%@%@ %@>", flag?@"/": @"", tag, attributes);
case '<':
{
NSString *tag;
NSMutableDictionary *parameters;
NSMutableDictionary *attributes;
NSString *arg;
const unsigned char *tp = this->cp; // tag pointer
const unsigned char *sp = tp - 1; // Open angle bracket
@ -1740,7 +1799,16 @@ NSLog(@"_processTag <%@%@ %@>", flag?@"/": @"", tag, attributes);
NSLog(@"tag=%@ - %02x %c", tag, c, isprint(c)?c: ' ');
#endif
parameters = [[NSMutableDictionary alloc] initWithCapacity: 5];
/* Create an attributes dictionary for this tag,
* using default values if available.
*/
attributes = [[this->defaults objectForKey: tag] mutableCopy];
if (nil == attributes)
{
attributes
= [[NSMutableDictionary alloc] initWithCapacity: 5];
}
while (isspace(c))
{
c = cget();
@ -1758,7 +1826,7 @@ NSLog(@"_processTag <%@%@ %@>", flag?@"/": @"", tag, attributes);
}
[self _processTag: tag
isEnd: NO
withAttributes: parameters];
withAttributes: attributes];
[self _processTag: tag isEnd: YES withAttributes: nil];
break;
}
@ -1784,7 +1852,7 @@ NSLog(@"_processTag <%@%@ %@>", flag?@"/": @"", tag, attributes);
}
[self _processTag: tag
isEnd: NO
withAttributes: parameters]; // single <?tag ...?>
withAttributes: attributes]; // single <?tag ...?>
break; // done
}
// this should also allow for line break and tab
@ -1796,7 +1864,7 @@ NSLog(@"_processTag <%@%@ %@>", flag?@"/": @"", tag, attributes);
{
[self _processTag: tag
isEnd: (*tp == '/')
withAttributes: parameters];
withAttributes: attributes];
break;
}
/* get next argument (eats up to /, ?, >, =, space)
@ -1826,17 +1894,17 @@ NSLog(@"_processTag <%@%@ %@>", flag?@"/": @"", tag, attributes);
c = cget();
}
val = [self _newQarg];
[parameters setObject: val forKey: arg];
[attributes setObject: val forKey: arg];
[val release];
c = cget(); // get character behind qarg value
}
else // implicit
{
[parameters setObject: @"" forKey: arg];
[attributes setObject: @"" forKey: arg];
}
[arg release];
}
[parameters release];
[attributes release];
[tag release];
vp = this->cp; // prepare for next value
c = cget(); // skip > and fetch next character