comparison toys/posix/sed.c @ 694:786841fdb1e0

Reindent to two spaces per level. Remove vi: directives that haven't worked right in years (ubuntu broke its' vim implementation). Remove trailing spaces. Add/remove blank lines. Re-wordwrap in places. Update documentation with new coding style. The actual code should be the same afterward, this is just cosmetic refactoring.
author Rob Landley <rob@landley.net>
date Tue, 13 Nov 2012 17:14:08 -0600
parents 7e846e281e38
children
comparison
equal deleted inserted replaced
693:4a5a250e0633 694:786841fdb1e0
1 /* vi: set sw=4 ts=4: 1 /* sed.c - Stream editor.
2 * 2 *
3 * sed.c - Stream editor. 3 * Copyright 2012 Rob Landley <rob@landley.net>
4 *
5 * Copyright 2008 Rob Landley <rob@landley.net>
6 * 4 *
7 * See http://opengroup.org/onlinepubs/9699919799/utilities/sed.c 5 * See http://opengroup.org/onlinepubs/9699919799/utilities/sed.c
8 6
9 USE_SED(NEWTOY(sed, "irne*", TOYFLAG_BIN)) 7 USE_SED(NEWTOY(sed, "irne*", TOYFLAG_BIN))
10 8
11 config SED 9 config SED
12 bool "sed" 10 bool "sed"
13 default n 11 default n
14 help 12 help
15 usage: sed [-irn] {command | [-e command]...} [FILE...] 13 usage: sed [-irn] {command | [-e command]...} [FILE...]
16 14
17 Stream EDitor, transforms text by appling commands to each line 15 Stream EDitor, transforms text by appling script of command to each line
18 of input. 16 of input.
17
18 -e Add expression to the command script (if no -e, use first argument)
19 -i Modify file in place
20 -n No default output (p commands only)
21 -r Use extended regular expression syntex
19 */ 22 */
20 23
21 #define FOR_sed 24 #define FOR_sed
22 #include "toys.h" 25 #include "toys.h"
23 #include "lib/xregcomp.h" 26 #include "lib/xregcomp.h"
24 27
25 GLOBALS( 28 GLOBALS(
26 struct arg_list *commands; 29 struct arg_list *scripts;
30 struct double_list *commands;
31
32 void *parsed;
27 ) 33 )
28 34
35 // Digested version of what sed commands can actually tell use to do.
36
37
29 struct sed_command { 38 struct sed_command {
30 // Doubly linked list of commands. 39 // double_list compatibility (easier to create in-order)
31 struct sed_command *next, *prev; 40 struct sed_command *next, *prev;
32 41
33 // Regexes for s/match/data/ and /match_begin/,/match_end/command 42 // data string for (saicytb)
34 regex_t *match, *match_begin, *match_end; 43 char c, *data;
44 // Regexes for s/match/data/ and /begin/,/end/command
45 regex_t *match, *begin, *end;
46 // For numeric ranges ala 10,20command
47 long lstart, lstop;
48 // Which match to replace, 0 for all. s and w commands can write to a file
49 int which, outfd;
50 };
35 51
36 // For numeric ranges ala 10,20command 52 // Space. Space. Gotta get past space. Spaaaaaaaace! (But not newline.)
37 int first_line, last_line; 53 void spaceorb(char **s)
54 {
55 while (**s == ' ' || **s == '\t') *s++;
56 }
38 57
39 // Which match to replace, 0 for all. 58 void parse_scripts(void)
40 int which; 59 {
60 struct sed_command *commands = 0;
61 struct arg_list *script;
62 int which = 0;
63 long l;
41 64
42 // s and w commands can write to a file. Slight optimization: we use 0 65 for (script = TT.scripts; *script; script = script->next) {
43 // instead of -1 to mean no file here, because even when there's no stdin 66 char *str = script->arg, *s;
44 // our input file would take fd 0. 67 struct sed_command *cmd;
45 int outfd;
46 68
47 // Data string for (saicytb) 69 which++;
48 char *data; 70 for (i=1;;) {
71 if (!*str) break;
49 72
50 // Which command letter is this? 73 cmd = xzalloc(sizeof(struct sed_command));
51 char command; 74
52 }; 75 // Identify prefix
76 for (;;) {
77 long l;
78
79 spaceorb(&str);
80 if (*str == '$') {
81 l = -1;
82 str++;
83 } else if (isdigit(*str)) l = strtol(str, &str, 10);
84 else if (!cmd->lstart) break;
85 else goto parse_fail;
86
87 spaceorb(&str);
88 if (!cmd->lstart) {
89 if (!l) goto parse_fail;
90 cmd->lstart = l;
91 if (*str != ',') break;
92 str++;
93 continue;
94 }
95 cmd->lstop = l;
96 break;
97 } else if (*str == '/') {
98 printf("regex\n");
99 }
100 l = stridx("{bcdDgGhHlnNpPstwxyrqia= \t#:}", *str);
101 if (l == -1) goto parse_fail;
102
103
104 }
105 }
106
107 return;
108
109 parse_fail:
110 error_exit("bad expression %d@%d: %s", which, i, script->arg+i);
111 }
53 112
54 void sed_main(void) 113 void sed_main(void)
55 { 114 {
56 struct arg_list *test; 115 char **files=toys.optargs;
57 116
58 for (test = TT.commands; test; test = test->next) 117 // If no -e, use first argument
59 dprintf(2,"command=%s\n",test->arg); 118 if (!TT.scripts) {
119 if (!*files) error_exit("Need script");
120 (TT.scripts=xzalloc(sizeof(struct arg_list)))->arg=*(files++);
121 }
60 122
61 printf("Hello world\n"); 123
124 {
125 struct arg_list *test;
126
127 for (test = TT.commands; test; test = test->next)
128 dprintf(2,"command=%s\n",test->arg);
129 while (*files) dprintf(2,"file=%s\n", *(files++));
130 }
62 } 131 }