col.c 4.2 KB

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