summaryrefslogtreecommitdiff
path: root/sed
diff options
context:
space:
mode:
authorPaolo Bonzini <bonzini@gnu.org>2006-07-20 16:05:46 +0000
committerPaolo Bonzini <bonzini@gnu.org>2008-01-09 16:12:09 +0100
commit4ca34ac568881f50c9d5ecd2750938396686cf25 (patch)
tree5fcff6244b4e1eee45b8d46b5a5b2da87ac00f39 /sed
parentec9561cfa498794621c415005c196abd736f7587 (diff)
downloadsed-4ca34ac568881f50c9d5ecd2750938396686cf25.tar.gz
don't rely on malloc(0) != NULL
git-archimport-id: bonzini@gnu.org--2004b/sed--stable--4.1--patch-69
Diffstat (limited to 'sed')
-rw-r--r--sed/execute.c139
1 files changed, 101 insertions, 38 deletions
diff --git a/sed/execute.c b/sed/execute.c
index 5e8a38a..ab2cc5c 100644
--- a/sed/execute.c
+++ b/sed/execute.c
@@ -84,6 +84,12 @@ struct line {
#endif
};
+#ifdef HAVE_MBRTOWC
+#define SIZEOF_LINE (sizeof (struct line) - sizeof (mbstate_t))
+#else
+#define SIZEOF_LINE (sizeof (struct line))
+#endif
+
/* A queue of text to write out at the end of a cycle
(filled by the "a", "r" and "R" commands.) */
struct append_queue {
@@ -366,11 +372,13 @@ str_append_modified(to, string, length, type)
#endif
}
-/* initialize a "struct line" buffer */
-static void line_init P_((struct line *, size_t initial_size));
+/* Initialize a "struct line" buffer. Copy multibyte state from `state'
+ if not null. */
+static void line_init P_((struct line *, struct line *, size_t initial_size));
static void
-line_init(buf, initial_size)
+line_init(buf, state, initial_size)
struct line *buf;
+ struct line *state;
size_t initial_size;
{
buf->text = MALLOC(initial_size, char);
@@ -380,18 +388,43 @@ line_init(buf, initial_size)
buf->chomped = true;
#ifdef HAVE_MBRTOWC
- memset (&buf->mbstate, 0, sizeof (buf->mbstate));
+ if (state)
+ memcpy (&buf->mbstate, &state->mbstate, sizeof (buf->mbstate));
+ else
+ memset (&buf->mbstate, 0, sizeof (buf->mbstate));
#endif
+}
+/* Reset a "struct line" buffer to length zero. Copy multibyte state from
+ `state' if not null. */
+static void line_reset P_((struct line *, struct line *));
+static void
+line_reset(buf, state)
+ struct line *buf, *state;
+{
+ if (buf->alloc == 0)
+ line_init(buf, state, INITIAL_BUFFER_SIZE);
+ else
+ {
+ buf->length = 0;
+#ifdef HAVE_MBRTOWC
+ if (state)
+ memcpy (&buf->mbstate, &state->mbstate, sizeof (buf->mbstate));
+ else
+ memset (&buf->mbstate, 0, sizeof (buf->mbstate));
+#endif
+ }
}
/* Copy the contents of the line `from' into the line `to'.
- This destroys the old contents of `to'. */
-static void line_copy P_((struct line *from, struct line *to));
+ This destroys the old contents of `to'.
+ Copy the multibyte state if `state' is true. */
+static void line_copy P_((struct line *from, struct line *to, bool state));
static void
-line_copy(from, to)
+line_copy(from, to, state)
struct line *from;
struct line *to;
+ bool state;
{
/* Remove the inactive portion in the destination buffer. */
to->alloc += to->active - to->text;
@@ -415,38 +448,53 @@ line_copy(from, to)
MEMCPY(to->active, from->active, from->length);
#ifdef HAVE_MBRTOWC
- MEMCPY(&to->mbstate, &from->mbstate, sizeof (from->mbstate));
+ if (state)
+ MEMCPY(&to->mbstate, &from->mbstate, sizeof (from->mbstate));
#endif
}
-/* Append the contents of the line `from' to the line `to'. */
-static void line_append P_((struct line *from, struct line *to));
+/* Append the contents of the line `from' to the line `to'.
+ Copy the multibyte state if `state' is true. */
+static void line_append P_((struct line *from, struct line *to, bool state));
static void
-line_append(from, to)
+line_append(from, to, state)
struct line *from;
struct line *to;
+ bool state;
{
str_append(to, "\n", 1);
str_append(to, from->active, from->length);
to->chomped = from->chomped;
#ifdef HAVE_MBRTOWC
- MEMCPY (&to->mbstate, &from->mbstate, sizeof (from->mbstate));
+ if (state)
+ MEMCPY (&to->mbstate, &from->mbstate, sizeof (from->mbstate));
#endif
}
-/* Exchange the contents of two "struct line" buffers. */
-static void line_exchange P_((struct line *, struct line *));
+/* Exchange two "struct line" buffers.
+ Copy the multibyte state if `state' is true. */
+static void line_exchange P_((struct line *a, struct line *b, bool state));
static void
-line_exchange(a, b)
+line_exchange(a, b, state)
struct line *a;
struct line *b;
+ bool state;
{
struct line t;
- MEMCPY(&t, a, sizeof(struct line));
- MEMCPY( a, b, sizeof(struct line));
- MEMCPY( b, &t, sizeof(struct line));
+ if (state)
+ {
+ MEMCPY(&t, a, sizeof (struct line));
+ MEMCPY( a, b, sizeof (struct line));
+ MEMCPY( b, &t, sizeof (struct line));
+ }
+ else
+ {
+ MEMCPY(&t, a, SIZEOF_LINE);
+ MEMCPY( a, b, SIZEOF_LINE);
+ MEMCPY( b, &t, SIZEOF_LINE);
+ }
}
@@ -1072,9 +1120,7 @@ do_subst(sub)
static struct re_registers regs;
- if (s_accum.alloc == 0)
- line_init(&s_accum, INITIAL_BUFFER_SIZE);
- s_accum.length = 0;
+ line_reset(&s_accum, &line);
/* The first part of the loop optimizes s/xxx// when xxx is at the
start, and s/xxx$// */
@@ -1166,8 +1212,8 @@ do_subst(sub)
/* Exchange line and s_accum. This can be much cheaper
than copying s_accum.active into line.text (for huge lines). */
- line_exchange(&line, &s_accum);
-
+ line_exchange(&line, &s_accum, false);
+
/* Finish up. */
if (count < sub->numb)
return;
@@ -1180,7 +1226,7 @@ do_subst(sub)
{
#ifdef HAVE_POPEN
FILE *pipe;
- s_accum.length = 0;
+ line_reset(&s_accum, NULL);
str_append (&line, "", 1);
pipe = popen(line.active, "r");
@@ -1197,7 +1243,10 @@ do_subst(sub)
pclose (pipe);
- line_exchange(&line, &s_accum);
+ /* Exchange line and s_accum. This can be much cheaper than copying
+ s_accum.active into line.text (for huge lines). See comment above
+ for 'g' as to while the third argument is incorrect anyway. */
+ line_exchange(&line, &s_accum, true);
if (line.length &&
line.active[line.length - 1] == '\n')
line.length--;
@@ -1337,9 +1386,7 @@ execute_program(vec, input)
#ifdef HAVE_POPEN
FILE *pipe;
int cmd_length = cur_cmd->x.cmd_txt.text_length;
- if (s_accum.alloc == 0)
- line_init(&s_accum, INITIAL_BUFFER_SIZE);
- s_accum.length = 0;
+ line_reset(&s_accum, NULL);
if (!cmd_length)
{
@@ -1376,8 +1423,9 @@ execute_program(vec, input)
/* Exchange line and s_accum. This can be much
cheaper than copying s_accum.active into line.text
- (for huge lines). */
- line_exchange(&line, &s_accum);
+ (for huge lines). See comment above for 'g' as
+ to while the third argument is incorrect anyway. */
+ line_exchange(&line, &s_accum, true);
}
else
flush_output(output_file.fp);
@@ -1392,19 +1440,33 @@ execute_program(vec, input)
}
case 'g':
- line_copy(&hold, &line);
+ /* We do not have a really good choice for the third parameter.
+ The problem is that hold space and the input file might as
+ well have different states; copying it from hold space means
+ that subsequent input might be read incorrectly, while
+ keeping it as in pattern space means that commands operating
+ on the moved buffer might consider a wrong character set.
+ We keep it true because it's what sed <= 4.1.5 did. */
+ line_copy(&hold, &line, true);
break;
case 'G':
- line_append(&hold, &line);
+ /* We do not have a really good choice for the third parameter.
+ The problem is that hold space and pattern space might as
+ well have different states. So, true is as wrong as false.
+ We keep it true because it's what sed <= 4.1.5 did, but
+ we could consider having line_ap. */
+ line_append(&hold, &line, true);
break;
case 'h':
- line_copy(&line, &hold);
+ /* Here, it is ok to have true. */
+ line_copy(&line, &hold, true);
break;
case 'H':
- line_append(&line, &hold);
+ /* See comment above for 'G' regarding the third parameter. */
+ line_append(&line, &hold, true);
break;
case 'i':
@@ -1535,7 +1597,8 @@ execute_program(vec, input)
break;
case 'x':
- line_exchange(&line, &hold);
+ /* See comment above for 'g' regarding the third parameter. */
+ line_exchange(&line, &hold, false);
break;
case 'y':
@@ -1700,9 +1763,9 @@ process_files(the_program, argv)
struct input input;
int status;
- line_init(&line, INITIAL_BUFFER_SIZE);
- line_init(&hold, 0);
- line_init(&buffer, 0);
+ line_init(&line, NULL, INITIAL_BUFFER_SIZE);
+ line_init(&hold, NULL, 0);
+ line_init(&buffer, NULL, 0);
#ifdef EXPERIMENTAL_DASH_N_OPTIMIZATION
branches = count_branches(the_program);