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