aboutsummaryrefslogtreecommitdiff
path: root/sed.c
diff options
context:
space:
mode:
Diffstat (limited to 'sed.c')
-rw-r--r--sed.c338
1 files changed, 254 insertions, 84 deletions
diff --git a/sed.c b/sed.c
index 4dfc0246c..8e5f695c4 100644
--- a/sed.c
+++ b/sed.c
@@ -5,6 +5,11 @@
5 * Copyright (C) 1999 by Lineo, inc. 5 * Copyright (C) 1999 by Lineo, inc.
6 * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> 6 * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
7 * 7 *
8 * Modifications for addresses and append command have been
9 * written by Marco Pantaleoni <panta@prosa.it>, <panta@elasticworld.org>
10 * and are:
11 * Copyright (C) 1999 Marco Pantaleoni.
12 *
8 * This program is free software; you can redistribute it and/or modify 13 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 14 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or 15 * the Free Software Foundation; either version 2 of the License, or
@@ -31,48 +36,144 @@
31#include <time.h> 36#include <time.h>
32#include <ctype.h> 37#include <ctype.h>
33 38
34static const char sed_usage[] = 39static const char sed_usage[] =
35"sed [-n] [-e script] [file...]\n\n" 40 "sed [-n] -e script [file...]\n\n"
36"Allowed sed scripts come in the following form:\n" 41 "Allowed sed scripts come in the following form:\n"
37"\t's/regexp/replacement/[gp]'\n" 42 "\t'ADDR [!] COMMAND'\n\n"
38"which attempt to match regexp against the pattern space\n" 43 "\twhere address ADDR can be:\n"
39"and if successful replaces the matched portion with replacement.\n\n" 44 "\t NUMBER Match specified line number\n"
40"Options:\n" 45 "\t $ Match last line\n"
41"-e\tadd the script to the commands to be executed\n" 46 "\t /REGEXP/ Match specified regexp\n"
42"-n\tsuppress automatic printing of pattern space\n\n" 47 "\t (! inverts the meaning of the match)\n\n"
48 "\tand COMMAND can be:\n"
49 "\t s/regexp/replacement/[gp]\n"
50 "\t which attempt to match regexp against the pattern space\n"
51 "\t and if successful replaces the matched portion with replacement.\n\n"
52 "\t aTEXT\n"
53 "\t which appends TEXT after the pattern space\n"
54 "Options:\n"
55 "-e\tadd the script to the commands to be executed\n"
56 "-n\tsuppress automatic printing of pattern space\n\n"
43#if defined BB_REGEXP 57#if defined BB_REGEXP
44"This version of sed matches full regular expresions.\n"; 58 "This version of sed matches full regular expresions.\n";
45#else 59#else
46"This version of sed matches strings (not full regular expresions).\n"; 60 "This version of sed matches strings (not full regular expresions).\n";
47#endif 61#endif
48
49 62
50static void do_sed(FILE *fp, char *needle, char *newNeedle, int ignoreCase, int printFlag, int quietFlag) 63/* Flags & variables */
64
65typedef enum { f_none, f_replace, f_append } sed_function;
66
67#define NO_LINE -2
68#define LAST_LINE -1
69static int addr_line = NO_LINE;
70static char *addr_pattern = NULL;
71static int negated = 0;
72
73#define SKIPSPACES(p) do { while (isspace(*(p))) (p)++; } while (0)
74
75#define BUFSIZE 1024
76
77static inline int at_last(FILE * fp)
51{ 78{
52 int foundOne=FALSE; 79 int res = 0;
53 char haystack[1024];
54 80
55 while (fgets (haystack, 1023, fp)) { 81 if (feof(fp))
56 foundOne = replace_match(haystack, needle, newNeedle, ignoreCase); 82 return 1;
57 if (foundOne==TRUE && printFlag==TRUE) { 83 else {
58 fprintf(stdout, haystack); 84 char ch;
85 if ((ch = fgetc(fp)) == EOF)
86 res++;
87 ungetc(ch, fp);
88 }
89 return res;
90}
91
92static void do_sed_repl(FILE * fp, char *needle, char *newNeedle,
93 int ignoreCase, int printFlag, int quietFlag)
94{
95 int foundOne = FALSE;
96 char haystack[BUFSIZE];
97 int line = 1, doit;
98
99 while (fgets(haystack, BUFSIZE - 1, fp)) {
100 doit = 0;
101 if (addr_pattern) {
102 doit = !find_match(haystack, addr_pattern, FALSE);
103 } else if (addr_line == NO_LINE)
104 doit = 1;
105 else if (addr_line == LAST_LINE) {
106 if (at_last(fp))
107 doit = 1;
108 } else {
109 if (line == addr_line)
110 doit = 1;
111 }
112 if (negated)
113 doit = 1 - doit;
114 if (doit) {
115 foundOne =
116 replace_match(haystack, needle, newNeedle, ignoreCase);
117
118 if (foundOne == TRUE && printFlag == TRUE) {
119 fprintf(stdout, haystack);
120 }
59 } 121 }
60 if (quietFlag==FALSE) { 122
123 if (quietFlag == FALSE) {
61 fprintf(stdout, haystack); 124 fprintf(stdout, haystack);
62 } 125 }
126
127 line++;
128 }
129}
130
131static void do_sed_append(FILE * fp, char *appendline, int quietFlag)
132{
133 char buffer[BUFSIZE];
134 int line = 1, doit;
135
136 while (fgets(buffer, BUFSIZE - 1, fp)) {
137 doit = 0;
138 if (addr_pattern) {
139 doit = !find_match(buffer, addr_pattern, FALSE);
140 } else if (addr_line == NO_LINE)
141 doit = 1;
142 else if (addr_line == LAST_LINE) {
143 if (at_last(fp))
144 doit = 1;
145 } else {
146 if (line == addr_line)
147 doit = 1;
148 }
149 if (negated)
150 doit = 1 - doit;
151 if (quietFlag == FALSE) {
152 fprintf(stdout, buffer);
153 }
154 if (doit) {
155 fputs(appendline, stdout);
156 fputc('\n', stdout);
157 }
158
159 line++;
63 } 160 }
64} 161}
65 162
66extern int sed_main (int argc, char **argv) 163extern int sed_main(int argc, char **argv)
67{ 164{
68 FILE *fp; 165 FILE *fp;
69 char *needle=NULL, *newNeedle=NULL; 166 char *needle = NULL, *newNeedle = NULL;
70 char *name; 167 char *name;
71 char *cp; 168 char *cp;
72 int ignoreCase=FALSE; 169 int ignoreCase = FALSE;
73 int printFlag=FALSE; 170 int printFlag = FALSE;
74 int quietFlag=FALSE; 171 int quietFlag = FALSE;
75 int stopNow; 172 int stopNow;
173 char *line_s = NULL, saved;
174 char *appendline = NULL;
175 char *pos;
176 sed_function sed_f = f_none;
76 177
77 argc--; 178 argc--;
78 argv++; 179 argv++;
@@ -83,68 +184,119 @@ extern int sed_main (int argc, char **argv)
83 if (**argv == '-') { 184 if (**argv == '-') {
84 argc--; 185 argc--;
85 cp = *argv++; 186 cp = *argv++;
86 stopNow=FALSE; 187 stopNow = FALSE;
87 188
88 while (*++cp && stopNow==FALSE) { 189 while (*++cp && stopNow == FALSE) {
89 switch (*cp) { 190 switch (*cp) {
90 case 'n': 191 case 'n':
91 quietFlag = TRUE; 192 quietFlag = TRUE;
92 break; 193 break;
93 case 'e': 194 case 'e':
94 if (*(cp+1)==0 && --argc < 0) { 195 if (*(cp + 1) == 0 && --argc < 0) {
95 usage( sed_usage); 196 usage(sed_usage);
96 } 197 }
97 if ( *++cp != 's') 198 if (*++cp != 's')
98 cp = *argv++; 199 cp = *argv++;
99 while( *cp ) { 200
100 if (*cp == 's' && strlen(cp) > 3 && *(cp+1) == '/') { 201 /* Read address if present */
101 char* pos=needle=cp+2; 202 SKIPSPACES(cp);
102 for(;;) { 203 if (*cp == '$') {
103 pos = strchr(pos, '/'); 204 addr_line = LAST_LINE;
104 if (pos==NULL) { 205 cp++;
105 usage( sed_usage); 206 } else {
106 } 207 if (isdigit(*cp)) { /* LINE ADDRESS */
107 if (*(pos-1) == '\\') { 208 line_s = cp;
108 pos++; 209 while (isdigit(*cp))
109 continue; 210 cp++;
110 } 211 if (cp > line_s) {
111 break; 212 /* numeric line */
213 saved = *cp;
214 *cp = '\0';
215 addr_line = atoi(line_s);
216 *cp = saved;
112 } 217 }
113 *pos=0; 218 } else if (*cp == '/') { /* PATTERN ADDRESS */
114 newNeedle=++pos; 219 pos = addr_pattern = cp + 1;
115 for(;;) { 220 pos = strchr(pos, '/');
116 pos = strchr(pos, '/'); 221 if (!pos)
117 if (pos==NULL) { 222 usage(sed_usage);
118 usage( sed_usage); 223 *pos = '\0';
119 } 224 cp = pos + 1;
120 if (*(pos-1) == '\\') { 225 }
121 pos++; 226 }
122 continue; 227
123 } 228 SKIPSPACES(cp);
124 break; 229 if (*cp == '!') {
230 negated++;
231 cp++;
232 }
233
234 /* Read command */
235
236 SKIPSPACES(cp);
237 switch (*cp) {
238 case 's': /* REPLACE */
239 if (strlen(cp) <= 3 || *(cp + 1) != '/')
240 break;
241 sed_f = f_replace;
242
243 pos = needle = cp + 2;
244
245 for (;;) {
246 pos = strchr(pos, '/');
247 if (pos == NULL) {
248 usage(sed_usage);
249 }
250 if (*(pos - 1) == '\\') {
251 pos++;
252 continue;
125 } 253 }
126 *pos=0; 254 break;
127 if (pos+2 != 0) { 255 }
128 while (*++pos) { 256 *pos = 0;
129 switch (*pos) { 257 newNeedle = ++pos;
130 case 'i': 258 for (;;) {
131 ignoreCase=TRUE; 259 pos = strchr(pos, '/');
132 break; 260 if (pos == NULL) {
133 case 'p': 261 usage(sed_usage);
134 printFlag=TRUE; 262 }
135 break; 263 if (*(pos - 1) == '\\') {
136 case 'g': 264 pos++;
137 break; 265 continue;
138 default: 266 }
139 usage( sed_usage); 267 break;
140 } 268 }
269 *pos = 0;
270 if (pos + 2 != 0) {
271 while (*++pos) {
272 switch (*pos) {
273 case 'i':
274 ignoreCase = TRUE;
275 break;
276 case 'p':
277 printFlag = TRUE;
278 break;
279 case 'g':
280 break;
281 default:
282 usage(sed_usage);
141 } 283 }
142 } 284 }
143 } 285 }
144 cp++; 286 cp = pos;
287 /* fprintf(stderr, "replace '%s' with '%s'\n", needle, newNeedle); */
288 break;
289
290 case 'a': /* APPEND */
291 if (strlen(cp) < 2)
292 break;
293 sed_f = f_append;
294 appendline = ++cp;
295 /* fprintf(stderr, "append '%s'\n", appendline); */
296 break;
145 } 297 }
146 //fprintf(stderr, "replace '%s' with '%s'\n", needle, newNeedle); 298
147 stopNow=TRUE; 299 stopNow = TRUE;
148 break; 300 break;
149 301
150 default: 302 default:
@@ -153,30 +305,48 @@ extern int sed_main (int argc, char **argv)
153 } 305 }
154 } 306 }
155 307
156 if (argc==0) { 308 if (argc == 0) {
157 do_sed( stdin, needle, newNeedle, ignoreCase, printFlag, quietFlag); 309 switch (sed_f) {
310 case f_none:
311 break;
312 case f_replace:
313 do_sed_repl(stdin, needle, newNeedle, ignoreCase, printFlag,
314 quietFlag);
315 break;
316 case f_append:
317 do_sed_append(stdin, appendline, quietFlag);
318 break;
319 }
158 } else { 320 } else {
159 while (argc-- > 0) { 321 while (argc-- > 0) {
160 name = *argv++; 322 name = *argv++;
161 323
162 fp = fopen (name, "r"); 324 fp = fopen(name, "r");
163 if (fp == NULL) { 325 if (fp == NULL) {
164 perror (name); 326 perror(name);
165 continue; 327 continue;
166 } 328 }
167 329
168 do_sed( fp, needle, newNeedle, ignoreCase, printFlag, quietFlag); 330 switch (sed_f) {
331 case f_none:
332 break;
333 case f_replace:
334 do_sed_repl(fp, needle, newNeedle, ignoreCase, printFlag,
335 quietFlag);
336 break;
337 case f_append:
338 do_sed_append(fp, appendline, quietFlag);
339 break;
340 }
169 341
170 if (ferror (fp)) 342 if (ferror(fp))
171 perror (name); 343 perror(name);
172 344
173 fclose (fp); 345 fclose(fp);
174 } 346 }
175 } 347 }
176 exit( TRUE); 348 exit(TRUE);
177} 349}
178 350
179 351
180/* END CODE */ 352/* END CODE */
181
182