// REMTAB.C
// Replaces tab characters with spaces in text files.
// Author: Peter Meyer
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <direct.h>
#define TRUE 1
#define FALSE 0
#define loop while(TRUE)
#define TAB 9
#define LINEFEED 10
#define SPACE 32
#define MAX_TAB_SIZE 8
#define MIN_TAB_SIZE 1
#define DEFAULT_TAB_SIZE 4
#define MAX_LINE_LENGTH 1023
int tab_size, num_tabs=0;
char *version = "1.1";
char line[MAX_LINE_LENGTH+1];
char tab_spaces[MAX_TAB_SIZE+1];
FILE *input_file, *output_file;
void read_command_line(int ac, char *argv[]);
void set_tab(void);
void open_files(char *argv[]);
int read_line(char *argv[]);
void write_line(char *argv[]);
void replace_tabs(void);
void terminate(char *argv[]);
/*-----------------------------*/
void main(int argc, char *argv[])
{
printf("\nREMTAB.EXE, Version %s, Copyright 1999 Hermetic Systems",version);
printf("\nThis program replaces tab characters with spaces in a text file.");
_getcwd(line,sizeof(line));
printf("\nCurrent directory is %s\n",line);
read_command_line(argc,argv);
set_tab();
open_files(argv);
loop
{
if ( !read_line(argv) )
terminate(argv);
replace_tabs();
write_line(argv);
}
}
/*----------------------------------------*/
void read_command_line(int ac, char *argv[])
{
if ( ac < 3 || ac > 4 )
{
printf("\nUse: REMTAB input_file output_file");
printf("\n or: REMTAB input_file output_file tab_size");
printf("\ntab_size defaults to 4 spaces.\n");
exit(0);
}
// fopen() does not check for inconsistent openings of same file.
if ( !strcmp(argv[1],argv[2]) )
{
printf("\nOutput file must be different from input file.\n");
exit(1);
}
tab_size = ( ac > 3 ? atoi(argv[3]) : DEFAULT_TAB_SIZE );
}
/*--------------*/
void set_tab(void)
{
int i;
if ( tab_size < MIN_TAB_SIZE || tab_size > MAX_TAB_SIZE )
{
printf("\nInvalid value %d for tab_size (must be in the range %u through %u).\n",
tab_size, MIN_TAB_SIZE, MAX_TAB_SIZE);
exit(2);
}
i = tab_size;
while ( --i >= 0 )
tab_spaces[i] = SPACE;
tab_spaces[tab_size] = 0;
}
/*-------------------------*/
void open_files(char *argv[])
{
if ( ( input_file = fopen(argv[1],"rt") ) == NULL )
{
printf("\nCannot open input file %s\n",argv[1]);
exit(3);
}
if ( ( output_file = fopen(argv[2],"wt") ) == NULL )
{
printf("\nCannot open output file %s\n",argv[2]);
fclose(input_file);
exit(4);
}
printf("\nInput file %s opened for reading.\n",argv[1]);
}
/*-----------------------*/
int read_line(char *argv[])
{
char *ptr;
// fgets() reads at most sizeof(line)-1 bytes
// and keeps the final LINEFEED if found.
if ( fgets(line,sizeof(line),input_file) == NULL )
return ( FALSE );
ptr = strchr(line,LINEFEED);
if ( ptr != NULL )
*ptr = 0; // Remove final line feed
return ( TRUE );
}
/*-------------------------*/
void write_line(char *argv[])
{
if ( fprintf(output_file,"%s\n",line) == EOF )
{
printf("\nError when writing to output file %s.\n",argv[2]);
exit(6);
}
}
// This replaces all occurrences of tab characters in line[]
// with the appropriate number of spaces
// (as long as there is sufficient space in line[]).
/*-------------------*/
void replace_tabs(void)
{
int i, num_spaces;
char *ptr1, *ptr2;
while ( ( ptr1 = strchr(line,TAB) ) != NULL )
{
num_tabs++;
num_spaces = tab_size - (ptr1-line)%tab_size;
if ( strlen(line) + num_spaces > sizeof(line) - 1 )
{
printf("\nExpanded line exceeds maximum length of %d characters.\n",sizeof(line)-1);
exit(7);
}
ptr2 = strchr(line,0) + 1;
while ( --ptr2 > ptr1 )
*(ptr2+num_spaces-1) = *ptr2;
for ( i=0; i<num_spaces; i++ )
*(ptr1+i) = SPACE;
}
}
/*------------------------*/
void terminate(char *argv[])
{
fclose(input_file);
fclose(output_file);
printf("\nOutput file %s written. ",argv[2]);
if ( !num_tabs )
printf("No tab characters found.\n");
else
printf("%d tab character%s replaced.\n",
num_tabs,(num_tabs>1?"s":""));
exit(0);
}