Browse code

Added some historic projects to the utilities. Fix is for ancient property lists, that apple refuses to load. The hack is an attempt to change values inside a plist.

Nat! authored on 11-02-2013 23:39:39
Showing 20 changed files
... ...
@@ -4,10 +4,18 @@
4 4
 all:
5 5
 	( cd mulle-plist-from-files; make )	
6 6
 	( cd mulle-plist-compress; make )	
7
+	( cd mulle-plist-fix; make )
8
+	( cd mulle-plist-hack; make )	
9
+
7 10
 clean:
8 11
 	( cd mulle-plist-from-files; make clean )	
9 12
 	( cd mulle-plist-compress; make clean )	
13
+	( cd mulle-plist-fix; make clean )
14
+	( cd mulle-plist-hack; make clean )	
15
+
10 16
 install:
11 17
 	( cd mulle-plist-from-files; make install )	
12 18
 	( cd mulle-plist-compress; make install )	
19
+	( cd mulle-plist-fix; make install )
20
+	( cd mulle-plist-hack; make install )	
13 21
 
... ...
@@ -6,26 +6,32 @@ Just say *sudo make install* and the files will end up in /usr/local.
6 6
 man pages
7 7
 =========
8 8
 NAME
9
+
9 10
      mulle‐plist‐from‐files — Combine multiple files into a single property
10 11
      list
11 12
 
12 13
 SYNOPSIS
14
+
13 15
      mulle‐plist‐from‐files file [file ...]
14 16
 
15 17
 DESCRIPTION
18
+
16 19
      Reads, possibly recursively, a bunch of files and creates a property
17 20
      plist from them. This property list is then written to standard output.
18 21
 
19 22
 ----------------------------------------------------------------------------
20 23
 
21 24
 NAME
25
+
22 26
      mulle‐plist‐compress — Compress and format a property list for inclusion
23 27
      in C code.
24 28
 
25 29
 SYNOPSIS
30
+
26 31
      mulle‐plist‐compress [−s style] [−c compression] [−f format]
27 32
 
28 33
 DESCRIPTION
34
+
29 35
      Reads a property plist from standard input and writes it’s result to
30 36
      standard output. The property list is by default space optimized and
31 37
      escaped to be used in a C‐String. The options are processed in the order
... ...
@@ -60,6 +66,7 @@ DESCRIPTION
60 66
               char C‐Array.
61 67
 
62 68
 ENVIRONMENT
69
+
63 70
      MULLE_PLIST_HEADER  The contents of this environment variable are
64 71
                          prepended to the output.
65 72
 
... ...
@@ -15,4 +15,4 @@ install:	all
15 15
 	install mulle-plist-compress.8 $(MANDST)
16 16
 
17 17
 clean:
18
-	rm *.o mulle-plist-compress
18
+	- rm *.o mulle-plist-compress
19 19
new file mode 100755
... ...
@@ -0,0 +1,18 @@
1
+#
2
+# old skool Makefile by Nat!
3
+#
4
+DST=/usr/local/bin
5
+MANDST=/usr/local/share/man/man8
6
+
7
+
8
+all:	mulle-plist-fix
9
+
10
+mulle-plist-fix:	main.o
11
+	gcc -o mulle-plist-fix $+ -framework Foundation
12
+
13
+install:	all
14
+	install mulle-plist-fix $(DST)
15
+	install mulle-plist-fix.8 $(MANDST)
16
+
17
+clean:
18
+	- rm *.o mulle-plist-fix
0 19
new file mode 100644
... ...
@@ -0,0 +1,319 @@
1
+//
2
+//  main.m
3
+//  mulle-plist-fix
4
+//
5
+//  Created by Nat! on 11.02.13.
6
+//  Copyright (c) 2013 Nat!. All rights reserved.
7
+//
8
+
9
+#import <Foundation/Foundation.h>
10
+#include <ctype.h>
11
+
12
+
13
+/* this is really very, very old cold, that has been resurrected */
14
+
15
+#define TRY_VALIANTLY_TO_CONVERT  0
16
+
17
+
18
+
19
+static inline int   iswhite( int c)
20
+{
21
+   return( c == ' ' || c == '\n' || c == '\r' || c == '\t');
22
+}
23
+
24
+
25
+static id  _parse_object( char **s, NSUInteger *len);
26
+
27
+static int   skip_white( char **s, NSUInteger *len)
28
+{
29
+   while( *len)
30
+   {
31
+      if( ! iswhite( **s))
32
+         return( 0);
33
+      ++*s;
34
+      --*len;
35
+   }
36
+   return( -1);
37
+}
38
+
39
+/*
40
+ static NSString  *slurp_identifier( char **s, unsigned int *len)
41
+ {
42
+ int    c;
43
+ char   *memo;
44
+ 
45
+ memo = *s;
46
+ while( *len)
47
+ {
48
+ c = **s;
49
+ if( ! (isalnum( c) || c == '_'))
50
+ break;
51
+ ++*s;
52
+ --*len;
53
+ }
54
+ return( [NSString stringWithCString:memo
55
+ length:*s - memo]);
56
+ }
57
+ */
58
+
59
+static id   _parse_value( char **s, NSUInteger *len)
60
+{
61
+   int        c;
62
+   char       *memo;
63
+   int        quoted;
64
+   NSString   *string;
65
+   
66
+   quoted = **s == '"';
67
+   if( quoted)
68
+   {
69
+      ++*s;
70
+      --*len;
71
+   }
72
+   
73
+   memo = *s;
74
+   while( *len)
75
+   {
76
+      c = **s;
77
+      if( quoted)
78
+      {
79
+         if( c == '"')
80
+            break;
81
+      }
82
+      else
83
+      {
84
+         if( iswhite( c))
85
+            break;
86
+      }
87
+      ++*s;
88
+      --*len;
89
+   }
90
+   
91
+   
92
+   string = [NSString stringWithCString:memo
93
+                                 length:*s - memo];
94
+   if( quoted)
95
+   {
96
+      ++*s;
97
+      --*len;
98
+   }
99
+   
100
+   // brute force, try NSCalendarDate first
101
+   // then NSDecimalNumber Number
102
+   // finally stay as NSString
103
+#if TRY_VALIANTLY_TO_CONVERT
104
+   if( isdigit( *memo))
105
+   {
106
+      if( value = [NSDecimalNumber decimalNumberWithString:string])
107
+         return( value);
108
+   }
109
+   
110
+   if( value = [NSCalendarDate dateWithString:string])
111
+      return( value);
112
+#endif
113
+   
114
+   return( string);
115
+}
116
+
117
+
118
+static int   _parse_key_value_into_dictionary( char **s, NSUInteger *len, NSMutableDictionary *dictionary)
119
+{
120
+   id   key;
121
+   id   value;
122
+   
123
+   
124
+   key = _parse_value( s, len);
125
+   if( ! key)
126
+      return( -1);
127
+   
128
+   if( skip_white( s, len))
129
+   {
130
+      NSLog( @"Malformed key value pair, only key %@ present", key);
131
+      return( -2);
132
+   }
133
+   
134
+   if( **s != '=')
135
+   {
136
+      NSLog( @"Malformed key value pair, = missing after key %@", key);
137
+      return( -3);
138
+   }
139
+   
140
+   ++*s;
141
+   --*len;
142
+   
143
+   if( skip_white( s, len))
144
+   {
145
+      NSLog( @"Malformed key value pair, missing value after key %@", key);
146
+      return( -4);
147
+   }
148
+   
149
+   value = _parse_object( s, len);
150
+   if( ! value)
151
+   {
152
+      NSLog( @"Malformed key value pair, missing value after key %@", key);
153
+      return( -4);
154
+   }
155
+   [dictionary setObject:value
156
+                  forKey:key];
157
+   
158
+   return( 0);
159
+}
160
+
161
+
162
+static id   _parse_array( char **s, NSUInteger *len)
163
+{
164
+   NSMutableArray   *array;
165
+   id               parsed;
166
+   
167
+   array = [NSMutableArray array];
168
+   while( *len)
169
+   {
170
+      if( skip_white( s, len))
171
+         return( nil);
172
+      
173
+      if( **s == ',')
174
+      {
175
+         ++*s;
176
+         --*len;
177
+         continue;
178
+      }
179
+      
180
+      if( **s == ')')
181
+      {
182
+         ++*s;
183
+         --*len;
184
+         return( array);
185
+      }
186
+      
187
+      parsed = _parse_object( s, len);
188
+      if( ! parsed)
189
+         break;
190
+      [array addObject:parsed];
191
+   }
192
+   NSLog( @"Array truncated");
193
+   return( nil);
194
+}
195
+
196
+
197
+static id   _parse_dictionary( char **s, NSUInteger *len)
198
+{
199
+   NSMutableDictionary   *dictionary;
200
+   
201
+   dictionary = [NSMutableDictionary dictionary];
202
+   while( *len)
203
+   {
204
+      if( skip_white( s, len))
205
+         break;
206
+      
207
+      if( **s == ';')
208
+      {
209
+         ++*s;
210
+         --*len;
211
+         continue;
212
+      }
213
+      
214
+      if( **s == '}')
215
+      {
216
+         ++*s;
217
+         --*len;
218
+         return( dictionary);
219
+      }
220
+      
221
+      if( _parse_key_value_into_dictionary( s, len, dictionary) < 0)
222
+         return( nil);
223
+   }
224
+   NSLog( @"Dictionary truncated");
225
+   return( nil);
226
+}
227
+
228
+
229
+static id  _parse_object( char **s, NSUInteger *len)
230
+{
231
+   if( skip_white( s, len))
232
+      return( nil);
233
+   
234
+   switch( **s)
235
+   {
236
+      case '{' :
237
+         ++*s;
238
+         --*len;
239
+         return( _parse_dictionary( s, len));
240
+         
241
+      case '(' :
242
+         ++*s;
243
+         --*len;
244
+         return( _parse_array( s, len));
245
+   }
246
+   return( _parse_value( s, len));
247
+}
248
+
249
+
250
+static id    parse_old_plist( NSData *data)
251
+{
252
+   char         *s;
253
+   NSUInteger   len;
254
+   
255
+   s   = (char *) [data bytes];
256
+   len = [data length];
257
+   return( _parse_object( &s, &len));
258
+}
259
+
260
+
261
+static NSStringEncoding   encodings[] =
262
+{
263
+   NSUTF8StringEncoding,
264
+   NSUTF16StringEncoding,
265
+   NSUTF16BigEndianStringEncoding,
266
+   NSUTF16LittleEndianStringEncoding,
267
+   NSMacOSRomanStringEncoding,
268
+   0
269
+};
270
+
271
+
272
+int main (int argc, const char * argv[])
273
+{
274
+   NSAutoreleasePool      *pool;
275
+   NSData                 *data;
276
+   NSPropertyListFormat   format;
277
+   NSString               *error;
278
+   NSString               *s;
279
+   id                     list;
280
+   NSStringEncoding       *p_encoding;
281
+   NSFileHandle           *handle;
282
+   
283
+   pool   = [NSAutoreleasePool new];
284
+   handle = [NSFileHandle fileHandleWithStandardInput];
285
+   data   = [handle readDataToEndOfFile];
286
+   
287
+   if( ! [data length])
288
+   {
289
+      fprintf( stderr, "No data to convert\n");
290
+      return( -1);
291
+   }
292
+   
293
+   list = [NSPropertyListSerialization propertyListFromData:data
294
+                                           mutabilityOption:NSPropertyListImmutable
295
+                                                     format:&format
296
+                                           errorDescription:&error];
297
+   if( ! list)
298
+   {
299
+      for( p_encoding = encodings; *p_encoding; p_encoding++)
300
+      {
301
+         s = [[NSString alloc] initWithData:data
302
+                                   encoding:*p_encoding];
303
+         
304
+         list = parse_old_plist( [s dataUsingEncoding:NSUTF8StringEncoding]);
305
+         [s release];
306
+         if( list)
307
+            break;
308
+      }
309
+      
310
+      if( ! list)
311
+      {
312
+         fprintf( stderr, "Conversion of property list failed: %s\n", [error cString]);
313
+         return( -1);;
314
+      }
315
+   }
316
+
317
+   printf( "%s", [[list description] cString]);
318
+   return( 0);
319
+}
0 320
new file mode 100644
... ...
@@ -0,0 +1,54 @@
1
+.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples.
2
+.\"See Also:
3
+.\"man mdoc.samples for a complete listing of options
4
+.\"man mdoc for the short list of editing options
5
+.\"/usr/share/misc/mdoc.template
6
+.Dd 7/2/13               \" DATE 
7
+.Dt mulle-plist-fix 8      \" Program name and manual section number 
8
+.Os Darwin
9
+.Sh NAME                 \" Section Header - required - don't modify 
10
+.Nm mulle-plist-fix
11
+.\" The following lines are read in generating the apropos(man -k) database. Use only key
12
+.\" words here as the database is built based on the words here and in the .ND line. 
13
+.\" Use .Nm macro to designate other names for the documented program.
14
+.Nd Fix ancient property list files
15
+.Sh SYNOPSIS             \" Section Header - required - don't modify
16
+.Nm
17
+.Ar file                \" [file]
18
+.Op Ar                   \" [file ...]
19
+.Sh DESCRIPTION          \" Section Header - required - don't modify
20
+Reads very, very old 
21
+.Em property list
22
+format from standard input and
23
+a more modern 
24
+.Em property plist
25
+format is then then written to standard output.
26
+.Pp
27
+.\" .It Ev ENV_VAR_1
28
+.\" Description of ENV_VAR_1
29
+.\" .It Ev ENV_VAR_2
30
+.\" Description of ENV_VAR_2
31
+.\" .El                      
32
+.\".Sh FILES                \" File used or created by the topic of the man page
33
+.\".Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact
34
+.\".It Pa /usr/share/file_name
35
+.\"FILE_1 description
36
+.\".It Pa /Users/joeuser/Library/really_long_file_name
37
+.\"FILE_2 description
38
+.\".El                      \" Ends the list
39
+.\" .Sh DIAGNOSTICS       \" May not be needed
40
+.\" .Bl -diag
41
+.\" .It Diagnostic Tag
42
+.\" Diagnostic informtion here.
43
+.\" .It Diagnostic Tag
44
+.\" Diagnostic informtion here.
45
+.\" .El
46
+.Sh SEE ALSO 
47
+.\" List links in ascending order by section, alphabetically within a section.
48
+.\" Please do not reference files that do not exist without filing a bug report
49
+.Xr mulle-plist-fix 8
50
+.\" .Sh BUGS              \" Document known, unremedied bugs 
51
+.\" .Sh HISTORY           \" Document history if command behaves in a unique manner
52
+.Sh AUTHOR
53
+Coded by Nat! 2013, Mulle kybernetiK. www.mulle-kybernetik.com. The lastest 
54
+version should be available on github. http://github.com/mulle-nat/mulle-plist-utilities
0 55
\ No newline at end of file
... ...
@@ -15,4 +15,4 @@ install:	all
15 15
 	install mulle-plist-from-files.8 $(MANDST)
16 16
 
17 17
 clean:
18
-	rm *.o mulle-plist-from-files
18
+	- rm *.o mulle-plist-from-files
... ...
@@ -45,7 +45,7 @@ is then written to standard output.
45 45
 .Sh SEE ALSO 
46 46
 .\" List links in ascending order by section, alphabetically within a section.
47 47
 .\" Please do not reference files that do not exist without filing a bug report
48
-.Xr mulle-plist-compress 8
48
+.Xr mulle-plist-from-files 8
49 49
 .\" .Sh BUGS              \" Document known, unremedied bugs 
50 50
 .\" .Sh HISTORY           \" Document history if command behaves in a unique manner
51 51
 .Sh AUTHOR
52 52
new file mode 100755
... ...
@@ -0,0 +1,18 @@
1
+#
2
+# old skool Makefile by Nat!
3
+#
4
+DST=/usr/local/bin
5
+MANDST=/usr/local/share/man/man8
6
+
7
+
8
+all:	mulle-plist-hack
9
+
10
+mulle-plist-hack:	main.o NSDictionary+PListOldSkool.o  NSObject+PListOldSkool.o NSPropertyListSerialization+MullePlistWriter.o NSPropertyListSerialization+MullePlistReader.o
11
+	gcc -o mulle-plist-hack $+ -framework Foundation
12
+
13
+install:	all
14
+	install mulle-plist-hack $(DST)
15
+	install mulle-plist-hack.8 $(MANDST)
16
+
17
+clean:
18
+	- rm *.o mulle-plist-hack
0 19
new file mode 100644
... ...
@@ -0,0 +1,21 @@
1
+// ---------------------------------------------------------------------
2
+// Copyright (C) 2002 by Codeon GmbH. All rights reserved.
3
+//
4
+// Autor: nat
5
+//
6
+// $Id: NSDictionary+PListOldSkool.h,v 1.1 2002/09/09 10:42:11 nat Exp $
7
+//
8
+// $Log: NSDictionary+PListOldSkool.h,v $
9
+// Revision 1.1  2002/09/09 10:42:11  nat
10
+// OldSkool PList writing for Solaris compatibility
11
+//
12
+//
13
+// ---------------------------------------------------------------------
14
+#import "NSObject+PListOldSkool.h"
15
+
16
+
17
+@interface NSDictionary ( PListOldSkool)
18
+
19
+- (BOOL) writeOldSkoolFormatToFileHandle:(NSFileHandle *) handle;
20
+
21
+@end
0 22
new file mode 100644
... ...
@@ -0,0 +1,68 @@
1
+// ---------------------------------------------------------------------
2
+// Copyright (C) 2002 by Codeon GmbH. All rights reserved.
3
+//
4
+// Autor: nat
5
+//
6
+// $Id: NSDictionary+PListOldSkool.m,v 1.1 2002/09/09 10:42:11 nat Exp $
7
+//
8
+// $Log: NSDictionary+PListOldSkool.m,v $
9
+// Revision 1.1  2002/09/09 10:42:11  nat
10
+// OldSkool PList writing for Solaris compatibility
11
+//
12
+//
13
+// ---------------------------------------------------------------------
14
+#import "NSDictionary+PListOldSkool.h"
15
+
16
+
17
+@implementation NSDictionary ( PListOldSkool)
18
+
19
+- (NSString *) plistDescription:(NSString *) prefix
20
+{
21
+   NSMutableString   *string;
22
+   NSEnumerator      *rover;
23
+   id                key;
24
+   NSString          *prefix2;
25
+   
26
+   prefix2 = [@"   " stringByAppendingString:prefix];
27
+   
28
+   string = [NSMutableString string];
29
+   
30
+   if( [self count] > 0)
31
+   {
32
+      [string appendString:@"{\n"];
33
+      
34
+      rover = [[[self allKeys] sortedArrayUsingSelector:@selector( compare:)] objectEnumerator];
35
+      key = [rover nextObject];
36
+      do
37
+      {
38
+         [string appendString:prefix2];
39
+         [string appendString:key];
40
+         [string appendString:@" = "];
41
+         [string appendString:[[self objectForKey:key] plistDescription:prefix2]];
42
+         key = [rover nextObject];
43
+         if( key)
44
+            [string appendString:@";"];
45
+         [string appendString:@"\n"];
46
+      }
47
+      while( key);
48
+      [string appendString:prefix];
49
+      [string appendString:@"}"];
50
+   }
51
+   else
52
+      [string appendString:@"{}"];
53
+   return( string);
54
+}
55
+
56
+
57
+- (BOOL) writeOldSkoolFormatToFileHandle:(NSFileHandle *) handle
58
+{
59
+   NSString  *string;
60
+   NSData    *data;
61
+   
62
+   string = [self plistDescription:@""];
63
+   data   = [string dataUsingEncoding:NSISOLatin1StringEncoding];
64
+   [handle writeData:data];
65
+   return( YES);
66
+}
67
+
68
+@end
0 69
\ No newline at end of file
1 70
new file mode 100644
... ...
@@ -0,0 +1,22 @@
1
+// ---------------------------------------------------------------------
2
+// Copyright (C) 2002 by Codeon GmbH. All rights reserved.
3
+//
4
+// Autor: nat
5
+//
6
+// $Id: NSObject+PListOldSkool.h,v 1.1 2002/09/09 10:42:11 nat Exp $
7
+//
8
+// $Log: NSObject+PListOldSkool.h,v $
9
+// Revision 1.1  2002/09/09 10:42:11  nat
10
+// OldSkool PList writing for Solaris compatibility
11
+//
12
+//
13
+// ---------------------------------------------------------------------
14
+#import <Foundation/Foundation.h>
15
+
16
+
17
+@interface NSObject( PListOldSkool)
18
+
19
+- (NSString *) plistDescription:(NSString *) prefix;
20
+
21
+@end
22
+
0 23
new file mode 100644
... ...
@@ -0,0 +1,78 @@
1
+// ---------------------------------------------------------------------
2
+// Copyright (C) 2002 by Codeon GmbH. All rights reserved.
3
+//
4
+// Autor: nat
5
+//
6
+// $Id: NSObject+PListOldSkool.m,v 1.1 2002/09/09 10:42:12 nat Exp $
7
+//
8
+// $Log: NSObject+PListOldSkool.m,v $
9
+// Revision 1.1  2002/09/09 10:42:12  nat
10
+// OldSkool PList writing for Solaris compatibility
11
+//
12
+//
13
+// ---------------------------------------------------------------------
14
+#import "NSObject+PListOldSkool.h"
15
+
16
+
17
+@implementation NSObject( PListOldSkool)
18
+
19
+- (NSString *) plistDescription:(NSString *) prefix
20
+{
21
+   return( [self description]);
22
+}
23
+
24
+@end
25
+
26
+
27
+@implementation NSString ( PListOldSkool)
28
+
29
+- (NSString *) plistDescription:(NSString *) prefix
30
+{
31
+   return( [NSString stringWithFormat:@"\"%@\"", self]);
32
+}
33
+
34
+@end
35
+
36
+
37
+@implementation NSArray ( PListOldSkool)
38
+
39
+- (NSString *) plistDescription:(NSString *) prefix
40
+{
41
+   NSMutableString   *string;
42
+   NSEnumerator      *rover;
43
+   id                object;
44
+   NSString          *prefix2;
45
+   
46
+   prefix2 = [@"   " stringByAppendingString:prefix];
47
+   
48
+   string = [NSMutableString string];
49
+   
50
+   if( [self count] > 0)
51
+   {
52
+      [string appendString:@"(\n"];
53
+      
54
+      rover = [self objectEnumerator];
55
+      object = [rover nextObject];
56
+      do
57
+      {
58
+         [string appendString:prefix2];
59
+         [string appendString:[object plistDescription:prefix2]];
60
+         object = [rover nextObject];
61
+         if( object)
62
+            [string appendString:@","];
63
+         [string appendString:@"\n"];
64
+      }
65
+      while( object);
66
+      [string appendString:prefix];
67
+      [string appendString:@")"];
68
+   }
69
+   else
70
+      [string appendString:@"()"];
71
+   
72
+   return( string);
73
+}      
74
+
75
+@end
76
+
77
+
78
+
0 79
new file mode 100644
... ...
@@ -0,0 +1,20 @@
1
+/*
2
+ *  NSPropertyListSerialization+MullePlist.h
3
+ *  plisthack
4
+ *
5
+ *  Created by Nat! on 09.06.05.
6
+ *  Copyright 2005 __MyCompanyName__. All rights reserved.
7
+ *
8
+ */
9
+#include <Foundation/Foundation.h>
10
+
11
+
12
+@interface NSPropertyListSerialization ( MullePlistReader)
13
+
14
++ (id) mullePropertyListFromData:(NSData *) data
15
+                mutabilityOption:(NSPropertyListMutabilityOptions) option 
16
+                          format:(NSPropertyListFormat *) format
17
+                errorDescription:(NSString **) error;
18
+
19
+
20
+@end
0 21
new file mode 100644
... ...
@@ -0,0 +1,279 @@
1
+#import "NSPropertyListSerialization+MullePlistReader.h"
2
+#include <ctype.h>
3
+
4
+
5
+#define TRY_VALIANTLY_TO_CONVERT  0
6
+
7
+
8
+@implementation NSPropertyListSerialization ( MullePlistReader)
9
+
10
+
11
+static inline int   iswhite( int c)
12
+{
13
+   return( c == ' ' || c == '\n' || c == '\r' || c == '\t');
14
+}
15
+
16
+
17
+static id  _parse_object( char **s, unsigned int *len);
18
+
19
+static int   skip_white( char **s, unsigned int *len)
20
+{
21
+    while( *len)
22
+    {
23
+        if( ! iswhite( **s))
24
+            return( 0);
25
+        ++*s;
26
+        --*len;
27
+    }
28
+    return( -1);
29
+}
30
+
31
+/*
32
+static NSString  *slurp_identifier( char **s, unsigned int *len)
33
+{
34
+    int    c;
35
+    char   *memo;
36
+
37
+    memo = *s;
38
+    while( *len)
39
+    {
40
+        c = **s;
41
+        if( ! (isalnum( c) || c == '_'))
42
+           break;
43
+        ++*s;
44
+        --*len;
45
+    }
46
+    return( [NSString stringWithCString:memo
47
+                                 length:*s - memo]);
48
+}
49
+*/
50
+
51
+static id   _parse_value( char **s, unsigned int *len)
52
+{
53
+    int        c;
54
+    char       *memo;
55
+    int        quoted;
56
+    NSString   *string;
57
+    
58
+    quoted = **s == '"';
59
+    if( quoted)
60
+    {
61
+        ++*s;
62
+        --*len;
63
+    }
64
+    
65
+    memo = *s;
66
+    while( *len)
67
+    {
68
+        c = **s;
69
+        if( quoted)
70
+        {
71
+            if( c == '"')
72
+                break;
73
+        }
74
+        else
75
+        {
76
+            if( iswhite( c) || c == ',' || c == ';')
77
+                break;
78
+        }
79
+        ++*s;
80
+        --*len;
81
+    }
82
+    
83
+
84
+    string = [NSString stringWithCString:memo
85
+                                  length:*s - memo];
86
+    if( quoted)
87
+    {
88
+        ++*s;
89
+        --*len;
90
+    }
91
+
92
+// brute force, try NSCalendarDate first    
93
+// then NSDecimalNumber Number 
94
+// finally stay as NSString
95
+#if TRY_VALIANTLY_TO_CONVERT
96
+    if( isdigit( *memo))
97
+    {
98
+        if( value = [NSDecimalNumber decimalNumberWithString:string])
99
+            return( value);
100
+    }
101
+    
102
+    if( value = [NSCalendarDate dateWithString:string])
103
+        return( value);
104
+#endif
105
+        
106
+    return( string);
107
+}
108
+
109
+
110
+static int   _parse_key_value_into_dictionary( char **s, unsigned int *len, NSMutableDictionary *dictionary)
111
+{
112
+    id   key;
113
+    id   value;
114
+    
115
+    
116
+    key = _parse_value( s, len);
117
+    if( ! key)
118
+        return( -1);
119
+    
120
+    if( skip_white( s, len))
121
+    {
122
+       NSLog( @"Malformed key value pair, only key %@ present", key);
123
+       return( -2);
124
+    }
125
+
126
+    if( **s != '=')
127
+    {
128
+       NSLog( @"Malformed key value pair, = missing after key %@", key);
129
+       return( -3);
130
+    }
131
+    
132
+    ++*s;
133
+    --*len;
134
+    
135
+    if( skip_white( s, len))
136
+    {
137
+       NSLog( @"Malformed key value pair, missing value after key %@", key);
138
+       return( -4);
139
+    }
140
+   
141
+    value = _parse_object( s, len);
142
+    if( ! value)
143
+    {
144
+       NSLog( @"Malformed key value pair, missing value after key %@", key);
145
+       return( -4);
146
+    }
147
+    [dictionary setObject:value
148
+                   forKey:key];
149
+                   
150
+    return( 0);
151
+}
152
+
153
+
154
+static id   _parse_array( char **s, unsigned int *len)
155
+{
156
+    NSMutableArray   *array;
157
+    id               parsed;
158
+    
159
+    array = [NSMutableArray array];
160
+    while( *len)
161
+    {
162
+        if( skip_white( s, len))
163
+            return( nil);
164
+    
165
+        if( **s == ',')
166
+        {
167
+           ++*s;
168
+           --*len;
169
+           continue;
170
+        }
171
+
172
+        if( **s == ')')
173
+        {
174
+           ++*s;
175
+           --*len;
176
+           return( array);
177
+        }
178
+
179
+        parsed = _parse_object( s, len);
180
+        if( ! parsed)
181
+            break;
182
+        [array addObject:parsed];
183
+    }
184
+    NSLog( @"Array truncated");
185
+    return( nil);
186
+}
187
+
188
+
189
+static id   _parse_dictionary( char **s, unsigned int *len)
190
+{
191
+    NSMutableDictionary   *dictionary;
192
+    
193
+    dictionary = [NSMutableDictionary dictionary];
194
+    while( *len)
195
+    {
196
+        if( skip_white( s, len))
197
+            break;
198
+                
199
+        if( **s == ';')
200
+        {
201
+           ++*s;
202
+           --*len;
203
+           continue;
204
+        }
205
+        
206
+        if( **s == '}')
207
+        {
208
+           ++*s;
209
+           --*len;
210
+           return( dictionary);
211
+        }
212
+        
213
+        if( _parse_key_value_into_dictionary( s, len, dictionary) < 0)
214
+            return( nil);
215
+    }
216
+    NSLog( @"Dictionary truncated");
217
+    return( nil);
218
+}
219
+
220
+
221
+static id  _parse_object( char **s, unsigned int *len)
222
+{
223
+    if( skip_white( s, len))
224
+        return( nil);
225
+        
226
+    switch( **s)
227
+    {
228
+    case '{' :
229
+        ++*s;
230
+        --*len;
231
+        return( _parse_dictionary( s, len));
232
+
233
+    case '(' :
234
+        ++*s;
235
+        --*len;
236
+        return( _parse_array( s, len));
237
+    }
238
+    return( _parse_value( s, len));
239
+}
240
+
241
+
242
+static id  parse_old_plist( NSData *data)
243
+{
244
+   char         *s;
245
+   NSUInteger   len;
246
+   
247
+   s   = (char *) [data bytes];
248
+   len = [data length];
249
+   return( _parse_object( &s, &len));
250
+}
251
+
252
+
253
++ (id) mullePropertyListFromData:(NSData *) data
254
+                mutabilityOption:(NSPropertyListMutabilityOptions) option 
255
+                          format:(NSPropertyListFormat *) format
256
+                errorDescription:(NSString **) error
257
+{
258
+   id   list;
259
+   
260
+   list = [NSPropertyListSerialization propertyListFromData:data
261
+                                           mutabilityOption:option 
262
+                                                     format:format 
263
+                                           errorDescription:error];
264
+   if( ! list)
265
+   {
266
+      // can only do immutable containers
267
+      if( option == NSPropertyListImmutable)
268
+      {
269
+         list = parse_old_plist( data);
270
+         if( list)
271
+            *format = NSPropertyListOpenStepFormat;
272
+      }
273
+      // fall through, if this is nil then Foundation
274
+      // will provide the error 
275
+   }
276
+   return( list);
277
+}
278
+
279
+@end
0 280
new file mode 100644
... ...
@@ -0,0 +1,13 @@
1
+#import <Foundation/Foundation.h>
2
+
3
+
4
+extern NSString   *MullePlistPrinterException;
5
+
6
+
7
+@interface NSPropertyListSerialization ( MullePlistWriter)
8
+
9
++ (id) mulleDataFromPropertyList:(id) plist
10
+                          format:(NSPropertyListFormat) format
11
+                errorDescription:(NSString **) error;
12
+
13
+@end
0 14
new file mode 100644
... ...
@@ -0,0 +1,319 @@
1
+#import "NSPropertyListSerialization+MullePlistWriter.h"
2
+
3
+
4
+NSString *MullePlistWriterException = @"MullePlistWriterException";
5
+
6
+
7
+@interface NSObject ( MullePlistWriter)
8
+
9
+- (void) mullePlistWriteIntoData:(NSMutableData *) data
10
+                          indent:(NSData *) indent;
11
+
12
+@end
13
+
14
+
15
+@implementation NSObject ( MullePlistWriter)
16
+
17
+- (void) mullePlistWriteIntoData:(NSMutableData *) data
18
+                          indent:(NSData *) indent
19
+{
20
+   [NSException raise:MullePlistWriterException
21
+               format:@"Objects of class %@ can't be saved in a plist", isa];
22
+}
23
+
24
+@end
25
+
26
+
27
+/*
28
+ *
29
+ *
30
+ */
31
+
32
+@interface NSData ( MullePlistWriter)
33
+
34
+- (void) mullePlistWriteIntoData:(NSMutableData *) data
35
+                          indent:(NSData *) indent;
36
+@end
37
+
38
+
39
+static inline char	hexit( unsigned char c)
40
+{
41
+   return( c > 10 ? 'A' - 10 + c : '0' + c);
42
+}
43
+
44
+
45
+@implementation NSData ( MullePlistWriter)
46
+
47
+- (void) mullePlistWriteIntoData:(NSMutableData *) data
48
+                          indent:(NSData *) indent
49
+{
50
+   NSMutableData   *buffer;
51
+   char            *hex;
52
+   unsigned char   *s;
53
+   NSUInteger      len;
54
+   NSUInteger      i;
55
+   
56
+   len    = [self length];
57
+   buffer = [NSMutableData dataWithLength:len * 3 + 3];
58
+   
59
+   hex = (char *) [buffer bytes];
60
+   s   = (unsigned char *) [self bytes];
61
+
62
+   *hex++ = '<';
63
+   i = 0;
64
+   while( len)
65
+   {
66
+      *hex++ = hexit( *s >> 4);
67
+      *hex++ = hexit( *s & 0xF);
68
+      if( ! (++i & 0x7))
69
+         *hex++ = ' ';
70
+      s++;
71
+   }
72
+   *hex++ = '>';
73
+   
74
+   len = (char *) hex - (char *) [buffer bytes];
75
+   [buffer setLength:len];
76
+   [data appendBytes:buffer
77
+              length:len];
78
+}
79
+
80
+@end
81
+
82
+/*
83
+ *
84
+ *
85
+ */
86
+
87
+@interface NSNumber ( MullePlistWriter)
88
+
89
+- (void) mullePlistWriteIntoData:(NSMutableData *) data
90
+                          indent:(NSData *) indent;
91
+@end
92
+
93
+
94
+@implementation NSNumber ( MullePlistWriter)
95
+
96
+- (void) mullePlistWriteIntoData:(NSMutableData *) data
97
+                          indent:(NSData *) indent
98
+{
99
+   char  *s;
100
+
101
+   s = (char *) [[self descriptionWithLocale:nil] UTF8String];
102
+   [data appendBytes:s
103
+              length:strlen( s)];
104
+}
105
+
106
+@end
107
+
108
+/*
109
+ *
110
+ *
111
+ */
112
+
113
+
114
+@interface NSString ( MullePlistWriter)
115
+
116
+- (void) mullePlistWriteIntoData:(NSMutableData *) data
117
+                          indent:(NSData *) indent;
118
+
119
+@end
120
+
121
+
122
+@implementation NSString ( MullePlistWriter)
123
+
124
+- (void) mullePlistWriteIntoData:(NSMutableData *) data
125
+                          indent:(NSData *) indent
126
+{
127
+   char      *s;
128
+   BOOL      quoted;
129
+   NSArray   *components;
130
+   NSString  *quotedSelf;
131
+   
132
+   quoted  = [self rangeOfCharacterFromSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]].length;
133
+   quoted |= [self rangeOfCharacterFromSet:[NSCharacterSet punctuationCharacterSet]].length;
134
+   quoted |= [self length] == 0;
135
+      
136
+   components = [self componentsSeparatedByString:@"\""];
137
+   quotedSelf = [components componentsJoinedByString:@"\\\""];
138
+   quoted |= [components count] > 1;
139
+      
140
+   if( quoted)
141
+      [data appendBytes:"\""
142
+                 length:1];
143
+
144
+
145
+   s = (char *) [quotedSelf UTF8String];
146
+   [data appendBytes:s
147
+              length:strlen( s)];
148
+   if( quoted)
149
+      [data appendBytes:"\""
150
+                 length:1];
151
+}
152
+
153
+@end
154
+
155
+/*
156
+ *
157
+ *
158
+ */
159
+
160
+
161
+@interface NSArray ( MullePlistWriter)
162
+
163
+- (void) mullePlistWriteIntoData:(NSMutableData *) data
164
+                          indent:(NSData *) indent;
165
+
166
+@end
167
+
168
+
169
+@implementation NSArray ( MullePlistWriter)
170
+
171
+- (void) mullePlistWriteIntoData:(NSMutableData *) data
172
+                          indent:(NSData *) indent
173
+{
174
+   NSMutableData   *indent2;
175
+   unsigned int    i, n;
176
+
177
+   [data appendBytes:"("
178
+              length:1];
179
+   n = [self count];
180
+   if( n)
181
+   {
182
+      [data appendBytes:"\n"
183
+                 length:1];
184
+      indent2 = [indent mutableCopy];
185
+      [indent2 appendBytes:"   "
186
+                    length:3];
187
+      for( i = 0; i < n; i++)
188
+      {
189
+         if( i > 0)
190
+            [data appendBytes:",\n"
191
+                       length:2];
192
+         [data appendData:indent2];
193
+         [[self objectAtIndex:i] mullePlistWriteIntoData:data
194
+                                                  indent:indent2];
195
+      }
196
+      [data appendBytes:"\n"
197
+                 length:1];
198
+      [data appendData:indent];
199
+   }
200
+   [data appendBytes:")"
201
+              length:1];
202
+}
203
+
204
+
205
+@end
206
+
207
+/*
208
+ *
209
+ *
210
+ */
211
+
212
+
213
+@interface NSDictionary ( MullePlistWriter)
214
+
215
+- (void) mullePlistWriteIntoData:(NSMutableData *) data
216
+                          indent:(NSData *) indent;
217
+
218
+@end
219
+
220
+
221
+@implementation NSDictionary ( MullePlistWriter)
222
+
223
+- (void) mullePlistWriteIntoData:(NSMutableData *) data
224
+                          indent:(NSData *) indent
225
+{
226
+   NSArray         *keys;
227
+   id              key;
228
+   id              value;
229
+   NSMutableData   *indent2;
230
+   unsigned int    i, n;
231
+
232
+   [data appendBytes:"{"
233
+              length:1];
234
+   keys = [self allKeys];  // sort'em ?
235
+   n    = [keys count];
236
+
237
+   if( n)
238
+   {
239
+      [data appendBytes:"\n"
240
+                 length:1];
241
+
242
+//      keys    = [keys sortedArrayUsingSelector:@selector( compare:)];
243
+      indent2 = [indent mutableCopy];
244
+      [indent2 appendBytes:"   "
245
+                    length:3];
246
+
247
+      for( i = 0; i < n; i++)
248
+      {
249
+         key   = [keys objectAtIndex:i];
250
+         value = [self objectForKey:key];
251
+
252
+         [data appendData:indent2];
253
+         [key mullePlistWriteIntoData:data
254
+                               indent:nil];
255
+         [data appendBytes:" = "
256
+                    length:3];
257
+         [value mullePlistWriteIntoData:data
258
+                                 indent:indent2];
259
+         [data appendBytes:";\n"
260
+                    length:2];
261
+
262
+      }
263
+      [data appendData:indent];
264
+   }
265
+   [data appendBytes:"}"
266
+              length:1];
267
+}
268
+
269
+@end
270
+
271
+
272
+
273
+@implementation NSPropertyListSerialization ( MullePlistWriter)
274
+
275
+
276
++ (NSData *) plistDataFromObject:(id) obj
277
+                errorDescription:(NSString **) error
278
+{
279
+   NSMutableData   *data;
280
+   
281
+   if( ! obj)
282
+   {
283
+      *error = @"plist is nil";
284
+      return( nil);
285
+   }
286
+   
287
+   data = [NSMutableData dataWithCapacity:0x1000];
288
+   [obj mullePlistWriteIntoData:data
289
+                         indent:[NSData data]];
290
+   if( ! [data length])
291
+   {
292
+      *error = @"Some objects were not plist compatible";
293
+      return( nil);
294
+   }
295
+
296
+#if 0   
297
+   [data appendBytes:""  // trailin zero
298
+              length:1];
299
+#endif   
300
+   return( data);
301
+}
302
+
303
+
304
++ (id) mulleDataFromPropertyList:(id) plist
305
+                          format:(NSPropertyListFormat) format
306
+                errorDescription:(NSString **) error
307
+{
308
+   if( format != NSPropertyListOpenStepFormat)
309
+      return( [self dataFromPropertyList:plist
310
+                                  format:format
311
+                         errorDescription:error]);
312
+   
313
+   return( [self plistDataFromObject:plist
314
+                    errorDescription:error]);
315
+}
316
+
317
+
318
+@end
319
+
0 320
new file mode 100644
... ...
@@ -0,0 +1,523 @@
1
+//
2
+// This is a small tool that does the listing of plists and the arbitrary
3
+// change of a value
4
+//
5
+// $Id: main.m,v 1.5 2005/06/16 13:31:04 nat Exp $
6
+//
7
+// $Log: main.m,v $
8
+// Revision 1.5  2005/06/16 13:31:04  nat
9
+// rein damit
10
+//
11
+// Revision 1.4  2005/06/07 14:40:30  nat
12
+// mann kann jetzt plisten als values setzen
13
+//
14
+// Revision 1.3  2002/09/09 12:02:58  nat
15
+// make oldskool format optional and allow force rewriting
16
+//
17
+// Revision 1.2  2002/09/09 10:42:13  nat
18
+// OldSkool PList writing for Solaris compatibility
19
+//
20
+// Revision 1.1.1.1  2001/07/25 12:41:42  admin
21
+// Resurrected from the dead
22
+//
23
+// Revision 1.10  1999/06/30 15:20:11  nat
24
+// Slight cleanup restructuring. Usage is more helpful
25
+//
26
+// Revision 1.9  1999/06/30 15:12:47  nat
27
+// completely revised hack algorithm.
28
+// Now supports recursive descent thru arrays.
29
+// Can do relative and absolute keypaths.
30
+// Slightly more dangerous!
31
+// Much slower
32
+//
33
+// Revision 1.8  1999/06/30 10:50:04  nat
34
+// fatal als bail wrapper dazu.
35
+// hack ein bischen uebersichtlicher umgestaltet
36
+// filename braucht nicht mehr absolute path zu sein
37
+//
38
+// Revision 1.7  1998/11/20 15:53:08  nat
39
+// neue Version von plisthack, inkompatibel zur vorigen Version.
40
+// Jetzt mit add und delete Option
41
+//
42
+// Revision 1.6  1998/11/09 16:12:12  nat
43
+// Anpassungen an neue Foundation bugs
44
+//
45
+// Revision 1.5  1998/10/20 15:00:29  nat
46
+// ja klar, fertig...
47
+// Exit codes ueberall, damit jetzt ziemlich scriptfaehig.
48
+// Ausserdem werden bei Aenderungen die keine sind, nicht
49
+// per default nochmal der alte Wert ausgegeben
50
+//
51
+// Revision 1.4  1998/10/20 14:46:15  nat
52
+// advertisement dazu, ich hoffe jetzt ists fertig
53
+//
54
+// Revision 1.3  1998/10/20 14:40:06  nat
55
+// simplified user interface. Also the need to do more than just
56
+// top level hacking unfortunately arose sooner than expected...
57
+//
58
+// Revision 1.2  1998/10/20 13:49:57  nat
59
+// grr ein tippfehler in den CVS vars
60
+//
61
+// Revision 1.1  1998/10/20 13:48:56  nat
62
+// Merciful Release
63
+//
64
+//
65
+static char  rcs_id__[] = "$Id: main.m,v 1.5 2005/06/16 13:31:04 nat Exp $";
66
+
67
+#import <Foundation/Foundation.h>
68
+#import "NSDictionary+PListOldSkool.h"
69
+#import "NSPropertyListSerialization+MullePlistReader.h"
70
+#import "NSPropertyListSerialization+MullePlistWriter.h"
71
+
72
+//#define DEBUG   1
73
+
74
+
75
+typedef enum
76
+{
77
+   Add    = 0,
78
+   Change = 1,
79
+   Delete = 2,
80
+   Print  = 3
81
+} ActionType;
82