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 @@
1
+{% requires "com.apple.Foundation" }
2
+
3
+This will try to locate a NSBundle at print time. If the bundle identifier
4
+matches, then the bundle will get loaded. The idea is to add available 
5
+functionality to a standalone script.
6
+
7
+requires searches in the following places.
8
+
9
+first in all already loaded bundles and frameworks
10
+
11
+in the mainBundle builtInPlugInsPath
12
+
13
+it then will search through all Library directories Frameworks and PlugIns
14
+directories.
15
+
16
+Turn on the MULLESCION_DUMP_BUNDLE_SEARCHPATH environment variable to see the
17
+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 1886
 }
1888 1887
 
1889 1888
 @end
1889
+
1890
+
1891
+static NSBundle  *search( NSFileManager *manager, NSString *identifier, NSString *path, NSString *subdir, NSString *extension)
1892
+{
1893
+   NSDirectoryEnumerator  *rover;
1894
+   NSString               *item;
1895
+   NSAutoreleasePool      *pool;
1896
+   NSBundle               *bundle;
1897
+   
1898
+   bundle = nil;
1899
+   pool = [NSAutoreleasePool new];
1900
+   if( subdir)
1901
+      path = [path stringByAppendingPathComponent:subdir];
1902
+
1903
+   if( getenv( "MULLESCION_DUMP_BUNDLE_SEARCHPATH"))
1904
+      NSLog( @"Searching %@ with %@ extension", path, extension ? extension : @"any");
1905
+   
1906
+   rover = [manager enumeratorAtPath:path];
1907
+   
1908
+   while( item = [rover nextObject])
1909
+   {
1910
+      if( ! [[[rover fileAttributes] objectForKey:NSFileType] isEqualToString:NSFileTypeDirectory])
1911
+         continue;
1912
+      [rover skipDescendents];
1913
+         
1914
+      if( extension && ! [[item pathExtension] isEqualToString:extension])
1915
+         continue;
1916
+      
1917
+      bundle = [NSBundle bundleWithPath:[path stringByAppendingPathComponent:item]];
1918
+      if( [[bundle bundleIdentifier] isEqualToString:identifier])
1919
+         break;
1920
+      bundle = nil;
1921
+   }
1922
+
1923
+   [bundle retain];
1924
+   [pool release];
1925
+   return( [bundle autorelease]);
1926
+}
1927
+
1928
+
1929
+static NSBundle  *searchForBundleInDirectory( NSFileManager *manager, NSString *identifier, NSString *path)
1930
+{
1931
+   NSBundle   *bundle;
1932
+   
1933
+   bundle = search( manager, identifier, path, @"Frameworks", @"framework");
1934
+   if( ! bundle)
1935
+      bundle = search( manager, identifier, path, @"PlugIns", nil);
1936
+   
1937
+   return( bundle);
1938
+}
1939
+
1940
+
1941
+#pragma mark -
1942
+
1943
+@implementation MulleScionRequires ( Printing)
1944
+
1945
+- (MulleScionObject *) renderInto:(id <MulleScionOutput>) s
1946
+                   localVariables:(NSMutableDictionary *) locals
1947
+                       dataSource:(id <MulleScionDataSource>) dataSource
1948
+{
1949
+   NSAutoreleasePool    *pool;
1950
+   NSBundle             *bundle;
1951
+   NSArray              *directories;
1952
+   NSString             *path;
1953
+   NSEnumerator         *rover;
1954
+   NSFileManager        *manager;
1955
+   
1956
+   TRACE_RENDER( self, s, locals, dataSource);
1957
+   
1958
+   pool = [NSAutoreleasePool new];
1959
+   
1960
+   updateLineNumber( self, locals);
1961
+   bundle = [NSBundle bundleWithIdentifier:identifier_];
1962
+   if( ! bundle)
1963
+   {
1964
+      manager = [NSFileManager defaultManager];
1965
+      bundle  = searchForBundleInDirectory( manager, identifier_, [[NSBundle mainBundle] builtInPlugInsPath]);
1966
+      if( ! bundle)
1967
+      {
1968
+         // search through frameworks
1969
+         directories = NSSearchPathForDirectoriesInDomains( NSLibraryDirectory, NSAllDomainsMask, YES);
1970
+
1971
+         rover = [directories objectEnumerator];
1972
+         while( path = [rover nextObject])
1973
+         {
1974
+            bundle = searchForBundleInDirectory( manager, identifier_, path);
1975
+            if( bundle)
1976
+               break;
1977
+         }
1978
+      }
1979
+   }
1980
+   
1981
+   if( ! [bundle load])
1982
+      MulleScionPrintingException( NSInvalidArgumentException, locals, @"could not %@ bundle with identifier \"%@\"", bundle ? @"load" : @"locate", identifier_);
1983
+   
1984
+   [pool release];
1985
+   
1986
+   return( self->next_);
1987
+}
1988
+
1989
+@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 1786
    "if",
1786 1787
    "includes",
1787 1788
    "macro",
1789
+   "requires",
1788 1790
    "set",
1789 1791
    "verbatim",
1790 1792
    "while"
... ...
@@ -1814,6 +1816,7 @@ static int   _parser_opcode_for_string( parser *p, NSString *s)
1814 1816
             if( [s isEqualToString:@"endwhile"]) return( EndwhileOpcode);
1815 1817
             if( [s isEqualToString:@"endmacro"]) return( EndmacroOpcode);
1816 1818
             if( [s isEqualToString:@"includes"]) return( IncludesOpcode);
1819
+            if( [s isEqualToString:@"requires"]) return( RequiresOpcode);
1817 1820
             if( [s isEqualToString:@"verbatim"]) return( VerbatimOpcode); break;
1818 1821
    case 9 : if( [s isEqualToString:@"endfilter"]) return( EndfilterOpcode); break;
1819 1822
    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 1962
    return( s);
1960 1963
 }
1961 1964
 
1965
+
1966
+static MulleScionObject * NS_RETURNS_RETAINED  parser_do_requires( parser *p, NSUInteger line)
1967
+{
1968
+   NSString               *identifier;
1969
+   
1970
+   parser_skip_whitespace( p);
1971
+   
1972
+   identifier = parser_do_string( p);
1973
+   if( ! [identifier length])
1974
+      parser_error( p, "a bundle identifier was expected as a quoted string");
1975
+   
1976
+   return( [MulleScionRequires newWithIdentifier:identifier
1977
+                                      lineNumber:line]);
1978
+}
1979
+
1962 1980
 /*
1963 1981
  * How Extends works.
1964 1982
  * 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 2463
          case IfOpcode       : return( parser_do_if( p, line));
2446 2464
          case IncludesOpcode : return( parser_do_includes( p, YES));
2447 2465
          case MacroOpcode    : return( parser_do_macro( p, line));
2466
+         case RequiresOpcode : return( parser_do_requires( p, line));
2448 2467
          case SetOpcode      : return( parser_do_set( p, line));
2449 2468
          case VerbatimOpcode : return( parser_do_verbatim( p, line));
2450 2469
          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