xref: /minix3/usr.bin/make/str.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: str.c,v 1.35 2014/02/12 01:35:56 sjg Exp $	*/
22e2caf59SThomas Veerman 
32e2caf59SThomas Veerman /*-
42e2caf59SThomas Veerman  * Copyright (c) 1988, 1989, 1990, 1993
52e2caf59SThomas Veerman  *	The Regents of the University of California.  All rights reserved.
62e2caf59SThomas Veerman  *
72e2caf59SThomas Veerman  * This code is derived from software contributed to Berkeley by
82e2caf59SThomas Veerman  * Adam de Boor.
92e2caf59SThomas Veerman  *
102e2caf59SThomas Veerman  * Redistribution and use in source and binary forms, with or without
112e2caf59SThomas Veerman  * modification, are permitted provided that the following conditions
122e2caf59SThomas Veerman  * are met:
132e2caf59SThomas Veerman  * 1. Redistributions of source code must retain the above copyright
142e2caf59SThomas Veerman  *    notice, this list of conditions and the following disclaimer.
152e2caf59SThomas Veerman  * 2. Redistributions in binary form must reproduce the above copyright
162e2caf59SThomas Veerman  *    notice, this list of conditions and the following disclaimer in the
172e2caf59SThomas Veerman  *    documentation and/or other materials provided with the distribution.
182e2caf59SThomas Veerman  * 3. Neither the name of the University nor the names of its contributors
192e2caf59SThomas Veerman  *    may be used to endorse or promote products derived from this software
202e2caf59SThomas Veerman  *    without specific prior written permission.
212e2caf59SThomas Veerman  *
222e2caf59SThomas Veerman  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
232e2caf59SThomas Veerman  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
242e2caf59SThomas Veerman  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
252e2caf59SThomas Veerman  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
262e2caf59SThomas Veerman  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
272e2caf59SThomas Veerman  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
282e2caf59SThomas Veerman  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
292e2caf59SThomas Veerman  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
302e2caf59SThomas Veerman  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
312e2caf59SThomas Veerman  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
322e2caf59SThomas Veerman  * SUCH DAMAGE.
332e2caf59SThomas Veerman  */
342e2caf59SThomas Veerman 
352e2caf59SThomas Veerman /*-
362e2caf59SThomas Veerman  * Copyright (c) 1989 by Berkeley Softworks
372e2caf59SThomas Veerman  * All rights reserved.
382e2caf59SThomas Veerman  *
392e2caf59SThomas Veerman  * This code is derived from software contributed to Berkeley by
402e2caf59SThomas Veerman  * Adam de Boor.
412e2caf59SThomas Veerman  *
422e2caf59SThomas Veerman  * Redistribution and use in source and binary forms, with or without
432e2caf59SThomas Veerman  * modification, are permitted provided that the following conditions
442e2caf59SThomas Veerman  * are met:
452e2caf59SThomas Veerman  * 1. Redistributions of source code must retain the above copyright
462e2caf59SThomas Veerman  *    notice, this list of conditions and the following disclaimer.
472e2caf59SThomas Veerman  * 2. Redistributions in binary form must reproduce the above copyright
482e2caf59SThomas Veerman  *    notice, this list of conditions and the following disclaimer in the
492e2caf59SThomas Veerman  *    documentation and/or other materials provided with the distribution.
502e2caf59SThomas Veerman  * 3. All advertising materials mentioning features or use of this software
512e2caf59SThomas Veerman  *    must display the following acknowledgement:
522e2caf59SThomas Veerman  *	This product includes software developed by the University of
532e2caf59SThomas Veerman  *	California, Berkeley and its contributors.
542e2caf59SThomas Veerman  * 4. Neither the name of the University nor the names of its contributors
552e2caf59SThomas Veerman  *    may be used to endorse or promote products derived from this software
562e2caf59SThomas Veerman  *    without specific prior written permission.
572e2caf59SThomas Veerman  *
582e2caf59SThomas Veerman  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
592e2caf59SThomas Veerman  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
602e2caf59SThomas Veerman  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
612e2caf59SThomas Veerman  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
622e2caf59SThomas Veerman  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
632e2caf59SThomas Veerman  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
642e2caf59SThomas Veerman  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
652e2caf59SThomas Veerman  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
662e2caf59SThomas Veerman  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
672e2caf59SThomas Veerman  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
682e2caf59SThomas Veerman  * SUCH DAMAGE.
692e2caf59SThomas Veerman  */
702e2caf59SThomas Veerman 
712e2caf59SThomas Veerman #ifndef MAKE_NATIVE
72*0a6a1f1dSLionel Sambuc static char rcsid[] = "$NetBSD: str.c,v 1.35 2014/02/12 01:35:56 sjg Exp $";
732e2caf59SThomas Veerman #else
742e2caf59SThomas Veerman #include <sys/cdefs.h>
752e2caf59SThomas Veerman #ifndef lint
762e2caf59SThomas Veerman #if 0
772e2caf59SThomas Veerman static char     sccsid[] = "@(#)str.c	5.8 (Berkeley) 6/1/90";
782e2caf59SThomas Veerman #else
79*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: str.c,v 1.35 2014/02/12 01:35:56 sjg Exp $");
802e2caf59SThomas Veerman #endif
812e2caf59SThomas Veerman #endif				/* not lint */
822e2caf59SThomas Veerman #endif
832e2caf59SThomas Veerman 
842e2caf59SThomas Veerman #include "make.h"
852e2caf59SThomas Veerman 
862e2caf59SThomas Veerman /*-
872e2caf59SThomas Veerman  * str_concat --
882e2caf59SThomas Veerman  *	concatenate the two strings, inserting a space or slash between them,
892e2caf59SThomas Veerman  *	freeing them if requested.
902e2caf59SThomas Veerman  *
912e2caf59SThomas Veerman  * returns --
922e2caf59SThomas Veerman  *	the resulting string in allocated space.
932e2caf59SThomas Veerman  */
942e2caf59SThomas Veerman char *
str_concat(const char * s1,const char * s2,int flags)952e2caf59SThomas Veerman str_concat(const char *s1, const char *s2, int flags)
962e2caf59SThomas Veerman {
972e2caf59SThomas Veerman 	int len1, len2;
982e2caf59SThomas Veerman 	char *result;
992e2caf59SThomas Veerman 
1002e2caf59SThomas Veerman 	/* get the length of both strings */
1012e2caf59SThomas Veerman 	len1 = strlen(s1);
1022e2caf59SThomas Veerman 	len2 = strlen(s2);
1032e2caf59SThomas Veerman 
1042e2caf59SThomas Veerman 	/* allocate length plus separator plus EOS */
1052e2caf59SThomas Veerman 	result = bmake_malloc((u_int)(len1 + len2 + 2));
1062e2caf59SThomas Veerman 
1072e2caf59SThomas Veerman 	/* copy first string into place */
1082e2caf59SThomas Veerman 	memcpy(result, s1, len1);
1092e2caf59SThomas Veerman 
1102e2caf59SThomas Veerman 	/* add separator character */
1112e2caf59SThomas Veerman 	if (flags & STR_ADDSPACE) {
1122e2caf59SThomas Veerman 		result[len1] = ' ';
1132e2caf59SThomas Veerman 		++len1;
1142e2caf59SThomas Veerman 	} else if (flags & STR_ADDSLASH) {
1152e2caf59SThomas Veerman 		result[len1] = '/';
1162e2caf59SThomas Veerman 		++len1;
1172e2caf59SThomas Veerman 	}
1182e2caf59SThomas Veerman 
1192e2caf59SThomas Veerman 	/* copy second string plus EOS into place */
1202e2caf59SThomas Veerman 	memcpy(result + len1, s2, len2 + 1);
1212e2caf59SThomas Veerman 
1222e2caf59SThomas Veerman 	return(result);
1232e2caf59SThomas Veerman }
1242e2caf59SThomas Veerman 
1252e2caf59SThomas Veerman /*-
1262e2caf59SThomas Veerman  * brk_string --
1272e2caf59SThomas Veerman  *	Fracture a string into an array of words (as delineated by tabs or
1282e2caf59SThomas Veerman  *	spaces) taking quotation marks into account.  Leading tabs/spaces
1292e2caf59SThomas Veerman  *	are ignored.
1302e2caf59SThomas Veerman  *
1312e2caf59SThomas Veerman  * If expand is TRUE, quotes are removed and escape sequences
1322e2caf59SThomas Veerman  *  such as \r, \t, etc... are expanded.
1332e2caf59SThomas Veerman  *
1342e2caf59SThomas Veerman  * returns --
1352e2caf59SThomas Veerman  *	Pointer to the array of pointers to the words.
1362e2caf59SThomas Veerman  *      Memory containing the actual words in *buffer.
1372e2caf59SThomas Veerman  *		Both of these must be free'd by the caller.
1382e2caf59SThomas Veerman  *      Number of words in *store_argc.
1392e2caf59SThomas Veerman  */
1402e2caf59SThomas Veerman char **
brk_string(const char * str,int * store_argc,Boolean expand,char ** buffer)1412e2caf59SThomas Veerman brk_string(const char *str, int *store_argc, Boolean expand, char **buffer)
1422e2caf59SThomas Veerman {
1432e2caf59SThomas Veerman 	int argc, ch;
1442e2caf59SThomas Veerman 	char inquote, *start, *t;
1452e2caf59SThomas Veerman 	const char *p;
1462e2caf59SThomas Veerman 	int len;
1472e2caf59SThomas Veerman 	int argmax = 50, curlen = 0;
148*0a6a1f1dSLionel Sambuc     	char **argv;
1492e2caf59SThomas Veerman 
1502e2caf59SThomas Veerman 	/* skip leading space chars. */
1512e2caf59SThomas Veerman 	for (; *str == ' ' || *str == '\t'; ++str)
1522e2caf59SThomas Veerman 		continue;
1532e2caf59SThomas Veerman 
1542e2caf59SThomas Veerman 	/* allocate room for a copy of the string */
1552e2caf59SThomas Veerman 	if ((len = strlen(str) + 1) > curlen)
1562e2caf59SThomas Veerman 		*buffer = bmake_malloc(curlen = len);
1572e2caf59SThomas Veerman 
1582e2caf59SThomas Veerman 	/*
159*0a6a1f1dSLionel Sambuc 	 * initial argmax based on len
160*0a6a1f1dSLionel Sambuc 	 */
161*0a6a1f1dSLionel Sambuc 	argmax = MAX((len / 5), 50);
162*0a6a1f1dSLionel Sambuc 	argv = bmake_malloc((argmax + 1) * sizeof(char *));
163*0a6a1f1dSLionel Sambuc 
164*0a6a1f1dSLionel Sambuc 	/*
1652e2caf59SThomas Veerman 	 * copy the string; at the same time, parse backslashes,
1662e2caf59SThomas Veerman 	 * quotes and build the argument list.
1672e2caf59SThomas Veerman 	 */
1682e2caf59SThomas Veerman 	argc = 0;
1692e2caf59SThomas Veerman 	inquote = '\0';
1702e2caf59SThomas Veerman 	for (p = str, start = t = *buffer;; ++p) {
1712e2caf59SThomas Veerman 		switch(ch = *p) {
1722e2caf59SThomas Veerman 		case '"':
1732e2caf59SThomas Veerman 		case '\'':
1742e2caf59SThomas Veerman 			if (inquote) {
1752e2caf59SThomas Veerman 				if (inquote == ch)
1762e2caf59SThomas Veerman 					inquote = '\0';
1772e2caf59SThomas Veerman 				else
1782e2caf59SThomas Veerman 					break;
1792e2caf59SThomas Veerman 			}
1802e2caf59SThomas Veerman 			else {
1812e2caf59SThomas Veerman 				inquote = (char) ch;
1822e2caf59SThomas Veerman 				/* Don't miss "" or '' */
1832e2caf59SThomas Veerman 				if (start == NULL && p[1] == inquote) {
1842e2caf59SThomas Veerman 					if (!expand) {
1852e2caf59SThomas Veerman 						start = t;
1862e2caf59SThomas Veerman 						*t++ = ch;
1872e2caf59SThomas Veerman 					} else
1882e2caf59SThomas Veerman 						start = t + 1;
1892e2caf59SThomas Veerman 					p++;
1902e2caf59SThomas Veerman 					inquote = '\0';
1912e2caf59SThomas Veerman 					break;
1922e2caf59SThomas Veerman 				}
1932e2caf59SThomas Veerman 			}
1942e2caf59SThomas Veerman 			if (!expand) {
1952e2caf59SThomas Veerman 				if (!start)
1962e2caf59SThomas Veerman 					start = t;
1972e2caf59SThomas Veerman 				*t++ = ch;
1982e2caf59SThomas Veerman 			}
1992e2caf59SThomas Veerman 			continue;
2002e2caf59SThomas Veerman 		case ' ':
2012e2caf59SThomas Veerman 		case '\t':
2022e2caf59SThomas Veerman 		case '\n':
2032e2caf59SThomas Veerman 			if (inquote)
2042e2caf59SThomas Veerman 				break;
2052e2caf59SThomas Veerman 			if (!start)
2062e2caf59SThomas Veerman 				continue;
2072e2caf59SThomas Veerman 			/* FALLTHROUGH */
2082e2caf59SThomas Veerman 		case '\0':
2092e2caf59SThomas Veerman 			/*
2102e2caf59SThomas Veerman 			 * end of a token -- make sure there's enough argv
2112e2caf59SThomas Veerman 			 * space and save off a pointer.
2122e2caf59SThomas Veerman 			 */
2132e2caf59SThomas Veerman 			if (!start)
2142e2caf59SThomas Veerman 			    goto done;
2152e2caf59SThomas Veerman 
2162e2caf59SThomas Veerman 			*t++ = '\0';
2172e2caf59SThomas Veerman 			if (argc == argmax) {
2182e2caf59SThomas Veerman 				argmax *= 2;		/* ramp up fast */
2192e2caf59SThomas Veerman 				argv = (char **)bmake_realloc(argv,
2202e2caf59SThomas Veerman 				    (argmax + 1) * sizeof(char *));
2212e2caf59SThomas Veerman 			}
2222e2caf59SThomas Veerman 			argv[argc++] = start;
2232e2caf59SThomas Veerman 			start = NULL;
2242e2caf59SThomas Veerman 			if (ch == '\n' || ch == '\0') {
2252e2caf59SThomas Veerman 				if (expand && inquote) {
2262e2caf59SThomas Veerman 					free(argv);
2272e2caf59SThomas Veerman 					free(*buffer);
2282e2caf59SThomas Veerman 					*buffer = NULL;
2292e2caf59SThomas Veerman 					return NULL;
2302e2caf59SThomas Veerman 				}
2312e2caf59SThomas Veerman 				goto done;
2322e2caf59SThomas Veerman 			}
2332e2caf59SThomas Veerman 			continue;
2342e2caf59SThomas Veerman 		case '\\':
2352e2caf59SThomas Veerman 			if (!expand) {
2362e2caf59SThomas Veerman 				if (!start)
2372e2caf59SThomas Veerman 					start = t;
2382e2caf59SThomas Veerman 				*t++ = '\\';
2392e2caf59SThomas Veerman 				if (*(p+1) == '\0') /* catch '\' at end of line */
2402e2caf59SThomas Veerman 					continue;
2412e2caf59SThomas Veerman 				ch = *++p;
2422e2caf59SThomas Veerman 				break;
2432e2caf59SThomas Veerman 			}
2442e2caf59SThomas Veerman 
2452e2caf59SThomas Veerman 			switch (ch = *++p) {
2462e2caf59SThomas Veerman 			case '\0':
2472e2caf59SThomas Veerman 			case '\n':
2482e2caf59SThomas Veerman 				/* hmmm; fix it up as best we can */
2492e2caf59SThomas Veerman 				ch = '\\';
2502e2caf59SThomas Veerman 				--p;
2512e2caf59SThomas Veerman 				break;
2522e2caf59SThomas Veerman 			case 'b':
2532e2caf59SThomas Veerman 				ch = '\b';
2542e2caf59SThomas Veerman 				break;
2552e2caf59SThomas Veerman 			case 'f':
2562e2caf59SThomas Veerman 				ch = '\f';
2572e2caf59SThomas Veerman 				break;
2582e2caf59SThomas Veerman 			case 'n':
2592e2caf59SThomas Veerman 				ch = '\n';
2602e2caf59SThomas Veerman 				break;
2612e2caf59SThomas Veerman 			case 'r':
2622e2caf59SThomas Veerman 				ch = '\r';
2632e2caf59SThomas Veerman 				break;
2642e2caf59SThomas Veerman 			case 't':
2652e2caf59SThomas Veerman 				ch = '\t';
2662e2caf59SThomas Veerman 				break;
2672e2caf59SThomas Veerman 			}
2682e2caf59SThomas Veerman 			break;
2692e2caf59SThomas Veerman 		}
2702e2caf59SThomas Veerman 		if (!start)
2712e2caf59SThomas Veerman 			start = t;
2722e2caf59SThomas Veerman 		*t++ = (char) ch;
2732e2caf59SThomas Veerman 	}
2742e2caf59SThomas Veerman done:	argv[argc] = NULL;
2752e2caf59SThomas Veerman 	*store_argc = argc;
2762e2caf59SThomas Veerman 	return(argv);
2772e2caf59SThomas Veerman }
2782e2caf59SThomas Veerman 
2792e2caf59SThomas Veerman /*
2802e2caf59SThomas Veerman  * Str_FindSubstring -- See if a string contains a particular substring.
2812e2caf59SThomas Veerman  *
2822e2caf59SThomas Veerman  * Input:
2832e2caf59SThomas Veerman  *	string		String to search.
2842e2caf59SThomas Veerman  *	substring	Substring to find in string.
2852e2caf59SThomas Veerman  *
2862e2caf59SThomas Veerman  * Results: If string contains substring, the return value is the location of
2872e2caf59SThomas Veerman  * the first matching instance of substring in string.  If string doesn't
2882e2caf59SThomas Veerman  * contain substring, the return value is NULL.  Matching is done on an exact
2892e2caf59SThomas Veerman  * character-for-character basis with no wildcards or special characters.
2902e2caf59SThomas Veerman  *
2912e2caf59SThomas Veerman  * Side effects: None.
2922e2caf59SThomas Veerman  */
2932e2caf59SThomas Veerman char *
Str_FindSubstring(const char * string,const char * substring)2942e2caf59SThomas Veerman Str_FindSubstring(const char *string, const char *substring)
2952e2caf59SThomas Veerman {
2962e2caf59SThomas Veerman 	const char *a, *b;
2972e2caf59SThomas Veerman 
2982e2caf59SThomas Veerman 	/*
2992e2caf59SThomas Veerman 	 * First scan quickly through the two strings looking for a single-
3002e2caf59SThomas Veerman 	 * character match.  When it's found, then compare the rest of the
3012e2caf59SThomas Veerman 	 * substring.
3022e2caf59SThomas Veerman 	 */
3032e2caf59SThomas Veerman 
3042e2caf59SThomas Veerman 	for (b = substring; *string != 0; string += 1) {
3052e2caf59SThomas Veerman 		if (*string != *b)
3062e2caf59SThomas Veerman 			continue;
3072e2caf59SThomas Veerman 		a = string;
3082e2caf59SThomas Veerman 		for (;;) {
3092e2caf59SThomas Veerman 			if (*b == 0)
3102e2caf59SThomas Veerman 				return UNCONST(string);
3112e2caf59SThomas Veerman 			if (*a++ != *b++)
3122e2caf59SThomas Veerman 				break;
3132e2caf59SThomas Veerman 		}
3142e2caf59SThomas Veerman 		b = substring;
3152e2caf59SThomas Veerman 	}
3162e2caf59SThomas Veerman 	return NULL;
3172e2caf59SThomas Veerman }
3182e2caf59SThomas Veerman 
3192e2caf59SThomas Veerman /*
3202e2caf59SThomas Veerman  * Str_Match --
3212e2caf59SThomas Veerman  *
3222e2caf59SThomas Veerman  * See if a particular string matches a particular pattern.
3232e2caf59SThomas Veerman  *
3242e2caf59SThomas Veerman  * Results: Non-zero is returned if string matches pattern, 0 otherwise. The
3252e2caf59SThomas Veerman  * matching operation permits the following special characters in the
3262e2caf59SThomas Veerman  * pattern: *?\[] (see the man page for details on what these mean).
3272e2caf59SThomas Veerman  *
3282e2caf59SThomas Veerman  * XXX this function does not detect or report malformed patterns.
3292e2caf59SThomas Veerman  *
3302e2caf59SThomas Veerman  * Side effects: None.
3312e2caf59SThomas Veerman  */
3322e2caf59SThomas Veerman int
Str_Match(const char * string,const char * pattern)3332e2caf59SThomas Veerman Str_Match(const char *string, const char *pattern)
3342e2caf59SThomas Veerman {
3352e2caf59SThomas Veerman 	char c2;
3362e2caf59SThomas Veerman 
3372e2caf59SThomas Veerman 	for (;;) {
3382e2caf59SThomas Veerman 		/*
3392e2caf59SThomas Veerman 		 * See if we're at the end of both the pattern and the
3402e2caf59SThomas Veerman 		 * string. If, we succeeded.  If we're at the end of the
3412e2caf59SThomas Veerman 		 * pattern but not at the end of the string, we failed.
3422e2caf59SThomas Veerman 		 */
3432e2caf59SThomas Veerman 		if (*pattern == 0)
3442e2caf59SThomas Veerman 			return(!*string);
3452e2caf59SThomas Veerman 		if (*string == 0 && *pattern != '*')
3462e2caf59SThomas Veerman 			return(0);
3472e2caf59SThomas Veerman 		/*
3482e2caf59SThomas Veerman 		 * Check for a "*" as the next pattern character.  It matches
3492e2caf59SThomas Veerman 		 * any substring.  We handle this by calling ourselves
3502e2caf59SThomas Veerman 		 * recursively for each postfix of string, until either we
3512e2caf59SThomas Veerman 		 * match or we reach the end of the string.
3522e2caf59SThomas Veerman 		 */
3532e2caf59SThomas Veerman 		if (*pattern == '*') {
3542e2caf59SThomas Veerman 			pattern += 1;
3552e2caf59SThomas Veerman 			if (*pattern == 0)
3562e2caf59SThomas Veerman 				return(1);
3572e2caf59SThomas Veerman 			while (*string != 0) {
3582e2caf59SThomas Veerman 				if (Str_Match(string, pattern))
3592e2caf59SThomas Veerman 					return(1);
3602e2caf59SThomas Veerman 				++string;
3612e2caf59SThomas Veerman 			}
3622e2caf59SThomas Veerman 			return(0);
3632e2caf59SThomas Veerman 		}
3642e2caf59SThomas Veerman 		/*
3652e2caf59SThomas Veerman 		 * Check for a "?" as the next pattern character.  It matches
3662e2caf59SThomas Veerman 		 * any single character.
3672e2caf59SThomas Veerman 		 */
3682e2caf59SThomas Veerman 		if (*pattern == '?')
3692e2caf59SThomas Veerman 			goto thisCharOK;
3702e2caf59SThomas Veerman 		/*
3712e2caf59SThomas Veerman 		 * Check for a "[" as the next pattern character.  It is
3722e2caf59SThomas Veerman 		 * followed by a list of characters that are acceptable, or
3732e2caf59SThomas Veerman 		 * by a range (two characters separated by "-").
3742e2caf59SThomas Veerman 		 */
3752e2caf59SThomas Veerman 		if (*pattern == '[') {
3762e2caf59SThomas Veerman 			++pattern;
3772e2caf59SThomas Veerman 			for (;;) {
3782e2caf59SThomas Veerman 				if ((*pattern == ']') || (*pattern == 0))
3792e2caf59SThomas Veerman 					return(0);
3802e2caf59SThomas Veerman 				if (*pattern == *string)
3812e2caf59SThomas Veerman 					break;
3822e2caf59SThomas Veerman 				if (pattern[1] == '-') {
3832e2caf59SThomas Veerman 					c2 = pattern[2];
3842e2caf59SThomas Veerman 					if (c2 == 0)
3852e2caf59SThomas Veerman 						return(0);
3862e2caf59SThomas Veerman 					if ((*pattern <= *string) &&
3872e2caf59SThomas Veerman 					    (c2 >= *string))
3882e2caf59SThomas Veerman 						break;
3892e2caf59SThomas Veerman 					if ((*pattern >= *string) &&
3902e2caf59SThomas Veerman 					    (c2 <= *string))
3912e2caf59SThomas Veerman 						break;
3922e2caf59SThomas Veerman 					pattern += 2;
3932e2caf59SThomas Veerman 				}
3942e2caf59SThomas Veerman 				++pattern;
3952e2caf59SThomas Veerman 			}
3962e2caf59SThomas Veerman 			while ((*pattern != ']') && (*pattern != 0))
3972e2caf59SThomas Veerman 				++pattern;
3982e2caf59SThomas Veerman 			goto thisCharOK;
3992e2caf59SThomas Veerman 		}
4002e2caf59SThomas Veerman 		/*
4012e2caf59SThomas Veerman 		 * If the next pattern character is '/', just strip off the
4022e2caf59SThomas Veerman 		 * '/' so we do exact matching on the character that follows.
4032e2caf59SThomas Veerman 		 */
4042e2caf59SThomas Veerman 		if (*pattern == '\\') {
4052e2caf59SThomas Veerman 			++pattern;
4062e2caf59SThomas Veerman 			if (*pattern == 0)
4072e2caf59SThomas Veerman 				return(0);
4082e2caf59SThomas Veerman 		}
4092e2caf59SThomas Veerman 		/*
4102e2caf59SThomas Veerman 		 * There's no special character.  Just make sure that the
4112e2caf59SThomas Veerman 		 * next characters of each string match.
4122e2caf59SThomas Veerman 		 */
4132e2caf59SThomas Veerman 		if (*pattern != *string)
4142e2caf59SThomas Veerman 			return(0);
4152e2caf59SThomas Veerman thisCharOK:	++pattern;
4162e2caf59SThomas Veerman 		++string;
4172e2caf59SThomas Veerman 	}
4182e2caf59SThomas Veerman }
4192e2caf59SThomas Veerman 
4202e2caf59SThomas Veerman 
4212e2caf59SThomas Veerman /*-
4222e2caf59SThomas Veerman  *-----------------------------------------------------------------------
4232e2caf59SThomas Veerman  * Str_SYSVMatch --
4242e2caf59SThomas Veerman  *	Check word against pattern for a match (% is wild),
4252e2caf59SThomas Veerman  *
4262e2caf59SThomas Veerman  * Input:
4272e2caf59SThomas Veerman  *	word		Word to examine
4282e2caf59SThomas Veerman  *	pattern		Pattern to examine against
4292e2caf59SThomas Veerman  *	len		Number of characters to substitute
4302e2caf59SThomas Veerman  *
4312e2caf59SThomas Veerman  * Results:
4322e2caf59SThomas Veerman  *	Returns the beginning position of a match or null. The number
4332e2caf59SThomas Veerman  *	of characters matched is returned in len.
4342e2caf59SThomas Veerman  *
4352e2caf59SThomas Veerman  * Side Effects:
4362e2caf59SThomas Veerman  *	None
4372e2caf59SThomas Veerman  *
4382e2caf59SThomas Veerman  *-----------------------------------------------------------------------
4392e2caf59SThomas Veerman  */
4402e2caf59SThomas Veerman char *
Str_SYSVMatch(const char * word,const char * pattern,int * len)4412e2caf59SThomas Veerman Str_SYSVMatch(const char *word, const char *pattern, int *len)
4422e2caf59SThomas Veerman {
4432e2caf59SThomas Veerman     const char *p = pattern;
4442e2caf59SThomas Veerman     const char *w = word;
4452e2caf59SThomas Veerman     const char *m;
4462e2caf59SThomas Veerman 
4472e2caf59SThomas Veerman     if (*p == '\0') {
4482e2caf59SThomas Veerman 	/* Null pattern is the whole string */
4492e2caf59SThomas Veerman 	*len = strlen(w);
4502e2caf59SThomas Veerman 	return UNCONST(w);
4512e2caf59SThomas Veerman     }
4522e2caf59SThomas Veerman 
4532e2caf59SThomas Veerman     if ((m = strchr(p, '%')) != NULL) {
4542e2caf59SThomas Veerman 	/* check that the prefix matches */
4552e2caf59SThomas Veerman 	for (; p != m && *w && *w == *p; w++, p++)
4562e2caf59SThomas Veerman 	     continue;
4572e2caf59SThomas Veerman 
4582e2caf59SThomas Veerman 	if (p != m)
4592e2caf59SThomas Veerman 	    return NULL;	/* No match */
4602e2caf59SThomas Veerman 
4612e2caf59SThomas Veerman 	if (*++p == '\0') {
4622e2caf59SThomas Veerman 	    /* No more pattern, return the rest of the string */
4632e2caf59SThomas Veerman 	    *len = strlen(w);
4642e2caf59SThomas Veerman 	    return UNCONST(w);
4652e2caf59SThomas Veerman 	}
4662e2caf59SThomas Veerman     }
4672e2caf59SThomas Veerman 
4682e2caf59SThomas Veerman     m = w;
4692e2caf59SThomas Veerman 
4702e2caf59SThomas Veerman     /* Find a matching tail */
4712e2caf59SThomas Veerman     do
4722e2caf59SThomas Veerman 	if (strcmp(p, w) == 0) {
4732e2caf59SThomas Veerman 	    *len = w - m;
4742e2caf59SThomas Veerman 	    return UNCONST(m);
4752e2caf59SThomas Veerman 	}
4762e2caf59SThomas Veerman     while (*w++ != '\0');
4772e2caf59SThomas Veerman 
4782e2caf59SThomas Veerman     return NULL;
4792e2caf59SThomas Veerman }
4802e2caf59SThomas Veerman 
4812e2caf59SThomas Veerman 
4822e2caf59SThomas Veerman /*-
4832e2caf59SThomas Veerman  *-----------------------------------------------------------------------
4842e2caf59SThomas Veerman  * Str_SYSVSubst --
4852e2caf59SThomas Veerman  *	Substitute '%' on the pattern with len characters from src.
4862e2caf59SThomas Veerman  *	If the pattern does not contain a '%' prepend len characters
4872e2caf59SThomas Veerman  *	from src.
4882e2caf59SThomas Veerman  *
4892e2caf59SThomas Veerman  * Results:
4902e2caf59SThomas Veerman  *	None
4912e2caf59SThomas Veerman  *
4922e2caf59SThomas Veerman  * Side Effects:
4932e2caf59SThomas Veerman  *	Places result on buf
4942e2caf59SThomas Veerman  *
4952e2caf59SThomas Veerman  *-----------------------------------------------------------------------
4962e2caf59SThomas Veerman  */
4972e2caf59SThomas Veerman void
Str_SYSVSubst(Buffer * buf,char * pat,char * src,int len)4982e2caf59SThomas Veerman Str_SYSVSubst(Buffer *buf, char *pat, char *src, int len)
4992e2caf59SThomas Veerman {
5002e2caf59SThomas Veerman     char *m;
5012e2caf59SThomas Veerman 
5022e2caf59SThomas Veerman     if ((m = strchr(pat, '%')) != NULL) {
5032e2caf59SThomas Veerman 	/* Copy the prefix */
5042e2caf59SThomas Veerman 	Buf_AddBytes(buf, m - pat, pat);
5052e2caf59SThomas Veerman 	/* skip the % */
5062e2caf59SThomas Veerman 	pat = m + 1;
5072e2caf59SThomas Veerman     }
5082e2caf59SThomas Veerman 
5092e2caf59SThomas Veerman     /* Copy the pattern */
5102e2caf59SThomas Veerman     Buf_AddBytes(buf, len, src);
5112e2caf59SThomas Veerman 
5122e2caf59SThomas Veerman     /* append the rest */
5132e2caf59SThomas Veerman     Buf_AddBytes(buf, strlen(pat), pat);
5142e2caf59SThomas Veerman }
515