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 */ 42 int 43 pmatch(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