mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-25 01:31:08 +00:00
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:
parent
f25cb10514
commit
5b8ea53689
6 changed files with 653 additions and 393 deletions
81
ChangeLog
81
ChangeLog
|
@ -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.
|
||||
|
|
|
@ -28,42 +28,54 @@
|
|||
|
||||
@class NSString;
|
||||
@class NSArray;
|
||||
@class NSDictionary;
|
||||
|
||||
extern NSString* NSBundleDidLoadNotification;
|
||||
extern NSString* NSShowNonLocalizedStrings;
|
||||
extern NSString* NSLoadedClasses;
|
||||
|
||||
@interface NSBundle : NSObject
|
||||
{
|
||||
NSString *_path;
|
||||
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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,110 +126,91 @@ 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 */
|
||||
|
||||
if (executable)
|
||||
name = [path stringByAppendingPathComponent: executable];
|
||||
else
|
||||
{
|
||||
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
|
||||
}
|
||||
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)
|
||||
{
|
||||
assert(_loadingBundle);
|
||||
/* Don't store categories */
|
||||
assert(_loadingBundlePos >= 0);
|
||||
if (!theCategory)
|
||||
[[_bundleClasses objectAtIndex:_loadingBundlePos]
|
||||
addObject:(id)theClass];
|
||||
[(NSMutableArray *)[_loadingBundle _bundleClasses] addObject: (id)theClass];
|
||||
}
|
||||
|
||||
@implementation NSBundle
|
||||
|
||||
+ (NSBundle *)mainBundle
|
||||
{
|
||||
if ( !_mainBundle ) {
|
||||
char *s;
|
||||
|
||||
CHECK_LOCK(load_lock);
|
||||
[load_lock lock];
|
||||
|
||||
if ( !_mainBundle )
|
||||
{
|
||||
char *output;
|
||||
NSString *path;
|
||||
|
||||
|
@ -217,61 +221,46 @@ _bundle_load_callback(Class theClass, Category *theCategory)
|
|||
OBJC_FREE(output);
|
||||
|
||||
/* 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
|
||||
|
||||
/* Construct a path from the directory, language, name and extension.
|
||||
Used by */
|
||||
|
||||
#ifdef DEBUG
|
||||
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
|
||||
*/
|
||||
/* We do alloc and init separately so initWithPath: knows
|
||||
we are the _mainBundle */
|
||||
_mainBundle = [NSBundle alloc];
|
||||
_mainBundle = [_mainBundle initWithPath:path];
|
||||
}
|
||||
|
||||
[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;
|
||||
|
||||
// FIXME: should this be an error if aClass == nil?
|
||||
void* key;
|
||||
NSBundle* bundle;
|
||||
NSMapEnumerator enumerate;
|
||||
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];
|
||||
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)
|
||||
break;
|
||||
}
|
||||
if (!bundle) {
|
||||
if (!bundle)
|
||||
{
|
||||
/* Is it in the main bundle? */
|
||||
if (class_is_class(aClass))
|
||||
bundle = [NSBundle mainBundle];
|
||||
|
@ -282,7 +271,7 @@ _bundle_load_callback(Class theClass, Category *theCategory)
|
|||
|
||||
+ (NSBundle *)bundleWithPath:(NSString *)path
|
||||
{
|
||||
return [[[NSBundle alloc] initWithPath:path] autorelease];
|
||||
return [[[NSBundle alloc] initWithPath: path] autorelease];
|
||||
}
|
||||
|
||||
- initWithPath:(NSString *)path;
|
||||
|
@ -290,236 +279,393 @@ _bundle_load_callback(Class theClass, Category *theCategory)
|
|||
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];
|
||||
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];
|
||||
|
||||
CHECK_LOCK(load_lock);
|
||||
[load_lock lock];
|
||||
if (!_bundles)
|
||||
{
|
||||
_bundles = NSCreateMapTable(NSObjectMapKeyCallBacks,
|
||||
NSNonOwnedPointerMapValueCallBacks, 0);
|
||||
_releasedBundles = NSCreateMapTable(NSObjectMapKeyCallBacks,
|
||||
NSNonOwnedPointerMapValueCallBacks, 0);
|
||||
}
|
||||
[load_lock unlock];
|
||||
|
||||
_path = [path copy];
|
||||
_bundleType = (unsigned int)NSBUNDLE_BUNDLE;
|
||||
if (self == _mainBundle)
|
||||
return self;
|
||||
|
||||
if (!_bundles) {
|
||||
_bundles = [[NSMutableArray arrayWithCapacity:2] retain];
|
||||
_bundleClasses = [[NSMutableArray arrayWithCapacity:2] retain];
|
||||
}
|
||||
[_bundles addObject:self];
|
||||
[_bundleClasses addObject:[[NSMutableArray arrayWithCapacity:0] retain]];
|
||||
_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.
|
||||
*/
|
||||
- (void)dealloc
|
||||
/* 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
|
||||
{
|
||||
int pos = [_bundles indexOfObject:self];
|
||||
|
||||
if (pos >= 0) {
|
||||
[_bundleClasses removeObjectAtIndex:pos];
|
||||
[_bundles removeObjectAtIndex:pos];
|
||||
if (self == NSMapGet(_releasedBundles, _path))
|
||||
{
|
||||
[NSException raise: NSGenericException
|
||||
format: @"Bundle for path %@ released too many times", _path];
|
||||
}
|
||||
FREE_OBJECT(_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
|
||||
- (NSString *) bundlePath
|
||||
{
|
||||
return _path;
|
||||
}
|
||||
|
||||
- classNamed:(NSString *)className
|
||||
- (Class) classNamed: (NSString *)className
|
||||
{
|
||||
int j, class_count;
|
||||
NSArray *classList;
|
||||
int j;
|
||||
Class theClass = Nil;
|
||||
if (!_codeLoaded) {
|
||||
if (self != _mainBundle && ![self principalClass]) {
|
||||
[NSException raise:NSGenericException
|
||||
format:@"No classes in bundle"];
|
||||
/* NOT REACHED */
|
||||
if (!_codeLoaded)
|
||||
{
|
||||
if (self != _mainBundle && ![self principalClass])
|
||||
{
|
||||
NSLog(@"No classes in bundle");
|
||||
return Nil;
|
||||
}
|
||||
}
|
||||
|
||||
if (self == _mainBundle) {
|
||||
theClass = objc_lookup_class([className cString]);
|
||||
if (self == _mainBundle)
|
||||
{
|
||||
theClass = NSClassFromString(className);
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
j = [_bundleClasses indexOfObject: NSClassFromString(className)];
|
||||
if (j != NSNotFound)
|
||||
theClass = [_bundleClasses objectAtIndex: j];
|
||||
}
|
||||
|
||||
return theClass;
|
||||
}
|
||||
|
||||
- principalClass
|
||||
- (Class) principalClass
|
||||
{
|
||||
NSArray *classList;
|
||||
if (self == _mainBundle) {
|
||||
NSString* class_name;
|
||||
|
||||
if (_principalClass)
|
||||
return _principalClass;
|
||||
|
||||
class_name = [[self infoDictionary] objectForKey: @"NSPrincipalClass"];
|
||||
|
||||
if (self == _mainBundle)
|
||||
{
|
||||
_codeLoaded = YES;
|
||||
return nil; // the mainBundle does not have a principal class
|
||||
if (class_name)
|
||||
_principalClass = NSClassFromString(class_name);
|
||||
return _principalClass;
|
||||
}
|
||||
|
||||
if (!_codeLoaded) {
|
||||
NSString *object = bundle_object_name(_path);
|
||||
/* Link in the object file */
|
||||
_loadingBundlePos = [_bundles indexOfObject:self];
|
||||
[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)) {
|
||||
[NSException raise:NSGenericException
|
||||
format:@"Unable to load module %s", [object cString]];
|
||||
/* NOT REACHED */
|
||||
} else
|
||||
stderr, _bundle_load_callback, NULL, NULL))
|
||||
return Nil;
|
||||
_codeLoaded = YES;
|
||||
_loadingBundlePos = -1;
|
||||
_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>
|
||||
*/
|
||||
- (NSArray *) _bundleResourcePathsWithDirectory: (NSString *)bundlePath
|
||||
{
|
||||
NSString* primary;
|
||||
NSString* language;
|
||||
NSArray* languages;
|
||||
NSMutableArray* array;
|
||||
NSEnumerator* enumerate;
|
||||
|
||||
array = [NSMutableArray arrayWithCapacity: 2];
|
||||
languages = [NSUserDefaults userLanguages];
|
||||
|
||||
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)];
|
||||
|
||||
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 */
|
||||
}
|
||||
|
||||
classList = [_bundleClasses objectAtIndex:[_bundles indexOfObject:self]];
|
||||
if ([classList count])
|
||||
return [classList objectAtIndex:0];
|
||||
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;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSString *)pathForResource:(NSString *)name
|
||||
ofType:(NSString *)ext;
|
||||
- (NSArray *) pathsForResourcesOfType: (NSString *)extension
|
||||
inDirectory: (NSString *)bundlePath
|
||||
{
|
||||
return [[self class] pathForResource:name
|
||||
ofType:ext
|
||||
inDirectory: _path
|
||||
withVersion: 0];
|
||||
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 resources;
|
||||
}
|
||||
|
||||
+ (NSString *)pathForResource:(NSString *)name
|
||||
ofType:(NSString *)ext
|
||||
inDirectory:(NSString *)bundlePath
|
||||
withVersion:(int)version;
|
||||
- (NSString *) localizedStringForKey: (NSString *)key
|
||||
value: (NSString *)value
|
||||
table: (NSString *)tableName
|
||||
{
|
||||
struct stat statbuf;
|
||||
NSString *path = nil;
|
||||
NSString* new_string;
|
||||
|
||||
if (!name || [name length] == 0) {
|
||||
[NSException raise:NSInvalidArgumentException
|
||||
format:@"No resource name specified."];
|
||||
/* NOT REACHED */
|
||||
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 (_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;
|
||||
new_string = value;
|
||||
if (tableName)
|
||||
{
|
||||
NSDictionary* dict;
|
||||
dict = [[[NSDictionary alloc] initWithContentsOfFile: tableName]
|
||||
autorelease];
|
||||
new_string = [dict objectForKey: key];
|
||||
if (!new_string)
|
||||
new_string = value;
|
||||
}
|
||||
} else {
|
||||
path = bundle_resource_path(bundlePath, @"English", name, ext );
|
||||
if ( stat([path cString], &statbuf) != 0) {
|
||||
path = nil;
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!path) {
|
||||
path = bundle_resource_path(bundlePath, nil, name, ext );
|
||||
if ( stat([path cString], &statbuf) != 0) {
|
||||
path = nil;
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
return new_string;
|
||||
}
|
||||
|
||||
+ (void)stripAfterLoading:(BOOL)flag
|
||||
+ (void) stripAfterLoading: (BOOL)flag
|
||||
{
|
||||
_stripAfterLoading = flag;
|
||||
_strip_after_loading = flag;
|
||||
}
|
||||
|
||||
- (NSString *)localizedStringForKey:(NSString *)key
|
||||
value:(NSString *)value
|
||||
table:(NSString *)tableName
|
||||
- (NSString *) resourcePath
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
return 0;
|
||||
return [_path stringByAppendingPathComponent: @"Resources"];
|
||||
}
|
||||
|
||||
- (unsigned)bundleVersion
|
||||
- (NSDictionary *) infoDictionary
|
||||
{
|
||||
return _bundleVersion;
|
||||
}
|
||||
NSString* path;
|
||||
|
||||
- (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];
|
||||
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
7
aclocal.m4
vendored
|
@ -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'
|
||||
|
|
16
configure.in
16
configure.in
|
@ -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
|
||||
#--------------------------------------------------------------------
|
||||
|
|
Loading…
Reference in a new issue