home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / cprog / actlib12.zip / STRINGS.ZIP / REGEXP.C < prev    next >
C/C++ Source or Header  |  1993-03-03  |  7KB  |  279 lines

  1. /*  Copyright (C) 1993   Marc Stern  (internet: stern@mble.philips.be)  */
  2.  
  3. #include "strings.h"
  4. #include <stdlib.h>
  5.  
  6.  
  7. /*
  8.    Functions :   matchset
  9.                  match
  10.                  recursexp
  11.                  regexp
  12. */
  13.  
  14.  
  15.  
  16. /***
  17.  *  Function    :  matchset
  18.  *
  19.  *  Description :  Test if a character matches a set expression.
  20.  *
  21.  *  Parameters  :  in    char c          character to be matched
  22.  *                 in    char *pattern   regular expression to match
  23.  *
  24.  *  Parameters  :  in   char   *string
  25.  *
  26.  *  Decisions   :  The following symbols are treated specially:
  27.  *
  28.  *              \  quote next character      -  range of values
  29.  *              ^  non-inclusion (if first character)
  30.  *
  31.  *              ex: aeiou0-9   match a, e, i, o, u, and 0 thru 9
  32.  *                  ^aeiou0-9  match anything but a, e, i, o, u, and 0 thru 9
  33.  *
  34.  *  Return      :  1 or 0
  35.  *
  36.  *  OS/Compiler :  All
  37.  ***/
  38.  
  39. int matchset( char c, char *pattern )
  40.  
  41. { const char *begin;
  42.   int match_ok = 1;
  43.  
  44.   if ( ! c ) return 0;
  45.  
  46.   if ( *pattern == '^' ) { match_ok = 0; pattern ++; }
  47.  
  48.   for ( begin = pattern; *pattern; begin = pattern++ )
  49.       {
  50.         if ( (*pattern == '-') && (pattern != begin) )  /* range */
  51.            {
  52.              pattern ++; if ( *pattern == '\\' ) pattern ++;
  53.              if ( (min(*pattern, *begin) <= c) && (max(*pattern, *begin) >= c) )
  54.                 return match_ok;
  55.            }
  56.  
  57.         if ( *pattern == '\\' ) pattern++;
  58.  
  59.         if ( *pattern == c ) return match_ok;
  60.       }
  61.  
  62.   return (! match_ok);
  63. }
  64.  
  65.  
  66.  
  67.  
  68. /***
  69.  *  Function    :  match (internal)
  70.  *
  71.  *  Description :  Returns the number of character of a string matched
  72.  *                 by a one character regular expression.
  73.  *
  74.  *  Decisions   :  The following symbols are treated specially:
  75.  *
  76.  *                 .  any character             \  quote next character
  77.  *                 [] set of characters
  78.  *
  79.  *  Parameters  :  in   char *string    input string to be matched
  80.  *                 in   char *pattern   regular expression to match
  81.  *
  82.  *  Side-effects:  pattern contents will be destroyed.
  83.  *
  84.  *  Return      :  number of character matched by regular expression
  85.  *                 0 if not matched
  86.  *
  87.  *  OS/Compiler :  All
  88.  ***/
  89.  
  90. static int near match( const char *string, char *pattern )
  91.  
  92. { char *ptr;
  93.   int  length = 0;
  94.                  
  95.   switch ( *pattern )
  96.          {
  97.            case '.' : *pattern = '\0';
  98.                       length = strlen(string);
  99.                       break;
  100.  
  101.            case '[' : for ( ptr = ++pattern;
  102.                            *ptr && ! (*ptr == ']' && *(ptr - 1) != '\\');
  103.                            ptr ++ );
  104.  
  105.                       if ( *ptr ) *ptr = '\0';
  106.                       while ( matchset(*string++, pattern) ) length ++;
  107.                       break;
  108.  
  109.            case '\\': pattern ++;
  110.  
  111.            default  : while ( *string++ == *pattern ) length ++;
  112.                       *pattern = '\0';
  113.                       break;
  114.           }
  115.  
  116.   return length;
  117. }
  118.  
  119.  
  120.  
  121.  
  122. /***
  123.  *  Function    :  recursexp
  124.  *
  125.  *  Description :  Returns the number of character of a string matched
  126.  *                 by a regular expression.
  127.  *
  128.  *  Decisions   :  The following symbols are treated specially:
  129.  *
  130.  *                 .  any character             \  quote next character
  131.  *                 *  match zero or more        +  match one or more
  132.  *                 [] set of characters
  133.  *
  134.  *
  135.  *  Parameters  :  in   char *string    input string to be matched
  136.  *                 in   char *pattern   regular expression to match
  137.  *
  138.  *  Return      :  number of character matched by regular expression
  139.  *                 -1 if not matched
  140.  *
  141.  *  OS/Compiler :  All
  142.  ***/
  143.  
  144. int recursexp( const char *string, char *pattern )
  145.  
  146. { int count1, count2 = -1, minone = 0;
  147.   char *pattrn;
  148.  
  149.   if ( ! *pattern ) return 0;
  150.  
  151.   pattrn = strdup( pattern );
  152.   count1 = match( string, pattrn );
  153.   if ( count1 < 0 ) { free( pattrn );
  154.                       return -1;
  155.                     }
  156.  
  157.   while ( *pattrn++ );
  158.  
  159.   switch ( *pattrn )
  160.          {
  161.            case '\0': free( pattrn );
  162.                       if ( count1 ) return 1;
  163.                                else return -1;
  164.  
  165.            case '*': pattrn ++;
  166.                      minone = 0;
  167.                      break;
  168.  
  169.            case '+': if ( ! count1 ) return -1;
  170.                      pattrn ++;
  171.                      break;
  172.  
  173.            default : if ( ! count1 ) return -1;
  174.                      count1 = 1;
  175.                      break;
  176.          }
  177.  
  178.   for ( ; count1 >= 0; count1 -- )
  179.       {
  180.         count2 = recursexp( string + count1, pattrn );
  181.         if ( count2 >= 0 ) break;
  182.       }
  183.  
  184.   free( pattrn );
  185.  
  186.   if ( count2 < 0 ) return -1;
  187.   if ( ! count1 && minone ) return -1;
  188.  
  189.   return (count1 + count2);
  190. }
  191.  
  192.  
  193.  
  194.  
  195. /***
  196.  *  Function    :  regexp
  197.  *
  198.  *  Description :  Returns the string matched by a regular expression
  199.  *                 into a string.
  200.  *
  201.  *  Decisions   :  The following symbols are treated specially:
  202.  *
  203.  *                 ^  start of line             $  end of line
  204.  *                 ?  any character             \  quote next character
  205.  *                 *  match zero or more        [] set of characters
  206.  *
  207.  *              ex: [aeiou0-9]   match a, e, i, o, u, and 0 thru 9
  208.  *                  [^aeiou0-9]  match anything but a, e, i, o, u, and 0 thru 9
  209.  *
  210.  *  Parameters  :  out   char *outstr    resulting string
  211.  *                 in    char *string    input string in which we search
  212.  *                 in    char *pattern   regular expression to match
  213.  *
  214.  *  Return      :  - pointer to resulting string
  215.  *                 - if ( outstr == NULL ) returns pointer to matched string
  216.  *                   inside 'string'.
  217.  *
  218.  *  OS/Compiler :  All
  219.  ***/
  220.  
  221. char *regexp( char *outstr, const char *string, const char *pattern )
  222.  
  223. { char *ptr, *pattrn;
  224.   int count, begin = 0, end = 0;
  225.  
  226.   pattrn = strdup( pattern );
  227.   ptr = strend( pattrn ) - 1;
  228.   if ( (*ptr == '$') && (*(ptr - 1) != '\\') )   /* Match end of line */
  229.      {
  230.        end = 1;
  231.        *ptr = '\0';
  232.      }
  233.  
  234.   if ( *pattrn == '^' )        /* Match begin of line */
  235.      {
  236.        begin = 1;
  237.        pattrn ++;
  238.      }
  239.  
  240.   for (; *string; string ++ )
  241.       if ( (count = recursexp(string, pattrn)) >= 0 || begin ) break;
  242.  
  243.   free( pattrn );
  244.  
  245.   if ( end && (count != strlen(string)) ) count = 0;
  246.  
  247.   if ( outstr )
  248.      {
  249.        strleft( outstr, string, count );
  250.        return outstr;
  251.      }
  252.   return string;
  253. }
  254.  
  255.  
  256. #ifdef TEST
  257.  
  258. #include <stdio.h>
  259. #include <stdlib.h>
  260.  
  261. void main()
  262.  
  263. { char string[255], pattern[255], result[255];
  264.  
  265.   regexp( result, "I123", "[^A-Z\\-^][0-9]+\\.*" );
  266.   printf( "\n    Result : %s\n\n", result );
  267.   exit(1);
  268.  
  269.   for (;;) {
  270.              printf( "\n    String : " ); gets( string );
  271.              printf( "    Pattern: " ); gets( pattern );
  272.  
  273.              regexp( result, string, pattern );
  274.              printf( "\n    Result : %s\n\n", result );
  275.            }
  276. }
  277.  
  278. #endif
  279.