1/* $NetBSD: pmatch.c,v 1.6 2009/03/14 21:04:24 dsl Exp $ */
2
3/*-
4 * Copyright (c) 1980, 1991 The Regents of the University of California.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <sys/param.h>
33#include <lib/libkern/libkern.h>
34/*
35 * pmatch():
36 * Return 2 on exact match.
37 * Return 1 on substring match.
38 * Return 0 on no match.
39 * Return -1 on error.
40 * *estr will point to the end of thelongest exact or substring match.
41 */
42int
43pmatch(const char *string, const char *pattern, const char **estr)
44{
45 u_char stringc, patternc, rangec;
46 int match, negate_range;
47 const char *oestr, *pestr, *testr;
48
49 if (estr == NULL)
50 estr = &testr;
51
52 for (;; ++string) {
53 stringc = *string;
54 switch (patternc = *pattern++) {
55 case 0:
56 *estr = string;
57 return stringc == '\0' ? 2 : 1;
58 case '?':
59 if (stringc == '\0')
60 return 0;
61 *estr = string;
62 break;
63 case '*':
64 if (!*pattern) {
65 while (*string)
66 string++;
67 *estr = string;
68 return 2;
69 }
70 oestr = *estr;
71 pestr = NULL;
72
73 do {
74 switch (pmatch(string, pattern, estr)) {
75 case -1:
76 return -1;
77 case 0:
78 break;
79 case 1:
80 pestr = *estr;
81 break;
82 case 2:
83 return 2;
84 default:
85 return -1;
86 }
87 *estr = string;
88 }
89 while (*string++);
90
91 if (pestr) {
92 *estr = pestr;
93 return 1;
94 } else {
95 *estr = oestr;
96 return 0;
97 }
98
99 case '[':
100 match = 0;
101 if ((negate_range = (*pattern == '^')) != 0)
102 pattern++;
103 while ((rangec = *pattern++) != '\0') {
104 if (rangec == ']')
105 break;
106 if (match)
107 continue;
108 if (rangec == '-' && *(pattern - 2) != '[' &&
109 *pattern != ']') {
110 match =
111 stringc <= (u_char)*pattern &&
112 (u_char)*(pattern - 2) <= stringc;
113 pattern++;
114 } else
115 match = (stringc == rangec);
116 }
117 if (rangec == 0)
118 return -1;
119 if (match == negate_range)
120 return 0;
121 *estr = string;
122 break;
123 default:
124 if (patternc != stringc)
125 return 0;
126 *estr = string;
127 break;
128 }
129 }
130}
131