11bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata/*
21bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata * This file is part of ltrace.
3d435b43c338a692531af0fe3df29cb968a863403Petr Machata * Copyright (C) 2007,2008,2012,2013 Petr Machata, Red Hat Inc.
41bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata *
51bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata * This program is free software; you can redistribute it and/or
61bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata * modify it under the terms of the GNU General Public License as
71bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata * published by the Free Software Foundation; either version 2 of the
81bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata * License, or (at your option) any later version.
91bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata *
101bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata * This program is distributed in the hope that it will be useful, but
111bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata * WITHOUT ANY WARRANTY; without even the implied warranty of
121bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
131bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata * General Public License for more details.
141bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata *
151bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata * You should have received a copy of the GNU General Public License
161bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata * along with this program; if not, write to the Free Software
171bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
181bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata * 02110-1301 USA
191bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata */
201bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
211bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata#include <sys/types.h>
221bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata#include <regex.h>
231bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata#include <string.h>
241bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata#include <stdlib.h>
25a41e6fc5f1621bef5551edbb48c0405fc722e206Petr Machata#include <assert.h>
261bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
271bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatastatic ssize_t
281bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatamatch_character_class(const char *glob, size_t length, size_t from)
291bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata{
305ca9b6fb48aaaefdf34039d32267a02e76f4ceb8Petr Machata	assert(length > 0);
315ca9b6fb48aaaefdf34039d32267a02e76f4ceb8Petr Machata	const char *colon = memchr(glob + from + 2, ':', length - 1);
325ca9b6fb48aaaefdf34039d32267a02e76f4ceb8Petr Machata	if (colon == NULL || colon[1] != ']')
331bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		return -1;
345ca9b6fb48aaaefdf34039d32267a02e76f4ceb8Petr Machata	return colon - glob;
351bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata}
361bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
371bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatastatic ssize_t
381bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatamatch_brack(const char *glob, size_t length, size_t from, int *exclmp)
391bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata{
401bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	size_t i = from + 1;
411bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
421bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	if (i >= length)
431bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		return -1;
441bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
451bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	/* Complement operator.  */
461bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	*exclmp = 0;
471bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	if (glob[i] == '^' || glob[i] == '!') {
481bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		*exclmp = glob[i++] == '!';
491bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		if (i >= length)
501bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata			return -1;
511bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	}
521bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
531bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	/* On first character, both [ and ] are legal.  But when [ is
541bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	 * followed with :, it's character class.  */
551bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	if (glob[i] == '[' && glob[i + 1] == ':') {
561bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		ssize_t j = match_character_class(glob, length, i);
571bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		if (j < 0)
581bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		fail:
591bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata			return -1;
601bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		i = j;
611bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	}
621bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	++i; /* skip any character, including [ or ]  */
631bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
641bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	for (; i < length; ++i) {
651bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		char c = glob[i];
66d435b43c338a692531af0fe3df29cb968a863403Petr Machata		if (c == '[' && glob[i + 1] == ':') {
671bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata			ssize_t j = match_character_class(glob, length, i);
681bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata			if (j < 0)
691bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata				goto fail;
701bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata			i = j;
711bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
721bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		} else if (c == ']') {
731bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata			return i;
741bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		}
751bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	}
761bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	return -1;
771bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata}
781bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
791bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatastatic int
801bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machataappend(char **bufp, const char *str, size_t str_size,
811bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata       size_t *sizep, size_t *allocp)
821bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata{
831bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	if (str_size == 0)
841bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		str_size = strlen(str);
851bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	size_t nsize = *sizep + str_size;
861bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	if (nsize > *allocp) {
871bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		size_t nalloc = nsize * 2;
881bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		char *nbuf = realloc(*bufp, nalloc);
891bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		if (nbuf == NULL)
901bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata			return -1;
911bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		*allocp = nalloc;
921bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		*bufp = nbuf;
931bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	}
941bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
951bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	memcpy(*bufp + *sizep, str, str_size);
961bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	*sizep = nsize;
971bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	return 0;
981bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata}
991bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
1001bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatastatic int
1011bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machataglob_to_regex(const char *glob, char **retp)
1021bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata{
1031bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	size_t allocd = 0;
1041bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	size_t size = 0;
1051bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	char *buf = NULL;
1061bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
1071bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	size_t length = strlen(glob);
1081bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	int escape = 0;
1091bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	size_t i;
1101bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	for(i = 0; i < length; ++i) {
1111bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		char c = glob[i];
1121bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		if (escape) {
1131bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata			if (c == '\\') {
1141bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata				if (append(&buf, "\\\\", 0,
1151bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata					   &size, &allocd) < 0) {
1161bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata				fail:
1171bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata					free(buf);
1181bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata					return REG_ESPACE;
1191bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata				}
1201bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
1211bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata			} else if (c == '*') {
1221bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata				if (append(&buf, "\\*", 0, &size, &allocd) < 0)
1231bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata					goto fail;
1241bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata			} else if (c == '?') {
1251bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata				if (append(&buf, "?", 0, &size, &allocd) < 0)
1261bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata					goto fail;
1271bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata			} else if (append(&buf, (char[]){ '\\', c }, 2,
1281bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata					  &size, &allocd) < 0)
1291bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata				goto fail;
1301bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata			escape = 0;
1311bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		} else {
1321bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata			if (c == '\\')
1331bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata				escape = 1;
1341bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata			else if (c == '[') {
1351bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata				int exclm;
1361bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata				ssize_t j = match_brack(glob, length, i, &exclm);
13728cd84db222ce68ad13c6d37dfed5f3bb0a44784Petr Machata				if (j < 0) {
13828cd84db222ce68ad13c6d37dfed5f3bb0a44784Petr Machata					free(buf);
1391bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata					return REG_EBRACK;
14028cd84db222ce68ad13c6d37dfed5f3bb0a44784Petr Machata				}
1411bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata				if (exclm
1421bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata				    && append(&buf, "[^", 2,
1431bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata					      &size, &allocd) < 0)
1441bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata					goto fail;
1451bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata				if (append(&buf, glob + i + 2*exclm,
1461bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata					   j - i + 1 - 2*exclm,
1471bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata					   &size, &allocd) < 0)
1481bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata					goto fail;
1491bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata				i = j;
1501bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
1511bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata			} else if (c == '*') {
1521bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata				if (append(&buf, ".*", 0, &size, &allocd) < 0)
1531bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata					goto fail;
1541bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata			} else if (c == '?') {
1551bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata				if (append(&buf, ".", 0, &size, &allocd) < 0)
1561bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata					goto fail;
1571bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata			} else if (c == '.') {
1581bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata				if (append(&buf, "\\.", 0, &size, &allocd) < 0)
1591bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata					goto fail;
1601bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata			} else if (append(&buf, &c, 1, &size, &allocd) < 0)
1611bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata				goto fail;
1621bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		}
1631bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	}
1641bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
1651bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	if (escape) {
1661bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		free(buf);
1671bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		return REG_EESCAPE;
1681bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	}
1691bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
1701bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	{
1711bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		char c = 0;
1721bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		if (append(&buf, &c, 1, &size, &allocd) < 0)
1731bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata			goto fail;
1741bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	}
1751bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	*retp = buf;
176b6c5c8c51f954cfbe76424fd57c33a87166f0545Petr Machata	return 0;
1771bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata}
1781bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
1791bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machataint
1801bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machataglobcomp(regex_t *preg, const char *glob, int cflags)
1811bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata{
182a41e6fc5f1621bef5551edbb48c0405fc722e206Petr Machata	char *regex = NULL;
1831bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	int status = glob_to_regex(glob, &regex);
184b6c5c8c51f954cfbe76424fd57c33a87166f0545Petr Machata	if (status != 0)
1851bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		return status;
186a41e6fc5f1621bef5551edbb48c0405fc722e206Petr Machata	assert(regex != NULL);
1871bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	status = regcomp(preg, regex, cflags);
1881bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	free(regex);
1891bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	return status;
1901bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata}
1911bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
1921bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata#ifdef TEST
1931bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata#include <stdio.h>
1941bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
1951bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatastatic void
1961bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatatranslate(const char *glob, int exp_status, const char *expect)
1971bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata{
1981bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	char *pattern = NULL;
1991bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	int status = glob_to_regex(glob, &pattern);
2001bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	if (status != exp_status) {
2011bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		fprintf(stderr, "translating %s, expected status %d, got %d\n",
2021bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata			glob, exp_status, status);
2031bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		return;
2041bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	}
2051bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
2061bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	if (status == 0) {
2071bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		assert(pattern != NULL);
2081bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		if (strcmp(pattern, expect) != 0)
2091bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata			fprintf(stderr, "translating %s, expected %s, got %s\n",
2101bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata				glob, expect, pattern);
2111bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		free(pattern);
2121bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	} else {
2131bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		assert(pattern == NULL);
2141bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	}
2151bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata}
2161bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
2171bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatastatic void
2181bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatatry_match(const char *glob, const char *str, int expect)
2191bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata{
2201bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	regex_t preg;
2211bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	int status = globcomp(&preg, glob, 0);
2221bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	assert(status == 0);
2231bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	status = regexec(&preg, str, 0, NULL, 0);
2241bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	assert(status == expect);
2251bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	regfree(&preg);
2261bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata}
2271bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
2281bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machataint
2291bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machatamain(void)
2301bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata{
2311bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata        translate("*", 0, ".*");
2321bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata        translate("?", 0, ".");
2331bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata        translate(".*", 0, "\\..*");
2341bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata        translate("*.*", 0, ".*\\..*");
2351bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata        translate("*a*", 0, ".*a.*");
2361bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata        translate("[abc]", 0, "[abc]");
2371bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata        translate("[^abc]", 0, "[^abc]");
2381bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata        translate("[!abc]", 0, "[^abc]");
2391bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata        translate("[]]", 0, "[]]");
2401bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata        translate("[[]", 0, "[[]");
2411bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata        translate("[^]]", 0, "[^]]");
2421bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata        translate("[^a-z]", 0, "[^a-z]");
2431bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata        translate("[abc\\]]", 0, "[abc\\]]");
2441bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata        translate("[abc\\]def]", 0, "[abc\\]def]");
2451bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata        translate("[[:space:]]", 0, "[[:space:]]");
2461bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata        translate("[^[:space:]]", 0, "[^[:space:]]");
2471bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata        translate("[![:space:]]", 0, "[^[:space:]]");
2481bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata        translate("[^a-z]*", 0, "[^a-z].*");
2491bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata        translate("[^a-z]bar*", 0, "[^a-z]bar.*");
2501bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	translate("*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.", 0,
2511bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		  ".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\."
2521bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata		  ".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.");
2531bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
2541bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata        translate("\\", REG_EESCAPE, NULL);
2551bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata        translate("[^[:naotuh\\", REG_EBRACK, NULL);
2561bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata        translate("[^[:", REG_EBRACK, NULL);
2571bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata        translate("[^[", REG_EBRACK, NULL);
2581bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata        translate("[^", REG_EBRACK, NULL);
2591bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata        translate("[\\", REG_EBRACK, NULL);
2601bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata        translate("[", REG_EBRACK, NULL);
26128cd84db222ce68ad13c6d37dfed5f3bb0a44784Petr Machata        translate("abc[", REG_EBRACK, NULL);
2621bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
2631bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	try_match("abc*def", "abc012def", 0);
2641bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	try_match("abc*def", "ab012def", REG_NOMATCH);
2651bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	try_match("[abc]*def", "a1def", 0);
2661bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	try_match("[abc]*def", "b1def", 0);
2671bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	try_match("[abc]*def", "d1def", REG_NOMATCH);
2681bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
2691bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata	return 0;
2701bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata}
2711bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata
2721bbfbc6c6a7b7706bf4e8bf152d7ffc28453c3bdPetr Machata#endif
273