fpr.c revision 1.3 1 /* $NetBSD: fpr.c,v 1.3 1995/09/01 01:34:16 jtc 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 #ifndef lint
40 static char copyright[] =
41 "@(#) 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 static char rcsid[] = "$NetBSD: fpr.c,v 1.3 1995/09/01 01:34:16 jtc Exp $";
50 #endif /* not lint */
51
52 #include <stdio.h>
53
54 #define BLANK ' '
55 #define TAB '\t'
56 #define NUL '\000'
57 #define FF '\f'
58 #define BS '\b'
59 #define CR '\r'
60 #define VTAB '\013'
61 #define EOL '\n'
62
63 #define TRUE 1
64 #define FALSE 0
65
66 #define MAXCOL 170
67 #define TABSIZE 8
68 #define INITWIDTH 8
69
70 typedef
71 struct column
72 {
73 int count;
74 int width;
75 char *str;
76 }
77 COLUMN;
78
79 char cc;
80 char saved;
81 int length;
82 char *text;
83 int highcol;
84 COLUMN *line;
85 int maxpos;
86 int maxcol;
87
88 extern char *malloc();
89 extern char *calloc();
90 extern char *realloc();
91
92
93
95 main()
96 {
97 register int ch;
98 register char ateof;
99 register int i;
100 register 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 {
113 cc = NUL;
114 ungetc((int) EOL, stdin);
115 }
116 else if (ch == BLANK)
117 cc = NUL;
118 else if (ch == '1')
119 cc = FF;
120 else if (ch == '0')
121 cc = EOL;
122 else if (ch == '+')
123 cc = CR;
124 else
125 {
126 errorcount = 1;
127 cc = NUL;
128 ungetc(ch, stdin);
129 }
130
131 while ( ! ateof)
132 {
133 gettext();
134 ch = getchar();
135 if (ch == EOF)
136 {
137 flush();
138 ateof = TRUE;
139 }
140 else if (ch == EOL)
141 {
142 flush();
143 cc = NUL;
144 ungetc((int) EOL, stdin);
145 }
146 else if (ch == BLANK)
147 {
148 flush();
149 cc = NUL;
150 }
151 else if (ch == '1')
152 {
153 flush();
154 cc = FF;
155 }
156 else if (ch == '0')
157 {
158 flush();
159 cc = EOL;
160 }
161 else if (ch == '+')
162 {
163 for (i = 0; i < length; i++)
164 savech(i);
165 }
166 else
167 {
168 errorcount++;
169 flush();
170 cc = NUL;
171 ungetc(ch, stdin);
172 }
173 }
174
175 if (errorcount == 1)
176 fprintf(stderr, "Illegal carriage control - 1 line.\n");
177 else if (errorcount > 1)
178 fprintf(stderr, "Illegal carriage control - %d lines.\n", errorcount);
179
180 exit(0);
181 }
182
183
184
186 init()
187 {
188 register COLUMN *cp;
189 register COLUMN *cend;
190 register char *sp;
191
192
193 length = 0;
194 maxpos = MAXCOL;
195 sp = malloc((unsigned) maxpos);
196 if (sp == NULL)
197 nospace();
198 text = sp;
199
200 highcol = -1;
201 maxcol = MAXCOL;
202 line = (COLUMN *) calloc(maxcol, (unsigned) sizeof(COLUMN));
203 if (line == NULL)
204 nospace();
205 cp = line;
206 cend = line + (maxcol-1);
207 while (cp <= cend)
208 {
209 cp->width = INITWIDTH;
210 sp = calloc(INITWIDTH, (unsigned) sizeof(char));
211 if (sp == NULL)
212 nospace();
213 cp->str = sp;
214 cp++;
215 }
216 }
217
218
219
221 gettext()
222 {
223 register int i;
224 register char ateol;
225 register int ch;
226 register int pos;
227
228
229 i = 0;
230 ateol = FALSE;
231
232 while ( ! ateol)
233 {
234 ch = getchar();
235 if (ch == EOL || ch == EOF)
236 ateol = TRUE;
237 else if (ch == TAB)
238 {
239 pos = (1 + i/TABSIZE) * TABSIZE;
240 if (pos > maxpos)
241 {
242 maxpos = pos + 10;
243 text = realloc(text, (unsigned) maxpos);
244 if (text == NULL)
245 nospace();
246 }
247 while (i < pos)
248 {
249 text[i] = BLANK;
250 i++;
251 }
252 }
253 else if (ch == BS)
254 {
255 if (i > 0)
256 {
257 i--;
258 savech(i);
259 }
260 }
261 else if (ch == CR)
262 {
263 while (i > 0)
264 {
265 i--;
266 savech(i);
267 }
268 }
269 else if (ch == FF || ch == VTAB)
270 {
271 flush();
272 cc = ch;
273 i = 0;
274 }
275 else
276 {
277 if (i >= maxpos)
278 {
279 maxpos = i + 10;
280 text = realloc(text, (unsigned) maxpos);
281 if (text == NULL)
282 nospace();
283 }
284 text[i] = ch;
285 i++;
286 }
287 }
288
289 length = i;
290 }
291
292
293
295 savech(col)
296 int col;
297 {
298 register char ch;
299 register int oldmax;
300 register COLUMN *cp;
301 register COLUMN *cend;
302 register char *sp;
303 register int newcount;
304
305
306 ch = text[col];
307 if (ch == BLANK)
308 return;
309
310 saved = TRUE;
311
312 if (col >= highcol)
313 highcol = col;
314
315 if (col >= maxcol)
316 {
317 oldmax = maxcol;
318 maxcol = col + 10;
319 line = (COLUMN *) realloc(line, (unsigned) maxcol*sizeof(COLUMN));
320 if (line == NULL)
321 nospace();
322 cp = line + oldmax;
323 cend = line + (maxcol - 1);
324 while (cp <= cend)
325 {
326 cp->width = INITWIDTH;
327 cp->count = 0;
328 sp = calloc(INITWIDTH, (unsigned) sizeof(char));
329 if (sp == NULL)
330 nospace();
331 cp->str = sp;
332 cp++;
333 }
334 }
335
336 cp = line + col;
337 newcount = cp->count + 1;
338 if (newcount > cp->width)
339 {
340 cp->width = newcount;
341 sp = realloc(cp->str, (unsigned) newcount*sizeof(char));
342 if (sp == NULL)
343 nospace();
344 cp->str = sp;
345 }
346 cp->count = newcount;
347 cp->str[newcount-1] = ch;
348 }
349
350
351
353 flush()
354 {
355 register int i;
356 register int anchor;
357 register int height;
358 register int j;
359
360
361 if (cc != NUL)
362 putchar(cc);
363
364 if ( ! saved)
365 {
366 i = length;
367 while (i > 0 && text[i-1] == BLANK)
368 i--;
369 length = i;
370 for (i = 0; i < length; i++)
371 putchar(text[i]);
372 putchar(EOL);
373 return;
374 }
375
376 for (i =0; i < length; i++)
377 savech(i);
378
379 anchor = 0;
380 while (anchor <= highcol)
381 {
382 height = line[anchor].count;
383 if (height == 0)
384 {
385 putchar(BLANK);
386 anchor++;
387 }
388 else if (height == 1)
389 {
390 putchar( *(line[anchor].str) );
391 line[anchor].count = 0;
392 anchor++;
393 }
394 else
395 {
396 i = anchor;
397 while (i < highcol && line[i+1].count > 1)
398 i++;
399 for (j = anchor; j <= i; j++)
400 {
401 height = line[j].count - 1;
402 putchar(line[j].str[height]);
403 line[j].count = height;
404 }
405 for (j = anchor; j <= i; j++)
406 putchar(BS);
407 }
408 }
409
410 putchar(EOL);
411 highcol = -1;
412 }
413
414
415
417 nospace()
418 {
419 fputs("Storage limit exceeded.\n", stderr);
420 exit(1);
421 }
422