summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/plist/plist.h28
-rw-r--r--src/jplist.c129
-rw-r--r--src/plist.c4
-rw-r--r--tools/Makefile.am6
-rw-r--r--tools/plistutil.c29
5 files changed, 165 insertions, 31 deletions
diff --git a/include/plist/plist.h b/include/plist/plist.h
index b46b9a9..bd35c53 100644
--- a/include/plist/plist.h
+++ b/include/plist/plist.h
@@ -175,6 +175,11 @@ extern "C"
175 PLIST_OPT_PARTIAL_DATA = 1 << 1, /**< Print 24 bytes maximum of #PLIST_DATA values. If the data is longer than 24 bytes, the first 16 and last 8 bytes will be written. Only valid for #PLIST_FORMAT_PRINT. */ 175 PLIST_OPT_PARTIAL_DATA = 1 << 1, /**< Print 24 bytes maximum of #PLIST_DATA values. If the data is longer than 24 bytes, the first 16 and last 8 bytes will be written. Only valid for #PLIST_FORMAT_PRINT. */
176 PLIST_OPT_NO_NEWLINE = 1 << 2, /**< Do not print a final newline character. Only valid for #PLIST_FORMAT_PRINT, #PLIST_FORMAT_LIMD, and #PLIST_FORMAT_PLUTIL. */ 176 PLIST_OPT_NO_NEWLINE = 1 << 2, /**< Do not print a final newline character. Only valid for #PLIST_FORMAT_PRINT, #PLIST_FORMAT_LIMD, and #PLIST_FORMAT_PLUTIL. */
177 PLIST_OPT_INDENT = 1 << 3, /**< Indent each line of output. Currently only #PLIST_FORMAT_PRINT and #PLIST_FORMAT_LIMD are supported. Use #PLIST_OPT_INDENT_BY() macro to specify the level of indentation. */ 177 PLIST_OPT_INDENT = 1 << 3, /**< Indent each line of output. Currently only #PLIST_FORMAT_PRINT and #PLIST_FORMAT_LIMD are supported. Use #PLIST_OPT_INDENT_BY() macro to specify the level of indentation. */
178 PLIST_OPT_COERCE = 1 << 4, /**< Coerce plist types that have no native JSON representation into JSON-compatible types.
179 #PLIST_DATE is converted to an ISO 8601 date string,
180 #PLIST_DATA is converted to a Base64-encoded string, and
181 #PLIST_UID is converted to an integer.
182 Only valid for #PLIST_FORMAT_JSON. Without this option, these types cause #PLIST_ERR_FORMAT. */
178 } plist_write_options_t; 183 } plist_write_options_t;
179 184
180 /** To be used with #PLIST_OPT_INDENT - encodes the level of indentation for OR'ing it into the #plist_write_options_t bitfield. */ 185 /** To be used with #PLIST_OPT_INDENT - encodes the level of indentation for OR'ing it into the #plist_write_options_t bitfield. */
@@ -938,6 +943,29 @@ extern "C"
938 PLIST_API plist_err_t plist_to_json(plist_t plist, char **plist_json, uint32_t* length, int prettify); 943 PLIST_API plist_err_t plist_to_json(plist_t plist, char **plist_json, uint32_t* length, int prettify);
939 944
940 /** 945 /**
946 * Export the #plist_t structure to JSON format with extended options.
947 *
948 * When \a PLIST_OPT_COMPACT is set in \a options, the resulting JSON
949 * will be non-prettified.
950 *
951 * When \a PLIST_OPT_COERCE is set in \a options, plist types that have
952 * no native JSON representation are converted to JSON-compatible types
953 * instead of returning #PLIST_ERR_FORMAT:
954 * - #PLIST_DATE is serialized as an ISO 8601 date string
955 * - #PLIST_DATA is serialized as a Base64-encoded string
956 * - #PLIST_UID is serialized as an integer
957 *
958 * @param plist the root node to export
959 * @param plist_json a pointer to a char* buffer. This function allocates the memory,
960 * caller is responsible for freeing it.
961 * @param length a pointer to an uint32_t variable. Represents the length of the allocated buffer.
962 * @param options One or more bitwise ORed values of #plist_write_options_t.
963 * @return PLIST_ERR_SUCCESS on success or a #plist_err_t on failure
964 * @note Use plist_mem_free() to free the allocated memory.
965 */
966 PLIST_API plist_err_t plist_to_json_with_options(plist_t plist, char **plist_json, uint32_t* length, plist_write_options_t options);
967
968 /**
941 * Export the #plist_t structure to OpenStep format. 969 * Export the #plist_t structure to OpenStep format.
942 * 970 *
943 * @param plist the root node to export 971 * @param plist the root node to export
diff --git a/src/jplist.c b/src/jplist.c
index 0ac1e0b..410d4b3 100644
--- a/src/jplist.c
+++ b/src/jplist.c
@@ -39,6 +39,10 @@
39#include "strbuf.h" 39#include "strbuf.h"
40#include "jsmn.h" 40#include "jsmn.h"
41#include "hashtable.h" 41#include "hashtable.h"
42#include "base64.h"
43#include "time64.h"
44
45#define MAC_EPOCH 978307200
42 46
43#ifdef DEBUG 47#ifdef DEBUG
44static int plist_json_debug = 0; 48static int plist_json_debug = 0;
@@ -115,7 +119,7 @@ static size_t dtostr(char *buf, size_t bufsize, double realval)
115 return len; 119 return len;
116} 120}
117 121
118static plist_err_t node_to_json(node_t node, bytearray_t **outbuf, uint32_t depth, int prettify) 122static plist_err_t node_to_json(node_t node, bytearray_t **outbuf, uint32_t depth, int prettify, int coerce)
119{ 123{
120 plist_data_t node_data = NULL; 124 plist_data_t node_data = NULL;
121 125
@@ -211,7 +215,7 @@ static plist_err_t node_to_json(node_t node, bytearray_t **outbuf, uint32_t dept
211 str_buf_append(*outbuf, " ", 2); 215 str_buf_append(*outbuf, " ", 2);
212 } 216 }
213 } 217 }
214 plist_err_t res = node_to_json(ch, outbuf, depth+1, prettify); 218 plist_err_t res = node_to_json(ch, outbuf, depth+1, prettify, coerce);
215 if (res < 0) { 219 if (res < 0) {
216 return res; 220 return res;
217 } 221 }
@@ -239,7 +243,7 @@ static plist_err_t node_to_json(node_t node, bytearray_t **outbuf, uint32_t dept
239 str_buf_append(*outbuf, " ", 2); 243 str_buf_append(*outbuf, " ", 2);
240 } 244 }
241 } 245 }
242 plist_err_t res = node_to_json(ch, outbuf, depth+1, prettify); 246 plist_err_t res = node_to_json(ch, outbuf, depth+1, prettify, coerce);
243 if (res < 0) { 247 if (res < 0) {
244 return res; 248 return res;
245 } 249 }
@@ -260,17 +264,60 @@ static plist_err_t node_to_json(node_t node, bytearray_t **outbuf, uint32_t dept
260 str_buf_append(*outbuf, "}", 1); 264 str_buf_append(*outbuf, "}", 1);
261 } break; 265 } break;
262 case PLIST_DATA: 266 case PLIST_DATA:
263 // NOT VALID FOR JSON 267 if (coerce) {
264 PLIST_JSON_WRITE_ERR("PLIST_DATA type is not valid for JSON format\n"); 268 size_t b64_len = ((node_data->length + 2) / 3) * 4;
265 return PLIST_ERR_FORMAT; 269 char *b64_buf = (char*)malloc(b64_len + 1);
270 if (!b64_buf) {
271 return PLIST_ERR_NO_MEM;
272 }
273 size_t actual_len = base64encode(b64_buf, node_data->buff, node_data->length);
274 str_buf_append(*outbuf, "\"", 1);
275 str_buf_append(*outbuf, b64_buf, actual_len);
276 str_buf_append(*outbuf, "\"", 1);
277 free(b64_buf);
278 } else {
279 PLIST_JSON_WRITE_ERR("PLIST_DATA type is not valid for JSON format\n");
280 return PLIST_ERR_FORMAT;
281 }
282 break;
266 case PLIST_DATE: 283 case PLIST_DATE:
267 // NOT VALID FOR JSON 284 if (coerce) {
268 PLIST_JSON_WRITE_ERR("PLIST_DATE type is not valid for JSON format\n"); 285 Time64_T timev = (Time64_T)node_data->realval + MAC_EPOCH;
269 return PLIST_ERR_FORMAT; 286 struct TM _btime;
287 struct TM *btime = gmtime64_r(&timev, &_btime);
288 char datebuf[32];
289 size_t datelen = 0;
290 if (btime) {
291 struct tm _tmcopy;
292 copy_TM64_to_tm(btime, &_tmcopy);
293 datelen = strftime(datebuf, sizeof(datebuf), "%Y-%m-%dT%H:%M:%SZ", &_tmcopy);
294 }
295 if (datelen <= 0) {
296 datelen = snprintf(datebuf, sizeof(datebuf), "1970-01-01T00:00:00Z");
297 }
298 str_buf_append(*outbuf, "\"", 1);
299 str_buf_append(*outbuf, datebuf, datelen);
300 str_buf_append(*outbuf, "\"", 1);
301 } else {
302 PLIST_JSON_WRITE_ERR("PLIST_DATE type is not valid for JSON format\n");
303 return PLIST_ERR_FORMAT;
304 }
305 break;
270 case PLIST_UID: 306 case PLIST_UID:
271 // NOT VALID FOR JSON 307 if (coerce) {
272 PLIST_JSON_WRITE_ERR("PLIST_UID type is not valid for JSON format\n"); 308 val = (char*)malloc(64);
273 return PLIST_ERR_FORMAT; 309 if (node_data->length == 16) {
310 val_len = snprintf(val, 64, "%" PRIu64, node_data->intval);
311 } else {
312 val_len = snprintf(val, 64, "%" PRIi64, node_data->intval);
313 }
314 str_buf_append(*outbuf, val, val_len);
315 free(val);
316 } else {
317 PLIST_JSON_WRITE_ERR("PLIST_UID type is not valid for JSON format\n");
318 return PLIST_ERR_FORMAT;
319 }
320 break;
274 default: 321 default:
275 return PLIST_ERR_UNKNOWN; 322 return PLIST_ERR_UNKNOWN;
276 } 323 }
@@ -316,7 +363,7 @@ static int num_digits_u(uint64_t i)
316 return n; 363 return n;
317} 364}
318 365
319static plist_err_t _node_estimate_size(node_t node, uint64_t *size, uint32_t depth, int prettify, hashtable_t *visited) 366static plist_err_t _node_estimate_size(node_t node, uint64_t *size, uint32_t depth, int prettify, int coerce, hashtable_t *visited)
320{ 367{
321 plist_data_t data; 368 plist_data_t data;
322 if (!node) { 369 if (!node) {
@@ -341,7 +388,7 @@ static plist_err_t _node_estimate_size(node_t node, uint64_t *size, uint32_t dep
341 node_t ch; 388 node_t ch;
342 unsigned int n_children = node_n_children(node); 389 unsigned int n_children = node_n_children(node);
343 for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) { 390 for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) {
344 plist_err_t res = _node_estimate_size(ch, size, depth + 1, prettify, visited); 391 plist_err_t res = _node_estimate_size(ch, size, depth + 1, prettify, coerce, visited);
345 if (res < 0) { 392 if (res < 0) {
346 return res; 393 return res;
347 } 394 }
@@ -398,17 +445,36 @@ static plist_err_t _node_estimate_size(node_t node, uint64_t *size, uint32_t dep
398 *size += 2; 445 *size += 2;
399 break; 446 break;
400 case PLIST_DATA: 447 case PLIST_DATA:
401 // NOT VALID FOR JSON 448 if (coerce) {
402 PLIST_JSON_WRITE_ERR("PLIST_DATA type is not valid for JSON format\n"); 449 // base64 encoded string: 2 quotes + ((len+2)/3)*4 base64 chars
403 return PLIST_ERR_FORMAT; 450 *size += 2 + ((data->length + 2) / 3) * 4;
451 } else {
452 PLIST_JSON_WRITE_ERR("PLIST_DATA type is not valid for JSON format\n");
453 return PLIST_ERR_FORMAT;
454 }
455 break;
404 case PLIST_DATE: 456 case PLIST_DATE:
405 // NOT VALID FOR JSON 457 if (coerce) {
406 PLIST_JSON_WRITE_ERR("PLIST_DATE type is not valid for JSON format\n"); 458 // ISO 8601 string: "YYYY-MM-DDTHH:MM:SSZ" = 22 chars max
407 return PLIST_ERR_FORMAT; 459 *size += 24;
460 } else {
461 PLIST_JSON_WRITE_ERR("PLIST_DATE type is not valid for JSON format\n");
462 return PLIST_ERR_FORMAT;
463 }
464 break;
408 case PLIST_UID: 465 case PLIST_UID:
409 // NOT VALID FOR JSON 466 if (coerce) {
410 PLIST_JSON_WRITE_ERR("PLIST_UID type is not valid for JSON format\n"); 467 // integer representation
411 return PLIST_ERR_FORMAT; 468 if (data->length == 16) {
469 *size += num_digits_u(data->intval);
470 } else {
471 *size += num_digits_i((int64_t)data->intval);
472 }
473 } else {
474 PLIST_JSON_WRITE_ERR("PLIST_UID type is not valid for JSON format\n");
475 return PLIST_ERR_FORMAT;
476 }
477 break;
412 default: 478 default:
413 PLIST_JSON_WRITE_ERR("invalid node type encountered\n"); 479 PLIST_JSON_WRITE_ERR("invalid node type encountered\n");
414 return PLIST_ERR_UNKNOWN; 480 return PLIST_ERR_UNKNOWN;
@@ -417,17 +483,23 @@ static plist_err_t _node_estimate_size(node_t node, uint64_t *size, uint32_t dep
417 return PLIST_ERR_SUCCESS; 483 return PLIST_ERR_SUCCESS;
418} 484}
419 485
420static plist_err_t node_estimate_size(node_t node, uint64_t *size, uint32_t depth, int prettify) 486static plist_err_t node_estimate_size(node_t node, uint64_t *size, uint32_t depth, int prettify, int coerce)
421{ 487{
422 hashtable_t *visited = hash_table_new(plist_node_ptr_hash, plist_node_ptr_compare, NULL); 488 hashtable_t *visited = hash_table_new(plist_node_ptr_hash, plist_node_ptr_compare, NULL);
423 if (!visited) return PLIST_ERR_NO_MEM; 489 if (!visited) return PLIST_ERR_NO_MEM;
424 plist_err_t err = _node_estimate_size(node, size, depth, prettify, visited); 490 plist_err_t err = _node_estimate_size(node, size, depth, prettify, coerce, visited);
425 hash_table_destroy(visited); 491 hash_table_destroy(visited);
426 return err; 492 return err;
427} 493}
428 494
429plist_err_t plist_to_json(plist_t plist, char **plist_json, uint32_t* length, int prettify) 495plist_err_t plist_to_json(plist_t plist, char **plist_json, uint32_t* length, int prettify)
430{ 496{
497 plist_write_options_t opts = prettify ? PLIST_OPT_NONE : PLIST_OPT_COMPACT;
498 return plist_to_json_with_options(plist, plist_json, length, opts);
499}
500
501plist_err_t plist_to_json_with_options(plist_t plist, char **plist_json, uint32_t* length, plist_write_options_t options)
502{
431 uint64_t size = 0; 503 uint64_t size = 0;
432 plist_err_t res; 504 plist_err_t res;
433 505
@@ -440,7 +512,10 @@ plist_err_t plist_to_json(plist_t plist, char **plist_json, uint32_t* length, in
440 return PLIST_ERR_FORMAT; 512 return PLIST_ERR_FORMAT;
441 } 513 }
442 514
443 res = node_estimate_size((node_t)plist, &size, 0, prettify); 515 int prettify = !(options & PLIST_OPT_COMPACT);
516 int coerce = options & PLIST_OPT_COERCE;
517
518 res = node_estimate_size((node_t)plist, &size, 0, prettify, coerce);
444 if (res < 0) { 519 if (res < 0) {
445 return res; 520 return res;
446 } 521 }
@@ -451,7 +526,7 @@ plist_err_t plist_to_json(plist_t plist, char **plist_json, uint32_t* length, in
451 return PLIST_ERR_NO_MEM; 526 return PLIST_ERR_NO_MEM;
452 } 527 }
453 528
454 res = node_to_json((node_t)plist, &outbuf, 0, prettify); 529 res = node_to_json((node_t)plist, &outbuf, 0, prettify, coerce);
455 if (res < 0) { 530 if (res < 0) {
456 str_buf_free(outbuf); 531 str_buf_free(outbuf);
457 *plist_json = NULL; 532 *plist_json = NULL;
diff --git a/src/plist.c b/src/plist.c
index 7697a75..a6d3547 100644
--- a/src/plist.c
+++ b/src/plist.c
@@ -2404,7 +2404,7 @@ plist_err_t plist_write_to_string(plist_t plist, char **output, uint32_t* length
2404 err = plist_to_xml(plist, output, length); 2404 err = plist_to_xml(plist, output, length);
2405 break; 2405 break;
2406 case PLIST_FORMAT_JSON: 2406 case PLIST_FORMAT_JSON:
2407 err = plist_to_json(plist, output, length, ((options & PLIST_OPT_COMPACT) == 0)); 2407 err = plist_to_json_with_options(plist, output, length, options);
2408 break; 2408 break;
2409 case PLIST_FORMAT_OSTEP: 2409 case PLIST_FORMAT_OSTEP:
2410 err = plist_to_openstep(plist, output, length, ((options & PLIST_OPT_COMPACT) == 0)); 2410 err = plist_to_openstep(plist, output, length, ((options & PLIST_OPT_COMPACT) == 0));
@@ -2442,7 +2442,7 @@ plist_err_t plist_write_to_stream(plist_t plist, FILE *stream, plist_format_t fo
2442 err = plist_to_xml(plist, &output, &length); 2442 err = plist_to_xml(plist, &output, &length);
2443 break; 2443 break;
2444 case PLIST_FORMAT_JSON: 2444 case PLIST_FORMAT_JSON:
2445 err = plist_to_json(plist, &output, &length, ((options & PLIST_OPT_COMPACT) == 0)); 2445 err = plist_to_json_with_options(plist, &output, &length, options);
2446 break; 2446 break;
2447 case PLIST_FORMAT_OSTEP: 2447 case PLIST_FORMAT_OSTEP:
2448 err = plist_to_openstep(plist, &output, &length, ((options & PLIST_OPT_COMPACT) == 0)); 2448 err = plist_to_openstep(plist, &output, &length, ((options & PLIST_OPT_COMPACT) == 0));
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 5883286..93b5b9f 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -11,4 +11,10 @@ bin_PROGRAMS = plistutil
11plistutil_SOURCES = plistutil.c 11plistutil_SOURCES = plistutil.c
12plistutil_LDADD = $(top_builddir)/src/libplist-2.0.la 12plistutil_LDADD = $(top_builddir)/src/libplist-2.0.la
13 13
14install-exec-hook:
15 cd $(DESTDIR)$(bindir) && ln -sf plistutil plist2json
16
17uninstall-hook:
18 rm -f $(DESTDIR)$(bindir)/plist2json
19
14endif 20endif
diff --git a/tools/plistutil.c b/tools/plistutil.c
index bdf195e..fef72b7 100644
--- a/tools/plistutil.c
+++ b/tools/plistutil.c
@@ -52,6 +52,7 @@ typedef struct _options
52#define OPT_DEBUG (1 << 0) 52#define OPT_DEBUG (1 << 0)
53#define OPT_COMPACT (1 << 1) 53#define OPT_COMPACT (1 << 1)
54#define OPT_SORT (1 << 2) 54#define OPT_SORT (1 << 2)
55#define OPT_COERCE (1 << 3)
55 56
56static void print_usage(int argc, char *argv[]) 57static void print_usage(int argc, char *argv[])
57{ 58{
@@ -74,6 +75,10 @@ static void print_usage(int argc, char *argv[])
74 printf(" -n, --nodepath PATH Restrict output to nodepath defined by PATH.\n"); 75 printf(" -n, --nodepath PATH Restrict output to nodepath defined by PATH.\n");
75 printf(" -c, --compact JSON and OpenStep only: Print output in compact form.\n"); 76 printf(" -c, --compact JSON and OpenStep only: Print output in compact form.\n");
76 printf(" By default, the output will be pretty-printed.\n"); 77 printf(" By default, the output will be pretty-printed.\n");
78 printf(" -C, --coerce JSON only: Coerce non-JSON plist types to JSON-compatible\n");
79 printf(" representations. Date values become ISO 8601 strings,\n");
80 printf(" data values become Base64-encoded strings, and UID values\n");
81 printf(" become integers. Implied when invoked as plist2json.\n");
77 printf(" -s, --sort Sort all dictionary nodes lexicographically by key\n"); 82 printf(" -s, --sort Sort all dictionary nodes lexicographically by key\n");
78 printf(" before converting to the output format.\n"); 83 printf(" before converting to the output format.\n");
79 printf(" -d, --debug Enable extended debug output\n"); 84 printf(" -d, --debug Enable extended debug output\n");
@@ -96,6 +101,7 @@ static options_t *parse_arguments(int argc, char *argv[])
96 { "outfile", required_argument, 0, 'o' }, 101 { "outfile", required_argument, 0, 'o' },
97 { "format", required_argument, 0, 'f' }, 102 { "format", required_argument, 0, 'f' },
98 { "compact", no_argument, 0, 'c' }, 103 { "compact", no_argument, 0, 'c' },
104 { "coerce", no_argument, 0, 'C' },
99 { "sort", no_argument, 0, 's' }, 105 { "sort", no_argument, 0, 's' },
100 { "print", required_argument, 0, 'p' }, 106 { "print", required_argument, 0, 'p' },
101 { "nodepath", required_argument, 0, 'n' }, 107 { "nodepath", required_argument, 0, 'n' },
@@ -106,7 +112,7 @@ static options_t *parse_arguments(int argc, char *argv[])
106 }; 112 };
107 113
108 int c; 114 int c;
109 while ((c = getopt_long(argc, argv, "i:o:f:csp:n:dhv", long_options, NULL)) != -1) 115 while ((c = getopt_long(argc, argv, "i:o:f:cCsp:n:dhv", long_options, NULL)) != -1)
110 { 116 {
111 switch (c) 117 switch (c)
112 { 118 {
@@ -154,6 +160,10 @@ static options_t *parse_arguments(int argc, char *argv[])
154 options->flags |= OPT_COMPACT; 160 options->flags |= OPT_COMPACT;
155 break; 161 break;
156 162
163 case 'C':
164 options->flags |= OPT_COERCE;
165 break;
166
157 case 's': 167 case 's':
158 options->flags |= OPT_SORT; 168 options->flags |= OPT_SORT;
159 break; 169 break;
@@ -230,6 +240,18 @@ int main(int argc, char *argv[])
230 return 0; 240 return 0;
231 } 241 }
232 242
243 // detect invocation as plist2json symlink
244 {
245 char *progname = strrchr(argv[0], '/');
246 progname = progname ? progname + 1 : argv[0];
247 if (!strcmp(progname, "plist2json")) {
248 if (options->out_fmt == 0) {
249 options->out_fmt = PLIST_FORMAT_JSON;
250 }
251 options->flags |= OPT_COERCE;
252 }
253 }
254
233 if (options->flags & OPT_DEBUG) 255 if (options->flags & OPT_DEBUG)
234 { 256 {
235 plist_set_debug(1); 257 plist_set_debug(1);
@@ -404,7 +426,10 @@ int main(int argc, char *argv[])
404 } else if (options->out_fmt == PLIST_FORMAT_XML) { 426 } else if (options->out_fmt == PLIST_FORMAT_XML) {
405 output_res = plist_to_xml(root_node, &plist_out, &size); 427 output_res = plist_to_xml(root_node, &plist_out, &size);
406 } else if (options->out_fmt == PLIST_FORMAT_JSON) { 428 } else if (options->out_fmt == PLIST_FORMAT_JSON) {
407 output_res = plist_to_json(root_node, &plist_out, &size, !(options->flags & OPT_COMPACT)); 429 plist_write_options_t wropts = PLIST_OPT_NONE;
430 if (options->flags & OPT_COMPACT) wropts |= PLIST_OPT_COMPACT;
431 if (options->flags & OPT_COERCE) wropts |= PLIST_OPT_COERCE;
432 output_res = plist_to_json_with_options(root_node, &plist_out, &size, wropts);
408 } else if (options->out_fmt == PLIST_FORMAT_OSTEP) { 433 } else if (options->out_fmt == PLIST_FORMAT_OSTEP) {
409 output_res = plist_to_openstep(root_node, &plist_out, &size, !(options->flags & OPT_COMPACT)); 434 output_res = plist_to_openstep(root_node, &plist_out, &size, !(options->flags & OPT_COMPACT));
410 } else { 435 } else {