]> git.proxmox.com Git - mirror_qemu.git/blob - check-qjson.c
isa: always use provided ISA bus when creating an isa device
[mirror_qemu.git] / check-qjson.c
1 /*
2 * Copyright IBM, Corp. 2009
3 *
4 * Authors:
5 * Anthony Liguori <aliguori@us.ibm.com>
6 *
7 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
8 * See the COPYING.LIB file in the top-level directory.
9 *
10 */
11 #include <check.h>
12
13 #include "qstring.h"
14 #include "qint.h"
15 #include "qdict.h"
16 #include "qlist.h"
17 #include "qfloat.h"
18 #include "qbool.h"
19 #include "qjson.h"
20
21 #include "qemu-common.h"
22
23 START_TEST(escaped_string)
24 {
25 int i;
26 struct {
27 const char *encoded;
28 const char *decoded;
29 int skip;
30 } test_cases[] = {
31 { "\"\\b\"", "\b" },
32 { "\"\\f\"", "\f" },
33 { "\"\\n\"", "\n" },
34 { "\"\\r\"", "\r" },
35 { "\"\\t\"", "\t" },
36 { "\"/\"", "/" },
37 { "\"\\/\"", "/", .skip = 1 },
38 { "\"\\\\\"", "\\" },
39 { "\"\\\"\"", "\"" },
40 { "\"hello world \\\"embedded string\\\"\"",
41 "hello world \"embedded string\"" },
42 { "\"hello world\\nwith new line\"", "hello world\nwith new line" },
43 { "\"single byte utf-8 \\u0020\"", "single byte utf-8 ", .skip = 1 },
44 { "\"double byte utf-8 \\u00A2\"", "double byte utf-8 \xc2\xa2" },
45 { "\"triple byte utf-8 \\u20AC\"", "triple byte utf-8 \xe2\x82\xac" },
46 {}
47 };
48
49 for (i = 0; test_cases[i].encoded; i++) {
50 QObject *obj;
51 QString *str;
52
53 obj = qobject_from_json(test_cases[i].encoded);
54
55 fail_unless(obj != NULL);
56 fail_unless(qobject_type(obj) == QTYPE_QSTRING);
57
58 str = qobject_to_qstring(obj);
59 fail_unless(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0,
60 "%s != %s\n", qstring_get_str(str), test_cases[i].decoded);
61
62 if (test_cases[i].skip == 0) {
63 str = qobject_to_json(obj);
64 fail_unless(strcmp(qstring_get_str(str),test_cases[i].encoded) == 0,
65 "%s != %s\n", qstring_get_str(str),
66 test_cases[i].encoded);
67
68 qobject_decref(obj);
69 }
70
71 QDECREF(str);
72 }
73 }
74 END_TEST
75
76 START_TEST(simple_string)
77 {
78 int i;
79 struct {
80 const char *encoded;
81 const char *decoded;
82 } test_cases[] = {
83 { "\"hello world\"", "hello world" },
84 { "\"the quick brown fox jumped over the fence\"",
85 "the quick brown fox jumped over the fence" },
86 {}
87 };
88
89 for (i = 0; test_cases[i].encoded; i++) {
90 QObject *obj;
91 QString *str;
92
93 obj = qobject_from_json(test_cases[i].encoded);
94
95 fail_unless(obj != NULL);
96 fail_unless(qobject_type(obj) == QTYPE_QSTRING);
97
98 str = qobject_to_qstring(obj);
99 fail_unless(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
100
101 str = qobject_to_json(obj);
102 fail_unless(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
103
104 qobject_decref(obj);
105
106 QDECREF(str);
107 }
108 }
109 END_TEST
110
111 START_TEST(single_quote_string)
112 {
113 int i;
114 struct {
115 const char *encoded;
116 const char *decoded;
117 } test_cases[] = {
118 { "'hello world'", "hello world" },
119 { "'the quick brown fox \\' jumped over the fence'",
120 "the quick brown fox ' jumped over the fence" },
121 {}
122 };
123
124 for (i = 0; test_cases[i].encoded; i++) {
125 QObject *obj;
126 QString *str;
127
128 obj = qobject_from_json(test_cases[i].encoded);
129
130 fail_unless(obj != NULL);
131 fail_unless(qobject_type(obj) == QTYPE_QSTRING);
132
133 str = qobject_to_qstring(obj);
134 fail_unless(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
135
136 QDECREF(str);
137 }
138 }
139 END_TEST
140
141 START_TEST(vararg_string)
142 {
143 int i;
144 struct {
145 const char *decoded;
146 } test_cases[] = {
147 { "hello world" },
148 { "the quick brown fox jumped over the fence" },
149 {}
150 };
151
152 for (i = 0; test_cases[i].decoded; i++) {
153 QObject *obj;
154 QString *str;
155
156 obj = qobject_from_jsonf("%s", test_cases[i].decoded);
157
158 fail_unless(obj != NULL);
159 fail_unless(qobject_type(obj) == QTYPE_QSTRING);
160
161 str = qobject_to_qstring(obj);
162 fail_unless(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
163
164 QDECREF(str);
165 }
166 }
167 END_TEST
168
169 START_TEST(simple_number)
170 {
171 int i;
172 struct {
173 const char *encoded;
174 int64_t decoded;
175 int skip;
176 } test_cases[] = {
177 { "0", 0 },
178 { "1234", 1234 },
179 { "1", 1 },
180 { "-32", -32 },
181 { "-0", 0, .skip = 1 },
182 { },
183 };
184
185 for (i = 0; test_cases[i].encoded; i++) {
186 QObject *obj;
187 QInt *qint;
188
189 obj = qobject_from_json(test_cases[i].encoded);
190 fail_unless(obj != NULL);
191 fail_unless(qobject_type(obj) == QTYPE_QINT);
192
193 qint = qobject_to_qint(obj);
194 fail_unless(qint_get_int(qint) == test_cases[i].decoded);
195 if (test_cases[i].skip == 0) {
196 QString *str;
197
198 str = qobject_to_json(obj);
199 fail_unless(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
200 QDECREF(str);
201 }
202
203 QDECREF(qint);
204 }
205 }
206 END_TEST
207
208 START_TEST(float_number)
209 {
210 int i;
211 struct {
212 const char *encoded;
213 double decoded;
214 int skip;
215 } test_cases[] = {
216 { "32.43", 32.43 },
217 { "0.222", 0.222 },
218 { "-32.12313", -32.12313 },
219 { "-32.20e-10", -32.20e-10, .skip = 1 },
220 { },
221 };
222
223 for (i = 0; test_cases[i].encoded; i++) {
224 QObject *obj;
225 QFloat *qfloat;
226
227 obj = qobject_from_json(test_cases[i].encoded);
228 fail_unless(obj != NULL);
229 fail_unless(qobject_type(obj) == QTYPE_QFLOAT);
230
231 qfloat = qobject_to_qfloat(obj);
232 fail_unless(qfloat_get_double(qfloat) == test_cases[i].decoded);
233
234 if (test_cases[i].skip == 0) {
235 QString *str;
236
237 str = qobject_to_json(obj);
238 fail_unless(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
239 QDECREF(str);
240 }
241
242 QDECREF(qfloat);
243 }
244 }
245 END_TEST
246
247 START_TEST(vararg_number)
248 {
249 QObject *obj;
250 QInt *qint;
251 QFloat *qfloat;
252 int value = 0x2342;
253 int64_t value64 = 0x2342342343LL;
254 double valuef = 2.323423423;
255
256 obj = qobject_from_jsonf("%d", value);
257 fail_unless(obj != NULL);
258 fail_unless(qobject_type(obj) == QTYPE_QINT);
259
260 qint = qobject_to_qint(obj);
261 fail_unless(qint_get_int(qint) == value);
262
263 QDECREF(qint);
264
265 obj = qobject_from_jsonf("%" PRId64, value64);
266 fail_unless(obj != NULL);
267 fail_unless(qobject_type(obj) == QTYPE_QINT);
268
269 qint = qobject_to_qint(obj);
270 fail_unless(qint_get_int(qint) == value64);
271
272 QDECREF(qint);
273
274 obj = qobject_from_jsonf("%f", valuef);
275 fail_unless(obj != NULL);
276 fail_unless(qobject_type(obj) == QTYPE_QFLOAT);
277
278 qfloat = qobject_to_qfloat(obj);
279 fail_unless(qfloat_get_double(qfloat) == valuef);
280
281 QDECREF(qfloat);
282 }
283 END_TEST
284
285 START_TEST(keyword_literal)
286 {
287 QObject *obj;
288 QBool *qbool;
289 QString *str;
290
291 obj = qobject_from_json("true");
292 fail_unless(obj != NULL);
293 fail_unless(qobject_type(obj) == QTYPE_QBOOL);
294
295 qbool = qobject_to_qbool(obj);
296 fail_unless(qbool_get_int(qbool) != 0);
297
298 str = qobject_to_json(obj);
299 fail_unless(strcmp(qstring_get_str(str), "true") == 0);
300 QDECREF(str);
301
302 QDECREF(qbool);
303
304 obj = qobject_from_json("false");
305 fail_unless(obj != NULL);
306 fail_unless(qobject_type(obj) == QTYPE_QBOOL);
307
308 qbool = qobject_to_qbool(obj);
309 fail_unless(qbool_get_int(qbool) == 0);
310
311 str = qobject_to_json(obj);
312 fail_unless(strcmp(qstring_get_str(str), "false") == 0);
313 QDECREF(str);
314
315 QDECREF(qbool);
316
317 obj = qobject_from_jsonf("%i", false);
318 fail_unless(obj != NULL);
319 fail_unless(qobject_type(obj) == QTYPE_QBOOL);
320
321 qbool = qobject_to_qbool(obj);
322 fail_unless(qbool_get_int(qbool) == 0);
323
324 QDECREF(qbool);
325
326 obj = qobject_from_jsonf("%i", true);
327 fail_unless(obj != NULL);
328 fail_unless(qobject_type(obj) == QTYPE_QBOOL);
329
330 qbool = qobject_to_qbool(obj);
331 fail_unless(qbool_get_int(qbool) != 0);
332
333 QDECREF(qbool);
334 }
335 END_TEST
336
337 typedef struct LiteralQDictEntry LiteralQDictEntry;
338 typedef struct LiteralQObject LiteralQObject;
339
340 struct LiteralQObject
341 {
342 int type;
343 union {
344 int64_t qint;
345 const char *qstr;
346 LiteralQDictEntry *qdict;
347 LiteralQObject *qlist;
348 } value;
349 };
350
351 struct LiteralQDictEntry
352 {
353 const char *key;
354 LiteralQObject value;
355 };
356
357 #define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)}
358 #define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
359 #define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
360 #define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
361
362 typedef struct QListCompareHelper
363 {
364 int index;
365 LiteralQObject *objs;
366 int result;
367 } QListCompareHelper;
368
369 static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs);
370
371 static void compare_helper(QObject *obj, void *opaque)
372 {
373 QListCompareHelper *helper = opaque;
374
375 if (helper->result == 0) {
376 return;
377 }
378
379 if (helper->objs[helper->index].type == QTYPE_NONE) {
380 helper->result = 0;
381 return;
382 }
383
384 helper->result = compare_litqobj_to_qobj(&helper->objs[helper->index++], obj);
385 }
386
387 static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs)
388 {
389 if (lhs->type != qobject_type(rhs)) {
390 return 0;
391 }
392
393 switch (lhs->type) {
394 case QTYPE_QINT:
395 return lhs->value.qint == qint_get_int(qobject_to_qint(rhs));
396 case QTYPE_QSTRING:
397 return (strcmp(lhs->value.qstr, qstring_get_str(qobject_to_qstring(rhs))) == 0);
398 case QTYPE_QDICT: {
399 int i;
400
401 for (i = 0; lhs->value.qdict[i].key; i++) {
402 QObject *obj = qdict_get(qobject_to_qdict(rhs), lhs->value.qdict[i].key);
403
404 if (!compare_litqobj_to_qobj(&lhs->value.qdict[i].value, obj)) {
405 return 0;
406 }
407 }
408
409 return 1;
410 }
411 case QTYPE_QLIST: {
412 QListCompareHelper helper;
413
414 helper.index = 0;
415 helper.objs = lhs->value.qlist;
416 helper.result = 1;
417
418 qlist_iter(qobject_to_qlist(rhs), compare_helper, &helper);
419
420 return helper.result;
421 }
422 default:
423 break;
424 }
425
426 return 0;
427 }
428
429 START_TEST(simple_dict)
430 {
431 int i;
432 struct {
433 const char *encoded;
434 LiteralQObject decoded;
435 } test_cases[] = {
436 {
437 .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
438 .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
439 { "foo", QLIT_QINT(42) },
440 { "bar", QLIT_QSTR("hello world") },
441 { }
442 })),
443 }, {
444 .encoded = "{}",
445 .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
446 { }
447 })),
448 }, {
449 .encoded = "{\"foo\": 43}",
450 .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
451 { "foo", QLIT_QINT(43) },
452 { }
453 })),
454 },
455 { }
456 };
457
458 for (i = 0; test_cases[i].encoded; i++) {
459 QObject *obj;
460 QString *str;
461
462 obj = qobject_from_json(test_cases[i].encoded);
463 fail_unless(obj != NULL);
464 fail_unless(qobject_type(obj) == QTYPE_QDICT);
465
466 fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
467
468 str = qobject_to_json(obj);
469 qobject_decref(obj);
470
471 obj = qobject_from_json(qstring_get_str(str));
472 fail_unless(obj != NULL);
473 fail_unless(qobject_type(obj) == QTYPE_QDICT);
474
475 fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
476 qobject_decref(obj);
477 QDECREF(str);
478 }
479 }
480 END_TEST
481
482 START_TEST(simple_list)
483 {
484 int i;
485 struct {
486 const char *encoded;
487 LiteralQObject decoded;
488 } test_cases[] = {
489 {
490 .encoded = "[43,42]",
491 .decoded = QLIT_QLIST(((LiteralQObject[]){
492 QLIT_QINT(43),
493 QLIT_QINT(42),
494 { }
495 })),
496 },
497 {
498 .encoded = "[43]",
499 .decoded = QLIT_QLIST(((LiteralQObject[]){
500 QLIT_QINT(43),
501 { }
502 })),
503 },
504 {
505 .encoded = "[]",
506 .decoded = QLIT_QLIST(((LiteralQObject[]){
507 { }
508 })),
509 },
510 {
511 .encoded = "[{}]",
512 .decoded = QLIT_QLIST(((LiteralQObject[]){
513 QLIT_QDICT(((LiteralQDictEntry[]){
514 {},
515 })),
516 {},
517 })),
518 },
519 { }
520 };
521
522 for (i = 0; test_cases[i].encoded; i++) {
523 QObject *obj;
524 QString *str;
525
526 obj = qobject_from_json(test_cases[i].encoded);
527 fail_unless(obj != NULL);
528 fail_unless(qobject_type(obj) == QTYPE_QLIST);
529
530 fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
531
532 str = qobject_to_json(obj);
533 qobject_decref(obj);
534
535 obj = qobject_from_json(qstring_get_str(str));
536 fail_unless(obj != NULL);
537 fail_unless(qobject_type(obj) == QTYPE_QLIST);
538
539 fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
540 qobject_decref(obj);
541 QDECREF(str);
542 }
543 }
544 END_TEST
545
546 START_TEST(simple_whitespace)
547 {
548 int i;
549 struct {
550 const char *encoded;
551 LiteralQObject decoded;
552 } test_cases[] = {
553 {
554 .encoded = " [ 43 , 42 ]",
555 .decoded = QLIT_QLIST(((LiteralQObject[]){
556 QLIT_QINT(43),
557 QLIT_QINT(42),
558 { }
559 })),
560 },
561 {
562 .encoded = " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
563 .decoded = QLIT_QLIST(((LiteralQObject[]){
564 QLIT_QINT(43),
565 QLIT_QDICT(((LiteralQDictEntry[]){
566 { "h", QLIT_QSTR("b") },
567 { }})),
568 QLIT_QLIST(((LiteralQObject[]){
569 { }})),
570 QLIT_QINT(42),
571 { }
572 })),
573 },
574 {
575 .encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
576 .decoded = QLIT_QLIST(((LiteralQObject[]){
577 QLIT_QINT(43),
578 QLIT_QDICT(((LiteralQDictEntry[]){
579 { "h", QLIT_QSTR("b") },
580 { "a", QLIT_QINT(32) },
581 { }})),
582 QLIT_QLIST(((LiteralQObject[]){
583 { }})),
584 QLIT_QINT(42),
585 { }
586 })),
587 },
588 { }
589 };
590
591 for (i = 0; test_cases[i].encoded; i++) {
592 QObject *obj;
593 QString *str;
594
595 obj = qobject_from_json(test_cases[i].encoded);
596 fail_unless(obj != NULL);
597 fail_unless(qobject_type(obj) == QTYPE_QLIST);
598
599 fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
600
601 str = qobject_to_json(obj);
602 qobject_decref(obj);
603
604 obj = qobject_from_json(qstring_get_str(str));
605 fail_unless(obj != NULL);
606 fail_unless(qobject_type(obj) == QTYPE_QLIST);
607
608 fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
609
610 qobject_decref(obj);
611 QDECREF(str);
612 }
613 }
614 END_TEST
615
616 START_TEST(simple_varargs)
617 {
618 QObject *embedded_obj;
619 QObject *obj;
620 LiteralQObject decoded = QLIT_QLIST(((LiteralQObject[]){
621 QLIT_QINT(1),
622 QLIT_QINT(2),
623 QLIT_QLIST(((LiteralQObject[]){
624 QLIT_QINT(32),
625 QLIT_QINT(42),
626 {}})),
627 {}}));
628
629 embedded_obj = qobject_from_json("[32, 42]");
630 fail_unless(embedded_obj != NULL);
631
632 obj = qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj);
633 fail_unless(obj != NULL);
634
635 fail_unless(compare_litqobj_to_qobj(&decoded, obj) == 1);
636
637 qobject_decref(obj);
638 }
639 END_TEST
640
641 START_TEST(empty_input)
642 {
643 const char *empty = "";
644
645 QObject *obj = qobject_from_json(empty);
646 fail_unless(obj == NULL);
647 }
648 END_TEST
649
650 START_TEST(unterminated_string)
651 {
652 QObject *obj = qobject_from_json("\"abc");
653 fail_unless(obj == NULL);
654 }
655 END_TEST
656
657 START_TEST(unterminated_sq_string)
658 {
659 QObject *obj = qobject_from_json("'abc");
660 fail_unless(obj == NULL);
661 }
662 END_TEST
663
664 START_TEST(unterminated_escape)
665 {
666 QObject *obj = qobject_from_json("\"abc\\\"");
667 fail_unless(obj == NULL);
668 }
669 END_TEST
670
671 START_TEST(unterminated_array)
672 {
673 QObject *obj = qobject_from_json("[32");
674 fail_unless(obj == NULL);
675 }
676 END_TEST
677
678 START_TEST(unterminated_array_comma)
679 {
680 QObject *obj = qobject_from_json("[32,");
681 fail_unless(obj == NULL);
682 }
683 END_TEST
684
685 START_TEST(invalid_array_comma)
686 {
687 QObject *obj = qobject_from_json("[32,}");
688 fail_unless(obj == NULL);
689 }
690 END_TEST
691
692 START_TEST(unterminated_dict)
693 {
694 QObject *obj = qobject_from_json("{'abc':32");
695 fail_unless(obj == NULL);
696 }
697 END_TEST
698
699 START_TEST(unterminated_dict_comma)
700 {
701 QObject *obj = qobject_from_json("{'abc':32,");
702 fail_unless(obj == NULL);
703 }
704 END_TEST
705
706 #if 0
707 START_TEST(invalid_dict_comma)
708 {
709 QObject *obj = qobject_from_json("{'abc':32,}");
710 fail_unless(obj == NULL);
711 }
712 END_TEST
713
714 START_TEST(unterminated_literal)
715 {
716 QObject *obj = qobject_from_json("nul");
717 fail_unless(obj == NULL);
718 }
719 END_TEST
720 #endif
721
722 static Suite *qjson_suite(void)
723 {
724 Suite *suite;
725 TCase *string_literals, *number_literals, *keyword_literals;
726 TCase *dicts, *lists, *whitespace, *varargs, *errors;
727
728 string_literals = tcase_create("String Literals");
729 tcase_add_test(string_literals, simple_string);
730 tcase_add_test(string_literals, escaped_string);
731 tcase_add_test(string_literals, single_quote_string);
732 tcase_add_test(string_literals, vararg_string);
733
734 number_literals = tcase_create("Number Literals");
735 tcase_add_test(number_literals, simple_number);
736 tcase_add_test(number_literals, float_number);
737 tcase_add_test(number_literals, vararg_number);
738
739 keyword_literals = tcase_create("Keywords");
740 tcase_add_test(keyword_literals, keyword_literal);
741 dicts = tcase_create("Objects");
742 tcase_add_test(dicts, simple_dict);
743 lists = tcase_create("Lists");
744 tcase_add_test(lists, simple_list);
745
746 whitespace = tcase_create("Whitespace");
747 tcase_add_test(whitespace, simple_whitespace);
748
749 varargs = tcase_create("Varargs");
750 tcase_add_test(varargs, simple_varargs);
751
752 errors = tcase_create("Invalid JSON");
753 tcase_add_test(errors, empty_input);
754 tcase_add_test(errors, unterminated_string);
755 tcase_add_test(errors, unterminated_escape);
756 tcase_add_test(errors, unterminated_sq_string);
757 tcase_add_test(errors, unterminated_array);
758 tcase_add_test(errors, unterminated_array_comma);
759 tcase_add_test(errors, invalid_array_comma);
760 tcase_add_test(errors, unterminated_dict);
761 tcase_add_test(errors, unterminated_dict_comma);
762 #if 0
763 /* FIXME: this print parse error messages on stderr. */
764 tcase_add_test(errors, invalid_dict_comma);
765 tcase_add_test(errors, unterminated_literal);
766 #endif
767
768 suite = suite_create("QJSON test-suite");
769 suite_add_tcase(suite, string_literals);
770 suite_add_tcase(suite, number_literals);
771 suite_add_tcase(suite, keyword_literals);
772 suite_add_tcase(suite, dicts);
773 suite_add_tcase(suite, lists);
774 suite_add_tcase(suite, whitespace);
775 suite_add_tcase(suite, varargs);
776 suite_add_tcase(suite, errors);
777
778 return suite;
779 }
780
781 int main(void)
782 {
783 int nf;
784 Suite *s;
785 SRunner *sr;
786
787 s = qjson_suite();
788 sr = srunner_create(s);
789
790 srunner_run_all(sr, CK_NORMAL);
791 nf = srunner_ntests_failed(sr);
792 srunner_free(sr);
793
794 return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
795 }