/* Translator Version 2 *//* Brian Bates 2005 *//* Includes */#include <stdio.h>#include <stdlib.h>#include <string.h>/* Defines */#define RULE_LENGTH 64#define PATH_LENGTH 128/* Structures *//* The Rule, which has a find and a replace */struct rule{ char find[RULE_LENGTH]; char replace[RULE_LENGTH]; struct rule *next;};typedef struct rule rule;/* Function Prototypes *//* Input Functions */int GetString( char *s, int delimiter );/* Rule Reading functions *//* Creates a list of rules and returns the number of rules read */int CreateRules( FILE *file, rule **list );/* Find the next rule from the file */int FindRule( FILE *file, char *find, char *replace );/* Fill a string with a certain value */void FillString( char *string, int size, char value );/* Copies two strings of the same size */void CopyString( char *original, char *new, int size );/* Read up to a specific character */int ReadUpTo( FILE *file, char c );/* Read from a file - returns the amount of characters read */int Read( FILE *file, char *string, int delimiter );/* Get a part of the rule */int GetRulePart( FILE *file, char *string );/* Translation functions *//* Translate the input file to a temporary file */void Translate( rule *rules, FILE *input, FILE *output );/* Get the next character from the buffer *//* Returns the 'falloff' character */int GetNext( FILE *file, char *Buffer );/* Flip an array, ignoring zeros */void Flip( char *array, int size );/* See if there is a match between the buffer and the find string *//* Returns the position in the buffer where the match starts */int IsMatch( char *find, char *buffer );/* Clean out and shift a certain part of the buffer *//* Works backwards */void CleanBuffer( char *buffer, int start, int length );/* Write a string to file, returns chracters written */int WriteToFile( FILE *file, char *string );/* Output Functions *//* Copy the contents of one file to another */int CopyFile( char *input, char *output );/* Print the rules to the screen */void PrintRules( rule *rules );/* MAIN */int main( void ){ /* Declare Variables */ rule *rules = 0; /* The list of rules */ /* The file path arrays */ char ci[PATH_LENGTH] = {0}, ct[PATH_LENGTH] = {0}, co[PATH_LENGTH] = {0}; /* The file pointers */ FILE *input = 0, *output = 0, *translation = 0; int r = 0; /* The number of rules read */ /* Get input from the user */ printf( "Enter the path of the input file: " ); GetString( ci, '\n' ); printf( "Enter the path of the translation file: " ); GetString( ct, '\n' ); printf( "Enter the path of the output file: " ); GetString( co, '\n' ); /* Create a linked list of rules from the translation file */ printf( "Reading rules...\n" ); /* Open the translation file */ if( (translation = fopen( ct, "r" )) == NULL ) { printf( "The translation file could not be opened.\n" ); return -1; } /* Create the list */ /* If no rules were read, generate an error */ if( (r = CreateRules( translation, &rules )) == 0 ) { printf( "No Rules were read. Aborting.\n" ); return -1; } /* Print the number of rules read */ printf( "%d Rules read.\n", r ); /* Close the translation file */ fclose( translation ); PrintRules( rules ); /* Read through the input file and do the translation */ printf( "Translating the input file...\n" ); /* Open the input file and a temporary output file */ if( (input = fopen( ci, "r" )) == NULL ) { printf( "The input file could not be opened.\n" ); return -1; } if( (output = fopen( "temp.txt", "w" )) == NULL ) { printf( "A necessary temporary file could not be created.\n" ); return -1; } /* Do the actual translation */ Translate( rules, input, output ); /* Close the input and temp files */ fclose( input ); fclose( output ); /* Copy the output file */ if( CopyFile( "temp.txt", co ) == -1 ) { printf( "Could not create the output file.\n" ); return -1; } /* Return Normal */ printf( "Done.\n" ); getchar(); return 0;}int GetString( char *s, int delimiter ){ int i = 0, c = 0; while( (c = getchar()) != delimiter ) s[i++] = c; return i;}/* Rule Creation */int CreateRules( FILE *file, rule **list ){ /* Declare Variables */ rule **new = list; /* The New rule to be made */ int n = 0; /* the number of rules read */ /* Temporary information holding strings */ char find[RULE_LENGTH] = {0}, replace[RULE_LENGTH] = {0}; /* Create a loop */ while( FindRule( file, find, replace ) != EOF ) { /* Create the structure and fill it */ *new = malloc( sizeof(rule) ); CopyString( find, (*new)->find, RULE_LENGTH ); CopyString( replace, (*new)->replace, RULE_LENGTH ); (*new)->next = 0; /* Set the new new */ new = &((*new)->next); /* Increment the number of rules read */ n++; /* Clear the find and replace strings for the next rule */ FillString( find, RULE_LENGTH, 0 ); FillString( replace, RULE_LENGTH, 0 ); } return n;}int FindRule( FILE *file, char *find, char *replace ){ /* Read until the first semicolon is found */ if( ReadUpTo( file, ':' ) == EOF ) return EOF; /* Reading Rules: /: becomes : // becomes / if its right before the ending colon */ /* Get the two rule parts: find and replace */ if( GetRulePart( file, find ) == EOF ) return EOF; if( GetRulePart( file, replace ) == EOF ) return EOF; /* Return Normal */ return 0;}void FillString( char *string, int size, char value ){ int i; for( i = 0; i < size; ++i ) string[i] = value;}void CopyString( char *original, char *new, int size ){ int i; for( i = 0; i < size; ++i ) new[i] = original[i];}int ReadUpTo( FILE *file, char c ){ int i = 0; while( (i = getc(file)) != EOF ) if( i == c ) return 0; return EOF;}int Read( FILE *file, char *string, int delimiter ){ int i = 0, c = 0; while( (c = getc(file)) != EOF ) if( c != delimiter ) string[i++] = c; else return i; return EOF;}int GetRulePart( FILE *file, char *string ){ int i = 0, j = 0; while( (j = Read( file, &string[i], ':' )) != EOF ) { i += j; /* Only check if at least one character was read */ if( i > 0 ) { /* See if the last character read was a slash */ if( string[i-1] == '/' ) { if( i > 1 ) { /* If the one behind the slash was another slash, make it into one slash and return */ if( string[i-2] == '/' ) { string[i-1] = '\0'; break; } } /* Add a colon and go again */ string[i-1] = ':'; } else break; } else break; } if( j == EOF ) return EOF; return 0;}/* Translation*/void Translate( rule *rules, FILE *input, FILE *output ){ int c = 0, i = 0, j = 0; char Buffer[RULE_LENGTH] = {0}; rule *curr = rules; while( Buffer[0] != EOF ) { /* Set the rules to the beginning */ curr = rules; /* If the falloff character is not 0, put it in the file */ if( (c = GetNext( input, Buffer )) != 0 ) putc( c, output ); /* Loop through all of the rules */ while( curr != NULL ) { /* See if there is a match between the buffer and the find */ if( (i = IsMatch( curr->find, Buffer )) >= 0 ) { /* Write everything in the buffer above i */ for( j = RULE_LENGTH-1; j > i; --j ) if( Buffer[j] != 0 ) putc( Buffer[j], output ); /* Write the replace string to the file */ WriteToFile( output, curr->replace ); /* Clear the buffer */ FillString( Buffer, RULE_LENGTH, 0 ); /* Break */ break; } /* Increment the rule list */ curr = curr->next; } } /* Set Buffer 0 to 0 (not EOF), flip it, and write it to the file */ Buffer[0] = '\0'; Flip( Buffer, RULE_LENGTH ); WriteToFile( output, Buffer );}int GetNext( FILE *file, char *Buffer ){ int i = 0, c = Buffer[RULE_LENGTH-1]; /* Shift the buffer */ for( i = RULE_LENGTH-1; i > 0; --i ) Buffer[i] = Buffer[i-1]; /* Read in the new character */ Buffer[0] = getc(file); /* Return the falloff character */ return c;}void Flip( char *array, int size ){ /* Declare variables */ int i = 0, j = 0; char *temp = 0; /* Allocate memory for temp */ temp = calloc( size, sizeof(char) ); /* Loop */ for( i = size-1; i >= 0; --i ) if( array[i] != 0 ) temp[j++] = array[i]; /* Set the temp to the array */ CopyString( temp, array, size ); /* Free the memory */ free( temp );}int IsMatch( char *find, char *buffer ){ /* Declare variables */ int i = 0, j= 0, c = 0; /* Loop thorugh the entire buffer */ for( i = RULE_LENGTH-1; i >= 0; --i ) { c = i; j = 0; /* Loop through all the characters in the find string */ while( find[j] != '\0' ) { /* If there is no match, break */ if( find[j] != buffer[c] ) break; /* Else try the next letter */ else if( (--c >= 0) || find[j+1] == '\0' ) j++; else break; } /* Find is inside, starting at i, if we are at the end of the find string */ if( find[j] == '\0' ) return i; } /* Return -1, not found */ return -1;}void CleanBuffer( char *buffer, int start, int length ){ int i = 0, j = 0, end = start-length; char temp[RULE_LENGTH] = {0}; /* First, zero out the part to be replaced */ for( i = start; i > end; --i ) buffer[i] = 0; /* Now, Loop through and copy non zero characters */ for( i = 0; i < RULE_LENGTH; i++ ) if( buffer[i] != 0 ) temp[j++] = buffer[i]; /* Copy temp to the buffer */ CopyString( temp, buffer, RULE_LENGTH );}int WriteToFile( FILE *file, char *string ){ int i = 0; while( string[i] != '\0' ) putc( string[i++], file ); return i;}int CopyFile( char *input, char *output ){ FILE *i = 0, *o = 0; int c = 0; /* Open the files */ if( (i = fopen( input, "r" )) == NULL ) return -1; if( (o = fopen( output, "w" )) == NULL ){ fclose(i); return -1; } /* Copy */ while( (c = getc(i)) != EOF ) putc( c, o ); /* Close the files */ fclose(i); fclose(o); /* Return Normal */ return 0;}void PrintRules( rule *rules ){ while( rules != 0 ) { printf( "Find: %s\nReplace: %s\n", rules->find, rules->replace ); rules = rules->next; }}