version 1.17, 2001/07/12 05:17:05 |
version 1.18, 2001/11/28 22:01:42 |
|
|
"Copyright (c) 1997 Gareth McCaughan. All rights reserved.\n"; |
"Copyright (c) 1997 Gareth McCaughan. All rights reserved.\n"; |
#endif /* not lint */ |
#endif /* not lint */ |
|
|
/* Cater for BSD and non-BSD systems. |
|
* I hate the C preprocessor. |
|
*/ |
|
|
|
#undef HAVE_errx |
|
#undef HAVE_sysexits |
|
|
|
#ifdef unix |
|
# include <sys/param.h> |
|
# ifdef BSD |
|
# define HAVE_errx |
|
# if BSD >= 199306 |
|
# define HAVE_sysexits |
|
# endif |
|
# endif |
|
#endif |
|
|
|
#ifdef HAVE_errx |
|
# include <err.h> |
|
#else |
|
# define errx(rc,str) { fprintf(stderr,"fmt: %s\n",str); exit(rc); } |
|
#endif |
|
|
|
#ifdef HAVE_sysexits |
|
# include <sysexits.h> |
|
#else |
|
# define EX_USAGE 1 |
|
# define EX_NOINPUT 1 |
|
# define EX_SOFTWARE 1 |
|
# define EX_OSERR 1 |
|
#endif |
|
|
|
#include <ctype.h> |
#include <ctype.h> |
|
#include <err.h> |
|
#include <locale.h> |
#include <stdio.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <stdlib.h> |
#include <string.h> |
#include <string.h> |
|
#include <sysexits.h> |
|
#include <unistd.h> |
|
|
#ifdef NEED_getopt_h |
|
# include "getopt.h" |
|
#endif |
|
|
|
/* Something that, we hope, will never be a genuine line length, |
/* Something that, we hope, will never be a genuine line length, |
* indentation etc. |
* indentation etc. |
*/ |
*/ |
|
|
* If |fussyp==0| then we don't complain about non-numbers |
* If |fussyp==0| then we don't complain about non-numbers |
* (returning 0 instead), but we do complain about bad numbers. |
* (returning 0 instead), but we do complain about bad numbers. |
*/ |
*/ |
size_t get_positive(const char *s, const char *err_mess, int fussyP) { |
static size_t |
|
get_positive(const char *s, const char *err_mess, int fussyP) { |
char *t; |
char *t; |
long result = strtol(s,&t,0); |
long result = strtol(s,&t,0); |
if (*t) { if (fussyP) goto Lose; else return 0; } |
if (*t) { if (fussyP) goto Lose; else return 0; } |
|
|
return (size_t) result; |
return (size_t) result; |
} |
} |
|
|
/* Just for the sake of linguistic purity: */ |
|
|
|
#ifdef BRITISH |
|
# define CENTER "centre" |
|
#else |
|
# define CENTER "center" |
|
#endif |
|
|
|
/* Global variables */ |
/* Global variables */ |
|
|
static int centerP=0; /* Try to center lines? */ |
static int centerP=0; /* Try to center lines? */ |
|
|
static int coalesce_spaces_P=0; /* Coalesce multiple whitespace -> ' ' ? */ |
static int coalesce_spaces_P=0; /* Coalesce multiple whitespace -> ' ' ? */ |
static int allow_indented_paragraphs=0; /* Can first line have diff. ind.? */ |
static int allow_indented_paragraphs=0; /* Can first line have diff. ind.? */ |
static int tab_width=8; /* Number of spaces per tab stop */ |
static int tab_width=8; /* Number of spaces per tab stop */ |
static int output_tab_width=0; /* Ditto, when squashing leading spaces */ |
static size_t output_tab_width=0; /* Ditto, when squashing leading spaces */ |
static char *sentence_enders=".?!"; /* Double-space after these */ |
static const char *sentence_enders=".?!"; /* Double-space after these */ |
static int grok_mail_headers=0; /* treat embedded mail headers magically? */ |
static int grok_mail_headers=0; /* treat embedded mail headers magically? */ |
|
|
static int n_errors=0; /* Number of failed files. Return on exit. */ |
static int n_errors=0; /* Number of failed files. Return on exit. */ |
|
|
|
|
/* Prototypes */ |
/* Prototypes */ |
|
|
static void process_named_file (const char *); |
static void process_named_file(const char *); |
static void process_stream (FILE *, const char *); |
static void process_stream(FILE *, const char *); |
static size_t indent_length (const char *, size_t); |
static size_t indent_length(const char *, size_t); |
static int might_be_header (const char *); |
static int might_be_header(const unsigned char *); |
static void new_paragraph (size_t, size_t); |
static void new_paragraph(size_t, size_t); |
static void output_word (size_t, size_t, const char *, size_t, size_t); |
static void output_word(size_t, size_t, const char *, size_t, size_t); |
static void output_indent (size_t); |
static void output_indent(size_t); |
static void center_stream (FILE *, const char *); |
static void center_stream(FILE *, const char *); |
static char * get_line (FILE *, size_t *); |
static char * get_line(FILE *, size_t *); |
static void * xrealloc (void *, size_t); |
static void * xrealloc(void *, size_t); |
|
|
#define XMALLOC(x) xrealloc(0,x) |
#define XMALLOC(x) xrealloc(0,x) |
|
|
|
|
main(int argc, char *argv[]) { |
main(int argc, char *argv[]) { |
int ch; /* used for |getopt| processing */ |
int ch; /* used for |getopt| processing */ |
|
|
|
|
|
(void)setlocale(LC_CTYPE, ""); |
|
|
/* 1. Grok parameters. */ |
/* 1. Grok parameters. */ |
|
|
while ((ch = getopt(argc, argv, "0123456789cd:hl:mpst:w:")) != -1) |
while ((ch = getopt(argc, argv, "0123456789cd:hl:mpst:w:")) != -1) |
|
|
centerP = 1; |
centerP = 1; |
continue; |
continue; |
case 'd': |
case 'd': |
sentence_enders = XMALLOC(strlen(optarg)+1); |
sentence_enders = optarg; |
strcpy(sentence_enders, optarg); /* ok */ |
|
continue; |
continue; |
case 'l': |
case 'l': |
output_tab_width |
output_tab_width |
|
|
fprintf(stderr, |
fprintf(stderr, |
"Usage: fmt [-cmps] [-d chars] [-l num] [-t num]\n" |
"Usage: fmt [-cmps] [-d chars] [-l num] [-t num]\n" |
" [-w width | -width | goal [maximum]] [file ...]\n" |
" [-w width | -width | goal [maximum]] [file ...]\n" |
"Options: -c " CENTER " each line instead of formatting\n" |
"Options: -c center each line instead of formatting\n" |
" -d <chars> double-space after <chars> at line end\n" |
" -d <chars> double-space after <chars> at line end\n" |
" -l <n> turn each <n> spaces at start of line into a tab\n" |
" -l <n> turn each <n> spaces at start of line into a tab\n" |
" -m try to make sure mail header lines stay separate\n" |
" -m try to make sure mail header lines stay separate\n" |
|
|
* conservative to avoid mangling ordinary civilised text. |
* conservative to avoid mangling ordinary civilised text. |
*/ |
*/ |
static int |
static int |
might_be_header(const char *line) { |
might_be_header(const unsigned char *line) { |
if (!isupper(*line++)) return 0; |
if (!isupper(*line++)) return 0; |
while (*line && (isalnum(*line) || *line=='-')) ++line; |
while (*line && (isalnum(*line) || *line=='-')) ++line; |
return (*line==':' && isspace(line[1])); |
return (*line==':' && isspace(line[1])); |