/* piro2.c - Don Yang (uguu.org) 04/08/01 */ #include #include #include #define DICTIONARY_SIZE 15 #define MAX_WORD_LENGTH 8 /* Custom character type */ typedef struct { int c; int ucase; int punct; } Character; /* Conversion dictionary (sort for greedy matching) */ static char *Dictionary[DICTIONARY_SIZE][2] = { {"computer", "box"}, {"dude", "d00d"}, {"elite", "l33t"}, {"you.", "j00."}, {"the.", "da."}, {"il", "i1"}, {"li", "1i"}, {"s.", "z."}, {"a", "4"}, {"e", "3"}, {"i", "1"}, {"l", "1"}, {"o", "0"}, {"s", "5"}, {"t", "7"} }; /* Globals */ static Character Stack[MAX_WORD_LENGTH + 1]; static Character Buffer[MAX_WORD_LENGTH + 1]; static int BufSize, StackSize, EndOfFile, d; /* Prototypes */ static int Compare(void); static void Convert(Character *dst, int src); static int ExactMatch(void); static void NextChar(void); static void Output(char *str, Character *ref, int length); /******************************************************************** main */ int main(void) { int index, i; /* Process input until file/buffer/stack is completely read */ StackSize = BufSize = EndOfFile = 0; for(NextChar(); BufSize++ || StackSize || !EndOfFile; NextChar()) { for(d = i = 0; d < DICTIONARY_SIZE; d++) { if( Compare() ) { i++; index = d; } } if( i == 1 ) { /* Exactly one match in dictionary */ if( strlen(Dictionary[index][0]) == (size_t)BufSize ) { /* Print when complete entry matched */ Output(Dictionary[index][1], Buffer, BufSize); BufSize = 0; } } else if( !i ) { /* Nothing matched, try push back extra characters */ while( BufSize > 1 ) { Stack[StackSize].c = Buffer[--BufSize].c; Stack[StackSize].ucase = Buffer[BufSize].ucase; Stack[StackSize++].punct = Buffer[BufSize].punct; if( (index = ExactMatch()) > -1 ) { Output(Dictionary[index][1], Buffer, BufSize); BufSize = 0; break; } } /* Do no push back first character to prevent infinite loop */ if( BufSize == 1 ) { if( (index = ExactMatch()) > -1 ) { Output(Dictionary[index][1], Buffer, BufSize); } else if( Buffer[0].c != EOF ) { if( Buffer[0].punct ) putchar(Buffer[0].punct); else putchar( Buffer[0].ucase ? toupper(Buffer[0].c) : Buffer[0].c); } BufSize = 0; } } } /* End */ return 0; } /* main() */ /******************************************************************* Compare Compare strings. */ static int Compare(void) { Character c; int i; for(i = 0; i < BufSize; i++) { Convert(&c, Dictionary[d][0][i]); if( !Dictionary[d][0][i] || Buffer[i].c != c.c ) return 0; } return 1; } /* Compare() */ /******************************************************************* Convert Convert ASCII character to internal character. */ static void Convert(Character *dst, int src) { if( !isalpha(src) ) { dst->c = '.'; dst->ucase = 0; dst->punct = src; if( src == EOF ) EndOfFile = 1; } else { dst->c = tolower(src); dst->ucase = isupper(src); dst->punct = 0; } } /* Convert() */ /**************************************************************** ExactMatch find exact match in dictionary, return dictionary index. */ static int ExactMatch(void) { for(d = 0; d < DICTIONARY_SIZE; d++) { if( strlen(Dictionary[d][0]) == (size_t)BufSize && Compare() ) return d; } return -1; } /* ExactMatch() */ /****************************************************************** NextChar Get next character. */ static void NextChar(void) { if( StackSize ) { Buffer[BufSize].c = Stack[--StackSize].c; Buffer[BufSize].ucase = Stack[StackSize].ucase; Buffer[BufSize].punct = Stack[StackSize].punct; } else { Convert(&Buffer[BufSize], EndOfFile ? EOF : getchar()); } } /* NextChar() */ /******************************************************************** Output Output string, preserving case and punctuation. */ static void Output(char *str, Character *ref, int length) { int i, u; /* Write first character */ if( ref[0].punct ) putchar(ref[0].punct); else putchar(ref[0].ucase ? toupper(str[0]) : str[0]); /* Write remaining characters */ if( strlen(str) > 1 ) { u = ref[1].ucase; for(i = 1; i < strlen(str) - 1; i++) putchar(u ? toupper(str[i]) : str[i]); if( ref[length - 1].punct ) putchar(ref[length - 1].punct); else putchar(u ? toupper(str[strlen(str) - 1]) : str[strlen(str) - 1]); } } /* Output() */