1N/A/***********************************************************************
1N/A* *
1N/A* This software is part of the ast package *
1N/A* Copyright (c) 1985-2011 AT&T Intellectual Property *
1N/A* and is licensed under the *
1N/A* Common Public License, Version 1.0 *
1N/A* by AT&T Intellectual Property *
1N/A* *
1N/A* A copy of the License is available at *
1N/A* http://www.opensource.org/licenses/cpl1.0.txt *
1N/A* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
1N/A* *
1N/A* Information and Software Systems Research *
1N/A* AT&T Research *
1N/A* Florham Park NJ *
1N/A* *
1N/A* Glenn Fowler <gsf@research.att.com> *
1N/A* David Korn <dgk@research.att.com> *
1N/A* Phong Vo <kpv@research.att.com> *
1N/A* *
1N/A***********************************************************************/
1N/A#pragma prototyped
1N/A/*
1N/A * regex collation symbol support
1N/A */
1N/A
1N/A#include "reglib.h"
1N/A
1N/A/*
1N/A * return the collating symbol delimited by [c c], where c is either '=' or '.'
1N/A * s points to the first char after the initial [
1N/A * if e!=0 it is set to point to the next char in s on return
1N/A *
1N/A * the collating symbol is converted to multibyte in <buf,size>
1N/A * the return value is:
1N/A * -1 syntax error / invalid collating element
1N/A * >=0 size with 0-terminated mb character (*wc != 0)
1N/A * or collating element (*wc == 0) in buf
1N/A */
1N/A
1N/Aint
1N/Aregcollate(register const char* s, char** e, char* buf, size_t size, wchar_t* wc)
1N/A{
1N/A register int c;
1N/A register char* b;
1N/A register char* x;
1N/A const char* t;
1N/A int i;
1N/A int r;
1N/A int term;
1N/A wchar_t w;
1N/A char xfm[256];
1N/A char tmp[sizeof(xfm)];
1N/A
1N/A if (size < 2 || (term = *s) != '.' && term != '=' || !*++s || *s == term && *(s + 1) == ']')
1N/A goto nope;
1N/A t = s;
1N/A w = mbchar(s);
1N/A if ((r = (s - t)) > 1)
1N/A {
1N/A if (*s++ != term || *s++ != ']')
1N/A goto oops;
1N/A goto done;
1N/A }
1N/A if (*s == term && *(s + 1) == ']')
1N/A {
1N/A s += 2;
1N/A goto done;
1N/A }
1N/A b = buf;
1N/A x = buf + size - 2;
1N/A s = t;
1N/A for (;;)
1N/A {
1N/A if (!(c = *s++))
1N/A goto oops;
1N/A if (c == term)
1N/A {
1N/A if (!(c = *s++))
1N/A goto oops;
1N/A if (c != term)
1N/A {
1N/A if (c != ']')
1N/A goto oops;
1N/A break;
1N/A }
1N/A }
1N/A if (b < x)
1N/A *b++ = c;
1N/A }
1N/A r = s - t - 2;
1N/A w = 0;
1N/A if (b >= x)
1N/A goto done;
1N/A *b = 0;
1N/A for (i = 0; i < r && i < sizeof(tmp) - 1; i++)
1N/A tmp[i] = '0';
1N/A tmp[i] = 0;
1N/A if (mbxfrm(xfm, buf, sizeof(xfm)) >= mbxfrm(xfm, tmp, sizeof(xfm)))
1N/A goto nope;
1N/A t = (const char*)buf;
1N/A done:
1N/A if (r <= size)
1N/A {
1N/A memcpy(buf, t, r);
1N/A if (r < size)
1N/A buf[r] = 0;
1N/A }
1N/A if (wc)
1N/A *wc = w;
1N/A if (e)
1N/A *e = (char*)s;
1N/A return r;
1N/A oops:
1N/A s--;
1N/A nope:
1N/A if (e)
1N/A *e = (char*)s;
1N/A return -1;
1N/A}