Browse code

Experimental support for requires keyword, to load bundles during printing.

Nat! authored on 17/11/2013 23:37:12
Showing 8 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,17 @@
0
+{% requires "com.apple.Foundation" }
1
+
2
+This will try to locate a NSBundle at print time. If the bundle identifier
3
+matches, then the bundle will get loaded. The idea is to add available 
4
+functionality to a standalone script.
5
+
6
+requires searches in the following places.
7
+
8
+first in all already loaded bundles and frameworks
9
+
10
+in the mainBundle builtInPlugInsPath
11
+
12
+it then will search through all Library directories Frameworks and PlugIns
13
+directories.
14
+
15
+Turn on the MULLESCION_DUMP_BUNDLE_SEARCHPATH environment variable to see the
16
+paths searched.
... ...
@@ -356,3 +356,25 @@
356 356
 }
357 357
 @end
358 358
 #endif
359
+
360
+
361
+@implementation MulleScionRequires ( NSCoding)
362
+
363
+- (id) initWithCoder:(NSCoder *) decoder
364
+{
365
+   self = [super initWithCoder:decoder];
366
+   assert( self);
367
+   
368
+   [decoder decodeValuesOfObjCTypes:"@", &identifier_];
369
+   return( self);
370
+}
371
+
372
+
373
+- (void) encodeWithCoder:(NSCoder *) encoder
374
+{
375
+   [super encodeWithCoder:encoder];
376
+   [encoder encodeValuesOfObjCTypes:"@", &identifier_];
377
+}
378
+
379
+@end
380
+
... ...
@@ -208,10 +208,9 @@ void   MulleScionRenderString( NSString *value,
208 208
                                NSMutableDictionary *locals,
209 209
                                id <MulleScionDataSource> dataSource)
210 210
 {
211
-   NSString     *s;
212
-   NSUInteger   len;
211
+   NSString   *s;
213 212
 
214
-   s   = MulleScionFilteredString( value, locals, dataSource);
213
+   s = MulleScionFilteredString( value, locals, dataSource);
215 214
    if( ! s)
216 215
       return;
217 216
 
... ...
@@ -1887,3 +1886,104 @@ static BOOL  isTrue( id value)
1887 1887
 }
1888 1888
 
1889 1889
 @end
1890
+
1891
+
1892
+static NSBundle  *search( NSFileManager *manager, NSString *identifier, NSString *path, NSString *subdir, NSString *extension)
1893
+{
1894
+   NSDirectoryEnumerator  *rover;
1895
+   NSString               *item;
1896
+   NSAutoreleasePool      *pool;
1897
+   NSBundle               *bundle;
1898
+   
1899
+   bundle = nil;
1900
+   pool = [NSAutoreleasePool new];
1901
+   if( subdir)
1902
+      path = [path stringByAppendingPathComponent:subdir];
1903
+
1904
+   if( getenv( "MULLESCION_DUMP_BUNDLE_SEARCHPATH"))
1905
+      NSLog( @"Searching %@ with %@ extension", path, extension ? extension : @"any");
1906
+   
1907
+   rover = [manager enumeratorAtPath:path];
1908
+   
1909
+   while( item = [rover nextObject])
1910
+   {
1911
+      if( ! [[[rover fileAttributes] objectForKey:NSFileType] isEqualToString:NSFileTypeDirectory])
1912
+         continue;
1913
+      [rover skipDescendents];
1914
+         
1915
+      if( extension && ! [[item pathExtension] isEqualToString:extension])
1916
+         continue;
1917
+      
1918
+      bundle = [NSBundle bundleWithPath:[path stringByAppendingPathComponent:item]];
1919
+      if( [[bundle bundleIdentifier] isEqualToString:identifier])
1920
+         break;
1921
+      bundle = nil;
1922
+   }
1923
+
1924
+   [bundle retain];
1925
+   [pool release];
1926
+   return( [bundle autorelease]);
1927
+}
1928
+
1929
+
1930
+static NSBundle  *searchForBundleInDirectory( NSFileManager *manager, NSString *identifier, NSString *path)
1931
+{
1932
+   NSBundle   *bundle;
1933
+   
1934
+   bundle = search( manager, identifier, path, @"Frameworks", @"framework");
1935
+   if( ! bundle)
1936
+      bundle = search( manager, identifier, path, @"PlugIns", nil);
1937
+   
1938
+   return( bundle);
1939
+}
1940
+
1941
+
1942
+#pragma mark -
1943
+
1944
+@implementation MulleScionRequires ( Printing)
1945
+
1946
+- (MulleScionObject *) renderInto:(id <MulleScionOutput>) s
1947
+                   localVariables:(NSMutableDictionary *) locals
1948
+                       dataSource:(id <MulleScionDataSource>) dataSource
1949
+{
1950
+   NSAutoreleasePool    *pool;
1951
+   NSBundle             *bundle;
1952
+   NSArray              *directories;
1953
+   NSString             *path;
1954
+   NSEnumerator         *rover;
1955
+   NSFileManager        *manager;
1956
+   
1957
+   TRACE_RENDER( self, s, locals, dataSource);
1958
+   
1959
+   pool = [NSAutoreleasePool new];
1960
+   
1961
+   updateLineNumber( self, locals);
1962
+   bundle = [NSBundle bundleWithIdentifier:identifier_];
1963
+   if( ! bundle)
1964
+   {
1965
+      manager = [NSFileManager defaultManager];
1966
+      bundle  = searchForBundleInDirectory( manager, identifier_, [[NSBundle mainBundle] builtInPlugInsPath]);
1967
+      if( ! bundle)
1968
+      {
1969
+         // search through frameworks
1970
+         directories = NSSearchPathForDirectoriesInDomains( NSLibraryDirectory, NSAllDomainsMask, YES);
1971
+
1972
+         rover = [directories objectEnumerator];
1973
+         while( path = [rover nextObject])
1974
+         {
1975
+            bundle = searchForBundleInDirectory( manager, identifier_, path);
1976
+            if( bundle)
1977
+               break;
1978
+         }
1979
+      }
1980
+   }
1981
+   
1982
+   if( ! [bundle load])
1983
+      MulleScionPrintingException( NSInvalidArgumentException, locals, @"could not %@ bundle with identifier \"%@\"", bundle ? @"load" : @"locate", identifier_);
1984
+   
1985
+   [pool release];
1986
+   
1987
+   return( self->next_);
1988
+}
1989
+
1990
+@end
... ...
@@ -456,3 +456,16 @@ typedef enum
456 456
 
457 457
 @end
458 458
 
459
+
460
+@interface MulleScionRequires : MulleScionCommand
461
+{
462
+   NSString   *identifier_;
463
+}
464
+
465
++ (id) newWithIdentifier:(NSString *) identifier
466
+              lineNumber:(NSUInteger) nr;
467
+
468
+- (NSString *) identifier;
469
+
470
+@end
471
+
... ...
@@ -1162,3 +1162,34 @@ static id   newMulleScionValueObject( Class self, id value, NSUInteger nr)
1162 1162
 
1163 1163
 @end
1164 1164
 
1165
+
1166
+#pragma mark -
1167
+
1168
+@implementation MulleScionRequires
1169
+
1170
++ (id) newWithIdentifier:(NSString *) identifier
1171
+              lineNumber:(NSUInteger) nr;
1172
+{
1173
+   MulleScionRequires   *p;
1174
+   
1175
+   NSParameterAssert( [identifier isKindOfClass:[NSString class]]);
1176
+   
1177
+   p = [super newWithLineNumber:nr];
1178
+   p->identifier_ = [identifier copy];
1179
+   
1180
+   return( p);
1181
+}
1182
+
1183
+- (void) dealloc
1184
+{
1185
+   [identifier_ release];
1186
+   [super dealloc];
1187
+}
1188
+
1189
+- (NSString *) identifier
1190
+{
1191
+   return( identifier_);
1192
+}
1193
+
1194
+@end
1195
+
... ...
@@ -1760,6 +1760,7 @@ typedef enum
1760 1760
    IfOpcode,
1761 1761
    IncludesOpcode,
1762 1762
    MacroOpcode,
1763
+   RequiresOpcode,
1763 1764
    SetOpcode,
1764 1765
    VerbatimOpcode,
1765 1766
    WhileOpcode
... ...
@@ -1785,6 +1786,7 @@ static char   *mnemonics[] =
1785 1785
    "if",
1786 1786
    "includes",
1787 1787
    "macro",
1788
+   "requires",
1788 1789
    "set",
1789 1790
    "verbatim",
1790 1791
    "while"
... ...
@@ -1814,6 +1816,7 @@ static int   _parser_opcode_for_string( parser *p, NSString *s)
1814 1814
             if( [s isEqualToString:@"endwhile"]) return( EndwhileOpcode);
1815 1815
             if( [s isEqualToString:@"endmacro"]) return( EndmacroOpcode);
1816 1816
             if( [s isEqualToString:@"includes"]) return( IncludesOpcode);
1817
+            if( [s isEqualToString:@"requires"]) return( RequiresOpcode);
1817 1818
             if( [s isEqualToString:@"verbatim"]) return( VerbatimOpcode); break;
1818 1819
    case 9 : if( [s isEqualToString:@"endfilter"]) return( EndfilterOpcode); break;
1819 1820
    case 11: if( [s isEqualToString:@"endverbatim"]) return( EndverbatimOpcode); break;
... ...
@@ -1959,6 +1962,21 @@ static NSString  * NS_RETURNS_RETAINED parser_remove_hashbang_from_string_if_des
1959 1959
    return( s);
1960 1960
 }
1961 1961
 
1962
+
1963
+static MulleScionObject * NS_RETURNS_RETAINED  parser_do_requires( parser *p, NSUInteger line)
1964
+{
1965
+   NSString               *identifier;
1966
+   
1967
+   parser_skip_whitespace( p);
1968
+   
1969
+   identifier = parser_do_string( p);
1970
+   if( ! [identifier length])
1971
+      parser_error( p, "a bundle identifier was expected as a quoted string");
1972
+   
1973
+   return( [MulleScionRequires newWithIdentifier:identifier
1974
+                                      lineNumber:line]);
1975
+}
1976
+
1962 1977
 /*
1963 1978
  * How Extends works.
1964 1979
  * when you read a file, the parser collects statement for the template.
... ...
@@ -2445,6 +2463,7 @@ static MulleScionObject * NS_RETURNS_RETAINED  parser_do_command( parser *p)
2445 2445
          case IfOpcode       : return( parser_do_if( p, line));
2446 2446
          case IncludesOpcode : return( parser_do_includes( p, YES));
2447 2447
          case MacroOpcode    : return( parser_do_macro( p, line));
2448
+         case RequiresOpcode : return( parser_do_requires( p, line));
2448 2449
          case SetOpcode      : return( parser_do_set( p, line));
2449 2450
          case VerbatimOpcode : return( parser_do_verbatim( p, line));
2450 2451
          case WhileOpcode    : return( parser_do_while( p, line));
... ...
@@ -36,7 +36,7 @@
36 36
 
37 37
 
38 38
 #import <Foundation/Foundation.h>
39
-#import "MulleScionObjectModel+Printing.h"
39
+#import "MulleScionOutputProtocol.h"
40 40
 
41 41
 
42 42
 @class MulleScionTemplate;
... ...
@@ -36,7 +36,9 @@
36 36
 
37 37
 
38 38
 #import "MulleScionPrinter.h"
39
+
39 40
 #import "MulleScionObjectModel.h"
41
+#import "MulleScionObjectModel+Printing.h"
40 42
 
41 43
 
42 44