xref: /original-bsd/usr.bin/fpr/fpr.c (revision af60fb2a)
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 
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 
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 
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 
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 
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 
380 nospace()
381 {
382   fputs("Storage limit exceeded.\n", stderr);
383   exit(1);
384 }
385