fpr.c revision 1.4 1 /* $NetBSD: fpr.c,v 1.4 1997/10/18 15:05:47 lukem Exp $ */
2
3 /*
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Robert Corbett.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 */
38
39 #include <sys/cdefs.h>
40 #ifndef lint
41 __COPYRIGHT("@(#) Copyright (c) 1989, 1993\n\
42 The Regents of the University of California. All rights reserved.\n");
43 #endif /* not lint */
44
45 #ifndef lint
46 #if 0
47 static char sccsid[] = "@(#)fpr.c 8.1 (Berkeley) 6/6/93";
48 #endif
49 __RCSID("$NetBSD: fpr.c,v 1.4 1997/10/18 15:05:47 lukem Exp $");
50 #endif /* not lint */
51
52 #include <err.h>
53 #include <stdio.h>
54 #include <stdlib.h>
55
56 #define BLANK ' '
57 #define TAB '\t'
58 #define NUL '\000'
59 #define FF '\f'
60 #define BS '\b'
61 #define CR '\r'
62 #define VTAB '\013'
63 #define EOL '\n'
64
65 #define TRUE 1
66 #define FALSE 0
67
68 #define MAXCOL 170
69 #define TABSIZE 8
70 #define INITWIDTH 8
71
72 typedef
73 struct column {
74 int count;
75 int width;
76 char *str;
77 }
78 COLUMN;
79
80 char cc;
81 char saved;
82 int length;
83 char *text;
84 int highcol;
85 COLUMN *line;
86 int maxpos;
87 int maxcol;
88
89 void flush __P((void));
90 void gettext __P((void));
91 void init __P((void));
92 int main __P((int, char **));
93 void nospace __P((void));
94 void savech __P((int));
95
96 int
97 main(argc, argv)
98 int argc;
99 char **argv;
100 {
101 int ch;
102 char ateof;
103 int i;
104 int errorcount;
105
106
107 init();
108 errorcount = 0;
109 ateof = FALSE;
110
111 ch = getchar();
112 if (ch == EOF)
113 exit(0);
114
115 if (ch == EOL) {
116 cc = NUL;
117 ungetc((int) EOL, stdin);
118 } else
119 if (ch == BLANK)
120 cc = NUL;
121 else
122 if (ch == '1')
123 cc = FF;
124 else
125 if (ch == '0')
126 cc = EOL;
127 else
128 if (ch == '+')
129 cc = CR;
130 else {
131 errorcount = 1;
132 cc = NUL;
133 ungetc(ch, stdin);
134 }
135
136 while (!ateof) {
137 gettext();
138 ch = getchar();
139 if (ch == EOF) {
140 flush();
141 ateof = TRUE;
142 } else
143 if (ch == EOL) {
144 flush();
145 cc = NUL;
146 ungetc((int) EOL, stdin);
147 } else
148 if (ch == BLANK) {
149 flush();
150 cc = NUL;
151 } else
152 if (ch == '1') {
153 flush();
154 cc = FF;
155 } else
156 if (ch == '0') {
157 flush();
158 cc = EOL;
159 } else
160 if (ch == '+') {
161 for (i = 0; i < length; i++)
162 savech(i);
163 } else {
164 errorcount++;
165 flush();
166 cc = NUL;
167 ungetc(ch, stdin);
168 }
169 }
170
171 if (errorcount == 1)
172 fprintf(stderr, "Illegal carriage control - 1 line.\n");
173 else
174 if (errorcount > 1)
175 fprintf(stderr, "Illegal carriage control - %d lines.\n", errorcount);
176
177 exit(0);
178 }
179
180 void
181 init()
182 {
183 COLUMN *cp;
184 COLUMN *cend;
185 char *sp;
186
187
188 length = 0;
189 maxpos = MAXCOL;
190 sp = malloc((unsigned) maxpos);
191 if (sp == NULL)
192 nospace();
193 text = sp;
194
195 highcol = -1;
196 maxcol = MAXCOL;
197 line = (COLUMN *) calloc(maxcol, (unsigned) sizeof(COLUMN));
198 if (line == NULL)
199 nospace();
200 cp = line;
201 cend = line + (maxcol - 1);
202 while (cp <= cend) {
203 cp->width = INITWIDTH;
204 sp = calloc(INITWIDTH, (unsigned) sizeof(char));
205 if (sp == NULL)
206 nospace();
207 cp->str = sp;
208 cp++;
209 }
210 }
211
212 void
213 gettext()
214 {
215 int i;
216 char ateol;
217 int ch;
218 int pos;
219
220 i = 0;
221 ateol = FALSE;
222
223 while (!ateol) {
224 ch = getchar();
225 if (ch == EOL || ch == EOF)
226 ateol = TRUE;
227 else
228 if (ch == TAB) {
229 pos = (1 + i / TABSIZE) * TABSIZE;
230 if (pos > maxpos) {
231 maxpos = pos + 10;
232 text = realloc(text, (unsigned) maxpos);
233 if (text == NULL)
234 nospace();
235 }
236 while (i < pos) {
237 text[i] = BLANK;
238 i++;
239 }
240 } else
241 if (ch == BS) {
242 if (i > 0) {
243 i--;
244 savech(i);
245 }
246 } else
247 if (ch == CR) {
248 while (i > 0) {
249 i--;
250 savech(i);
251 }
252 } else
253 if (ch == FF || ch == VTAB) {
254 flush();
255 cc = ch;
256 i = 0;
257 } else {
258 if (i >= maxpos) {
259 maxpos = i + 10;
260 text = realloc(text, (unsigned) maxpos);
261 if (text == NULL)
262 nospace();
263 }
264 text[i] = ch;
265 i++;
266 }
267 }
268
269 length = i;
270 }
271
272 void
273 savech(col)
274 int col;
275 {
276 char ch;
277 int oldmax;
278 COLUMN *cp;
279 COLUMN *cend;
280 char *sp;
281 int newcount;
282
283 ch = text[col];
284 if (ch == BLANK)
285 return;
286
287 saved = TRUE;
288
289 if (col >= highcol)
290 highcol = col;
291
292 if (col >= maxcol) {
293 oldmax = maxcol;
294 maxcol = col + 10;
295 line = (COLUMN *) realloc(line, (unsigned) maxcol * sizeof(COLUMN));
296 if (line == NULL)
297 nospace();
298 cp = line + oldmax;
299 cend = line + (maxcol - 1);
300 while (cp <= cend) {
301 cp->width = INITWIDTH;
302 cp->count = 0;
303 sp = calloc(INITWIDTH, (unsigned) sizeof(char));
304 if (sp == NULL)
305 nospace();
306 cp->str = sp;
307 cp++;
308 }
309 }
310 cp = line + col;
311 newcount = cp->count + 1;
312 if (newcount > cp->width) {
313 cp->width = newcount;
314 sp = realloc(cp->str, (unsigned) newcount * sizeof(char));
315 if (sp == NULL)
316 nospace();
317 cp->str = sp;
318 }
319 cp->count = newcount;
320 cp->str[newcount - 1] = ch;
321 }
322
323 void
324 flush()
325 {
326 int i;
327 int anchor;
328 int height;
329 int j;
330
331 if (cc != NUL)
332 putchar(cc);
333
334 if (!saved) {
335 i = length;
336 while (i > 0 && text[i - 1] == BLANK)
337 i--;
338 length = i;
339 for (i = 0; i < length; i++)
340 putchar(text[i]);
341 putchar(EOL);
342 return;
343 }
344 for (i = 0; i < length; i++)
345 savech(i);
346
347 anchor = 0;
348 while (anchor <= highcol) {
349 height = line[anchor].count;
350 if (height == 0) {
351 putchar(BLANK);
352 anchor++;
353 } else
354 if (height == 1) {
355 putchar(*(line[anchor].str));
356 line[anchor].count = 0;
357 anchor++;
358 } else {
359 i = anchor;
360 while (i < highcol && line[i + 1].count > 1)
361 i++;
362 for (j = anchor; j <= i; j++) {
363 height = line[j].count - 1;
364 putchar(line[j].str[height]);
365 line[j].count = height;
366 }
367 for (j = anchor; j <= i; j++)
368 putchar(BS);
369 }
370 }
371
372 putchar(EOL);
373 highcol = -1;
374 }
375
376 void
377 nospace()
378 {
379 errx(1, "Storage limit exceeded.");
380 }
381