"Fossies" - the Fresh Open Source Software Archive

Member "tin-2.6.2/src/wildmat.c" (9 Dec 2022, 5555 Bytes) of package /linux/misc/tin-2.6.2.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "wildmat.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.6.1_vs_2.6.2.

    1 /*  @Revision: 1.9 @
    2 **
    3 **  Do shell-style pattern matching for ?, \, [], and * characters.
    4 **  Might not be robust in face of malformed patterns; e.g., "foo[a-"
    5 **  could cause a segmentation violation.  It is 8bit clean.
    6 **
    7 **  Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986.
    8 **  Rich $alz is now <rsalz@osf.org>.
    9 **  April, 1991:  Replaced mutually-recursive calls with in-line code
   10 **  for the star character.
   11 **
   12 **  Special thanks to Lars Mathiesen <thorinn@diku.dk> for the ABORT code.
   13 **  This can greatly speed up failing wildcard patterns.  For example:
   14 **  pattern: -*-*-*-*-*-*-12-*-*-*-m-*-*-*
   15 **  text 1:  -adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1
   16 **  text 2:  -adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1
   17 **  Text 1 matches with 51 calls, while text 2 fails with 54 calls.  Without
   18 **  the ABORT code, it takes 22310 calls to fail.  Ugh.  The following
   19 **  explanation is from Lars:
   20 **  The precondition that must be fulfilled is that DoMatch will consume
   21 **  at least one character in text.  This is true if *p is neither '*' nor
   22 **  '\0'.)  The last return has ABORT instead of FALSE to avoid quadratic
   23 **  behavior in cases like pattern "*a*b*c*d" with text "abcxxxxx".  With
   24 **  FALSE, each star-loop has to run to the end of the text; with ABORT
   25 **  only the last one does.
   26 **
   27 **  Once the control of one instance of DoMatch enters the star-loop, that
   28 **  instance will return either TRUE or ABORT, and any calling instance
   29 **  will therefore return immediately after (without calling recursively
   30 **  again).  In effect, only one star-loop is ever active.  It would be
   31 **  possible to modify the code to maintain this context explicitly,
   32 **  eliminating all recursive calls at the cost of some complication and
   33 **  loss of clarity (and the ABORT stuff seems to be unclear enough by
   34 **  itself).  I think it would be unwise to try to get this into a
   35 **  released version unless you have a good test data base to try it out
   36 **  on.
   37 */
   38 
   39 #ifndef TIN_H
   40 #   include "tin.h"
   41 #endif /* !TIN_H */
   42 
   43 #define ABORT   -1
   44 
   45 /* What character marks an inverted character class? */
   46 #define NEGATE_CLASS    '^'
   47 
   48 /* Is "*" a common pattern? */
   49 #define OPTIMIZE_JUST_STAR 1
   50 
   51 /* Do tar(1) matching rules, which ignore a trailing slash? */
   52 #undef MATCH_TAR_PATTERN
   53 
   54 /*
   55  * local prototypes
   56  */
   57 static int DoMatch(const char *text, char *p);
   58 
   59 /*
   60  *  Match text and p, return 1 (TRUE), 0 (FALSE), or -1 (ABORT).
   61  */
   62 
   63 static int
   64 DoMatch(
   65     const char *text,
   66     char *p)
   67 {
   68     int last;
   69     int matched;
   70     int reverse;
   71 
   72     for (; *p; text++, p++) {
   73         if (*text == '\0' && *p != '*')
   74             return ABORT;
   75         switch (*p) {
   76             case '\\':
   77                 /* Literal match with following character. */
   78                 p++;
   79                 /* FALLTHROUGH */
   80             default:
   81                 if (*text != *p)
   82                     return 0;
   83                 continue;
   84             case '?':
   85                 /* Match anything. */
   86                 continue;
   87             case '*':
   88                 while (*++p == '*')
   89                     /* Consecutive stars act just like one. */
   90                     continue;
   91                 if (*p == '\0')
   92                     /* Trailing star matches everything. */
   93                     return 1;
   94                 while (*text)
   95                     if ((matched = DoMatch(text++, p)) != 0)
   96                         return matched;
   97                 return ABORT;
   98             case '[':
   99                 reverse = p[1] == NEGATE_CLASS ? TRUE : FALSE;
  100                 if (reverse)
  101                     /* Inverted character class. */
  102                     p++;
  103                 matched = FALSE;
  104                 if (p[1] == ']' || p[1] == '-')
  105                     if (*++p == *text)
  106                         matched = TRUE;
  107                 for (last = *p; *++p && *p != ']'; last = *p)
  108                     /* This next line requires a good C compiler. */
  109                     if (*p == '-' && p[1] != ']' ? *text <= *++p && *text >= last : *text == *p)
  110                         matched = TRUE;
  111                 if (matched == reverse)
  112                     return 0;
  113                 continue;
  114             }
  115         }
  116 #ifdef MATCH_TAR_PATTERN
  117         if (*text == '/')
  118             return 1;
  119 #endif /* MATCH_TAR_ATTERN */
  120     return *text == '\0';
  121 }
  122 
  123 
  124 /*
  125  * User-level routine. Returns TRUE or FALSE.
  126  */
  127 t_bool
  128 wildmat(
  129     const char *text,
  130     char *p,
  131     t_bool icase)
  132 {
  133     char *txt;
  134     t_bool ret;
  135 
  136     /*
  137      * Make sure the pattern is not NULL
  138      */
  139     if (p == NULL || text == NULL)
  140         return FALSE;
  141 #ifdef OPTIMIZE_JUST_STAR
  142     if (p[0] == '*' && p[1] == '\0')
  143         return TRUE;
  144 #endif /* OPTIMIZE_JUST_STAR */
  145 
  146     if (icase) {
  147         txt = my_strdup(text);
  148         str_lwr(txt);
  149         str_lwr(p);
  150         ret = (DoMatch(txt, p) == TRUE);
  151         free(txt);
  152     } else
  153         ret = (DoMatch(text, p) == TRUE);
  154 
  155     return ret;
  156 }
  157 
  158 
  159 /*
  160  * User-level routine. Calculates position of a match within a line.
  161  * Returns TRUE or FALSE.
  162  */
  163 t_bool
  164 wildmatpos(
  165     const char *text,
  166     char *p,
  167     t_bool icase,
  168     REGEX_SIZE *srch_offsets,
  169     REGEX_NOFFSET srch_offsets_size)
  170 {
  171     char *txt, *t, *px;
  172     int i;
  173     REGEX_SIZE prev_offset = srch_offsets[1];
  174     t_bool ret = FALSE;
  175 
  176     if (srch_offsets_size >= 2)
  177         srch_offsets[0] = srch_offsets[1] = 0;
  178 
  179     /*
  180      * Make sure the pattern is not NULL
  181      */
  182     if (p == NULL || text == NULL)
  183         return FALSE;
  184 #ifdef OPTIMIZE_JUST_STAR
  185     if (p[0] == '*' && p[1] == '\0') {
  186         if (srch_offsets_size >= 2) {
  187             srch_offsets[0] = 0;
  188             srch_offsets[1] = (REGEX_SIZE) strlen(text);
  189         }
  190         return TRUE;
  191     }
  192 #endif /* OPTIMIZE_JUST_STAR */
  193 
  194     txt = my_strdup(text);
  195     if (icase) {
  196         str_lwr(txt);
  197         str_lwr(p);
  198     }
  199 
  200     /* remove the leading '*' */
  201     px = my_strdup(p + 1);
  202 
  203     for (t = txt + prev_offset; *t; t++)
  204         if ((ret = (DoMatch(t, px) == 1))) {
  205             /* remove the trailing '*' */
  206             px[strlen(px) - 1] = '\0';
  207             for (i = (int) strlen(t); i > 0; i--) {
  208                 t[i] = '\0';
  209                 if ((ret = (DoMatch(t, px) == 1))) {
  210                     if (srch_offsets_size >= 2) {
  211                         srch_offsets[0] = (REGEX_SIZE) (t - txt);
  212                         srch_offsets[1] = srch_offsets[0] + i;
  213                     }
  214                     break;
  215                 }
  216             }
  217             break;
  218         }
  219     free(px);
  220     free(txt);
  221 
  222     return ret;
  223 }