/*
* sed.c - very minimalist version of sed
*
- * Copyright (C) 1999,2000 by Lineo, inc.
- * Written by Mark Whitley <markw@lineo.com>, <markw@enol.com>
+ * Copyright (C) 1999,2000,2001 by Lineo, inc.
+ * Written by Mark Whitley <markw@lineo.com>, <markw@codepoet.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include <string.h> /* for strdup() */
#include <errno.h>
#include <ctype.h> /* for isspace() */
+#include <stdlib.h>
#include "busybox.h"
/* externs */
+extern void xregcomp(regex_t *preg, const char *regex, int cflags);
extern int optind; /* in unistd.h */
extern char *optarg; /* ditto */
{
char *my_str = strdup(str);
int idx = 0;
+ char olddelimiter;
+ olddelimiter = sed_cmd->delimiter;
+ sed_cmd->delimiter = '/';
if (isdigit(my_str[idx])) {
do {
else if (my_str[idx] == '/') {
idx = index_of_next_unescaped_regexp_delim(sed_cmd, my_str, ++idx);
if (idx == -1)
- error_msg_and_die("unterminated match expression\n");
+ error_msg_and_die("unterminated match expression");
my_str[idx] = '\0';
*regex = (regex_t *)xmalloc(sizeof(regex_t));
xregcomp(*regex, my_str+1, 0);
}
else {
error_msg("get_address: no address found in string\n"
- "\t(you probably didn't check the string you passed me)\n");
+ "\t(you probably didn't check the string you passed me)");
idx = -1;
}
free(my_str);
+ sed_cmd->delimiter = olddelimiter;
return idx;
}
/* verify that the 's' is followed by something. That something
* (typically a 'slash') is now our regexp delimiter... */
if (!substr[++idx])
- error_msg_and_die("bad format in substitution expression\n");
+ error_msg_and_die("bad format in substitution expression");
else
sed_cmd->delimiter=substr[idx];
oldidx = idx+1;
idx = index_of_next_unescaped_regexp_delim(sed_cmd, substr, ++idx);
if (idx == -1)
- error_msg_and_die("bad format in substitution expression\n");
+ error_msg_and_die("bad format in substitution expression");
match = strdup_substr(substr, oldidx, idx);
/* determine the number of back references in the match string */
oldidx = idx+1;
idx = index_of_next_unescaped_regexp_delim(sed_cmd, substr, ++idx);
if (idx == -1)
- error_msg_and_die("bad format in substitution expression\n");
+ error_msg_and_die("bad format in substitution expression");
sed_cmd->replace = strdup_substr(substr, oldidx, idx);
/* process the flags */
if (strchr("; \t\v\n\r", substr[idx]))
goto out;
/* else */
- error_msg_and_die("bad option in substitution expression\n");
+ error_msg_and_die("bad option in substitution expression");
}
}
*/
if (editstr[1] != '\\' && (editstr[2] != '\n' || editstr[2] != '\r'))
- error_msg_and_die("bad format in edit expression\n");
+ error_msg_and_die("bad format in edit expression");
/* store the edit line text */
/* make editline big enough to accomodate the extra '\n' we will tack on
/* now we need to go through * and: s/\\[\r\n]$/\n/g on the edit line */
while (ptr[idx]) {
- while (ptr[idx] != '\\' && (ptr[idx+1] != '\n' || ptr[idx+1] != '\r')) {
+ while (ptr[idx] != '\\' || (ptr[idx+1] != '\n' && ptr[idx+1] != '\r')) {
idx++;
if (!ptr[idx]) {
goto out;
}
out:
- ptr[idx] = '\n';
- ptr[idx+1] = 0;
-
/* this accounts for discrepancies between the modified string and the
* original string passed in to this function */
idx += slashes_eaten;
- /* this accounts for the fact that A) we started at index 3, not at index
- * 0 and B) that we added an extra '\n' at the end (if you think the next
- * line should read 'idx += 4' remember, arrays are zero-based) */
+ /* figure out if we need to add a newline */
+ if (ptr[idx-1] != '\n') {
+ ptr[idx] = '\n';
+ idx++;
+ }
- idx += 3;
+ /* terminate string */
+ ptr[idx]= 0;
+ /* adjust for opening 2 chars [aic]\ */
+ idx += 2;
return idx;
}
/* last part (mandatory) will be a command */
if (cmdstr[idx] == '\0')
- error_msg_and_die("missing command\n");
+ error_msg_and_die("missing command");
if (!strchr("pdsaic", cmdstr[idx])) /* <-- XXX add new commands here */
- error_msg_and_die("invalid command\n");
+ error_msg_and_die("invalid command");
sed_cmd->cmd = cmdstr[idx];
/* special-case handling for (s)ubstitution */
/* special-case handling for (a)ppend, (i)nsert, and (c)hange */
else if (strchr("aic", cmdstr[idx])) {
if (sed_cmd->end_line || sed_cmd->end_match)
- error_msg_and_die("only a beginning address can be specified for edit commands\n");
+ error_msg_and_die("only a beginning address can be specified for edit commands");
idx += parse_edit_cmd(sed_cmd, &cmdstr[idx]);
}
/* if it was a single-letter command (such as 'p' or 'd') we need to
}
/* eat trailing newline (if any) --if I don't do this, edit commands
* (aic) will print an extra newline */
- if (line[strlen(line)-1] == '\n')
- line[strlen(line)-1] = 0;
+ chomp(line);
add_cmd_str(line);
free(line);
}
if (sed_cmds[i].beg_match && sed_cmds[i].end_match) {
if (still_in_range || regexec(sed_cmds[i].beg_match, line, 0, NULL, 0) == 0) {
line_altered += do_sed_command(&sed_cmds[i], line);
- still_in_range = 1;
- if (regexec(sed_cmds[i].end_match, line, 0, NULL, 0) == 0)
+ if (still_in_range && regexec(sed_cmds[i].end_match, line, 0, NULL, 0) == 0)
still_in_range = 0;
+ else
+ still_in_range = 1;
}
}
#endif
/* do normal option parsing */
- while ((opt = getopt(argc, argv, "hne:f:")) > 0) {
+ while ((opt = getopt(argc, argv, "ne:f:")) > 0) {
switch (opt) {
- case 'h':
- usage(sed_usage);
- break;
case 'n':
be_quiet++;
break;
case 'f':
load_cmd_file(optarg);
break;
+ default:
+ show_usage();
}
}
* argv[optind] should be the pattern. no pattern, no worky */
if (ncmds == 0) {
if (argv[optind] == NULL)
- usage(sed_usage);
+ show_usage();
else {
add_cmd_str(argv[optind]);
optind++;