diff --git a/ChangeLog b/ChangeLog index 8b9fe9850..523b1c879 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2001-04-28 Richard Frith-Macdonald + + * Source/NSLog.m: Use RETAIN/RELEASE + * Source/GSLocale.m: Set up NSDecimalSeparator and NSThousandsSeparator + from locale if possible. Fix bug dereferencing nil pointer. + * Source/GSFormat.m: Hack to rewrite output from sprintf of floats and + doubles to use the value in NSDecimalSeparator. + 2001-04-27 Nicola Pero * Source/NSString.m: Minor optimization for parsing property diff --git a/Source/GSFormat.m b/Source/GSFormat.m index 58aecb879..06c26ce16 100644 --- a/Source/GSFormat.m +++ b/Source/GSFormat.m @@ -61,6 +61,7 @@ #include #include #include +#include #include #include // for strstr() #include @@ -1368,116 +1369,240 @@ NSDictionary *locale) LABEL (form_float): { /* Floating-point number. This is handled by the native sprintf. */ - char buf1[32], *bp, buf2[specs[nspecs_done].info.width+specs[nspecs_done].info.prec+32]; - unichar work_buffer[MAX (specs[nspecs_done].info.width, specs[nspecs_done].info.spec) + 32]; - unichar *const workend - = &work_buffer[sizeof (work_buffer) / sizeof (unichar)]; - register unichar *w; + char buf1[32], *bp; + char buf2[specs[nspecs_done].info.width + +specs[nspecs_done].info.prec+32]; + unichar work_buffer[MAX (specs[nspecs_done].info.width, + specs[nspecs_done].info.spec) + 32]; + unichar *const workend + = &work_buffer[sizeof (work_buffer) / sizeof (unichar)]; + register unichar *w; + NSString *decimal_sep; - bp = buf1; + decimal_sep = [locale objectForKey: NSDecimalSeparator]; - *bp++ = '%'; + bp = buf1; - if (specs[nspecs_done].info.alt) - *bp++ = '#'; - if (specs[nspecs_done].info.group) - *bp++ = '\''; - if (specs[nspecs_done].info.showsign) - *bp++ = '+'; - else if (specs[nspecs_done].info.space) - *bp++ = ' '; - if (specs[nspecs_done].info.left) - *bp++ = '-'; - if (specs[nspecs_done].info.pad == '0') - *bp++ = '0'; - if (specs[nspecs_done].info.i18n) - *bp++ = 'I'; + *bp++ = '%'; - if (specs[nspecs_done].info.width != 0) - { - w = _itowa_word (specs[nspecs_done].info.width, workend, 10, 0); - while (w < workend) - *bp++ = *w++; - } + if (specs[nspecs_done].info.alt) + *bp++ = '#'; + if (specs[nspecs_done].info.group) + *bp++ = '\''; + if (specs[nspecs_done].info.showsign) + *bp++ = '+'; + else if (specs[nspecs_done].info.space) + *bp++ = ' '; + if (specs[nspecs_done].info.left) + *bp++ = '-'; + if (specs[nspecs_done].info.pad == '0') + *bp++ = '0'; + if (specs[nspecs_done].info.i18n) + *bp++ = 'I'; - if (specs[nspecs_done].info.prec != -1) - { - *bp++ = '.'; - w = _itowa_word (specs[nspecs_done].info.prec, workend, 10, 0); - while (w < workend) - *bp++ = *w++; - } + if (specs[nspecs_done].info.width != 0) + { + w = _itowa_word (specs[nspecs_done].info.width, workend, 10, 0); + while (w < workend) + *bp++ = *w++; + } - if (specs[nspecs_done].info.spec != '\0') - *bp++ = specs[nspecs_done].info.spec; + if (specs[nspecs_done].info.prec != -1) + { + *bp++ = '.'; + w = _itowa_word (specs[nspecs_done].info.prec, workend, 10, 0); + while (w < workend) + *bp++ = *w++; + } - *bp++ = '\0'; + if (specs[nspecs_done].info.spec != '\0') + *bp++ = specs[nspecs_done].info.spec; - if (specs[nspecs_done].info.is_long_double) - sprintf(buf2, buf1, args_value[specs[nspecs_done].data_arg].pa_long_double); - else - sprintf(buf2, buf1, args_value[specs[nspecs_done].data_arg].pa_double); + *bp++ = '\0'; - bp = buf2; - while (*bp) outchar(*bp++); + if (specs[nspecs_done].info.is_long_double) + { + sprintf(buf2, buf1, + args_value[specs[nspecs_done].data_arg].pa_long_double); + } + else + { + sprintf(buf2, buf1, + args_value[specs[nspecs_done].data_arg].pa_double); + } + + /* + * FIXME - hack to rewrite decimal separator into correct locale + * if necessary. + */ + if (decimal_sep != nil) + { + NSDictionary *def = GSDomainFromDefaultLocale(); + NSString *sep = [def objectForKey: NSDecimalSeparator]; + + if (sep == nil) + sep = @"."; + if ([decimal_sep isEqual: sep] == NO && [sep length] == 1) + { + unichar m = [sep characterAtIndex: 0]; + char *p = &buf2[strlen(buf2)]; + + /* + * Assume that we won't be finding an escape in the string + * so we can use it as a marker. + */ + while (p-- > buf2) + { + if (*p == m) + { + *p = '\033'; + break; + } + } + } + } + + bp = buf2; + while (*bp) + { + if (*bp == '\033') + { + int i = 0; + int c = [decimal_sep length]; + unichar b[c]; + + [decimal_sep getCharacters: b]; + while (i < c) + { + outchar(b[i++]); + } + bp++; + } + else + { + outchar(*bp++); + } + } } break; LABEL (form_floathex): { - /* Floating point number printed as hexadecimal number. */ - char buf1[32], *bp, buf2[specs[nspecs_done].info.width+specs[nspecs_done].info.prec+32]; - unichar work_buffer[MAX (specs[nspecs_done].info.width, specs[nspecs_done].info.spec) + 32]; - unichar *const workend - = &work_buffer[sizeof (work_buffer) / sizeof (unichar)]; - register unichar *w; + /* Floating point number printed as hexadecimal number. */ + char buf1[32], *bp; + char buf2[specs[nspecs_done].info.width + +specs[nspecs_done].info.prec+32]; + unichar work_buffer[MAX (specs[nspecs_done].info.width, + specs[nspecs_done].info.spec) + 32]; + unichar *const workend + = &work_buffer[sizeof (work_buffer) / sizeof (unichar)]; + register unichar *w; + NSString *decimal_sep; - bp = buf1; + decimal_sep = [locale objectForKey: NSDecimalSeparator]; - *bp++ = '%'; + bp = buf1; - if (specs[nspecs_done].info.alt) - *bp++ = '#'; - if (specs[nspecs_done].info.group) - *bp++ = '\''; - if (specs[nspecs_done].info.showsign) - *bp++ = '+'; - else if (specs[nspecs_done].info.space) - *bp++ = ' '; - if (specs[nspecs_done].info.left) - *bp++ = '-'; - if (specs[nspecs_done].info.pad == '0') - *bp++ = '0'; - if (specs[nspecs_done].info.i18n) - *bp++ = 'I'; + *bp++ = '%'; - if (specs[nspecs_done].info.width != 0) - { - w = _itowa_word (specs[nspecs_done].info.width, workend, 10, 0); - while (w < workend) - *bp++ = *w++; - } + if (specs[nspecs_done].info.alt) + *bp++ = '#'; + if (specs[nspecs_done].info.group) + *bp++ = '\''; + if (specs[nspecs_done].info.showsign) + *bp++ = '+'; + else if (specs[nspecs_done].info.space) + *bp++ = ' '; + if (specs[nspecs_done].info.left) + *bp++ = '-'; + if (specs[nspecs_done].info.pad == '0') + *bp++ = '0'; + if (specs[nspecs_done].info.i18n) + *bp++ = 'I'; - if (specs[nspecs_done].info.prec != -1) - { - *bp++ = '.'; - w = _itowa_word (specs[nspecs_done].info.prec, workend, 10, 0); - while (w < workend) - *bp++ = *w++; - } + if (specs[nspecs_done].info.width != 0) + { + w = _itowa_word (specs[nspecs_done].info.width, workend, 10, 0); + while (w < workend) + *bp++ = *w++; + } - if (specs[nspecs_done].info.spec != '\0') - *bp++ = specs[nspecs_done].info.spec; + if (specs[nspecs_done].info.prec != -1) + { + *bp++ = '.'; + w = _itowa_word (specs[nspecs_done].info.prec, workend, 10, 0); + while (w < workend) + *bp++ = *w++; + } - *bp++ = '\0'; + if (specs[nspecs_done].info.spec != '\0') + *bp++ = specs[nspecs_done].info.spec; - if (specs[nspecs_done].info.is_long_double) - sprintf(buf2, buf1, args_value[specs[nspecs_done].data_arg].pa_long_double); - else - sprintf(buf2, buf1, args_value[specs[nspecs_done].data_arg].pa_double); + *bp++ = '\0'; - bp = buf2; - while (*bp) outchar(*bp++); + if (specs[nspecs_done].info.is_long_double) + { + sprintf(buf2, buf1, + args_value[specs[nspecs_done].data_arg].pa_long_double); + } + else + { + sprintf(buf2, buf1, + args_value[specs[nspecs_done].data_arg].pa_double); + } + + /* + * FIXME - hack to rewrite decimal separator into correct locale + * if necessary. + */ + if (decimal_sep != nil) + { + NSDictionary *def = GSDomainFromDefaultLocale(); + NSString *sep = [def objectForKey: NSDecimalSeparator]; + + if (sep == nil) + sep = @"."; + if ([decimal_sep isEqual: sep] == NO && [sep length] == 1) + { + unichar m = [sep characterAtIndex: 0]; + char *p = &buf2[strlen(buf2)]; + + /* + * Assume that we won't be finding an escape in the string + * so we can use it as a marker. + */ + while (p-- > buf2) + { + if (*p == m) + { + *p = '\033'; + break; + } + } + } + } + + bp = buf2; + while (*bp) + { + if (*bp == '\033') + { + int i = 0; + int c = [decimal_sep length]; + unichar b[c]; + + [decimal_sep getCharacters: b]; + while (i < c) + { + outchar(b[i++]); + } + bp++; + } + else + { + outchar(*bp++); + } + } } break; diff --git a/Source/GSLocale.m b/Source/GSLocale.m index c6fbcd0da..c0775f4b6 100644 --- a/Source/GSLocale.m +++ b/Source/GSLocale.m @@ -25,6 +25,7 @@ #include #include #include +#include #ifdef HAVE_LOCALE_H @@ -50,7 +51,7 @@ GSSetLocaleC(const char *loc) /* Set the locale for libc functions from the supplied string or from the environment if not specified. This function should be called as soon as possible after the start of the program. Passing - @"" will set the locale from the environment varialbes LC_ALL or LANG (or + @"" will set the locale from the environment variables LC_ALL or LANG (or whatever is specified by setlocale) Passing nil will just return the current locale. */ NSString * @@ -88,6 +89,7 @@ NSDictionary * GSDomainFromDefaultLocale(void) { #ifdef HAVE_LANGINFO_H + static NSDictionary *saved = nil; int i; struct lconv *lconv; NSMutableDictionary *dict; @@ -95,6 +97,9 @@ GSDomainFromDefaultLocale(void) NSString *str1; NSString *str2; + if (saved != nil) + return saved; + dict = [NSMutableDictionary dictionary]; /* Time/Date Information */ @@ -164,17 +169,36 @@ GSDomainFromDefaultLocale(void) [dict setObject: [NSString stringWithCString: lconv->mon_thousands_sep] forKey: NSInternationalCurrencyString]; } + + if (lconv->decimal_point) + { + [dict setObject: [NSString stringWithCString: lconv->decimal_point] + forKey: NSDecimalSeparator]; + } + if (lconv->thousands_sep) + { + [dict setObject: [NSString stringWithCString: lconv->thousands_sep] + forKey: NSThousandsSeparator]; + } + + /* FIXME: Get currency format from localeconv */ str1 = GSSetLocale(nil); - [dict setObject: str1 forKey: NSLocale]; + if (str1 != nil) + { + [dict setObject: str1 forKey: NSLocale]; + } str2 = GSLanguageFromLocale(str1); - if (str2) + if (str2 != nil) { [dict setObject: str2 forKey: NSLanguageName]; } - return dict; + [gnustep_global_lock lock]; + saved = [dict mutableCopy]; + [gnustep_global_lock unlock]; + return saved; #else /* HAVE_LANGINFO_H */ return nil; #endif diff --git a/Source/NSLog.m b/Source/NSLog.m index 5d9c621c2..f967639ab 100644 --- a/Source/NSLog.m +++ b/Source/NSLog.m @@ -89,13 +89,11 @@ void NSLogv (NSString* format, va_list args) { static NSRecursiveLock *myLock = nil; - NSAutoreleasePool *arp; + CREATE_AUTORELEASE_POOL(arp); NSString *prefix; NSString *message; int pid; - arp = [NSAutoreleasePool new]; - if (_NSLog_printf_handler == NULL) _NSLog_printf_handler = *_NSLog_standard_printf_handler; @@ -134,6 +132,6 @@ NSLogv (NSString* format, va_list args) [myLock unlock]; - [arp release]; + RELEASE(arp); }