Пример #1
0
/* helper function for the *one functions */
static void do_charone( int iSwitch )
{
   const char * pcString;
   HB_SIZE sStrLen;
   const char * pcDeleteSet;
   HB_SIZE sDeleteSetLen;

   /* param check */
   if( HB_ISCHAR( 1 ) )
   {
      if( HB_ISCHAR( 2 ) )
      {
         pcString = hb_parc( 2 );
         sStrLen = hb_parclen( 2 );
         pcDeleteSet = hb_parc( 1 );
         sDeleteSetLen = hb_parclen( 1 );
      }
      else
      {
         pcString = hb_parc( 1 );
         sStrLen = hb_parclen( 1 );
         pcDeleteSet = NULL;
         sDeleteSetLen = 0;
      }

      switch( iSwitch )
      {
         case DO_CHARONE_CHARONE:
            if( sStrLen > 1 )
            {
               const char * pcSub;
               char * pcRet;
               HB_SIZE sRetStrLen = 0;
               char cCurrent = *pcString;

               pcRet = ( char * ) hb_xgrab( sStrLen );
               /* copy first char */
               pcRet[ sRetStrLen++ ] = cCurrent;
               for( pcSub = pcString + 1; pcSub < pcString + sStrLen; pcSub++ )
               {
                  if( *pcSub != cCurrent )
                  {
                     cCurrent = *pcSub;
                     pcRet[ sRetStrLen++ ] = cCurrent;
                  }
                  else if( pcDeleteSet != NULL &&
                           ! ct_at_exact_forward( pcDeleteSet, sDeleteSetLen,
                                                  pcSub, 1, NULL ) )
                  {
                     pcRet[ sRetStrLen++ ] = cCurrent;
                  }
               }
               hb_retclen( pcRet, sRetStrLen );
               hb_xfree( pcRet );
            }
            else
            {
               /* algorithm does nothing to 1-char-strings */
               hb_retclen( pcString, sStrLen );
            }
            break;

         case DO_CHARONE_WORDONE:
            if( sStrLen > 3 && ( pcDeleteSet == NULL || sDeleteSetLen >= 2 ) )
            {
               const char * pcSub;
               char * pcRet;
               HB_SIZE sRetStrLen = 0;
               char cCurrent1 = pcString[ 0 ];
               char cCurrent2 = pcString[ 1 ];

               pcRet = ( char * ) hb_xgrab( sStrLen );
               /* copy first double char */
               pcRet[ sRetStrLen++ ] = cCurrent1;
               pcRet[ sRetStrLen++ ] = cCurrent2;

               for( pcSub = pcString + 2; pcSub < pcString + sStrLen - 1; pcSub += 2 )
               {
                  if( ! ( pcSub[ 0 ] == cCurrent1 && pcSub[ 1 ] == cCurrent2 ) )
                  {
                     cCurrent1 = pcSub[ 0 ];
                     cCurrent2 = pcSub[ 1 ];
                     pcRet[ sRetStrLen++ ] = cCurrent1;
                     pcRet[ sRetStrLen++ ] = cCurrent2;
                  }
                  else if( pcDeleteSet != NULL )
                  {
                     const char * pc = NULL;
                     const char * pStart = pcDeleteSet;
                     HB_SIZE sLen = sDeleteSetLen;

                     while( sLen >= 2 &&
                            ( pc = ct_at_exact_forward( pStart, sLen, pcSub,
                                                        2, NULL ) ) != 0 &&
                            ( pc - pcDeleteSet ) % 2 == 1 )
                     {
                        pStart = pc + 1;
                        sLen = sDeleteSetLen - ( pStart - pcDeleteSet );
                     }
                     if( pc == NULL )
                     {
                        pcRet[ sRetStrLen++ ] = cCurrent1;
                        pcRet[ sRetStrLen++ ] = cCurrent2;
                     }
                  }
               }

               /* copy last character if string len is odd */
               if( sStrLen & 1 )
                  pcRet[ sRetStrLen++ ] = pcString[ sStrLen - 1 ];

               hb_retclen( pcRet, sRetStrLen );
               hb_xfree( pcRet );
            }
            else
            {
               /* algorithm does nothing to 3-char-strings */
               hb_retclen( pcString, sStrLen );
            }
            break;
      }
   }
   else
   {
      PHB_ITEM pSubst = NULL;
      int iArgErrorMode = ct_getargerrormode();

      if( iArgErrorMode != CT_ARGERR_IGNORE )
         pSubst = ct_error_subst( ( HB_USHORT ) iArgErrorMode, EG_ARG,
                                  iSwitch == DO_CHARONE_CHARONE ?
                                  CT_ERROR_CHARONE : CT_ERROR_WORDONE,
                                  NULL, HB_ERR_FUNCNAME, 0, EF_CANSUBSTITUTE,
                                  HB_ERR_ARGS_BASEPARAMS );
      if( pSubst != NULL )
         hb_itemReturnRelease( pSubst );
      else
         hb_retc_null();
   }
}
Пример #2
0
/* helper function */
static void do_atnum( int iSwitch )
{
   if( ( ISCHAR( 1 ) ) && ( ISCHAR( 2 ) ) )
   {
      const char *   pcStringToMatch   = hb_parc( 1 );
      HB_SIZE        sStrToMatchLen    = hb_parclen( 1 );
      const char *   pcString          = hb_parc( 2 );
      HB_SIZE        sStrLen           = hb_parclen( 2 );
      int            iMultiPass        = ct_getatmupa();
      int            iAtLike           = ct_getatlike();
      char           cAtLike           = ct_getatlikechar();
      HB_SIZE        sIgnore, sMatchStrLen = 0;
      ULONG          ulCounter;
      const char *   pc                = NULL;

      /* eventually ignore some characters */
      if( ISNUM( 4 ) )
         sIgnore = ( size_t ) hb_parnl( 4 );
      else
         sIgnore = 0;

      if( sIgnore >= sStrLen )
      {
         switch( iSwitch )
         {
            case DO_ATNUM_AFTERATNUM:
            {
               /* AFTERATNUM */
               int iArgErrorMode = ct_getargerrormode();
               if( iArgErrorMode != CT_ARGERR_IGNORE )
               {
                  ct_error( ( USHORT ) iArgErrorMode, EG_ARG, CT_ERROR_AFTERATNUM,
                            NULL, "AFTERATNUM", 0, EF_CANDEFAULT, 4,
                            hb_paramError( 1 ), hb_paramError( 2 ),
                            hb_paramError( 3 ), hb_paramError( 4 ) );
               }
               ;
               hb_retc( "" );
            }; break;

            case DO_ATNUM_BEFORATNUM:
            {
               /* BEFORATNUM */
               int iArgErrorMode = ct_getargerrormode();
               if( iArgErrorMode != CT_ARGERR_IGNORE )
               {
                  ct_error( ( USHORT ) iArgErrorMode, EG_ARG, CT_ERROR_BEFORATNUM,
                            NULL, "BEFORATNUM", 0, EF_CANDEFAULT, 4,
                            hb_paramError( 1 ), hb_paramError( 2 ),
                            hb_paramError( 3 ), hb_paramError( 4 ) );
               }
               ;
               hb_retc( "" );
            }; break;

            case DO_ATNUM_ATNUM:
            {
               /* ATNUM */
               int iArgErrorMode = ct_getargerrormode();
               if( iArgErrorMode != CT_ARGERR_IGNORE )
               {
                  ct_error( ( USHORT ) iArgErrorMode, EG_ARG, CT_ERROR_ATNUM,
                            NULL, "ATNUM", 0, EF_CANDEFAULT, 4,
                            hb_paramError( 1 ), hb_paramError( 2 ),
                            hb_paramError( 3 ), hb_paramError( 4 ) );
               }
               ;
               hb_retnl( 0 );
            }; break;
         }

         return;
      }
      else
      {
         pcString += sIgnore;
         sStrLen  -= sIgnore;
      }

      /* nth match or last match ? */
      if( ISNUM( 3 ) && ( ( ulCounter = hb_parnl( 3 ) ) != 0 ) )
      {
         /* find the <ulCounter>th match */
         const char *   pcSubStr;
         HB_SIZE        sSubStrLen;
         ULONG          ulMatchCounter = 0;

         pcSubStr    = pcString;
         sSubStrLen  = sStrLen;

         while( ulMatchCounter < ulCounter )
         {
            switch( iAtLike )
            {
               case CT_SETATLIKE_EXACT:
               {
                  pc = ct_at_exact_forward( pcSubStr, sSubStrLen,
                                            pcStringToMatch, sStrToMatchLen,
                                            &sMatchStrLen );
               }; break;

               case CT_SETATLIKE_WILDCARD:
               {
                  pc = ct_at_wildcard_forward( pcSubStr, sSubStrLen,
                                               pcStringToMatch, sStrToMatchLen,
                                               cAtLike, &sMatchStrLen );
               }; break;

               default:
               {
                  pc = NULL;
               };
            }

            if( pc == NULL )
            {
               /* no match found; if this happens at this point,
                  there are no <ulCounter> matches, so return an empty string */
               switch( iSwitch )
               {
                  case DO_ATNUM_AFTERATNUM:
                  case DO_ATNUM_BEFORATNUM:
                  {
                     /* AFTERATNUM */
                     /* BEFORATNUM */
                     hb_retc( "" );
                  }; break;

                  case DO_ATNUM_ATNUM:
                  {
                     /* ATNUM */
                     hb_retnl( 0 );
                  }; break;
               }

               return;
            }

            ulMatchCounter++;

            if( iMultiPass )
               pcSubStr = pc + 1;
            else
               pcSubStr = pc + sMatchStrLen;
            sSubStrLen = sStrLen - ( pcSubStr - pcString );
         }

      }
      else /* (ISNUM (3) && ((ulCounter = hb_parnl (3)) != 0) */
      {
         /* we have to find the last match and return the
            string after that last match */

         switch( iAtLike )
         {
            case CT_SETATLIKE_EXACT:
            {
               pc = ct_at_exact_backward( pcString, sStrLen,
                                          pcStringToMatch, sStrToMatchLen,
                                          &sMatchStrLen );
            }; break;

            case CT_SETATLIKE_WILDCARD:
            {
               pc = ct_at_wildcard_backward( pcString, sStrLen,
                                             pcStringToMatch, sStrToMatchLen,
                                             cAtLike, &sMatchStrLen );
            }; break;

            default:
            {
               pc = NULL;
            };
         }

         if( pc == NULL )
         {
            /* no matches found */
            switch( iSwitch )
            {
               case DO_ATNUM_AFTERATNUM:
               case DO_ATNUM_BEFORATNUM:
               {
                  /* AFTERATNUM */
                  /* BEFORATNUM */
                  hb_retc( "" );
               }; break;

               case DO_ATNUM_ATNUM:
               {
                  /* ATNUM */
                  hb_retnl( 0 );
               }; break;
            }

            return;
         }

      }

      switch( iSwitch )
      {
         case DO_ATNUM_AFTERATNUM:
         {
            /* AFTERATNUM */
            if( pc + sMatchStrLen >= pcString + sStrLen )
               hb_retc( "" );
            else
               hb_retclen( pc + sMatchStrLen, sStrLen - ( pc + sMatchStrLen - pcString ) );
         }; break;

         case DO_ATNUM_BEFORATNUM:
         {
            /* BEFORATNUM */
            hb_retclen( pcString - sIgnore, pc - ( pcString - sIgnore ) );
         }; break;

         case DO_ATNUM_ATNUM:
         {
            /* ATNUM */
            hb_retns( pc - ( pcString - sIgnore ) + 1 );
         }; break;
      }

   }
   else /* ((ISCHAR (1)) && (ISCHAR (2))) */
   {
      switch( iSwitch )
      {
         case DO_ATNUM_AFTERATNUM:
         case DO_ATNUM_BEFORATNUM:
         {
            /* AFTERATNUM */
            PHB_ITEM pSubst         = NULL;
            int      iArgErrorMode  = ct_getargerrormode();
            if( iArgErrorMode != CT_ARGERR_IGNORE )
            {
               pSubst = ct_error_subst( ( USHORT ) iArgErrorMode, EG_ARG,
                                        ( iSwitch == DO_ATNUM_AFTERATNUM ? CT_ERROR_AFTERATNUM : CT_ERROR_BEFORATNUM ),
                                        NULL,
                                        ( iSwitch == DO_ATNUM_AFTERATNUM ? "AFTERATNUM" : "BEFORATNUM" ),
                                        0, EF_CANSUBSTITUTE, 4,
                                        hb_paramError( 1 ), hb_paramError( 2 ),
                                        hb_paramError( 3 ), hb_paramError( 4 ) );
            }

            if( pSubst != NULL )
            {
               hb_itemRelease( hb_itemReturnForward( pSubst ) );
            }
            else
            {
               hb_retc( "" );
            }
         }; break;

         case DO_ATNUM_ATNUM:
         {
            /* ATNUM */
            PHB_ITEM pSubst         = NULL;
            int      iArgErrorMode  = ct_getargerrormode();
            if( iArgErrorMode != CT_ARGERR_IGNORE )
            {
               pSubst = ct_error_subst( ( USHORT ) iArgErrorMode, EG_ARG, CT_ERROR_ATNUM,
                                        NULL, "ATNUM", 0, EF_CANSUBSTITUTE, 4,
                                        hb_paramError( 1 ), hb_paramError( 2 ),
                                        hb_paramError( 3 ), hb_paramError( 4 ) );
            }

            if( pSubst != NULL )
            {
               hb_itemRelease( hb_itemReturnForward( pSubst ) );
            }
            else
            {
               hb_retnl( 0 );
            }
         }; break;
      }
   }
}
Пример #3
0
/* helper function for the *one functions */
static void do_charone( int iSwitch )
{
   char *pcString;
   size_t sStrLen;
   char *pcDeleteSet;
   size_t sDeleteSetLen;

   /* param check */
   if ( ISCHAR( 1 ) )
   {
      if ( ISCHAR( 2 ) )
      {
         pcString = hb_parc( 2 );
         sStrLen = (size_t)hb_parclen( 2 );
         pcDeleteSet = hb_parc( 1 );
         sDeleteSetLen = (size_t)hb_parclen( 1 );
      }
      else
      {
         pcString = hb_parc( 1 );
         sStrLen = (size_t)hb_parclen( 1 );
         pcDeleteSet = NULL;
         sDeleteSetLen = 0;
      }

      switch ( iSwitch )
      {
         case DO_CHARONE_CHARONE:
         {
            if (sStrLen > 1)
            {
               char *pcSub;
               char *pcRet;
               size_t sRetStrLen = 0;
               char cCurrent = *pcString;

               pcRet = (char *)hb_xgrab( sStrLen );

               /* copy first char */
               pcRet[ sRetStrLen++ ] = cCurrent;

               for ( pcSub = pcString + 1; pcSub < pcString + sStrLen; pcSub++ )
               {
                  if ( *pcSub != cCurrent )
                  {
                     cCurrent = *pcSub;
                     pcRet[ sRetStrLen++ ] = cCurrent;
		  }
		  else if ( pcDeleteSet != NULL
		            && !ct_at_exact_forward( pcDeleteSet, sDeleteSetLen,
		                                     pcSub, 1, NULL ) )
		  {
		     pcRet[ sRetStrLen++ ] = cCurrent;
		  }
	       }

               hb_retclen( pcRet, sRetStrLen );
               hb_xfree( pcRet );
            }
            else  /* if (sStrLen > 1) */
            {
               /* algorithm does nothing to 1-char-strings */
               hb_retclen( pcString, sStrLen );
            }
         }
	 break;

         case DO_CHARONE_WORDONE:
         {
            if ( sStrLen > 3 && sDeleteSetLen >= 2 )
            {
               char *pcSub;
               char *pcRet;
               size_t sRetStrLen = 0;
               char cCurrent1 = pcString[0];
               char cCurrent2 = pcString[1];

               pcRet = (char *)hb_xgrab( sStrLen );

               /* copy first double char */
               pcRet[ sRetStrLen++ ] = cCurrent1;
               pcRet[ sRetStrLen++ ] = cCurrent2;

               for ( pcSub = pcString + 2; pcSub < pcString + sStrLen - 1; pcSub += 2 )
               {
                  if ( !( pcSub[0] == cCurrent1 && pcSub[1] == cCurrent2 ) )
                  {
                     cCurrent1 = pcSub[0];
                     cCurrent2 = pcSub[1];
                     pcRet[ sRetStrLen++ ] = cCurrent1;
                     pcRet[ sRetStrLen++ ] = cCurrent2;
		  }
		  else if ( pcDeleteSet != NULL )
		  {
		     char *pc = NULL;
		     char *pStart = pcDeleteSet;
		     size_t sLen = sDeleteSetLen;
		     
		     while ( sLen >= 2
		             && ( pc = ct_at_exact_forward( pStart, sLen,
		                                            pcSub, 2, NULL ) ) != 0
			     && ( pc - pcDeleteSet ) % 2 == 1 )
		     {
		        pStart = pc + 1;
			sLen = sDeleteSetLen - ( pStart - pcDeleteSet );
		     }
		     
		     if ( pc == NULL )
		     {
		        pcRet[ sRetStrLen++ ] = cCurrent1;
			pcRet[ sRetStrLen++ ] = cCurrent2;
		     }
		  }
               }

               /* copy last character if string len is odd */
               if ( sStrLen % 2 == 1 )
               {
                  pcRet[ sRetStrLen++ ] = pcString[ sStrLen - 1 ];
               }
               hb_retclen( pcRet, sRetStrLen );
               hb_xfree( pcRet );
            }
            else  /* if (sStrLen > 3) */
            {
               /* algorithm does nothing to 3-char-strings */
               hb_retclen( pcString, sStrLen );
            }
         }
	 break;
      } /* switch (iSwitch) */
   }
   else /* if (ISCHAR (1)) */
   {
      PHB_ITEM pSubst = NULL;
      int iArgErrorMode = ct_getargerrormode();
    
      if ( iArgErrorMode != CT_ARGERR_IGNORE )
      {
         pSubst = ct_error_subst( (USHORT)iArgErrorMode, EG_ARG,
                                  ( iSwitch == DO_CHARONE_CHARONE ? CT_ERROR_CHARONE : CT_ERROR_WORDONE ),
                                  NULL,
                                  ( iSwitch == DO_CHARONE_CHARONE ? "CHARONE" : "WORDONE" ),
                                  0, EF_CANSUBSTITUTE, 2,
                                  hb_paramError( 1 ), hb_paramError( 2 ) );
      }
     
      if ( pSubst != NULL )
      {
         hb_itemRelease( hb_itemReturnForward( pSubst ) );
      }
      else
      {
         hb_retc( "" );
      }
   }
}
Пример #4
0
/* helper function for the *one functions */
static void do_charonly( int iSwitch )
{
   /* param check */
   if( HB_ISCHAR( 1 ) && HB_ISCHAR( 2 ) )
   {
      const char * pcString = hb_parc( 2 );
      HB_SIZE sStrLen = hb_parclen( 2 );
      const char * pcOnlySet = hb_parc( 1 );
      HB_SIZE sOnlySetLen = hb_parclen( 1 );
      char * pcRet;
      HB_SIZE sRetStrLen = 0;
      int iShift, iBool;
      const char * pcSub, * pc;

      /* check for zero-length strings  */
      switch( iSwitch )
      {
         case DO_CHARONLY_CHARONLY:
         case DO_CHARONLY_WORDONLY:
            if( sStrLen == 0 || sOnlySetLen == 0 )
            {
               hb_retc_null();
               return;
            }
            break;

         case DO_CHARONLY_CHARREM:
         case DO_CHARONLY_WORDREM:
            if( sStrLen == 0 )
            {
               hb_retc_null();
               return;
            }
            if( sOnlySetLen == 0 )
            {
               hb_retclen( pcString, sStrLen );
               return;
            }
            break;
      }

      if( iSwitch == DO_CHARONLY_WORDONLY ||
          iSwitch == DO_CHARONLY_WORDREM )
         iShift = 2;
      else
         iShift = 1;

      pcRet = ( char * ) hb_xgrab( sStrLen );

      for( pcSub = pcString; pcSub < pcString + sStrLen + 1 - iShift; pcSub += iShift )
      {
         pc = ct_at_exact_forward( pcOnlySet, sOnlySetLen, pcSub, iShift, NULL );
         iBool = ( ( pc != NULL ) && ( ( ( pc - pcOnlySet ) % iShift ) == 0 ) );
         if( iBool ? ( iSwitch == DO_CHARONLY_CHARONLY ||
                       iSwitch == DO_CHARONLY_WORDONLY )
                   : ( iSwitch == DO_CHARONLY_CHARREM ||
                       iSwitch == DO_CHARONLY_WORDREM ) )
         {
            for( pc = pcSub; pc < pcSub + iShift; pc++ )
               pcRet[ sRetStrLen++ ] = *pc;
         }
      }

      /* copy last character if string len is odd */
      if( iShift == 2 && sStrLen % 2 == 1 )
         pcRet[ sRetStrLen++ ] = pcString[ sStrLen - 1 ];

      hb_retclen( pcRet, sRetStrLen );
      hb_xfree( pcRet );
   }
   else
   {
      PHB_ITEM pSubst = NULL;
      int iArgErrorMode = ct_getargerrormode(), iError = 0;

      if( iArgErrorMode != CT_ARGERR_IGNORE )
      {
         switch( iSwitch )
         {
            case DO_CHARONLY_CHARONLY:
               iError = CT_ERROR_CHARONLY;
               break;

            case DO_CHARONLY_WORDONLY:
               iError = CT_ERROR_WORDONLY;
               break;

            case DO_CHARONLY_CHARREM:
               iError = CT_ERROR_CHARREM;
               break;

            case DO_CHARONLY_WORDREM:
               iError = CT_ERROR_WORDREM;
               break;
         }
         pSubst = ct_error_subst( ( HB_USHORT ) iArgErrorMode, EG_ARG, iError,
                                  NULL, HB_ERR_FUNCNAME, 0, EF_CANSUBSTITUTE,
                                  HB_ERR_ARGS_BASEPARAMS );
      }

      if( pSubst != NULL )
         hb_itemReturnRelease( pSubst );
      else
         hb_retc_null();
   }
}
Пример #5
0
/* helper function */
static void do_atnum( int iSwitch )
{
   if( HB_ISCHAR( 1 ) && HB_ISCHAR( 2 ) )
   {
      const char * pcStringToMatch = hb_parc( 1 );
      HB_SIZE sStrToMatchLen = hb_parclen( 1 );
      const char * pcString = hb_parc( 2 );
      HB_SIZE sStrLen = hb_parclen( 2 );
      int iMultiPass = ct_getatmupa();
      int iAtLike = ct_getatlike();
      char cAtLike = ct_getatlikechar();
      HB_SIZE sIgnore = hb_parnsdef( 4, 0 ); /* eventually ignore some characters */
      HB_SIZE sMatchStrLen = 0;
      HB_SIZE nCounter;
      const char * pc = NULL;

      if( sIgnore >= sStrLen )
      {
         switch( iSwitch )
         {
            case DO_ATNUM_AFTERATNUM:
            {
               /* AFTERATNUM */
               int iArgErrorMode = ct_getargerrormode();

               if( iArgErrorMode != CT_ARGERR_IGNORE )
                  ct_error( ( HB_USHORT ) iArgErrorMode, EG_ARG, CT_ERROR_AFTERATNUM, NULL,
                            HB_ERR_FUNCNAME, 0, EF_CANDEFAULT, HB_ERR_ARGS_BASEPARAMS );

               hb_retc_null();
               break;
            }
            case DO_ATNUM_BEFORATNUM:
            {
               /* BEFORATNUM */
               int iArgErrorMode = ct_getargerrormode();

               if( iArgErrorMode != CT_ARGERR_IGNORE )
                  ct_error( ( HB_USHORT ) iArgErrorMode, EG_ARG, CT_ERROR_BEFORATNUM, NULL,
                            HB_ERR_FUNCNAME, 0, EF_CANDEFAULT, HB_ERR_ARGS_BASEPARAMS );

               hb_retc_null();
               break;
            }
            case DO_ATNUM_ATNUM:
            {
               /* ATNUM */
               int iArgErrorMode = ct_getargerrormode();

               if( iArgErrorMode != CT_ARGERR_IGNORE )
                  ct_error( ( HB_USHORT ) iArgErrorMode, EG_ARG, CT_ERROR_ATNUM, NULL, HB_ERR_FUNCNAME, 0,
                            EF_CANDEFAULT, HB_ERR_ARGS_BASEPARAMS );

               hb_retns( 0 );
               break;
            }
         }
         return;
      }
      else
      {
         pcString += sIgnore;
         sStrLen -= sIgnore;
      }

      /* nth match or last match ? */
      if( HB_ISNUM( 3 ) && ( nCounter = hb_parns( 3 ) ) != 0 )
      {
         /* find the <nCounter>th match */
         const char * pcSubStr;
         HB_SIZE sSubStrLen;
         HB_SIZE nMatchCounter = 0;

         pcSubStr = pcString;
         sSubStrLen = sStrLen;

         while( nMatchCounter < nCounter )
         {
            switch( iAtLike )
            {
               case CT_SETATLIKE_EXACT:
                  pc = ct_at_exact_forward( pcSubStr, sSubStrLen, pcStringToMatch,
                                            sStrToMatchLen, &sMatchStrLen );
                  break;

               case CT_SETATLIKE_WILDCARD:
                  pc = ct_at_wildcard_forward( pcSubStr, sSubStrLen, pcStringToMatch,
                                               sStrToMatchLen, cAtLike, &sMatchStrLen );
                  break;

               default:
                  pc = NULL;
            }

            if( pc == NULL )
            {
               /* no match found; if this happens at this point,
                  there are no <nCounter> matches, so return an empty string */
               switch( iSwitch )
               {
                  case DO_ATNUM_AFTERATNUM:
                  case DO_ATNUM_BEFORATNUM:
                     /* AFTERATNUM */
                     /* BEFORATNUM */
                     hb_retc_null();
                     break;

                  case DO_ATNUM_ATNUM:
                     /* ATNUM */
                     hb_retns( 0 );
                     break;
               }
               return;
            }
            nMatchCounter++;

            if( iMultiPass )
               pcSubStr = pc + 1;
            else
               pcSubStr = pc + sMatchStrLen;
            sSubStrLen = sStrLen - ( pcSubStr - pcString );
         }
      }
      else
      {
         /* we have to find the last match and return the
            string after that last match */
         switch( iAtLike )
         {
            case CT_SETATLIKE_EXACT:
               pc = ct_at_exact_backward( pcString, sStrLen, pcStringToMatch,
                                          sStrToMatchLen, &sMatchStrLen );
               break;

            case CT_SETATLIKE_WILDCARD:
               pc = ct_at_wildcard_backward( pcString, sStrLen, pcStringToMatch,
                                             sStrToMatchLen, cAtLike, &sMatchStrLen );
               break;

            default:
               pc = NULL;
         }
         if( pc == NULL )
         {
            /* no matches found */
            switch( iSwitch )
            {
               case DO_ATNUM_AFTERATNUM:
               case DO_ATNUM_BEFORATNUM:
                  /* AFTERATNUM */
                  /* BEFORATNUM */
                  hb_retc_null();
                  break;

               case DO_ATNUM_ATNUM:
                  /* ATNUM */
                  hb_retns( 0 );
                  break;
            }
            return;
         }
      }

      switch( iSwitch )
      {
         case DO_ATNUM_AFTERATNUM:
            /* AFTERATNUM */
            if( pc + sMatchStrLen >= pcString + sStrLen )
               hb_retc_null();
            else
               hb_retclen( pc + sMatchStrLen, sStrLen - ( pc + sMatchStrLen - pcString ) );
            break;

         case DO_ATNUM_BEFORATNUM:
            /* BEFORATNUM */
            hb_retclen( pcString - sIgnore, pc - ( pcString - sIgnore ) );
            break;

         case DO_ATNUM_ATNUM:
            /* ATNUM */
#if defined( __POCC__ ) && ( __POCC__ >= 500 ) && defined( HB_OS_WIN_64 )
            /* NOTE: Workaround for Pelles C 5.00.13 AMD64 mode internal error:
                     'fatal error: Internal error: reduce_tree()' [vszakats]. */
            hb_retns( pc - pcString + sIgnore + 1 );
#else
            hb_retns( pc - ( pcString - sIgnore ) + 1 );
#endif
            break;
      }
   }
   else
   {
      switch( iSwitch )
      {
         case DO_ATNUM_AFTERATNUM:
         case DO_ATNUM_BEFORATNUM:
         {
            /* AFTERATNUM */
            PHB_ITEM pSubst = NULL;
            int iArgErrorMode = ct_getargerrormode();

            if( iArgErrorMode != CT_ARGERR_IGNORE )
               pSubst = ct_error_subst( ( HB_USHORT ) iArgErrorMode, EG_ARG,
                                        iSwitch ==
                                        DO_ATNUM_AFTERATNUM ? CT_ERROR_AFTERATNUM :
                                        CT_ERROR_BEFORATNUM, NULL, HB_ERR_FUNCNAME, 0,
                                        EF_CANSUBSTITUTE, HB_ERR_ARGS_BASEPARAMS );

            if( pSubst != NULL )
               hb_itemReturnRelease( pSubst );
            else
               hb_retc_null();
            break;
         }
         case DO_ATNUM_ATNUM:
         {
            /* ATNUM */
            PHB_ITEM pSubst = NULL;
            int iArgErrorMode = ct_getargerrormode();

            if( iArgErrorMode != CT_ARGERR_IGNORE )
               pSubst = ct_error_subst( ( HB_USHORT ) iArgErrorMode, EG_ARG, CT_ERROR_ATNUM,
                                        NULL, HB_ERR_FUNCNAME, 0, EF_CANSUBSTITUTE,
                                        HB_ERR_ARGS_BASEPARAMS );

            if( pSubst != NULL )
               hb_itemReturnRelease( pSubst );
            else
               hb_retns( 0 );
            break;
         }
      }
   }
}