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

Revision 7196, 6.3 KB checked in by miki, 30 years ago (diff)
replaced index and rindex with strchr, strrchr
Line 
1/*
2 *      $Source: /afs/dev.mit.edu/source/repository/athena/bin/just/just.c,v $
3 *      $Author: miki $
4 *      $Locker:  $
5 *      $Header: /afs/dev.mit.edu/source/repository/athena/bin/just/just.c,v 1.2 1994-03-30 10:30:51 miki 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.2 1994-03-30 10:30:51 miki 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
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],
56        outbuf[MAXLINE],
57        wordbuf[MAXLINE];
58
59char   *inptr = inbuf,
60       *outptr = outbuf,
61       *wordptr = wordbuf;
62
63char   *me;
64
65
66/* Next Page */
67
68main (argc, argv)
69int     argc;
70char   *argv[];
71{
72    char   *fgets ();
73
74
75    int     nlp = 0;            /* # lines in current paragraph */
76    int     i;
77    char    c;
78
79    me = strrchr (argv[0], '/');        /* fill or just? */
80    if (me == NULL)             /* No prefix to strip? */
81        me = argv[0];
82
83    if (argc > 2)
84        arg_err ();
85
86    if (argc > 1)
87        line_width = max (min (MAXLINE - 2, atoi (argv[1])), 1);
88
89    just = seq (me, "just");
90
91    outbuf[0] = '\0';
92    while (fgets (inbuf, MAXLINE, stdin) != NULL) {
93        inptr = inbuf;
94
95        /* Check for blank lines and breaks (last line of paragraph, etc.) */
96
97        while (*inptr == '\n')
98            if (nwords > 0) {   /* break? */
99                puts (outbuf);  /* never justify this line */
100                outptr = outbuf;
101                outbuf[0] = '\0';
102                nwords = 0;
103                nlp = 0;
104                }
105            else
106                putchar (*inptr++);/* blank line */
107
108        if (nlp == 0 && (*inptr != '\0')) {     /* 1st line of paragraph */
109            while (*inptr == ' ' || *inptr == '\t')
110                if (*inptr == ' ')
111                    *outptr++ = *inptr++;
112                else {          /* convert tabs */
113                    inptr++;
114                    i = (*outptr = '\0', slength (outbuf));
115                    do
116                        *outptr++ = ' ';
117                        while (++i % 8 != 0 && (outptr < &outbuf[line_width - 1]));
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                if (c == '\t')
127                    while (++inval % 8 != 0 && (inval < (line_width - 1)));
128                else
129                    inval++;
130
131            if (!feof (stdin))
132                ungetc (c, stdin);
133            nlp++;
134            }
135
136        while (getword ())
137            putword ();
138        }
139
140    if (outptr != outbuf)
141        puts (outbuf);
142    exit (0);
143}
144
145/* Next Page */
146
147/*
148 * getword -- returns true if it got a word; copies a word from inptr to outptr
149 */
150
151getword ()
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    if (wordptr != wordbuf && isbreak (*(inptr - 1)) && (*(inptr + 1) == ' ' || *inptr == '\n'))
163        *wordptr++ = ' ';
164
165    *wordptr = '\0';
166    return slength (wordbuf);
167}
168
169/* Next Page */
170
171/*
172 * putword -- write a word into outbuf if it fits, pads and writes the
173 *      buffer as appropriate
174 */
175
176putword ()
177{
178    char   *strcpy ();
179    register int    i = inval,
180                    sl = slength (wordbuf) + slength (outbuf);
181
182    if (*(wordptr - 1) == ' ' && sl == line_width) {
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        while (*(outptr - 1) == ' ')/* no spaces at end of line */
188            *--outptr = '\0';
189        if (just)
190            spread ();
191        *outptr = '\n';
192        *++outptr = '\0';
193        fputs (outbuf, stdout);
194        outptr = outbuf;
195        nwords = 0;
196        while (i--)
197            *outptr++ = ' ';
198        }
199    else
200        if (outptr != outbuf && nwords)
201            *outptr++ = ' ';
202
203 /* the scopy below places a null ('\0') at the end of the string * in
204    outbuf */
205    outptr = scopy (wordbuf, outptr, &outbuf[line_width]);
206    nwords++;
207}
208
209/* Next Page */
210
211/* spread -- spread out lines using the justification algorithm of
212 *      Kernighan and Plauger, "Software Tools", Chap. 7, pg. 241
213 *      (1976 edition)
214 */
215
216spread ()
217{
218    static int  dir = 0;
219    int     nextra = line_width - slength (outbuf),
220            ne,
221            nholes,
222            nb;
223    char   *ip,
224           *jp;
225
226    if (nextra > 0 && nwords > 1) {
227        dir = 1 - dir;          /* alternate side to put extra space on */
228        ne = nextra;
229        nholes = nwords - 1;
230        ip = outptr - 1;
231        jp = min (&outbuf[line_width], (ip + ne));
232        outptr = jp + 1;
233        while (ip < jp) {
234            *jp = *ip;
235            if (*ip == ' ') {
236                if (dir == 0)
237                    nb = (ne - 1) / nholes + 1;
238                else
239                    nb = ne / nholes;
240                ne -= nb;
241                nholes--;
242                for (; nb > 0; nb--)
243                    *--jp = ' ';
244                while (*(ip - 1) == ' ')
245                    *--jp = *--ip;/* protected space */
246                }
247            ip--;
248            jp--;
249            }
250        }
251}
252
253/* Next Page */
254
255/*
256 * arg_err -- usage message; because this is used as an editor filter,
257 *      copy the input to the output if being misued -- this prevents
258 *      the user's entire input from disappearing in vi, pen, etc.
259 */
260
261arg_err ()
262{
263    int     c;
264
265    fprintf (stderr, "%s: Usage is %s [line width].\n", me, me);
266
267    while ((c = getchar ()) != EOF)
268        putchar (c);
269
270    exit (1);
271}
272
273/* Next Page */
274/*
275 * isbreak -- is a character a member of the "ends a sentence" set?
276 */
277
278isbreak (c)
279    register char   c;
280{
281    switch (c) {
282        case '.':
283        case '!':
284        case '?':
285        case ':':
286            return (c);         /* true */
287            break;              /* pro forma */
288        default:
289            return (0);         /* false */
290        }
291}
Note: See TracBrowser for help on using the repository browser.