#include #include #include static int nstop = 8; static int minspace; static Biobuf bout; static void untab(Biobuf *b) { long c; int pos; pos = 0; while((c = Bgetrune(b)) != Beof) { if(c == '\t') { do Bputrune(&bout, ' '); while(++pos % nstop); } else { Bputrune(&bout, c); if(c == '\n') pos = 0; else ++pos; } } } static void putspaces(int pos, int n) { int epos; if(n < minspace) { while(n-- > 0) Bputrune(&bout, ' '); return; } epos = pos + n; while(pos/nstop != epos/nstop) { Bputrune(&bout, '\t'); pos += nstop - pos % nstop; } while(pos++ < epos) Bputrune(&bout, ' '); } static void tab(Biobuf *b) { int c, nspace, pos; pos = 0; nspace = 0; while((c = Bgetrune(b)) != Beof) { switch(c) { case ' ': nspace++; pos++; continue; case '\t': nspace += nstop - pos % nstop; pos += nstop - pos % nstop; continue; } putspaces(pos-nspace, nspace); nspace = 0; Bputrune(&bout, c); if(c == '\n') pos = 0; else pos++; } } void usage(void) { fprint(2, "usage: tab [-n tabstop] [-u] [file...]\n"); exits("usage"); } void main(int argc, char **argv) { int i, err; Biobuf *b, bin; void (*cvt)(Biobuf *b); cvt = tab; ARGBEGIN{ case 'm': minspace = atoi(ARGF()); break; case 'n': nstop = atoi(ARGF()); break; case 'u': cvt = untab; break; default: usage(); }ARGEND; if(minspace == 0) minspace = 2; Binit(&bout, 1, OWRITE); if(argc > 0) { err = 0; for(i=0; i