117 |
int idx; /* Space used */ |
int idx; /* Space used */ |
118 |
int len; /* Space allocated */ |
int len; /* Space allocated */ |
119 |
} pipeline; |
} pipeline; |
120 |
}; |
} FIX_ALIASING; |
121 |
#define G (*(struct globals*)&bb_common_bufsiz1) |
#define G (*(struct globals*)&bb_common_bufsiz1) |
122 |
void BUG_sed_globals_too_big(void); |
struct BUG_G_too_big { |
123 |
|
char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1]; |
124 |
|
}; |
125 |
#define INIT_G() do { \ |
#define INIT_G() do { \ |
|
if (sizeof(struct globals) > COMMON_BUFSIZE) \ |
|
|
BUG_sed_globals_too_big(); \ |
|
126 |
G.sed_cmd_tail = &G.sed_cmd_head; \ |
G.sed_cmd_tail = &G.sed_cmd_head; \ |
127 |
} while (0) |
} while (0) |
128 |
|
|
385 |
break; |
break; |
386 |
/* Comment */ |
/* Comment */ |
387 |
case '#': |
case '#': |
388 |
while (substr[++idx]) /*skip all*/; |
// while (substr[++idx]) continue; |
389 |
|
idx += strlen(substr + idx); // same |
390 |
/* Fall through */ |
/* Fall through */ |
391 |
/* End of command */ |
/* End of command */ |
392 |
case ';': |
case ';': |
396 |
bb_error_msg_and_die("bad option in substitution expression"); |
bb_error_msg_and_die("bad option in substitution expression"); |
397 |
} |
} |
398 |
} |
} |
399 |
out: |
out: |
400 |
/* compile the match string into a regex */ |
/* compile the match string into a regex */ |
401 |
if (*match != '\0') { |
if (*match != '\0') { |
402 |
/* If match is empty, we use last regex used at runtime */ |
/* If match is empty, we use last regex used at runtime */ |
563 |
/* last part (mandatory) will be a command */ |
/* last part (mandatory) will be a command */ |
564 |
if (!*cmdstr) |
if (!*cmdstr) |
565 |
bb_error_msg_and_die("missing command"); |
bb_error_msg_and_die("missing command"); |
566 |
sed_cmd->cmd = *(cmdstr++); |
sed_cmd->cmd = *cmdstr++; |
567 |
cmdstr = parse_cmd_args(sed_cmd, cmdstr); |
cmdstr = parse_cmd_args(sed_cmd, cmdstr); |
568 |
|
|
569 |
/* Add the command to the command array */ |
/* Add the command to the command array */ |
897 |
|
|
898 |
/* Determine if this command matches this line: */ |
/* Determine if this command matches this line: */ |
899 |
|
|
900 |
|
//bb_error_msg("match1:%d", sed_cmd->in_match); |
901 |
|
//bb_error_msg("match2:%d", (!sed_cmd->beg_line && !sed_cmd->end_line |
902 |
|
// && !sed_cmd->beg_match && !sed_cmd->end_match)); |
903 |
|
//bb_error_msg("match3:%d", (sed_cmd->beg_line > 0 |
904 |
|
// && (sed_cmd->end_line || sed_cmd->end_match |
905 |
|
// ? (sed_cmd->beg_line <= linenum) |
906 |
|
// : (sed_cmd->beg_line == linenum) |
907 |
|
// ) |
908 |
|
// ) |
909 |
|
//bb_error_msg("match4:%d", (beg_match(sed_cmd, pattern_space))); |
910 |
|
//bb_error_msg("match5:%d", (sed_cmd->beg_line == -1 && next_line == NULL)); |
911 |
|
|
912 |
/* Are we continuing a previous multi-line match? */ |
/* Are we continuing a previous multi-line match? */ |
913 |
sed_cmd->in_match = sed_cmd->in_match |
sed_cmd->in_match = sed_cmd->in_match |
914 |
/* Or is no range necessary? */ |
/* Or is no range necessary? */ |
915 |
|| (!sed_cmd->beg_line && !sed_cmd->end_line |
|| (!sed_cmd->beg_line && !sed_cmd->end_line |
916 |
&& !sed_cmd->beg_match && !sed_cmd->end_match) |
&& !sed_cmd->beg_match && !sed_cmd->end_match) |
917 |
/* Or did we match the start of a numerical range? */ |
/* Or did we match the start of a numerical range? */ |
918 |
|| (sed_cmd->beg_line > 0 && (sed_cmd->beg_line <= linenum)) |
|| (sed_cmd->beg_line > 0 |
919 |
|
&& (sed_cmd->end_line || sed_cmd->end_match |
920 |
|
/* note: even if end is numeric and is < linenum too, |
921 |
|
* GNU sed matches! We match too */ |
922 |
|
? (sed_cmd->beg_line <= linenum) /* N,end */ |
923 |
|
: (sed_cmd->beg_line == linenum) /* N */ |
924 |
|
) |
925 |
|
) |
926 |
/* Or does this line match our begin address regex? */ |
/* Or does this line match our begin address regex? */ |
927 |
|| (beg_match(sed_cmd, pattern_space)) |
|| (beg_match(sed_cmd, pattern_space)) |
928 |
/* Or did we match last line of input? */ |
/* Or did we match last line of input? */ |
996 |
case 'P': |
case 'P': |
997 |
{ |
{ |
998 |
char *tmp = strchr(pattern_space, '\n'); |
char *tmp = strchr(pattern_space, '\n'); |
|
|
|
999 |
if (tmp) { |
if (tmp) { |
1000 |
*tmp = '\0'; |
*tmp = '\0'; |
1001 |
/* TODO: explain why '\n' below */ |
/* TODO: explain why '\n' below */ |
1018 |
case 'D': |
case 'D': |
1019 |
{ |
{ |
1020 |
char *tmp = strchr(pattern_space, '\n'); |
char *tmp = strchr(pattern_space, '\n'); |
|
|
|
1021 |
if (tmp) { |
if (tmp) { |
1022 |
tmp = xstrdup(tmp+1); |
overlapping_strcpy(pattern_space, tmp + 1); |
|
free(pattern_space); |
|
|
pattern_space = tmp; |
|
1023 |
goto restart; |
goto restart; |
1024 |
} |
} |
1025 |
} |
} |
1064 |
case 'r': |
case 'r': |
1065 |
{ |
{ |
1066 |
FILE *rfile; |
FILE *rfile; |
|
|
|
1067 |
rfile = fopen_for_read(sed_cmd->string); |
rfile = fopen_for_read(sed_cmd->string); |
1068 |
if (rfile) { |
if (rfile) { |
1069 |
char *line; |
char *line; |
1112 |
int len; |
int len; |
1113 |
/* If no next line, jump to end of script and exit. */ |
/* If no next line, jump to end of script and exit. */ |
1114 |
if (next_line == NULL) { |
if (next_line == NULL) { |
|
/* Jump to end of script and exit */ |
|
1115 |
free(next_line); |
free(next_line); |
1116 |
next_line = NULL; |
next_line = NULL; |
1117 |
goto discard_line; |
goto discard_line; |
|
/* append next_line, read new next_line. */ |
|
1118 |
} |
} |
1119 |
|
/* Append next_line, read new next_line. */ |
1120 |
len = strlen(pattern_space); |
len = strlen(pattern_space); |
1121 |
pattern_space = xrealloc(pattern_space, len + strlen(next_line) + 2); |
pattern_space = xrealloc(pattern_space, len + strlen(next_line) + 2); |
1122 |
pattern_space[len] = '\n'; |
pattern_space[len] = '\n'; |
1145 |
case 'y': |
case 'y': |
1146 |
{ |
{ |
1147 |
int i, j; |
int i, j; |
|
|
|
1148 |
for (i = 0; pattern_space[i]; i++) { |
for (i = 0; pattern_space[i]; i++) { |
1149 |
for (j = 0; sed_cmd->string[j]; j += 2) { |
for (j = 0; sed_cmd->string[j]; j += 2) { |
1150 |
if (pattern_space[i] == sed_cmd->string[j]) { |
if (pattern_space[i] == sed_cmd->string[j]) { |
1333 |
if (opt & OPT_in_place) |
if (opt & OPT_in_place) |
1334 |
bb_error_msg_and_die(bb_msg_requires_arg, "-i"); |
bb_error_msg_and_die(bb_msg_requires_arg, "-i"); |
1335 |
add_input_file(stdin); |
add_input_file(stdin); |
|
process_files(); |
|
1336 |
} else { |
} else { |
1337 |
int i; |
int i; |
1338 |
FILE *file; |
FILE *file; |
1364 |
|
|
1365 |
/* Set permissions/owner of output file */ |
/* Set permissions/owner of output file */ |
1366 |
fstat(fileno(file), &statbuf); |
fstat(fileno(file), &statbuf); |
1367 |
|
/* chmod'ing AFTER chown would preserve suid/sgid bits, |
1368 |
|
* but GNU sed 4.2.1 does not preserve them either */ |
1369 |
fchmod(nonstdoutfd, statbuf.st_mode); |
fchmod(nonstdoutfd, statbuf.st_mode); |
1370 |
fchown(nonstdoutfd, statbuf.st_uid, statbuf.st_gid); |
fchown(nonstdoutfd, statbuf.st_uid, statbuf.st_gid); |
1371 |
add_input_file(file); |
add_input_file(file); |
1378 |
free(G.outname); |
free(G.outname); |
1379 |
G.outname = NULL; |
G.outname = NULL; |
1380 |
} |
} |
1381 |
if (G.input_file_count > G.current_input_file) |
/* Here, to handle "sed 'cmds' nonexistent_file" case we did: |
1382 |
process_files(); |
* if (G.current_input_file >= G.input_file_count) |
1383 |
|
* return status; |
1384 |
|
* but it's not needed since process_files() works correctly |
1385 |
|
* in this case too. */ |
1386 |
} |
} |
1387 |
|
process_files(); |
1388 |
|
|
1389 |
return status; |
return status; |
1390 |
} |
} |