xref: /minix3/lib/libc/locale/fix_grouping.c (revision f14fb602092e015ff630df58e17c2a9cd57d29b3)
1*f14fb602SLionel Sambuc /* $NetBSD: fix_grouping.c,v 1.6 2012/03/21 14:11:24 christos Exp $ */
22fe8fb19SBen Gras 
32fe8fb19SBen Gras /*
42fe8fb19SBen Gras  * Copyright (c) 2001 Alexey Zelkin <phantom@FreeBSD.org>
52fe8fb19SBen Gras  * All rights reserved.
62fe8fb19SBen Gras  *
72fe8fb19SBen Gras  * Redistribution and use in source and binary forms, with or without
82fe8fb19SBen Gras  * modification, are permitted provided that the following conditions
92fe8fb19SBen Gras  * are met:
102fe8fb19SBen Gras  * 1. Redistributions of source code must retain the above copyright
112fe8fb19SBen Gras  *    notice, this list of conditions and the following disclaimer.
122fe8fb19SBen Gras  * 2. Redistributions in binary form must reproduce the above copyright
132fe8fb19SBen Gras  *    notice, this list of conditions and the following disclaimer in the
142fe8fb19SBen Gras  *    documentation and/or other materials provided with the distribution.
152fe8fb19SBen Gras  *
162fe8fb19SBen Gras  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
172fe8fb19SBen Gras  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
182fe8fb19SBen Gras  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
192fe8fb19SBen Gras  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
202fe8fb19SBen Gras  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
212fe8fb19SBen Gras  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
222fe8fb19SBen Gras  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
232fe8fb19SBen Gras  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
242fe8fb19SBen Gras  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
252fe8fb19SBen Gras  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
262fe8fb19SBen Gras  * SUCH DAMAGE.
272fe8fb19SBen Gras  *
282fe8fb19SBen Gras  * Original version ID:
292fe8fb19SBen Gras  *     FreeBSD: fix_grouping.c,v 1.8 2003/06/26 10:46:16 phantom Exp
302fe8fb19SBen Gras  */
312fe8fb19SBen Gras 
322fe8fb19SBen Gras #if HAVE_NBTOOL_CONFIG_H
332fe8fb19SBen Gras #include "nbtool_config.h"
342fe8fb19SBen Gras #endif
352fe8fb19SBen Gras 
362fe8fb19SBen Gras #include <sys/cdefs.h>
372fe8fb19SBen Gras #if defined(LIBC_SCCS) && !defined(lint)
38*f14fb602SLionel Sambuc __RCSID("$NetBSD: fix_grouping.c,v 1.6 2012/03/21 14:11:24 christos Exp $");
392fe8fb19SBen Gras #endif /* LIBC_SCCS and not lint */
402fe8fb19SBen Gras 
412fe8fb19SBen Gras #include <limits.h>
422fe8fb19SBen Gras #include <stddef.h>
432fe8fb19SBen Gras 
442fe8fb19SBen Gras #include "fix_grouping.h"
452fe8fb19SBen Gras 
462fe8fb19SBen Gras #ifndef NBCHAR_MAX
47*f14fb602SLionel Sambuc #define NBCHAR_MAX	(char)CHAR_MAX
482fe8fb19SBen Gras #endif
492fe8fb19SBen Gras 
502fe8fb19SBen Gras #ifndef __UNCONST
512fe8fb19SBen Gras #define __UNCONST(a)    ((void *)(unsigned long)(const void *)(a))
522fe8fb19SBen Gras #endif
532fe8fb19SBen Gras 
542fe8fb19SBen Gras static const char nogrouping[] = { NBCHAR_MAX, '\0' };
552fe8fb19SBen Gras 
562fe8fb19SBen Gras /* don't use libc's isdigit, it owes locale. */
572fe8fb19SBen Gras #define isdigit(c)	(c >= '0' && c <= '9')
582fe8fb19SBen Gras 
592fe8fb19SBen Gras /*
602fe8fb19SBen Gras  * Internal helper used to convert grouping sequences from string
612fe8fb19SBen Gras  * representation into POSIX specified form, i.e.
622fe8fb19SBen Gras  *
632fe8fb19SBen Gras  * "3;3;-1" -> "\003\003\177\000"
642fe8fb19SBen Gras  */
652fe8fb19SBen Gras 
662fe8fb19SBen Gras const char *
__fix_locale_grouping_str(const char * str)672fe8fb19SBen Gras __fix_locale_grouping_str(const char *str)
682fe8fb19SBen Gras {
692fe8fb19SBen Gras 	char *src, *dst;
702fe8fb19SBen Gras 	char n;
712fe8fb19SBen Gras 
722fe8fb19SBen Gras 	if (str == NULL || *str == '\0') {
732fe8fb19SBen Gras 		return nogrouping;
742fe8fb19SBen Gras 	}
752fe8fb19SBen Gras 
762fe8fb19SBen Gras 	for (src = __UNCONST(str), dst = __UNCONST(str); *src != '\0'; src++) {
772fe8fb19SBen Gras 
782fe8fb19SBen Gras 		/* input string examples: "3;3", "3;2;-1" */
792fe8fb19SBen Gras 		if (*src == ';')
802fe8fb19SBen Gras 			continue;
812fe8fb19SBen Gras 
822fe8fb19SBen Gras 		if (*src == '-' && *(src+1) == '1') {
832fe8fb19SBen Gras 			*dst++ = NBCHAR_MAX;
842fe8fb19SBen Gras 			src++;
852fe8fb19SBen Gras 			continue;
862fe8fb19SBen Gras 		}
872fe8fb19SBen Gras 
882fe8fb19SBen Gras 		if (!isdigit((unsigned char)*src)) {
892fe8fb19SBen Gras 			/* broken grouping string */
902fe8fb19SBen Gras 			return nogrouping;
912fe8fb19SBen Gras 		}
922fe8fb19SBen Gras 
932fe8fb19SBen Gras 		/* assume all numbers <= 99 */
942fe8fb19SBen Gras 		n = *src - '0';
952fe8fb19SBen Gras 		if (isdigit((unsigned char)*(src+1))) {
962fe8fb19SBen Gras 			src++;
972fe8fb19SBen Gras 			n *= 10;
982fe8fb19SBen Gras 			n += *src - '0';
992fe8fb19SBen Gras 		}
1002fe8fb19SBen Gras 
1012fe8fb19SBen Gras 		*dst = n;
1022fe8fb19SBen Gras 		/* NOTE: assume all input started with "0" as 'no grouping' */
1032fe8fb19SBen Gras 		if (*dst == '\0')
1042fe8fb19SBen Gras 			return (dst == __UNCONST(str)) ? nogrouping : str;
1052fe8fb19SBen Gras 		dst++;
1062fe8fb19SBen Gras 	}
1072fe8fb19SBen Gras 	*dst = '\0';
1082fe8fb19SBen Gras 	return str;
1092fe8fb19SBen Gras }
110