morpheus-base

morpheus base system
git clone git://git.2f30.org/morpheus-base
Log | Files | Refs

unexpand.c (1989B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <wchar.h>
      5 
      6 #include "utf.h"
      7 #include "util.h"
      8 
      9 static void unexpand(const char *, FILE *);
     10 
     11 static int aflag = 0;
     12 static int tabsize = 8;
     13 
     14 static void
     15 usage(void)
     16 {
     17 	eprintf("usage: %s [-a] [-t n] [file ...]\n", argv0);
     18 }
     19 
     20 int
     21 main(int argc, char *argv[])
     22 {
     23 	FILE *fp;
     24 	int ret = 0;
     25 
     26 	ARGBEGIN {
     27 	case 't':
     28 		tabsize = estrtol(EARGF(usage()), 0);
     29 		if (tabsize <= 0)
     30 			eprintf("unexpand: invalid tabsize\n");
     31 		/* Fallthrough: -t implies -a */
     32 	case 'a':
     33 		aflag = 1;
     34 		break;
     35 	default:
     36 		usage();
     37 	} ARGEND;
     38 
     39 	if (argc == 0) {
     40 		unexpand("<stdin>", stdin);
     41 	} else {
     42 		for (; argc > 0; argc--, argv++) {
     43 			if (!(fp = fopen(argv[0], "r"))) {
     44 				weprintf("fopen %s:", argv[0]);
     45 				ret = 1;
     46 				continue;
     47 			}
     48 			unexpand(argv[0], fp);
     49 			fclose(fp);
     50 		}
     51 	}
     52 	return ret;
     53 }
     54 
     55 static void
     56 unexpandspan(unsigned int n, unsigned int col)
     57 {
     58 	unsigned int off = (col-n) % tabsize;
     59 	Rune r;
     60 
     61 	if (n + off >= tabsize && n > 1)
     62 		n += off;
     63 
     64 	r = '\t';
     65 	for (; n >= tabsize; n -= tabsize)
     66 		writerune("<stdout>", stdout, &r);
     67 	r = ' ';
     68 	while (n--)
     69 		writerune("<stdout>", stdout, &r);
     70 }
     71 
     72 static void
     73 unexpand(const char *file, FILE *fp)
     74 {
     75 	unsigned int n = 0, col = 0;
     76 	Rune r;
     77 	int bol = 1;
     78 
     79 	while (1) {
     80 		if (!readrune(file, fp, &r))
     81 			break;
     82 
     83 		switch (r) {
     84 		case ' ':
     85 			if (bol || aflag)
     86 				n++;
     87 			col++;
     88 			break;
     89 		case '\t':
     90 			if (bol || aflag)
     91 				n += tabsize - col % tabsize;
     92 			col += tabsize - col % tabsize;
     93 			break;
     94 		case '\b':
     95 			if (bol || aflag)
     96 				unexpandspan(n, col);
     97 			col -= (col > 0);
     98 			n = 0;
     99 			bol = 0;
    100 			break;
    101 		case '\n':
    102 			if (bol || aflag)
    103 				unexpandspan(n, col);
    104 			n = col = 0;
    105 			bol = 1;
    106 			break;
    107 		default:
    108 			if (bol || aflag)
    109 				unexpandspan(n, col);
    110 			n = 0;
    111 			col++;
    112 			bol = 0;
    113 		}
    114 		if ((r != ' ' && r != '\t') || (!aflag && !bol))
    115 			writerune("<stdout>", stdout, &r);
    116 	}
    117 	if (n > 0 && (bol || aflag))
    118 		unexpandspan(n, col);
    119 }