summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchristos <christos@NetBSD.org>2007-05-29 15:27:37 +0000
committerchristos <christos@NetBSD.org>2007-05-29 15:27:37 +0000
commit3d9ab41d78bc8e44b7aa10cfd581e95023955463 (patch)
tree24ba055dff92cb44efba4d55c4a4d2c5bc2e5979
parent64e3562f4fd2b9482ae6177f707e8c9c6cfd4df8 (diff)
- getopt parsing
- add raw mode [-r] - add -g and -m to get the goal and max respectively. - document that lines that start with a period or look like mail headers don't get formatted.
-rw-r--r--usr.bin/fmt/fmt.126
-rw-r--r--usr.bin/fmt/fmt.c115
2 files changed, 107 insertions, 34 deletions
diff --git a/usr.bin/fmt/fmt.1 b/usr.bin/fmt/fmt.1
index 4aca9a85a49..749f96d405b 100644
--- a/usr.bin/fmt/fmt.1
+++ b/usr.bin/fmt/fmt.1
@@ -1,4 +1,4 @@
-.\" $NetBSD: fmt.1,v 1.9 2005/09/11 23:15:20 wiz Exp $
+.\" $NetBSD: fmt.1,v 1.10 2007/05/29 15:27:37 christos Exp $
.\"
.\" Copyright (c) 1980, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -29,7 +29,7 @@
.\"
.\" @(#)fmt.1 8.1 (Berkeley) 6/6/93
.\"
-.Dd June 6, 1993
+.Dd May 29, 2007
.Dt FMT 1
.Os
.Sh NAME
@@ -37,12 +37,17 @@
.Nd simple text formatter
.Sh SYNOPSIS
.Nm
-.Op Fl C
+.Op Fl Cr
.Oo
.Ar goal
.Op Ar maximum
.Oc
.Op name ...
+.Nm
+.Op Fl Cr
+.Op Fl g Ar goal
+.Op Fl m Ar maximum
+.Op name ...
.Sh DESCRIPTION
.Nm
is a simple text formatter which reads the concatenation of input
@@ -58,11 +63,22 @@ length defaults to 65 and the
to 75.
The spacing at the beginning of the input lines is preserved in
the output, as are blank lines and interword spacing.
+In non raw mode, lines that look like mail headers or begin with
+a period are not formatted.
.Pp
-.Fl C
+.Bl -tag -indent
+.It Fl C
instructs
-.Nm fmt
+.Nm
to center the text.
+.It Fl g Ar goal
+New way to set the goal length.
+.It Fl m Ar maximum
+New way to set the maximum length.
+.It Fl r
+Raw mode; formats all lines and does not make exceptions for lines
+that start with a period or look like mail headers.
+.El
.Pp
.Nm
is meant to format mail messages prior to sending, but may also be useful
diff --git a/usr.bin/fmt/fmt.c b/usr.bin/fmt/fmt.c
index ab99dfb9285..cd92897ad70 100644
--- a/usr.bin/fmt/fmt.c
+++ b/usr.bin/fmt/fmt.c
@@ -1,4 +1,4 @@
-/* $NetBSD: fmt.c,v 1.25 2006/01/15 14:41:45 christos Exp $ */
+/* $NetBSD: fmt.c,v 1.26 2007/05/29 15:27:37 christos Exp $ */
/*
* Copyright (c) 1980, 1993
@@ -39,13 +39,17 @@ __COPYRIGHT("@(#) Copyright (c) 1980, 1993\n\
#if 0
static char sccsid[] = "@(#)fmt.c 8.1 (Berkeley) 7/20/93";
#endif
-__RCSID("$NetBSD: fmt.c,v 1.25 2006/01/15 14:41:45 christos Exp $");
+__RCSID("$NetBSD: fmt.c,v 1.26 2007/05/29 15:27:37 christos Exp $");
#endif /* not lint */
#include <ctype.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <err.h>
+#include <limits.h>
#include <string.h>
#include "buffer.h"
@@ -64,6 +68,7 @@ __RCSID("$NetBSD: fmt.c,v 1.25 2006/01/15 14:41:45 christos Exp $");
static size_t goal_length; /* Target or goal line length in output */
static size_t max_length; /* Max line length in output */
static size_t pfx; /* Current leading blank count */
+static int raw; /* Don't treat mail specially */
static int lineno; /* Current input line */
static int mark; /* Last place we saw a head line */
static int center;
@@ -71,6 +76,8 @@ static struct buffer outbuf;
static const char *headnames[] = {"To", "Subject", "Cc", 0};
+static void usage(void) __attribute__((__noreturn__));
+static int getnum(const char *, const char *, size_t *, int);
static void fmt(FILE *);
static int ispref(const char *, const char *);
static void leadin(void);
@@ -94,7 +101,8 @@ main(int argc, char **argv)
{
FILE *fi;
int errs = 0;
- int number; /* LIZ@UOM 6/18/85 */
+ int compat = 1;
+ int c;
goal_length = GOAL_LENGTH;
max_length = MAX_LENGTH;
@@ -105,35 +113,52 @@ main(int argc, char **argv)
setprogname(*argv);
(void)setlocale(LC_ALL, "");
+ while ((c = getopt(argc, argv, "Cg:m:r")) != -1)
+ switch (c) {
+ case 'C':
+ center++;
+ break;
+ case 'g':
+ (void)getnum(optarg, "goal", &goal_length, 1);
+ compat = 0;
+ break;
+ case 'm':
+ (void)getnum(optarg, "max", &max_length, 1);
+ compat = 0;
+ break;
+ case 'r':
+ raw++;
+ break;
+ default:
+ usage();
+ }
+
+ argc -= optind;
+ argv += optind;
+
/*
- * LIZ@UOM 6/18/85 -- Check for goal and max length arguments
+ * compatibility with old usage.
*/
- if (argc > 1 && !strcmp(argv[1], "-C")) {
- center++;
- argc--;
- argv++;
- }
- if (argc > 1 && (1 == (sscanf(argv[1], "%d", &number)))) {
+ if (compat && getnum(*argv, "goal", &goal_length, 0)) {
argv++;
argc--;
- goal_length = abs(number);
- if (argc > 1 && (1 == (sscanf(argv[1], "%d", &number)))) {
+ if (getnum(*argv, "max", &max_length, 0)) {
argv++;
argc--;
- max_length = abs(number);
}
}
+
if (max_length <= goal_length) {
errx(1, "Max length (%zu) must be greater than goal "
"length (%zu)", max_length, goal_length);
}
- if (argc < 2) {
+ if (argc == 0) {
fmt(stdin);
oflush();
return 0;
}
- while (--argc) {
- if ((fi = fopen(*++argv, "r")) == NULL) {
+ while (argc--) {
+ if ((fi = fopen(*argv++, "r")) == NULL) {
warn("Cannot open `%s'", *argv);
errs++;
continue;
@@ -146,6 +171,35 @@ main(int argc, char **argv)
return errs;
}
+static void
+usage(void)
+{
+ (void)fprintf(stderr,
+ "Usage: %s [-Cr] [-g <goal>] [-m <max>] [<files>..]\n"
+ "\t %s [-Cr] [<goal>] [<max>] [<files>]\n",
+ getprogname(), getprogname());
+ exit(1);
+}
+
+static int
+getnum(const char *str, const char *what, size_t *res, int badnum)
+{
+ unsigned long ul;
+ char *ep;
+
+ errno = 0;
+ ul = strtoul(str, &ep, 0);
+ if (*str != '\0' && *ep == '\0') {
+ if ((errno == ERANGE && ul == ULONG_MAX) || ul > SIZE_T_MAX)
+ errx(1, "%s number `%s' too big", what, str);
+ *res = (size_t)ul;
+ return 1;
+ } else if (badnum)
+ errx(1, "Bad %s number `%s'", what, str);
+
+ return 0;
+}
+
/*
* Read up characters from the passed input file, forming lines,
* doing ^H processing, expanding tabs, stripping trailing blanks,
@@ -272,19 +326,22 @@ prefix(const struct buffer *buf, int add_space)
*/
if (np != pfx && (np > pfx || abs((int)(pfx - np)) > 8))
oflush();
- if ((h = ishead(cp)) != 0) {
- oflush();
- mark = lineno;
- }
- if (lineno - mark < 3 && lineno - mark > 0)
- for (hp = &headnames[0]; *hp != NULL; hp++)
- if (ispref(*hp, cp)) {
- h = 1;
- oflush();
- break;
- }
- if (!h && (h = (*cp == '.')))
- oflush();
+ if (!raw) {
+ if ((h = ishead(cp)) != 0) {
+ oflush();
+ mark = lineno;
+ }
+ if (lineno - mark < 3 && lineno - mark > 0)
+ for (hp = &headnames[0]; *hp != NULL; hp++)
+ if (ispref(*hp, cp)) {
+ h = 1;
+ oflush();
+ break;
+ }
+ if (!h && (h = (*cp == '.')))
+ oflush();
+ } else
+ h = 0;
pfx = np;
if (h) {
pack(cp, (size_t)(buf->ptr - cp));