1331722Seadler/*
288278Sphantom * Copyright (c) 2001 Alexey Zelkin <phantom@FreeBSD.org>
372321Sphantom * All rights reserved.
472321Sphantom *
572321Sphantom * Redistribution and use in source and binary forms, with or without
672321Sphantom * modification, are permitted provided that the following conditions
772321Sphantom * are met:
872321Sphantom * 1. Redistributions of source code must retain the above copyright
972321Sphantom *    notice, this list of conditions and the following disclaimer.
1072321Sphantom * 2. Redistributions in binary form must reproduce the above copyright
1172321Sphantom *    notice, this list of conditions and the following disclaimer in the
1272321Sphantom *    documentation and/or other materials provided with the distribution.
1372321Sphantom *
1472321Sphantom * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1572321Sphantom * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1672321Sphantom * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1772321Sphantom * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1872321Sphantom * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1972321Sphantom * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2072321Sphantom * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2172321Sphantom * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2272321Sphantom * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2372321Sphantom * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2472321Sphantom * SUCH DAMAGE.
2572321Sphantom */
2672321Sphantom
2792986Sobrien#include <sys/cdefs.h>
2892986Sobrien__FBSDID("$FreeBSD$");
2992986Sobrien
3072333Sphantom#include <ctype.h>
3172321Sphantom#include <limits.h>
3272407Sphantom#include <stddef.h>
3372321Sphantom
3472321Sphantomstatic const char nogrouping[] = { CHAR_MAX, '\0' };
3572321Sphantom
3672321Sphantom/*
37116875Sphantom * Internal helper used to convert grouping sequences from string
38116875Sphantom * representation into POSIX specified form, i.e.
39116875Sphantom *
40116875Sphantom * "3;3;-1" -> "\003\003\177\000"
4172321Sphantom */
4272321Sphantom
4372321Sphantomconst char *
44116875Sphantom__fix_locale_grouping_str(const char *str)
45116875Sphantom{
4672321Sphantom	char *src, *dst;
4772333Sphantom	char n;
4872321Sphantom
4972407Sphantom	if (str == NULL || *str == '\0') {
5072321Sphantom		return nogrouping;
5172321Sphantom	}
5272321Sphantom
5372407Sphantom	for (src = (char*)str, dst = (char*)str; *src != '\0'; src++) {
5472407Sphantom
5572321Sphantom		/* input string examples: "3;3", "3;2;-1" */
5672321Sphantom		if (*src == ';')
5772321Sphantom			continue;
5872321Sphantom
5972321Sphantom		if (*src == '-' && *(src+1) == '1') {
6072321Sphantom			*dst++ = CHAR_MAX;
6172321Sphantom			src++;
6272321Sphantom			continue;
6372321Sphantom		}
6472321Sphantom
6572333Sphantom		if (!isdigit((unsigned char)*src)) {
6672321Sphantom			/* broken grouping string */
6772321Sphantom			return nogrouping;
6872321Sphantom		}
6972321Sphantom
7087657Sphantom		/* assume all numbers <= 99 */
7187657Sphantom		n = *src - '0';
7287657Sphantom		if (isdigit((unsigned char)*(src+1))) {
7387657Sphantom			src++;
7472333Sphantom			n *= 10;
7572333Sphantom			n += *src - '0';
7672333Sphantom		}
7772333Sphantom
7872686Sache		*dst = n;
7972686Sache		/* NOTE: assume all input started with "0" as 'no grouping' */
8072686Sache		if (*dst == '\0')
8172686Sache			return (dst == (char*)str) ? nogrouping : str;
8272686Sache		dst++;
8372321Sphantom	}
8472321Sphantom	*dst = '\0';
8572321Sphantom	return str;
8672321Sphantom}
87