Don't include version.h.
[platform/upstream/coreutils.git] / src / fold.c
index ca20a28..747f786 100644 (file)
@@ -1,5 +1,5 @@
 /* fold -- wrap each input line to fit in specified width.
-   Copyright (C) 1991 Free Software Foundation, Inc.
+   Copyright (C) 1991, 1995 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 /* Written by David MacKenzie, djm@gnu.ai.mit.edu. */
 
+#include <config.h>
+
 /* Get isblank from GNU libc.  */
 #define _GNU_SOURCE
 
 #include <stdio.h>
 #include <getopt.h>
 #include <sys/types.h>
+
+#if HAVE_LIMITS_H
+# include <limits.h>
+#endif
+
+#ifndef UINT_MAX
+# define UINT_MAX ((unsigned int) ~(unsigned int) 0)
+#endif
+
+#ifndef INT_MAX
+# define INT_MAX ((int) (UINT_MAX >> 1))
+#endif
+
 #include "system.h"
-#include "version.h"
+#include "xstrtol.h"
+#include "error.h"
 
 char *xrealloc ();
-void error ();
+char *xmalloc ();
 
 /* The name this program was run with. */
 char *program_name;
 
-static int adjust_column ();
-static int fold_file ();
-
 /* If nonzero, try to break on whitespace. */
 static int break_spaces;
 
@@ -44,90 +57,70 @@ static int count_bytes;
 /* If nonzero, at least one of the files we read was standard input. */
 static int have_read_stdin;
 
-/* If non-zero, display usage information and exit.  */
-static int flag_help;
+/* If nonzero, display usage information and exit.  */
+static int show_help;
 
-/* If non-zero, print the version on standard error.  */
-static int flag_version;
+/* If nonzero, print the version on standard output then exit.  */
+static int show_version;
 
 static struct option const longopts[] =
 {
   {"bytes", no_argument, NULL, 'b'},
   {"spaces", no_argument, NULL, 's'},
   {"width", required_argument, NULL, 'w'},
-  {"help", no_argument, &flag_help, 1},
-  {"version", no_argument, &flag_version, 1},
+  {"help", no_argument, &show_help, 1},
+  {"version", no_argument, &show_version, 1},
   {NULL, 0, NULL, 0}
 };
-\f
+
 static void
-usage ()
+usage (int status)
 {
-  fprintf (stderr, "\
-Usage: %s [-bs] [-w width] [--bytes] [--spaces] [--width=width]\n\
-       [--help] [--version] [file...]\n",
-          program_name);
-  exit (1);
+  if (status != 0)
+    fprintf (stderr, _("Try `%s --help' for more information.\n"),
+            program_name);
+  else
+    {
+      printf (_("\
+Usage: %s [OPTION]... [FILE]...\n\
+"),
+             program_name);
+      printf (_("\
+Wrap input lines in each FILE (standard input by default), writing to\n\
+standard output.\n\
+\n\
+  -b, --bytes         count bytes rather than columns\n\
+  -s, --spaces        break at spaces\n\
+  -w, --width=WIDTH   use WIDTH columns instead of 80\n\
+"));
+    }
+  exit (status);
 }
 
-void
-main (argc, argv)
-     int argc;
-     char **argv;
-{
-  int width = 80;
-  int i;
-  int optc;
-  int errs = 0;
-
-  program_name = argv[0];
-  break_spaces = count_bytes = have_read_stdin = 0;
+/* Assuming the current column is COLUMN, return the column that
+   printing C will move the cursor to.
+   The first column is 0. */
 
-  while ((optc = getopt_long (argc, argv, "bsw:", longopts, (int *) 0))
-        != EOF)
+static int
+adjust_column (int column, char c)
+{
+  if (!count_bytes)
     {
-      switch (optc)
+      if (c == '\b')
        {
-       case 0:
-         break;
-
-       case 'b':               /* Count bytes rather than columns. */
-         count_bytes = 1;
-         break;
-
-       case 's':               /* Break at word boundaries. */
-         break_spaces = 1;
-         break;
-
-       case 'w':               /* Line width. */
-         width = atoi (optarg);
-         if (width < 1)
-           error (1, 0, "%s: invalid line width", optarg);
-         break;
-
-       default:
-         usage ();
+         if (column > 0)
+           column--;
        }
+      else if (c == '\r')
+       column = 0;
+      else if (c == '\t')
+       column = column + 8 - column % 8;
+      else /* if (isprint (c)) */
+       column++;
     }
-
-  if (flag_version)
-    fprintf (stderr, "%s\n", version_string);
-
-  if (flag_help)
-    usage ();
-
-  if (argc == optind)
-    errs |= fold_file ("-", width);
   else
-    for (i = optind; i < argc; i++)
-      errs |= fold_file (argv[i], width);
-
-  if (have_read_stdin && fclose (stdin) == EOF)
-    error (1, errno, "-");
-  if (fclose (stdout) == EOF)
-    error (1, errno, "write error");
-
-  exit (errs);
+    column++;
+  return column;
 }
 
 /* Fold file FILENAME, or standard input if FILENAME is "-",
@@ -135,16 +128,14 @@ main (argc, argv)
    Return 0 if successful, 1 if an error occurs. */
 
 static int
-fold_file (filename, width)
-     char *filename;
-     int width;
+fold_file (char *filename, int width)
 {
   FILE *istream;
   register int c;
   int column = 0;              /* Screen column where next char will go. */
-  int offset_out = 0;          /* Index in `line_out' for next char. */
+  int offset_out = 0;  /* Index in `line_out' for next char. */
   static char *line_out = NULL;
-  static size_t allocated_out = 0;
+  static int allocated_out = 0;
 
   if (!strcmp (filename, "-"))
     {
@@ -167,11 +158,11 @@ fold_file (filename, width)
          allocated_out += 1024;
          line_out = xrealloc (line_out, allocated_out);
        }
-      
+
       if (c == '\n')
        {
          line_out[offset_out++] = c;
-         fwrite (line_out, sizeof (char), offset_out, stdout);
+         fwrite (line_out, sizeof (char), (size_t) offset_out, stdout);
          column = offset_out = 0;
          continue;
        }
@@ -199,20 +190,29 @@ fold_file (filename, width)
 
                  /* Found a blank.  Don't output the part after it. */
                  logical_end++;
-                 fwrite (line_out, sizeof (char), logical_end, stdout);
+                 fwrite (line_out, sizeof (char), (size_t) logical_end,
+                         stdout);
                  putchar ('\n');
                  /* Move the remainder to the beginning of the next line.
                     The areas being copied here might overlap. */
-                 bcopy (line_out + logical_end, line_out,
-                        offset_out - logical_end);
+                 memmove (line_out, line_out + logical_end,
+                          offset_out - logical_end);
                  offset_out -= logical_end;
                  for (column = i = 0; i < offset_out; i++)
                    column = adjust_column (column, line_out[i]);
                  goto rescan;
                }
            }
+         else
+           {
+             if (offset_out == 0)
+               {
+                 line_out[offset_out++] = c;
+                 continue;
+               }
+           }
          line_out[offset_out++] = '\n';
-         fwrite (line_out, sizeof (char), offset_out, stdout);
+         fwrite (line_out, sizeof (char), (size_t) offset_out, stdout);
          column = offset_out = 0;
          goto rescan;
        }
@@ -221,7 +221,7 @@ fold_file (filename, width)
     }
 
   if (offset_out)
-    fwrite (line_out, sizeof (char), offset_out, stdout);
+    fwrite (line_out, sizeof (char), (size_t) offset_out, stdout);
 
   if (ferror (istream))
     {
@@ -238,37 +238,93 @@ fold_file (filename, width)
 
   if (ferror (stdout))
     {
-      error (0, errno, "write error");
+      error (0, errno, _("write error"));
       return 1;
     }
 
   return 0;
 }
 
-/* Assuming the current column is COLUMN, return the column that
-   printing C will move the cursor to.
-   The first column is 0. */
-
-static int
-adjust_column (column, c)
-     int column;
-     char c;
+void
+main (int argc, char **argv)
 {
-  if (!count_bytes)
+  int width = 80;
+  int i;
+  int optc;
+  int errs = 0;
+
+  program_name = argv[0];
+  setlocale (LC_ALL, "");
+  bindtextdomain (PACKAGE, LOCALEDIR);
+  textdomain (PACKAGE);
+
+  break_spaces = count_bytes = have_read_stdin = 0;
+
+  /* Turn any numeric options into -w options.  */
+  for (i = 1; i < argc; i++)
     {
-      if (c == '\b')
+      if (argv[i][0] == '-' && ISDIGIT (argv[i][1]))
        {
-         if (column > 0)
-           column--;
+         char *s;
+
+         s = xmalloc (strlen (argv[i]) + 2);
+         s[0] = '-';
+         s[1] = 'w';
+         strcpy (s + 2, argv[i] + 1);
+         argv[i] = s;
        }
-      else if (c == '\r')
-       column = 0;
-      else if (c == '\t')
-       column = column + 8 - column % 8;
-      else /* if (isprint (c)) */
-       column++;
     }
+
+  while ((optc = getopt_long (argc, argv, "bsw:", longopts, (int *) 0))
+        != EOF)
+    {
+      switch (optc)
+       {
+       case 0:
+         break;
+
+       case 'b':               /* Count bytes rather than columns. */
+         count_bytes = 1;
+         break;
+
+       case 's':               /* Break at word boundaries. */
+         break_spaces = 1;
+         break;
+
+       case 'w':               /* Line width. */
+         {
+           long int tmp_long;
+           if (xstrtol (optarg, NULL, 10, &tmp_long, NULL) != LONGINT_OK
+               || tmp_long <= 0 || tmp_long > INT_MAX)
+             error (1, 0, _("invalid number of columns: `%s'"), optarg);
+           width = (int) tmp_long;
+         }
+         break;
+
+       default:
+         usage (1);
+       }
+    }
+
+  if (show_version)
+    {
+      printf ("fold - %s\n", PACKAGE_VERSION);
+      exit (0);
+    }
+
+  if (show_help)
+    usage (0);
+
+  if (argc == optind)
+    errs |= fold_file ("-", width);
   else
-    column++;
-  return column;
+    for (i = optind; i < argc; i++)
+      errs |= fold_file (argv[i], width);
+
+  if (have_read_stdin && fclose (stdin) == EOF)
+    error (1, errno, "-");
+  if (fclose (stdout) == EOF)
+    error (1, errno, _("write error"));
+
+  exit (errs);
 }