grepsrch.c
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 14k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. /**********************************************************************
  2. //  SEARCH.C
  3. //
  4. //      Copyright (c) 1992 - Microsoft Corp.
  5. //      All rights reserved.
  6. //      Microsoft Confidential
  7. //
  8. //  Entry point for string search criteria.
  9. //
  10. //  TABS = 3
  11. // johnhe - 04-26-92
  12. **********************************************************************/
  13. #include "shellprv.h"
  14. #pragma  hdrstop
  15. #pragma warning( disable:4001 )         // Disable new type remark warning
  16. //*********************************************************************
  17. //  Local function prototypes.
  18. //*********************************************************************
  19. void BldSearchLsts   ( LPGREPINFO lpgi, LPSTR pStrLst, LPSTR pNotList );
  20. static LPSTR s_pSrchStrLst = NULL;            // Ptr to normal search string list
  21. //*********************************************************************
  22. //  Builds allocates search buffers and builds search list trees.
  23. //
  24. //  The format of the pStrLst and pNotLst is multiple zero terminated
  25. //  strings with a zero length string marking the end of the list.
  26. //
  27. //  "string1",0,"string2",0,"string3",0,"...",0,0
  28. //
  29. //  int InitGrepInfo( LPSTR pStrLst, LPSTR pNotList, unsigned uOpts )
  30. //
  31. //  ARGUMENTS:
  32. //      pStrLst     - Ptr to list of string to try to match
  33. //      pNotLst     - Ptr to list of string which must not match
  34. //      uOpts           - Search options of FLG_REGULAR and FLG_CASE
  35. //  RETURNS:
  36. //      int         - OK is no errors else ERR_NOMEMORY, ERR_MEMCORUPT,
  37. //                        ERR_STRLST_LEN, or ERR_SRCH_EXPRESSION
  38. //
  39. //*********************************************************************
  40. LPGREPINFO InitGrepInfo( LPSTR pStrLst, LPSTR pNotList, unsigned uOpts )
  41. {
  42.     int     i;                                      // Loop indice
  43.     LPGREPINFO lpgi;
  44.             // Make sure there is at least one string to match in at least
  45.             // one of the search lists and set flag if no normal srch strings.
  46.     if ( pStrLst[ 0 ] == '' && pNotList[ 0 ] == '' )
  47.         return( OK );
  48.     s_pSrchStrLst = pStrLst;
  49.     if ( (lpgi = InitGrepBufs()) == NULL )
  50.         return( NULL );
  51.     if ( (uOpts & FLG_REGULAR) != FALSE )   // Use regular expression (/R) ?
  52.         lpgi->addstr = addexpr;                       // Then add expression to list
  53.     else
  54.         lpgi->addstr = addstring;                     // Else treat strings literally
  55.                                                         // Set if case sensitivity
  56.     lpgi->CaseSen = ((uOpts & FLG_CASE) ? TRUE : FALSE);
  57.                                             // Set longjmp to allow aborting on errors
  58.     _try
  59.     {
  60.         BldSearchLsts( lpgi, pStrLst, pNotList );
  61.         if ( !(uOpts & FLG_REGULAR) )           // If not using expressions
  62.         {
  63.             lpgi->find = findlist;              // Assume finding many
  64.             for ( i = 0; i < 2; i++ )
  65.             {
  66.                 _fmemset(lpgi->ge.td1, (int)(lpgi->ge.ShortStrLen + 1), TRTABLEN);  // Init lpgi->ge.td1 tables
  67.                 enumstrings(lpgi);              // Build lpgi->ge.td1 table
  68.                 if (lpgi->ge.StrCount == 1 && lpgi->CaseSen)
  69.                     lpgi->find = findone;       // Find one case-sensitive string
  70.                 else
  71.                     lpgi->find = findlist;      // Assume finding many
  72.                 SwapSrchTables(lpgi);           // Do the data swap
  73.             }
  74.         }
  75.         else if (lpgi->find == NULL)
  76.             lpgi->find = findexpr;                        // Else find expressions
  77.     }
  78.     // Let the debugger get a chance at the exceptions first...
  79.     _except(SetErrorMode(SEM_NOGPFAULTERRORBOX),UnhandledExceptionFilter(GetExceptionInformation()))
  80.     {
  81.         FreeGrepBufs(lpgi);
  82.         return NULL ;
  83.     }
  84.     return( lpgi );
  85. }
  86. //*********************************************************************
  87. //  Initializes the search tree data for both the search list and
  88. //  not search list.
  89. //
  90. //  void BldSearchLsts( LPSTR pStrLst, LPSTR pNotList )
  91. //
  92. //  ARGUMENTS:
  93. //      pStrLst - Ptr to list of strings or expression to match
  94. //      pNotLst - Ptr to list of strings or expression which must not match
  95. //  RETURNS:
  96. //      void
  97. //
  98. //*********************************************************************
  99. void BldSearchLsts( LPGREPINFO lpgi, LPSTR pStrLst, LPSTR pNotList )
  100. {
  101.     LPSTR   szNext;                                // Ptr to next string to add
  102.     int     i;                                      // Loop indice
  103.     int     iStrLen;                                // Length of current string
  104.         // Loop 3 times. First iteration add all search strings to normal
  105.         // search list, 2nd iteration add all /NOT string to the normal
  106.         // search list and then swap the search data so that on the
  107.         // 3rd iteration all the /NOT string will be added to the /NOT
  108.         // search list. Then swap the data again to restore the original.
  109.     for ( szNext = pStrLst, i = 0; i < 3; i++ )
  110.     {
  111.         while ( *szNext != '' )
  112.         {
  113.             iStrLen = (int)lstrlenA( szNext );
  114.                 // If doing string search make sure this is not a duplicate
  115.                 // before adding it to the search tree.
  116.             if ( lpgi->addstr == addexpr ||
  117.                   findlist( lpgi, szNext, szNext + iStrLen ) == NULL )
  118.                 (*lpgi->addstr)( lpgi, szNext, iStrLen ); // Add string to list
  119.             szNext += iStrLen + 1;
  120.         }
  121.         if ( i == 1 )                               // Is this the 2nd iteration
  122.             SwapSrchTables(lpgi);                   // Do the data swap
  123.                 // Set string ptr to /NOT list for 2nd and 3rd iterations.
  124.         szNext = pNotList;
  125.     }
  126.     SwapSrchTables(lpgi);                           // Restore the original data area
  127. }
  128. //*********************************************************************
  129. //  Reads in portions of an open file and search the strings initialized
  130. //  by BldSearchLsts().
  131. //
  132. // If (fFlags & FLG_FIND_FILE) will continue reading thru the file until
  133. //  a matching search string is found or the end of the file is reached.
  134. //  If there are string specified in the /NOT list the file will continue
  135. //  to be scanned until either a string the the /NOT list is detected
  136. //  or the end of the file is reached.
  137. //
  138. //  If !(fFlags & FLG_FIND_FILE) the file will be searched for lines
  139. //  which match containing a matching string and then the user supplied
  140. //  callback will be called for each line which contains a match or
  141. //  does not contain a match, depending on the bits in fFlags.
  142. //
  143. //
  144. //  NOTE:
  145. //      InitSearchInfo() must be called to setup the search information
  146. //      and intialize the search buffers before this function is called
  147. //      the first time.
  148. //
  149. //  int FileFindGrep( HANDLE fh, unsigned fFlags, FIND_CALLBACK FindCb )
  150. //
  151. //  ARGUMENTS:
  152. //      fHandle - Open DOS file handle of file to search
  153. //      fFlags  - Operation flags can be a combination of:
  154. //                    FLG_FIND_FILE  - Only try to locate the file (EXCLUSIVE)
  155. //                    FLG_FIND_NOMATCH - Display non-matching lines
  156. //                    FLG_FIND_MATCH   - Display matching lines
  157. //                    FLG_FIND_COUNT     - Display on count of matching lines
  158. //                    FLG_FIND_LINENO  - Display line numbers on output
  159. //      FindCb  - Call function for displaying matching strings or NULL
  160. //                    if (fFlags & FLG_FIND_FILE).
  161. //  RETURNS:
  162. //      int     - If (fFlags & FLG_FIND_FILE) returns TRUE if at least one
  163. //                    string match from pStrLst and no string match from pNotLst
  164. //                    else FALSE. If !(fFlags & FLG_FIND_FILE) returns OK
  165. //                    if no errors else returns ERR_FILE_READ or any value
  166. //                    returned by a callback function.
  167. //
  168. //*********************************************************************
  169. int FileFindGrep( LPGREPINFO lpgi, HANDLE fh, unsigned fFlags,
  170.                   long (far pascal *AppCb)( int Func,
  171.                                              unsigned uArg0,
  172.                                              void far *pArg1,
  173.                                              unsigned long ulArg2 ) )
  174. {
  175.     register LPSTR  BufPtr;             // Buffer pointer
  176.     LPSTR           EndBuf;             // End of buffer
  177.     LPSTR           pchChar;            // Ptr to matching string in buffer
  178. #ifdef DO_CALLBACK
  179.     TCHAR            *pchBegin;          // Ptr to start of line
  180.     TCHAR            *pchEnd;            // Ptr to end of line
  181. #endif
  182.     int             iStatus;            //
  183.     DWORD           ByteCount;          // Byte count
  184.     unsigned        TailLen;            // Length of buffer tail
  185.     unsigned long   ulLineNum;          // Current line number in the file
  186.     unsigned long   ulMatchCnt;         // Count of lines containing match
  187.     lpgi->ReadBuf[ 3 ] = 'n';          // Mark beginning with newline
  188.     BufPtr = lpgi->ReadBuf + 4;         // Set buf ptr to after newline
  189.     TailLen = 0;                        // No buffer tail yet
  190.     ulLineNum = 0UL;                    // Start with line 1
  191.     ulMatchCnt = 0UL;                   // Zero the match count
  192.     iStatus = OK;                       // Assume no errors to start
  193.     // Loop filling the buffer and then searching it
  194.     while ( ReadFile(fh, BufPtr, SectorBased( FILBUFLEN - TailLen),
  195.                      &ByteCount, NULL)
  196.                 && (ByteCount + TailLen != 0))
  197.     {
  198.         if ( ByteCount == 0 )
  199.         {                                               // If buffer tail is all that's left
  200.             TailLen = 0;                            // Set tail length to zero
  201.             *BufPtr++ = 'r';                       // Add end of line sequence
  202.             *BufPtr++ = 'n';
  203.             EndBuf = BufPtr;                        // Note end of buffer
  204.         }
  205.         else                                            // Else start next read
  206.         {                                               // Find length of partial line
  207.             TailLen = (unsigned)preveol( BufPtr + ByteCount - 1 );
  208.             if ( TailLen == ByteCount )     // Find tail length after last LF
  209.             {
  210.                 TailLen = 0;                        // No linefeeds in buffer
  211.                 EndBuf = BufPtr + ByteCount;
  212.             }
  213.             else
  214.                 EndBuf = BufPtr + ByteCount - TailLen;
  215.         }
  216.         pchChar = lpgi->ReadBuf + 4;
  217.             // Loop searching thru the buffer for matching strings
  218.         while ( pchChar != NULL &&
  219.                 EndBuf > pchChar &&
  220.                 (EndBuf - pchChar) >= lpgi->ge.ShortStrLen )
  221.         {
  222.             if ( !(fFlags & FIND_FILE) )
  223.             {
  224. #ifdef DO_CALLBACKS
  225.                 ulLineNum++;                        // Increment the line count
  226.                 pchBegin = pchChar;
  227.                 pchEnd = NextEol( pchChar, EndBuf );
  228.                 if ( (pchChar = (*find)( pchChar, pchEnd )) != NULL )
  229.                 {
  230.                     ulMatchCnt++;
  231.                     if ( !(fFlags & FIND_NOMATCH) &&
  232.                           !(fFlags & FIND_COUNT) )
  233.                         iStatus = CB_FindMatch( pchEnd - pchBegin,
  234.                                                         pchBegin, ulLineNum );
  235.                 }
  236.                 else if ( (fFlags & FLG_FIND_NOMATCH) )
  237.                     iStatus = CB_FindMatch( pchEnd - pchBegin, pchBegin,
  238.                                                     ulLineNum );
  239.                 if ( iStatus != OK )
  240.                     return( iStatus );
  241.                 pchChar = pchEnd;
  242. #endif // DO_CALLBACKS
  243.             }
  244.             else if ( (pchChar = (*lpgi->find)( lpgi, pchChar, EndBuf )) != NULL )
  245.             {
  246.                     // If we looking for /NOT strings the
  247.                     // findfile fails unless NoSrchStr == TRUE, if we are not
  248.                     // looking for /NOT strings it means we found a normal
  249.                     // string so see if there are any not strings.
  250.                 if ( (fFlags & FIND_NOT) )
  251.                 {
  252.                     SwapSrchTables(lpgi);   // Restore the normal data area
  253.                     return( FALSE );        // Always FALSE if /NOT strs found
  254.                 }
  255.                 else if ( lpgi->geNot.TblEntriesUsed <= 1 )    // Are there any /NOT strings
  256.                     return( TRUE );         // Found a match and no /NOT strings
  257.                 else
  258.                 {
  259.                     SwapSrchTables(lpgi);   // Need to search for /NOT strings
  260.                     fFlags |= FIND_NOT;     // Signal we've changed the data
  261.                 }
  262.             }
  263.                                             // Copy tail to head of buffer
  264.         }
  265.         if ( TailLen != 0 )
  266.             hmemcpy( lpgi->ReadBuf + 4, EndBuf, TailLen );
  267.         BufPtr = lpgi->ReadBuf + TailLen + 4; // Skip over tail
  268.         // If our last read returned no bytes
  269.     }
  270.     if ( !(fFlags & FIND_FILE) )
  271. #ifdef DOCALLBACKS
  272.         return( CB_FindCount( ulMatchCnt ) );
  273. #else
  274.         return(1);
  275. #endif //CALLBACK
  276.     else if ( !(fFlags & FIND_NOT) )
  277.         return( (s_pSrchStrLst[ 0 ] == '') ? TRUE : FALSE );
  278.     SwapSrchTables(lpgi);                   // Restore the normal data area
  279.     return( TRUE );                         // No /NOT strings found success
  280. }
  281. //*********************************************************************
  282. //*********************************************************************
  283. LPSTR NextEol( LPSTR pchChar, LPSTR EndBuf )
  284. {
  285.     pchChar++;                                      // String starts with /r
  286.     while( pchChar < EndBuf && *pchChar != 0x0A )
  287.         pchChar++;
  288.     return( pchChar );
  289. }