359 |
continue; |
continue; |
360 |
} |
} |
361 |
/* Skip spaces */ |
/* Skip spaces */ |
362 |
if (isspace(substr[idx])) continue; |
if (isspace(substr[idx])) |
363 |
|
continue; |
364 |
|
|
365 |
switch (substr[idx]) { |
switch (substr[idx]) { |
366 |
/* Replace all occurrences */ |
/* Replace all occurrences */ |
418 |
/* handle edit cmds: (a)ppend, (i)nsert, and (c)hange */ |
/* handle edit cmds: (a)ppend, (i)nsert, and (c)hange */ |
419 |
else if (strchr("aic", sed_cmd->cmd)) { |
else if (strchr("aic", sed_cmd->cmd)) { |
420 |
if ((sed_cmd->end_line || sed_cmd->end_match) && sed_cmd->cmd != 'c') |
if ((sed_cmd->end_line || sed_cmd->end_match) && sed_cmd->cmd != 'c') |
421 |
bb_error_msg_and_die |
bb_error_msg_and_die("only a beginning address can be specified for edit commands"); |
|
("only a beginning address can be specified for edit commands"); |
|
422 |
for (;;) { |
for (;;) { |
423 |
if (*cmdstr == '\n' || *cmdstr == '\\') { |
if (*cmdstr == '\n' || *cmdstr == '\\') { |
424 |
cmdstr++; |
cmdstr++; |
425 |
break; |
break; |
426 |
} else if (isspace(*cmdstr)) |
} |
427 |
cmdstr++; |
if (!isspace(*cmdstr)) |
|
else |
|
428 |
break; |
break; |
429 |
|
cmdstr++; |
430 |
} |
} |
431 |
sed_cmd->string = xstrdup(cmdstr); |
sed_cmd->string = xstrdup(cmdstr); |
432 |
/* "\anychar" -> "anychar" */ |
/* "\anychar" -> "anychar" */ |
589 |
|
|
590 |
static void do_subst_w_backrefs(char *line, char *replace) |
static void do_subst_w_backrefs(char *line, char *replace) |
591 |
{ |
{ |
592 |
int i,j; |
int i, j; |
593 |
|
|
594 |
/* go through the replacement string */ |
/* go through the replacement string */ |
595 |
for (i = 0; replace[i]; i++) { |
for (i = 0; replace[i]; i++) { |
624 |
} |
} |
625 |
} |
} |
626 |
|
|
627 |
static int do_subst_command(sed_cmd_t *sed_cmd, char **line) |
static int do_subst_command(sed_cmd_t *sed_cmd, char **line_p) |
628 |
{ |
{ |
629 |
char *oldline = *line; |
char *line = *line_p; |
630 |
int altered = 0; |
int altered = 0; |
631 |
unsigned match_count = 0; |
unsigned match_count = 0; |
632 |
regex_t *current_regex; |
regex_t *current_regex; |
633 |
|
|
634 |
|
current_regex = sed_cmd->sub_match; |
635 |
/* Handle empty regex. */ |
/* Handle empty regex. */ |
636 |
if (sed_cmd->sub_match == NULL) { |
if (!current_regex) { |
637 |
current_regex = G.previous_regex_ptr; |
current_regex = G.previous_regex_ptr; |
638 |
if (!current_regex) |
if (!current_regex) |
639 |
bb_error_msg_and_die("no previous regexp"); |
bb_error_msg_and_die("no previous regexp"); |
640 |
} else |
} |
641 |
G.previous_regex_ptr = current_regex = sed_cmd->sub_match; |
G.previous_regex_ptr = current_regex; |
642 |
|
|
643 |
/* Find the first match */ |
/* Find the first match */ |
644 |
if (REG_NOMATCH == regexec(current_regex, oldline, 10, G.regmatch, 0)) |
if (REG_NOMATCH == regexec(current_regex, line, 10, G.regmatch, 0)) |
645 |
return 0; |
return 0; |
646 |
|
|
647 |
/* Initialize temporary output buffer. */ |
/* Initialize temporary output buffer. */ |
658 |
The match_count check is so not to break |
The match_count check is so not to break |
659 |
echo "hi" | busybox sed 's/^/!/g' */ |
echo "hi" | busybox sed 's/^/!/g' */ |
660 |
if (!G.regmatch[0].rm_so && !G.regmatch[0].rm_eo && match_count) { |
if (!G.regmatch[0].rm_so && !G.regmatch[0].rm_eo && match_count) { |
661 |
pipe_putc(*oldline++); |
pipe_putc(*line++); |
662 |
continue; |
continue; |
663 |
} |
} |
664 |
|
|
670 |
&& (sed_cmd->which_match != match_count) |
&& (sed_cmd->which_match != match_count) |
671 |
) { |
) { |
672 |
for (i = 0; i < G.regmatch[0].rm_eo; i++) |
for (i = 0; i < G.regmatch[0].rm_eo; i++) |
673 |
pipe_putc(*oldline++); |
pipe_putc(*line++); |
674 |
continue; |
continue; |
675 |
} |
} |
676 |
|
|
677 |
/* print everything before the match */ |
/* print everything before the match */ |
678 |
for (i = 0; i < G.regmatch[0].rm_so; i++) |
for (i = 0; i < G.regmatch[0].rm_so; i++) |
679 |
pipe_putc(oldline[i]); |
pipe_putc(line[i]); |
680 |
|
|
681 |
/* then print the substitution string */ |
/* then print the substitution string */ |
682 |
do_subst_w_backrefs(oldline, sed_cmd->string); |
do_subst_w_backrefs(line, sed_cmd->string); |
683 |
|
|
684 |
/* advance past the match */ |
/* advance past the match */ |
685 |
oldline += G.regmatch[0].rm_eo; |
line += G.regmatch[0].rm_eo; |
686 |
/* flag that something has changed */ |
/* flag that something has changed */ |
687 |
altered++; |
altered++; |
688 |
|
|
689 |
/* if we're not doing this globally, get out now */ |
/* if we're not doing this globally, get out now */ |
690 |
if (sed_cmd->which_match) |
if (sed_cmd->which_match) |
691 |
break; |
break; |
|
} while (*oldline && (regexec(current_regex, oldline, 10, G.regmatch, 0) != REG_NOMATCH)); |
|
692 |
|
|
693 |
/* Copy rest of string into output pipeline */ |
//maybe (G.regmatch[0].rm_eo ? REG_NOTBOL : 0) instead of unconditional REG_NOTBOL? |
694 |
|
} while (*line && regexec(current_regex, line, 10, G.regmatch, REG_NOTBOL) != REG_NOMATCH); |
695 |
|
|
696 |
while (*oldline) |
/* Copy rest of string into output pipeline */ |
697 |
pipe_putc(*oldline++); |
while (1) { |
698 |
pipe_putc(0); |
char c = *line++; |
699 |
|
pipe_putc(c); |
700 |
|
if (c == '\0') |
701 |
|
break; |
702 |
|
} |
703 |
|
|
704 |
free(*line); |
free(*line_p); |
705 |
*line = G.pipeline.buf; |
*line_p = G.pipeline.buf; |
706 |
return altered; |
return altered; |
707 |
} |
} |
708 |
|
|
870 |
/* Prime the pump */ |
/* Prime the pump */ |
871 |
next_line = get_next_line(&next_gets_char); |
next_line = get_next_line(&next_gets_char); |
872 |
|
|
873 |
/* go through every line in each file */ |
/* Go through every line in each file */ |
874 |
again: |
again: |
875 |
substituted = 0; |
substituted = 0; |
876 |
|
|
877 |
/* Advance to next line. Stop if out of lines. */ |
/* Advance to next line. Stop if out of lines. */ |
878 |
pattern_space = next_line; |
pattern_space = next_line; |
879 |
if (!pattern_space) return; |
if (!pattern_space) |
880 |
|
return; |
881 |
last_gets_char = next_gets_char; |
last_gets_char = next_gets_char; |
882 |
|
|
883 |
/* Read one line in advance so we can act on the last line, |
/* Read one line in advance so we can act on the last line, |
884 |
* the '$' address */ |
* the '$' address */ |
885 |
next_line = get_next_line(&next_gets_char); |
next_line = get_next_line(&next_gets_char); |
886 |
linenum++; |
linenum++; |
887 |
|
|
888 |
|
/* For every line, go through all the commands */ |
889 |
restart: |
restart: |
|
/* for every line, go through all the commands */ |
|
890 |
for (sed_cmd = G.sed_cmd_head.next; sed_cmd; sed_cmd = sed_cmd->next) { |
for (sed_cmd = G.sed_cmd_head.next; sed_cmd; sed_cmd = sed_cmd->next) { |
891 |
int old_matched, matched; |
int old_matched, matched; |
892 |
|
|
900 |
|| (!sed_cmd->beg_line && !sed_cmd->end_line |
|| (!sed_cmd->beg_line && !sed_cmd->end_line |
901 |
&& !sed_cmd->beg_match && !sed_cmd->end_match) |
&& !sed_cmd->beg_match && !sed_cmd->end_match) |
902 |
/* Or did we match the start of a numerical range? */ |
/* Or did we match the start of a numerical range? */ |
903 |
|| (sed_cmd->beg_line > 0 && (sed_cmd->beg_line == linenum)) |
|| (sed_cmd->beg_line > 0 && (sed_cmd->beg_line <= linenum)) |
904 |
/* Or does this line match our begin address regex? */ |
/* Or does this line match our begin address regex? */ |
905 |
|| (beg_match(sed_cmd, pattern_space)) |
|| (beg_match(sed_cmd, pattern_space)) |
906 |
/* Or did we match last line of input? */ |
/* Or did we match last line of input? */ |
907 |
|| (sed_cmd->beg_line == -1 && next_line == NULL); |
|| (sed_cmd->beg_line == -1 && next_line == NULL); |
908 |
|
|
909 |
/* Snapshot the value */ |
/* Snapshot the value */ |
|
|
|
910 |
matched = sed_cmd->in_match; |
matched = sed_cmd->in_match; |
911 |
|
|
912 |
|
//bb_error_msg("cmd:'%c' matched:%d beg_line:%d end_line:%d linenum:%d", |
913 |
|
//sed_cmd->cmd, matched, sed_cmd->beg_line, sed_cmd->end_line, linenum); |
914 |
|
|
915 |
/* Is this line the end of the current match? */ |
/* Is this line the end of the current match? */ |
916 |
|
|
917 |
if (matched) { |
if (matched) { |
918 |
|
/* once matched, "n,xxx" range is dead, disabling it */ |
919 |
|
if (sed_cmd->beg_line > 0) |
920 |
|
sed_cmd->beg_line = -2; |
921 |
sed_cmd->in_match = !( |
sed_cmd->in_match = !( |
922 |
/* has the ending line come, or is this a single address command? */ |
/* has the ending line come, or is this a single address command? */ |
923 |
(sed_cmd->end_line ? |
(sed_cmd->end_line ? |
933 |
); |
); |
934 |
} |
} |
935 |
|
|
936 |
/* Skip blocks of commands we didn't match. */ |
/* Skip blocks of commands we didn't match */ |
937 |
if (sed_cmd->cmd == '{') { |
if (sed_cmd->cmd == '{') { |
938 |
if (sed_cmd->invert ? matched : !matched) { |
if (sed_cmd->invert ? matched : !matched) { |
939 |
while (sed_cmd->cmd != '}') { |
while (sed_cmd->cmd != '}') { |
946 |
} |
} |
947 |
|
|
948 |
/* Okay, so did this line match? */ |
/* Okay, so did this line match? */ |
949 |
if (sed_cmd->invert ? !matched : matched) { |
if (sed_cmd->invert ? matched : !matched) |
950 |
/* Update last used regex in case a blank substitute BRE is found */ |
continue; /* no */ |
|
if (sed_cmd->beg_match) { |
|
|
G.previous_regex_ptr = sed_cmd->beg_match; |
|
|
} |
|
951 |
|
|
952 |
/* actual sedding */ |
/* Update last used regex in case a blank substitute BRE is found */ |
953 |
switch (sed_cmd->cmd) { |
if (sed_cmd->beg_match) { |
954 |
|
G.previous_regex_ptr = sed_cmd->beg_match; |
955 |
/* Print line number */ |
} |
|
case '=': |
|
|
fprintf(G.nonstdout, "%d\n", linenum); |
|
|
break; |
|
956 |
|
|
957 |
/* Write the current pattern space up to the first newline */ |
/* actual sedding */ |
958 |
case 'P': |
switch (sed_cmd->cmd) { |
|
{ |
|
|
char *tmp = strchr(pattern_space, '\n'); |
|
|
|
|
|
if (tmp) { |
|
|
*tmp = '\0'; |
|
|
/* TODO: explain why '\n' below */ |
|
|
sed_puts(pattern_space, '\n'); |
|
|
*tmp = '\n'; |
|
|
break; |
|
|
} |
|
|
/* Fall Through */ |
|
|
} |
|
959 |
|
|
960 |
/* Write the current pattern space to output */ |
/* Print line number */ |
961 |
case 'p': |
case '=': |
962 |
/* NB: we print this _before_ the last line |
fprintf(G.nonstdout, "%d\n", linenum); |
963 |
* (of current file) is printed. Even if |
break; |
|
* that line is nonterminated, we print |
|
|
* '\n' here (gnu sed does the same) */ |
|
|
sed_puts(pattern_space, '\n'); |
|
|
break; |
|
|
/* Delete up through first newline */ |
|
|
case 'D': |
|
|
{ |
|
|
char *tmp = strchr(pattern_space, '\n'); |
|
|
|
|
|
if (tmp) { |
|
|
tmp = xstrdup(tmp+1); |
|
|
free(pattern_space); |
|
|
pattern_space = tmp; |
|
|
goto restart; |
|
|
} |
|
|
} |
|
|
/* discard this line. */ |
|
|
case 'd': |
|
|
goto discard_line; |
|
|
|
|
|
/* Substitute with regex */ |
|
|
case 's': |
|
|
if (!do_subst_command(sed_cmd, &pattern_space)) |
|
|
break; |
|
|
substituted |= 1; |
|
|
|
|
|
/* handle p option */ |
|
|
if (sed_cmd->sub_p) |
|
|
sed_puts(pattern_space, last_gets_char); |
|
|
/* handle w option */ |
|
|
if (sed_cmd->sw_file) |
|
|
puts_maybe_newline( |
|
|
pattern_space, sed_cmd->sw_file, |
|
|
&sed_cmd->sw_last_char, last_gets_char); |
|
|
break; |
|
964 |
|
|
965 |
/* Append line to linked list to be printed later */ |
/* Write the current pattern space up to the first newline */ |
966 |
case 'a': |
case 'P': |
967 |
append(sed_cmd->string); |
{ |
968 |
break; |
char *tmp = strchr(pattern_space, '\n'); |
969 |
|
|
970 |
/* Insert text before this line */ |
if (tmp) { |
971 |
case 'i': |
*tmp = '\0'; |
972 |
sed_puts(sed_cmd->string, '\n'); |
/* TODO: explain why '\n' below */ |
973 |
|
sed_puts(pattern_space, '\n'); |
974 |
|
*tmp = '\n'; |
975 |
break; |
break; |
976 |
|
} |
977 |
|
/* Fall Through */ |
978 |
|
} |
979 |
|
|
980 |
/* Cut and paste text (replace) */ |
/* Write the current pattern space to output */ |
981 |
case 'c': |
case 'p': |
982 |
/* Only triggers on last line of a matching range. */ |
/* NB: we print this _before_ the last line |
983 |
if (!sed_cmd->in_match) |
* (of current file) is printed. Even if |
984 |
sed_puts(sed_cmd->string, NO_EOL_CHAR); |
* that line is nonterminated, we print |
985 |
goto discard_line; |
* '\n' here (gnu sed does the same) */ |
986 |
|
sed_puts(pattern_space, '\n'); |
987 |
|
break; |
988 |
|
/* Delete up through first newline */ |
989 |
|
case 'D': |
990 |
|
{ |
991 |
|
char *tmp = strchr(pattern_space, '\n'); |
992 |
|
|
993 |
/* Read file, append contents to output */ |
if (tmp) { |
994 |
case 'r': |
tmp = xstrdup(tmp+1); |
995 |
{ |
free(pattern_space); |
996 |
FILE *rfile; |
pattern_space = tmp; |
997 |
|
goto restart; |
998 |
rfile = fopen_for_read(sed_cmd->string); |
} |
999 |
if (rfile) { |
} |
1000 |
char *line; |
/* discard this line. */ |
1001 |
|
case 'd': |
1002 |
while ((line = xmalloc_fgetline(rfile)) |
goto discard_line; |
|
!= NULL) |
|
|
append(line); |
|
|
xprint_and_close_file(rfile); |
|
|
} |
|
1003 |
|
|
1004 |
|
/* Substitute with regex */ |
1005 |
|
case 's': |
1006 |
|
if (!do_subst_command(sed_cmd, &pattern_space)) |
1007 |
break; |
break; |
1008 |
} |
substituted |= 1; |
1009 |
|
|
1010 |
/* Write pattern space to file. */ |
/* handle p option */ |
1011 |
case 'w': |
if (sed_cmd->sub_p) |
1012 |
|
sed_puts(pattern_space, last_gets_char); |
1013 |
|
/* handle w option */ |
1014 |
|
if (sed_cmd->sw_file) |
1015 |
puts_maybe_newline( |
puts_maybe_newline( |
1016 |
pattern_space, sed_cmd->sw_file, |
pattern_space, sed_cmd->sw_file, |
1017 |
&sed_cmd->sw_last_char, last_gets_char); |
&sed_cmd->sw_last_char, last_gets_char); |
1018 |
break; |
break; |
1019 |
|
|
1020 |
/* Read next line from input */ |
/* Append line to linked list to be printed later */ |
1021 |
case 'n': |
case 'a': |
1022 |
if (!G.be_quiet) |
append(sed_cmd->string); |
1023 |
sed_puts(pattern_space, last_gets_char); |
break; |
|
if (next_line) { |
|
|
free(pattern_space); |
|
|
pattern_space = next_line; |
|
|
last_gets_char = next_gets_char; |
|
|
next_line = get_next_line(&next_gets_char); |
|
|
substituted = 0; |
|
|
linenum++; |
|
|
break; |
|
|
} |
|
|
/* fall through */ |
|
1024 |
|
|
1025 |
/* Quit. End of script, end of input. */ |
/* Insert text before this line */ |
1026 |
case 'q': |
case 'i': |
1027 |
/* Exit the outer while loop */ |
sed_puts(sed_cmd->string, '\n'); |
1028 |
free(next_line); |
break; |
|
next_line = NULL; |
|
|
goto discard_commands; |
|
1029 |
|
|
1030 |
/* Append the next line to the current line */ |
/* Cut and paste text (replace) */ |
1031 |
case 'N': |
case 'c': |
1032 |
{ |
/* Only triggers on last line of a matching range. */ |
1033 |
int len; |
if (!sed_cmd->in_match) |
1034 |
/* If no next line, jump to end of script and exit. */ |
sed_puts(sed_cmd->string, NO_EOL_CHAR); |
1035 |
if (next_line == NULL) { |
goto discard_line; |
1036 |
/* Jump to end of script and exit */ |
|
1037 |
free(next_line); |
/* Read file, append contents to output */ |
1038 |
next_line = NULL; |
case 'r': |
1039 |
goto discard_line; |
{ |
1040 |
/* append next_line, read new next_line. */ |
FILE *rfile; |
1041 |
} |
|
1042 |
len = strlen(pattern_space); |
rfile = fopen_for_read(sed_cmd->string); |
1043 |
pattern_space = realloc(pattern_space, len + strlen(next_line) + 2); |
if (rfile) { |
1044 |
pattern_space[len] = '\n'; |
char *line; |
1045 |
strcpy(pattern_space + len+1, next_line); |
|
1046 |
|
while ((line = xmalloc_fgetline(rfile)) |
1047 |
|
!= NULL) |
1048 |
|
append(line); |
1049 |
|
xprint_and_close_file(rfile); |
1050 |
|
} |
1051 |
|
|
1052 |
|
break; |
1053 |
|
} |
1054 |
|
|
1055 |
|
/* Write pattern space to file. */ |
1056 |
|
case 'w': |
1057 |
|
puts_maybe_newline( |
1058 |
|
pattern_space, sed_cmd->sw_file, |
1059 |
|
&sed_cmd->sw_last_char, last_gets_char); |
1060 |
|
break; |
1061 |
|
|
1062 |
|
/* Read next line from input */ |
1063 |
|
case 'n': |
1064 |
|
if (!G.be_quiet) |
1065 |
|
sed_puts(pattern_space, last_gets_char); |
1066 |
|
if (next_line) { |
1067 |
|
free(pattern_space); |
1068 |
|
pattern_space = next_line; |
1069 |
last_gets_char = next_gets_char; |
last_gets_char = next_gets_char; |
1070 |
next_line = get_next_line(&next_gets_char); |
next_line = get_next_line(&next_gets_char); |
1071 |
|
substituted = 0; |
1072 |
linenum++; |
linenum++; |
1073 |
break; |
break; |
1074 |
} |
} |
1075 |
|
/* fall through */ |
1076 |
|
|
1077 |
/* Test/branch if substitution occurred */ |
/* Quit. End of script, end of input. */ |
1078 |
case 't': |
case 'q': |
1079 |
if (!substituted) break; |
/* Exit the outer while loop */ |
1080 |
substituted = 0; |
free(next_line); |
1081 |
/* Fall through */ |
next_line = NULL; |
1082 |
/* Test/branch if substitution didn't occur */ |
goto discard_commands; |
|
case 'T': |
|
|
if (substituted) break; |
|
|
/* Fall through */ |
|
|
/* Branch to label */ |
|
|
case 'b': |
|
|
if (!sed_cmd->string) goto discard_commands; |
|
|
else sed_cmd = branch_to(sed_cmd->string); |
|
|
break; |
|
|
/* Transliterate characters */ |
|
|
case 'y': |
|
|
{ |
|
|
int i, j; |
|
|
|
|
|
for (i = 0; pattern_space[i]; i++) { |
|
|
for (j = 0; sed_cmd->string[j]; j += 2) { |
|
|
if (pattern_space[i] == sed_cmd->string[j]) { |
|
|
pattern_space[i] = sed_cmd->string[j + 1]; |
|
|
break; |
|
|
} |
|
|
} |
|
|
} |
|
1083 |
|
|
1084 |
break; |
/* Append the next line to the current line */ |
1085 |
|
case 'N': |
1086 |
|
{ |
1087 |
|
int len; |
1088 |
|
/* If no next line, jump to end of script and exit. */ |
1089 |
|
if (next_line == NULL) { |
1090 |
|
/* Jump to end of script and exit */ |
1091 |
|
free(next_line); |
1092 |
|
next_line = NULL; |
1093 |
|
goto discard_line; |
1094 |
|
/* append next_line, read new next_line. */ |
1095 |
} |
} |
1096 |
case 'g': /* Replace pattern space with hold space */ |
len = strlen(pattern_space); |
1097 |
free(pattern_space); |
pattern_space = xrealloc(pattern_space, len + strlen(next_line) + 2); |
1098 |
pattern_space = xstrdup(G.hold_space ? G.hold_space : ""); |
pattern_space[len] = '\n'; |
1099 |
break; |
strcpy(pattern_space + len+1, next_line); |
1100 |
case 'G': /* Append newline and hold space to pattern space */ |
last_gets_char = next_gets_char; |
1101 |
{ |
next_line = get_next_line(&next_gets_char); |
1102 |
int pattern_space_size = 2; |
linenum++; |
1103 |
int hold_space_size = 0; |
break; |
1104 |
|
} |
|
if (pattern_space) |
|
|
pattern_space_size += strlen(pattern_space); |
|
|
if (G.hold_space) |
|
|
hold_space_size = strlen(G.hold_space); |
|
|
pattern_space = xrealloc(pattern_space, |
|
|
pattern_space_size + hold_space_size); |
|
|
if (pattern_space_size == 2) |
|
|
pattern_space[0] = 0; |
|
|
strcat(pattern_space, "\n"); |
|
|
if (G.hold_space) |
|
|
strcat(pattern_space, G.hold_space); |
|
|
last_gets_char = '\n'; |
|
1105 |
|
|
1106 |
break; |
/* Test/branch if substitution occurred */ |
1107 |
} |
case 't': |
1108 |
case 'h': /* Replace hold space with pattern space */ |
if (!substituted) break; |
1109 |
free(G.hold_space); |
substituted = 0; |
1110 |
G.hold_space = xstrdup(pattern_space); |
/* Fall through */ |
1111 |
break; |
/* Test/branch if substitution didn't occur */ |
1112 |
case 'H': /* Append newline and pattern space to hold space */ |
case 'T': |
1113 |
{ |
if (substituted) break; |
1114 |
int hold_space_size = 2; |
/* Fall through */ |
1115 |
int pattern_space_size = 0; |
/* Branch to label */ |
1116 |
|
case 'b': |
1117 |
if (G.hold_space) |
if (!sed_cmd->string) goto discard_commands; |
1118 |
hold_space_size += strlen(G.hold_space); |
else sed_cmd = branch_to(sed_cmd->string); |
1119 |
if (pattern_space) |
break; |
1120 |
pattern_space_size = strlen(pattern_space); |
/* Transliterate characters */ |
1121 |
G.hold_space = xrealloc(G.hold_space, |
case 'y': |
1122 |
hold_space_size + pattern_space_size); |
{ |
1123 |
|
int i, j; |
|
if (hold_space_size == 2) |
|
|
*G.hold_space = 0; |
|
|
strcat(G.hold_space, "\n"); |
|
|
if (pattern_space) |
|
|
strcat(G.hold_space, pattern_space); |
|
1124 |
|
|
1125 |
break; |
for (i = 0; pattern_space[i]; i++) { |
1126 |
} |
for (j = 0; sed_cmd->string[j]; j += 2) { |
1127 |
case 'x': /* Exchange hold and pattern space */ |
if (pattern_space[i] == sed_cmd->string[j]) { |
1128 |
{ |
pattern_space[i] = sed_cmd->string[j + 1]; |
1129 |
char *tmp = pattern_space; |
break; |
1130 |
pattern_space = G.hold_space ? : xzalloc(1); |
} |
1131 |
last_gets_char = '\n'; |
} |
|
G.hold_space = tmp; |
|
|
break; |
|
|
} |
|
1132 |
} |
} |
1133 |
|
|
1134 |
|
break; |
1135 |
} |
} |
1136 |
} |
case 'g': /* Replace pattern space with hold space */ |
1137 |
|
free(pattern_space); |
1138 |
|
pattern_space = xstrdup(G.hold_space ? G.hold_space : ""); |
1139 |
|
break; |
1140 |
|
case 'G': /* Append newline and hold space to pattern space */ |
1141 |
|
{ |
1142 |
|
int pattern_space_size = 2; |
1143 |
|
int hold_space_size = 0; |
1144 |
|
|
1145 |
|
if (pattern_space) |
1146 |
|
pattern_space_size += strlen(pattern_space); |
1147 |
|
if (G.hold_space) |
1148 |
|
hold_space_size = strlen(G.hold_space); |
1149 |
|
pattern_space = xrealloc(pattern_space, |
1150 |
|
pattern_space_size + hold_space_size); |
1151 |
|
if (pattern_space_size == 2) |
1152 |
|
pattern_space[0] = 0; |
1153 |
|
strcat(pattern_space, "\n"); |
1154 |
|
if (G.hold_space) |
1155 |
|
strcat(pattern_space, G.hold_space); |
1156 |
|
last_gets_char = '\n'; |
1157 |
|
|
1158 |
|
break; |
1159 |
|
} |
1160 |
|
case 'h': /* Replace hold space with pattern space */ |
1161 |
|
free(G.hold_space); |
1162 |
|
G.hold_space = xstrdup(pattern_space); |
1163 |
|
break; |
1164 |
|
case 'H': /* Append newline and pattern space to hold space */ |
1165 |
|
{ |
1166 |
|
int hold_space_size = 2; |
1167 |
|
int pattern_space_size = 0; |
1168 |
|
|
1169 |
|
if (G.hold_space) |
1170 |
|
hold_space_size += strlen(G.hold_space); |
1171 |
|
if (pattern_space) |
1172 |
|
pattern_space_size = strlen(pattern_space); |
1173 |
|
G.hold_space = xrealloc(G.hold_space, |
1174 |
|
hold_space_size + pattern_space_size); |
1175 |
|
|
1176 |
|
if (hold_space_size == 2) |
1177 |
|
*G.hold_space = 0; |
1178 |
|
strcat(G.hold_space, "\n"); |
1179 |
|
if (pattern_space) |
1180 |
|
strcat(G.hold_space, pattern_space); |
1181 |
|
|
1182 |
|
break; |
1183 |
|
} |
1184 |
|
case 'x': /* Exchange hold and pattern space */ |
1185 |
|
{ |
1186 |
|
char *tmp = pattern_space; |
1187 |
|
pattern_space = G.hold_space ? G.hold_space : xzalloc(1); |
1188 |
|
last_gets_char = '\n'; |
1189 |
|
G.hold_space = tmp; |
1190 |
|
break; |
1191 |
|
} |
1192 |
|
} /* switch */ |
1193 |
|
} /* for each cmd */ |
1194 |
|
|
1195 |
/* |
/* |
1196 |
* exit point from sedding... |
* Exit point from sedding... |
1197 |
*/ |
*/ |
1198 |
discard_commands: |
discard_commands: |
1199 |
/* we will print the line unless we were told to be quiet ('-n') |
/* we will print the line unless we were told to be quiet ('-n') |
1337 |
G.outname = xasprintf("%sXXXXXX", argv[i]); |
G.outname = xasprintf("%sXXXXXX", argv[i]); |
1338 |
nonstdoutfd = mkstemp(G.outname); |
nonstdoutfd = mkstemp(G.outname); |
1339 |
if (-1 == nonstdoutfd) |
if (-1 == nonstdoutfd) |
1340 |
bb_perror_msg_and_die("cannot create temp file %s", G.outname); |
bb_perror_msg_and_die("can't create temp file %s", G.outname); |
1341 |
G.nonstdout = fdopen(nonstdoutfd, "w"); |
G.nonstdout = xfdopen_for_write(nonstdoutfd); |
|
|
|
|
/* Set permissions of output file */ |
|
1342 |
|
|
1343 |
|
/* Set permissions/owner of output file */ |
1344 |
fstat(fileno(file), &statbuf); |
fstat(fileno(file), &statbuf); |
1345 |
fchmod(nonstdoutfd, statbuf.st_mode); |
fchmod(nonstdoutfd, statbuf.st_mode); |
1346 |
|
fchown(nonstdoutfd, statbuf.st_uid, statbuf.st_gid); |
1347 |
add_input_file(file); |
add_input_file(file); |
1348 |
process_files(); |
process_files(); |
1349 |
fclose(G.nonstdout); |
fclose(G.nonstdout); |