/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 1995 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984 AT&T */
/* All Rights Reserved */
#pragma ident "%Z%%M% %I% %E% SMI"
#include <locale.h>
#include <stdlib.h>
#include "codeset.h"
#include <ctype.h>
#include <string.h>
#include <memory.h>
#include <malloc.h>
#include <errno.h>
#include <limits.h>
NULL,
CODESET_NONE, /* no codeset */
NULL, /* not defined */
0,
};
/* tolower() and toupper() conversion table
* is hidden here to avoid being placed in the
* extern .sa file in the dynamic version of libc
*/
char _ctype_ul[] = { 0,
/* 0 1 2 3 4 5 6 7 */
'\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
'\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
'\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
'\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
' ', '!', '"', '#', '$', '%', '&', '\'',
'(', ')', '*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', ':', ';', '<', '=', '>', '?',
'@', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', '[', '\\', ']', '^', '_',
'`', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z', '{', '|', '}', '~', '\177',
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
/* following layout is:
* LC_NUMERIC LC_TIME LC_MONETARY LANGINFO LC_COLLATE LC_MESSAGES
*/
/* The array Default holds the systems notion of default locale. It is normally
* found in {LOCALE}/.default and moved to here. Note there is only one
* default locale spanning all categories
*/
/* Set the values here to guarantee stdio use of the
decimal point
*/
".", "", "", "", "",
"", "", "", "", "",
};
/* lconv is externally defined by ANSI C */
int openlocale(char *, int, char *, char *);
int getlocale_ctype(char *, char *, char *);
char *getlocale_numeric(char *, struct lconv *, char *);
void init_statics(void);
static char *getlocale_monetary(char *, struct lconv *, char *);
static char *getstr(char *, char **);
static char *getgrouping(char *, char **);
static char *getnum(char *, char *);
static char *getbool(char *, char *);
static void set_default(void);
char *
{
/* buffer for current LC_ALL value */
int nonuniform;
short ret;
char *my_lconv_numeric_str;
char *my_lconv_monetary_str;
int i;
char *p;
/* initialize my_lconv to lconv */
/*
* Following code is to avoid static initialisation of
* strings which would otherwise blow up "xstr".
*/
if (_locales[0][0] == '\0')
init_statics();
/*
* Assume all locales are set to the same value. Then
* scan through the locales to see if any are
* different. If they are the same, return the common
* value; otherwise, construct a "composite" value.
*/
nonuniform = 0; /* assume all locales set the same */
for (i = 0; i < MAXLOCALE - 2; i++) {
nonuniform = 1;
break;
}
}
if (nonuniform) {
/*
* They're not all the same. Construct a list
* of all the locale values, in order,
* separated by slashes. Return that value.
*/
}
return (buf);
} else {
/*
* They're all the same; any one you return is
* OK.
*/
return (_locales[0]);
}
} else
}
switch (category) {
case LC_ALL:
/*
* Composite value; extract each category.
*/
return (NULL); /* too long */
p = buf;
/*
* LC_CTYPE and LC_NUMERIC are set here.
* Others locales won't be set here,
* they will be just marked.
*/
for (i = 0; i < MAXLOCALE - 1; i++) {
p = strtok(p, "/");
if (p == NULL)
return (NULL); /* missing item */
switch (i) {
case LC_CTYPE - 1:
return (NULL);
break;
case LC_NUMERIC - 1:
return (NULL);
break;
case LC_TIME - 1:
return (NULL);
break;
case LC_MONETARY - 1:
return (NULL);
break;
case LANGINFO - 1:
return (NULL);
break;
case LC_COLLATE - 1:
return (NULL);
break;
case LC_MESSAGES - 1:
return (NULL);
break;
}
p = NULL;
}
return (NULL); /* extra stuff at end */
}
/* If category = LC_ALL, Drop through to test each individual
* category, one at a time. Note default rules where env vars
* are not set
*/
case LC_CTYPE:
return (NULL);
if (ret) {
}
break;
case LC_NUMERIC:
if ((my_lconv_numeric_str =
return (NULL);
if (*my_lconv_numeric_str) {
if (lconv_numeric_str != NULL)
}
break;
case LC_TIME:
return (NULL);
if (ret)
break;
case LC_MONETARY:
if ((my_lconv_monetary_str =
return (NULL);
if (*my_lconv_monetary_str) {
if (lconv_monetary_str != NULL)
}
break;
case LANGINFO:
return (NULL);
}
if (ret) {
}
break;
case LC_COLLATE:
return (NULL);
if (ret) {
}
break;
case LC_MESSAGES:
return (NULL);
if (ret) {
}
}
}
int
{
int fd;
fd = -1;
}
}
return (fd);
}
/* open and load the numeric information */
char *
{
int fd;
char *str;
char *p;
return (NULL);
if (fd == 0)
return "";
return (NULL);
return (NULL);
return (NULL);
}
/* Set last character of str to '\0' */
*p++ = '\n';
*p = '\0';
/* p will "walk thru" str */
p = str;
if (p == NULL)
goto fail;
if (p == NULL)
goto fail;
if (p == NULL)
goto fail;
return (str);
fail:
return (NULL);
}
static char *
{
int fd;
char *str;
char *p;
return (NULL);
if (fd == 0)
return ("");
return (NULL);
return (NULL);
return (NULL);
}
/* Set last character of str to '\0' */
*p++ = '\n';
*p = '\0';
/* p will "walk thru" str */
p = str;
if (p == NULL)
goto fail;
if (p == NULL)
goto fail;
if (p == NULL)
goto fail;
if (p == NULL)
goto fail;
if (p == NULL)
goto fail;
if (p == NULL)
goto fail;
if (p == NULL)
goto fail;
if (p == NULL)
goto fail;
if (p == NULL)
goto fail;
if (p == NULL)
goto fail;
if (p == NULL)
goto fail;
if (p == NULL)
goto fail;
if (p == NULL)
goto fail;
if (p == NULL)
goto fail;
return (str);
fail:
return (NULL);
}
static char *
{
*strp = p;
p = strchr(p, '\n');
if (p == NULL)
return (NULL); /* no end-of-line */
*p++ = '\0';
return (p);
}
static char *
{
int c;
if (*p == '\0')
return (NULL); /* no grouping */
*groupingp = p;
while ((c = *p) != '\n') {
if (c == '\0')
return (NULL); /* no end-of-line */
if (c >= '0' && c <= '9')
*p++ = c - '0';
else
*p++ = '\177';
}
*p++ = '\0';
return (p);
}
static char *
{
int num;
int c;
if (*p == '\0')
return (NULL); /* no number */
if (*p == '\n')
else {
num = 0;
while ((c = *p) != '\n') {
if (c < '0' || c > '9')
return (NULL); /* bad number */
p++;
}
}
*p++ = '\0';
return (p);
}
static char *
{
if (*p == '\0')
return (NULL); /* no number */
if (*p == '\n')
else {
switch (*p++) {
case 'y':
case 'Y':
case 't':
case 'T':
break;
case 'n':
case 'N':
case 'f':
case 'F':
*boolp = 0; /* false */
break;
default:
return (NULL); /* bad boolean */
}
if (*p != '\n')
return (NULL); /* noise at end of line */
}
*p++ = '\0';
return (p);
}
/*
* Open a locale file. First, check the value of "locale"; if it's a null
* string, first check the environment variable with the same name as the
* category, and then check the environment variable "LANG". If neither of
* them are set to non-null strings, use the LC_default env.var and if this
* has no meaning then assume we are running in the C locale. It is expected
* That LC_default is set across the whole system. If the resulting locale is
* longer than MAXLOCALENAME characters, reject it. Then, try looking in the
* per-machine locale directory for the file in question; if it's not found
* there, try looking in the shared locale directory.
* If there is no work to do, that is, the last setting of locales is equal
* to the current request, then we don't do anything, and exit with value 0.
* Copy the name of the locale used into "newlocale".
* Exit with positive value if we opened a file
* Exit with -1 if an error occured (invalid locale).
* Exit with 0 if there is no need to look at the disk file.
* (Assumption - there is always at least one fd open before setlocale
* is called)
*/
int
{
char *my_info;
if (*locale == '\0') {
if (*Default == '\0') {
else
}
}
}
}
return (0);
}
return (-1);
}
if (fd >= 0)
/*
* bug id 1072740; if by some chance the actual fd we're going to
* return is 0, change it to be some non-zero descriptor, because
* returning 0 means something different. If '0' is the only
* descriptor left, return an error.
*/
if (fd == 0) {
int dupfd;
fd = -1;
} else {
}
}
/* Go and get the trailer file */
if ( fd2 == 0 ) {
close(0);
}
if (fd2 == -1) {
set_default();
return (fd);
}
/*
* ctype trailer file exists - read it
*/
sizeof (code_header)) {
/*
* File format not correct
*/
set_default();
return (-1);
}
/*
* set up trailer file
*/
if (code_header.code_info_size > 0) {
set_default();
return (-1);
}
}
else {
/*
* We have a corrupted file too
*/
set_default();
return (-1);
}
}
return (fd);
}
struct lconv *
localeconv(void)
{
return (lconv);
}
struct dtconv *
localdtconv(void)
{
char *p;
short i;
char *rawmonths = "Jan\nFeb\nMar\nApr\nMay\nJun\nJul\nAug\nSep\nOct\nNov\nDec\nJanuary\nFebruary\nMarch\nApril\nMay\nJune\nJuly\nAugust\nSeptember\nOctober\nNovember\nDecember";
char *rawdays = "Sun\nMon\nTue\nWed\nThu\nFri\nSat\nSunday\nMonday\nTuesday\nWednesday\nThursday\nFriday\nSaturday";
/* fix for bugid 1067574 ... robinson */
(void)getlocale_time();
/* We malloc both the space for the dtconv struct and the
* copy of the strings above because this program is later run
* through xstr and the resultant strings are put in read-only
* text segment. Therefore we cannot write to the original
* raw strings but we can to their copies.
*/
return (NULL);
return (NULL);
return (NULL);
return (NULL);
/* p will "walk thru" str */
p = realmonths;
for (i = 0; i < 12; i++)
for (i = 0; i < 12; i++)
p = realdays;
for (i= 0; i < 7; i++)
for (i = 0; i < 7; i++)
p = realfmts;
}
return (_dtconv);
}
static void
set_default(void)
{
_code_set_info.open_flag = 0;
}
void
init_statics(void)
{
short i;
for (i=0; i<MAXLOCALE-1;i++)
}