1 /* exp_glob.c - expect functions for doing glob
3 Based on Tcl's glob functions but modified to support anchors and to
4 return information about the possibility of future matches
6 Modifications by: Don Libes, NIST, 2/6/90
8 Design and implementation of this program was paid for by U.S. tax
9 dollars. Therefore it is public domain. However, the author and NIST
10 would appreciate credit if this program or parts of it are used.
14 #include "expect_cf.h"
19 /* The following functions implement expect's glob-style string matching */
20 /* Exp_StringMatch allow's implements the unanchored front (or conversely */
21 /* the '^') feature. Exp_StringMatch2 does the rest of the work. */
22 int /* returns # of chars that matched */
23 Exp_StringMatch(string, pattern,offset)
26 int *offset; /* offset from beginning of string where pattern matches */
29 int sm; /* count of chars matched or -1 */
34 if (pattern[0] == '^') {
39 sm = Exp_StringMatch2(string,pattern);
40 if (sm >= 0) return(sm);
42 if (caret) return(-1);
44 if (pattern[0] == '*') return(-1);
46 for (s = string;*s;s++) {
47 sm = Exp_StringMatch2(s,pattern);
57 /* The following functions implement expect's glob-style string matching */
58 /* Exp_StringMatch allow's implements the unanchored front (or conversely */
59 /* the '^') feature. Exp_StringMatch2 does the rest of the work. */
60 int /* returns # of chars that matched */
61 Exp_StringMatch(string, pattern,offset)
64 int *offset; /* offset from beginning of string where pattern matches */
67 int sm; /* count of chars matched or -1 */
73 if (pattern[0] == '^') {
76 } else if (pattern[0] == '*') {
81 * test if pattern matches in initial position.
82 * This handles front-anchor and 1st iteration of non-front-anchor.
83 * Note that 1st iteration must be tried even if string is empty.
86 sm = Exp_StringMatch2(string,pattern);
87 if (sm >= 0) return(sm);
92 if (*string == '\0') return -1;
94 for (s = string+1;*s;s++) {
95 sm = Exp_StringMatch2(s,pattern);
104 /* Exp_StringMatch2 --
106 Like Tcl_StringMatch except that
107 1) returns number of characters matched, -1 if failed.
108 (Can return 0 on patterns like "" or "$")
109 2) does not require pattern to match to end of string
110 3) much of code is stolen from Tcl_StringMatch
111 4) front-anchor is assumed (Tcl_StringMatch retries for non-front-anchor)
114 int Exp_StringMatch2(string,pattern)
115 register char *string; /* String. */
116 register char *pattern; /* Pattern, which may contain
117 * special characters. */
120 int match = 0; /* # of chars matched */
123 /* If at end of pattern, success! */
128 /* If last pattern character is '$', verify that entire
129 * string has been matched.
131 if ((*pattern == '$') && (pattern[1] == 0)) {
132 if (*string == 0) return(match);
136 /* Check for a "*" as the next pattern character. It matches
137 * any substring. We handle this by calling ourselves
138 * recursively for each postfix of string, until either we
139 * match or we reach the end of the string.
142 if (*pattern == '*') {
149 return(strlen(string)+match); /* DEL */
152 /* find longest match - switched to this on 12/31/93 */
153 head_len = strlen(string); /* length before tail */
154 tail = string + head_len;
155 while (head_len >= 0) {
158 if (-1 != (rc = Exp_StringMatch2(tail, pattern))) {
159 return rc + match + head_len; /* DEL */
165 /* find shortest match */
166 while (*string != 0) {
169 if (-1 != (rc = Exp_StringMatch2(string, pattern))) {
170 return rc+match; /* DEL */
175 if (*pattern == '$') return 0; /* handle *$ */
181 * after this point, all patterns must match at least one
182 * character, so check this
185 if (*string == 0) return -1;
187 /* Check for a "?" as the next pattern character. It matches
188 * any single character.
191 if (*pattern == '?') {
195 /* Check for a "[" as the next pattern character. It is followed
196 * by a list of characters that are acceptable, or by a range
197 * (two characters separated by "-").
200 if (*pattern == '[') {
203 if ((*pattern == ']') || (*pattern == 0)) {
204 return -1; /* was 0; DEL */
206 if (*pattern == *string) {
209 if (pattern[1] == '-') {
214 if ((*pattern <= *string) && (c2 >= *string)) {
217 if ((*pattern >= *string) && (c2 <= *string)) {
225 /* OOPS! Found a bug in vanilla Tcl - have sent back to Ousterhout */
226 /* but he hasn't integrated it yet. - DEL */
229 while ((*pattern != ']') && (*pattern != 0)) {
231 while (*pattern != ']') {
242 /* If the next pattern character is backslash, strip it off
243 * so we do exact matching on the character that follows.
246 if (*pattern == '\\') {
253 /* There's no special character. Just make sure that the next
254 * characters of each string match.
257 if (*pattern != *string) {
261 thisCharOK: pattern += 1;