Blame src/wildmat.c

Packit 15a96c
/*
Packit 15a96c
**
Packit 15a96c
**  Do shell-style pattern matching for ?, \, [], and * characters.
Packit 15a96c
**  Might not be robust in face of malformed patterns; e.g., "foo[a-"
Packit 15a96c
**  could cause a segmentation violation.  It is 8bit clean.
Packit 15a96c
**
Packit 15a96c
**  Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986.
Packit 15a96c
**  Special thanks to Lars Mathiesen for the ABORT code.  This can greatly
Packit 15a96c
**  speed up failing wildcard patterns.  For example:
Packit 15a96c
**	pattern: -*-*-*-*-*-*-12-*-*-*-m-*-*-*
Packit 15a96c
**	text 1:	 -adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1
Packit 15a96c
**	text 2:	 -adobe-courier-bold-o-normal--12-120-75-75-p-70-iso8859-1
Packit 15a96c
**  Text 1 matches with 51 calls, while text 2 fails with 54 calls.  Without
Packit 15a96c
**  the ABORT, then it takes 22310 calls to fail.  Ugh.
Packit 15a96c
**
Packit 15a96c
**  bernie    613-01 91/01/04 19:34
Packit 15a96c
**  Fixed problem with terminating * not matching with (null)
Packit 15a96c
**
Packit 15a96c
**  bernie    597-00 91/01/08 11:24
Packit 15a96c
**  Fixed shell glob negate from '^' to '!'
Packit 15a96c
**
Packit 15a96c
**  bernie    597-02 91/01/21 13:43
Packit 15a96c
**	Fixed . matching * or ? on first char.
Packit 15a96c
**
Packit 15a96c
**  jseymour  91/02/05 22:56
Packit 15a96c
**	Fixed problems with ill-formed sets in pattern yielding false
Packit 15a96c
**	matches.  Should now be robust in such cases (not all possibilities
Packit 15a96c
**	tested - standard disclaimer).  Added stand-alone debug code.
Packit 15a96c
**
Packit 15a96c
**  jseymour  91/03/28 20:50
Packit 15a96c
**	Re-fixed problems with ill-formed sets in pattern yielding false
Packit 15a96c
**	matches - one hopes correctly this time.
Packit 15a96c
**
Packit 15a96c
**  jseymour  1998/04/04 17:45 EST
Packit 15a96c
**	Before adding this to minicom (as part of my "getsdir()" addition),
Packit 15a96c
**	I emailed a request to Rich $alz, asking if I could "GPL" it.  Here
Packit 15a96c
**	is his reply:
Packit 15a96c
**
Packit 15a96c
**	    Date: Mon, 30 Mar 1998 10:50:06 -0500 (EST)
Packit 15a96c
**	    Message-Id: <199803301550.KAA14018@<anonymized>.com>
Packit 15a96c
**	    From: Rich Salz <salzr@<anonymized>.com>
Packit 15a96c
**	    To: jseymour@jimsun.LinxNet.com
Packit 15a96c
**	    Subject: Re: A Little Thing Named "Wildmat"
Packit 15a96c
**
Packit 15a96c
**	    Wildmat is in the public domain -- enjoy it.
Packit 15a96c
**
Packit 15a96c
**	    I would rather it not get encumbered with various licenses,
Packit 15a96c
**	    but since it is in the public domain you can do what you want...
Packit 15a96c
**
Packit 15a96c
**	So there you go.  (I anonymized his email address as I don't know
Packit 15a96c
**	that he was particularly interested in having it "advertised".)
Packit 15a96c
*/
Packit 15a96c
#ifdef HAVE_CONFIG_H
Packit 15a96c
#include <config.h>
Packit 15a96c
#endif
Packit 15a96c
Packit 15a96c
#include "minicom.h"
Packit 15a96c
Packit 15a96c
#ifndef TRUE
Packit 15a96c
#define TRUE	 1
Packit 15a96c
#endif
Packit 15a96c
#ifndef FALSE
Packit 15a96c
#define FALSE	 0
Packit 15a96c
#endif
Packit 15a96c
#define ABORT	-1
Packit 15a96c
Packit 15a96c
static int Star(const char *, const char *);
Packit 15a96c
static int DoMatch(const char *, const char *);
Packit 15a96c
Packit 15a96c
static int Star(const char *s, const char *p)
Packit 15a96c
{
Packit 15a96c
  int retval;
Packit 15a96c
Packit 15a96c
  while ((retval = DoMatch(s, p)) == FALSE)	/* gobble up * match */
Packit 15a96c
    if (*++s == '\0')
Packit 15a96c
      return ABORT;
Packit 15a96c
  return retval;
Packit 15a96c
}
Packit 15a96c
Packit 15a96c
/* match string "s" to pattern "p" */
Packit 15a96c
static int DoMatch(const char *s, const char *p)
Packit 15a96c
{
Packit 15a96c
  register int last;
Packit 15a96c
  register int matched;
Packit 15a96c
  register int reverse;
Packit 15a96c
  const char *ss;
Packit 15a96c
  int escaped;
Packit 15a96c
Packit 15a96c
  for (; *p; s++, p++) {                        /* parse the string to end */
Packit 15a96c
Packit 15a96c
    if (*s == '\0')
Packit 15a96c
      return *p == '*' && *++p == '\0' ? TRUE : ABORT;
Packit 15a96c
Packit 15a96c
    switch (*p) {			        /* parse pattern */
Packit 15a96c
Packit 15a96c
      case '\\':
Packit 15a96c
        /* Literal match with following character. */
Packit 15a96c
        p++;
Packit 15a96c
        /* FALLTHROUGH */
Packit 15a96c
Packit 15a96c
      default:		/*literal match*/
Packit 15a96c
        if (*s != *p)
Packit 15a96c
          return FALSE;
Packit 15a96c
        continue;
Packit 15a96c
Packit 15a96c
      case '?':
Packit 15a96c
        /* Match anything. */
Packit 15a96c
        continue;
Packit 15a96c
Packit 15a96c
      case '*':
Packit 15a96c
        /* Trailing star matches everything. */
Packit 15a96c
        return *++p ? Star(s, p) : TRUE;
Packit 15a96c
Packit 15a96c
      case '[':
Packit 15a96c
        /* [!....] means inverse character class. */
Packit 15a96c
        if ((reverse = (p[1] == '!')))
Packit 15a96c
          p++;
Packit 15a96c
        ss = p + 1;	/* set start point */
Packit 15a96c
Packit 15a96c
        for (last = 0400, escaped = matched = FALSE; *++p; last = *p) {
Packit 15a96c
          if (*p == ']' && !(escaped || p == ss))
Packit 15a96c
            break;
Packit 15a96c
          if (escaped)
Packit 15a96c
            escaped = FALSE;
Packit 15a96c
          else if (*p == '\\') {
Packit 15a96c
            escaped = TRUE;
Packit 15a96c
            continue;
Packit 15a96c
          }
Packit 15a96c
Packit 15a96c
          /* This next line requires a good C compiler.	    */
Packit 15a96c
          /*     range?	(in bounds)                 (equal) */
Packit 15a96c
          if ((*p == '-') ? (*s <= *++p && *s >= last) : (*s == *p))
Packit 15a96c
            matched = TRUE;
Packit 15a96c
        }
Packit 15a96c
Packit 15a96c
        if (matched == reverse)
Packit 15a96c
          return FALSE;
Packit 15a96c
        continue;
Packit 15a96c
    }
Packit 15a96c
  }
Packit 15a96c
Packit 15a96c
  return *s == '\0';
Packit 15a96c
}
Packit 15a96c
Packit 15a96c
Packit 15a96c
/*
Packit 15a96c
 * usage: wildmat(string, pattern)
Packit 15a96c
 *
Packit 15a96c
 * returns: non-0 on match
Packit 15a96c
 */
Packit 15a96c
int wildmat(const char *s, const char *p)
Packit 15a96c
{
Packit 15a96c
  if ((*p == '?' || *p == '*') && *s == '.') {
Packit 15a96c
    return FALSE;
Packit 15a96c
  } else {
Packit 15a96c
    return DoMatch(s, p) == TRUE;
Packit 15a96c
  }
Packit 15a96c
}
Packit 15a96c
Packit 15a96c
#ifdef STAND_ALONE_TEST
Packit 15a96c
#include <stdio.h>
Packit 15a96c
Packit 15a96c
/*
Packit 15a96c
 * usage: wildmat <pattern> <test arg(s)>
Packit 15a96c
 */
Packit 15a96c
Packit 15a96c
int main(int argc, char **argv)
Packit 15a96c
{
Packit 15a96c
  int index;
Packit 15a96c
  int status = FALSE;
Packit 15a96c
Packit 15a96c
  for (index = 2; index < argc; ++index) {
Packit 15a96c
    if (wildmat(argv[index], argv[1])) {
Packit 15a96c
      if (status)
Packit 15a96c
        fputs(" ", stdout);
Packit 15a96c
      printf("%s", argv[index]);
Packit 15a96c
      status = TRUE;
Packit 15a96c
    }
Packit 15a96c
  }
Packit 15a96c
Packit 15a96c
  printf("%s\n", status ? "" : argv[1]);
Packit 15a96c
  return 0;
Packit 15a96c
}
Packit 15a96c
Packit 15a96c
#endif