aboutsummaryrefslogtreecommitdiff
path: root/toys/posix/sed.c
diff options
context:
space:
mode:
Diffstat (limited to 'toys/posix/sed.c')
-rw-r--r--toys/posix/sed.c133
1 files changed, 101 insertions, 32 deletions
diff --git a/toys/posix/sed.c b/toys/posix/sed.c
index a3ba9e38..15099cc6 100644
--- a/toys/posix/sed.c
+++ b/toys/posix/sed.c
@@ -1,21 +1,24 @@
-/* vi: set sw=4 ts=4:
+/* sed.c - Stream editor.
*
- * sed.c - Stream editor.
- *
- * Copyright 2008 Rob Landley <rob@landley.net>
+ * Copyright 2012 Rob Landley <rob@landley.net>
*
* See http://opengroup.org/onlinepubs/9699919799/utilities/sed.c
USE_SED(NEWTOY(sed, "irne*", TOYFLAG_BIN))
config SED
- bool "sed"
- default n
- help
- usage: sed [-irn] {command | [-e command]...} [FILE...]
+ bool "sed"
+ default n
+ help
+ usage: sed [-irn] {command | [-e command]...} [FILE...]
+
+ Stream EDitor, transforms text by appling script of command to each line
+ of input.
- Stream EDitor, transforms text by appling commands to each line
- of input.
+ -e Add expression to the command script (if no -e, use first argument)
+ -i Modify file in place
+ -n No default output (p commands only)
+ -r Use extended regular expression syntex
*/
#define FOR_sed
@@ -23,40 +26,106 @@ config SED
#include "lib/xregcomp.h"
GLOBALS(
- struct arg_list *commands;
+ struct arg_list *scripts;
+ struct double_list *commands;
+
+ void *parsed;
)
+// Digested version of what sed commands can actually tell use to do.
+
+
struct sed_command {
- // Doubly linked list of commands.
- struct sed_command *next, *prev;
+ // double_list compatibility (easier to create in-order)
+ struct sed_command *next, *prev;
- // Regexes for s/match/data/ and /match_begin/,/match_end/command
- regex_t *match, *match_begin, *match_end;
+ // data string for (saicytb)
+ char c, *data;
+ // Regexes for s/match/data/ and /begin/,/end/command
+ regex_t *match, *begin, *end;
+ // For numeric ranges ala 10,20command
+ long lstart, lstop;
+ // Which match to replace, 0 for all. s and w commands can write to a file
+ int which, outfd;
+};
- // For numeric ranges ala 10,20command
- int first_line, last_line;
+// Space. Space. Gotta get past space. Spaaaaaaaace! (But not newline.)
+void spaceorb(char **s)
+{
+ while (**s == ' ' || **s == '\t') *s++;
+}
- // Which match to replace, 0 for all.
- int which;
+void parse_scripts(void)
+{
+ struct sed_command *commands = 0;
+ struct arg_list *script;
+ int which = 0;
+ long l;
- // s and w commands can write to a file. Slight optimization: we use 0
- // instead of -1 to mean no file here, because even when there's no stdin
- // our input file would take fd 0.
- int outfd;
+ for (script = TT.scripts; *script; script = script->next) {
+ char *str = script->arg, *s;
+ struct sed_command *cmd;
- // Data string for (saicytb)
- char *data;
+ which++;
+ for (i=1;;) {
+ if (!*str) break;
- // Which command letter is this?
- char command;
-};
+ cmd = xzalloc(sizeof(struct sed_command));
+
+ // Identify prefix
+ for (;;) {
+ long l;
+
+ spaceorb(&str);
+ if (*str == '$') {
+ l = -1;
+ str++;
+ } else if (isdigit(*str)) l = strtol(str, &str, 10);
+ else if (!cmd->lstart) break;
+ else goto parse_fail;
+
+ spaceorb(&str);
+ if (!cmd->lstart) {
+ if (!l) goto parse_fail;
+ cmd->lstart = l;
+ if (*str != ',') break;
+ str++;
+ continue;
+ }
+ cmd->lstop = l;
+ break;
+ } else if (*str == '/') {
+ printf("regex\n");
+ }
+ l = stridx("{bcdDgGhHlnNpPstwxyrqia= \t#:}", *str);
+ if (l == -1) goto parse_fail;
+
+
+ }
+ }
+
+ return;
+
+parse_fail:
+ error_exit("bad expression %d@%d: %s", which, i, script->arg+i);
+}
void sed_main(void)
{
- struct arg_list *test;
+ char **files=toys.optargs;
+
+ // If no -e, use first argument
+ if (!TT.scripts) {
+ if (!*files) error_exit("Need script");
+ (TT.scripts=xzalloc(sizeof(struct arg_list)))->arg=*(files++);
+ }
+
- for (test = TT.commands; test; test = test->next)
- dprintf(2,"command=%s\n",test->arg);
+ {
+ struct arg_list *test;
- printf("Hello world\n");
+ for (test = TT.commands; test; test = test->next)
+ dprintf(2,"command=%s\n",test->arg);
+ while (*files) dprintf(2,"file=%s\n", *(files++));
+ }
}