1/*
2  tre_regcomp.c - TRE POSIX compatible regex compilation functions.
3
4  This software is released under a BSD-style license.
5  See the file LICENSE for details and copyright.
6
7*/
8
9#ifdef HAVE_CONFIG_H
10#include <config.h>
11#endif /* HAVE_CONFIG_H */
12
13#include <string.h>
14#include <errno.h>
15#include <stdlib.h>
16
17#include "tre.h"
18#include "tre-internal.h"
19#include "xmalloc.h"
20
21#ifndef BUILDING_VARIANT
22int
23tre_regncomp_l(regex_t *preg, const char *regex, size_t n, int cflags, locale_t loc)
24{
25  int ret;
26#if TRE_WCHAR
27  tre_char_t *wregex;
28  size_t wlen;
29
30  wregex = xmalloc(sizeof(tre_char_t) * (n + 1));
31  if (wregex == NULL)
32    return REG_ESPACE;
33#ifdef __LIBC__
34  NORMALIZE_LOCALE(loc);
35#endif /* __LIBC__ */
36
37  /* If the current locale uses the standard single byte encoding of
38     characters, we don't do a multibyte string conversion.  If we did,
39     many applications which use the default locale would break since
40     the default "C" locale uses the 7-bit ASCII character set, and
41     all characters with the eighth bit set would be considered invalid. */
42#if TRE_MULTIBYTE
43  if (TRE_MB_CUR_MAX_L(loc) == 1)
44#endif /* TRE_MULTIBYTE */
45    {
46      unsigned int i;
47      const unsigned char *str = (const unsigned char *)regex;
48      tre_char_t *wstr = wregex;
49
50      for (i = 0; i < n; i++)
51	*(wstr++) = *(str++);
52      wlen = n;
53    }
54#if TRE_MULTIBYTE
55  else
56    {
57      size_t consumed;
58      tre_char_t *wcptr = wregex;
59#ifdef HAVE_MBSTATE_T
60      mbstate_t state;
61      memset(&state, '\0', sizeof(state));
62#endif /* HAVE_MBSTATE_T */
63      while (n > 0)
64	{
65	  consumed = tre_mbrtowc_l(wcptr, regex, n, &state, loc);
66
67	  switch (consumed)
68	    {
69	    case 0:
70	      if (*regex == '\0')
71		consumed = 1;
72	      else
73		{
74		  xfree(wregex);
75		  return REG_BADPAT;
76		}
77	      break;
78	    case (size_t)-1:
79	    case (size_t)-2:
80	      DPRINT(("mbrtowc: error %d: %s.\n", errno, strerror(errno)));
81	      xfree(wregex);
82	      return REG_ILLSEQ;
83	    }
84	  regex += consumed;
85	  n -= consumed;
86	  wcptr++;
87	}
88      wlen = wcptr - wregex;
89    }
90#endif /* TRE_MULTIBYTE */
91
92  wregex[wlen] = L'\0';
93  ret = tre_compile(preg, wregex, wlen, cflags, loc);
94  xfree(wregex);
95#else /* !TRE_WCHAR */
96#ifdef __LIBC__
97  NORMALIZE_LOCALE(loc);
98#endif /* __LIBC__ */
99
100  ret = tre_compile(preg, (const tre_char_t *)regex, n, cflags, loc);
101#endif /* !TRE_WCHAR */
102
103  return ret;
104}
105
106int
107tre_regncomp(regex_t *preg, const char *regex, size_t n, int cflags)
108{
109  locale_t loc;
110
111#ifdef __LIBC__
112  loc = __current_locale();
113#else /* !__LIBC__ */
114  loc = duplocale(NULL);
115  if (!loc) return REG_ESPACE;
116#endif /* !__LIBC__ */
117
118  return tre_regncomp_l(preg, regex, n, cflags, loc);
119}
120
121int
122tre_regcomp_l(regex_t *preg, const char *regex, int cflags, locale_t loc)
123{
124  size_t len;
125
126  if (cflags & REG_PEND)
127    {
128      if ((const char *)(preg->re_endp) < regex)
129	return REG_INVARG;
130      len = (const char *)(preg->re_endp) - regex;
131    }
132  else
133    len = strlen(regex);
134  return tre_regncomp_l(preg, regex, len, cflags, loc);
135}
136#endif /* !BUILDING_VARIANT */
137
138int
139tre_regcomp(regex_t *preg, const char *regex, int cflags)
140{
141  locale_t loc;
142
143#ifdef __LIBC__
144  loc = __current_locale();
145#else /* !__LIBC__ */
146  loc = duplocale(NULL);
147  if (!loc) return REG_ESPACE;
148#endif /* !__LIBC__ */
149
150  return tre_regcomp_l(preg, regex, cflags, loc);
151}
152
153
154#ifndef BUILDING_VARIANT
155#ifdef TRE_WCHAR
156int
157tre_regwncomp_l(regex_t *preg, const wchar_t *regex, size_t n, int cflags, locale_t loc)
158{
159#ifdef __LIBC__
160  NORMALIZE_LOCALE(loc);
161#endif /* __LIBC__ */
162  return tre_compile(preg, regex, n, cflags, loc);
163}
164
165int
166tre_regwncomp(regex_t *preg, const wchar_t *regex, size_t n, int cflags)
167{
168  locale_t loc;
169
170#ifdef __LIBC__
171  loc = __current_locale();
172#else /* !__LIBC__ */
173  loc = duplocale(NULL);
174  if (!loc) return REG_ESPACE;
175#endif /* !__LIBC__ */
176
177  return tre_compile(preg, regex, n, cflags, loc);
178}
179
180int
181tre_regwcomp_l(regex_t *preg, const wchar_t *regex, int cflags, locale_t loc)
182{
183#ifdef __LIBC__
184  NORMALIZE_LOCALE(loc);
185#endif /* __LIBC__ */
186  return tre_compile(preg, regex, wcslen(regex), cflags, loc);
187}
188
189int
190tre_regwcomp(regex_t *preg, const wchar_t *regex, int cflags)
191{
192  return tre_regwncomp(preg, regex, wcslen(regex), cflags);
193}
194#endif /* TRE_WCHAR */
195
196void
197tre_regfree(regex_t *preg)
198{
199  tre_free(preg);
200}
201#endif /* !BUILDING_VARIANT */
202
203/* EOF */
204