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

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