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