source: trunk/athena/bin/just/just.c @ 13628

Revision 13628, 6.4 KB checked in by danw, 25 years ago (diff)
reindent and remove really gross macros
Line 
1/* Copyright 1985, 1998 by the Massachusetts Institute of Technology.
2 *
3 * Permission to use, copy, modify, and distribute this
4 * software and its documentation for any purpose and without
5 * fee is hereby granted, provided that the above copyright
6 * notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting
8 * documentation, and that the name of M.I.T. not be used in
9 * advertising or publicity pertaining to distribution of the
10 * software without specific, written prior permission.
11 * M.I.T. makes no representations about the suitability of
12 * this software for any purpose.  It is provided "as is"
13 * without express or implied warranty.
14 */
15
16static const char rcsid[] = "$Id: just.c,v 1.6 1999-09-24 20:36:09 danw Exp $";
17
18/*
19 * fill/just filter
20 *
21 * Initial Coding 7 Feb 80, bbn:yba.
22 * Version of 21 Sep 83, fsi:yba
23 * Rehashed 18 Mar 85, mit:yba
24 *
25 *
26 * Use: fill [line_length]      (1 <= line_length <= 510.)
27 *      just [line_length]
28 *
29 * Will fill lines or fill and justify lines to line_length (default
30 * LINESIZE, below).
31 *
32 * Word longer than line_length are truncated!
33 * Tabs are converted on input; double space at end of sentence is
34 *     preserved.  Indentation for first line of paragraph preserved;
35 *     subsequent lines have indentation of second line (if present).
36 */
37
38/* Globals */
39
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
43
44#define MAXLINE 512
45#define LINESIZE 65     /* default line_length */
46
47#define min(x,y) ((x) < (y) ? (x) : (y))
48#define max(x,y) ((x) > (y) ? (x) : (y))
49
50int just;               /* bool: fill (false) or just (true)? */
51int nwords = 0;
52int line_width = LINESIZE;
53int inval = 0;          /* indentation from left margin */
54
55char inbuf[MAXLINE], outbuf[MAXLINE], wordbuf[MAXLINE];
56char *inptr = inbuf, *outptr = outbuf, *wordptr = wordbuf;
57
58char *me;
59
60static int getword(void);
61static void putword(void);
62static void spread(void);
63static void usage(void);
64static int isbreak(int c);
65
66int main(int argc, char **argv)
67{
68  int nlp = 0;          /* # lines in current paragraph */
69  int i;
70  char c;
71
72  me = strrchr(argv[0], '/');   /* fill or just? */
73  if (me == NULL)               /* No prefix to strip? */
74    me = argv[0];
75
76  if (argc > 2)
77    usage();
78
79  if (argc > 1)
80    line_width = max(min(MAXLINE - 2, atoi(argv[1])), 1);
81
82  just = !strcmp(me, "just");
83
84  outbuf[0] = '\0';
85  while (fgets(inbuf, MAXLINE, stdin))
86    {
87      inptr = inbuf;
88
89      /* Check for blank lines and breaks (last line of paragraph, etc.) */
90      while (*inptr == '\n')
91        {
92          if (nwords > 0)       /* break? */
93            {
94              puts(outbuf);     /* never justify this line */
95              outptr = outbuf;
96              outbuf[0] = '\0';
97              nwords = 0;
98              nlp = 0;
99            }
100          else
101            putchar(*inptr++);  /* blank line */
102        }
103
104      if (nlp == 0 && (*inptr != '\0')) /* 1st line of paragraph */
105        {
106          while (*inptr == ' ' || *inptr == '\t')
107            {
108              if (*inptr == ' ')
109                *outptr++ = *inptr++;
110              else              /* convert tabs */
111                {
112                  inptr++;
113                  i = (*outptr = '\0', strlen(outbuf));
114                  do
115                    *outptr++ = ' ';
116                  while (++i % 8 != 0 && (outptr < &outbuf[line_width - 1]));
117                }
118            }
119          *outptr = '\0';
120          /*
121           * Above we read from the buffered 1st line of the paragraph;
122           * below note that we are looking at stdin again,
123           * reading the second line (if any) of that paragraph
124           */
125          for (inval = 0; (c = getchar ()) == ' ' || (c == '\t');)
126            {
127              if (c == '\t')
128                while (++inval % 8 != 0 && (inval < (line_width - 1)));
129              else
130                inval++;
131            }
132
133          if (!feof (stdin))
134            ungetc(c, stdin);
135          nlp++;
136        }
137
138      while (getword ())
139        putword ();
140    }
141
142    if (outptr != outbuf)
143      puts(outbuf);
144    exit(0);
145}
146
147/*
148 * getword -- returns true if it got a word; copies a word from inptr to outptr
149 */
150
151static int getword(void)
152{
153  wordptr = wordbuf;
154  while (*inptr == ' ' || *inptr == '\t')
155    inptr++;
156  while (*inptr != ' ' && *inptr != '\t' && *inptr != '\n' && *inptr != '\0')
157    *wordptr++ = *inptr++;
158
159  /* add an extra space after end of sentence if it was present in source,
160   * or if at the end of a line.
161   */
162
163  if (wordptr != wordbuf && isbreak(*(inptr - 1)) &&
164      (*(inptr + 1) == ' ' || *inptr == '\n'))
165    *wordptr++ = ' ';
166
167  *wordptr = '\0';
168  return strlen(wordbuf);
169}
170
171/*
172 * putword -- write a word into outbuf if it fits, pads and writes the
173 *      buffer as appropriate
174 */
175
176static void putword (void)
177{
178  int i = inval;
179  int sl = strlen(wordbuf) + strlen(outbuf);
180
181  if (*(wordptr - 1) == ' ' && sl == line_width)
182    {
183      *--wordptr = '\0';        /* get rid of space at end of line */
184      sl--;                     /* if it would put us over by one */
185    }
186  if (sl >= line_width)
187    {
188      while (*(outptr - 1) == ' ')/* no spaces at end of line */
189        *--outptr = '\0';
190      if (just)
191        spread();
192      *outptr = '\n';
193      *++outptr = '\0';
194      fputs(outbuf, stdout);
195      outptr = outbuf;
196      nwords = 0;
197      while (i--)
198        *outptr++ = ' ';
199    }
200  else
201    if (outptr != outbuf && nwords)
202      *outptr++ = ' ';
203
204  outptr = strchr(strcpy(outptr, wordbuf), '\0');
205  nwords++;
206}
207
208/* spread -- spread out lines using the justification algorithm of
209 *      Kernighan and Plauger, "Software Tools", Chap. 7, pg. 241
210 *      (1976 edition)
211 */
212
213static void spread(void)
214{
215  static int dir = 0;
216  int nextra = line_width - strlen(outbuf), ne, nholes, nb;
217  char *ip, *jp;
218
219  if (nextra > 0 && nwords > 1)
220    {
221      dir = 1 - dir;            /* alternate side to put extra space on */
222      ne = nextra;
223      nholes = nwords - 1;
224      ip = outptr - 1;
225      jp = min(&outbuf[line_width], (ip + ne));
226      outptr = jp + 1;
227      while (ip < jp)
228        {
229          *jp = *ip;
230          if (*ip == ' ')
231            {
232              if (dir == 0)
233                nb = (ne - 1) / nholes + 1;
234              else
235                nb = ne / nholes;
236              ne -= nb;
237              nholes--;
238              for (; nb > 0; nb--)
239                *--jp = ' ';
240              while (*(ip - 1) == ' ')
241                *--jp = *--ip;/* protected space */
242            }
243          ip--;
244          jp--;
245        }
246    }
247}
248
249/*
250 * usage -- usage message; because this is used as an editor filter,
251 *      copy the input to the output if being misued -- this prevents
252 *      the user's entire input from disappearing in vi, pen, etc.
253 */
254
255static void usage(void)
256{
257  int c;
258
259  fprintf(stderr, "%s: Usage is %s [line width].\n", me, me);
260
261  while ((c = getchar ()) != EOF)
262    putchar(c);
263
264  exit(1);
265}
266
267/*
268 * isbreak -- is a character a member of the "ends a sentence" set?
269 */
270
271static int isbreak(int c)
272{
273  switch (c)
274    {
275    case '.':
276    case '!':
277    case '?':
278    case ':':
279      return (c);               /* true */
280    default:
281      return (0);               /* false */
282    }
283}
Note: See TracBrowser for help on using the repository browser.