1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski #include <stdlib.h>
25*b1cdbd2cSJim Jagielski #include <stdio.h>
26*b1cdbd2cSJim Jagielski #include <fcntl.h>
27*b1cdbd2cSJim Jagielski #include <errno.h>
28*b1cdbd2cSJim Jagielski #include <string.h>
29*b1cdbd2cSJim Jagielski #include <unistd.h>
30*b1cdbd2cSJim Jagielski #include <ctype.h>
31*b1cdbd2cSJim Jagielski #include <sal/alloca.h>
32*b1cdbd2cSJim Jagielski 
33*b1cdbd2cSJim Jagielski #include <rtl/ustring.hxx>
34*b1cdbd2cSJim Jagielski 
35*b1cdbd2cSJim Jagielski #include <map>
36*b1cdbd2cSJim Jagielski #include <string>
37*b1cdbd2cSJim Jagielski 
38*b1cdbd2cSJim Jagielski /*****************************************************************************
39*b1cdbd2cSJim Jagielski  * typedefs
40*b1cdbd2cSJim Jagielski  *****************************************************************************/
41*b1cdbd2cSJim Jagielski 
42*b1cdbd2cSJim Jagielski typedef std::map< const std::string, rtl_TextEncoding > EncodingMap;
43*b1cdbd2cSJim Jagielski 
44*b1cdbd2cSJim Jagielski struct _pair {
45*b1cdbd2cSJim Jagielski     const char *key;
46*b1cdbd2cSJim Jagielski     rtl_TextEncoding value;
47*b1cdbd2cSJim Jagielski };
48*b1cdbd2cSJim Jagielski 
49*b1cdbd2cSJim Jagielski static int _pair_compare (const char *key, const _pair *pair);
50*b1cdbd2cSJim Jagielski static const _pair* _pair_search (const char *key, const _pair *base, unsigned int member );
51*b1cdbd2cSJim Jagielski 
52*b1cdbd2cSJim Jagielski 
53*b1cdbd2cSJim Jagielski const _pair _ms_encoding_list[] = {
54*b1cdbd2cSJim Jagielski     { "0",       RTL_TEXTENCODING_UTF8        },
55*b1cdbd2cSJim Jagielski     { "1250",    RTL_TEXTENCODING_MS_1250     },
56*b1cdbd2cSJim Jagielski     { "1251",    RTL_TEXTENCODING_MS_1251     },
57*b1cdbd2cSJim Jagielski     { "1252",    RTL_TEXTENCODING_MS_1252     },
58*b1cdbd2cSJim Jagielski     { "1253",    RTL_TEXTENCODING_MS_1253     },
59*b1cdbd2cSJim Jagielski     { "1254",    RTL_TEXTENCODING_MS_1254     },
60*b1cdbd2cSJim Jagielski     { "1255",    RTL_TEXTENCODING_MS_1255     },
61*b1cdbd2cSJim Jagielski     { "1256",    RTL_TEXTENCODING_MS_1256     },
62*b1cdbd2cSJim Jagielski     { "1257",    RTL_TEXTENCODING_MS_1257     },
63*b1cdbd2cSJim Jagielski     { "1258",    RTL_TEXTENCODING_MS_1258     },
64*b1cdbd2cSJim Jagielski     { "874",     RTL_TEXTENCODING_MS_874      },
65*b1cdbd2cSJim Jagielski     { "932",     RTL_TEXTENCODING_MS_932      },
66*b1cdbd2cSJim Jagielski     { "936",     RTL_TEXTENCODING_MS_936      },
67*b1cdbd2cSJim Jagielski     { "949",     RTL_TEXTENCODING_MS_949      },
68*b1cdbd2cSJim Jagielski     { "950",     RTL_TEXTENCODING_MS_950      }
69*b1cdbd2cSJim Jagielski };
70*b1cdbd2cSJim Jagielski 
71*b1cdbd2cSJim Jagielski 
72*b1cdbd2cSJim Jagielski /*****************************************************************************
73*b1cdbd2cSJim Jagielski  * fgets that work with unix line ends on Windows
74*b1cdbd2cSJim Jagielski  *****************************************************************************/
75*b1cdbd2cSJim Jagielski 
my_fgets(char * s,int n,FILE * fp)76*b1cdbd2cSJim Jagielski char * my_fgets(char *s, int n, FILE *fp)
77*b1cdbd2cSJim Jagielski {
78*b1cdbd2cSJim Jagielski     int i;
79*b1cdbd2cSJim Jagielski     for( i=0; i < n-1; i++ )
80*b1cdbd2cSJim Jagielski     {
81*b1cdbd2cSJim Jagielski         int c = getc(fp);
82*b1cdbd2cSJim Jagielski 
83*b1cdbd2cSJim Jagielski         if( c == EOF )
84*b1cdbd2cSJim Jagielski             break;
85*b1cdbd2cSJim Jagielski 
86*b1cdbd2cSJim Jagielski         s[i] = (char) c;
87*b1cdbd2cSJim Jagielski 
88*b1cdbd2cSJim Jagielski         if( s[i] == '\n' )
89*b1cdbd2cSJim Jagielski         {
90*b1cdbd2cSJim Jagielski             i++;
91*b1cdbd2cSJim Jagielski             break;
92*b1cdbd2cSJim Jagielski         }
93*b1cdbd2cSJim Jagielski     }
94*b1cdbd2cSJim Jagielski 
95*b1cdbd2cSJim Jagielski     if( i>0 )
96*b1cdbd2cSJim Jagielski     {
97*b1cdbd2cSJim Jagielski         s[i] = '\0';
98*b1cdbd2cSJim Jagielski         return s;
99*b1cdbd2cSJim Jagielski     }
100*b1cdbd2cSJim Jagielski     else
101*b1cdbd2cSJim Jagielski     {
102*b1cdbd2cSJim Jagielski         return NULL;
103*b1cdbd2cSJim Jagielski     }
104*b1cdbd2cSJim Jagielski }
105*b1cdbd2cSJim Jagielski 
106*b1cdbd2cSJim Jagielski /*****************************************************************************
107*b1cdbd2cSJim Jagielski  * compare function for binary search
108*b1cdbd2cSJim Jagielski  *****************************************************************************/
109*b1cdbd2cSJim Jagielski 
110*b1cdbd2cSJim Jagielski static int
_pair_compare(const char * key,const _pair * pair)111*b1cdbd2cSJim Jagielski _pair_compare (const char *key, const _pair *pair)
112*b1cdbd2cSJim Jagielski {
113*b1cdbd2cSJim Jagielski     int result = rtl_str_compareIgnoreAsciiCase( key, pair->key );
114*b1cdbd2cSJim Jagielski     return result;
115*b1cdbd2cSJim Jagielski }
116*b1cdbd2cSJim Jagielski 
117*b1cdbd2cSJim Jagielski /*****************************************************************************
118*b1cdbd2cSJim Jagielski  * binary search on encoding tables
119*b1cdbd2cSJim Jagielski  *****************************************************************************/
120*b1cdbd2cSJim Jagielski 
121*b1cdbd2cSJim Jagielski static const _pair*
_pair_search(const char * key,const _pair * base,unsigned int member)122*b1cdbd2cSJim Jagielski _pair_search (const char *key, const _pair *base, unsigned int member )
123*b1cdbd2cSJim Jagielski {
124*b1cdbd2cSJim Jagielski     unsigned int lower = 0;
125*b1cdbd2cSJim Jagielski     unsigned int upper = member;
126*b1cdbd2cSJim Jagielski     unsigned int current;
127*b1cdbd2cSJim Jagielski     int comparison;
128*b1cdbd2cSJim Jagielski 
129*b1cdbd2cSJim Jagielski     /* check for validity of input */
130*b1cdbd2cSJim Jagielski     if ( (key == NULL) || (base == NULL) || (member == 0) )
131*b1cdbd2cSJim Jagielski         return NULL;
132*b1cdbd2cSJim Jagielski 
133*b1cdbd2cSJim Jagielski     /* binary search */
134*b1cdbd2cSJim Jagielski     while ( lower < upper )
135*b1cdbd2cSJim Jagielski     {
136*b1cdbd2cSJim Jagielski         current = (lower + upper) / 2;
137*b1cdbd2cSJim Jagielski         comparison = _pair_compare( key, base + current );
138*b1cdbd2cSJim Jagielski         if (comparison < 0)
139*b1cdbd2cSJim Jagielski             upper = current;
140*b1cdbd2cSJim Jagielski         else
141*b1cdbd2cSJim Jagielski         if (comparison > 0)
142*b1cdbd2cSJim Jagielski             lower = current + 1;
143*b1cdbd2cSJim Jagielski         else
144*b1cdbd2cSJim Jagielski             return base + current;
145*b1cdbd2cSJim Jagielski     }
146*b1cdbd2cSJim Jagielski 
147*b1cdbd2cSJim Jagielski     return NULL;
148*b1cdbd2cSJim Jagielski }
149*b1cdbd2cSJim Jagielski 
150*b1cdbd2cSJim Jagielski 
151*b1cdbd2cSJim Jagielski /************************************************************************
152*b1cdbd2cSJim Jagielski  * read_encoding_table
153*b1cdbd2cSJim Jagielski  ************************************************************************/
154*b1cdbd2cSJim Jagielski 
read_encoding_table(char * file,EncodingMap & aEncodingMap)155*b1cdbd2cSJim Jagielski void read_encoding_table(char * file, EncodingMap& aEncodingMap)
156*b1cdbd2cSJim Jagielski {
157*b1cdbd2cSJim Jagielski     FILE * fp = fopen(file, "r");
158*b1cdbd2cSJim Jagielski     if ( ! fp  ) {
159*b1cdbd2cSJim Jagielski         fprintf(stderr, "ulfconv: %s %s\n", file, strerror(errno));
160*b1cdbd2cSJim Jagielski         exit(2);
161*b1cdbd2cSJim Jagielski     }
162*b1cdbd2cSJim Jagielski 
163*b1cdbd2cSJim Jagielski     char buffer[512];
164*b1cdbd2cSJim Jagielski     while ( NULL != my_fgets(buffer, sizeof(buffer), fp) ) {
165*b1cdbd2cSJim Jagielski 
166*b1cdbd2cSJim Jagielski         // strip comment lines
167*b1cdbd2cSJim Jagielski         if ( buffer[0] == '#' )
168*b1cdbd2cSJim Jagielski             continue;
169*b1cdbd2cSJim Jagielski 
170*b1cdbd2cSJim Jagielski         // find end of language string
171*b1cdbd2cSJim Jagielski         char * cp;
172*b1cdbd2cSJim Jagielski         for ( cp = buffer; ! isspace(*cp); cp++ )
173*b1cdbd2cSJim Jagielski             ;
174*b1cdbd2cSJim Jagielski         *cp = '\0';
175*b1cdbd2cSJim Jagielski 
176*b1cdbd2cSJim Jagielski         // find start of codepage string
177*b1cdbd2cSJim Jagielski         for ( ++cp; isspace(*cp); ++cp )
178*b1cdbd2cSJim Jagielski             ;
179*b1cdbd2cSJim Jagielski         char * codepage = cp;
180*b1cdbd2cSJim Jagielski 
181*b1cdbd2cSJim Jagielski         // find end of codepage string
182*b1cdbd2cSJim Jagielski         for ( ++cp; ! isspace(*cp); ++cp )
183*b1cdbd2cSJim Jagielski             ;
184*b1cdbd2cSJim Jagielski         *cp = '\0';
185*b1cdbd2cSJim Jagielski 
186*b1cdbd2cSJim Jagielski         // find the correct mapping for codepage
187*b1cdbd2cSJim Jagielski         const unsigned int members = sizeof( _ms_encoding_list ) / sizeof( _pair );
188*b1cdbd2cSJim Jagielski         const _pair *encoding = _pair_search( codepage, _ms_encoding_list, members );
189*b1cdbd2cSJim Jagielski 
190*b1cdbd2cSJim Jagielski         if ( encoding != NULL ) {
191*b1cdbd2cSJim Jagielski             const std::string language(buffer);
192*b1cdbd2cSJim Jagielski             aEncodingMap.insert( EncodingMap::value_type(language, encoding->value) );
193*b1cdbd2cSJim Jagielski         }
194*b1cdbd2cSJim Jagielski     }
195*b1cdbd2cSJim Jagielski 
196*b1cdbd2cSJim Jagielski     fclose(fp);
197*b1cdbd2cSJim Jagielski }
198*b1cdbd2cSJim Jagielski 
199*b1cdbd2cSJim Jagielski /************************************************************************
200*b1cdbd2cSJim Jagielski  * print_legacy_mixed
201*b1cdbd2cSJim Jagielski  ************************************************************************/
202*b1cdbd2cSJim Jagielski 
print_legacy_mixed(FILE * ostream,const rtl::OUString & aString,const std::string & language,EncodingMap & aEncodingMap)203*b1cdbd2cSJim Jagielski void print_legacy_mixed(
204*b1cdbd2cSJim Jagielski     FILE * ostream,
205*b1cdbd2cSJim Jagielski     const rtl::OUString& aString,
206*b1cdbd2cSJim Jagielski     const std::string& language,
207*b1cdbd2cSJim Jagielski     EncodingMap& aEncodingMap)
208*b1cdbd2cSJim Jagielski {
209*b1cdbd2cSJim Jagielski     EncodingMap::iterator iter = aEncodingMap.find(language);
210*b1cdbd2cSJim Jagielski 
211*b1cdbd2cSJim Jagielski     if ( iter != aEncodingMap.end() ) {
212*b1cdbd2cSJim Jagielski         fputs(OUStringToOString(aString, iter->second).getStr(), ostream);
213*b1cdbd2cSJim Jagielski     } else {
214*b1cdbd2cSJim Jagielski         fprintf(stderr, "ulfconv: WARNING: no legacy encoding found for %s\n", language.c_str());
215*b1cdbd2cSJim Jagielski     }
216*b1cdbd2cSJim Jagielski }
217*b1cdbd2cSJim Jagielski 
218*b1cdbd2cSJim Jagielski /************************************************************************
219*b1cdbd2cSJim Jagielski  * print_java_style
220*b1cdbd2cSJim Jagielski  ************************************************************************/
221*b1cdbd2cSJim Jagielski 
print_java_style(FILE * ostream,const rtl::OUString & aString)222*b1cdbd2cSJim Jagielski void print_java_style(FILE * ostream, const rtl::OUString& aString)
223*b1cdbd2cSJim Jagielski {
224*b1cdbd2cSJim Jagielski     int imax = aString.getLength();
225*b1cdbd2cSJim Jagielski     for (int i = 0; i < imax; i++) {
226*b1cdbd2cSJim Jagielski         sal_Unicode uc = aString[i];
227*b1cdbd2cSJim Jagielski         if ( uc < 128 ) {
228*b1cdbd2cSJim Jagielski             fprintf(ostream, "%c", (char) uc);
229*b1cdbd2cSJim Jagielski         } else {
230*b1cdbd2cSJim Jagielski             fprintf(ostream, "\\u%2.2x%2.2x", uc >> 8, uc & 0xFF );
231*b1cdbd2cSJim Jagielski         }
232*b1cdbd2cSJim Jagielski     }
233*b1cdbd2cSJim Jagielski }
234*b1cdbd2cSJim Jagielski 
235*b1cdbd2cSJim Jagielski /************************************************************************
236*b1cdbd2cSJim Jagielski  * main
237*b1cdbd2cSJim Jagielski  ************************************************************************/
238*b1cdbd2cSJim Jagielski 
main(int argc,char * const argv[])239*b1cdbd2cSJim Jagielski int main( int argc, char * const argv[] )
240*b1cdbd2cSJim Jagielski {
241*b1cdbd2cSJim Jagielski     EncodingMap aEncodingMap;
242*b1cdbd2cSJim Jagielski 
243*b1cdbd2cSJim Jagielski     FILE *istream = stdin;
244*b1cdbd2cSJim Jagielski     FILE *ostream = stdout;
245*b1cdbd2cSJim Jagielski 
246*b1cdbd2cSJim Jagielski     char *outfile = NULL;
247*b1cdbd2cSJim Jagielski 
248*b1cdbd2cSJim Jagielski     int errflg = 0;
249*b1cdbd2cSJim Jagielski     int argi;
250*b1cdbd2cSJim Jagielski 
251*b1cdbd2cSJim Jagielski     for( argi=1; argi < argc; argi++ )
252*b1cdbd2cSJim Jagielski     {
253*b1cdbd2cSJim Jagielski         if( argv[argi][0] == '-' && argv[argi][2] == '\0' )
254*b1cdbd2cSJim Jagielski         {
255*b1cdbd2cSJim Jagielski             switch(argv[argi][1]) {
256*b1cdbd2cSJim Jagielski             case 'o':
257*b1cdbd2cSJim Jagielski                 if (argi+1 >= argc || argv[argi+1][0] == '-')
258*b1cdbd2cSJim Jagielski                 {
259*b1cdbd2cSJim Jagielski                     fprintf(stderr, "Option -%c requires an operand\n", argv[argi][1]);
260*b1cdbd2cSJim Jagielski                     errflg++;
261*b1cdbd2cSJim Jagielski                     break;
262*b1cdbd2cSJim Jagielski                 }
263*b1cdbd2cSJim Jagielski 
264*b1cdbd2cSJim Jagielski                 ++argi;
265*b1cdbd2cSJim Jagielski                 outfile = argv[argi];
266*b1cdbd2cSJim Jagielski                 break;
267*b1cdbd2cSJim Jagielski             case 't':
268*b1cdbd2cSJim Jagielski                 if (argi+1 >= argc || argv[argi+1][0] == '-')
269*b1cdbd2cSJim Jagielski                 {
270*b1cdbd2cSJim Jagielski                     fprintf(stderr, "Option -%c requires an operand\n", argv[argi][1]);
271*b1cdbd2cSJim Jagielski                     errflg++;
272*b1cdbd2cSJim Jagielski                     break;
273*b1cdbd2cSJim Jagielski                 }
274*b1cdbd2cSJim Jagielski 
275*b1cdbd2cSJim Jagielski                 read_encoding_table(argv[++argi], aEncodingMap);
276*b1cdbd2cSJim Jagielski                 break;
277*b1cdbd2cSJim Jagielski             default:
278*b1cdbd2cSJim Jagielski                 fprintf(stderr, "Unrecognized option: -%c\n", argv[argi][1]);
279*b1cdbd2cSJim Jagielski                 errflg++;
280*b1cdbd2cSJim Jagielski             }
281*b1cdbd2cSJim Jagielski         }
282*b1cdbd2cSJim Jagielski         else
283*b1cdbd2cSJim Jagielski         {
284*b1cdbd2cSJim Jagielski             break;
285*b1cdbd2cSJim Jagielski         }
286*b1cdbd2cSJim Jagielski     }
287*b1cdbd2cSJim Jagielski 
288*b1cdbd2cSJim Jagielski     if (errflg) {
289*b1cdbd2cSJim Jagielski       fprintf(stderr, "Usage: ulfconv [-o <output file>] [-t <encoding table>] [<ulf file>]\n");
290*b1cdbd2cSJim Jagielski       exit(2);
291*b1cdbd2cSJim Jagielski     }
292*b1cdbd2cSJim Jagielski 
293*b1cdbd2cSJim Jagielski     /* assign input file to stdin */
294*b1cdbd2cSJim Jagielski     if ( argi < argc )
295*b1cdbd2cSJim Jagielski     {
296*b1cdbd2cSJim Jagielski         istream = fopen(argv[argi], "r");
297*b1cdbd2cSJim Jagielski         if ( istream  == NULL ) {
298*b1cdbd2cSJim Jagielski             fprintf(stderr, "ulfconv: %s : %s\n", argv[argi], strerror(errno));
299*b1cdbd2cSJim Jagielski             exit(2);
300*b1cdbd2cSJim Jagielski         }
301*b1cdbd2cSJim Jagielski     }
302*b1cdbd2cSJim Jagielski 
303*b1cdbd2cSJim Jagielski 	/* open output file if any */
304*b1cdbd2cSJim Jagielski 	if ( outfile )
305*b1cdbd2cSJim Jagielski 	{
306*b1cdbd2cSJim Jagielski         ostream = fopen(outfile, "w");
307*b1cdbd2cSJim Jagielski         if ( ostream == NULL ) {
308*b1cdbd2cSJim Jagielski             fprintf(stderr, "ulfconv: %s : %s\n", outfile, strerror(errno));
309*b1cdbd2cSJim Jagielski             fclose(istream);
310*b1cdbd2cSJim Jagielski             exit(2);
311*b1cdbd2cSJim Jagielski         }
312*b1cdbd2cSJim Jagielski 	}
313*b1cdbd2cSJim Jagielski 
314*b1cdbd2cSJim Jagielski     /* read line by line from stdin */
315*b1cdbd2cSJim Jagielski     char buffer[65536];
316*b1cdbd2cSJim Jagielski     while ( NULL != fgets(buffer, sizeof(buffer), istream) ) {
317*b1cdbd2cSJim Jagielski 
318*b1cdbd2cSJim Jagielski         /* only handle lines containing " = " */
319*b1cdbd2cSJim Jagielski         char * cp = strstr(buffer, " = \"");
320*b1cdbd2cSJim Jagielski         if ( cp ) {
321*b1cdbd2cSJim Jagielski             rtl::OUString aString;
322*b1cdbd2cSJim Jagielski 
323*b1cdbd2cSJim Jagielski             /* find end of lang string */
324*b1cdbd2cSJim Jagielski             int n;
325*b1cdbd2cSJim Jagielski             for ( n=0; ! isspace(buffer[n]); n++ )
326*b1cdbd2cSJim Jagielski                 ;
327*b1cdbd2cSJim Jagielski 
328*b1cdbd2cSJim Jagielski             std::string line = buffer;
329*b1cdbd2cSJim Jagielski             std::string lang(line, 0, n);
330*b1cdbd2cSJim Jagielski 
331*b1cdbd2cSJim Jagielski             cp += 4;
332*b1cdbd2cSJim Jagielski             rtl_string2UString( &aString.pData, cp, strrchr(cp, '\"') - cp,
333*b1cdbd2cSJim Jagielski                 RTL_TEXTENCODING_UTF8, OSTRING_TO_OUSTRING_CVTFLAGS );
334*b1cdbd2cSJim Jagielski 
335*b1cdbd2cSJim Jagielski             fprintf(ostream, "%s = \"", lang.c_str());
336*b1cdbd2cSJim Jagielski 
337*b1cdbd2cSJim Jagielski             if ( aEncodingMap.empty() ) {
338*b1cdbd2cSJim Jagielski                 print_java_style(ostream, aString);
339*b1cdbd2cSJim Jagielski             } else {
340*b1cdbd2cSJim Jagielski                 print_legacy_mixed(ostream, aString, lang, aEncodingMap);
341*b1cdbd2cSJim Jagielski             }
342*b1cdbd2cSJim Jagielski 
343*b1cdbd2cSJim Jagielski             fprintf(ostream, "\"\n");
344*b1cdbd2cSJim Jagielski 
345*b1cdbd2cSJim Jagielski 
346*b1cdbd2cSJim Jagielski         } else {
347*b1cdbd2cSJim Jagielski             fputs(buffer, ostream);
348*b1cdbd2cSJim Jagielski         }
349*b1cdbd2cSJim Jagielski     }
350*b1cdbd2cSJim Jagielski 
351*b1cdbd2cSJim Jagielski     fclose(ostream);
352*b1cdbd2cSJim Jagielski     fclose(istream);
353*b1cdbd2cSJim Jagielski }
354