summaryrefslogtreecommitdiff
path: root/src/lib/libast/regex/regcoll.c
blob: 64dc7a825d56ab8118c7d619d68533260b04be5e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/***********************************************************************
*                                                                      *
*               This software is part of the ast package               *
*          Copyright (c) 1985-2011 AT&T Intellectual Property          *
*                      and is licensed under the                       *
*                 Eclipse Public License, Version 1.0                  *
*                    by AT&T Intellectual Property                     *
*                                                                      *
*                A copy of the License is available at                 *
*          http://www.eclipse.org/org/documents/epl-v10.html           *
*         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
*                                                                      *
*              Information and Software Systems Research               *
*                            AT&T Research                             *
*                           Florham Park NJ                            *
*                                                                      *
*                 Glenn Fowler <gsf@research.att.com>                  *
*                  David Korn <dgk@research.att.com>                   *
*                   Phong Vo <kpv@research.att.com>                    *
*                                                                      *
***********************************************************************/
#pragma prototyped
/*
 * regex collation symbol support
 */

#include "reglib.h"

/*
 * return the collating symbol delimited by [c c], where c is either '=' or '.'
 * s points to the first char after the initial [
 * if e!=0 it is set to point to the next char in s on return
 *
 * the collating symbol is converted to multibyte in <buf,size>
 * the return value is:
 *	-1	syntax error / invalid collating element
 *	>=0	size with 0-terminated mb character (*wc != 0)
 *		or collating element (*wc == 0) in buf
 */

int
regcollate(register const char* s, char** e, char* buf, size_t size, wchar_t* wc)
{
	register int			c;
	register char*			b;
	register char*			x;
	const char*			t;
	int				i;
	int				r;
	int				term;
	wchar_t				w;
	char				xfm[256];
	char				tmp[sizeof(xfm)];

	if (size < 2 || (term = *s) != '.' && term != '=' || !*++s || *s == term && *(s + 1) == ']')
		goto nope;
	t = s;
	w = mbchar(s);
	if ((r = (s - t)) > 1)
	{
		if (*s++ != term || *s++ != ']')
			goto oops;
		goto done;
	}
	if (*s == term && *(s + 1) == ']')
	{
		s += 2;
		goto done;
	}
	b = buf;
	x = buf + size - 2;
	s = t;
	for (;;)
	{
		if (!(c = *s++))
			goto oops;
		if (c == term)
		{
			if (!(c = *s++))
				goto oops;
			if (c != term)
			{
				if (c != ']')
					goto oops;
				break;
			}
		}
		if (b < x)
			*b++ = c;
	}
	r = s - t - 2;
	w = 0;
	if (b >= x)
		goto done;
	*b = 0;
	for (i = 0; i < r && i < sizeof(tmp) - 1; i++)
		tmp[i] = '0';
	tmp[i] = 0;
	if (mbxfrm(xfm, buf, sizeof(xfm)) >= mbxfrm(xfm, tmp, sizeof(xfm)))
		goto nope;
	t = (const char*)buf;
 done:
	if (r <= size)
	{
		memcpy(buf, t, r);
		if (r < size)
			buf[r] = 0;
	}
	if (wc)
		*wc = w;
	if (e)
		*e = (char*)s;
	return r;
 oops:
 	s--;
 nope:
	if (e)
		*e = (char*)s;
	return -1;
}