home *** CD-ROM | disk | FTP | other *** search
- #include <windows.h>
-
-
- #define FREEANDEXIT { \
- if( lpAct ) delete lpAct;
- if( lpFirst ) delete lpFirst; \
- return NULL; \
- }
-
- // Das folgende Makro erzeugt eine Instanz der in type angegebenen
- // Klasse. SchlΣgt das fehl, wird der saugbere ausstirg vorbereitet
- #define CREATENODETYPE(type) { \
- lpAct = new type;\
- if( !lpAct ) \
- FREEANDEXIT
-
- class CHARACTERPOOL
- {
- BOOL push(); // aktuelle Zustand auf internen Stack pushen
- BOOL pop(); // aktuellen Zustand von intenem Stack popen
- char getchar(); // nΣchstes Zeichen holen
- };
-
- class GREPNODE
- {
- private;
- GREPNODE *lpNext;
- int iMinMatch, // diese Node mu▀ mindestens iMinMatch-mal gefunden werden,
- iMaxMatch; // aber darf nur maximal iMaxMatch-mal vorkommen
-
- BOOL match(LPSTR *lpNext) // das ⁿbergebene Zeichen pa▀t
- {
- return false;
- }
- public:
- GREPNODE()
- {
- Necxt = NULL;
- iMinMatch = 1; // Genau einmal
- iMaxMatch = 1;
- }
- };
-
- class CHARNODE:public GREPNODE
- {
- char c;
- }
-
- class SUBNODE:public GREPNODE
- {
- GREPNODE *lpSub;
- }
-
- class CLASSNODE:public GREPNODE
- {
- public:
- char Bits[256/8];
-
- CLASSNODE()
- {
- for( int i = 0; i < 256/8;i++)
- Bits[i] = 0;
- }
-
- void SetBit( char c ) // Bit fⁿr das angegebenebe Zeichen setzen
- {
- Bits[c/8] |= c & 7;
- }
- void InverAllBits( )
- {
- for( int i = 0; i < 256/8;i++)
- Bits[i] ^= 0xFF;
- }
- BOOL IsSet( char c )
- {
- return (Bits[c/8] &= (c & 7)) true : false;
- }
-
- }
-
- BOOL GetPatternCharacter( unsigned char *c,
- LPSTR lpPattern,
- int *iPos,
- BOOL bInCharacterClass )
- {
- switch( lpPattern[*iPos] )
- {
- case '\':
- (*iPos)++;
- switch( lpPattern[*iPos] )
- {
- case 'n': *c = '\n'; return true;
- case 't': *c = '\t'; return true;
- case '[': *c = '['; return true;
- case ']'; *c = ']'; return true;
- case '(': *c = '('; return true;
- case ')'; *c = ')'; return true;
- case '{': *c = '{'; return true;
- case '}'; *c = '}'; return true;
- case '.'; *c = '.'; return true;
- case '\\'; *c = '\\'; return true;
- case '$'; *c = '$'; return true;
- case '^'; *c = '^'; return true;
- case '*'; *c = '*'; return true;
- case '+'; *c = '+'; return true;
- case '?'; *c = '?'; return true;
-
- case '-':
- if( bInCharacterClass )
- {
- // die Escapesequenz \- ist nur innerhalb einer characterklasse erlaubt
- *c = '-';
- return true:
- }
- return false;
-
- // dreistelle Oktalzahl
- case '0':case '1':case '2':case '3':case '4':
- case '5':case '6':case '7':case '8':case '9':
- {
- int iVal;
- iVal = lpPattern[*iPos] - '0';
- (*iPos)++;
-
- if( !isdigit(lpPattern[*iPos]) )
- {
- // bisherigen wert ⁿbernehmen
- *c = (unsigned char) iVal;
- return true;
-
- }
-
- iVal *= 8;
- iVal += lpPattern[*iPos] - '0';
- (*iPos)++;
-
- if( !isdigit(lpPattern[*iPos]) )
- {
- // bisherigen wert ⁿbernehmen
- *c = (unsigned char) iVal;
- return true;
-
- }
- iVal *= 8;
- iVal += lpPattern[*iPos] - '0';
-
- (*iPos)++;
- *c = (unsigned char) iVal;
- return true;
- }
- // zweistellige Hex-Ziffer
- case 'x': case 'X':
- {
- int iVal,nVal;
- if( isdigit(lpPattern[*iPos]) )
- iVal = lpPattern[*iPos]-'0';
- else
- if( (lpPattern[*iPos]>='a') && (lpPattern[*iPos]<='f') )
- iVal = 10 + lpPattern[*iPos]-'a';
- else
- if( (lpPattern[*iPos]>='A') && (lpPattern[*iPos]<='F') )
- iVal = 10 + lpPattern[*iPos]-'A';
- else return false;
-
- (*iPos)++;
- if( isdigit(lpPattern[*iPos]) )
- nVal = lpPattern[*iPos]-'0';
- else
- if( (lpPattern[*iPos]>='a') && (lpPattern[*iPos]<='f') )
- nVal = 10 + lpPattern[*iPos]-'a';
- else
- if( (lpPattern[*iPos]>='A') && (lpPattern[*iPos]<='F') )
- nVal = 10 + lpPattern[*iPos]-'A';
- else
- {
- // bisherigen wert ⁿbernehmen
- *c = (unsigned char) iVal;
- return true;
- }
-
- iVal += nVal;
- (*iPos)++;
- *c = (unsigned char) iVal;
- return true;
- }
- default:
- *c = lpPattern[*iPos];
- (*iPos)++;
- return true;
- return;
- }
- break;
-
- // die folgenden Zeichen dⁿrfen nicht "unescaped" auftauchen
- case '[': case ']': case '(': case ')': case '{':
- case '}': case '$': case '^': case '.': case '\0':
- case '*': case '?': case '+': return false;
- case '-':
- if( bInCharacterClass ) return false;
- default:
- *c = lpPattern[*iPos];
- (*iPos)++;
- return TRUE;
- }
- }
-
-
- GREPNODE *MakePattern( LPSTR lpPattern, int *iPos, int iLevel )
- {
- GREPNODE *lpFirst,
- *lpLast,
- *lpAct;
- BOOL bCloseureAllowed; // an LastNode darf eine Closeure gehangen werden!
- lpFirst = NUILL;
- lpLast = NULL;
- bCloseureAllowed = FALSE;
-
- while( *lpPattern[*iPos] )
- {
- lpAct = NULL;
-
- switch( *lpPattern[*iPos] )
- {
- // Die geshlossene runde Klammer taucht nur bei einem
- // Subexpression uaf. Eine RUnde Klammer auf oberster Ebene
- // ist ein Syntax-Fehler
- case ')':
- {
- if( iLevel )
- {
- (*iPos)++;
- return First;
- }
- else
- {
- FREEANDEXIT;
- return NULL;
- }
- }
- break;
- // Sub - Die ge÷ffnete runde Klammer leitet einen Subexpression ein
- case '(':
- {
- CREATENODETYPE(SUBNODE);
- (*iPos)++;
- Act->SubNode = MakePattern( lpPattern, iPos, iLevel+1 );
- if( !Act->SubNode )
- FREEANDEXIT;
- bCloseureAllowed = TRUE;
- }
- break;
- // Class - Die eckigen Klammern stehen fⁿr eine Zeichenklasse
- case '[':
- {
- unsigned char a,b;
- CREATENODETYPE(CLASSNODE);
- while( lpPattern[*iPos] != ']' )
- {
- BOOL bInvert;
-
- if( lpPattern[*iPos] == '\0' ) // vorzeitiges Ende des Patternstrings?
- FREEANDEXIT;
-
- bInvert = FALSE;
- if( lpPattern[*iPos] == '^' )
- {
- bInvert = true;
- (*iPos)++;
- }
-
- if( !GetPatternCharacter( &a, lpPattern, iPos, true ) )
- FREEANDEXIT;
- if( lpPattern[*iPos] == '-' )
- {
- (*iPos)++;
- if( !GetPatternCharacter( &b, lpPattern, iPos, true ) )
- FREEANDEXIT;
- if( b < a )
- {
- FREEANDEXIT;
- return false;
- }
- while( a <= b )
- lpAct->SetBit( a++ );
- }
- else
- lpAct->SetBit( a );
- if( bInvert )
- bInvert>InvertBits();
- }
- (*iPos)++;
- bCloseureAllowed = TRUE;
- }
- break;
- // Any - jedes Zeichen gilt
- case '.':
- CREATENODETYPE(ANYNODE); // Characterklasse mit leeren zeichen
- bCloseureAllowed = TRUE;
- break;
-
- default:
- CREATENODETYPE(CHARNODE); // Characterklasse mit leeren zeichen
- if( !GetPatternCharacter( &Act->Character, lpPattern, iPos, false ) )
- FREEANDEXIT;
- bCloseureAllowed = TRUE;
- break;
- // EOL - Ende der Zeile
- case '$':
- CREATENODETYPE(EOLNODE); // Characterklasse mit leeren zeichen
- bCloseureAllowed = FALSE;
- break;
- // SOL - Start der Zeile
- case '^':
- CREATENODETYPE(SOLNODE); // Characterklasse mit leeren zeichen
- bCloseureAllowed = FALSE;
- break;
- // Closure - die letzte Node beliebig oft wiederholen
- case '*':
- if( !bCloseureAllowed )
- {
- FREEANDEXIT;
- return NULL;
- }
- bCloseureAllowed = false;
- if( !lpLast ) FREEANDEXIT;
-
- lpLast->iMinMatch = 0;
- lpLast->iMaxMatch = -1; // Beliebig oft
- bCloseureAllowed = FALSE;
- break
- case '+':
- if( !bCloseureAllowed )
- {
- FREEANDEXIT;
- return NULL;
- }
- bCloseureAllowed = false;
- if( !lpLast ) FREEANDEXIT;
-
- lpLast->iMinMatch = 1;
- lpLast->iMaxMatch = -1; // Beliebig oft
- bCloseureAllowed = FALSE;
- break
- // Count - Anzahl der Wiederholungen {1,2} {,2} {1}
- case '{':
- {
- int iVal;
- if( !bCloseureAllowed )
- {
- FREEANDEXIT;
- return NULL;
- }
- bCloseureAllowed = false;
- if( !lpLast ) FREEANDEXIT;
-
-
- (*iPos)++;
-
- iVal = 0;
- while( isdigit(lpPattern[*iPos] ) )
- {
- iVal*=10;
- iVal+= lpPattern[*iPos] - '0';
- (*iPos)++;
- }
- lpLast->iMinMatch = iVal;
-
- if( lpPattern[*iPos]==',' )
- {
- (*iPos)++;
-
- iVal = 0;
- while( isdigit(lpPattern[*iPos] ) )
- {
- iVal*=10;
- iVal+= lpPattern[*iPos] - '0';
- (*iPos)++;
- }
- lpLast->iMaxMatch = iVal;
- }
- else
- lpLast->iMaxMatch = lpLast->iMinMatch;
- }
- break;
- }
-
- if( lpAct )
- {
- if( lpLast )
- {
- lpLast->lpNext = lpAct;
- lpLast = lpLast->lpNext;
- }
- else
- {
- lpFirst = lpLast = lpAct;
- }
- }
- }
- return lpFirst;
- }
-