1 /* GNU SED, a batch stream editor.
2 Copyright (C) 1989,90,91,92,93,94,95,98,99,2002,2003,2006,2008,2009
3 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19
20 #include "sed.h"
21
22
23 #include <stdio.h>
24 #ifdef HAVE_STRINGS_H
25 # include <strings.h>
26 #else
27 # include <string.h>
28 #endif /*HAVE_STRINGS_H*/
29 #ifdef HAVE_MEMORY_H
30 # include <memory.h>
31 #endif
32
33 #ifndef HAVE_STRCHR
34 # define strchr index
35 # define strrchr rindex
36 #endif
37
38 #ifdef HAVE_STDLIB_H
39 # include <stdlib.h>
40 #endif
41
42 #ifdef HAVE_SYS_TYPES_H
43 # include <sys/types.h>
44 #endif
45 #include "getopt.h"
46
47 #ifndef BOOTSTRAP
48 #ifndef HAVE_STDLIB_H
49 extern char *getenv P_((const char *));
50 #endif
51 #endif
52
53 #ifndef HAVE_STRTOUL
54 # define ATOI(x) atoi(x)
55 #else
56 # define ATOI(x) strtoul(x, NULL, 0)
57 #endif
58
59 char *program_name;
60
61 int extended_regexp_flags = 0;
62
63 /* If set, fflush(stdout) on every line output. */
64 bool unbuffered_output = false;
65
66 /* If set, don't write out the line unless explicitly told to */
67 bool no_default_output = false;
68
69 /* If set, reset line counts on every new file. */
70 bool separate_files = false;
71
72 /* If set, follow symlinks when processing in place */
73 bool follow_symlinks = false;
74
75 /* How do we edit files in-place? (we don't if NULL) */
76 char *in_place_extension = NULL;
77
78 /* The mode to use to read files, either "rt" or "rb". */
79 char *read_mode = "rt";
80
81 /* Do we need to be pedantically POSIX compliant? */
82 enum posixicity_types posixicity;
83
84 /* How long should the `l' command's output line be? */
85 countT lcmd_out_line_len = 70;
86
87 /* The complete compiled SED program that we are going to run: */
88 static struct vector *the_program = NULL;
89
90 static void usage P_((int));
91 static void
contact(errmsg)92 contact(errmsg)
93 int errmsg;
94 {
95 FILE *out = errmsg ? stderr : stdout;
96 #ifndef REG_PERL
97 fprintf(out, _("GNU sed home page: <http://www.gnu.org/software/sed/>.\n\
98 General help using GNU software: <http://www.gnu.org/gethelp/>.\n"));
99 #endif
100
101 /* Only print the bug report address for `sed --help', otherwise we'll
102 get reports for other people's bugs. */
103 if (!errmsg)
104 fprintf(out, _("E-mail bug reports to: <%s>.\n\
105 Be sure to include the word ``%s'' somewhere in the ``Subject:'' field.\n"),
106 PACKAGE_BUGREPORT, PACKAGE);
107 }
108
109 static void usage P_((int));
110 static void
usage(status)111 usage(status)
112 int status;
113 {
114 FILE *out = status ? stderr : stdout;
115
116 #ifdef REG_PERL
117 #define PERL_HELP _(" -R, --regexp-perl\n use Perl 5's regular expressions syntax in the script.\n")
118 #else
119 #define PERL_HELP ""
120 #endif
121
122 fprintf(out, _("\
123 Usage: %s [OPTION]... {script-only-if-no-other-script} [input-file]...\n\
124 \n"), myname);
125
126 fprintf(out, _(" -n, --quiet, --silent\n\
127 suppress automatic printing of pattern space\n"));
128 fprintf(out, _(" -e script, --expression=script\n\
129 add the script to the commands to be executed\n"));
130 fprintf(out, _(" -f script-file, --file=script-file\n\
131 add the contents of script-file to the commands to be executed\n"));
132 #ifdef ENABLE_FOLLOW_SYMLINKS
133 fprintf(out, _(" --follow-symlinks\n\
134 follow symlinks when processing in place\n"));
135 #endif
136 fprintf(out, _(" -i[SUFFIX], --in-place[=SUFFIX]\n\
137 edit files in place (makes backup if extension supplied)\n"));
138 #if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) || defined(MSDOS) || defined(__EMX__)
139 fprintf(out, _(" -b, --binary\n\
140 open files in binary mode (CR+LFs are not processed specially)\n"));
141 #endif
142 fprintf(out, _(" -l N, --line-length=N\n\
143 specify the desired line-wrap length for the `l' command\n"));
144 fprintf(out, _(" --posix\n\
145 disable all GNU extensions.\n"));
146 fprintf(out, _(" -r, --regexp-extended\n\
147 use extended regular expressions in the script.\n"));
148 #ifdef REG_PERL
149 fprintf(out, PERL_HELP);
150 #endif
151 fprintf(out, _(" -s, --separate\n\
152 consider files as separate rather than as a single continuous\n\
153 long stream.\n"));
154 fprintf(out, _(" -u, --unbuffered\n\
155 load minimal amounts of data from the input files and flush\n\
156 the output buffers more often\n"));
157 fprintf(out, _(" --help display this help and exit\n"));
158 fprintf(out, _(" --version output version information and exit\n"));
159 fprintf(out, _("\n\
160 If no -e, --expression, -f, or --file option is given, then the first\n\
161 non-option argument is taken as the sed script to interpret. All\n\
162 remaining arguments are names of input files; if no input files are\n\
163 specified, then the standard input is read.\n\
164 \n"));
165 contact (status);
166
167 ck_fclose (NULL);
168 exit (status);
169 }
170
171 int
main(argc,argv)172 main(argc, argv)
173 int argc;
174 char **argv;
175 {
176 #ifdef REG_PERL
177 #define SHORTOPTS "bsnrRuEe:f:l:i::V:"
178 #else
179 #define SHORTOPTS "bsnruEe:f:l:i::V:"
180 #endif
181
182 static struct option longopts[] = {
183 {"binary", 0, NULL, 'b'},
184 {"regexp-extended", 0, NULL, 'r'},
185 #ifdef REG_PERL
186 {"regexp-perl", 0, NULL, 'R'},
187 #endif
188 {"expression", 1, NULL, 'e'},
189 {"file", 1, NULL, 'f'},
190 {"in-place", 2, NULL, 'i'},
191 {"line-length", 1, NULL, 'l'},
192 {"quiet", 0, NULL, 'n'},
193 {"posix", 0, NULL, 'p'},
194 {"silent", 0, NULL, 'n'},
195 {"separate", 0, NULL, 's'},
196 {"unbuffered", 0, NULL, 'u'},
197 {"version", 0, NULL, 'v'},
198 {"help", 0, NULL, 'h'},
199 #ifdef ENABLE_FOLLOW_SYMLINKS
200 {"follow-symlinks", 0, NULL, 'F'},
201 #endif
202 {NULL, 0, NULL, 0}
203 };
204
205 int opt;
206 int return_code;
207 const char *cols = getenv("COLS");
208
209 program_name = argv[0];
210 initialize_main (&argc, &argv);
211 #if HAVE_SETLOCALE
212 /* Set locale according to user's wishes. */
213 setlocale (LC_ALL, "");
214 #endif
215 initialize_mbcs ();
216
217 #if ENABLE_NLS
218
219 /* Tell program which translations to use and where to find. */
220 bindtextdomain (PACKAGE, LOCALEDIR);
221 textdomain (PACKAGE);
222 #endif
223
224 if (getenv("POSIXLY_CORRECT") != NULL)
225 posixicity = POSIXLY_CORRECT;
226 else
227 posixicity = POSIXLY_EXTENDED;
228
229 /* If environment variable `COLS' is set, use its value for
230 the baseline setting of `lcmd_out_line_len'. The "-1"
231 is to avoid gratuitous auto-line-wrap on ttys.
232 */
233 if (cols)
234 {
235 countT t = ATOI(cols);
236 if (t > 1)
237 lcmd_out_line_len = t-1;
238 }
239
240 myname = *argv;
241 while ((opt = getopt_long(argc, argv, SHORTOPTS, longopts, NULL)) != EOF)
242 {
243 switch (opt)
244 {
245 case 'n':
246 no_default_output = true;
247 break;
248 case 'e':
249 the_program = compile_string(the_program, optarg, strlen(optarg));
250 break;
251 case 'f':
252 the_program = compile_file(the_program, optarg);
253 break;
254
255 case 'F':
256 follow_symlinks = true;
257 break;
258
259 case 'i':
260 separate_files = true;
261 if (optarg == NULL)
262 /* use no backups */
263 in_place_extension = ck_strdup ("*");
264
265 else if (strchr(optarg, '*') != NULL)
266 in_place_extension = ck_strdup(optarg);
267
268 else
269 {
270 in_place_extension = MALLOC (strlen(optarg) + 2, char);
271 in_place_extension[0] = '*';
272 strcpy (in_place_extension + 1, optarg);
273 }
274
275 break;
276
277 case 'l':
278 lcmd_out_line_len = ATOI(optarg);
279 break;
280
281 case 'p':
282 posixicity = POSIXLY_BASIC;
283 break;
284
285 case 'b':
286 read_mode = "rb";
287 break;
288
289 /* Undocumented, for compatibility with BSD sed. */
290 case 'E':
291 case 'r':
292 if (extended_regexp_flags)
293 usage(4);
294 extended_regexp_flags = REG_EXTENDED;
295 break;
296
297 #ifdef REG_PERL
298 case 'R':
299 if (extended_regexp_flags)
300 usage(4);
301 extended_regexp_flags = REG_PERL;
302 break;
303 #endif
304
305 case 's':
306 separate_files = true;
307 break;
308
309 case 'u':
310 unbuffered_output = true;
311 break;
312
313 case 'v':
314 #ifdef REG_PERL
315 fprintf(stdout, _("super-sed version %s\n"), VERSION);
316 fprintf(stdout, _("based on GNU sed version %s\n\n"), SED_FEATURE_VERSION);
317 #else
318 fprintf(stdout, _("GNU sed version %s\n"), VERSION);
319 #endif
320 fprintf(stdout, _("Copyright (C) %d Free Software Foundation, Inc.\n\
321 This is free software; see the source for copying conditions. There is NO\n\
322 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n\
323 to the extent permitted by law.\n\
324 "), COPYRIGHT_YEAR);
325 fputc('\n', stdout);
326 contact(false);
327
328 ck_fclose (NULL);
329 exit (0);
330 case 'h':
331 usage(0);
332 default:
333 usage(4);
334 }
335 }
336
337 if (!the_program)
338 {
339 if (optind < argc)
340 {
341 char *arg = argv[optind++];
342 the_program = compile_string(the_program, arg, strlen(arg));
343 }
344 else
345 usage(4);
346 }
347 check_final_program(the_program);
348
349 return_code = process_files(the_program, argv+optind);
350
351 finish_program(the_program);
352 ck_fclose(NULL);
353
354 return return_code;
355 }
356