// 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); }