1d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj
2d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj/*--------------------------------------------------------------------*/
3d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj/*--- A simple sequence matching facility.                         ---*/
4d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj/*---                                                 m_seqmatch.c ---*/
5d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj/*--------------------------------------------------------------------*/
6d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj
7d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj/*
8d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   This file is part of Valgrind, a dynamic binary instrumentation
9d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   framework.
10d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj
11b3a1e4bffbdbbf38304f216af405009868f43628sewardj   Copyright (C) 2008-2015 OpenWorks Ltd
12d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj      info@open-works.co.uk
13d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj
14d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   This program is free software; you can redistribute it and/or
15d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   modify it under the terms of the GNU General Public License as
16d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   published by the Free Software Foundation; either version 2 of the
17d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   License, or (at your option) any later version.
18d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj
19d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   This program is distributed in the hope that it will be useful, but
20d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   WITHOUT ANY WARRANTY; without even the implied warranty of
21d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   General Public License for more details.
23d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj
24d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   You should have received a copy of the GNU General Public License
25d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   along with this program; if not, write to the Free Software
26d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   02111-1307, USA.
28d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj
29d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   The GNU General Public License is contained in the file COPYING.
30d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj*/
31d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj
32d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj#include "pub_core_basics.h"
33d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj#include "pub_core_libcassert.h"
34d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj#include "pub_core_libcbase.h"    // VG_(strlen)
35d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj#include "pub_core_seqmatch.h"    // self
36d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj
37d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj/* ---------------------------------------------------------------------
38d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   A simple sequence matching facility
39d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   ------------------------------------------------------------------ */
40d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj
41d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj/* See detailed comment in include/pub_tool_seqmatch.h about this. */
42d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardjBool VG_(generic_match) (
43d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj        Bool matchAll,
443e7986312a0ffc7646b0552d4c4ea3744a870e73florian        const void* patt,  SizeT szbPatt,  UWord nPatt,  UWord ixPatt,
453e7986312a0ffc7646b0552d4c4ea3744a870e73florian        const void* input, SizeT szbInput, UWord nInput, UWord ixInput,
463e7986312a0ffc7646b0552d4c4ea3744a870e73florian        Bool (*pIsStar)(const void*),
473e7986312a0ffc7646b0552d4c4ea3744a870e73florian        Bool (*pIsQuery)(const void*),
483e7986312a0ffc7646b0552d4c4ea3744a870e73florian        Bool (*pattEQinp)(const void*,const void*,void*,UWord),
49a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe        void* inputCompleter, Bool (*haveInputInpC)(void*,UWord)
50d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj     )
51d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj{
52d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   /* This is the spec, written in my favourite formal specification
53d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj      language.  It specifies non-greedy matching of '*'s.
54d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj
55d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj      ma ('*':ps) (i:is) = ma ps (i:is) || ma ('*':ps) is
56d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj      ma ('*':ps) []     = ma ps []
57d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj
58d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj      ma ('?':ps) (i:is) = ma ps is
59d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj      ma ('?':ps) []     = False
60d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj
61d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj      ma (p:ps)   (i:is) = p == i && ma ps is
62d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj
63d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj      ma (p:ps)   []     = False
64d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj      ma []       (i:is) = False -- m-all, True for m-prefix
65d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj      ma []       []     = True
66d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   */
67d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   Bool  havePatt, haveInput;
683e7986312a0ffc7646b0552d4c4ea3744a870e73florian   const HChar *currPatt, *currInput;
69d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj  tailcall:
70a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   vg_assert(nPatt >= 0 && nPatt  < 1000000); /* arbitrary */
71a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   vg_assert(inputCompleter
72a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe             || (nInput >= 0  && nInput < 1000000)); /* arbitrary */
73d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   vg_assert(ixPatt >= 0  && ixPatt <= nPatt);
74a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   vg_assert(ixInput >= 0 && (inputCompleter || ixInput <= nInput));
75d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj
76d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   havePatt  = ixPatt < nPatt;
77a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   haveInput = inputCompleter ?
78a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      (*haveInputInpC)(inputCompleter, ixInput)
79a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      : ixInput < nInput;
80d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj
81d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   /* No specific need to set NULL when !have{Patt,Input}, but guards
82d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj      against inadvertantly dereferencing an out of range pointer to
83d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj      the pattern or input arrays. */
843e7986312a0ffc7646b0552d4c4ea3744a870e73florian   currPatt  = havePatt  ? ((const HChar*)patt) + szbPatt * ixPatt    : NULL;
85a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe   currInput = haveInput && !inputCompleter ?
86a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe      ((const HChar*)input) + szbInput * ixInput : NULL;
87d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj
88d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   // Deal with the complex case first: wildcards.  Do frugal
89d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   // matching.  When encountering a '*', first skip no characters
90d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   // at all, and see if the rest of the match still works.  Only if
91d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   // that fails do we then skip a character, and retry at the next
92d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   // position.
93d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   //
94d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   // ma ('*':ps) (i:is) = ma ps (i:is) || ma ('*':ps) is
95d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   //
96d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   // If we're out of input, check the rest of the pattern matches
97d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   // the empty input.  This really means can only be be empty or
98d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   // composed entirely of '*'s.
99d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   //
100d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   // ma ('*':ps) []     = ma ps []
101d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   //
102d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   if (havePatt && pIsStar(currPatt)) {
103d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj      if (haveInput) {
104d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj         // ma ('*':ps) (i:is) = ma ps (i:is) || ma ('*':ps) is
105d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj         // we unavoidably have to make a real recursive call for the
106d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj         // first half of the OR, since this isn't straight tail-recursion.
107d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj         if (VG_(generic_match)( matchAll,
108d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj                                 patt, szbPatt, nPatt,  ixPatt+1,
109d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj                                 input,szbInput,nInput, ixInput+0,
11013a59524748a7af0f403e4aba435144fa9a6af4cphilippe                                 pIsStar,pIsQuery,pattEQinp,
111a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe                                 inputCompleter,haveInputInpC) ) {
112d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj            return True;
113d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj         }
114d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj         // but we can tail-recurse for the second call
115d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj         ixInput++; goto tailcall;
116d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj      } else {
117d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj         // ma ('*':ps) []     = ma ps []
118d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj         ixPatt++; goto tailcall;
119d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj      }
120d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   }
121d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj
122d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   // simpler cases now.  Deal with '?' wildcards.
123d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   //
124d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   // ma ('?':ps) (i:is) = ma ps is
125d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   // ma ('?':ps) []     = False
126d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   if (havePatt && pIsQuery(currPatt)) {
127d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj      if (haveInput) {
128d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj         ixPatt++; ixInput++; goto tailcall;
129d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj      } else {
130d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj         return False;
131d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj      }
132d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   }
133d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj
134d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   // obvious case with literal chars in the pattern
135d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   //
136d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   // ma (p:ps)   (i:is) = p == i && ma ps is
137d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   if (havePatt && haveInput) {
13813a59524748a7af0f403e4aba435144fa9a6af4cphilippe      if (!pattEQinp(currPatt,currInput,inputCompleter,ixInput)) return False;
139d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj      ixPatt++; ixInput++; goto tailcall;
140d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   }
141d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj
142d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   // if we run out of input before we run out of pattern, we must fail
143d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   // ma (p:ps)   []     = False
144d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   if (havePatt && !haveInput) return False;
145d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj
146d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   // if we run out of pattern before we run out of input, the
147d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   // verdict depends on the matching mode.  If we are trying to
148d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   // match exactly (the pattern must consume the entire input)
149d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   // then the outcome is failure.  However, if we're merely attempting
150d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   // to match some prefix of the input, then we have been successful.
151d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   //
152d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   // ma []       (i:is) = False -- m-all, True for m-prefix
153d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   if (!havePatt && haveInput) {
154d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj      return matchAll ? False // match-all
155d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj                      : True; // match-prefix
156d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   }
157d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj
158d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   // finally, if both sequence and input are both completely
159d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   // consumed, then we were successful, regardless of matching mode.
160d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   if (!havePatt && !haveInput) return True;
161d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj
162d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   // end of cases
163d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   vg_assert(0);
164d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj}
165d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj
166d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj
167d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj/* And a parameterization of the above, to make it do
168d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   string matching.
169d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj*/
1703e7986312a0ffc7646b0552d4c4ea3744a870e73florianstatic Bool charIsStar  ( const void* pV ) { return *(const HChar*)pV == '*'; }
1713e7986312a0ffc7646b0552d4c4ea3744a870e73florianstatic Bool charIsQuery ( const void* pV ) { return *(const HChar*)pV == '?'; }
1723e7986312a0ffc7646b0552d4c4ea3744a870e73florianstatic Bool char_p_EQ_i ( const void* pV, const void* cV,
17313a59524748a7af0f403e4aba435144fa9a6af4cphilippe                          void* null_completer, UWord ixcV ) {
1743e7986312a0ffc7646b0552d4c4ea3744a870e73florian   HChar p = *(const HChar*)pV;
1753e7986312a0ffc7646b0552d4c4ea3744a870e73florian   HChar c = *(const HChar*)cV;
176d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   vg_assert(p != '*' && p != '?');
177d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   return p == c;
178d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj}
17919f91bbaedb4caef8a60ce94b0f507193cc0bc10florianBool VG_(string_match) ( const HChar* patt, const HChar* input )
180d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj{
181d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj   return VG_(generic_match)(
182d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj             True/* match-all */,
1833e7986312a0ffc7646b0552d4c4ea3744a870e73florian             patt,  sizeof(HChar), VG_(strlen)(patt), 0,
1843e7986312a0ffc7646b0552d4c4ea3744a870e73florian             input, sizeof(HChar), VG_(strlen)(input), 0,
18513a59524748a7af0f403e4aba435144fa9a6af4cphilippe             charIsStar, charIsQuery, char_p_EQ_i,
186a0a73939b0398b6608fd6dbde49820ce6530d12cphilippe             NULL, NULL
187d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj          );
188d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj}
189d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj
190d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj
191d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj// test cases for the matcher (in match-all mode)
192d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj// typedef struct { char* patt; char* input; Bool xres; } Test;
193d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//
194d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//static Test tests[] =
195d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//  {
196d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//    { ""          ,""   , True },
197d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//    { "a"         ,""   , False },
198d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//    { "a"         ,"b"  , False },
199d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//    { "a"         ,"a"  , True },
200d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//    { "a"         ,"aa" , False },
201d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//    { "*"         ,""   , True },
202d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//    { "**"        ,""   , True },
203d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//    { "*"         ,"abc", True },
204d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//    { "*a"        ,"abc", False },
205d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//    { "*b"        ,"abc", False },
206d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//    { "*bc"       ,"abc", True },
207d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//    { "a*b"       ,"abc", False },
208d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//    { "a*c"       ,"abc", True },
209d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//    { "*c"        ,"abc", True },
210d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//    { "c*c"       ,"abc", False },
211d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//    { "abc*"      ,"abc", True },
212d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//    { "abc**"     ,"abc", True },
213d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//    { "**abc"     ,"abc", True },
214d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//    { "**a*b*c**" ,"abc", True },
215d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//    { "**a*b*d**" ,"abc", False },
216d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//    { "a?b"       ,"abc", False },
217d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//    { "a?c"       ,"abc", True },
218d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//    { "?"         ,""   , False },
219d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//    { "?"         ,"a"  , True },
220d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//    { "?"         ,"ab" , False },
221d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//    { "abcd"      ,"abc", False },
222d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//    { "ab"        ,"abc", False },
223d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//    { NULL        ,NULL , False }
224d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//  };
225d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//
226d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//int main ( void )
227d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//{
228d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//   Test* t;
229d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//   for (t = tests; t->patt; t++) {
230866862a87a06a70e2e0c0d7e5c773e252db8ecddflorian//     printf("%-10s %-6s  %s\n",
231d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//            t->patt, t->input,
232d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//            match_string_all((UChar*)t->patt,(UChar*)t->input,True)
233d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//            == t->xres
234d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//               ? "pass" : "FAIL" );
235d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//   }
236d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//   return 0;
237d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj//}
238d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj
239d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj/*--------------------------------------------------------------------*/
240d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj/*--- end                                             m_seqmatch.c ---*/
241d7a02db0e48d2f7681a555a4594ff10f2ef54530sewardj/*--------------------------------------------------------------------*/
242