1 /* $NetBSD: fpr.c,v 1.7 2003/10/16 06:50:17 itojun 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. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include <sys/cdefs.h> 36 #ifndef lint 37 __COPYRIGHT("@(#) Copyright (c) 1989, 1993\n\ 38 The Regents of the University of California. All rights reserved.\n"); 39 #endif /* not lint */ 40 41 #ifndef lint 42 #if 0 43 static char sccsid[] = "@(#)fpr.c 8.1 (Berkeley) 6/6/93"; 44 #endif 45 __RCSID("$NetBSD: fpr.c,v 1.7 2003/10/16 06:50:17 itojun Exp $"); 46 #endif /* not lint */ 47 48 #include <err.h> 49 #include <stdio.h> 50 #include <stdlib.h> 51 52 #define BLANK ' ' 53 #define TAB '\t' 54 #define NUL '\000' 55 #define FF '\f' 56 #define BS '\b' 57 #define CR '\r' 58 #define VTAB '\013' 59 #define EOL '\n' 60 61 #define TRUE 1 62 #define FALSE 0 63 64 #define MAXCOL 170 65 #define TABSIZE 8 66 #define INITWIDTH 8 67 68 typedef 69 struct column { 70 int count; 71 int width; 72 char *str; 73 } 74 COLUMN; 75 76 char cc; 77 char saved; 78 int length; 79 char *text; 80 int highcol; 81 COLUMN *line; 82 int maxpos; 83 int maxcol; 84 85 void flush __P((void)); 86 void get_text __P((void)); 87 void init __P((void)); 88 int main __P((int, char **)); 89 void nospace __P((void)); 90 void savech __P((int)); 91 92 int 93 main(argc, argv) 94 int argc; 95 char **argv; 96 { 97 int ch; 98 char ateof; 99 int i; 100 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 cc = NUL; 113 ungetc((int) EOL, stdin); 114 } else 115 if (ch == BLANK) 116 cc = NUL; 117 else 118 if (ch == '1') 119 cc = FF; 120 else 121 if (ch == '0') 122 cc = EOL; 123 else 124 if (ch == '+') 125 cc = CR; 126 else { 127 errorcount = 1; 128 cc = NUL; 129 ungetc(ch, stdin); 130 } 131 132 while (!ateof) { 133 get_text(); 134 ch = getchar(); 135 if (ch == EOF) { 136 flush(); 137 ateof = TRUE; 138 } else 139 if (ch == EOL) { 140 flush(); 141 cc = NUL; 142 ungetc((int) EOL, stdin); 143 } else 144 if (ch == BLANK) { 145 flush(); 146 cc = NUL; 147 } else 148 if (ch == '1') { 149 flush(); 150 cc = FF; 151 } else 152 if (ch == '0') { 153 flush(); 154 cc = EOL; 155 } else 156 if (ch == '+') { 157 for (i = 0; i < length; i++) 158 savech(i); 159 } else { 160 errorcount++; 161 flush(); 162 cc = NUL; 163 ungetc(ch, stdin); 164 } 165 } 166 167 if (errorcount == 1) 168 fprintf(stderr, "Illegal carriage control - 1 line.\n"); 169 else 170 if (errorcount > 1) 171 fprintf(stderr, "Illegal carriage control - %d lines.\n", errorcount); 172 173 exit(0); 174 } 175 176 void 177 init() 178 { 179 COLUMN *cp; 180 COLUMN *cend; 181 char *sp; 182 183 184 length = 0; 185 maxpos = MAXCOL; 186 sp = malloc((unsigned) maxpos); 187 if (sp == NULL) 188 nospace(); 189 text = sp; 190 191 highcol = -1; 192 maxcol = MAXCOL; 193 line = (COLUMN *) calloc(maxcol, (unsigned) sizeof(COLUMN)); 194 if (line == NULL) 195 nospace(); 196 cp = line; 197 cend = line + (maxcol - 1); 198 while (cp <= cend) { 199 cp->width = INITWIDTH; 200 sp = calloc(INITWIDTH, (unsigned) sizeof(char)); 201 if (sp == NULL) 202 nospace(); 203 cp->str = sp; 204 cp++; 205 } 206 } 207 208 void 209 get_text() 210 { 211 int i; 212 char ateol; 213 int ch; 214 int pos; 215 char *n; 216 217 i = 0; 218 ateol = FALSE; 219 220 while (!ateol) { 221 ch = getchar(); 222 if (ch == EOL || ch == EOF) 223 ateol = TRUE; 224 else 225 if (ch == TAB) { 226 pos = (1 + i / TABSIZE) * TABSIZE; 227 if (pos > maxpos) { 228 n = realloc(text, (unsigned)(pos + 10)); 229 if (n == NULL) 230 nospace(); 231 text = n; 232 maxpos = pos + 10; 233 } 234 while (i < pos) { 235 text[i] = BLANK; 236 i++; 237 } 238 } else 239 if (ch == BS) { 240 if (i > 0) { 241 i--; 242 savech(i); 243 } 244 } else 245 if (ch == CR) { 246 while (i > 0) { 247 i--; 248 savech(i); 249 } 250 } else 251 if (ch == FF || ch == VTAB) { 252 flush(); 253 cc = ch; 254 i = 0; 255 } else { 256 if (i >= maxpos) { 257 n = realloc(text, (unsigned)(i + 10)); 258 if (n == NULL) 259 nospace(); 260 maxpos = i + 10; 261 } 262 text[i] = ch; 263 i++; 264 } 265 } 266 267 length = i; 268 } 269 270 void 271 savech(col) 272 int col; 273 { 274 char ch; 275 int oldmax; 276 COLUMN *cp; 277 COLUMN *cend; 278 char *sp; 279 int newcount; 280 COLUMN *newline; 281 282 ch = text[col]; 283 if (ch == BLANK) 284 return; 285 286 saved = TRUE; 287 288 if (col >= highcol) 289 highcol = col; 290 291 if (col >= maxcol) { 292 newline = (COLUMN *) realloc(line, 293 (unsigned) (col + 10) * sizeof(COLUMN)); 294 if (newline == NULL) 295 nospace(); 296 line = newline; 297 oldmax = maxcol; 298 maxcol = col + 10; 299 cp = line + oldmax; 300 cend = line + (maxcol - 1); 301 while (cp <= cend) { 302 cp->width = INITWIDTH; 303 cp->count = 0; 304 sp = calloc(INITWIDTH, (unsigned) sizeof(char)); 305 if (sp == NULL) 306 nospace(); 307 cp->str = sp; 308 cp++; 309 } 310 } 311 cp = line + col; 312 newcount = cp->count + 1; 313 if (newcount > cp->width) { 314 cp->width = newcount; 315 sp = realloc(cp->str, (unsigned) newcount * sizeof(char)); 316 if (sp == NULL) 317 nospace(); 318 cp->str = sp; 319 } 320 cp->count = newcount; 321 cp->str[newcount - 1] = ch; 322 } 323 324 void 325 flush() 326 { 327 int i; 328 int anchor; 329 int height; 330 int j; 331 332 if (cc != NUL) 333 putchar(cc); 334 335 if (!saved) { 336 i = length; 337 while (i > 0 && text[i - 1] == BLANK) 338 i--; 339 length = i; 340 for (i = 0; i < length; i++) 341 putchar(text[i]); 342 putchar(EOL); 343 return; 344 } 345 for (i = 0; i < length; i++) 346 savech(i); 347 348 anchor = 0; 349 while (anchor <= highcol) { 350 height = line[anchor].count; 351 if (height == 0) { 352 putchar(BLANK); 353 anchor++; 354 } else 355 if (height == 1) { 356 putchar(*(line[anchor].str)); 357 line[anchor].count = 0; 358 anchor++; 359 } else { 360 i = anchor; 361 while (i < highcol && line[i + 1].count > 1) 362 i++; 363 for (j = anchor; j <= i; j++) { 364 height = line[j].count - 1; 365 putchar(line[j].str[height]); 366 line[j].count = height; 367 } 368 for (j = anchor; j <= i; j++) 369 putchar(BS); 370 } 371 } 372 373 putchar(EOL); 374 highcol = -1; 375 } 376 377 void 378 nospace() 379 { 380 errx(1, "Storage limit exceeded."); 381 } 382