Mail Archives: djgpp-workers/2001/07/16/14:36:40
> From: "Juan Manuel Guerrero" <ST001906 AT HRZ1 DOT HRZ DOT TU-Darmstadt DOT De>
> Date: Mon, 16 Jul 2001 16:26:22 +0200
> >
> > I have Sed 3.02.80 ported, too. I also added to it a feature whereby
> > Sed no longer reads in text mode. This makes it possible to support
> > files with embedded ^Z and lone ^M characters.
> >
> > I sent the diffs to the Sed maintainer, but didn't hear from him yet,
> > although this was long ago.
>
> Would be nice to have this feature available for all djgpp users.
> If you send the patch to me I will apply it.
Attached.
2000-01-01 Eli Zaretskii <eliz AT is DOT elta DOT co DOT il>
* sed/utils.h: Include fcntl.h.
(O_BINARY, setmode): Define if O_BINARY is undefined.
[O_BINARY]: Include io.h.
(set_read_mode): Declare a prototype.
* sed/utils.c [O_BINARY]: Include sys/stat.h and make sure S_ISCHR
is defined.
(set_read_mode): New function, switches a stream into binary mode.
This is a no-op unless O_BINARY is defined.
(ck_fwrite) [O_BINARY]: If we are writing to a character device,
replace every ^Z character with an ASCII string "^Z".
* sed/execute.c (line_undosify): New function, a no-op unless
O_BINARY is defined.
(read_mem_line, read_file_line): Call line_undosify to remove a
trailing ^M or ^Z from a line.
(dump_append_queue): Call set_read_mode.
[O_BINARY]: Remove ^M, if before the newline, and ^Z, if
immediately before EOF.
(open_next_file): Call set_read_mode.
--- sed/utils.h~0 Mon Jul 6 06:56:26 1998
+++ sed/utils.h Fri Dec 31 21:47:08 1999
@@ -1,7 +1,19 @@
#include <stdio.h>
+#include <fcntl.h>
+#ifndef O_BINARY
+# ifdef _O_BINARY
+# define O_BINARY _O_BINARY
+# define setmode _setmode
+# endif
+#endif
+#ifdef O_BINARY
+# include <io.h>
+#endif
+
void panic P_((const char *str, ...));
+void set_read_mode P_((FILE *stream));
FILE *ck_fopen P_((const char *name, const char *mode));
void ck_fwrite P_((const VOID *ptr, size_t size, size_t nmemb, FILE *stream));
size_t ck_fread P_((VOID *ptr, size_t size, size_t nmemb, FILE *stream));
--- sed/utils.c~0 Tue Sep 7 02:37:52 1999
+++ sed/utils.c Sat Jan 1 11:32:12 2000
@@ -62,6 +62,14 @@
# endif /* RX_MEMDBUG */
#endif /* HAVE_STDLIB_H */
+#ifdef O_BINARY
+# include <sys/types.h>
+# include <sys/stat.h>
+# ifndef S_ISCHR
+# define S_ISCHR(m) (((m)&S_IFMT) == S_IFCHR)
+# endif
+#endif
+
const char *myname;
@@ -132,6 +140,21 @@ utils_fp_name(fp)
return "{Unknown file pointer}";
}
+void
+set_read_mode (fp)
+ FILE *fp;
+{
+#ifdef O_BINARY
+ /* For systems that distinguish between text and binary files,
+ switch all input streams to binary mode. This is so we get all
+ the characters from the file, instead of relying on the
+ misfeatures of the C library conversions (e.g., most of them drop
+ lone ^M characters, stop at the first ^Z character, etc.) */
+ if (!isatty(fileno(fp)))
+ setmode(fileno (fp), O_BINARY);
+#endif
+}
+
/* Panic on failing fopen */
FILE *
ck_fopen(name, mode)
@@ -170,15 +193,44 @@ ck_fwrite(ptr, size, nmemb, stream)
size_t nmemb;
FILE *stream;
{
- if (size && fwrite(ptr, size, nmemb, stream) != nmemb)
+ size_t written;
+#ifdef O_BINARY
+ struct stat st;
+
+ if (!size)
+ return;
+ if (fstat(fileno(stream), &st) == 0 && S_ISCHR(st.st_mode))
{
- if (nmemb==1)
- panic(_("couldn't write an item to %s: %s"),
- utils_fp_name(stream), strerror(errno));
- else
- panic(_("couldn't write %d items to %s: %s"),
- nmemb, utils_fp_name(stream), strerror(errno));
+ char *p;
+ size_t left = nmemb*size;
+
+ /* Text-mode writes to character devices stop at the first ^Z
+ character. Repair this lossage. */
+ while ((p = memchr(ptr, 0x1a, left)) != NULL)
+ {
+ size_t this_write = p - (char *)ptr;
+
+ if (fwrite(ptr, 1, this_write, stream) != this_write)
+ break;
+ fwrite("^Z", 1, 2, stream);
+ left -= this_write + 1;
+ ptr = (char *)ptr + this_write + 1;
+ }
+ if (p == NULL && fwrite(ptr, 1, left, stream) == left)
+ return;
}
+ else
+#endif
+
+ if (!size || fwrite(ptr, size, nmemb, stream) == nmemb)
+ return;
+
+ if (nmemb==1)
+ panic(_("couldn't write an item to %s: %s"),
+ utils_fp_name(stream), strerror(errno));
+ else
+ panic(_("couldn't write %d items to %s: %s"),
+ nmemb, utils_fp_name(stream), strerror(errno));
}
/* Panic on failing fread */
--- sed/execute.c~0 Tue Sep 7 02:37:32 1999
+++ sed/execute.c Sat Jan 1 12:09:08 2000
@@ -263,6 +263,21 @@ line_exchange(a, b)
MEMCPY( b, &t, sizeof(struct line));
}
+static void line_undosify P_((struct line *, size_t, int));
+static void
+line_undosify(lbuf, from, ch)
+ struct line *lbuf;
+ size_t from;
+{
+#ifdef O_BINARY
+ size_t lbuf_len = lbuf->length;
+
+ /* Remove character CH from the end of the line starting at offset FROM. */
+ if (lbuf_len > from && lbuf->text[lbuf_len-1] == ch)
+ lbuf->length--;
+#endif
+}
+
/* dummy function to simplify read_pattern_space() */
static flagT read_always_fail P_((struct input *));
@@ -302,6 +317,7 @@ read_mem_line(input)
}
str_append(&line, input->cur, l);
+ line_undosify(&line, line.length - l, '\r');
input->left -= e - input->cur;
input->cur = e;
return 1;
@@ -361,6 +377,7 @@ read_file_line(input)
if (buffer.length == 0)
{
+ line_undosify(&line, initial_length, 0x1a);
if (!*input->file_list && !POSIXLY_CORRECT)
line.chomped = 0;
/* Did we hit EOF without reading anything? If so, try
@@ -372,6 +389,7 @@ read_file_line(input)
blen = b - buffer.active;
str_append(&line, buffer.active, blen);
+ line_undosify(&line, line.length - blen, '\r');
++blen;
buffer.active += blen;
buffer.length -= blen;
@@ -449,8 +467,52 @@ dump_append_queue()
no error condition." IEEE Std 1003.2-1992 */
if (fp)
{
+ set_read_mode(fp);
while ((cnt = ck_fread(buf, 1, sizeof buf, fp)) > 0)
- ck_fwrite(buf, 1, cnt, stdout);
+ {
+#ifdef O_BINARY
+ /* Remove CRs from CR-LF pairs, and the trailing ^Z. */
+ register char *s = buf, *d = buf;
+ register size_t len = cnt;
+
+ while (len--)
+ {
+ if (*s == '\r' || *s == 0x1a)
+ {
+ if (!len)
+ {
+ if (getc(fp) != EOF)
+ {
+ if (*s == '\r')
+ {
+ fseek(fp, -2L, SEEK_CUR);
+ cnt--;
+ }
+ else
+ {
+ fseek(fp, -1L, SEEK_CUR);
+ *d++ = *s++;
+ }
+ break;
+ }
+ else if (*s == 0x1a)
+ {
+ cnt--;
+ break;
+ }
+ }
+ else if (s[1] == '\n')
+ {
+ s++;
+ len--;
+ cnt--;
+ }
+ }
+ *d++ = *s++;
+ }
+#endif
+ ck_fwrite(buf, 1, cnt, stdout);
+ }
fclose(fp);
}
}
@@ -483,6 +545,8 @@ open_next_file(name, input)
return;
}
+ set_read_mode (input->fp); /* for systems with text/binary schizophrenia */
+
input->read_fn = read_file_line;
if (force_unbuffered)
input->no_buffering = 1;
- Raw text -