10d5acd74SJohn Marino /*
20d5acd74SJohn Marino * Copyright (c) 2001 Alexey Zelkin <phantom@FreeBSD.org>
30d5acd74SJohn Marino * All rights reserved.
40d5acd74SJohn Marino *
50d5acd74SJohn Marino * Redistribution and use in source and binary forms, with or without
60d5acd74SJohn Marino * modification, are permitted provided that the following conditions
70d5acd74SJohn Marino * are met:
80d5acd74SJohn Marino * 1. Redistributions of source code must retain the above copyright
90d5acd74SJohn Marino * notice, this list of conditions and the following disclaimer.
100d5acd74SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright
110d5acd74SJohn Marino * notice, this list of conditions and the following disclaimer in the
120d5acd74SJohn Marino * documentation and/or other materials provided with the distribution.
130d5acd74SJohn Marino *
140d5acd74SJohn Marino * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
150d5acd74SJohn Marino * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
160d5acd74SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
170d5acd74SJohn Marino * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
180d5acd74SJohn Marino * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
190d5acd74SJohn Marino * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
200d5acd74SJohn Marino * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
210d5acd74SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
220d5acd74SJohn Marino * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
230d5acd74SJohn Marino * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
240d5acd74SJohn Marino * SUCH DAMAGE.
250d5acd74SJohn Marino *
260d5acd74SJohn Marino * $FreeBSD: head/lib/libc/locale/fix_grouping.c 116875 2003-06-26 10:46:16Z phantom $
270d5acd74SJohn Marino */
280d5acd74SJohn Marino
290d5acd74SJohn Marino #include <ctype.h>
300d5acd74SJohn Marino #include <limits.h>
310d5acd74SJohn Marino #include <stddef.h>
320d5acd74SJohn Marino
33*f45ae2bfSSascha Wildner const char *__fix_locale_grouping_str(const char *);
34*f45ae2bfSSascha Wildner
350d5acd74SJohn Marino static const char nogrouping[] = { CHAR_MAX, '\0' };
360d5acd74SJohn Marino
370d5acd74SJohn Marino /*
380d5acd74SJohn Marino * Internal helper used to convert grouping sequences from string
390d5acd74SJohn Marino * representation into POSIX specified form, i.e.
400d5acd74SJohn Marino *
410d5acd74SJohn Marino * "3;3;-1" -> "\003\003\177\000"
420d5acd74SJohn Marino */
430d5acd74SJohn Marino
440d5acd74SJohn Marino const char *
__fix_locale_grouping_str(const char * str)450d5acd74SJohn Marino __fix_locale_grouping_str(const char *str)
460d5acd74SJohn Marino {
470d5acd74SJohn Marino char *src, *dst;
480d5acd74SJohn Marino char n;
490d5acd74SJohn Marino
500d5acd74SJohn Marino if (str == NULL || *str == '\0') {
510d5acd74SJohn Marino return nogrouping;
520d5acd74SJohn Marino }
530d5acd74SJohn Marino
540d5acd74SJohn Marino for (src = (char*)str, dst = (char*)str; *src != '\0'; src++) {
550d5acd74SJohn Marino
560d5acd74SJohn Marino /* input string examples: "3;3", "3;2;-1" */
570d5acd74SJohn Marino if (*src == ';')
580d5acd74SJohn Marino continue;
590d5acd74SJohn Marino
600d5acd74SJohn Marino if (*src == '-' && *(src+1) == '1') {
610d5acd74SJohn Marino *dst++ = CHAR_MAX;
620d5acd74SJohn Marino src++;
630d5acd74SJohn Marino continue;
640d5acd74SJohn Marino }
650d5acd74SJohn Marino
660d5acd74SJohn Marino if (!isdigit((unsigned char)*src)) {
670d5acd74SJohn Marino /* broken grouping string */
680d5acd74SJohn Marino return nogrouping;
690d5acd74SJohn Marino }
700d5acd74SJohn Marino
710d5acd74SJohn Marino /* assume all numbers <= 99 */
720d5acd74SJohn Marino n = *src - '0';
730d5acd74SJohn Marino if (isdigit((unsigned char)*(src+1))) {
740d5acd74SJohn Marino src++;
750d5acd74SJohn Marino n *= 10;
760d5acd74SJohn Marino n += *src - '0';
770d5acd74SJohn Marino }
780d5acd74SJohn Marino
790d5acd74SJohn Marino *dst = n;
800d5acd74SJohn Marino /* NOTE: assume all input started with "0" as 'no grouping' */
810d5acd74SJohn Marino if (*dst == '\0')
820d5acd74SJohn Marino return (dst == (char*)str) ? nogrouping : str;
830d5acd74SJohn Marino dst++;
840d5acd74SJohn Marino }
850d5acd74SJohn Marino *dst = '\0';
860d5acd74SJohn Marino return str;
870d5acd74SJohn Marino }
88