#include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include "define.h" #include "struct.h" #include "unistd.h" char* empty_string = (char*) "\0"; /* * STRING COMPARISON */ inline bool null_strings( const char* astr, const char* bstr ) { if( astr != NULL && bstr != NULL ) return FALSE; if( astr == NULL && bstr == NULL ) bug( "Str*cmp: Null string (x2)." ); else bug( "Str*cmp: Comparing '%s' to null.", astr == NULL ? bstr : astr ); return TRUE; } int strcasecmp( const char* astr, const char* bstr ) { if( astr == bstr ) return 0; if( null_strings( astr, bstr ) ) return 1; for( ; *astr != '\0' || *bstr != '\0'; astr++, bstr++ ) if( tolower( *astr ) != tolower( *bstr ) ) return( tolower( *astr ) > tolower( *bstr ) ? 1 : -1 ); return 0; } int strncasecmp( const char* astr, const char* bstr, int n ) { const char* end; if( null_strings( astr, bstr ) ) return 1; end = astr+n; for( ; astr < end && ( *astr != '\0' || *bstr != '\0' ); astr++, bstr++ ) if( tolower( *astr ) != tolower( *bstr ) ) return( tolower( *astr ) > tolower( *bstr ) ? 1 : -1 ); return 0; } int strncmp( const char* astr, const char* bstr, int n ) { const char* end; if( null_strings( astr, bstr ) ) return 1; end = astr+n; for( ; astr < end && ( *astr != '\0' || *bstr != '\0' ); astr++, bstr++ ) if( *astr != *bstr ) return( *astr > *bstr ? 1 : -1 ); return 0; } char* strcat( char* dst, const char* src ) { char* s; for( s = dst; *s != '\0'; s++ ); for( ; *src != '\0'; ) *s++ = *src++; *s = '\0'; return dst; } int rstrcasecmp( const char* astr, const char* bstr ) { int a, b, c; int i; if( null_strings( astr, bstr ) ) return 1; a = strlen( astr ); b = strlen( bstr ); c = min( a, b ); for( i = 1; i <= c; i++ ) if( tolower( astr[a-i] ) != tolower( bstr[b-i] ) ) return( tolower( astr[a-i] ) > tolower( bstr[b-i] ) ? 1 : -1 ); return( a < b ? -1 : a > b ); } int rstrncasecmp( const char* astr, const char* bstr, int n ) { int a, b, c; int i; if( null_strings( astr, bstr ) ) return 1; a = strlen( astr ); b = strlen( bstr ); c = min( min( a, b ), n ); for( i = 1; i <= c; i++ ) if( tolower( astr[a-i] ) != tolower( bstr[b-i] ) ) return( tolower( astr[a-i] ) > tolower( bstr[b-i] ) ? 1 : -1 ); return( c == n ? 0 : a < b ); } /* * GENERIC UTILITY ROUTINES */ bool fmatches( const char* argument, const char* word, int length ) { int i; for( i = 0; argument[i] != '\0'; i++ ) if( tolower( word[i] ) != tolower( argument[i] ) ) return FALSE; return( i > length ); } bool matches( const char*& argument, const char* word ) { const char* str = argument; if( *str == '\0' ) return FALSE; for( ; *str != '\0' && *str != ' '; word++, str++ ) if( tolower( *word ) != tolower( *str ) ) return FALSE; skip_spaces( str ); argument = str; return TRUE; } bool exact_match( const char*& argument, const char* word ) { const char* str = argument; for( ; *word != '\0'; word++, str++ ) if( tolower( *word ) != tolower( *str ) ) return FALSE; if( *str != ' ' && *str != '\0' && *str != ',' && *str != ';' ) return FALSE; skip_spaces( str ); argument = str; return TRUE; } bool number_arg( const char*& argument, int& i ) { const char* str = argument; int j = 0; bool minus = FALSE; if( *str == '-' ) { minus = TRUE; str++; } else if( *str == '+' ) str++; for( ; ; ) { if( !isdigit( *str ) ) return FALSE; j = 10*j+(*str++)-'0'; if( *str == '\0' || *str == ' ' ) break; } argument = str; i = minus ? -j : j; skip_spaces( argument ); return TRUE; } /* * */ char* seperate( char* string, bool identified ) { int i; if( *string != '{' ) return string; for( i = 1; string[i] != '}' && string[i] != '\0'; i++ ); if( !identified ) { if( i == 1 ) return empty_string; char* tmp = static_string( ); memcpy( tmp, &string[1], i-1 ); tmp[i-1] = '\0'; return tmp; } if( string[i] == '\0' ) return empty_string; for( i++; string[i] == ' '; i++ ); return &string[i]; } char* one_condition( char *argument, char *cond ) { if( *argument == '\0' ) *cond = '\0'; else { for( ; *argument != '\n' && *argument != '\0' && *argument != '&'; argument++, cond++ ) *cond = *argument; *cond = '\0'; if( *argument == '&' ) argument += 2; if( *argument == '\n' ) { argument++; if( *argument == '\r' ) argument++; } } return argument; } /* * IS_NAME ROUTINE */ bool is_name( char* str, const char* namelist, bool command ) { char name [ MAX_INPUT_LENGTH ]; char word [ MAX_INPUT_LENGTH ]; const char* list; int length; int pos; for( ; ; ) { str = one_argument( str, word ); if( *word == '\0' ) return TRUE; list = namelist; length = 3; for( ; ; ) { list = one_argument( list, name ); if( *name == '\0' ) return FALSE; if( isdigit( *name ) ) { length = atoi( name ); continue; } if( strncasecmp( word, name, strlen( word ) ) ) { length = 3; continue; } if( command ) { pos = search( command_table, MAX_ENTRY_COMMAND, name ); if( pos >= 0 && command_table[pos].reqlen <= strlen( word ) ) break; } if( strlen( word ) >= min( length, strlen( name ) ) ) break; } } } int subset( const char* s1, const char* s2, bool cmd ) { int i = 100; for( ; *s1 != '\0'; ) { switch( member( s1, s2, cmd ) ) { case 0 : return 0; case 1 : i = 50; } for( ; *s1 != '\0' && *s1 != ' '; s1++ ); for( ; *s1 == ' '; s1++ ); } return( i-count( s2 ) ); } int member( const char* s1, const char* s2, bool cmd ) { int len = 3; int i = 0; skip_spaces( s2 ); if( *s1 == '\0' ) return( *s2 == '\0' ); for( ; *s2 != '\0'; ) { if( isdigit( *s2 ) ) { len = atoi( s2 ); } else { switch( compare( s1, s2, cmd, len ) ) { case 2 : return 2; case 1 : i = 1; } len = 3; } for( ; *s2 != '\0' && *s2 != ' '; s2++ ); for( ; *s2 == ' '; s2++ ); } return i; } int compare( const char* s1, const char* s2, bool cmd, int len ) { const char* s3 = s2; int pos; for( ; *s1 != ' ' && *s1 != '\0'; s1++, s2++ ) if( toupper( *s1 ) != toupper( *s2 ) ) return 0; if( cmd && ( pos = search( command_table, MAX_ENTRY_COMMAND, s3 ) ) > 0 ) { if( command_table[pos].reqlen > s2-s3 ) return 0; } else if( s2-s3 < len && *s2 != '\0' && *s2 != ' ' ) return 0; return( *s2 == ' ' || *s2 == '\0' ? 2 : 1 ); } /* * STRING TYPES */ bool is_number( char* arg ) { if( *arg == '\0' ) return FALSE; if( ( *arg == '+' ) || ( *arg == '-' ) ) arg++; for( ; *arg != '\0' && *arg != ' '; arg++ ) if( !isdigit( *arg ) ) return FALSE; return TRUE; } bool isperiod( char letter ) { switch( letter ) { case '.' : case '?' : case '!' : return TRUE; } return FALSE; } bool isvowel( char letter ) { switch( toupper( letter ) ) { case 'A' : case 'E' : case 'I' : case 'O' : case 'U' : return TRUE; } return FALSE; } /* * PARSE INPUT */ bool contains_word( const char*& argument, const char* word, char* arg ) { const char* s1 = argument; const char* s2; for( ; *s1 != '\0'; ) { if( exact_match( s2 = s1, word ) ) { for( ; s1 != argument && *(s1-1) == ' '; s1-- ); memcpy( arg, argument, s1-argument ); arg[s1-argument] = '\0'; argument = s2; return TRUE; } for( ; *s1 != '\0' && *s1 != ' '; s1++ ); for( ; *s1 == ' '; s1++ ); } return FALSE; } bool two_argument( const char*& argument, const char* word, char* arg ) { int i; if( ( i = count( argument ) ) < 2 ) return FALSE; if( i == 2 ) { argument = one_argument( argument, arg ); return TRUE; } return( contains_word( argument, word, arg ) && *argument != '\0' && *arg != '\0' ); } char* one_argument( const char* argument, char* arg_first ) { char cEnd; while( isspace( *argument ) ) argument++; cEnd = ' '; if( *argument == '\'' || *argument == '"' ) { cEnd = *argument++; if( *argument == ' ' || *argument == '\0' ) { argument--; cEnd = ' '; } } while( *argument != '\0' ) { if( *argument == cEnd ) { argument++; break; } *arg_first = *argument; arg_first++; argument++; } *arg_first = '\0'; while( isspace( *argument ) ) argument++; return (char*) argument; } int smash_argument( char* tmp, char* argument ) { int number = 0; skip_spaces( argument ); if( !strncasecmp( argument, "all", 3 ) ) { if( argument[3] == '\0' ) { *tmp = '\0'; return -1; } if( argument[3] == '*' || argument[3] == '.' ) { argument += 4; number = -1; } } if( number == 0 ) { if( !isdigit( *argument ) ) number = 1; else { for( ; *argument != '\0' && isdigit( *argument ); argument++ ) number = 10*number+*argument-'0'; if( *argument == '*' ) { number *= -1; argument++; } else if( *argument == '.' ) argument++; } } for( ; *argument != '\0'; argument++ ) *tmp++ = ( *argument == '.' ? ' ' : *argument ); *tmp = '\0'; return number; } /* * FORMATTING STRINGS */ char* capitalize( char* arg ) { char* letter; if( *arg != '' ) { *arg = toupper( *arg ); return arg; } for( letter = arg; *letter != '\0'; ) if( *letter++ == 'm' ) { *letter = toupper( *letter ); return arg; } bug( "Capitalize: Missing end of escape code?" ); bug( "-- arg = %s", arg ); return arg; } char* capitalize_words( const char* argument ) { char* tmp = static_string( ); int i; *tmp = toupper( *argument ); for( i = 1; argument[i] != '\0'; i++ ) tmp[i] = ( argument[i-1] == ' ' ? toupper( argument[i] ) : argument[i] ); tmp[i] = '\0'; return tmp; } void smash_spaces( char* tmp ) { int i; for( i = 0; i < strlen( tmp ); i++ ) if( tmp[i] == ' ' ) tmp[i] = '_'; return; } void add_spaces( char* tmp, int i ) { if( i < 0 ) { roach( "Add_Spaces: Number to add negative." ); return; } tmp += strlen( tmp ); for( ; i > 0; i-- ) *tmp++ = ' '; *tmp = '\0'; return; }