• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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