Home | History | Annotate | Download | only in sed
      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
     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
    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
    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