windows-nt/Source/XPSP1/NT/base/crts/libw32/tools/source/detab.c
2020-09-26 16:20:57 +08:00

183 lines
4 KiB
C

/*
** 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 <fcntl.h>
#include <io.h>
#include <stdio.h>
#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 [ ] = "<stdin>" ;
static char MsgStdout [ ] = "<stdout>" ;
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 ;
}