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