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>
Further changes for the NSString implementation.

View file

@ -28,42 +28,54 @@
@class NSString;
@class NSArray;
@class NSDictionary;
extern NSString* NSBundleDidLoadNotification;
extern NSString* NSShowNonLocalizedStrings;
extern NSString* NSLoadedClasses;
@interface NSBundle : NSObject
{
NSString *_path;
Class _principalClass;
NSArray* _bundleClasses;
Class _principalClass;
id _infoDict;
unsigned int _retainCount;
unsigned int _bundleType;
BOOL _codeLoaded;
int _bundleVersion;
}
+ (NSBundle *)mainBundle;
+ (NSBundle *)bundleForClass:aClass;
+ (NSBundle *)bundleWithPath:(NSString *)path;
- initWithPath:(NSString *)path;
- (NSString *)bundlePath;
- classNamed:(NSString *)className;
- principalClass;
+ (NSBundle *) mainBundle;
+ (NSBundle *) bundleForClass: (Class)aClass;
+ (NSBundle *) bundleWithPath: (NSString *)path;
- initWithPath: (NSString *)path;
- (NSString *) bundlePath;
- (Class) classNamed: (NSString *)className;
- (Class) principalClass;
+ (NSString *)pathForResource:(NSString *)name
ofType:(NSString *)ext
inDirectory:(NSString *)bundlePath
withVersion:(int)version;
- (NSArray *) pathsForResourcesOfType: (NSString *)extension
inDirectory: (NSString *)bundlePath;
- (NSString *) pathForResource: (NSString *)name
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
ofType:(NSString *)ext;
+ (void)stripAfterLoading:(BOOL)flag;
- (NSString *)localizedStringForKey:(NSString *)key
value:(NSString *)value
table:(NSString *)tableName;
- (unsigned)bundleVersion;
- (void)setBundleVersion:(unsigned)version;
+ (void)setSystemLanguages:(NSArray *)languages;
#ifndef STRICT_OPENSTEP
- (NSDictionary *) infoDictionary;
#endif
@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 */

View file

@ -51,7 +51,7 @@ YACC = bison
# GNUSTEP_INSTALL_PREFIX must be defined here and not in config.h because
# 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
OEXT = .o

View file

@ -37,7 +37,13 @@
#include <Foundation/NSException.h>
#include <Foundation/NSString.h>
#include <Foundation/NSArray.h>
#include <Foundation/NSDictionary.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: */
#if STDC_HEADERS || HAVE_STRING_H
@ -56,39 +62,56 @@
/* memory.h and strings.h conflict on some systems. */
#endif /* not STDC_HEADERS and not HAVE_STRING_H */
#ifndef FREE_OBJECT
#define FFREE_OBJECT(id) ([id release],id=nil)
#define FREE_OBJECT(id) (id?FFREE_OBJECT(id):nil)
#if HAVE_DIRENT_H
# include <dirent.h>
# 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
/* This is the extension that NSBundle expect on all bundle names */
#define BUNDLE_EXT "bundle"
#define CHECK_LOCK(lock) \
if (!lock) lock = [NSLock new]
/* By default, we transmorgrify extensions of type "nib" to type "xmib"
which is the common extension for IB files for the GNUStep project
*/
static NSString *bundle_nib_ext = @"nib";
static NSString *bundle_xmib_ext = @"xmib";
typedef enum {
NSBUNDLE_BUNDLE = 1, NSBUNDLE_APPLICATION, NSBUNDLE_LIBRARY
} bundle_t;
/* Class variables - We keep track of all the bundles and all the classes
that are in each bundle
*/
static NSBundle *_mainBundle = nil;
static NSMutableArray *_bundles = nil;
static NSMutableArray *_bundleClasses = nil;
/* Class variables - We keep track of all the bundles */
static NSBundle* _mainBundle = nil;
static NSMapTable* _bundles = NULL;
/* List of language preferences */
static NSArray *_languages = nil;
/* This is for bundles that we can't unload, so they shouldn't be
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
callback routine for every Class and Category loaded. The following
variable stores the bundle that is currently doing the loading so we know
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 */
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 */
static NSString *
bundle_object_name(NSString *path)
bundle_object_name(NSString *path, NSString* executable)
{
NSString *name;
#if 0
/* FIXME: This will work when NSString is fully implemented */
name = [[path lastPathComponent] stringByDeletingPathExtension];
name = [path stringByAppendingPathComponent:name];
return name;
#else
#define BASENAME(str) ((rindex(str, '/')) ? rindex(str, '/')+1 : str)
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
if (executable)
name = [path stringByAppendingPathComponent: executable];
else
{
name = [[path lastPathComponent] stringByDeletingPathExtension];
name = [path stringByAppendingPathComponent:name];
}
return name;
}
/* Construct a path from the directory, language, name and extension. Used by
pathForResource:...
*/
/* Construct a path from components */
static NSString *
bundle_resource_path(NSString *path, NSString *lang, NSString *name,
NSString *ext )
_bundle_resource_path(NSString *primary, NSString* bundlePath, NSString *lang)
{
NSString *fullpath;
NSString *name_ext;
#if 0
/* FIXME: This will work when NSString is fully implemented */
name_ext = [name pathExtension];
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;
if (bundlePath)
primary = [primary stringByAppendingPathComponent: bundlePath];
if (lang)
primary = [primary stringByAppendingPathComponent:
[NSString stringWithFormat: @"%@.lproj", lang]];
return primary;
}
/* 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
_bundle_load_callback(Class theClass, Category *theCategory)
{
/* Don't store categories */
assert(_loadingBundlePos >= 0);
if (!theCategory)
[[_bundleClasses objectAtIndex:_loadingBundlePos]
addObject:(id)theClass];
assert(_loadingBundle);
/* Don't store categories */
if (!theCategory)
[(NSMutableArray *)[_loadingBundle _bundleClasses] addObject: (id)theClass];
}
@implementation NSBundle
+ (NSBundle *)mainBundle
{
if ( !_mainBundle ) {
char *s;
char *output;
NSString *path;
path = [[NSProcessInfo processInfo] processName];
output = objc_find_executable([path cString]);
assert(output);
path = [NSString stringWithCString: output];
OBJC_FREE(output);
CHECK_LOCK(load_lock);
[load_lock lock];
/* Strip off the name of the program */
#if 0
/* FIXME: Should work when NSString is implemented */
path = [path stringByDeletingLastPathComponent];
#else
OBJC_MALLOC(output, char, strlen([path cString])+1);
strcpy(output, [path cString]);
s = rindex(output, '/');
if (s && s != output) {*s = '\0';}
path = [NSString stringWithCString:output];
OBJC_FREE(output);
#endif
if ( !_mainBundle )
{
char *output;
NSString *path;
path = [[NSProcessInfo processInfo] processName];
output = objc_find_executable([path cString]);
assert(output);
path = [NSString stringWithCString: output];
OBJC_FREE(output);
/* Construct a path from the directory, language, name and extension.
Used by */
/* Strip off the name of the program */
path = [path stringByDeletingLastPathComponent];
#ifdef DEBUG
fprintf(stderr, "Debug (NSBundle): Found main in %s\n",
[path cString]);
fprintf(stderr, "Debug (NSBundle): Found main in %s\n",
[path cString]);
#endif
/* We do alloc and init separately so initWithPath: does not
add us to the _bundles list
*/
_mainBundle = [NSBundle alloc];
_mainBundle = [_mainBundle initWithPath:path];
/* We do alloc and init separately so initWithPath: knows
we are the _mainBundle */
_mainBundle = [NSBundle alloc];
_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
the class. (FIXME)
*/
+ (NSBundle *)bundleForClass:aClass
+ (NSBundle *) bundleForClass: (Class)aClass
{
int i, count;
NSBundle *bundle = nil;
void* key;
NSBundle* bundle;
NSMapEnumerator enumerate;
if (!aClass)
return nil;
// FIXME: should this be an error if aClass == nil?
if (!aClass)
return nil;
count = [_bundleClasses count];
for (i=0; i < count; i++) {
int j, class_count;
NSArray *classList = [_bundleClasses objectAtIndex:i];
class_count = [classList count];
for (j = 0; j < class_count; j++)
if ([aClass isEqual:[classList objectAtIndex:j]]) {
bundle = [_bundles objectAtIndex:i];
break;
}
if (bundle)
break;
bundle = nil;
enumerate = NSEnumerateMapTable(_bundles);
while (NSNextMapEnumeratorPair(&enumerate, &key, (void **)&bundle))
{
int j;
j = [[bundle _bundleClasses] indexOfObject: aClass];
if (j != NSNotFound && [bundle _bundleClasses])
break;
bundle = nil;
}
if (!bundle) {
/* Is it in the main bundle? */
if (class_is_class(aClass))
bundle = [NSBundle mainBundle];
if (!bundle)
{
/* Is it in the main bundle? */
if (class_is_class(aClass))
bundle = [NSBundle mainBundle];
}
return bundle;
return bundle;
}
+ (NSBundle *)bundleWithPath:(NSString *)path
{
return [[[NSBundle alloc] initWithPath:path] autorelease];
return [[[NSBundle alloc] initWithPath: path] autorelease];
}
- initWithPath:(NSString *)path;
{
struct stat statbuf;
[super init];
struct stat statbuf;
[super init];
if (!_languages)
[[self class] setSystemLanguages:NULL];
if (!path || [path length] == 0) {
[NSException raise:NSInvalidArgumentException
format:@"No path specified for bundle"];
/* NOT REACHED */
if (!path || [path length] == 0)
{
NSLog(@"No path specified for bundle");
return nil;
}
/* Check if we were already initialized for this directory */
if (_bundles) {
int i;
int count;
count = [_bundles count];
for (i=0; i < count; i++) {
if ([path isEqual:[[_bundles objectAtIndex:i] bundlePath]])
return [_bundles objectAtIndex:i];
}
/* Check if we were already initialized for this directory */
if (_bundles)
{
NSBundle* bundle = (NSBundle *)NSMapGet(_bundles, path);
if (bundle)
{
[self dealloc];
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) {
[NSException raise:NSGenericException
format:@"Could not find path %s", [path cString]];
/* NOT REACHED */
if (stat([path cString], &statbuf) != 0)
{
NSLog(@"Could not access path %s for bundle", [path cString]);
return nil;
}
_path = [path retain];
if (self == _mainBundle)
return self;
if (!_bundles) {
_bundles = [[NSMutableArray arrayWithCapacity:2] retain];
_bundleClasses = [[NSMutableArray arrayWithCapacity:2] retain];
CHECK_LOCK(load_lock);
[load_lock lock];
if (!_bundles)
{
_bundles = NSCreateMapTable(NSObjectMapKeyCallBacks,
NSNonOwnedPointerMapValueCallBacks, 0);
_releasedBundles = NSCreateMapTable(NSObjectMapKeyCallBacks,
NSNonOwnedPointerMapValueCallBacks, 0);
}
[_bundles addObject:self];
[_bundleClasses addObject:[[NSMutableArray arrayWithCapacity:0] retain]];
[load_lock unlock];
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
no idea where we were loaded from, so we just dealloc everything and
don't worry about it.
/* Some bundles should not be dealloced, such as the main bundle. So we
keep track of our own retain count to avoid this.
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) {
[_bundleClasses removeObjectAtIndex:pos];
[_bundles removeObjectAtIndex:pos];
}
FREE_OBJECT(_path);
[super dealloc];
}
array = [NSMutableArray arrayWithCapacity: 2];
languages = [NSUserDefaults userLanguages];
- (NSString *)bundlePath
{
return _path;
}
- 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;
primary = [self resourcePath];
[array addObject: _bundle_resource_path(primary, bundlePath, nil)];
enumerate = [languages objectEnumerator];
while ((language = [enumerate nextObject]))
[array addObject: _bundle_resource_path(primary, bundlePath, language)];
if (!name || [name length] == 0) {
[NSException raise:NSInvalidArgumentException
format:@"No resource name specified."];
/* NOT REACHED */
primary = [self bundlePath];
[array addObject: _bundle_resource_path(primary, bundlePath, nil)];
enumerate = [languages objectEnumerator];
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) {
unsigned i, count;
count = [_languages count];
for (i=0; i < count; i++) {
path = bundle_resource_path(bundlePath,
[_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;
}
paths = [self _bundleResourcePathsWithDirectory: bundlePath];
enumerate = [paths objectEnumerator];
while((path = [enumerate nextObject]))
{
NSString* fullpath = 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) {
path = bundle_resource_path(bundlePath, nil, name, ext );
if ( stat([path cString], &statbuf) != 0) {
path = nil;
return 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
value:(NSString *)value
table:(NSString *)tableName
{
[self notImplemented:_cmd];
return 0;
}
- (unsigned)bundleVersion
{
return _bundleVersion;
}
- (void)setBundleVersion:(unsigned)version
{
_bundleVersion = version;
}
+ (void)setSystemLanguages:(NSArray *)languages
{
// static NSString *separator = @" ";
if (_languages) {
FREE_OBJECT(_languages);
if (!tableName)
tableName = [self pathForResource: @"Localizable" ofType: @"strings"];
if (!tableName)
{
NSArray* resources = [self pathsForResourcesOfType: @"strings"
inDirectory: nil];
if (resources && [resources count])
tableName = [resources objectAtIndex: 0];
}
/* 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

7
aclocal.m4 vendored
View file

@ -156,7 +156,12 @@ elif test $DYNAMIC_LINKER = simple; then
else
DYNAMIC_BUNDLER_LINKER='$(CC) -nostdlib'
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"
elif test $DYNAMIC_LINKER = hpux; then
DYNAMIC_BUNDLER_LINKER='$(CC) -nostdlib -Xlinker -b'

View file

@ -175,6 +175,16 @@ AC_SUBST(NEXT_INCLUDES)
#--------------------------------------------------------------------
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
#--------------------------------------------------------------------
@ -229,6 +239,12 @@ if [ $HAVE_VSPRINTF ] ; then
AC_DEFINE(VSPRINTF_RETURNS_LENGTH)
fi
#--------------------------------------------------------------------
# DIR definitions needed by NSBundle.m
#--------------------------------------------------------------------
AC_HEADER_DIRENT
#--------------------------------------------------------------------
# This function needed by objc-malloc.c
#--------------------------------------------------------------------