diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2009-06-30 19:19:37 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-06-30 19:19:37 +0200 |
commit | 8bca3e20b9c057e9144af27870ca3905f1e5d316 (patch) | |
tree | c5472b7e8dfdbd847810ba833d5f69e5de327ccc /editors/sed.c | |
parent | f1fab0924285cca27903a1e4a4498c7205810742 (diff) | |
download | busybox-w32-8bca3e20b9c057e9144af27870ca3905f1e5d316.tar.gz busybox-w32-8bca3e20b9c057e9144af27870ca3905f1e5d316.tar.bz2 busybox-w32-8bca3e20b9c057e9144af27870ca3905f1e5d316.zip |
sed: fix handling of 1d;1,3p and 1d;1,REGEXp
function old new delta
process_files 2084 2173 +89
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'editors/sed.c')
-rw-r--r-- | editors/sed.c | 476 |
1 files changed, 247 insertions, 229 deletions
diff --git a/editors/sed.c b/editors/sed.c index eb31f7d2e..2127301d5 100644 --- a/editors/sed.c +++ b/editors/sed.c | |||
@@ -865,63 +865,80 @@ static void process_files(void) | |||
865 | /* Prime the pump */ | 865 | /* Prime the pump */ |
866 | next_line = get_next_line(&next_gets_char); | 866 | next_line = get_next_line(&next_gets_char); |
867 | 867 | ||
868 | /* go through every line in each file */ | 868 | /* Go through every line in each file */ |
869 | again: | 869 | again: |
870 | substituted = 0; | 870 | substituted = 0; |
871 | 871 | ||
872 | /* Advance to next line. Stop if out of lines. */ | 872 | /* Advance to next line. Stop if out of lines. */ |
873 | pattern_space = next_line; | 873 | pattern_space = next_line; |
874 | if (!pattern_space) return; | 874 | if (!pattern_space) |
875 | return; | ||
875 | last_gets_char = next_gets_char; | 876 | last_gets_char = next_gets_char; |
876 | 877 | ||
877 | /* Read one line in advance so we can act on the last line, | 878 | /* Read one line in advance so we can act on the last line, |
878 | * the '$' address */ | 879 | * the '$' address */ |
879 | next_line = get_next_line(&next_gets_char); | 880 | next_line = get_next_line(&next_gets_char); |
880 | linenum++; | 881 | linenum++; |
882 | |||
883 | /* For every line, go through all the commands */ | ||
881 | restart: | 884 | restart: |
882 | /* for every line, go through all the commands */ | ||
883 | for (sed_cmd = G.sed_cmd_head.next; sed_cmd; sed_cmd = sed_cmd->next) { | 885 | for (sed_cmd = G.sed_cmd_head.next; sed_cmd; sed_cmd = sed_cmd->next) { |
884 | int old_matched, matched; | 886 | int old_matched, matched; |
885 | 887 | ||
886 | old_matched = sed_cmd->in_match; | 888 | old_matched = sed_cmd->in_match; |
887 | 889 | ||
888 | /* Determine if this command matches this line: */ | 890 | /* Determine if this command matches this line: */ |
889 | 891 | /* Are we continuing a previous multi-line match? */ | |
890 | /* Are we continuing a previous multi-line match? */ | ||
891 | sed_cmd->in_match = sed_cmd->in_match | 892 | sed_cmd->in_match = sed_cmd->in_match |
892 | /* Or is no range necessary? */ | 893 | /* Or is no range necessary? */ |
893 | || (!sed_cmd->beg_line && !sed_cmd->end_line | 894 | || (!sed_cmd->beg_line && !sed_cmd->end_line |
894 | && !sed_cmd->beg_match && !sed_cmd->end_match) | 895 | && !sed_cmd->beg_match && !sed_cmd->end_match) |
895 | /* Or did we match the start of a numerical range? */ | 896 | /* Or did we match the start of a numerical range? */ |
896 | || (sed_cmd->beg_line > 0 && (sed_cmd->beg_line == linenum)) | 897 | || (sed_cmd->beg_line > 0 && (sed_cmd->beg_line == linenum |
898 | /* "shadowed beginning" case: "1d;1,ENDp" - p still matches at line 2 | ||
899 | * even though 1d skipped line 1 which is a start line for p */ | ||
900 | || (sed_cmd->end_line && sed_cmd->beg_line < linenum && sed_cmd->end_line >= linenum) | ||
901 | || (sed_cmd->end_match && sed_cmd->beg_line < linenum) | ||
902 | ) | ||
903 | ) | ||
897 | /* Or does this line match our begin address regex? */ | 904 | /* Or does this line match our begin address regex? */ |
898 | || (beg_match(sed_cmd, pattern_space)) | 905 | || (beg_match(sed_cmd, pattern_space)) |
899 | /* Or did we match last line of input? */ | 906 | /* Or did we match last line of input? */ |
900 | || (sed_cmd->beg_line == -1 && next_line == NULL); | 907 | || (sed_cmd->beg_line == -1 && next_line == NULL); |
901 | 908 | ||
902 | /* Snapshot the value */ | ||
903 | |||
904 | matched = sed_cmd->in_match; | 909 | matched = sed_cmd->in_match; |
905 | 910 | ||
906 | /* Is this line the end of the current match? */ | 911 | //bb_error_msg("cmd:'%c' matched:%d beg_line:%d end_line:%d linenum:%d", |
912 | //sed_cmd->cmd, matched, sed_cmd->beg_line, sed_cmd->end_line, linenum); | ||
907 | 913 | ||
914 | /* Is this line the end of the current match? */ | ||
908 | if (matched) { | 915 | if (matched) { |
909 | sed_cmd->in_match = !( | 916 | int n = ( |
910 | /* has the ending line come, or is this a single address command? */ | 917 | /* has the ending line come, or is this a single address command? */ |
911 | (sed_cmd->end_line ? | 918 | sed_cmd->end_line ? |
912 | sed_cmd->end_line == -1 ? | 919 | sed_cmd->end_line == -1 ? |
913 | !next_line | 920 | !next_line |
914 | : (sed_cmd->end_line <= linenum) | 921 | : (sed_cmd->end_line <= linenum) |
915 | : !sed_cmd->end_match | 922 | : !sed_cmd->end_match |
916 | ) | 923 | ); |
924 | if (!n) { | ||
917 | /* or does this line matches our last address regex */ | 925 | /* or does this line matches our last address regex */ |
918 | || (sed_cmd->end_match && old_matched | 926 | n = (sed_cmd->end_match |
927 | && old_matched | ||
919 | && (regexec(sed_cmd->end_match, | 928 | && (regexec(sed_cmd->end_match, |
920 | pattern_space, 0, NULL, 0) == 0)) | 929 | pattern_space, 0, NULL, 0) == 0) |
921 | ); | 930 | ); |
931 | if (n && sed_cmd->beg_line > 0) { | ||
932 | /* Once matched, "n,regex" range is dead, disabling it */ | ||
933 | regfree(sed_cmd->end_match); | ||
934 | free(sed_cmd->end_match); | ||
935 | sed_cmd->end_match = NULL; | ||
936 | } | ||
937 | } | ||
938 | sed_cmd->in_match = !n; | ||
922 | } | 939 | } |
923 | 940 | ||
924 | /* Skip blocks of commands we didn't match. */ | 941 | /* Skip blocks of commands we didn't match */ |
925 | if (sed_cmd->cmd == '{') { | 942 | if (sed_cmd->cmd == '{') { |
926 | if (sed_cmd->invert ? matched : !matched) { | 943 | if (sed_cmd->invert ? matched : !matched) { |
927 | while (sed_cmd->cmd != '}') { | 944 | while (sed_cmd->cmd != '}') { |
@@ -934,253 +951,254 @@ static void process_files(void) | |||
934 | } | 951 | } |
935 | 952 | ||
936 | /* Okay, so did this line match? */ | 953 | /* Okay, so did this line match? */ |
937 | if (sed_cmd->invert ? !matched : matched) { | 954 | if (sed_cmd->invert ? matched : !matched) |
938 | /* Update last used regex in case a blank substitute BRE is found */ | 955 | continue; /* no */ |
939 | if (sed_cmd->beg_match) { | ||
940 | G.previous_regex_ptr = sed_cmd->beg_match; | ||
941 | } | ||
942 | 956 | ||
943 | /* actual sedding */ | 957 | /* Update last used regex in case a blank substitute BRE is found */ |
944 | switch (sed_cmd->cmd) { | 958 | if (sed_cmd->beg_match) { |
959 | G.previous_regex_ptr = sed_cmd->beg_match; | ||
960 | } | ||
945 | 961 | ||
946 | /* Print line number */ | 962 | /* actual sedding */ |
947 | case '=': | 963 | switch (sed_cmd->cmd) { |
948 | fprintf(G.nonstdout, "%d\n", linenum); | ||
949 | break; | ||
950 | 964 | ||
951 | /* Write the current pattern space up to the first newline */ | 965 | /* Print line number */ |
952 | case 'P': | 966 | case '=': |
953 | { | 967 | fprintf(G.nonstdout, "%d\n", linenum); |
954 | char *tmp = strchr(pattern_space, '\n'); | 968 | break; |
955 | |||
956 | if (tmp) { | ||
957 | *tmp = '\0'; | ||
958 | /* TODO: explain why '\n' below */ | ||
959 | sed_puts(pattern_space, '\n'); | ||
960 | *tmp = '\n'; | ||
961 | break; | ||
962 | } | ||
963 | /* Fall Through */ | ||
964 | } | ||
965 | 969 | ||
966 | /* Write the current pattern space to output */ | 970 | /* Write the current pattern space up to the first newline */ |
967 | case 'p': | 971 | case 'P': |
968 | /* NB: we print this _before_ the last line | 972 | { |
969 | * (of current file) is printed. Even if | 973 | char *tmp = strchr(pattern_space, '\n'); |
970 | * that line is nonterminated, we print | 974 | |
971 | * '\n' here (gnu sed does the same) */ | 975 | if (tmp) { |
976 | *tmp = '\0'; | ||
977 | /* TODO: explain why '\n' below */ | ||
972 | sed_puts(pattern_space, '\n'); | 978 | sed_puts(pattern_space, '\n'); |
979 | *tmp = '\n'; | ||
973 | break; | 980 | break; |
974 | /* Delete up through first newline */ | ||
975 | case 'D': | ||
976 | { | ||
977 | char *tmp = strchr(pattern_space, '\n'); | ||
978 | |||
979 | if (tmp) { | ||
980 | tmp = xstrdup(tmp+1); | ||
981 | free(pattern_space); | ||
982 | pattern_space = tmp; | ||
983 | goto restart; | ||
984 | } | ||
985 | } | 981 | } |
986 | /* discard this line. */ | 982 | /* Fall Through */ |
987 | case 'd': | 983 | } |
988 | goto discard_line; | ||
989 | 984 | ||
990 | /* Substitute with regex */ | 985 | /* Write the current pattern space to output */ |
991 | case 's': | 986 | case 'p': |
992 | if (!do_subst_command(sed_cmd, &pattern_space)) | 987 | /* NB: we print this _before_ the last line |
993 | break; | 988 | * (of current file) is printed. Even if |
994 | substituted |= 1; | 989 | * that line is nonterminated, we print |
995 | 990 | * '\n' here (gnu sed does the same) */ | |
996 | /* handle p option */ | 991 | sed_puts(pattern_space, '\n'); |
997 | if (sed_cmd->sub_p) | 992 | break; |
998 | sed_puts(pattern_space, last_gets_char); | 993 | /* Delete up through first newline */ |
999 | /* handle w option */ | 994 | case 'D': |
1000 | if (sed_cmd->sw_file) | 995 | { |
1001 | puts_maybe_newline( | 996 | char *tmp = strchr(pattern_space, '\n'); |
1002 | pattern_space, sed_cmd->sw_file, | ||
1003 | &sed_cmd->sw_last_char, last_gets_char); | ||
1004 | break; | ||
1005 | 997 | ||
1006 | /* Append line to linked list to be printed later */ | 998 | if (tmp) { |
1007 | case 'a': | 999 | tmp = xstrdup(tmp+1); |
1008 | append(sed_cmd->string); | 1000 | free(pattern_space); |
1009 | break; | 1001 | pattern_space = tmp; |
1002 | goto restart; | ||
1003 | } | ||
1004 | } | ||
1005 | /* discard this line. */ | ||
1006 | case 'd': | ||
1007 | goto discard_line; | ||
1010 | 1008 | ||
1011 | /* Insert text before this line */ | 1009 | /* Substitute with regex */ |
1012 | case 'i': | 1010 | case 's': |
1013 | sed_puts(sed_cmd->string, '\n'); | 1011 | if (!do_subst_command(sed_cmd, &pattern_space)) |
1014 | break; | 1012 | break; |
1013 | substituted |= 1; | ||
1015 | 1014 | ||
1016 | /* Cut and paste text (replace) */ | 1015 | /* handle p option */ |
1017 | case 'c': | 1016 | if (sed_cmd->sub_p) |
1018 | /* Only triggers on last line of a matching range. */ | 1017 | sed_puts(pattern_space, last_gets_char); |
1019 | if (!sed_cmd->in_match) | 1018 | /* handle w option */ |
1020 | sed_puts(sed_cmd->string, NO_EOL_CHAR); | 1019 | if (sed_cmd->sw_file) |
1021 | goto discard_line; | 1020 | puts_maybe_newline( |
1021 | pattern_space, sed_cmd->sw_file, | ||
1022 | &sed_cmd->sw_last_char, last_gets_char); | ||
1023 | break; | ||
1022 | 1024 | ||
1023 | /* Read file, append contents to output */ | 1025 | /* Append line to linked list to be printed later */ |
1024 | case 'r': | 1026 | case 'a': |
1025 | { | 1027 | append(sed_cmd->string); |
1026 | FILE *rfile; | 1028 | break; |
1027 | 1029 | ||
1028 | rfile = fopen_for_read(sed_cmd->string); | 1030 | /* Insert text before this line */ |
1029 | if (rfile) { | 1031 | case 'i': |
1030 | char *line; | 1032 | sed_puts(sed_cmd->string, '\n'); |
1033 | break; | ||
1031 | 1034 | ||
1032 | while ((line = xmalloc_fgetline(rfile)) | 1035 | /* Cut and paste text (replace) */ |
1033 | != NULL) | 1036 | case 'c': |
1034 | append(line); | 1037 | /* Only triggers on last line of a matching range. */ |
1035 | xprint_and_close_file(rfile); | 1038 | if (!sed_cmd->in_match) |
1036 | } | 1039 | sed_puts(sed_cmd->string, NO_EOL_CHAR); |
1040 | goto discard_line; | ||
1037 | 1041 | ||
1038 | break; | 1042 | /* Read file, append contents to output */ |
1043 | case 'r': | ||
1044 | { | ||
1045 | FILE *rfile; | ||
1046 | |||
1047 | rfile = fopen_for_read(sed_cmd->string); | ||
1048 | if (rfile) { | ||
1049 | char *line; | ||
1050 | |||
1051 | while ((line = xmalloc_fgetline(rfile)) | ||
1052 | != NULL) | ||
1053 | append(line); | ||
1054 | xprint_and_close_file(rfile); | ||
1039 | } | 1055 | } |
1040 | 1056 | ||
1041 | /* Write pattern space to file. */ | 1057 | break; |
1042 | case 'w': | 1058 | } |
1043 | puts_maybe_newline( | ||
1044 | pattern_space, sed_cmd->sw_file, | ||
1045 | &sed_cmd->sw_last_char, last_gets_char); | ||
1046 | break; | ||
1047 | 1059 | ||
1048 | /* Read next line from input */ | 1060 | /* Write pattern space to file. */ |
1049 | case 'n': | 1061 | case 'w': |
1050 | if (!G.be_quiet) | 1062 | puts_maybe_newline( |
1051 | sed_puts(pattern_space, last_gets_char); | 1063 | pattern_space, sed_cmd->sw_file, |
1052 | if (next_line) { | 1064 | &sed_cmd->sw_last_char, last_gets_char); |
1053 | free(pattern_space); | 1065 | break; |
1054 | pattern_space = next_line; | ||
1055 | last_gets_char = next_gets_char; | ||
1056 | next_line = get_next_line(&next_gets_char); | ||
1057 | substituted = 0; | ||
1058 | linenum++; | ||
1059 | break; | ||
1060 | } | ||
1061 | /* fall through */ | ||
1062 | 1066 | ||
1063 | /* Quit. End of script, end of input. */ | 1067 | /* Read next line from input */ |
1064 | case 'q': | 1068 | case 'n': |
1065 | /* Exit the outer while loop */ | 1069 | if (!G.be_quiet) |
1066 | free(next_line); | 1070 | sed_puts(pattern_space, last_gets_char); |
1067 | next_line = NULL; | 1071 | if (next_line) { |
1068 | goto discard_commands; | 1072 | free(pattern_space); |
1069 | 1073 | pattern_space = next_line; | |
1070 | /* Append the next line to the current line */ | ||
1071 | case 'N': | ||
1072 | { | ||
1073 | int len; | ||
1074 | /* If no next line, jump to end of script and exit. */ | ||
1075 | if (next_line == NULL) { | ||
1076 | /* Jump to end of script and exit */ | ||
1077 | free(next_line); | ||
1078 | next_line = NULL; | ||
1079 | goto discard_line; | ||
1080 | /* append next_line, read new next_line. */ | ||
1081 | } | ||
1082 | len = strlen(pattern_space); | ||
1083 | pattern_space = realloc(pattern_space, len + strlen(next_line) + 2); | ||
1084 | pattern_space[len] = '\n'; | ||
1085 | strcpy(pattern_space + len+1, next_line); | ||
1086 | last_gets_char = next_gets_char; | 1074 | last_gets_char = next_gets_char; |
1087 | next_line = get_next_line(&next_gets_char); | 1075 | next_line = get_next_line(&next_gets_char); |
1076 | substituted = 0; | ||
1088 | linenum++; | 1077 | linenum++; |
1089 | break; | 1078 | break; |
1090 | } | 1079 | } |
1080 | /* fall through */ | ||
1091 | 1081 | ||
1092 | /* Test/branch if substitution occurred */ | 1082 | /* Quit. End of script, end of input. */ |
1093 | case 't': | 1083 | case 'q': |
1094 | if (!substituted) break; | 1084 | /* Exit the outer while loop */ |
1095 | substituted = 0; | 1085 | free(next_line); |
1096 | /* Fall through */ | 1086 | next_line = NULL; |
1097 | /* Test/branch if substitution didn't occur */ | 1087 | goto discard_commands; |
1098 | case 'T': | ||
1099 | if (substituted) break; | ||
1100 | /* Fall through */ | ||
1101 | /* Branch to label */ | ||
1102 | case 'b': | ||
1103 | if (!sed_cmd->string) goto discard_commands; | ||
1104 | else sed_cmd = branch_to(sed_cmd->string); | ||
1105 | break; | ||
1106 | /* Transliterate characters */ | ||
1107 | case 'y': | ||
1108 | { | ||
1109 | int i, j; | ||
1110 | |||
1111 | for (i = 0; pattern_space[i]; i++) { | ||
1112 | for (j = 0; sed_cmd->string[j]; j += 2) { | ||
1113 | if (pattern_space[i] == sed_cmd->string[j]) { | ||
1114 | pattern_space[i] = sed_cmd->string[j + 1]; | ||
1115 | break; | ||
1116 | } | ||
1117 | } | ||
1118 | } | ||
1119 | 1088 | ||
1120 | break; | 1089 | /* Append the next line to the current line */ |
1090 | case 'N': | ||
1091 | { | ||
1092 | int len; | ||
1093 | /* If no next line, jump to end of script and exit. */ | ||
1094 | if (next_line == NULL) { | ||
1095 | /* Jump to end of script and exit */ | ||
1096 | free(next_line); | ||
1097 | next_line = NULL; | ||
1098 | goto discard_line; | ||
1099 | /* append next_line, read new next_line. */ | ||
1121 | } | 1100 | } |
1122 | case 'g': /* Replace pattern space with hold space */ | 1101 | len = strlen(pattern_space); |
1123 | free(pattern_space); | 1102 | pattern_space = realloc(pattern_space, len + strlen(next_line) + 2); |
1124 | pattern_space = xstrdup(G.hold_space ? G.hold_space : ""); | 1103 | pattern_space[len] = '\n'; |
1125 | break; | 1104 | strcpy(pattern_space + len+1, next_line); |
1126 | case 'G': /* Append newline and hold space to pattern space */ | 1105 | last_gets_char = next_gets_char; |
1127 | { | 1106 | next_line = get_next_line(&next_gets_char); |
1128 | int pattern_space_size = 2; | 1107 | linenum++; |
1129 | int hold_space_size = 0; | 1108 | break; |
1130 | 1109 | } | |
1131 | if (pattern_space) | ||
1132 | pattern_space_size += strlen(pattern_space); | ||
1133 | if (G.hold_space) | ||
1134 | hold_space_size = strlen(G.hold_space); | ||
1135 | pattern_space = xrealloc(pattern_space, | ||
1136 | pattern_space_size + hold_space_size); | ||
1137 | if (pattern_space_size == 2) | ||
1138 | pattern_space[0] = 0; | ||
1139 | strcat(pattern_space, "\n"); | ||
1140 | if (G.hold_space) | ||
1141 | strcat(pattern_space, G.hold_space); | ||
1142 | last_gets_char = '\n'; | ||
1143 | 1110 | ||
1144 | break; | 1111 | /* Test/branch if substitution occurred */ |
1145 | } | 1112 | case 't': |
1146 | case 'h': /* Replace hold space with pattern space */ | 1113 | if (!substituted) break; |
1147 | free(G.hold_space); | 1114 | substituted = 0; |
1148 | G.hold_space = xstrdup(pattern_space); | 1115 | /* Fall through */ |
1149 | break; | 1116 | /* Test/branch if substitution didn't occur */ |
1150 | case 'H': /* Append newline and pattern space to hold space */ | 1117 | case 'T': |
1151 | { | 1118 | if (substituted) break; |
1152 | int hold_space_size = 2; | 1119 | /* Fall through */ |
1153 | int pattern_space_size = 0; | 1120 | /* Branch to label */ |
1154 | 1121 | case 'b': | |
1155 | if (G.hold_space) | 1122 | if (!sed_cmd->string) goto discard_commands; |
1156 | hold_space_size += strlen(G.hold_space); | 1123 | else sed_cmd = branch_to(sed_cmd->string); |
1157 | if (pattern_space) | 1124 | break; |
1158 | pattern_space_size = strlen(pattern_space); | 1125 | /* Transliterate characters */ |
1159 | G.hold_space = xrealloc(G.hold_space, | 1126 | case 'y': |
1160 | hold_space_size + pattern_space_size); | 1127 | { |
1161 | 1128 | int i, j; | |
1162 | if (hold_space_size == 2) | ||
1163 | *G.hold_space = 0; | ||
1164 | strcat(G.hold_space, "\n"); | ||
1165 | if (pattern_space) | ||
1166 | strcat(G.hold_space, pattern_space); | ||
1167 | 1129 | ||
1168 | break; | 1130 | for (i = 0; pattern_space[i]; i++) { |
1169 | } | 1131 | for (j = 0; sed_cmd->string[j]; j += 2) { |
1170 | case 'x': /* Exchange hold and pattern space */ | 1132 | if (pattern_space[i] == sed_cmd->string[j]) { |
1171 | { | 1133 | pattern_space[i] = sed_cmd->string[j + 1]; |
1172 | char *tmp = pattern_space; | 1134 | break; |
1173 | pattern_space = G.hold_space ? : xzalloc(1); | 1135 | } |
1174 | last_gets_char = '\n'; | 1136 | } |
1175 | G.hold_space = tmp; | ||
1176 | break; | ||
1177 | } | ||
1178 | } | 1137 | } |
1138 | |||
1139 | break; | ||
1179 | } | 1140 | } |
1180 | } | 1141 | case 'g': /* Replace pattern space with hold space */ |
1142 | free(pattern_space); | ||
1143 | pattern_space = xstrdup(G.hold_space ? G.hold_space : ""); | ||
1144 | break; | ||
1145 | case 'G': /* Append newline and hold space to pattern space */ | ||
1146 | { | ||
1147 | int pattern_space_size = 2; | ||
1148 | int hold_space_size = 0; | ||
1149 | |||
1150 | if (pattern_space) | ||
1151 | pattern_space_size += strlen(pattern_space); | ||
1152 | if (G.hold_space) | ||
1153 | hold_space_size = strlen(G.hold_space); | ||
1154 | pattern_space = xrealloc(pattern_space, | ||
1155 | pattern_space_size + hold_space_size); | ||
1156 | if (pattern_space_size == 2) | ||
1157 | pattern_space[0] = 0; | ||
1158 | strcat(pattern_space, "\n"); | ||
1159 | if (G.hold_space) | ||
1160 | strcat(pattern_space, G.hold_space); | ||
1161 | last_gets_char = '\n'; | ||
1162 | |||
1163 | break; | ||
1164 | } | ||
1165 | case 'h': /* Replace hold space with pattern space */ | ||
1166 | free(G.hold_space); | ||
1167 | G.hold_space = xstrdup(pattern_space); | ||
1168 | break; | ||
1169 | case 'H': /* Append newline and pattern space to hold space */ | ||
1170 | { | ||
1171 | int hold_space_size = 2; | ||
1172 | int pattern_space_size = 0; | ||
1173 | |||
1174 | if (G.hold_space) | ||
1175 | hold_space_size += strlen(G.hold_space); | ||
1176 | if (pattern_space) | ||
1177 | pattern_space_size = strlen(pattern_space); | ||
1178 | G.hold_space = xrealloc(G.hold_space, | ||
1179 | hold_space_size + pattern_space_size); | ||
1180 | |||
1181 | if (hold_space_size == 2) | ||
1182 | *G.hold_space = 0; | ||
1183 | strcat(G.hold_space, "\n"); | ||
1184 | if (pattern_space) | ||
1185 | strcat(G.hold_space, pattern_space); | ||
1186 | |||
1187 | break; | ||
1188 | } | ||
1189 | case 'x': /* Exchange hold and pattern space */ | ||
1190 | { | ||
1191 | char *tmp = pattern_space; | ||
1192 | pattern_space = G.hold_space ? : xzalloc(1); | ||
1193 | last_gets_char = '\n'; | ||
1194 | G.hold_space = tmp; | ||
1195 | break; | ||
1196 | } | ||
1197 | } /* switch */ | ||
1198 | } /* for each cmd */ | ||
1181 | 1199 | ||
1182 | /* | 1200 | /* |
1183 | * exit point from sedding... | 1201 | * Exit point from sedding... |
1184 | */ | 1202 | */ |
1185 | discard_commands: | 1203 | discard_commands: |
1186 | /* we will print the line unless we were told to be quiet ('-n') | 1204 | /* we will print the line unless we were told to be quiet ('-n') |