fix silly indirect-through-zero bug
[unix-history] / usr / src / usr.bin / fpr / fpr.c
CommitLineData
e659a7a0
KB
1/*
2 * Copyright (c) 1989 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Robert Corbett.
7 *
6ecf3d85 8 * %sccs.include.redist.c%
e659a7a0
KB
9 */
10
11#ifndef lint
12char copyright[] =
13"@(#) Copyright (c) 1989 The Regents of the University of California.\n\
14 All rights reserved.\n";
15#endif /* not lint */
16
17#ifndef lint
159e55a9 18static char sccsid[] = "@(#)fpr.c 5.4 (Berkeley) %G%";
e659a7a0 19#endif /* not lint */
5823e130
KB
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
39typedef
40 struct column
41 {
42 int count;
43 int width;
44 char *str;
45 }
46 COLUMN;
47
48char cc;
49char saved;
50int length;
51char *text;
52int highcol;
53COLUMN *line;
54int maxpos;
55int maxcol;
56
57extern char *malloc();
58extern char *calloc();
59extern char *realloc();
60
61\f
62
63main()
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\f
152
153init()
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\f
186
187gettext()
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\f
259
260savech(col)
261int 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\f
316
317flush()
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--;
159e55a9 333 length = i;
5823e130
KB
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\f
379
380nospace()
381{
382 fputs("Storage limit exceeded.\n", stderr);
383 exit(1);
384}