aboutsummaryrefslogtreecommitdiff
path: root/editors/sed.c
diff options
context:
space:
mode:
Diffstat (limited to 'editors/sed.c')
-rw-r--r--editors/sed.c22
1 files changed, 14 insertions, 8 deletions
diff --git a/editors/sed.c b/editors/sed.c
index 374830f3f..f4a5f7b8a 100644
--- a/editors/sed.c
+++ b/editors/sed.c
@@ -252,7 +252,6 @@ static void cleanup_outname(void)
252} 252}
253 253
254/* strcpy, replacing "\from" with 'to'. If to is NUL, replacing "\any" with 'any' */ 254/* strcpy, replacing "\from" with 'to'. If to is NUL, replacing "\any" with 'any' */
255
256static unsigned parse_escapes(char *dest, const char *string, int len, char from, char to) 255static unsigned parse_escapes(char *dest, const char *string, int len, char from, char to)
257{ 256{
258 char *d = dest; 257 char *d = dest;
@@ -282,7 +281,7 @@ static unsigned parse_escapes(char *dest, const char *string, int len, char from
282 return d - dest; 281 return d - dest;
283} 282}
284 283
285static char *copy_parsing_escapes(const char *string, int len) 284static char *copy_parsing_escapes(const char *string, int len, char delim)
286{ 285{
287 const char *s; 286 const char *s;
288 char *dest = xmalloc(len + 1); 287 char *dest = xmalloc(len + 1);
@@ -293,10 +292,15 @@ static char *copy_parsing_escapes(const char *string, int len)
293 len = parse_escapes(dest, string, len, s[1], s[0]); 292 len = parse_escapes(dest, string, len, s[1], s[0]);
294 string = dest; 293 string = dest;
295 } 294 }
295 if (delim) {
296 /* we additionally unescape any instances of escaped delimiter.
297 * For example, in 's+9\++X+' the pattern is "9+", not "9\+".
298 */
299 len = parse_escapes(dest, string, len, delim, delim);
300 }
296 return dest; 301 return dest;
297} 302}
298 303
299
300/* 304/*
301 * index_of_next_unescaped_regexp_delim - walks left to right through a string 305 * index_of_next_unescaped_regexp_delim - walks left to right through a string
302 * beginning at a specified index and returns the index of the next regular 306 * beginning at a specified index and returns the index of the next regular
@@ -353,12 +357,14 @@ static int parse_regex_delim(const char *cmdstr, char **match, char **replace)
353 357
354 /* save the match string */ 358 /* save the match string */
355 idx = index_of_next_unescaped_regexp_delim(delimiter, cmdstr_ptr); 359 idx = index_of_next_unescaped_regexp_delim(delimiter, cmdstr_ptr);
356 *match = copy_parsing_escapes(cmdstr_ptr, idx); 360 *match = copy_parsing_escapes(cmdstr_ptr, idx, delimiter);
357
358 /* save the replacement string */ 361 /* save the replacement string */
359 cmdstr_ptr += idx + 1; 362 cmdstr_ptr += idx + 1;
360 idx = index_of_next_unescaped_regexp_delim(- (int)delimiter, cmdstr_ptr); 363 idx = index_of_next_unescaped_regexp_delim(- (int)delimiter, cmdstr_ptr);
361 *replace = copy_parsing_escapes(cmdstr_ptr, idx); 364//GNU sed 4.8:
365// echo 789 | sed 's&8&\&&' - 7&9 ("\&" remained "\&")
366// echo 789 | sed 's1\(8\)1\1\11' - 7119 ("\1\1" become "11")
367 *replace = copy_parsing_escapes(cmdstr_ptr, idx, delimiter != '&' ? delimiter : 0);
362 368
363 return ((cmdstr_ptr - cmdstr) + idx); 369 return ((cmdstr_ptr - cmdstr) + idx);
364} 370}
@@ -386,7 +392,7 @@ static int get_address(const char *my_str, int *linenum, regex_t ** regex)
386 delimiter = *++pos; 392 delimiter = *++pos;
387 next = index_of_next_unescaped_regexp_delim(delimiter, ++pos); 393 next = index_of_next_unescaped_regexp_delim(delimiter, ++pos);
388 if (next != 0) { 394 if (next != 0) {
389 temp = copy_parsing_escapes(pos, next); 395 temp = copy_parsing_escapes(pos, next, 0);
390 G.previous_regex_ptr = *regex = xzalloc(sizeof(regex_t)); 396 G.previous_regex_ptr = *regex = xzalloc(sizeof(regex_t));
391 xregcomp(*regex, temp, G.regex_type); 397 xregcomp(*regex, temp, G.regex_type);
392 free(temp); 398 free(temp);
@@ -581,7 +587,7 @@ static const char *parse_cmd_args(sed_cmd_t *sed_cmd, const char *cmdstr)
581 cmdstr++; 587 cmdstr++;
582 } 588 }
583 len = strlen(cmdstr); 589 len = strlen(cmdstr);
584 sed_cmd->string = copy_parsing_escapes(cmdstr, len); 590 sed_cmd->string = copy_parsing_escapes(cmdstr, len, 0);
585 cmdstr += len; 591 cmdstr += len;
586 /* "\anychar" -> "anychar" */ 592 /* "\anychar" -> "anychar" */
587 parse_escapes(sed_cmd->string, sed_cmd->string, -1, '\0', '\0'); 593 parse_escapes(sed_cmd->string, sed_cmd->string, -1, '\0', '\0');