4 * Convert lf ('\x0a') characters in a file to cr lf ('\x0d' '\x0a')
7 * The dos2unix package is distributed under FreeBSD style license.
8 * See also http://www.freebsd.org/copyright/freebsd-license.html
11 * Copyright (C) 2009-2014 Erwin Waterlander
12 * Copyright (C) 1994-1995 Benjamin Lin.
13 * All rights reserved.
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice in the documentation and/or other materials provided with
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
25 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
30 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
31 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
33 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
34 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 * == 1.0 == 1989.10.04 == John Birchfield (jb@koko.csustan.edu)
37 * == 1.1 == 1994.12.20 == Benjamin Lin (blin@socs.uts.edu.au)
38 * Cleaned up for Borland C/C++ 4.02
39 * == 1.2 == 1995.03.09 == Benjamin Lin (blin@socs.uts.edu.au)
40 * Fixed minor typo error
41 * == 1.3 == 1995.03.16 == Benjamin Lin (blin@socs.uts.edu.au)
42 * Modified to more conform to UNIX style.
43 * == 2.0 == 1995.03.19 == Benjamin Lin (blin@socs.uts.edu.au)
44 * Rewritten from scratch.
45 * == 2.2 == 1995.03.30 == Benjamin Lin (blin@socs.uts.edu.au)
46 * Conversion from SunOS charset implemented.
48 * See ChangeLog.txt for complete version history.
59 #if !defined(__MSDOS__) && !defined(_WIN32) && !defined(__OS2__) /* Unix, Cygwin */
60 # include <langinfo.h>
64 void PrintLicense(void)
67 Copyright (C) 2009-2014 Erwin Waterlander\n\
68 Copyright (C) 1994-1995 Benjamin Lin\n\
69 All rights reserved.\n\n"));
74 void AddDOSNewLineW(FILE* ipOutF, CFlag *ipFlag, wint_t CurChar, wint_t PrevChar)
76 if (ipFlag->NewLine) { /* add additional CR-LF? */
77 /* Don't add line ending if it is a DOS line ending. Only in case of Unix line ending. */
78 if ((CurChar == 0x0a) && (PrevChar != 0x0d)) {
79 d2u_putwc(0x0d, ipOutF, ipFlag);
80 d2u_putwc(0x0a, ipOutF, ipFlag);
86 void AddDOSNewLine(FILE* ipOutF, CFlag *ipFlag, int CurChar, int PrevChar)
88 if (ipFlag->NewLine) { /* add additional CR-LF? */
89 /* Don't add line ending if it is a DOS line ending. Only in case of Unix line ending. */
90 if ((CurChar == '\x0a') && (PrevChar != '\x0d')) {
91 fputc('\x0d', ipOutF);
92 fputc('\x0a', ipOutF);
97 /* converts stream ipInF to DOS format text and write to stream ipOutF
98 * RetVal: 0 if success
102 int ConvertUnixToDosW(FILE* ipInF, FILE* ipOutF, CFlag *ipFlag, const char *progname)
106 wint_t PreviousChar = 0;
107 unsigned int line_nr = 1;
108 unsigned int converted = 0;
114 /* CR-LF -> CR-LF, in case the input file is a DOS text file */
115 /* \x0a = Newline/Line Feed (LF) */
116 /* \x0d = Carriage Return (CR) */
118 switch (ipFlag->FromToMode)
120 case FROMTO_UNIX2DOS: /* unix2dos */
121 while ((TempChar = d2u_getwc(ipInF, ipFlag->bomtype)) != WEOF) { /* get character */
122 if ((ipFlag->Force == 0) &&
124 (TempChar != 0x0a) && /* Not an LF */
125 (TempChar != 0x0d) && /* Not a CR */
126 (TempChar != 0x09) && /* Not a TAB */
127 (TempChar != 0x0c)) { /* Not a form feed */
129 ipFlag->status |= BINARY_FILE ;
130 if (ipFlag->verbose) {
131 if ((ipFlag->stdio_mode) && (!ipFlag->error)) ipFlag->error = 1;
132 fprintf(stderr, "%s: ", progname);
133 fprintf(stderr, _("Binary symbol 0x00%02X found at line %d\n"),TempChar, line_nr);
137 if (TempChar == 0x0a) {
138 d2u_putwc(0x0d, ipOutF, ipFlag); /* got LF, put extra CR */
141 if (TempChar == 0x0d) { /* got CR */
142 if ((TempChar = d2u_getwc(ipInF, ipFlag->bomtype)) == WEOF) /* get next char (possibly LF) */
143 TempChar = 0x0d; /* Read error, or end of file. */
145 d2u_putwc(0x0d, ipOutF, ipFlag); /* put CR */
150 if (TempChar == 0x0a) /* Count all DOS and Unix line breaks */
152 if (d2u_putwc(TempChar, ipOutF, ipFlag) == WEOF)
155 if (ipFlag->verbose) {
156 if (!(ipFlag->status & UNICODE_CONVERSION_ERROR)) {
157 ipFlag->error = errno;
158 errstr = strerror(errno);
159 fprintf(stderr, "%s: ", progname);
160 fprintf(stderr, _("can not write to output file: %s\n"), errstr);
165 AddDOSNewLineW( ipOutF, ipFlag, TempChar, PreviousChar);
167 PreviousChar = TempChar;
170 case FROMTO_UNIX2MAC: /* unix2mac */
171 while ((TempChar = d2u_getwc(ipInF, ipFlag->bomtype)) != WEOF) {
172 if ((ipFlag->Force == 0) &&
174 (TempChar != 0x0a) && /* Not an LF */
175 (TempChar != 0x0d) && /* Not a CR */
176 (TempChar != 0x09) && /* Not a TAB */
177 (TempChar != 0x0c)) { /* Not a form feed */
179 ipFlag->status |= BINARY_FILE ;
180 if (ipFlag->verbose) {
181 if ((ipFlag->stdio_mode) && (!ipFlag->error)) ipFlag->error = 1;
182 fprintf(stderr, "%s: ", progname);
183 fprintf(stderr, _("Binary symbol 0x00%02X found at line %d\n"),TempChar, line_nr);
187 if (TempChar != 0x0a) { /* Not an LF */
188 if(d2u_putwc(TempChar, ipOutF, ipFlag) == WEOF) {
190 if (ipFlag->verbose) {
191 if (!(ipFlag->status & UNICODE_CONVERSION_ERROR)) {
192 ipFlag->error = errno;
193 errstr = strerror(errno);
194 fprintf(stderr, "%s: ", progname);
195 fprintf(stderr, _("can not write to output file: %s\n"), errstr);
200 PreviousChar = TempChar;
201 if (TempChar == 0x0d) /* CR */
205 /* TempChar is an LF */
206 if (PreviousChar != 0x0d) /* CR already counted */
208 /* Don't touch this delimiter if it's a CR,LF pair. */
209 if ( PreviousChar == 0x0d ) {
210 if (d2u_putwc(0x0a, ipOutF, ipFlag) == WEOF) { /* CR,LF pair. Put LF */
212 if (ipFlag->verbose) {
213 if (!(ipFlag->status & UNICODE_CONVERSION_ERROR)) {
214 ipFlag->error = errno;
215 errstr = strerror(errno);
216 fprintf(stderr, "%s: ", progname);
217 fprintf(stderr, _("can not write to output file: %s\n"), errstr);
222 PreviousChar = TempChar;
225 PreviousChar = TempChar;
226 if (d2u_putwc(0x0d, ipOutF, ipFlag) == WEOF) { /* Unix line end (LF). Put CR */
228 if (ipFlag->verbose) {
229 if (!(ipFlag->status & UNICODE_CONVERSION_ERROR)) {
230 ipFlag->error = errno;
231 errstr = strerror(errno);
232 fprintf(stderr, "%s: ", progname);
233 fprintf(stderr, _("can not write to output file: %s\n"), errstr);
239 if (ipFlag->NewLine) { /* add additional CR? */
240 d2u_putwc(0x0d, ipOutF, ipFlag);
245 default: /* unknown FromToMode */
248 fprintf(stderr, "%s: ", progname);
249 fprintf(stderr, _("program error, invalid conversion mode %d\n"),ipFlag->FromToMode);
253 if (ipFlag->verbose > 1) {
254 fprintf(stderr, "%s: ", progname);
255 fprintf(stderr, _("Converted %d out of %d line breaks.\n"),converted, line_nr -1);
261 /* converts stream ipInF to DOS format text and write to stream ipOutF
262 * RetVal: 0 if success
265 int ConvertUnixToDos(FILE* ipInF, FILE* ipOutF, CFlag *ipFlag, const char *progname)
269 int PreviousChar = 0;
271 unsigned int line_nr = 1;
272 unsigned int converted = 0;
277 switch (ipFlag->ConvMode) {
278 case CONVMODE_ASCII: /* ascii */
279 case CONVMODE_UTF16LE: /* Assume UTF-16LE, bomtype = FILE_UTF8 */
280 case CONVMODE_UTF16BE: /* Assume UTF-16BE, bomtype = FILE_UTF8 */
281 ConvTable = U2DAsciiTable;
283 case CONVMODE_7BIT: /* 7bit */
284 ConvTable = U2D7BitTable;
286 case CONVMODE_437: /* iso */
287 ConvTable = U2DIso437Table;
289 case CONVMODE_850: /* iso */
290 ConvTable = U2DIso850Table;
292 case CONVMODE_860: /* iso */
293 ConvTable = U2DIso860Table;
295 case CONVMODE_863: /* iso */
296 ConvTable = U2DIso863Table;
298 case CONVMODE_865: /* iso */
299 ConvTable = U2DIso865Table;
301 case CONVMODE_1252: /* iso */
302 ConvTable = U2DIso1252Table;
304 default: /* unknown convmode */
305 ipFlag->status |= WRONG_CODEPAGE ;
308 /* Turn off ISO and 7-bit conversion for Unicode text files */
309 if (ipFlag->bomtype > 0)
310 ConvTable = U2DAsciiTable;
312 if ((ipFlag->ConvMode > CONVMODE_7BIT) && (ipFlag->verbose)) { /* not ascii or 7bit */
313 fprintf(stderr, "%s: ", progname);
314 fprintf(stderr, _("using code page %d.\n"), ipFlag->ConvMode);
318 /* CR-LF -> CR-LF, in case the input file is a DOS text file */
319 /* \x0a = Newline/Line Feed (LF) */
320 /* \x0d = Carriage Return (CR) */
322 switch (ipFlag->FromToMode) {
323 case FROMTO_UNIX2DOS: /* unix2dos */
324 while ((TempChar = fgetc(ipInF)) != EOF) { /* get character */
325 if ((ipFlag->Force == 0) &&
327 (TempChar != '\x0a') && /* Not an LF */
328 (TempChar != '\x0d') && /* Not a CR */
329 (TempChar != '\x09') && /* Not a TAB */
330 (TempChar != '\x0c')) { /* Not a form feed */
332 ipFlag->status |= BINARY_FILE ;
333 if (ipFlag->verbose) {
334 if ((ipFlag->stdio_mode) && (!ipFlag->error)) ipFlag->error = 1;
335 fprintf(stderr, "%s: ", progname);
336 fprintf(stderr, _("Binary symbol 0x%02X found at line %d\n"),TempChar, line_nr);
340 if (TempChar == '\x0a')
342 fputc('\x0d', ipOutF); /* got LF, put extra CR */
345 if (TempChar == '\x0d') { /* got CR */
346 if ((TempChar = fgetc(ipInF)) == EOF) /* get next char (possibly LF) */
347 TempChar = '\x0d'; /* Read error, or end of file. */
349 fputc('\x0d', ipOutF); /* put CR */
350 PreviousChar = '\x0d';
354 if (TempChar == '\x0a') /* Count all DOS and Unix line breaks */
356 if (fputc(ConvTable[TempChar], ipOutF) == EOF) { /* put LF or other char */
358 if (ipFlag->verbose) {
359 ipFlag->error = errno;
360 errstr = strerror(errno);
361 fprintf(stderr, "%s: ", progname);
362 fprintf(stderr, _("can not write to output file: %s\n"), errstr);
366 AddDOSNewLine( ipOutF, ipFlag, TempChar, PreviousChar);
368 PreviousChar = TempChar;
371 case FROMTO_UNIX2MAC: /* unix2mac */
372 while ((TempChar = fgetc(ipInF)) != EOF) {
373 if ((ipFlag->Force == 0) &&
375 (TempChar != '\x0a') && /* Not an LF */
376 (TempChar != '\x0d') && /* Not a CR */
377 (TempChar != '\x09') && /* Not a TAB */
378 (TempChar != '\x0c')) { /* Not a form feed */
380 ipFlag->status |= BINARY_FILE ;
381 if (ipFlag->verbose) {
382 if ((ipFlag->stdio_mode) && (!ipFlag->error)) ipFlag->error = 1;
383 fprintf(stderr, "%s: ", progname);
384 fprintf(stderr, _("Binary symbol 0x%02X found at line %d\n"),TempChar, line_nr);
388 if (TempChar != '\x0a') { /* Not an LF */
389 if(fputc(ConvTable[TempChar], ipOutF) == EOF) {
391 if (ipFlag->verbose) {
392 ipFlag->error = errno;
393 errstr = strerror(errno);
394 fprintf(stderr, "%s: ", progname);
395 fprintf(stderr, _("can not write to output file: %s\n"), errstr);
399 PreviousChar = TempChar;
400 if (TempChar == '\x0d') /* CR */
404 /* TempChar is an LF */
405 if (PreviousChar != '\x0d') /* CR already counted */
407 /* Don't touch this delimiter if it's a CR,LF pair. */
408 if ( PreviousChar == '\x0d' ) {
409 if (fputc('\x0a', ipOutF) == EOF) { /* CR,LF pair. Put LF */
411 if (ipFlag->verbose) {
412 ipFlag->error = errno;
413 errstr = strerror(errno);
414 fprintf(stderr, "%s: ", progname);
415 fprintf(stderr, _("can not write to output file: %s\n"), errstr);
419 PreviousChar = TempChar;
422 PreviousChar = TempChar;
423 if (fputc('\x0d', ipOutF) == EOF) { /* Unix line end (LF). Put CR */
425 if (ipFlag->verbose) {
426 ipFlag->error = errno;
427 errstr = strerror(errno);
428 fprintf(stderr, "%s: ", progname);
429 fprintf(stderr, _("can not write to output file: %s\n"), errstr);
434 if (ipFlag->NewLine) { /* add additional CR? */
435 fputc('\x0d', ipOutF);
440 default: /* unknown FromToMode */
443 fprintf(stderr, "%s: ", progname);
444 fprintf(stderr, _("program error, invalid conversion mode %d\n"),ipFlag->FromToMode);
448 if (ipFlag->verbose > 1) {
449 fprintf(stderr, "%s: ", progname);
450 fprintf(stderr, _("Converted %d out of %d line breaks.\n"),converted, line_nr -1);
456 int main (int argc, char *argv[])
458 /* variable declarations */
462 char localedir[1024];
464 int _dowildcard = -1; /* enable wildcard expansion for Win64 */
468 strcpy(progname,"unix2dos");
471 ptr = getenv("DOS2UNIX_LOCALEDIR");
473 strcpy(localedir,LOCALEDIR);
475 if (strlen(ptr) < sizeof(localedir))
476 strcpy(localedir,ptr);
478 fprintf(stderr,"%s: ",progname);
479 fprintf(stderr, "%s", _("error: Value of environment variable DOS2UNIX_LOCALEDIR is too long.\n"));
480 strcpy(localedir,LOCALEDIR);
485 #if defined(ENABLE_NLS) || (defined(D2U_UNICODE) && !defined(__MSDOS__) && !defined(_WIN32) && !defined(__OS2__))
486 /* setlocale() is also needed for nl_langinfo() */
487 setlocale (LC_ALL, "");
491 bindtextdomain (PACKAGE, localedir);
492 textdomain (PACKAGE);
496 /* variable initialisations */
497 pFlag = (CFlag*)malloc(sizeof(CFlag));
498 pFlag->FromToMode = FROMTO_UNIX2DOS; /* default unix2dos */
501 if ( ((ptr=strrchr(argv[0],'/')) == NULL) && ((ptr=strrchr(argv[0],'\\')) == NULL) )
506 if ((strcmpi("unix2mac", ptr) == 0) || (strcmpi("unix2mac.exe", ptr) == 0)) {
507 pFlag->FromToMode = FROMTO_UNIX2MAC;
508 strcpy(progname,"unix2mac");
512 return parse_options(argc, argv, pFlag, localedir, progname, PrintLicense, ConvertUnixToDos, ConvertUnixToDosW);
514 return parse_options(argc, argv, pFlag, localedir, progname, PrintLicense, ConvertUnixToDos);