2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * $TOG: strwcmp.C /main/7 1998/04/17 11:25:04 mgreess $
26 * (c) Copyright 1996 Digital Equipment Corporation.
27 * (c) Copyright 1993,1994,1996 Hewlett-Packard Company.
28 * (c) Copyright 1993,1994,1996 International Business Machines Corp.
29 * (c) Copyright 1993,1994,1996 Sun Microsystems, Inc.
30 * (c) Copyright 1993,1994,1996 Novell, Inc.
31 * (c) Copyright 1996 FUJITSU LIMITED.
32 * (c) Copyright 1996 Hitachi.
38 #include <codelibs/nl_hack.h>
40 #include <codelibs/stringx.h>
42 #define QUOTE 0x40000000
45 static char tabs[] = " ";
46 # define TABS (&tabs[10 - depth])
49 RETURN(int ret, int depth)
51 printf("%sreturning %s\n", TABS,
52 (ret ? "SUCCEEDED" : "FAILED"));
56 #define RETURN(x,y) (x)
60 static int match(const char *, const char *, int);
61 static const char *next_patt(const char *, int advance = 1);
62 static int match_class(const char *, char);
66 next_char(register const char *pattern, const char **cpp = NULL)
69 wchar_t __nlh_char[1];
71 ret = pattern ? (int)CHARAT(pattern) : '\0';
75 /* AIX needs line broken to get around macro bug (Temporary Fix) */
77 CHARAT(pattern) != '\0')
78 ret = QUOTE | (int)CHARADV(pattern);
87 strwcmp(const char *pattern, const char *string)
89 * String 'pattern' is matched against string 'string'. Zero is
90 * returned if the match is successful. 'pattern' may contain the
91 * shell metas * and ? and the semantics are the same. ? and * may
95 return !match(pattern, string, 0);
98 // stwpat returns a pointer to the first meta-character if the string
99 // is a pattern, else NULL
101 strwpat(register const char *pattern)
104 register char *prev_pattern = (char *)pattern;
105 wchar_t __nlh_char[1];
107 while ((ch = next_char(pattern, &pattern)) != '\0')
116 register const char *eop = next_patt(prev_pattern, 0);
117 if (CHARAT(eop) == ']')
123 prev_pattern = (char *)pattern;
130 * match will check to see if pattern can successfully be applied to
131 * the beginning of string.
134 match(register const char *pattern, register const char *string, int depth)
137 printf("%smatch(\"%s\", \"%s\")\n", TABS, pattern, string);
141 wchar_t __nlh_char[1];
143 while ((ch = next_char(pattern, &cp)) != '\0')
145 const char *laststr = string;
146 register int testchar = (int)CHARADV(string);
151 pattern = cp; /* skip over '*' */
152 string = laststr; /* reverse - testchar not used */
154 const char *s = string;
156 if (match(pattern, s, depth + 1))
157 return RETURN(1, depth);
158 while (CHARADV(s) != '\0');
159 return RETURN(0, depth);
164 int mt = match_class(pattern, testchar);
166 return RETURN(0, depth);
167 else if (mt == 2 && ch != testchar)
168 return RETURN(0, depth);
172 if ((ch & ~QUOTE) != testchar)
173 return RETURN(0, depth);
177 if (testchar == '\0')
178 string = laststr; // reverse string
180 pattern = next_patt(pattern);
183 return RETURN(CHARAT(string) == '\0', depth);
187 match_class(register const char *clss, register char testchar)
189 * pattern is a pointer to the leading [ of
190 * a shell-type class. testchar is the character to match against
194 int match = 1; /* false if first char is '!' */
195 wchar_t __nlh_char[1];
197 /* find end of class, ie an un-escaped ']' */
198 register const char *eop = next_patt(clss, 0);
201 if (CHARAT(eop) != ']')
204 if (CHARAT(clss) == '!')
212 register int ch = next_char(clss, &clss);
213 char const *clss_end = clss;
214 int sep = next_char(clss_end, &clss_end);
215 int ch2 = next_char(clss_end, &clss_end);
217 /* check if next three chars are a range */
218 if (sep == '-' && ch2 != ']')
220 /* check range - we have to use strcoll to do it right */
221 char c1[MB_LEN_MAX+1], c2[MB_LEN_MAX+1], tc[MB_LEN_MAX+1];
222 memset(c1, 0, sizeof(c1));
223 memset(c2, 0, sizeof(c2));
224 memset(tc, 0, sizeof(tc));
231 /* if (ch <= testchar && testchar <= ch2) // Original code */
233 /* Second implementation:
234 * if (nl_strncmp(c1, tc, 1) <= 0 && nl_strncmp(tc, c2, 1) <= 0)
238 /* Third, portable implementation: */
239 if (strcoll(c1, tc) <= 0 && strcoll(tc, c2) <= 0)
243 else /* they are not a range, check simple
246 if ((ch & ~QUOTE) == testchar)
255 next_patt(register const char *pattern, int advance)
257 wchar_t __nlh_char[1];
259 if (CHARAT(pattern) == '[')
262 const char *pp = pattern;
265 if (CHARAT(pp) == '^')
268 if (CHARAT(pp) == ']')
272 for (; (ch = next_char(pp, &np)) != '\0'; pp = np)
274 return (advance ? np : pp);
277 next_char(pattern, &pattern);
285 char pattern[50], string[50];
291 if (fgets(pattern, sizeof(pattern)-1, stdin) == NULL)
294 if (fgets(string, sizeof(pattern)-1, stdin) == NULL)
296 printf("MATCH is %s\n",
297 ((strwcmp(pattern, string) == 0) ? "SUCCEEDED" : "FAILED"));
299 printf("MATCHI is %s\n",
300 ((strwcmpi(pattern, string) == 0) ? "SUCCEEDED" : "FAILED"));