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

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