Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 03 May 1999 14:38:46 -0700
From:      Greg Shenaut <greg@bogslab.ucdavis.edu>
To:        stable@FreeBSD.ORG
Subject:   Re: Dos2unix 
Message-ID:  <199905032138.OAA23272@deal1.bogs.org>
In-Reply-To: Your message of "Mon, 03 May 1999 14:52:25 CDT." <19990503145223.A8709@holly.dyndns.org> 

next in thread | previous in thread | raw e-mail | index | archive | help
In message <19990503145223.A8709@holly.dyndns.org>, Chris Costello cleopede:
>On Mon, May 3, 1999, Vince Vielhaber wrote:
>> 
>> On 03-May-99 Chris Costello wrote:
>> > On Mon, May 3, 1999, Michael C. Vergallen wrote:
>> >> Here it is ... someone gave me this routine to use ...
>> > 
>> >    This code is both unnecessarily complex and it does not
>> > function the same way the BSDI dos2bsd/bsd2dos tools work.

If you want to see something which is seriously over-complex
and works almost nothing like the bsdi tools, read on.  If
nothing else, it may be good for a laugh. . . .

I used BSD/OS for several years before I came over to FreeBSD, and
I disliked the BSDI utils enough that I wrote the following code
several years ago.  Its main advantages are that it can be compiled
to run on *nix or msdos, it can handle *unix <--> msdos <--> mac,
and, while it can be used as a filter, it is designed to convert
multiple files *in place* (i.e., "fixnl *.[ch]" replaces all the
*.[ch] files with versions containing only locally valid end-of-line
characters).  This is because 99 times out of 100, this is what
you want to do.

BTW, you have to use the -z flag to cause ^Z to signal EOF; the -Z
flag will add a newline at the end of the file if it doesn't already
end with one--this is handy sometimes; the -F flag is like the -Z
flag, except that it won't add a newline if the file ends in \f (I
don't remember why I needed this--if you don't like this option,
don't use it).

-Greg Shenaut
(tabs set to 4 columns)
-----------------
/*
 * take care of \r\n stuff in a sightly more intelligent way
 * we are concerned with both \n\r and \r\n
 * \n\r --> NL	(nonstandard, but handled)
 * \r\n --> NL	(DOS)
 * x\n --> xNL	(UNIX)
 * \nx --> NLx	(UNIX)
 * x\r --> xNL	(MAC)
 * \rx --> NLx	(MAC)
 * xEOF --> xNL	(x is not \f--all)
 */
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

char Usage[] = "[ -n|-rn|-r|-z|-Z|-F ][ file ...]";

/* OS defaults */
char *nl = 0;
#ifdef __MSDOS__
#define NL "\r\n"	/* DOS */
#else dos
#ifdef __MAC__		/* not sure this is the right constant. . . . */
#define NL "\r"		/* Macintosh (anything to be different) */
#else mac
#define NL "\n"		/* UNIX newline */
#endif mac
#endif dos

FILE *
efopen(char *s, char *m) {
	FILE *f = fopen(s, m);

	if (f == NULL) {
		fprintf(stderr, "Failed to open %s, mode %s\n", s, m);
		exit (1);
	}
	return(f);
}
void
usage(char *s) {
	fprintf(stderr, "Usage: fixnl %s\n", s);
	exit(1);
}

char tmp[50];

void
main(int argc, char **argv) {
	int i, c, lastc;
	int zflg = 0;
	int Zflg = 0;
	int Fflg = 0;
	FILE *in, *out, *efopen();

	while (argc > 1 && *argv[1] == '-') {
		char *p;

		for (p = argv[1]+1; *p; p++) switch (*p) {
		default:
			usage(Usage);
		case 'z':
			zflg = 1;
			break;
		case 'F':
			Fflg = 1;
			/* fall thru */
		case 'Z':
			Zflg = 1;
			break;
		case 'n':
			if (nl) usage(Usage);
			if (p[1] == 'r')
				usage(Usage);
			nl = "\n";
			break;
		case 'r':
			if (nl) usage(Usage);
			if (p[1] == 'n') {
				nl = "\r\n";
				p++;
			} else
				nl = "\r";
		}
		argc--; argv++;
	}
	if (!nl) nl = NL;
	sprintf(tmp, "/tmp/fnl%04x.tmp", (short)getpid());
	if (argc <= 1) {
		in = stdin;
		out = stdout;
		i = 0;
		goto cheat;
	}
	for (i = 1; i < argc; i++) {
		struct stat s;

		if (stat(argv[i], &s)
		 || (s.st_mode & S_IFMT) != S_IFREG) {
		 	fprintf(stderr, "%s is not a regular file -- skipped\n", argv[i]);
		 	continue;
		}
		out = efopen(tmp, "w+");
		in = fopen(argv[i], "r+");
		if (!in) {
			fprintf(stderr, "Failed to open %s -- skipped\n", argv[i]);
			continue;
		}
cheat:
		lastc = EOF;
		while ((c = getc(in)) != EOF) {
			if (zflg != 0 && c == 032) { c = EOF; break; }	/* handle ^Z as early EOF */
			switch (c) {
			default:
				switch(lastc) {
				default:
					if (lastc != EOF)
						putc(lastc, out);
					break;
				case '\r':
				case '\n':
					fputs(nl, out);
					break;
				}
				break;
			case '\r':
				switch(lastc) {
				default:
					if (lastc != EOF)
						putc(lastc, out);
					break;
				case '\r':	/* two in a row */
					fputs(nl, out);
					break;
				case '\n':
					fputs(nl, out);
					c = EOF;
					break;
				}
				break;
			case '\n':
				switch(lastc) {
				default:
					if (lastc != EOF)
						putc(lastc, out);
					break;
				case '\n':	/* two in a row */
					fputs(nl, out);
					break;
				case '\r':
					fputs(nl, out);
					c = EOF;
					break;
				}
				break;
			}
			lastc = c;
		}
		switch(lastc) {
		default:
			putc(lastc, out);
			if (!Zflg && !Fflg) break;
		case '\n':
		case '\r':
			fputs(nl, out);
		case EOF:
			break;
		case '\f':
			putc(lastc, out);
			if (!Fflg && Zflg)
				fputs(nl, out);
			break;
		}
		if (in == stdin) break;
		/* now copy on top of the original file & unlink the tmp */
		/* ... I hope this won't leave smegma behind at the end ... */
		rewind(in);
		rewind(out);
		while ((c = getc(out)) != EOF)
			putc(c, in);
		fflush(in);
		write(fileno(in), NULL, 0);	/* works in DOS, no effect in unix */
#ifdef __unix__
		ftruncate(fileno(in), ftell(in));
#endif
		fclose(in);
		fclose(out);
		unlink(tmp);
	}
	exit(0);
}


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-stable" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199905032138.OAA23272>