/* ** DETAB - replaces tabs with multiple spaces as appropriate ** tab width defaults to 8 but may be anything ** Steve Salisbury 1988-03-09 Wed ** ** 1989 Aug 30 Wed -- arg parsing was wrong ** 1989 Nov 01 Wed 12:00 add selection of non-space fill character ** 1991 Jan 14 Mon 18:20 fix selection of non-space fill character ** 1991 Jan 17 Thu 12:00 change message every 4KB to every 16KB ** allow command line argument for input file ** do not use big output buffer if stdout=con ** ** cl -G2s -Oaltr detab.c -o detab.exr -link slibcr libh /nod:slibce; ** cl detab -link slibcp libh /nod:slibce, detab; */ #include #include #include #define SPACE ' ' #define TAB '\t' #define TABWIDTH 8 #define REG register #define NEWLINE(c) ( (c) == '\n' || (c) == '\r' || (c) == '\f' ) #ifndef BIGBUFSIZE #define BIGBUFSIZE 8192 #endif char inbuf [ BIGBUFSIZE ] ; char outbuf [ BIGBUFSIZE ] ; static char MsgInternalError [ ] = "detab: internal error: %s(%s)\n" ; static char MsgOpenError [ ] = "detab: cannot open `%s' for input\n" ; static char MsgWriteError [ ] = "detab: error writing to `%s'\n" ; static char MsgStdin [ ] = "" ; static char MsgStdout [ ] = "" ; static char MsgSetmode [ ] = "setmode" ; static char MsgSetvbuf [ ] = "setvbuf" ; int main ( int argc , char * * argv ) { REG int column ; REG int ch ; REG int spcount ; FILE * input ; char * MsgInput ; int tabwidth = TABWIDTH ; int countflag = 0 ; long kilobytes ; unsigned bytecount ; char * cp ; int FillChar = SPACE ; /* default character to use when detabbing */ while ( -- argc > 0 && * ( cp = * ++ argv ) == '-' ) { ++cp; while (*cp) { if ( * cp == 'k' ) ++ countflag , ++ cp ; else if ( '0' <= * cp && * cp <= '9' ) { tabwidth = * cp ++ - '0' ; while ( '0' <= * cp && * cp <= '9' ) tabwidth = 10 * tabwidth + * cp ++ - '0' ; } else if ( * cp == 'c' ) { FillChar = * ++ cp ; ++ cp ; } else { Usage : fprintf ( stderr , "Usage: detab [-cX -k -###] [inputfile]\n" "where ### is the number of colums per tab stop (default=8)\n" "-k selects progress reports (written to stderr) every 16 Kbytes\n" "and X is the character to use for tabs (default is space)\n" ) ; exit ( 1 ) ; } } } if ( argc == 0 ) { MsgInput = MsgStdin ; input = stdin ; if ( _setmode ( _fileno(stdin) , O_BINARY ) == -1 ) { fprintf ( stderr , MsgInternalError , MsgSetmode , MsgStdin ) ; exit ( -1 ) ; } } else if ( argc == 1 ) { MsgInput = * argv ; if ( ! ( input = fopen ( MsgInput , "rb" ) ) ) { fprintf ( stderr , MsgOpenError , MsgInput ) ; exit ( 1 ) ; } } else goto Usage ; if ( setvbuf ( input , inbuf , _IOFBF , BIGBUFSIZE ) ) { fprintf ( stderr , MsgInternalError , MsgSetvbuf , MsgInput ) ; exit ( -1 ) ; } if ( _setmode ( _fileno(stdout) , O_BINARY ) == -1 ) { fprintf ( stderr , MsgInternalError , MsgSetmode , MsgStdout ) ; exit ( -1 ) ; } if ( ! _isatty ( _fileno ( stdin ) ) && setvbuf ( stdout , outbuf , _IOFBF , BIGBUFSIZE ) ) { fprintf ( stderr , MsgInternalError , MsgSetvbuf , MsgStdout ) ; exit ( -1 ) ; } kilobytes = bytecount = 0 ; column = 0 ; while ( ( ch = getc ( input ) ) != EOF ) { if ( ch == TAB ) { do putchar ( FillChar ) ; while ( ++ column < tabwidth ) ; column = 0 ; } else { putchar ( ch ) ; if ( NEWLINE(ch) ) column = 0 ; else if ( ++ column == tabwidth ) column = 0 ; else if ( column > tabwidth ) { fprintf ( stderr , MsgInternalError , "" , "column>tabwidth" ) ; return 1 ; } } if ( ++ bytecount >= 16384 ) { bytecount -= 16384 ; if ( countflag ) fprintf ( stderr , "%ldK\r" , kilobytes += 16 ) ; if ( ferror ( stdout) ) { fprintf ( stderr , MsgWriteError , MsgStdout ) ; return 1 ; } } } if ( ferror ( stdout) || fflush ( stdout ) ) { fprintf ( stderr , MsgWriteError , MsgStdout ) ; return 1 ; } return 0 ; }