plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

col.c (3850B)


      1 /* col - eliminate reverse line feeds */
      2 #include <u.h>
      3 #include <libc.h>
      4 #include <ctype.h>
      5 #include <bio.h>
      6 
      7 enum {
      8 	ESC	= '\033',
      9 	RLF	= '\013',
     10 
     11 	PL	= 256,
     12 	LINELN	= 800,
     13 
     14 	Tabstop	= 8,		/* must be power of 2 */
     15 };
     16 
     17 static int bflag, xflag, fflag;
     18 static int cp, lp;
     19 static int half;
     20 static int ll, llh, mustwr;
     21 static int pcp = 0;
     22 
     23 static char *page[PL];
     24 static char *line;
     25 static char lbuff[LINELN];
     26 static Biobuf bin, bout;
     27 
     28 void	emit(char *s, int lineno);
     29 void	incr(void), decr(void);
     30 void	outc(Rune);
     31 
     32 static void
     33 usage(void)
     34 {
     35 	fprint(2, "usage: %s [-bfx]\n", argv0);
     36 	exits("usage");
     37 }
     38 
     39 void
     40 main(int argc, char **argv)
     41 {
     42 	int i, lno;
     43 	long ch;
     44 	Rune c;
     45 
     46 	ARGBEGIN{
     47 	case 'b':
     48 		bflag++;
     49 		break;
     50 	case 'f':
     51 		fflag++;
     52 		break;
     53 	case 'x':
     54 		xflag++;
     55 		break;
     56 	default:
     57 		usage();
     58 	}ARGEND;
     59 
     60 	for (ll=0; ll < PL; ll++)
     61 		page[ll] = nil;
     62 
     63 	cp = 0;
     64 	ll = 0;
     65 	mustwr = PL;
     66 	line = lbuff;
     67 
     68 	Binit(&bin, 0, OREAD);
     69 	Binit(&bout, 1, OWRITE);
     70 	while ((ch = Bgetrune(&bin)) != Beof) {
     71 		c = ch;
     72 		switch (c) {
     73 		case '\n':
     74 			incr();
     75 			incr();
     76 			cp = 0;
     77 			break;
     78 
     79 		case '\0':
     80 			break;
     81 
     82 		case ESC:
     83 			c = Bgetrune(&bin);
     84 			switch (c) {
     85 			case '7':	/* reverse full line feed */
     86 				decr();
     87 				decr();
     88 				break;
     89 
     90 			case '8':	/* reverse half line feed */
     91 				if (fflag)
     92 					decr();
     93 				else
     94 					if (--half < -1) {
     95 						decr();
     96 						decr();
     97 						half += 2;
     98 					}
     99 				break;
    100 
    101 			case '9':	/* forward half line feed */
    102 				if (fflag)
    103 					incr();
    104 				else
    105 					if (++half > 0) {
    106 						incr();
    107 						incr();
    108 						half -= 2;
    109 					}
    110 				break;
    111 			}
    112 			break;
    113 
    114 		case RLF:
    115 			decr();
    116 			decr();
    117 			break;
    118 
    119 		case '\r':
    120 			cp = 0;
    121 			break;
    122 
    123 		case '\t':
    124 			cp = (cp + Tabstop) & -Tabstop;
    125 			break;
    126 
    127 		case '\b':
    128 			if (cp > 0)
    129 				cp--;
    130 			break;
    131 
    132 		case ' ':
    133 			cp++;
    134 			break;
    135 
    136 		default:
    137 			if (!isascii(c) || isprint(c)) {
    138 				outc(c);
    139 				cp++;
    140 			}
    141 			break;
    142 		}
    143 	}
    144 
    145 	for (i=0; i < PL; i++) {
    146 		lno = (mustwr+i) % PL;
    147 		if (page[lno] != 0)
    148 			emit(page[lno], mustwr+i-PL);
    149 	}
    150 	emit(" ", (llh + 1) & -2);
    151 	exits(0);
    152 }
    153 
    154 void
    155 outc(Rune c)
    156 {
    157 	if (lp > cp) {
    158 		line = lbuff;
    159 		lp = 0;
    160 	}
    161 
    162 	while (lp < cp) {
    163 		switch (*line) {
    164 		case '\0':
    165 			*line = ' ';
    166 			lp++;
    167 			break;
    168 		case '\b':
    169 			lp--;
    170 			break;
    171 		default:
    172 			lp++;
    173 			break;
    174 		}
    175 		line++;
    176 	}
    177 	while (*line == '\b')
    178 		line += 2;
    179 	if (bflag || *line == '\0' || *line == ' ')
    180 		cp += runetochar(line, &c) - 1;
    181 	else {
    182 		char c1, c2, c3;
    183 
    184 		c1 = *++line;
    185 		*line++ = '\b';
    186 		c2 = *line;
    187 		*line++ = c;
    188 		while (c1) {
    189 			c3 = *line;
    190 			*line++ = c1;
    191 			c1 = c2;
    192 			c2 = c3;
    193 		}
    194 		lp = 0;
    195 		line = lbuff;
    196 	}
    197 }
    198 
    199 void
    200 store(int lno)
    201 {
    202 	lno %= PL;
    203 	if (page[lno] != nil)
    204 		free(page[lno]);
    205 	page[lno] = malloc((unsigned)strlen(lbuff) + 2);
    206 	if (page[lno] == nil)
    207 		sysfatal("out of memory");
    208 	strcpy(page[lno], lbuff);
    209 }
    210 
    211 void
    212 fetch(int lno)
    213 {
    214 	char *p;
    215 
    216 	lno %= PL;
    217 	p = lbuff;
    218 	while (*p)
    219 		*p++ = '\0';
    220 	line = lbuff;
    221 	lp = 0;
    222 	if (page[lno])
    223 		strcpy(line, page[lno]);
    224 }
    225 
    226 void
    227 emit(char *s, int lineno)
    228 {
    229 	int ncp;
    230 	char *p;
    231 	static int cline = 0;
    232 
    233 	if (*s) {
    234 		while (cline < lineno - 1) {
    235 			Bputc(&bout, '\n');
    236 			pcp = 0;
    237 			cline += 2;
    238 		}
    239 		if (cline != lineno) {
    240 			Bputc(&bout, ESC);
    241 			Bputc(&bout, '9');
    242 			cline++;
    243 		}
    244 		if (pcp)
    245 			Bputc(&bout, '\r');
    246 		pcp = 0;
    247 		p = s;
    248 		while (*p) {
    249 			ncp = pcp;
    250 			while (*p++ == ' ')
    251 				if ((++ncp & 7) == 0 && !xflag) {
    252 					pcp = ncp;
    253 					Bputc(&bout, '\t');
    254 				}
    255 			if (!*--p)
    256 				break;
    257 			while (pcp < ncp) {
    258 				Bputc(&bout, ' ');
    259 				pcp++;
    260 			}
    261 			Bputc(&bout, *p);
    262 			if (*p++ == '\b')
    263 				pcp--;
    264 			else
    265 				pcp++;
    266 		}
    267 	}
    268 }
    269 
    270 void
    271 incr(void)
    272 {
    273 	int lno;
    274 
    275 	store(ll++);
    276 	if (ll > llh)
    277 		llh = ll;
    278 	lno = ll % PL;
    279 	if (ll >= mustwr && page[lno]) {
    280 		emit(page[lno], ll - PL);
    281 		mustwr++;
    282 		free(page[lno]);
    283 		page[lno] = nil;
    284 	}
    285 	fetch(ll);
    286 }
    287 
    288 void
    289 decr(void)
    290 {
    291 	if (ll > mustwr - PL) {
    292 		store(ll--);
    293 		fetch(ll);
    294 	}
    295 }