Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

564 lines
22 KiB

//
//
// BUGBUG!!!!
//
// This file makes several calls to StrCmpN functions in comctl32.
// The StrCmpN functions are broken! They do not return the correct
// international ordering for strings because they do a character by
// character comparison of the two strings. Luckily, the functions
// in this file are just building a sorted search tree and appear to
// always use the same functions for building and searching; therefore,
// this code should work as is.
//
//
extern INT StrCmpNIA(LPSTR lptr1, LPSTR lpWStr2, INT nChar);
extern INT StrCmpNA(LPCSTR lptr1, LPCSTR lpWStr2, INT nChar);
/**********************************************************************
// Grepstrs
//
// Copyright (c) 1992 - Microsoft Corp.
// All rights reserved.
// Microsoft Confidential
//
//
// String search functions which duplciate those in QSUB.ASM.
//
**********************************************************************/
#include "shellprv.h"
#pragma hdrstop
#pragma warning( disable:4001 ) // Disable new type remark warning
// *********************************************************************
// String table
static int toklen[] = // Table of token lengths
{
32767, // T_END: invalid
32767, // T_STRING: invalid
2, // T_SINGLE
ASCII_LEN / 8+1, // T_CLASS
1, // T_ANY
32767 // T_STAR: invalid
};
// *********************************************************************
// Local function prototypes
// *********************************************************************
LPSTR findsub( LPGREPINFO, LPSTR , LPSTR ); // Findlist() worker
LPSTR findsubi( LPGREPINFO, LPSTR , LPSTR ); // Findlist() worker
#pragma data_seg(".text", "CODE")
LPSTR (*flworker[])( LPGREPINFO, LPSTR , LPSTR ) = { findsubi, findsub };
#pragma data_seg()
// *********************************************************************
// void matchstrings( LPSTR s1, LPSTR s2, int len, int *nmatched, int *leg)
//
// ARGUMENTS:
// s1 - First string
// s2 - Second string
// len - Length
// nmatched - Number of bytes matched
// leg - Less than, equal, greater than
// *********************************************************************
void matchstrings( LPGREPINFO lpgi, LPSTR s1, LPSTR s2, int len, int *nmatched, int *leg)
{
register LPSTR cp; // Char pointer
// Comparison function pointer
register int (*cmp)( LPCSTR , LPCSTR , int);
cmp = (lpgi->CaseSen ? StrCmpNA : StrCmpNIA); // Set pointer
// If strings don't match
if ( (*leg = (*cmp)(s1, s2, (unsigned)len)) != 0 )
{
// Find mismatch
for ( cp = s1; (*cmp)( cp, s2++, 1 ) == 0; cp++ )
;
*nmatched = cp - s1; // Return number matched
}
else
*nmatched = len; // Else all matched
}
// *********************************************************************
// int preveol( LPSTR s )
//
// ARGUMENTS:
// s - String to search
// *********************************************************************
int preveol( LPSTR s )
{
register LPSTR cp; // Char pointer
cp = s + 1; // Initialize pointer
while ( *(--cp) != '\n' ) // Find previous end-of-line
;
return( (s - cp) ); // Return distance to match
}
// *********************************************************************
// int countlines( register LPSTR start, LPSTR finish )
//
// ARGUMENTS:
// start - Start of buffer
// finish - End of buffer
// *********************************************************************
int countlines( register LPSTR start, LPSTR finish )
{
register int count; // Line count
for ( count = 0; start < finish; )
{ // Loop to count lines
if ( *(start++) == '\n' )
count++; // Increment count if linefeed found
}
return( count ); // Return count
}
// *********************************************************************
// Scans a buffer for the first character which does not match
// one of the characters in a specified list.
//
// int strnspn( LPSTR s, LPSTR t, int n)
//
// ARGUMENTS:
// s - String to search
// t - Target list
// n - Length of s
// *********************************************************************
int strnspn( LPSTR s, LPSTR t, int n)
{
LPSTR s1; // String pointer
LPSTR t1; // String pointer
for ( s1 = s; n-- != 0; s1++ ) // While not at end of s
{
for ( t1 = t; *t1 != '\0'; t1++ ) // While not at end of t
{
if ( *s1 == *t1 )
break; // Break if match found
}
if ( *t1 == '\0' )
break; // Break if no match found
}
return( s1 - s ); // Return length
}
// *********************************************************************
// Scans a buffer for the first character which matches a character
// from a specified list of characters
//
// int strncspn( LPSTR s, LPSTR t, int n )
//
// ARGUMENTS:
// s - String to search
// t - Target list
// n - Length of s
// *********************************************************************
int strncspn( LPSTR s, LPSTR t, int n )
{
LPSTR s1; // String pointer
LPSTR t1; // String pointer
for ( s1 = s; n-- != 0; s1++ ) // While not at end of s
{
for ( t1 = t; *t1 != '\0'; t1++ ) // While not at end of t
{
if ( *s1 == *t1 )
return( s1 - s ); // Return if match found
}
}
return( s1 - s ); // Return length
}
// *************************************************************************
// *********************************************************************
//
// This is an implementation of the QuickSearch algorith described
// by Daniel M. Sunday in the August 1990 issue of CACM. The TD1
// table is computed before this routine is called.
//
// LPSTR findone( LPGREPINFO lpgi, LPSTR buffer, LPSTR bufend )
//
// ARGUMENTS:
// buffer - Buffer in which to search
// bufend - End of buffer
// *********************************************************************
LPSTR findone( LPGREPINFO lpgi, LPSTR buffer, LPSTR bufend )
{
if ( (bufend -= lpgi->ge.TargetLen - 1) <= buffer )
return( (LPSTR )0 ); // Fail if buffer too small
while ( buffer < bufend )
{ // While space remains
int cch; // Character count
register LPSTR pch1; // Char pointer
register LPSTR pch2; // Char pointer
pch1 = lpgi->Target; // Point at pattern
pch2 = buffer; // Point at buffer
// Loop to try match
for ( cch = lpgi->ge.TargetLen; cch > 0; cch-- )
{
if ( *(pch1++) != *(pch2++) )
break; // Exit loop on mismatch
}
if ( cch == 0 )
return( buffer ); // Return pointer to match
buffer += lpgi->ge.td1[ (unsigned char)(buffer[ lpgi->ge.TargetLen ]) ]; // Skip ahead
}
return( NULL ); // No match
}
// *********************************************************************
// LPSTR findlist( LPSTR buffer, LPSTR bufend )
//
// ARGUMENTS:
// buffer - Buffer to search
// bufend - End of buffer
// *********************************************************************
LPSTR findlist( LPGREPINFO lpgi, LPSTR buffer, LPSTR bufend )
{
LPSTR szMatch; // Pointer to matching string
char endbyte; // First byte past end
endbyte = *bufend; // Save byte
*bufend = '\177'; // Mark end of buffer
// Call worker
szMatch = (*flworker[ lpgi->CaseSen ])( lpgi, buffer, bufend );
*bufend = endbyte; // Restore end of buffer
return( szMatch ); // Return matching string
}
// *********************************************************************
// LPSTR findsub( register LPSTR buffer, LPSTR bufend)
//
// ARGUMENTS:
// buffer - Pointer to buffer
// bufend - End of buffer
// *********************************************************************
LPSTR findsub( LPGREPINFO lpgi, register LPSTR buffer, LPSTR bufend)
{
register LPSTR cp; // Char pointer
STRINGNODE *s; // String node pointer
int i; // Index
if ( lpgi->ge.ShortStrLen == -1 ||
(bufend - buffer) < lpgi->ge.ShortStrLen )
return( NULL );
bufend -= (lpgi->ge.ShortStrLen - 1); // Compute effective buffer length
while( buffer < bufend ) // Loop to find match
{
if ( (i = lpgi->ge.TransTable[ (unsigned char)*buffer ]) != 0 )
{ // If valid first character
if ( (s = lpgi->ge.StringList[ i ]) == NULL )
return (buffer); // Check for 1-byte match
for ( cp = buffer + 1;; ) // Loop to search list
{
if ( (i = _fmemcmp( cp, s_text( s ), (unsigned)s->s_must)) == 0 )
{ // If portions match
cp += s->s_must; // Skip matching portion
if ( (s = s->s_suf) == NULL )
return( buffer ); // Return match if end of list
continue; // Else continue
}
if ( i < 0 || (s = s->s_alt) == NULL )
break; // Break if not in this list
}
}
// Shift as much as possible
buffer += lpgi->ge.td1[ (unsigned char)(buffer[ lpgi->ge.ShortStrLen ]) ];
}
return( NULL ); // No match
}
// *********************************************************************
// LPSTR findsubi( LPGREPINFO lpgi, register LPSTR buffer, LPSTR bufend)
//
// ARGUMENTS:
// buffer - Pointer to buffer
// bufend - End of buffer
// *********************************************************************
LPSTR findsubi( LPGREPINFO lpgi, register LPSTR buffer, LPSTR bufend)
{
register LPSTR cp; // Char pointer
STRINGNODE *s; // String node pointer
int i; // Index
int iTail;
if ( lpgi->ge.ShortStrLen == -1 ||
(bufend - buffer) < lpgi->ge.ShortStrLen )
return( NULL );
bufend -= (lpgi->ge.ShortStrLen - 1); // Compute effective buffer length
while ( buffer < bufend ) // Loop to find match
{
if ( (i = lpgi->ge.TransTable[ (unsigned char)*buffer ]) != 0 )
{ // If valid first character
if ( (s = lpgi->ge.StringList[ i ]) == NULL )
return( buffer ); // Check for 1-byte match
for ( cp = buffer + 1;; ) // Loop to search list
{
iTail = 0;
if ( IsDBCSLeadByte( *buffer ) )
{
if ( *cp == *s_text( s ) )
iTail = 1;
else
break;
}
if ( s->s_must - iTail == 0 ||
(i = StrCmpNIA( cp + iTail, s_text( s ) + iTail, (unsigned)s->s_must - iTail)) == 0 )
{ // If portions match
cp += s->s_must; // Skip matching portion
if ( (s = s->s_suf) == NULL )
return( buffer ); // Return match if end of list
continue; // And continue
}
if ( i < 0 || (s = s->s_alt) == 0 )
break; // Break if not in this list
}
}
// Shift as much as possible
buffer += lpgi->ge.td1[ (unsigned char)(buffer[ lpgi->ge.ShortStrLen ]) ];
}
return( NULL ); // No match
}
// *********************************************************************
// LPSTR findexpr( register LPSTR buffer, LPSTR bufend )
//
// ARGUMENTS:
// buffer - Buffer in which to search
// bufend - End of buffer
// *********************************************************************
LPSTR findexpr( LPGREPINFO lpgi, register LPSTR buffer, LPSTR bufend )
{
register EXPR *expr; // Expression list pointer
register LPSTR pattern; // Pattern
int i; // Index
while ( buffer < bufend ) // Loop to find match
{
if ( (i = lpgi->ge.TransTable[ (unsigned char)*(buffer++) ]) == 0 )
continue; // Continue if not valid 1st char
expr = (EXPR *)((LPSTR )lpgi->ge.StringList[ i ] );
#ifndef NDEBUG
Assert( expr != NULL );
#endif
buffer--; // Back up to first character
while ( expr != NULL ) // Loop to find match
{
pattern = expr->ex_pattern; // Point to pattern
expr = expr->ex_next; // Point to next record
if (pattern[ 0 ] == '^') // If match begin line
{
pattern++; // Skip caret
if ( buffer[ -1 ] != '\n' )
continue; // Don't bother if not at beginning
}
if ( exprmatch(lpgi, buffer, pattern) ) // Return pointer if match found
return( buffer );
}
buffer++; // Skip first character
}
return( NULL ); // No match
}
// *********************************************************************
// int ncmpi( const LPSTR sany,
// const LPSTR supper,
// int n )
//
// ARGUMENTS:
// sany - String whose case is unknown
// supper - Upper case string
// n - Number of characters to compare
// *********************************************************************
int ncmpi( LPCTSTR sany, LPCTSTR supper, unsigned n )
{
int i; // Difference
while ( n-- > 0 ) // While not at end of strings
{
if ( (i = LOWORD((DWORD)CharUpperA( (LPSTR)(DWORD)*sany ) - *(supper++) ))
!= 0 )
return( i ); // Return difference if mismatch
if ( *sany++ == '\0' )
break; // Break if end of string reached
}
return( 0 ); // Strings match
}
// *********************************************************************
// LPSTR simpleprefix( LPGREPINFO lpgi, register LPSTR s, LPSTR *pp )
//
// ARGUMENTS:
// s - String pointer
// pp - Pointer to pattern pointer
// *********************************************************************
LPSTR simpleprefix( LPGREPINFO lpgi, register LPSTR s, LPSTR *pp )
{
register LPSTR p; // Simple pattern pointer
register int c; // Single character
p = *pp; // Initialize
while ( *p != T_END && *p != T_STAR ) // While not at end of pattern
{
switch( *(p++) ) // Switch on token type
{
case T_STRING: // String to compare
if ( (*lpgi->ncmp)( s, p + 1, (unsigned)((int)*p) ) != 0 )
return( NULL ); // Fail if mismatch found
s += *p; // Skip matched portion
p += *p + 1; // Skip to next token
break;
case T_SINGLE: // Single character
c = *s++; // Get character
if ( !lpgi->CaseSen )
c = LOWORD((DWORD)CharUpperA( (LPSTR)(DWORD)c )); // Map to upper case if necessary
if ( c != *p++ )
return( NULL ); // Fail if mismatch found
break;
case T_CLASS: // Class of characters
if ( !(p[ *((LPBYTE )s) >> 3] & ( 1 << (*((LPBYTE )s) &7))))
return( NULL ); // Failure if bit not set
p += ASCII_LEN / 8; // Skip bit vector
s++; // Skip character
break;
case T_ANY: // Any character
if ( *s++ == EOS )
return( NULL ); // Match all but end of string
break;
default:
break;
}
}
*pp = p; // Update pointer
return( s ); // Pattern is prefix of s
}
// *********************************************************************
// int exprmatch( LPGREPINFO lpgi, LPSTR s, LPSTR p)
//
// ARGUMENTS:
// s - String
// p - Pattern
// *********************************************************************
int exprmatch( LPGREPINFO lpgi, LPSTR s, LPSTR p )
{
lpgi->ncmp = StrCmpNA; // Assume case-sensitive
if( !lpgi->CaseSen )
lpgi->ncmp = StrCmpNIA; // Be case-insensitive if flag set
return( match( lpgi, s, p ) ); // See if pattern matches string
}
// *********************************************************************
//
//
// int match( register LPSTR pStr, LPSTR pPattern )
//
// ARGUMENTS:
// pStr - String to match
// pPattern - Pattern to match against
//
// *********************************************************************
int match( LPGREPINFO lpgi, register LPSTR pStr, LPSTR pPattern )
{
register LPSTR pTmp1; // Temporary pointer
LPSTR pTmp2; // Temporary pointer
register int iChar; // Character
if ( *pPattern != T_END && *pPattern != T_STAR &&
(pStr = simpleprefix( lpgi, pStr, &pPattern )) == NULL )
return ( 0 ); // Failure if prefix mismatch
if ( *pPattern++ == T_END )
return( 1 ); // Match if end of pattern
pTmp1 = pTmp2 = pPattern; // Point to repeated token
pTmp2 += toklen[ *((LPBYTE )pTmp1) ]; // Skip repeated token
switch( *pTmp1++ ) // Switch on token type
{
case T_ANY: // Any character
// While match not found
while ( exprmatch( lpgi, pStr, pTmp2 ) == 0 )
if ( *pStr++ == EOS)
return( 0 ); // Match all but end of string
return( 1); // Success
case T_SINGLE: // Single character
while ( exprmatch( lpgi, pStr, pTmp2 ) == 0 ) // While match not found
{
iChar = *pStr++; // Get character
if ( !lpgi->CaseSen )
iChar = LOWORD((DWORD)CharUpperA( (LPSTR)(DWORD)iChar )); // Map to upper case if necessary
if ( (char) iChar != *pTmp1 )
return( 0); // Fail if mismatch found
}
return( 1 ); // Success
case T_CLASS: // Class of characters
while ( exprmatch( lpgi, pStr, pTmp2 ) == 0 ) // While match not found
{
if (!(pTmp1[ *((LPBYTE )pStr)>>3 ] &
(1 << (*((LPBYTE )pStr) & 7))) )
return( 0 ); // Fail if bit not set
pStr++; // Else skip character
}
return( 1 ); // Success
default:
break;
}
return( 0 ); // Return failure
}