1 /*
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Robert Corbett.
7 *
8 * %sccs.include.redist.c%
9 */
10
11 #ifndef lint
12 static char copyright[] =
13 "@(#) Copyright (c) 1989, 1993\n\
14 The Regents of the University of California. All rights reserved.\n";
15 #endif /* not lint */
16
17 #ifndef lint
18 static char sccsid[] = "@(#)fpr.c 8.1 (Berkeley) 06/06/93";
19 #endif /* not lint */
20
21 #include <stdio.h>
22
23 #define BLANK ' '
24 #define TAB '\t'
25 #define NUL '\000'
26 #define FF '\f'
27 #define BS '\b'
28 #define CR '\r'
29 #define VTAB '\013'
30 #define EOL '\n'
31
32 #define TRUE 1
33 #define FALSE 0
34
35 #define MAXCOL 170
36 #define TABSIZE 8
37 #define INITWIDTH 8
38
39 typedef
40 struct column
41 {
42 int count;
43 int width;
44 char *str;
45 }
46 COLUMN;
47
48 char cc;
49 char saved;
50 int length;
51 char *text;
52 int highcol;
53 COLUMN *line;
54 int maxpos;
55 int maxcol;
56
57 extern char *malloc();
58 extern char *calloc();
59 extern char *realloc();
60
61
62
main()63 main()
64 {
65 register int ch;
66 register char ateof;
67 register int i;
68 register int errorcount;
69
70
71 init();
72 errorcount = 0;
73 ateof = FALSE;
74
75 ch = getchar();
76 if (ch == EOF)
77 exit(0);
78
79 if (ch == EOL)
80 {
81 cc = NUL;
82 ungetc((int) EOL, stdin);
83 }
84 else if (ch == BLANK)
85 cc = NUL;
86 else if (ch == '1')
87 cc = FF;
88 else if (ch == '0')
89 cc = EOL;
90 else if (ch == '+')
91 cc = CR;
92 else
93 {
94 errorcount = 1;
95 cc = NUL;
96 ungetc(ch, stdin);
97 }
98
99 while ( ! ateof)
100 {
101 gettext();
102 ch = getchar();
103 if (ch == EOF)
104 {
105 flush();
106 ateof = TRUE;
107 }
108 else if (ch == EOL)
109 {
110 flush();
111 cc = NUL;
112 ungetc((int) EOL, stdin);
113 }
114 else if (ch == BLANK)
115 {
116 flush();
117 cc = NUL;
118 }
119 else if (ch == '1')
120 {
121 flush();
122 cc = FF;
123 }
124 else if (ch == '0')
125 {
126 flush();
127 cc = EOL;
128 }
129 else if (ch == '+')
130 {
131 for (i = 0; i < length; i++)
132 savech(i);
133 }
134 else
135 {
136 errorcount++;
137 flush();
138 cc = NUL;
139 ungetc(ch, stdin);
140 }
141 }
142
143 if (errorcount == 1)
144 fprintf(stderr, "Illegal carriage control - 1 line.\n");
145 else if (errorcount > 1)
146 fprintf(stderr, "Illegal carriage control - %d lines.\n", errorcount);
147
148 exit(0);
149 }
150
151
152
init()153 init()
154 {
155 register COLUMN *cp;
156 register COLUMN *cend;
157 register char *sp;
158
159
160 length = 0;
161 maxpos = MAXCOL;
162 sp = malloc((unsigned) maxpos);
163 if (sp == NULL)
164 nospace();
165 text = sp;
166
167 highcol = -1;
168 maxcol = MAXCOL;
169 line = (COLUMN *) calloc(maxcol, (unsigned) sizeof(COLUMN));
170 if (line == NULL)
171 nospace();
172 cp = line;
173 cend = line + (maxcol-1);
174 while (cp <= cend)
175 {
176 cp->width = INITWIDTH;
177 sp = calloc(INITWIDTH, (unsigned) sizeof(char));
178 if (sp == NULL)
179 nospace();
180 cp->str = sp;
181 cp++;
182 }
183 }
184
185
186
gettext()187 gettext()
188 {
189 register int i;
190 register char ateol;
191 register int ch;
192 register int pos;
193
194
195 i = 0;
196 ateol = FALSE;
197
198 while ( ! ateol)
199 {
200 ch = getchar();
201 if (ch == EOL || ch == EOF)
202 ateol = TRUE;
203 else if (ch == TAB)
204 {
205 pos = (1 + i/TABSIZE) * TABSIZE;
206 if (pos > maxpos)
207 {
208 maxpos = pos + 10;
209 text = realloc(text, (unsigned) maxpos);
210 if (text == NULL)
211 nospace();
212 }
213 while (i < pos)
214 {
215 text[i] = BLANK;
216 i++;
217 }
218 }
219 else if (ch == BS)
220 {
221 if (i > 0)
222 {
223 i--;
224 savech(i);
225 }
226 }
227 else if (ch == CR)
228 {
229 while (i > 0)
230 {
231 i--;
232 savech(i);
233 }
234 }
235 else if (ch == FF || ch == VTAB)
236 {
237 flush();
238 cc = ch;
239 i = 0;
240 }
241 else
242 {
243 if (i >= maxpos)
244 {
245 maxpos = i + 10;
246 text = realloc(text, (unsigned) maxpos);
247 if (text == NULL)
248 nospace();
249 }
250 text[i] = ch;
251 i++;
252 }
253 }
254
255 length = i;
256 }
257
258
259
savech(col)260 savech(col)
261 int col;
262 {
263 register char ch;
264 register int oldmax;
265 register COLUMN *cp;
266 register COLUMN *cend;
267 register char *sp;
268 register int newcount;
269
270
271 ch = text[col];
272 if (ch == BLANK)
273 return;
274
275 saved = TRUE;
276
277 if (col >= highcol)
278 highcol = col;
279
280 if (col >= maxcol)
281 {
282 oldmax = maxcol;
283 maxcol = col + 10;
284 line = (COLUMN *) realloc(line, (unsigned) maxcol*sizeof(COLUMN));
285 if (line == NULL)
286 nospace();
287 cp = line + oldmax;
288 cend = line + (maxcol - 1);
289 while (cp <= cend)
290 {
291 cp->width = INITWIDTH;
292 cp->count = 0;
293 sp = calloc(INITWIDTH, (unsigned) sizeof(char));
294 if (sp == NULL)
295 nospace();
296 cp->str = sp;
297 cp++;
298 }
299 }
300
301 cp = line + col;
302 newcount = cp->count + 1;
303 if (newcount > cp->width)
304 {
305 cp->width = newcount;
306 sp = realloc(cp->str, (unsigned) newcount*sizeof(char));
307 if (sp == NULL)
308 nospace();
309 cp->str = sp;
310 }
311 cp->count = newcount;
312 cp->str[newcount-1] = ch;
313 }
314
315
316
flush()317 flush()
318 {
319 register int i;
320 register int anchor;
321 register int height;
322 register int j;
323
324
325 if (cc != NUL)
326 putchar(cc);
327
328 if ( ! saved)
329 {
330 i = length;
331 while (i > 0 && text[i-1] == BLANK)
332 i--;
333 length = i;
334 for (i = 0; i < length; i++)
335 putchar(text[i]);
336 putchar(EOL);
337 return;
338 }
339
340 for (i =0; i < length; i++)
341 savech(i);
342
343 anchor = 0;
344 while (anchor <= highcol)
345 {
346 height = line[anchor].count;
347 if (height == 0)
348 {
349 putchar(BLANK);
350 anchor++;
351 }
352 else if (height == 1)
353 {
354 putchar( *(line[anchor].str) );
355 line[anchor].count = 0;
356 anchor++;
357 }
358 else
359 {
360 i = anchor;
361 while (i < highcol && line[i+1].count > 1)
362 i++;
363 for (j = anchor; j <= i; j++)
364 {
365 height = line[j].count - 1;
366 putchar(line[j].str[height]);
367 line[j].count = height;
368 }
369 for (j = anchor; j <= i; j++)
370 putchar(BS);
371 }
372 }
373
374 putchar(EOL);
375 highcol = -1;
376 }
377
378
379
nospace()380 nospace()
381 {
382 fputs("Storage limit exceeded.\n", stderr);
383 exit(1);
384 }
385