New function mem_iconveh.
[pspp] / tests / test-striconveh.c
1 /* Test of character set conversion with error handling.
2    Copyright (C) 2007 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2, or (at your option)
7    any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software Foundation,
16    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
17
18 /* Written by Bruno Haible <bruno@clisp.org>, 2007.  */
19
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23
24 #include "striconveh.h"
25
26 #if HAVE_ICONV
27 # include <iconv.h>
28 #endif
29
30 #include <errno.h>
31 #include <stdlib.h>
32 #include <string.h>
33
34 #define SIZEOF(array) (sizeof (array) / sizeof (array[0]))
35 #define ASSERT(expr) if (!(expr)) abort ();
36
37 int
38 main ()
39 {
40   static enum iconv_ilseq_handler handlers[] =
41     { iconveh_error, iconveh_question_mark, iconveh_escape_sequence };
42   size_t h;
43
44 #if HAVE_ICONV
45   /* Assume that iconv() supports at least the encodings ASCII, ISO-8859-1,
46      ISO-8859-2, and UTF-8.  */
47   iconv_t cd_88591_to_88592 = iconv_open ("ISO-8859-2", "ISO-8859-1");
48   iconv_t cd_88592_to_88591 = iconv_open ("ISO-8859-1", "ISO-8859-2");
49   iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1");
50   iconv_t cd_utf8_to_88591 = iconv_open ("ISO-8859-1", "UTF-8");
51   iconv_t cd_88592_to_utf8 = iconv_open ("UTF-8", "ISO-8859-2");
52   iconv_t cd_utf8_to_88592 = iconv_open ("ISO-8859-2", "UTF-8");
53
54   ASSERT (cd_88591_to_88592 != (iconv_t)(-1));
55   ASSERT (cd_88592_to_88591 != (iconv_t)(-1));
56   ASSERT (cd_88591_to_utf8 != (iconv_t)(-1));
57   ASSERT (cd_utf8_to_88591 != (iconv_t)(-1));
58   ASSERT (cd_88592_to_utf8 != (iconv_t)(-1));
59   ASSERT (cd_utf8_to_88592 != (iconv_t)(-1));
60
61   /* ------------------------ Test mem_cd_iconveh() ------------------------ */
62
63   /* Test conversion from ISO-8859-2 to ISO-8859-1 with no errors.  */
64   for (h = 0; h < SIZEOF (handlers); h++)
65     {
66       enum iconv_ilseq_handler handler = handlers[h];
67       static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
68       static const char expected[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
69       char *result = NULL;
70       size_t length = 0;
71       int retval = mem_cd_iconveh (input, strlen (input),
72                                    cd_88592_to_88591,
73                                    cd_88592_to_utf8, cd_utf8_to_88591,
74                                    handler,
75                                    &result, &length);
76       ASSERT (retval == 0);
77       ASSERT (length == strlen (expected));
78       ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
79       free (result);
80     }
81
82   /* Test conversion from ISO-8859-2 to ISO-8859-1 with EILSEQ.  */
83   for (h = 0; h < SIZEOF (handlers); h++)
84     {
85       enum iconv_ilseq_handler handler = handlers[h];
86       static const char input[] = "Rafa\263 Maszkowski"; /* Rafał Maszkowski */
87       char *result = NULL;
88       size_t length = 0;
89       int retval = mem_cd_iconveh (input, strlen (input),
90                                    cd_88592_to_88591,
91                                    cd_88592_to_utf8, cd_utf8_to_88591,
92                                    handler,
93                                    &result, &length);
94       switch (handler)
95         {
96         case iconveh_error:
97           ASSERT (retval == -1 && errno == EILSEQ);
98           ASSERT (result == NULL);
99           break;
100         case iconveh_question_mark:
101           {
102             static const char expected[] = "Rafa? Maszkowski";
103             ASSERT (retval == 0);
104             ASSERT (length == strlen (expected));
105             ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
106             free (result);
107           }
108           break;
109         case iconveh_escape_sequence:
110           {
111             static const char expected[] = "Rafa\\u0142 Maszkowski";
112             ASSERT (retval == 0);
113             ASSERT (length == strlen (expected));
114             ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
115             free (result);
116           }
117           break;
118         }
119     }
120
121   /* Test conversion from ISO-8859-1 to UTF-8 with no errors.  */
122   for (h = 0; h < SIZEOF (handlers); h++)
123     {
124       enum iconv_ilseq_handler handler = handlers[h];
125       static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
126       static const char expected[] = "\303\204rger mit b\303\266sen B\303\274bchen ohne Augenma\303\237";
127       char *result = NULL;
128       size_t length = 0;
129       int retval = mem_cd_iconveh (input, strlen (input),
130                                    cd_88591_to_utf8,
131                                    cd_88591_to_utf8, (iconv_t)(-1),
132                                    handler,
133                                    &result, &length);
134       ASSERT (retval == 0);
135       ASSERT (length == strlen (expected));
136       ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
137       free (result);
138     }
139
140   /* Test conversion from UTF-8 to ISO-8859-1 with no errors.  */
141   for (h = 0; h < SIZEOF (handlers); h++)
142     {
143       enum iconv_ilseq_handler handler = handlers[h];
144       static const char input[] = "\303\204rger mit b\303\266sen B\303\274bchen ohne Augenma\303\237";
145       static const char expected[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
146       char *result = NULL;
147       size_t length = 0;
148       int retval = mem_cd_iconveh (input, strlen (input),
149                                    cd_utf8_to_88591,
150                                    (iconv_t)(-1), cd_utf8_to_88591,
151                                    handler,
152                                    &result, &length);
153       ASSERT (retval == 0);
154       ASSERT (length == strlen (expected));
155       ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
156       free (result);
157     }
158
159   /* Test conversion from UTF-8 to ISO-8859-1 with EILSEQ.  */
160   for (h = 0; h < SIZEOF (handlers); h++)
161     {
162       enum iconv_ilseq_handler handler = handlers[h];
163       static const char input[] = "Rafa\305\202 Maszkowski"; /* Rafał Maszkowski */
164       char *result = NULL;
165       size_t length = 0;
166       int retval = mem_cd_iconveh (input, strlen (input),
167                                    cd_utf8_to_88591,
168                                    (iconv_t)(-1), cd_utf8_to_88591,
169                                    handler,
170                                    &result, &length);
171       switch (handler)
172         {
173         case iconveh_error:
174           ASSERT (retval == -1 && errno == EILSEQ);
175           ASSERT (result == NULL);
176           break;
177         case iconveh_question_mark:
178           {
179             static const char expected[] = "Rafa? Maszkowski";
180             ASSERT (retval == 0);
181             ASSERT (length == strlen (expected));
182             ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
183             free (result);
184           }
185           break;
186         case iconveh_escape_sequence:
187           {
188             static const char expected[] = "Rafa\\u0142 Maszkowski";
189             ASSERT (retval == 0);
190             ASSERT (length == strlen (expected));
191             ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
192             free (result);
193           }
194           break;
195         }
196     }
197
198   /* Test conversion from UTF-8 to ISO-8859-1 with EINVAL.  */
199   for (h = 0; h < SIZEOF (handlers); h++)
200     {
201       enum iconv_ilseq_handler handler = handlers[h];
202       static const char input[] = "\342";
203       char *result = NULL;
204       size_t length = 0;
205       int retval = mem_cd_iconveh (input, strlen (input),
206                                    cd_utf8_to_88591,
207                                    (iconv_t)(-1), cd_utf8_to_88591,
208                                    handler,
209                                    &result, &length);
210       ASSERT (retval == 0);
211       ASSERT (length == 0);
212       if (result != NULL)
213         free (result);
214     }
215
216   /* ------------------------ Test str_cd_iconveh() ------------------------ */
217
218   /* Test conversion from ISO-8859-2 to ISO-8859-1 with no errors.  */
219   for (h = 0; h < SIZEOF (handlers); h++)
220     {
221       enum iconv_ilseq_handler handler = handlers[h];
222       static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
223       static const char expected[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
224       char *result = str_cd_iconveh (input,
225                                      cd_88592_to_88591,
226                                      cd_88592_to_utf8, cd_utf8_to_88591,
227                                      handler);
228       ASSERT (result != NULL);
229       ASSERT (strcmp (result, expected) == 0);
230       free (result);
231     }
232
233   /* Test conversion from ISO-8859-2 to ISO-8859-1 with EILSEQ.  */
234   for (h = 0; h < SIZEOF (handlers); h++)
235     {
236       enum iconv_ilseq_handler handler = handlers[h];
237       static const char input[] = "Rafa\263 Maszkowski"; /* Rafał Maszkowski */
238       char *result = str_cd_iconveh (input,
239                                      cd_88592_to_88591,
240                                      cd_88592_to_utf8, cd_utf8_to_88591,
241                                      handler);
242       switch (handler)
243         {
244         case iconveh_error:
245           ASSERT (result == NULL && errno == EILSEQ);
246           break;
247         case iconveh_question_mark:
248           {
249             static const char expected[] = "Rafa? Maszkowski";
250             ASSERT (result != NULL);
251             ASSERT (strcmp (result, expected) == 0);
252             free (result);
253           }
254           break;
255         case iconveh_escape_sequence:
256           {
257             static const char expected[] = "Rafa\\u0142 Maszkowski";
258             ASSERT (result != NULL);
259             ASSERT (strcmp (result, expected) == 0);
260             free (result);
261           }
262           break;
263         }
264     }
265
266   /* Test conversion from ISO-8859-1 to UTF-8 with no errors.  */
267   for (h = 0; h < SIZEOF (handlers); h++)
268     {
269       enum iconv_ilseq_handler handler = handlers[h];
270       static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
271       static const char expected[] = "\303\204rger mit b\303\266sen B\303\274bchen ohne Augenma\303\237";
272       char *result = str_cd_iconveh (input,
273                                      cd_88591_to_utf8,
274                                      cd_88591_to_utf8, (iconv_t)(-1),
275                                      handler);
276       ASSERT (result != NULL);
277       ASSERT (strcmp (result, expected) == 0);
278       free (result);
279     }
280
281   /* Test conversion from UTF-8 to ISO-8859-1 with no errors.  */
282   for (h = 0; h < SIZEOF (handlers); h++)
283     {
284       enum iconv_ilseq_handler handler = handlers[h];
285       static const char input[] = "\303\204rger mit b\303\266sen B\303\274bchen ohne Augenma\303\237";
286       static const char expected[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
287       char *result = str_cd_iconveh (input,
288                                      cd_utf8_to_88591,
289                                      (iconv_t)(-1), cd_utf8_to_88591,
290                                      handler);
291       ASSERT (result != NULL);
292       ASSERT (strcmp (result, expected) == 0);
293       free (result);
294     }
295
296   /* Test conversion from UTF-8 to ISO-8859-1 with EILSEQ.  */
297   for (h = 0; h < SIZEOF (handlers); h++)
298     {
299       enum iconv_ilseq_handler handler = handlers[h];
300       static const char input[] = "Costs: 27 \342\202\254"; /* EURO SIGN */
301       char *result = str_cd_iconveh (input,
302                                      cd_utf8_to_88591,
303                                      (iconv_t)(-1), cd_utf8_to_88591,
304                                      handler);
305       switch (handler)
306         {
307         case iconveh_error:
308           ASSERT (result == NULL && errno == EILSEQ);
309           break;
310         case iconveh_question_mark:
311           {
312             static const char expected[] = "Costs: 27 ?";
313             ASSERT (result != NULL);
314             ASSERT (strcmp (result, expected) == 0);
315             free (result);
316           }
317           break;
318         case iconveh_escape_sequence:
319           {
320             static const char expected[] = "Costs: 27 \\u20AC";
321             ASSERT (result != NULL);
322             ASSERT (strcmp (result, expected) == 0);
323             free (result);
324           }
325           break;
326         }
327     }
328
329   /* Test conversion from UTF-8 to ISO-8859-1 with EINVAL.  */
330   for (h = 0; h < SIZEOF (handlers); h++)
331     {
332       enum iconv_ilseq_handler handler = handlers[h];
333       static const char input[] = "\342";
334       char *result = str_cd_iconveh (input,
335                                      cd_utf8_to_88591,
336                                      (iconv_t)(-1), cd_utf8_to_88591,
337                                      handler);
338       ASSERT (result != NULL);
339       ASSERT (strcmp (result, "") == 0);
340       free (result);
341     }
342
343   iconv_close (cd_88591_to_88592);
344   iconv_close (cd_88592_to_88591);
345   iconv_close (cd_88591_to_utf8);
346   iconv_close (cd_utf8_to_88591);
347   iconv_close (cd_88592_to_utf8);
348   iconv_close (cd_utf8_to_88592);
349
350   /* ------------------------- Test mem_iconveh() ------------------------- */
351
352   /* Test conversion from ISO-8859-2 to ISO-8859-1 with no errors.  */
353   for (h = 0; h < SIZEOF (handlers); h++)
354     {
355       enum iconv_ilseq_handler handler = handlers[h];
356       static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
357       static const char expected[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
358       char *result = NULL;
359       size_t length = 0;
360       int retval = mem_iconveh (input, strlen (input),
361                                 "ISO-8859-2", "ISO-8859-1",
362                                 handler,
363                                 &result, &length);
364       ASSERT (retval == 0);
365       ASSERT (length == strlen (expected));
366       ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
367       free (result);
368     }
369
370   /* Test conversion from ISO-8859-2 to ISO-8859-1 with EILSEQ.  */
371   for (h = 0; h < SIZEOF (handlers); h++)
372     {
373       enum iconv_ilseq_handler handler = handlers[h];
374       static const char input[] = "Rafa\263 Maszkowski"; /* Rafał Maszkowski */
375       char *result = NULL;
376       size_t length = 0;
377       int retval = mem_iconveh (input, strlen (input),
378                                 "ISO-8859-2", "ISO-8859-1",
379                                 handler,
380                                 &result, &length);
381       switch (handler)
382         {
383         case iconveh_error:
384           ASSERT (retval == -1 && errno == EILSEQ);
385           ASSERT (result == NULL);
386           break;
387         case iconveh_question_mark:
388           {
389             static const char expected[] = "Rafa? Maszkowski";
390             ASSERT (retval == 0);
391             ASSERT (length == strlen (expected));
392             ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
393             free (result);
394           }
395           break;
396         case iconveh_escape_sequence:
397           {
398             static const char expected[] = "Rafa\\u0142 Maszkowski";
399             ASSERT (retval == 0);
400             ASSERT (length == strlen (expected));
401             ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
402             free (result);
403           }
404           break;
405         }
406     }
407
408   /* Test conversion from ISO-8859-1 to UTF-8 with no errors.  */
409   for (h = 0; h < SIZEOF (handlers); h++)
410     {
411       enum iconv_ilseq_handler handler = handlers[h];
412       static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
413       static const char expected[] = "\303\204rger mit b\303\266sen B\303\274bchen ohne Augenma\303\237";
414       char *result = NULL;
415       size_t length = 0;
416       int retval = mem_iconveh (input, strlen (input),
417                                 "ISO-8859-1", "UTF-8",
418                                 handler,
419                                 &result, &length);
420       ASSERT (retval == 0);
421       ASSERT (length == strlen (expected));
422       ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
423       free (result);
424     }
425
426   /* Test conversion from UTF-8 to ISO-8859-1 with no errors.  */
427   for (h = 0; h < SIZEOF (handlers); h++)
428     {
429       enum iconv_ilseq_handler handler = handlers[h];
430       static const char input[] = "\303\204rger mit b\303\266sen B\303\274bchen ohne Augenma\303\237";
431       static const char expected[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
432       char *result = NULL;
433       size_t length = 0;
434       int retval = mem_iconveh (input, strlen (input),
435                                 "UTF-8", "ISO-8859-1",
436                                 handler,
437                                 &result, &length);
438       ASSERT (retval == 0);
439       ASSERT (length == strlen (expected));
440       ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
441       free (result);
442     }
443
444   /* Test conversion from UTF-8 to ISO-8859-1 with EILSEQ.  */
445   for (h = 0; h < SIZEOF (handlers); h++)
446     {
447       enum iconv_ilseq_handler handler = handlers[h];
448       static const char input[] = "Rafa\305\202 Maszkowski"; /* Rafał Maszkowski */
449       char *result = NULL;
450       size_t length = 0;
451       int retval = mem_iconveh (input, strlen (input),
452                                 "UTF-8", "ISO-8859-1",
453                                 handler,
454                                 &result, &length);
455       switch (handler)
456         {
457         case iconveh_error:
458           ASSERT (retval == -1 && errno == EILSEQ);
459           ASSERT (result == NULL);
460           break;
461         case iconveh_question_mark:
462           {
463             static const char expected[] = "Rafa? Maszkowski";
464             ASSERT (retval == 0);
465             ASSERT (length == strlen (expected));
466             ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
467             free (result);
468           }
469           break;
470         case iconveh_escape_sequence:
471           {
472             static const char expected[] = "Rafa\\u0142 Maszkowski";
473             ASSERT (retval == 0);
474             ASSERT (length == strlen (expected));
475             ASSERT (result != NULL && memcmp (result, expected, strlen (expected)) == 0);
476             free (result);
477           }
478           break;
479         }
480     }
481
482   /* Test conversion from UTF-8 to ISO-8859-1 with EINVAL.  */
483   for (h = 0; h < SIZEOF (handlers); h++)
484     {
485       enum iconv_ilseq_handler handler = handlers[h];
486       static const char input[] = "\342";
487       char *result = NULL;
488       size_t length = 0;
489       int retval = mem_iconveh (input, strlen (input),
490                                 "UTF-8", "ISO-8859-1",
491                                 handler,
492                                 &result, &length);
493       ASSERT (retval == 0);
494       ASSERT (length == 0);
495       if (result != NULL)
496         free (result);
497     }
498
499   /* ------------------------- Test str_iconveh() ------------------------- */
500
501   /* Test conversion from ISO-8859-2 to ISO-8859-1 with no errors.  */
502   for (h = 0; h < SIZEOF (handlers); h++)
503     {
504       enum iconv_ilseq_handler handler = handlers[h];
505       static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
506       static const char expected[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
507       char *result = str_iconveh (input, "ISO-8859-2", "ISO-8859-1", handler);
508       ASSERT (result != NULL);
509       ASSERT (strcmp (result, expected) == 0);
510       free (result);
511     }
512
513   /* Test conversion from ISO-8859-2 to ISO-8859-1 with EILSEQ.  */
514   for (h = 0; h < SIZEOF (handlers); h++)
515     {
516       enum iconv_ilseq_handler handler = handlers[h];
517       static const char input[] = "Rafa\263 Maszkowski"; /* Rafał Maszkowski */
518       char *result = str_iconveh (input, "ISO-8859-2", "ISO-8859-1", handler);
519       switch (handler)
520         {
521         case iconveh_error:
522           ASSERT (result == NULL && errno == EILSEQ);
523           break;
524         case iconveh_question_mark:
525           {
526             static const char expected[] = "Rafa? Maszkowski";
527             ASSERT (result != NULL);
528             ASSERT (strcmp (result, expected) == 0);
529             free (result);
530           }
531           break;
532         case iconveh_escape_sequence:
533           {
534             static const char expected[] = "Rafa\\u0142 Maszkowski";
535             ASSERT (result != NULL);
536             ASSERT (strcmp (result, expected) == 0);
537             free (result);
538           }
539           break;
540         }
541     }
542
543   /* Test conversion from ISO-8859-1 to UTF-8 with no errors.  */
544   for (h = 0; h < SIZEOF (handlers); h++)
545     {
546       enum iconv_ilseq_handler handler = handlers[h];
547       static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
548       static const char expected[] = "\303\204rger mit b\303\266sen B\303\274bchen ohne Augenma\303\237";
549       char *result = str_iconveh (input, "ISO-8859-1", "UTF-8", handler);
550       ASSERT (result != NULL);
551       ASSERT (strcmp (result, expected) == 0);
552       free (result);
553     }
554
555   /* Test conversion from UTF-8 to ISO-8859-1 with no errors.  */
556   for (h = 0; h < SIZEOF (handlers); h++)
557     {
558       enum iconv_ilseq_handler handler = handlers[h];
559       static const char input[] = "\303\204rger mit b\303\266sen B\303\274bchen ohne Augenma\303\237";
560       static const char expected[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
561       char *result = str_iconveh (input, "UTF-8", "ISO-8859-1", handler);
562       ASSERT (result != NULL);
563       ASSERT (strcmp (result, expected) == 0);
564       free (result);
565     }
566
567   /* Test conversion from UTF-8 to ISO-8859-1 with EILSEQ.  */
568   for (h = 0; h < SIZEOF (handlers); h++)
569     {
570       enum iconv_ilseq_handler handler = handlers[h];
571       static const char input[] = "Costs: 27 \342\202\254"; /* EURO SIGN */
572       char *result = str_iconveh (input, "UTF-8", "ISO-8859-1", handler);
573       switch (handler)
574         {
575         case iconveh_error:
576           ASSERT (result == NULL && errno == EILSEQ);
577           break;
578         case iconveh_question_mark:
579           {
580             static const char expected[] = "Costs: 27 ?";
581             ASSERT (result != NULL);
582             ASSERT (strcmp (result, expected) == 0);
583             free (result);
584           }
585           break;
586         case iconveh_escape_sequence:
587           {
588             static const char expected[] = "Costs: 27 \\u20AC";
589             ASSERT (result != NULL);
590             ASSERT (strcmp (result, expected) == 0);
591             free (result);
592           }
593           break;
594         }
595     }
596
597   /* Test conversion from UTF-8 to ISO-8859-1 with EINVAL.  */
598   for (h = 0; h < SIZEOF (handlers); h++)
599     {
600       enum iconv_ilseq_handler handler = handlers[h];
601       static const char input[] = "\342";
602       char *result = str_iconveh (input, "UTF-8", "ISO-8859-1", handler);
603       ASSERT (result != NULL);
604       ASSERT (strcmp (result, "") == 0);
605       free (result);
606     }
607
608 #endif
609
610   return 0;
611 }