Changes by Adam Fedor. See Nov 13 ChangeLog entry

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@2018 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
mccallum 1997-01-06 22:30:33 +00:00
parent f25cb10514
commit 5b8ea53689
6 changed files with 653 additions and 393 deletions

View file

@ -1,3 +1,84 @@
Mon Jan 6 16:06:21 1997 Andrew McCallum <mccallum@cs.cmu.edu>
* src/NSString.m ([NSString -description]): Free DEST to prevent
memory leak!
(Reported by Wolfgang Baron <wbaron@ixpoint.de>.)
* src/NSException.m (_NSUncaughtExceptionHandler): Don't declare
it static. (Reported by John Hethcox <johnhe@vnet.net>.)
* src/BinaryCStream.m (BITSPERBYTE): If it hasn't been defined
after #include's guess that it's 8.
* checks/nsscanner.m: Removed RCS keyword.
Wed Nov 13 14:10:00 1996 Richard Frith-Macdonald <richard@brainstorm.co.uk>
* src/Connection.m ([Connection +rootProxyAtName:onHost:]):
Return nil if we fail to create a port for talking to a remote server.
([Connection forwardForProxy:selector:argFrame:]):
Changes to ensure that ConnectedDecoder is correctly dismissed in the
case where a DO method returns an object but does not have any
parameter values returned.
* src/mframe.m (mframe_build_return()):
Cooperate with [Connection forwardForProxy:selector:argFrame:] so
that it's callback function is called to tell it dismiss the
ConnectedDecoder.
* src/RunLoop.m ([RunLoop -limitDateForMode:]):
Various changes to get timeouts working reliably.
Ensure that _current_mode is restored correctly on exit.
* src/RunLoop.m ([RunLoop -acceptInputForMode:beforeDate:]):
Ensure that _current_mode is restored correctly on exit.
Wed Nov 6 11:59:08 1996 Adam Fedor <fedor@boulder.Colorado.edu>
* src/NSLog.m: New file
* src/Makefile.in (GNUSTEP_MFILES): Add NSLog.m
* src/include/NSObjCRuntime.h: Add NSLog definitions.
Mon Nov 4 12:30:05 1996 Adam Fedor <fedor@wave.Colorado.edu>
* src/objc-load.c: Include <gnustep/base/config.h>.
Sat Sep 21 15:18:47 1996 Yoo C. Chung <wacko@power1.snu.ac.kr>
* src/NSZone.m: Use constructor attribute with initialize().
Thu Sep 19 22:09:08 1996 Yoo C. Chung <wacko@power1.snu.ac.kr>
* src/DelegatePool.m:
Use NSDefaultMallocZone() instead of NS_NOZONE.
* src/NSProcessInfo.m: Likewise.
* src/NSObject.m:
Use NSDefaultMallocZone() instead of NS_NOZONE.
Use NSZoneFromPointer() instead of NSZoneFromPtr().
* src/NSProcessInfo.m: Use NSDefaultMallocZone() instead of 0.
And cosmetic changes.
* src/NSHashTable.m: Use NSDefaultMallocZone() instead of 0.
* src/NSMapTable.m: Likewise.
* src/o_map.m: Likewise.
* src/NSPage.m:
Use valloc() in NSAllocateMemoryPages().
Cosmetic style changes.
* src/NSZone.m: Complete rewrite.
* src/include/NSZone.h: Extensive modifications.
Thu Dec 5 17:20:58 1996 Nick Christopher <nwc@mindspring.com>
* NSString.m [NSString -componentsSeparatedByString]: Didn't
handle strings with separators longer than a single character
and in other cases.
* stringsfile.l: The definition of LABEL needed expanding.
Sun Jan 5 17:41:37 1997 Andrew McCallum <mccallum@cs.cmu.edu> Sun Jan 5 17:41:37 1997 Andrew McCallum <mccallum@cs.cmu.edu>
Further changes for the NSString implementation. Further changes for the NSString implementation.

View file

@ -28,42 +28,54 @@
@class NSString; @class NSString;
@class NSArray; @class NSArray;
@class NSDictionary;
extern NSString* NSBundleDidLoadNotification;
extern NSString* NSShowNonLocalizedStrings;
extern NSString* NSLoadedClasses;
@interface NSBundle : NSObject @interface NSBundle : NSObject
{ {
NSString *_path; NSString *_path;
Class _principalClass; NSArray* _bundleClasses;
Class _principalClass;
id _infoDict;
unsigned int _retainCount;
unsigned int _bundleType;
BOOL _codeLoaded; BOOL _codeLoaded;
int _bundleVersion;
} }
+ (NSBundle *)mainBundle; + (NSBundle *) mainBundle;
+ (NSBundle *)bundleForClass:aClass; + (NSBundle *) bundleForClass: (Class)aClass;
+ (NSBundle *)bundleWithPath:(NSString *)path; + (NSBundle *) bundleWithPath: (NSString *)path;
- initWithPath:(NSString *)path; - initWithPath: (NSString *)path;
- (NSString *)bundlePath; - (NSString *) bundlePath;
- classNamed:(NSString *)className; - (Class) classNamed: (NSString *)className;
- principalClass; - (Class) principalClass;
+ (NSString *)pathForResource:(NSString *)name - (NSArray *) pathsForResourcesOfType: (NSString *)extension
ofType:(NSString *)ext inDirectory: (NSString *)bundlePath;
inDirectory:(NSString *)bundlePath - (NSString *) pathForResource: (NSString *)name
withVersion:(int)version; ofType: (NSString *)ext
inDirectory: (NSString *)bundlePath;
- (NSString *) pathForResource: (NSString *)name
ofType: (NSString *)ext;
- (NSString *) localizedStringForKey: (NSString *)key
value: (NSString *)value
table: (NSString *)tableName;
- (NSString *) resourcePath;
- (NSString *)pathForResource:(NSString *)name #ifndef STRICT_OPENSTEP
ofType:(NSString *)ext; - (NSDictionary *) infoDictionary;
#endif
+ (void)stripAfterLoading:(BOOL)flag;
- (NSString *)localizedStringForKey:(NSString *)key
value:(NSString *)value
table:(NSString *)tableName;
- (unsigned)bundleVersion;
- (void)setBundleVersion:(unsigned)version;
+ (void)setSystemLanguages:(NSArray *)languages;
@end @end
#define NSLocalizedString(key, comment) \
[[NSBundle mainBundle] localizedStringForKey:(key) value:@"" table:nil]
#define NSLocalizedStringFromTable(key, tbl, comment) \
[[NSBundle mainBundle] localizedStringForKey:(key) value:@"" table:(tbl)]
#define NSLocalizedStringFromTableInBundle(key, tbl, bundle, comment) \
[bundle localizedStringForKey:(key) value:@"" table:(tbl)]
#endif /* __NSBundle_h_GNUSTEP_BASE_INCLUDE */ #endif /* __NSBundle_h_GNUSTEP_BASE_INCLUDE */

View file

@ -51,7 +51,7 @@ YACC = bison
# GNUSTEP_INSTALL_PREFIX must be defined here and not in config.h because # GNUSTEP_INSTALL_PREFIX must be defined here and not in config.h because
# the installing person may set it on the `make' command line. # the installing person may set it on the `make' command line.
DEFS = -DGNUSTEP_INSTALL_PREFIX=$(prefix) @DEFS@ DEFS= -DGNUSTEP_INSTALL_PREFIX=$(prefix) -DPLATFORM_OS=\"@PLATFORM_OS@\" @DEFS@
# File name extensions # File name extensions
OEXT = .o OEXT = .o

View file

@ -37,7 +37,13 @@
#include <Foundation/NSException.h> #include <Foundation/NSException.h>
#include <Foundation/NSString.h> #include <Foundation/NSString.h>
#include <Foundation/NSArray.h> #include <Foundation/NSArray.h>
#include <Foundation/NSDictionary.h>
#include <Foundation/NSProcessInfo.h> #include <Foundation/NSProcessInfo.h>
#include <Foundation/NSObjCRuntime.h>
#include <Foundation/NSUserDefaults.h>
#include <Foundation/NSNotification.h>
#include <Foundation/NSLock.h>
#include <Foundation/NSMapTable.h>
/* Deal with strchr: */ /* Deal with strchr: */
#if STDC_HEADERS || HAVE_STRING_H #if STDC_HEADERS || HAVE_STRING_H
@ -56,39 +62,56 @@
/* memory.h and strings.h conflict on some systems. */ /* memory.h and strings.h conflict on some systems. */
#endif /* not STDC_HEADERS and not HAVE_STRING_H */ #endif /* not STDC_HEADERS and not HAVE_STRING_H */
#ifndef FREE_OBJECT #if HAVE_DIRENT_H
#define FFREE_OBJECT(id) ([id release],id=nil) # include <dirent.h>
#define FREE_OBJECT(id) (id?FFREE_OBJECT(id):nil) # define NAMLEN(dirent) strlen((dirent)->d_name)
#else
# define dirent direct
# define NAMLEN(dirent) (dirent)->d_namlen
# if HAVE_SYS_NDIR_H
# include <sys/ndir.h>
# endif
# if HAVE_SYS_DIR_H
# include <sys/dir.h>
# endif
# if HAVE_NDIR_H
# include <ndir.h>
# endif
#endif #endif
/* This is the extension that NSBundle expect on all bundle names */ #define CHECK_LOCK(lock) \
#define BUNDLE_EXT "bundle" if (!lock) lock = [NSLock new]
/* By default, we transmorgrify extensions of type "nib" to type "xmib" typedef enum {
which is the common extension for IB files for the GNUStep project NSBUNDLE_BUNDLE = 1, NSBUNDLE_APPLICATION, NSBUNDLE_LIBRARY
*/ } bundle_t;
static NSString *bundle_nib_ext = @"nib";
static NSString *bundle_xmib_ext = @"xmib";
/* Class variables - We keep track of all the bundles and all the classes /* Class variables - We keep track of all the bundles */
that are in each bundle static NSBundle* _mainBundle = nil;
*/ static NSMapTable* _bundles = NULL;
static NSBundle *_mainBundle = nil;
static NSMutableArray *_bundles = nil;
static NSMutableArray *_bundleClasses = nil;
/* List of language preferences */ /* This is for bundles that we can't unload, so they shouldn't be
static NSArray *_languages = nil; dealloced. This is true for all bundles right now */
static NSMapTable* _releasedBundles = NULL;
/* When we are linking in an object file, objc_load_modules calls our /* When we are linking in an object file, objc_load_modules calls our
callback routine for every Class and Category loaded. The following callback routine for every Class and Category loaded. The following
variable stores the bundle that is currently doing the loading so we know variable stores the bundle that is currently doing the loading so we know
where to store the class names. where to store the class names.
FIXME: This should be put into a NSThread dictionary
*/ */
static int _loadingBundlePos = -1; static NSBundle* _loadingBundle = nil;
static NSLock* load_lock = nil;
static BOOL _strip_after_loading = NO;
static BOOL _stripAfterLoading; NSString* NSBundleDidLoadNotification = @"NSBundleDidLoadNotification";
NSString* NSShowNonLocalizedStrings = @"NSShowNonLocalizedStrings";
NSString* NSLoadedClasses = @"NSLoadedClasses";
static NSString* platform =
#ifdef PLATFORM_OS
@PLATFORM_OS;
#else
nil;
#endif
/* Declaration from find_exec.c */ /* Declaration from find_exec.c */
extern char *objc_find_executable(const char *name); extern char *objc_find_executable(const char *name);
@ -103,423 +126,546 @@ objc_executable_location( void )
/* Get the object file that should be located in the bundle of the same name */ /* Get the object file that should be located in the bundle of the same name */
static NSString * static NSString *
bundle_object_name(NSString *path) bundle_object_name(NSString *path, NSString* executable)
{ {
NSString *name; NSString *name;
#if 0
/* FIXME: This will work when NSString is fully implemented */ if (executable)
name = [[path lastPathComponent] stringByDeletingPathExtension]; name = [path stringByAppendingPathComponent: executable];
name = [path stringByAppendingPathComponent:name]; else
return name; {
#else name = [[path lastPathComponent] stringByDeletingPathExtension];
#define BASENAME(str) ((rindex(str, '/')) ? rindex(str, '/')+1 : str) name = [path stringByAppendingPathComponent:name];
char *s; }
char *output;
OBJC_MALLOC(output, char, strlen(BASENAME([path cString]))+20);
strcpy(output, BASENAME([path cString]));
s = rindex(output, '.');
if (s)
*s = '\0';
name = [NSString stringWithFormat:@"%s/%s", [path cString], output];
OBJC_FREE(output);
#endif
return name; return name;
} }
/* Construct a path from the directory, language, name and extension. Used by /* Construct a path from components */
pathForResource:...
*/
static NSString * static NSString *
bundle_resource_path(NSString *path, NSString *lang, NSString *name, _bundle_resource_path(NSString *primary, NSString* bundlePath, NSString *lang)
NSString *ext )
{ {
NSString *fullpath; if (bundlePath)
NSString *name_ext; primary = [primary stringByAppendingPathComponent: bundlePath];
if (lang)
#if 0 primary = [primary stringByAppendingPathComponent:
/* FIXME: This will work when NSString is fully implemented */ [NSString stringWithFormat: @"%@.lproj", lang]];
name_ext = [name pathExtension]; return primary;
name = [name stringByDeletingPathExtension];
#else
char *s;
char *output;
OBJC_MALLOC(output, char, strlen([name cString])+1);
strcpy(output, [name cString]);
s = rindex(output, '.');
if (s)
{
*s = '\0';
name_ext = [NSString stringWithCString:(s+1)];
}
else
name_ext = nil;
name = [NSString stringWithCString:output];
OBJC_FREE(output);
#endif
// FIXME: we could check to see if name_ext and ext match, but what
// would we do if they didn't?
if (!ext)
ext = name_ext;
if ([ext isEqual:bundle_nib_ext])
ext = bundle_xmib_ext;
#if 0
/* FIXME: This will work when NSString is fully implemented */
if (lang) {
fullpath = [NSString stringWithFormat: @"%@/%@.lproj/%@",
path, lang, name];
} else {
fullpath = [NSString stringWithFormat: @"%@/%@", path, name];
}
if (ext && [ext length] != 0)
fullpath = [NSString stringByAppendingPathExtension:ext];
#else
if (lang) {
fullpath = [NSString stringWithFormat: @"%s/%s.lproj/%s",
[path cString], [lang cString], [name cString]];
} else {
fullpath = [NSString stringWithFormat: @"%s/%s",
[path cString], [name cString]];
}
if (ext && [ext length] != 0)
fullpath = [NSString stringWithFormat:@"%s.%s",
[fullpath cString], [ext cString]];
#endif
#ifdef DEBUG
fprintf(stderr, "Debug (NSBundle): path is %s\n", [fullpath cString]);
#endif
return fullpath;
} }
/* Find the first directory entry with a given name (with any extension) */
static NSString *
_bundle_path_for_name(NSString* path, NSString* name)
{
DIR *thedir;
struct dirent *entry;
NSString *fullname;
fullname = NULL;
thedir = opendir([path cString]);
if(thedir)
{
while ((entry = readdir(thedir)))
{
if (*entry->d_name != '.'
&& strncmp([name cString], entry->d_name, [name length]) == 0)
{
fullname = [NSString stringWithCString: entry->d_name];
break;
}
}
closedir(thedir);
}
if (!fullname)
return nil;
return [path stringByAppendingPathComponent: fullname];
}
@interface NSBundle (Private)
- (NSArray *) _bundleClasses;
@end
@implementation NSBundle (Private)
- (NSArray *) _bundleClasses
{
return _bundleClasses;
}
@end
void void
_bundle_load_callback(Class theClass, Category *theCategory) _bundle_load_callback(Class theClass, Category *theCategory)
{ {
/* Don't store categories */ assert(_loadingBundle);
assert(_loadingBundlePos >= 0); /* Don't store categories */
if (!theCategory) if (!theCategory)
[[_bundleClasses objectAtIndex:_loadingBundlePos] [(NSMutableArray *)[_loadingBundle _bundleClasses] addObject: (id)theClass];
addObject:(id)theClass];
} }
@implementation NSBundle @implementation NSBundle
+ (NSBundle *)mainBundle + (NSBundle *)mainBundle
{ {
if ( !_mainBundle ) {
char *s;
char *output;
NSString *path;
path = [[NSProcessInfo processInfo] processName]; CHECK_LOCK(load_lock);
output = objc_find_executable([path cString]); [load_lock lock];
assert(output);
path = [NSString stringWithCString: output];
OBJC_FREE(output);
/* Strip off the name of the program */ if ( !_mainBundle )
#if 0 {
/* FIXME: Should work when NSString is implemented */ char *output;
path = [path stringByDeletingLastPathComponent]; NSString *path;
#else
OBJC_MALLOC(output, char, strlen([path cString])+1); path = [[NSProcessInfo processInfo] processName];
strcpy(output, [path cString]); output = objc_find_executable([path cString]);
s = rindex(output, '/'); assert(output);
if (s && s != output) {*s = '\0';} path = [NSString stringWithCString: output];
path = [NSString stringWithCString:output]; OBJC_FREE(output);
OBJC_FREE(output);
#endif
/* Construct a path from the directory, language, name and extension. /* Strip off the name of the program */
Used by */ path = [path stringByDeletingLastPathComponent];
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "Debug (NSBundle): Found main in %s\n", fprintf(stderr, "Debug (NSBundle): Found main in %s\n",
[path cString]); [path cString]);
#endif #endif
/* We do alloc and init separately so initWithPath: does not /* We do alloc and init separately so initWithPath: knows
add us to the _bundles list we are the _mainBundle */
*/ _mainBundle = [NSBundle alloc];
_mainBundle = [NSBundle alloc]; _mainBundle = [_mainBundle initWithPath:path];
_mainBundle = [_mainBundle initWithPath:path];
} }
return _mainBundle;
[load_lock unlock];
return _mainBundle;
} }
/* Due to lazy evaluation, we will not find a class if a either classNamed: or /* Due to lazy evaluation, we will not find a class if either classNamed: or
principalClass has not been called on the particular bundle that contains principalClass has not been called on the particular bundle that contains
the class. (FIXME) the class. (FIXME)
*/ */
+ (NSBundle *)bundleForClass:aClass + (NSBundle *) bundleForClass: (Class)aClass
{ {
int i, count; void* key;
NSBundle *bundle = nil; NSBundle* bundle;
NSMapEnumerator enumerate;
if (!aClass)
return nil;
// FIXME: should this be an error if aClass == nil? bundle = nil;
if (!aClass) enumerate = NSEnumerateMapTable(_bundles);
return nil; while (NSNextMapEnumeratorPair(&enumerate, &key, (void **)&bundle))
{
count = [_bundleClasses count]; int j;
for (i=0; i < count; i++) { j = [[bundle _bundleClasses] indexOfObject: aClass];
int j, class_count; if (j != NSNotFound && [bundle _bundleClasses])
NSArray *classList = [_bundleClasses objectAtIndex:i]; break;
class_count = [classList count]; bundle = nil;
for (j = 0; j < class_count; j++)
if ([aClass isEqual:[classList objectAtIndex:j]]) {
bundle = [_bundles objectAtIndex:i];
break;
}
if (bundle)
break;
} }
if (!bundle) { if (!bundle)
/* Is it in the main bundle? */ {
if (class_is_class(aClass)) /* Is it in the main bundle? */
bundle = [NSBundle mainBundle]; if (class_is_class(aClass))
bundle = [NSBundle mainBundle];
} }
return bundle; return bundle;
} }
+ (NSBundle *)bundleWithPath:(NSString *)path + (NSBundle *)bundleWithPath:(NSString *)path
{ {
return [[[NSBundle alloc] initWithPath:path] autorelease]; return [[[NSBundle alloc] initWithPath: path] autorelease];
} }
- initWithPath:(NSString *)path; - initWithPath:(NSString *)path;
{ {
struct stat statbuf; struct stat statbuf;
[super init]; [super init];
if (!_languages) if (!path || [path length] == 0)
[[self class] setSystemLanguages:NULL]; {
NSLog(@"No path specified for bundle");
if (!path || [path length] == 0) { return nil;
[NSException raise:NSInvalidArgumentException
format:@"No path specified for bundle"];
/* NOT REACHED */
} }
/* Check if we were already initialized for this directory */ /* Check if we were already initialized for this directory */
if (_bundles) { if (_bundles)
int i; {
int count; NSBundle* bundle = (NSBundle *)NSMapGet(_bundles, path);
count = [_bundles count]; if (bundle)
for (i=0; i < count; i++) { {
if ([path isEqual:[[_bundles objectAtIndex:i] bundlePath]]) [self dealloc];
return [_bundles objectAtIndex:i]; return [bundle retain]; /* retain - look as if we were alloc'ed */
} }
}
if (_releasedBundles)
{
NSBundle* loaded = (NSBundle *)NSMapGet(_releasedBundles, path);
if (loaded)
{
NSMapInsert(_bundles, path, loaded);
NSMapRemove(_releasedBundles, path);
[self dealloc];
return [loaded retain]; /* retain - look as if we were alloc'ed */
}
} }
if (stat([path cString], &statbuf) != 0) { if (stat([path cString], &statbuf) != 0)
[NSException raise:NSGenericException {
format:@"Could not find path %s", [path cString]]; NSLog(@"Could not access path %s for bundle", [path cString]);
/* NOT REACHED */ return nil;
} }
_path = [path retain];
if (self == _mainBundle) CHECK_LOCK(load_lock);
return self; [load_lock lock];
if (!_bundles)
if (!_bundles) { {
_bundles = [[NSMutableArray arrayWithCapacity:2] retain]; _bundles = NSCreateMapTable(NSObjectMapKeyCallBacks,
_bundleClasses = [[NSMutableArray arrayWithCapacity:2] retain]; NSNonOwnedPointerMapValueCallBacks, 0);
_releasedBundles = NSCreateMapTable(NSObjectMapKeyCallBacks,
NSNonOwnedPointerMapValueCallBacks, 0);
} }
[_bundles addObject:self]; [load_lock unlock];
[_bundleClasses addObject:[[NSMutableArray arrayWithCapacity:0] retain]];
return self; _path = [path copy];
_bundleType = (unsigned int)NSBUNDLE_BUNDLE;
if (self == _mainBundle)
_bundleType = (unsigned int)NSBUNDLE_APPLICATION;
NSMapInsert(_bundles, _path, self);
return self;
} }
/* We can't really unload the module, since objc_unload_module has /* Some bundles should not be dealloced, such as the main bundle. So we
no idea where we were loaded from, so we just dealloc everything and keep track of our own retain count to avoid this.
don't worry about it. Currently, the objc runtime can't unload modules, so we actually
avoid deallocating any bundle */
- (oneway void) release
{
if (self == NSMapGet(_releasedBundles, _path))
{
[NSException raise: NSGenericException
format: @"Bundle for path %@ released too many times", _path];
}
NSParameterAssert(_retainCount >= 0);
if (_retainCount == 0)
{
/* Cache all bundles */
if (_bundleType == NSBUNDLE_APPLICATION
|| _bundleType == NSBUNDLE_LIBRARY
|| _bundleType == NSBUNDLE_BUNDLE)
{
NSMapRemove(_bundles, _path);
NSMapInsert(_releasedBundles, _path, self);
}
else
[self dealloc];
return;
}
_retainCount--;
}
- retain
{
_retainCount++;
return self;
}
- (unsigned) retainCount
{
return _retainCount;
}
- (void) dealloc
{
NSMapRemove(_bundles, _path);
[_bundleClasses release];
[_infoDict release];
[_path release];
[super dealloc];
}
- (NSString *) bundlePath
{
return _path;
}
- (Class) classNamed: (NSString *)className
{
int j;
Class theClass = Nil;
if (!_codeLoaded)
{
if (self != _mainBundle && ![self principalClass])
{
NSLog(@"No classes in bundle");
return Nil;
}
}
if (self == _mainBundle)
{
theClass = NSClassFromString(className);
if (theClass && [[self class] bundleForClass:theClass] != _mainBundle)
theClass = Nil;
}
else
{
j = [_bundleClasses indexOfObject: NSClassFromString(className)];
if (j != NSNotFound)
theClass = [_bundleClasses objectAtIndex: j];
}
return theClass;
}
- (Class) principalClass
{
NSString* class_name;
if (_principalClass)
return _principalClass;
class_name = [[self infoDictionary] objectForKey: @"NSPrincipalClass"];
if (self == _mainBundle)
{
_codeLoaded = YES;
if (class_name)
_principalClass = NSClassFromString(class_name);
return _principalClass;
}
[load_lock lock];
if (!_codeLoaded)
{
NSString* object;
object = [[self infoDictionary] objectForKey: @"NSExecutable"];
object = bundle_object_name(_path, object);
_loadingBundle = self;
_bundleClasses = [[NSMutableArray arrayWithCapacity:2] retain];
if (objc_load_module([object cString],
stderr, _bundle_load_callback, NULL, NULL))
return Nil;
_codeLoaded = YES;
_loadingBundle = nil;
[[NSNotificationCenter defaultCenter]
postNotificationName: NSBundleDidLoadNotification
object: self
userInfo: [NSDictionary dictionaryWithObjects: &_bundleClasses
forKeys: &NSLoadedClasses count: 1]];
}
[load_lock unlock];
if (class_name)
_principalClass = NSClassFromString(class_name);
else if ([_bundleClasses count])
_principalClass = [_bundleClasses objectAtIndex:0];
return _principalClass;
}
/* This method is the backbone of the resource searching for NSBundle. It
constructs an array of paths, where each path is a possible location
for a resource in the bundle. The current algorithm for searching goes:
<main bundle>/Resources/<bundlePath>
<main bundle>/Resources/<bundlePath>/<language.lproj>
<main bundle>/<bundlePath>
<main bundle>/<bundlePath>/<language.lproj>
*/ */
- (void)dealloc - (NSArray *) _bundleResourcePathsWithDirectory: (NSString *)bundlePath
{ {
int pos = [_bundles indexOfObject:self]; NSString* primary;
NSString* language;
NSArray* languages;
NSMutableArray* array;
NSEnumerator* enumerate;
if (pos >= 0) { array = [NSMutableArray arrayWithCapacity: 2];
[_bundleClasses removeObjectAtIndex:pos]; languages = [NSUserDefaults userLanguages];
[_bundles removeObjectAtIndex:pos];
}
FREE_OBJECT(_path);
[super dealloc];
}
- (NSString *)bundlePath primary = [self resourcePath];
{ [array addObject: _bundle_resource_path(primary, bundlePath, nil)];
return _path; enumerate = [languages objectEnumerator];
} while ((language = [enumerate nextObject]))
[array addObject: _bundle_resource_path(primary, bundlePath, language)];
- classNamed:(NSString *)className
{
int j, class_count;
NSArray *classList;
Class theClass = Nil;
if (!_codeLoaded) {
if (self != _mainBundle && ![self principalClass]) {
[NSException raise:NSGenericException
format:@"No classes in bundle"];
/* NOT REACHED */
}
}
if (self == _mainBundle) {
theClass = objc_lookup_class([className cString]);
if (theClass && [[self class] bundleForClass:theClass] != _mainBundle)
theClass = Nil;
} else {
classList = [_bundleClasses objectAtIndex:
[_bundles indexOfObject:self]];
class_count = [classList count];
for (j = 0; j < class_count; j++) {
theClass = [classList objectAtIndex:j];
if ([theClass isEqual:objc_lookup_class([className cString])]) {
break;
}
theClass = Nil;
}
}
return theClass;
}
- principalClass
{
NSArray *classList;
if (self == _mainBundle) {
_codeLoaded = YES;
return nil; // the mainBundle does not have a principal class
}
if (!_codeLoaded) {
NSString *object = bundle_object_name(_path);
/* Link in the object file */
_loadingBundlePos = [_bundles indexOfObject:self];
if (objc_load_module([object cString],
stderr, _bundle_load_callback, NULL, NULL)) {
[NSException raise:NSGenericException
format:@"Unable to load module %s", [object cString]];
/* NOT REACHED */
} else
_codeLoaded = YES;
_loadingBundlePos = -1;
}
classList = [_bundleClasses objectAtIndex:[_bundles indexOfObject:self]];
if ([classList count])
return [classList objectAtIndex:0];
else
return nil;
}
- (NSString *)pathForResource:(NSString *)name
ofType:(NSString *)ext;
{
return [[self class] pathForResource:name
ofType:ext
inDirectory: _path
withVersion: 0];
}
+ (NSString *)pathForResource:(NSString *)name
ofType:(NSString *)ext
inDirectory:(NSString *)bundlePath
withVersion:(int)version;
{
struct stat statbuf;
NSString *path = nil;
if (!name || [name length] == 0) { primary = [self bundlePath];
[NSException raise:NSInvalidArgumentException [array addObject: _bundle_resource_path(primary, bundlePath, nil)];
format:@"No resource name specified."]; enumerate = [languages objectEnumerator];
/* NOT REACHED */ while ((language = [enumerate nextObject]))
[array addObject: _bundle_resource_path(primary, bundlePath, language)];
return array;
}
- (NSString *) pathForResource: (NSString *)name
ofType: (NSString *)ext;
{
return [self pathForResource: name
ofType: ext
inDirectory: nil];
}
- (NSString *) pathForResource: (NSString *)name
ofType: (NSString *)ext
inDirectory: (NSString *)bundlePath
{
NSString *path;
NSArray* paths;
NSEnumerator* enumerate;
if (!name || [name length] == 0)
{
[NSException raise: NSInvalidArgumentException
format: @"No resource name specified."];
/* NOT REACHED */
} }
if (_languages) { paths = [self _bundleResourcePathsWithDirectory: bundlePath];
unsigned i, count; enumerate = [paths objectEnumerator];
count = [_languages count]; while((path = [enumerate nextObject]))
for (i=0; i < count; i++) { {
path = bundle_resource_path(bundlePath, NSString* fullpath = nil;
[_languages objectAtIndex:i], name, ext );
if ( stat([path cString], &statbuf) == 0)
break;
path = nil;
}
} else {
path = bundle_resource_path(bundlePath, @"English", name, ext );
if ( stat([path cString], &statbuf) != 0) {
path = nil;
}
if (ext && [ext length] != 0)
{
struct stat statbuf;
fullpath = [path stringByAppendingPathComponent:
[NSString stringWithFormat: @"%@.%@", name, ext]];
if ( stat([fullpath cString], &statbuf) == 0)
{
if (platform)
{
NSString* platpath;
platpath = [path stringByAppendingPathComponent:
[NSString stringWithFormat: @"%@-%@.%@",
name, platform, ext]];
if ( stat([platpath cString], &statbuf) == 0)
fullpath = platpath;
}
}
else
fullpath = nil;
}
else
{
fullpath = _bundle_path_for_name(path, name);
if (fullpath && platform)
{
NSString* platpath;
platpath = _bundle_path_for_name(path,
[NSString stringWithFormat: @"%@-%@",
name, platform]);
if (platpath)
fullpath = platpath;
}
}
if (fullpath)
return fullpath;
} }
if (!path) { return nil;
path = bundle_resource_path(bundlePath, nil, name, ext ); }
if ( stat([path cString], &statbuf) != 0) {
path = nil; - (NSArray *) pathsForResourcesOfType: (NSString *)extension
inDirectory: (NSString *)bundlePath
{
NSString *path;
NSArray* paths;
NSMutableArray* resources;
NSEnumerator* enumerate;
paths = [self _bundleResourcePathsWithDirectory: bundlePath];
enumerate = [paths objectEnumerator];
resources = [NSMutableArray arrayWithCapacity: 2];
while((path = [enumerate nextObject]))
{
DIR *thedir;
struct dirent *entry;
thedir = opendir([path cString]);
if (thedir)
{
while ((entry = readdir(thedir)))
{
if (*entry->d_name != '.')
{
char* ext;
ext = strrchr(entry->d_name, '.');
if (!extension || [extension length] == 0
|| (ext && strcmp(++ext, [extension cString]) == 0))
[resources addObject:
[path stringByAppendingPathComponent:
[NSString stringWithCString: entry->d_name]]];
}
}
closedir(thedir);
} }
} }
return path; return resources;
} }
+ (void)stripAfterLoading:(BOOL)flag - (NSString *) localizedStringForKey: (NSString *)key
value: (NSString *)value
table: (NSString *)tableName
{ {
_stripAfterLoading = flag; NSString* new_string;
}
- (NSString *)localizedStringForKey:(NSString *)key if (!tableName)
value:(NSString *)value tableName = [self pathForResource: @"Localizable" ofType: @"strings"];
table:(NSString *)tableName if (!tableName)
{ {
[self notImplemented:_cmd]; NSArray* resources = [self pathsForResourcesOfType: @"strings"
return 0; inDirectory: nil];
} if (resources && [resources count])
tableName = [resources objectAtIndex: 0];
- (unsigned)bundleVersion
{
return _bundleVersion;
}
- (void)setBundleVersion:(unsigned)version
{
_bundleVersion = version;
}
+ (void)setSystemLanguages:(NSArray *)languages
{
// static NSString *separator = @" ";
if (_languages) {
FREE_OBJECT(_languages);
} }
/* If called with a nil array, look in the environment for the
language list. The languages should separated by the "separator"
string.
*/
if (!languages) {
const char *env_list;
// NSString *env;
env_list = getenv("LANGUAGES");
if (env_list) {
#if 0
/* FIXME: This will work when NSString is fully implemented */
env = [NSString stringWithCString:e];
_languages = [[env componentsSeparatedByString:separator] retain];
#else
/* Just pick out the first one */
char *s;
s = index(env_list, ' ');
if (s)
*s = '\0';
_languages = [[NSString stringWithCString:env_list] retain];
#endif
}
} else
_languages = [languages retain];
new_string = value;
if (tableName)
{
NSDictionary* dict;
dict = [[[NSDictionary alloc] initWithContentsOfFile: tableName]
autorelease];
new_string = [dict objectForKey: key];
if (!new_string)
new_string = value;
}
if (!new_string || [new_string length] == 0)
{
NSString* show = [[NSUserDefaults standardUserDefaults]
objectForKey: NSShowNonLocalizedStrings];
if (!show || [show isEqual: @"YES"])
new_string = [key uppercaseString];
else
new_string = key;
}
return new_string;
}
+ (void) stripAfterLoading: (BOOL)flag
{
_strip_after_loading = flag;
}
- (NSString *) resourcePath
{
return [_path stringByAppendingPathComponent: @"Resources"];
}
- (NSDictionary *) infoDictionary
{
NSString* path;
if (_infoDict)
return _infoDict;
path = [self pathForResource: @"Info" ofType: @"plist"];
if (path)
_infoDict = [[NSDictionary alloc] initWithContentsOfFile: path];
else
_infoDict = [[NSDictionary dictionary] retain];
return _infoDict;
} }
@end @end

7
aclocal.m4 vendored
View file

@ -156,7 +156,12 @@ elif test $DYNAMIC_LINKER = simple; then
else else
DYNAMIC_BUNDLER_LINKER='$(CC) -nostdlib' DYNAMIC_BUNDLER_LINKER='$(CC) -nostdlib'
fi fi
DYNAMIC_LDFLAGS="" save_LDFLAGS=$LDFLAGS
LDFLAGS="-rdynamic"
AC_TRY_RUN([], objc_dynamic_ldflag="-rdynamic", objc_dynamic_ldflag="",
objc_dynamic_ldflag="")
LDFLAGS=$save_LDFLAGS
DYNAMIC_LDFLAGS="$objc_dynamic_ldflag"
DYNAMIC_CFLAGS="-fPIC" DYNAMIC_CFLAGS="-fPIC"
elif test $DYNAMIC_LINKER = hpux; then elif test $DYNAMIC_LINKER = hpux; then
DYNAMIC_BUNDLER_LINKER='$(CC) -nostdlib -Xlinker -b' DYNAMIC_BUNDLER_LINKER='$(CC) -nostdlib -Xlinker -b'

View file

@ -175,6 +175,16 @@ AC_SUBST(NEXT_INCLUDES)
#-------------------------------------------------------------------- #--------------------------------------------------------------------
OBJC_SYS_DYNAMIC_FLAGS() OBJC_SYS_DYNAMIC_FLAGS()
#--------------------------------------------------------------------
# Determine the target platform
#--------------------------------------------------------------------
if test "x$target" = "xNONE"; then
PLATFORM_OS=`config.guess`
else
PLATFORM_OS="$target"
fi
AC_SUBST(PLATFORM_OS)
#-------------------------------------------------------------------- #--------------------------------------------------------------------
# Find some programs # Find some programs
#-------------------------------------------------------------------- #--------------------------------------------------------------------
@ -229,6 +239,12 @@ if [ $HAVE_VSPRINTF ] ; then
AC_DEFINE(VSPRINTF_RETURNS_LENGTH) AC_DEFINE(VSPRINTF_RETURNS_LENGTH)
fi fi
#--------------------------------------------------------------------
# DIR definitions needed by NSBundle.m
#--------------------------------------------------------------------
AC_HEADER_DIRENT
#-------------------------------------------------------------------- #--------------------------------------------------------------------
# This function needed by objc-malloc.c # This function needed by objc-malloc.c
#-------------------------------------------------------------------- #--------------------------------------------------------------------