From f165e6f7c60bc88497360fcd8f29a08d766784e1 Mon Sep 17 00:00:00 2001 From: mccallum Date: Mon, 2 Sep 1996 13:16:35 +0000 Subject: [PATCH] New file. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@1660 72102866-910b-0410-8b05-ffd578937521 --- Headers/gnustep/base/NSScanner.h | 86 ++++ Source/NSScanner.m | 672 +++++++++++++++++++++++++++++++ config/config.retframe.c | 27 ++ 3 files changed, 785 insertions(+) create mode 100644 Headers/gnustep/base/NSScanner.h create mode 100644 Source/NSScanner.m create mode 100644 config/config.retframe.c diff --git a/Headers/gnustep/base/NSScanner.h b/Headers/gnustep/base/NSScanner.h new file mode 100644 index 000000000..110a33328 --- /dev/null +++ b/Headers/gnustep/base/NSScanner.h @@ -0,0 +1,86 @@ +/* Definitions for NSScanner class + Copyright (C) 1996 Free Software Foundation, Inc. + + Author: Eric Norum + Created: 1996 + + This file is part of the GNUstep Objective-C Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __NSScanner_h_GNUSTEP_INCLUDE +#define __NSScanner_h_GNUSTEP_INCLUDE + +#include +#include +#include + +// +// NSScanner class +// +@interface NSScanner : NSObject +{ +@private + NSString *string; + unsigned int len; + NSCharacterSet *charactersToBeSkipped; + NSDictionary *locale; + unsigned int scanLocation; + BOOL caseSensitive; +} + +/* + * Creating an NSScanner + */ ++ localizedScannerWithString:(NSString *)aString; ++ scannerWithString:(NSString *)aString; +- initWithString:(NSString *)aString; + +/* + * Getting an NSScanner's string + */ +- (NSString *)string; + +/* + * Configuring an NSScanner + */ +- (unsigned)scanLocation; +- (void)setScanLocation:(unsigned int)anIndex; +- (BOOL)caseSensitive; +- (void)setCaseSensitive:(BOOL)flag; +- (NSCharacterSet *)charactersToBeSkipped; +- (void)setCharactersToBeSkipped:(NSCharacterSet *)aSet; +- (NSDictionary *)locale; +- (void)setLocale:(NSDictionary *)localeDictionary; + +/* + * Scanning a string + */ +- (BOOL)scanInt:(int *)value; +- (BOOL)scanLongLong:(long long *)value; +- (BOOL)scanFloat:(float *)value; +- (BOOL)scanDouble:(double *)value; +- (BOOL)scanString:(NSString *)string intoString:(NSString **)value; +- (BOOL)scanCharactersFromSet:(NSCharacterSet *)aSet + intoString:(NSString **)value; +- (BOOL)scanUpToString:(NSString *)string intoString:(NSString **)value; +- (BOOL)scanUpToCharactersFromSet:(NSCharacterSet *)aSet + intoString:(NSString **)value; +- (BOOL)isAtEnd; + +@end + +#endif /* __NSScanner_h_GNUSTEP_INCLUDE */ diff --git a/Source/NSScanner.m b/Source/NSScanner.m new file mode 100644 index 000000000..6a3a74d20 --- /dev/null +++ b/Source/NSScanner.m @@ -0,0 +1,672 @@ +/* Implemenation of NSScanner class + Copyright (C) 1996 Free Software Foundation, Inc. + + Author: Eric Norum + Date: 1996 + + This file is part of the GNUstep Objective-C Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include +#include +#include /* FIXME: May go away once I figure out Unicode */ + +/* + * Cache the default NSCharacterSet of characters to be skipped. + * FIXME: This would be unecessary if NSCharacterSet did the caching. + */ +static NSCharacterSet *defaultCharactersToBeSkipped; + +@implementation NSScanner + +/* + * Class initialization. + * Fill in default NSCharacterSet of characters to be skipped. + */ ++ (void)initialize +{ + if (defaultCharactersToBeSkipped == nil) + defaultCharactersToBeSkipped = + [[NSCharacterSet whitespaceAndNewlineCharacterSet] retain]; +} + +/* + * Create and return a scanner that scans aString. + */ ++ scannerWithString:(NSString *)aString +{ + return [[[self alloc] initWithString: aString] + autorelease]; +} + ++ localizedScannerWithString: (NSString*)locale +{ + [self notImplemented: _cmd]; + return Nil; +} + +/* + * Initialize a a newly-allocated scanner to scan aString. + * Returns self. + */ +- initWithString:(NSString *)aString +{ + [super init]; + string = [aString copyWithZone: [self zone]]; + len = [string length]; + charactersToBeSkipped = defaultCharactersToBeSkipped; + return self; +} + +/* + * Deallocate a scanner and all its associated storage. + */ +- (void)dealloc +{ + [string release]; + [locale release]; + if (charactersToBeSkipped != defaultCharactersToBeSkipped) + [charactersToBeSkipped release]; + [super dealloc]; +} + +/* + * Like scanCharactersFromSet:intoString: but no initial skip + * For internal use only. + */ +- (BOOL)_scanCharactersFromSet: (NSCharacterSet *)set + intoString: (NSString **)value; +{ + unsigned int start; + + if (scanLocation >= len) + return NO; + start = scanLocation; + while (scanLocation < len) + { + if (![set characterIsMember: [string characterAtIndex:scanLocation]]) + break; + scanLocation++; + } + if (scanLocation == start) + return NO; + if (value) + { + NSRange range; + range.location = start; + range.length = scanLocation - start; + *value = [string substringFromRange: range]; + } + return YES; +} + +/* + * Scan characters to be skipped. + * Return YES if there are more characters to be scanned. + * Return NO if the end of the string is reached. + * For internal use only. + */ +- (BOOL) _skipToNextField +{ + [self _scanCharactersFromSet: charactersToBeSkipped intoString: NULL]; + if (scanLocation >= len) + return NO; + return YES; +} + +/* + * Returns YES if no more characters remain to be scanned. + * Returns YES if all characters remaining to be scanned are to be skipped. + * Returns NO if there are characters left to scan. + */ +- (BOOL) isAtEnd +{ + unsigned int save_scanLocation; + BOOL ret; + + if (scanLocation >= len) + return YES; + save_scanLocation = scanLocation; + ret = ![self _skipToNextField]; + scanLocation = save_scanLocation; + return ret; +} + +/* + * Internal version of scanInt: method. + * Does the actual work for scanInt: except for the initial skip. + * For internal use only. This method may move the scan location + * even if a valid integer is not scanned. + * Based on the strtol code from the GNU C library. A little simpler since + * we deal only with base 10. + * FIXME: I don't use the decimalDigitCharacterSet here since it + * includes many more characters than the ASCII digits. I don't + * know how to convert those other characters, so I ignore them + * for now. For the same reason, I don't try to support all the + * possible Unicode plus and minus characters. + */ +- (BOOL) _scanInt: (int*)value +{ + unsigned int num = 0; + const unsigned int limit = UINT_MAX / 10; + BOOL negative = NO; + BOOL overflow = NO; + BOOL got_digits = NO; + + /* Check for sign */ + switch ([string characterAtIndex:scanLocation]) + { + case '+': + scanLocation++; + break; + case '-': + negative = YES; + scanLocation++; + break; + } + + /* Process digits */ + while (scanLocation < len) + { + unichar digit = [string characterAtIndex: scanLocation]; + if ((digit < '0') || (digit > '9')) + break; + if (!overflow) { + if (num >= limit) + overflow = YES; + else + num = num * 10 + (digit - '0'); + } + scanLocation++; + got_digits = YES; + } + + /* Save result */ + if (!got_digits) + return NO; + if (value) + { + if (num > (negative ? -(unsigned int)INT_MIN : (unsigned int)INT_MAX)) + overflow = YES; + if (overflow) + num = negative ? INT_MIN: INT_MAX; + if (negative) + *value = -num; + else + *value = num; + } + return YES; +} + +/* + * Scan an int into value. + */ +- (BOOL) scanInt: (int*)value +{ + unsigned int saveScanLocation = scanLocation; + + if ([self _skipToNextField] && [self _scanInt: value]) + return YES; + scanLocation = saveScanLocation; + return NO; +} + +/* + * Scan a long long int into value. + * Same as scanInt, except with different variable types and limits. + */ +- (BOOL)scanLongLong: (long long *)value +{ +#if defined(LONG_LONG_MAX) + unsigned long long num = 0; + const unsigned long long limit = ULONG_LONG_MAX / 10; + BOOL negative = NO; + BOOL overflow = NO; + BOOL got_digits = NO; + unsigned int saveScanLocation = scanLocation; + + /* Skip whitespace */ + if (![self _skipToNextField]) + { + scanLocation = saveScanLocation; + return NO; + } + + /* Check for sign */ + switch ([string characterAtIndex:scanLocation]) + { + case '+': + scanLocation++; + break; + case '-': + negative = YES; + scanLocation++; + break; + } + + /* Process digits */ + while (scanLocation < len) + { + unichar digit = [string characterAtIndex:scanLocation]; + if ((digit < '0') || (digit > '9')) + break; + if (!overflow) { + if (num >= limit) + overflow = YES; + else + num = num * 10 + (digit - '0'); + } + scanLocation++; + got_digits = YES; + } + + /* Save result */ + if (!got_digits) + { + scanLocation = saveScanLocation; + return NO; + } + if (value) + { + if (num > (unsigned long long)LONG_LONG_MAX) + /* xxx When would this ever be true? Isn't is impossible? mccallum. */ + overflow = YES; + if (overflow) + num = negative ? LONG_LONG_MIN: LONG_LONG_MAX; + if (negative) + *value = -num; + else + *value = num; + } + return YES; +#else /* defined(LONG_LONG_MAX) */ + /* + * Provide compile-time warning and run-time exception. + */ +# warning "Can't use long long variables." + [NSException raise: NSGenericException + format:@"Can't use long long variables."]; + return NO; +#endif /* defined(LONG_LONG_MAX) */ +} + +/* + * Scan a double into value. + * Returns YES if a valid floating-point expression was scanned. + * Returns NO otherwise. + * On overflow, HUGE_VAL or -HUGE_VAL is put into value and YES is returned. + * On underflow, 0.0 is put into value and YES is returned. + * Based on the strtod code from the GNU C library. + */ +- (BOOL)scanDouble:(double *)value +{ + unichar decimal; + unichar c = 0; + double num = 0.0; + long int exponent = 0; + BOOL negative = NO; + BOOL got_dot = NO; + BOOL got_digit = NO; + unsigned int saveScanLocation = scanLocation; + + /* Skip whitespace */ + if (![self _skipToNextField]) + { + scanLocation = saveScanLocation; + return NO; + } + + /* + * FIXME: Should get decimal point character from locale. The problem + * is that I can't find anything in the OPENSTEP specification about + * the format of the locale dictionary. + */ + decimal = '.'; + + /* Check for sign */ + switch ([string characterAtIndex:scanLocation]) + { + case '+': + scanLocation++; + break; + case '-': + negative = YES; + scanLocation++; + break; + } + + /* Process number */ + while (scanLocation < len) + { + c = [string characterAtIndex: scanLocation]; + if ((c >= '0') && (c <= '9')) + { + /* Ensure that the number being accumulated will not overflow. */ + if (num >= (DBL_MAX / 10.000000001)) + { + ++exponent; + } + else + { + num = (num * 10.0) + (c - '0'); + got_digit = YES; + } + /* Keep track of the number of digits after the decimal point. + If we just divided by 10 here, we would lose precision. */ + if (got_dot) + --exponent; + } + else if (!got_dot && (c == decimal)) + { + /* Note that we have found the decimal point. */ + got_dot = YES; + } + else + { + /* Any other character terminates the number. */ + break; + } + scanLocation++; + } + if (!got_digit) + { + scanLocation = saveScanLocation; + return NO; + } + + /* Check for trailing exponent + Numbers like 1.23eFOO are rejected. */ + if ((scanLocation < len) && ((c == 'e') || (c == 'E'))) + { + int exp; + scanLocation++; + if (![self _scanInt: &exp]) + { + scanLocation = saveScanLocation; + return NO; + } + + /* Check for exponent overflow */ + if (num) + { + if ((exponent > 0) && (exp > (LONG_MAX - exponent))) + exponent = LONG_MAX; + else if ((exponent < 0) && (exp < (LONG_MIN - exponent))) + exponent = LONG_MIN; + else + exponent += exp; + } + } + if (value) + { + if (num && exponent) + num *= pow(10.0, (double) exponent); + if (negative) + *value = -num; + else + *value = num; + } + return YES; +} + +/* + * Scan a float into value. + * Returns YES if a valid floating-point expression was scanned. + * Returns NO otherwise. + * On overflow, HUGE_VAL or -HUGE_VAL is put into value and YES is returned. + * On underflow, 0.0 is put into value and YES is returned. + */ +- (BOOL)scanFloat: (float*)value +{ + double num; + + if (value == NULL) + return [self scanDouble:NULL]; + if ([self scanDouble:&num]) + { + *value = num; + return YES; + } + return NO; +} + +/* + * Scan as long as characters from aSet are encountered. + * Returns YES if any characters were scanned. + * Returns NO if no characters were scanned. + * If value is non-NULL, and any characters were scanned, a string + * containing the scanned characters is returned by reference in value. + */ +- (BOOL)scanCharactersFromSet:(NSCharacterSet *)aSet + intoString:(NSString **)value; +{ + unsigned int saveScanLocation = scanLocation; + + if ([self _skipToNextField] + && [self _scanCharactersFromSet: aSet intoString: value]) + return YES; + scanLocation = saveScanLocation; + return NO; +} + +/* + * Scan until a character from aSet is encountered. + * Returns YES if any characters were scanned. + * Returns NO if no characters were scanned. + * If value is non-NULL, and any characters were scanned, a string + * containing the scanned characters is returned by reference in value. + */ +- (BOOL)scanUpToCharactersFromSet:(NSCharacterSet *)set + intoString:(NSString **)value; +{ + unsigned int saveScanLocation = scanLocation; + unsigned int start; + + if (![self _skipToNextField]) + return NO; + start = scanLocation; + while (scanLocation < len) + { + if ([set characterIsMember:[string characterAtIndex: scanLocation]]) + break; + scanLocation++; + } + if (scanLocation == start) + { + scanLocation = saveScanLocation; + return NO; + } + if (value) + { + NSRange range; + range.location = start; + range.length = scanLocation - start; + *value = [string substringFromRange: range]; + } + return YES; +} + +/* + * Scans for aString. + * Returns YES if the characters at the scan location match aString. + * Returns NO if the characters at the scan location do not match aString. + * If the characters at the scan location match aString. + * If value is non-NULL, and the characters at the scan location match aString, + * a string containing the matching string is returned by reference in value. + */ +- (BOOL)scanString:(NSString *)aString intoString:(NSString **)value; +{ + NSRange range; + unsigned int saveScanLocation = scanLocation; + + [self _skipToNextField]; + range.location = scanLocation; + range.length = [aString length]; + range = [string rangeOfString:aString + options:caseSensitive ? 0 : NSCaseInsensitiveSearch + range:range]; + if (range.length == 0) + { + scanLocation = saveScanLocation; + return NO; + } + if (value) + *value = [string substringFromRange:range]; + scanLocation += range.length; + return YES; +} + +/* + * Scans the string until aString is encountered.. + * Returns YES if any characters were scanned. + * Returns NO if no characters were scanned. + * If value is non-NULL, and any characters were scanned, a string + * containing the scanned characters is returned by reference in value. + */ +- (BOOL)scanUpToString:(NSString *)aString + intoString:(NSString **)value; +{ + NSRange range; + NSRange found; + unsigned int saveScanLocation = scanLocation; + + [self _skipToNextField]; + range.location = scanLocation; + range.length = len - scanLocation; + found = [string rangeOfString:aString + options:caseSensitive ? 0 : NSCaseInsensitiveSearch + range:range]; + if (found.length) + range.length = found.location - scanLocation; + if (range.length == 0) + { + scanLocation = saveScanLocation; + return NO; + } + if (value) + *value = [string substringFromRange:range]; + scanLocation += range.length; + return YES; +} + +/* + * Returns the string being scanned. + */ +- (NSString *)string +{ + return string; +} + +/* + * Returns the character index at which the scanner + * will begin the next scanning operation. + */ +- (unsigned)scanLocation +{ + return scanLocation; +} + +/* + * Set the character location at which the scanner + * will begin the next scanning operation to anIndex. + */ +- (void)setScanLocation:(unsigned int)anIndex +{ + scanLocation = anIndex; +} + +/* + * Returns YES if the scanner makes a distinction + * between upper and lower case characters. + */ +- (BOOL)caseSensitive +{ + return caseSensitive; +} + +/* + * If flag is YES the scanner will consider upper and lower case + * to be the same during scanning. If flag is NO the scanner will + * not make a distinction between upper and lower case characters. + */ +- (void)setCaseSensitive:(BOOL)flag +{ + caseSensitive = flag; +} + +/* + * Return a character set object containing the characters the scanner + * will ignore when searching for the next element to be scanned. + */ +- (NSCharacterSet *)charactersToBeSkipped +{ + return charactersToBeSkipped; +} + +/* + * Set the characters to be ignored when the scanner + * searches for the next element to be scanned. + */ +- (void)setCharactersToBeSkipped:(NSCharacterSet *)aSet +{ + if (charactersToBeSkipped != defaultCharactersToBeSkipped) + [charactersToBeSkipped release]; + charactersToBeSkipped = [aSet copyWithZone: [self zone]]; +} + +/* + * Returns a dictionary object containing the locale + * information used by the scanner. + */ +- (NSDictionary *)locale +{ + return locale; +} + +/* + * Set the dictionary containing the locale + * information used by the scanner to localeDictionary. + */ +- (void)setLocale:(NSDictionary *)localeDictionary +{ + locale = [localeDictionary retain]; +} + +/* + * NSCopying protocol + */ +- copyWithZone:(NSZone *)zone +{ + NSScanner *n = [[self class] allocWithZone:zone]; + + [n initWithString: string]; + [n setCharactersToBeSkipped: charactersToBeSkipped]; + [n setLocale: locale]; + [n setScanLocation: scanLocation]; + [n setCaseSensitive: caseSensitive]; + return n; +} + +- copy +{ + return [self copyWithZone: [self zone]]; +} + +@end diff --git a/config/config.retframe.c b/config/config.retframe.c new file mode 100644 index 000000000..c8322d74f --- /dev/null +++ b/config/config.retframe.c @@ -0,0 +1,27 @@ +/* Find out if __builtin_apply()'s retframe points directly at `char' + and `short' return values, or if it points at an `int'-casted + version of them. */ + +/* This program exit's with status 0 if it retframe points directly at + them. */ + +char +foo () +{ + return 0x1; +} + +char +bar () +{ + void *retframe; + void *argframe; + argframe = __ + retframe = __builtin_apply (foo, argframe, 96); + __builtin_return (retframe); +} + +main () +{ + /* xxx Not finished... */ +}