1 /*
2 * (c) Copyright 1990, Kim Fabricius Storm. All rights reserved.
3 * Copyright (c) 1996-2005 Michael T Pins. All rights reserved.
4 *
5 * String/Subject matching routines.
6 */
7
8 #include <ctype.h>
9 #include "config.h"
10 #include "global.h"
11 #include "regexp.h"
12
13 int case_fold_search = 1;
14
15 #define MAXFOLD 256 /* max length of any string */
16
17 /*
18 * Systems which have a tolower(c) function which is defined for
19 * all characters, but no _tolower(c) macro which works for
20 * isupper(c) only, may define HAVE_GENERIC_TOLOWER -- it
21 * may give a slight speed-up, but is not mandatory.
22 */
23
24 #ifndef HAVE_GENERIC_TOLOWER
25
26 #ifndef _tolower
27 #define _tolower(c) tolower(c)
28 #endif
29
30 #endif
31
32 void
fold_string(register char * mask)33 fold_string(register char *mask)
34 { /* convert mask to lower-case */
35 register char c;
36
37 for (; (c = *mask); mask++) {
38
39 #ifdef _tolower
40 if (!isascii(c) || !isupper(c))
41 continue;
42 *mask = _tolower(c);
43 #else
44 *mask = tolower(c);
45 #endif
46 }
47 }
48
49 static int
streq_fold(register char * mask,register char * str)50 streq_fold(register char *mask, register char *str)
51 { /* mask is prefix of str - FOLD */
52 register char c = 0, d;
53
54 while ((d = *mask++)) {
55 if ((c = *str++) == NUL)
56 return 0;
57 if (c == d)
58 continue;
59
60 #ifdef _tolower
61 if (!isascii(c) || !isupper(c) || _tolower(c) != (unsigned) d)
62 return 0;
63 #else
64 if (tolower(c) != d)
65 return 0;
66 #endif
67 }
68 return c == NUL ? 1 : 2;
69 }
70
71 int
strmatch_fold(char * mask,register char * str)72 strmatch_fold(char *mask, register char *str)
73 { /* mask occurs anywhere in str - FOLD */
74 register char c, m1 = *mask++;
75
76 for (;;) {
77 while ((c = *str++)) { /* find first occ. of mask[0] in str. */
78 if (c == m1)
79 break;
80
81 #ifdef _tolower
82 if (!isascii(c) || !isupper(c))
83 continue;
84 if (_tolower(c) == (unsigned) m1)
85 break;
86 #else
87 if (tolower(c) == m1)
88 break;
89 #endif
90 }
91 if (c == NUL)
92 return 0;
93 if (streq_fold(mask, str))
94 return 1;
95 }
96 }
97
98 int
strmatch(char * mask,register char * str)99 strmatch(char *mask, register char *str)
100 { /* mask occurs anywhere in str - CASE */
101 register char *q, *m;
102 register char m1 = *mask;
103
104 for (; *str; str++) {
105 if (*str != m1)
106 continue;
107
108 q = str;
109 m = mask;
110 do
111 if (*++m == NUL)
112 return 1;
113 while (*++q == *m);
114 }
115 return 0;
116 }
117
118 int
strmatch_cf(char * mask,char * str)119 strmatch_cf(char *mask, char *str)
120 { /* fold if case_fold_search is set */
121 if (case_fold_search)
122 return strmatch_fold(mask, str);
123
124 return strmatch(mask, str);
125 }
126
127 /*
128 * case insensitive regexp matching
129 */
130
131 int
regexec_fold(register regexp * prog,char * string)132 regexec_fold(register regexp * prog, char *string)
133 {
134 char buf[256];
135 register char c, *bp, *str, *maxb;
136
137 bp = buf, maxb = &buf[255];
138 str = string;
139 while (bp < maxb && (c = *str++) != NUL)
140
141 #ifdef _tolower
142 *bp++ = (!isascii(c) || !isupper(c)) ? c : _tolower(c);
143 #else
144 *bp++ = tolower(c);
145 #endif
146
147 *bp = NUL;
148
149 if (!regexec(prog, buf))
150 return 0;
151
152 prog->startp[0] = string + (prog->startp[0] - buf);
153 prog->endp[0] = string + (prog->endp[0] - buf);
154 return 1;
155 }
156
157 int
regexec_cf(register regexp * prog,char * string)158 regexec_cf(register regexp * prog, char *string)
159 {
160 if (case_fold_search)
161 return regexec_fold(prog, string);
162
163 return regexec(prog, string);
164 }
165