#!mkcmd
# $Id: samepath.m,v 1.2 2005/10/30 03:12:36 ksb Exp $
#
%hi
#if !defined(SamePath)
#define SamePath(Mglob, Mfile)	_SamePath(Mglob, Mfile, 1)
extern int _SamePath(char *pcGlob, char *pcFile, int fDot);
#endif
%%

%c
/* _SamePath()  -- from install.d/special.c
 *	We want /bin/* to match every file in /bin OK.			(ksb)
 *	return non-zero for a glob match, 0 for not a match.
 */
int
_SamePath(pcGlob, pcFile, fDot)
char *pcGlob;		/* the pattern to match				*/
char *pcFile;		/* the file to match with			*/
int fDot;		/* are we at the start of pcFile, or post '/'	*/
{
	register char *pc;
	register int iLenGlob, iLenFile;
	auto int bFound, cStop;
	auto int fStarStar;

	for (;;) { switch (*pcGlob) {
	case '*':		/* match any string			*/
		fStarStar = '*' == pcGlob[1];
		if (fStarStar) {
			++pcGlob;
		}
		pc = ++pcGlob;
		iLenGlob = 0;
		while ('\\' != *pc && '?' != *pc && '[' != *pc && '*' != *pc && '\000' != *pc && '/' != *pc) {
			++pc, ++iLenGlob;
		}

		if (fStarStar) {
			iLenFile = strlen(pcFile);
		} else {
			iLenFile = 0;
			while ('/' != pcFile[iLenFile] && '\000' != pcFile[iLenFile] &&
			       (!fDot || '.' != pcFile[iLenFile])) {
				++iLenFile;
				fDot = 0;
			}
		}

		bFound = 0;
		do {
			if (iLenGlob == 0 || 0 == strncmp(pcGlob, pcFile, iLenGlob)) {
				if (_SamePath(pc, pcFile+iLenGlob, fDot)) {
					bFound = 1;
					break;
				}
			}
			--iLenFile, ++pcFile;
		} while (iLenFile >= iLenGlob);
		return bFound;
	case '[':		/* any of				*/
		++pcGlob;
		cStop = *pcFile++;
		if (cStop == '/')	/* range never match '/'	*/
			break;
		bFound = 0;
		if ('-' == *pcGlob) {
			bFound = '-' == cStop;
			++pcGlob;
		}
		while (']' != *pcGlob) {
			if ('-' == pcGlob[1]) {
				if (pcGlob[0] <= cStop && cStop <= pcGlob[2])
					bFound = 1;
				pcGlob += 2;
			} else {
				if (pcGlob[0] == cStop)
					bFound = 1;
			}
			++pcGlob;
		}
		++pcGlob;
		if (!bFound)
			break;
		continue;
	case '?':		/* any single char but '/'		*/
		if ('/' == *pcFile || (fDot && '.' == *pcFile) || '\000' == *pcFile)
			break;
		++pcGlob, ++pcFile;
		fDot = 0;
		continue;
	case '\\':		/* next char not special		*/
		++pcGlob;
		/*fall through*/
	case '/':		/* delimiter				*/
		fDot = 1;
		if (*pcGlob != *pcFile)
			break;
		++pcGlob;
		do {
			++pcFile;
		} while ('/' == *pcFile);
		continue;
	default:		/* or any other character		*/
		fDot = 0;
		if (*pcGlob != *pcFile)
			break;
		++pcGlob, ++pcFile;
		continue;
	case '\000':		/* end of pattern, end of file name	*/
		return '\000' == *pcFile;
	} break; }
	return 0;
}
%%
