froese@eric.mpr.ca (Edwin Froese) (02/27/89)
EFTH MINIX report #69 - February 1989 - expand(1) and unexpand(1) Tools to convert tabs to/from spaces..... Terrence W. Holm holm@bdc.ubc.ca ---------------------------------------------------------- echo x - expand.1 sed '/^X/s///' > expand.1 << '/' XNAME X expand(1) - convert tabs to spaces X XSYNOPSIS X expand [ -tab1,tab2,tab3,... ] [ file ... ] X XDESCRIPTION X Expand(1) copies the named files to standard output, X replacing tabs (^I) with equivalent strings of space X characters. If no files are specified then standard X input is used. X X The tab stops will be at <tab1>, <tab2>, etc. If only X one tab is specified then the tab stop is every <tab1> X columns. The default is "-8". X XSEE ALSO X unexpand(1) / echo x - unexpand.1 sed '/^X/s///' > unexpand.1 << '/' XNAME X unexpand(1) - convert spaces to tabs X XSYNOPSIS X unexpand [ -a ] [ file ... ] X XDESCRIPTION X Unexpand(1) copies the named files to standard output, X replacing strings of space characters with a tab (^I), X where this would reduce the number of characters in the X file. If no files are specified then standard input is X read. X X If the "-a" option is used then all sequences of spaces X are converted, otherwise only leading blanks on each line X are compressed. The tab stop is assumed to be every 8 X columns. X XSEE ALSO X expand(1) / echo x - expand.c sed '/^X/s///' > expand.c << '/' X/* expand(1) Terrence W. Holm Feb. 1989 */ X X/* Usage: expand [ -tab1,tab2,tab3,... ] [ file ... ] */ X X#include <stdio.h> X#include <string.h> X X#define MAX_TABS 32 X X Xmain( argc, argv ) X int argc; X char *argv[]; X X { X int tabs[ MAX_TABS ]; X int tab_index = 0; /* Default one tab */ X int i; X FILE *f; X X tabs[ 0 ] = 8; /* Default tab stop */ X X if ( argc > 1 && argv[1][0] == '-' ) X { X char *p = argv[1]; X int last_tab_stop = 0; X X for ( tab_index = 0; tab_index < MAX_TABS; ++tab_index ) X { X if ( (tabs[ tab_index ] = atoi( p+1 )) <= last_tab_stop ) X { X fprintf( stderr, "Bad tab stop spec\n" ); X exit( 1 ); X } X X last_tab_stop = tabs[ tab_index ]; X X if ( (p = strchr( p+1, ',' )) == NULL ) X break; X } X X --argc; X ++argv; X } X X if ( argc == 1 ) X Expand( stdin, tab_index, tabs ); X else X for ( i = 1; i < argc; ++i ) X { X if ( (f = fopen( argv[i], "r" )) == NULL ) X { X perror( argv[i] ); X exit( 1 ); X } X X Expand( f, tab_index, tabs ); X fclose( f ); X } X X exit( 0 ); X } X X X X Xint column = 0; /* Current column, retained between files */ X X XExpand( f, tab_index, tabs ) X FILE *f; X int tab_index; X int tabs[]; X X { X int next; X int c; X int i; X X while ( (c = getc( f )) != EOF ) X { X if ( c == '\t' ) X { X if ( tab_index == 0 ) X next = ( column / tabs[0] + 1 ) * tabs[0]; X else X { X for ( i = 0; i <= tab_index && tabs[i] <= column; ++i ); X X if ( i > tab_index ) X next = column + 1; X else X next = tabs[i]; X } X X do { X ++column; X putchar( ' ' ); X } while ( column < next ); X X continue; X } X X if ( c == '\b' ) X column = column > 0 ? column - 1 : 0; X else if ( c == '\n' || c == '\r' ) X column = 0; X else X ++column; X X putchar( c ); X } X } / echo x - unexpand.c sed '/^X/s///' > unexpand.c << '/' X/* unexpand(1) Terrence W. Holm Feb. 1989 */ X X/* Usage: unexpand [ -a ] [ file ... ] */ X X#include <stdio.h> X X#define TAB 8 X X Xint column = 0; /* Current column, retained between files */ Xint spaces = 0; /* Spaces since last tab stop */ Xint leading_blank = 1; /* Only unexpand leading blanks, */ X /* overruled by -a option */ X X X Xmain( argc, argv ) X int argc; X char *argv[]; X X { X int all = 0; /* -a flag means unexpand all spaces */ X int i; X FILE *f; X X if ( argc > 1 && argv[1][0] == '-' ) X { X if ( strcmp( argv[1], "-a" ) == 0 ) X all = 1; X else X { X fprintf( stderr, "Usage: unexpand [ -a ] [ file ... ]\n" ); X exit( 1 ); X } X X --argc; X ++argv; X } X X if ( argc == 1 ) X Unexpand( stdin, all ); X else X for ( i = 1; i < argc; ++i ) X { X if ( (f = fopen( argv[i], "r" )) == NULL ) X { X perror( argv[i] ); X exit( 1 ); X } X X Unexpand( f, all ); X fclose( f ); X } X X X /* If there are pending spaces print them. */ X X while ( spaces > 0 ) X { X putchar( ' ' ); X --spaces; X } X X exit( 0 ); X } X X X X XUnexpand( f, all ) X FILE *f; X int all; X X { X int c; X X while ( (c = getc( f )) != EOF ) X { X if ( c == ' ' && (all || leading_blank) ) X { X ++column; X ++spaces; X X /* If we have white space up to a tab stop, then output */ X /* a tab. If only one space is required, use a ' '. */ X X if ( column % TAB == 0 ) X { X if ( spaces == 1 ) X putchar( ' ' ); X else X putchar( '\t' ); X X spaces = 0; X } X X continue; X } X X /* If a tab character is encountered in the input then */ X /* simply echo it. Any accumulated spaces can only be */ X /* since the last tab stop, so ignore them. */ X X if ( c == '\t' ) X { X column = ( column / TAB + 1 ) * TAB; X spaces = 0; X X putchar( '\t' ); X continue; X } X X /* A non-space character is to be printed. If there */ X /* are pending spaces, then print them. There will be */ X /* at most TAB-1 spaces to print. */ X X while ( spaces > 0 ) X { X putchar( ' ' ); X --spaces; X } X X if ( c == '\n' || c == '\r' ) X { X column = 0; X leading_blank = 1; X putchar( c ); X continue; X } X X if ( c == '\b' ) X column = column > 0 ? column - 1 : 0; X else X ++column; X X leading_blank = 0; X putchar( c ); X } X } / ----------------------------------------------------------