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