mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
Improve radix point (decimal point/comma) handling
The GETDECIMAL(x) macro in src/cmd/ksh93/features/locale uses a global static variable 'lp' to get the localeconv() results. Several functions in ksh use local variables called 'lp'. It's dumb luck that this hasn't conflicted yet; it's a bug waiting to happen. It's also slightly inefficient as it calls localeconv() every time. In addition there is a redundant 'sh.decomma' flag that is set to 1 if the radix point is a comma, but only once, by sh_init(). It is not updated if the locale changes. That is not correct. This commit gets rid of both and implements a new approach instead: store the radix point in sh.radixpoint at init time in sh_init(), and in the put_lang() locale discipline function, reinitialise sh.radixpoint whenever LC_ALL or LC_NUMERIC changes. The rest of the code can then simply use sh.radixpoint without worry.
This commit is contained in:
parent
6dbde5ec7c
commit
f0386a8794
9 changed files with 25 additions and 26 deletions
|
@ -1080,7 +1080,6 @@ make install
|
||||||
done string.o generated
|
done string.o generated
|
||||||
make streval.o
|
make streval.o
|
||||||
make sh/streval.c
|
make sh/streval.c
|
||||||
prev include/defs.h implicit
|
|
||||||
prev FEATURE/externs implicit
|
prev FEATURE/externs implicit
|
||||||
prev ${PACKAGE_ast_INCLUDE}/stak.h implicit
|
prev ${PACKAGE_ast_INCLUDE}/stak.h implicit
|
||||||
prev ${PACKAGE_ast_INCLUDE}/error.h implicit
|
prev ${PACKAGE_ast_INCLUDE}/error.h implicit
|
||||||
|
|
|
@ -518,8 +518,8 @@ static void print_times(struct timeval utime, struct timeval stime)
|
||||||
int st_min = stime.tv_sec / 60;
|
int st_min = stime.tv_sec / 60;
|
||||||
int st_sec = stime.tv_sec % 60;
|
int st_sec = stime.tv_sec % 60;
|
||||||
int st_ms = stime.tv_usec / 1000;
|
int st_ms = stime.tv_usec / 1000;
|
||||||
char radix = GETDECIMAL(0);
|
sfprintf(sfstdout, "%dm%02d%c%03ds %dm%02d%c%03ds\n",
|
||||||
sfprintf(sfstdout, "%dm%02d%c%03ds %dm%02d%c%03ds\n", ut_min, ut_sec, radix, ut_ms, st_min, st_sec, radix, st_ms);
|
ut_min, ut_sec, sh.radixpoint, ut_ms, st_min, st_sec, sh.radixpoint, st_ms);
|
||||||
}
|
}
|
||||||
#if _lib_getrusage
|
#if _lib_getrusage
|
||||||
/* getrusage tends to have higher precision */
|
/* getrusage tends to have higher precision */
|
||||||
|
|
|
@ -73,16 +73,16 @@ int b_sleep(register int argc,char *argv[],Shbltin_t *context)
|
||||||
ns = 0;
|
ns = 0;
|
||||||
if(*cp == 'P' || *cp == 'p')
|
if(*cp == 'P' || *cp == 'p')
|
||||||
ns = tmxdate(cp, &last, now);
|
ns = tmxdate(cp, &last, now);
|
||||||
else if(*last=='.' && sh.decomma && d==(unsigned long)d)
|
else if(*last=='.' && sh.radixpoint!='.' && d==(unsigned long)d)
|
||||||
{
|
{
|
||||||
*(pp=last) = ',';
|
*(pp=last) = sh.radixpoint;
|
||||||
if(!strchr(cp,'.'))
|
if(!strchr(cp,'.'))
|
||||||
d = strtod(cp,&last);
|
d = strtod(cp,&last);
|
||||||
*pp = '.';
|
*pp = '.';
|
||||||
if(*last==0)
|
if(*last==0)
|
||||||
goto skip;
|
goto skip;
|
||||||
}
|
}
|
||||||
else if(*last!='.' && *last!=',')
|
else if(*last!='.' && *last!=sh.radixpoint)
|
||||||
{
|
{
|
||||||
if(pp = sfprints("exact %s", cp))
|
if(pp = sfprints("exact %s", cp))
|
||||||
ns = tmxdate(pp, &last, now);
|
ns = tmxdate(pp, &last, now);
|
||||||
|
|
|
@ -32,14 +32,4 @@ cat{
|
||||||
# endif /* LC_MESSAGES */
|
# endif /* LC_MESSAGES */
|
||||||
# endif /* _hdr_locale */
|
# endif /* _hdr_locale */
|
||||||
#endif /* _PACKAGE_ast */
|
#endif /* _PACKAGE_ast */
|
||||||
#ifdef _hdr_locale
|
|
||||||
# ifdef _lib_localeconv
|
|
||||||
static struct lconv *lp;
|
|
||||||
# define GETDECIMAL(x) (((lp=localeconv()) && lp->decimal_point && *lp->decimal_point) ? *lp->decimal_point : '.' )
|
|
||||||
# else
|
|
||||||
# define GETDECIMAL(x) ('.')
|
|
||||||
# endif /* _lib_localeconv */
|
|
||||||
#else
|
|
||||||
# define GETDECIMAL(x) ('.')
|
|
||||||
#endif /* _hdr_locale */
|
|
||||||
}end
|
}end
|
||||||
|
|
|
@ -322,7 +322,7 @@ struct Shell_s
|
||||||
char subshare; /* set when comsub==2 (shared-state ${ ...; } command substitution) */
|
char subshare; /* set when comsub==2 (shared-state ${ ...; } command substitution) */
|
||||||
char toomany; /* set when out of fd's */
|
char toomany; /* set when out of fd's */
|
||||||
char instance; /* in set_instance */
|
char instance; /* in set_instance */
|
||||||
char decomma; /* decimal_point=',' */
|
char radixpoint; /* current radix point ('.' or ',') */
|
||||||
char redir0; /* redirect of 0 */
|
char redir0; /* redirect of 0 */
|
||||||
char intrace; /* set when trace expands PS4 */
|
char intrace; /* set when trace expands PS4 */
|
||||||
char *readscript; /* set before reading a script */
|
char *readscript; /* set before reading a script */
|
||||||
|
|
|
@ -403,7 +403,6 @@ static Sfdouble_t arith(const char **ptr, struct lval *lvalue, int type, Sfdoubl
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char lastbase=0, *val = xp, oerrno = errno;
|
char lastbase=0, *val = xp, oerrno = errno;
|
||||||
const char radix = GETDECIMAL(0);
|
|
||||||
lvalue->eflag = 0;
|
lvalue->eflag = 0;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
if(!sh_isoption(sh.bltindata.bnode==SYSLET ? SH_LETOCTAL : SH_POSIX))
|
if(!sh_isoption(sh.bltindata.bnode==SYSLET ? SH_LETOCTAL : SH_POSIX))
|
||||||
|
@ -432,12 +431,12 @@ static Sfdouble_t arith(const char **ptr, struct lval *lvalue, int type, Sfdoubl
|
||||||
c='e';
|
c='e';
|
||||||
else
|
else
|
||||||
c = *str;
|
c = *str;
|
||||||
if(c=='.' && radix!='.')
|
if(c=='.' && sh.radixpoint!='.')
|
||||||
{
|
{
|
||||||
errormsg(SH_DICT,ERROR_exit(1),"%s: radix point '.' requires LC_NUMERIC=C",val);
|
errormsg(SH_DICT,ERROR_exit(1),"%s: radix point '.' requires LC_NUMERIC=C",val);
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
if(c==radix || c=='e' || c == 'E' || lastbase == 16 && (c == 'p' || c == 'P'))
|
if(c==sh.radixpoint || c=='e' || c == 'E' || lastbase == 16 && (c == 'p' || c == 'P'))
|
||||||
{
|
{
|
||||||
lvalue->isfloat=1;
|
lvalue->isfloat=1;
|
||||||
r = strtold(val,&str);
|
r = strtold(val,&str);
|
||||||
|
|
|
@ -428,6 +428,17 @@ static void put_cdpath(register Namval_t* np,const char *val,int flags,Namfun_t
|
||||||
sh.cdpathlist = (void*)path_addpath((Pathcomp_t*)sh.cdpathlist,val,PATH_CDPATH);
|
sh.cdpathlist = (void*)path_addpath((Pathcomp_t*)sh.cdpathlist,val,PATH_CDPATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void init_radixpoint(void)
|
||||||
|
{
|
||||||
|
#if _hdr_locale && _lib_localeconv
|
||||||
|
struct lconv *lp;
|
||||||
|
if((lp = localeconv()) && lp->decimal_point && *lp->decimal_point)
|
||||||
|
sh.radixpoint = *lp->decimal_point;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
sh.radixpoint = '.';
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef _hdr_locale
|
#ifdef _hdr_locale
|
||||||
/* Trap for the LC_* and LANG variables */
|
/* Trap for the LC_* and LANG variables */
|
||||||
static void put_lang(Namval_t* np,const char *val,int flags,Namfun_t *fp)
|
static void put_lang(Namval_t* np,const char *val,int flags,Namfun_t *fp)
|
||||||
|
@ -474,6 +485,8 @@ static void put_cdpath(register Namval_t* np,const char *val,int flags,Namfun_t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nv_putv(np, val, flags, fp);
|
nv_putv(np, val, flags, fp);
|
||||||
|
if(type==LC_ALL || type==LC_NUMERIC)
|
||||||
|
init_radixpoint();
|
||||||
if(CC_NATIVE!=CC_ASCII && (type==LC_ALL || type==LC_LANG || type==LC_CTYPE))
|
if(CC_NATIVE!=CC_ASCII && (type==LC_ALL || type==LC_LANG || type==LC_CTYPE))
|
||||||
{
|
{
|
||||||
if(sh_lexstates[ST_BEGIN]!=sh_lexrstates[ST_BEGIN])
|
if(sh_lexstates[ST_BEGIN]!=sh_lexrstates[ST_BEGIN])
|
||||||
|
@ -1454,8 +1467,7 @@ Shell_t *sh_init(register int argc,register char *argv[], Shinit_f userinit)
|
||||||
}
|
}
|
||||||
if(beenhere==1)
|
if(beenhere==1)
|
||||||
{
|
{
|
||||||
struct lconv* lc;
|
init_radixpoint();
|
||||||
sh.decomma = (lc=localeconv()) && lc->decimal_point && *lc->decimal_point==',';
|
|
||||||
beenhere = 2;
|
beenhere = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,6 @@
|
||||||
#include <error.h>
|
#include <error.h>
|
||||||
#include <stak.h>
|
#include <stak.h>
|
||||||
#include "FEATURE/externs"
|
#include "FEATURE/externs"
|
||||||
#include "defs.h" /* for sh.decomma */
|
|
||||||
|
|
||||||
#ifndef ERROR_dictionary
|
#ifndef ERROR_dictionary
|
||||||
# define ERROR_dictionary(s) (s)
|
# define ERROR_dictionary(s) (s)
|
||||||
|
@ -513,7 +512,7 @@ static int gettok(register struct vars *vp)
|
||||||
vp->nextchr--;
|
vp->nextchr--;
|
||||||
break;
|
break;
|
||||||
case A_COMMA:
|
case A_COMMA:
|
||||||
if(sh.decomma && (c=peekchr(vp))>='0' && c<='9')
|
if(sh.radixpoint==',' && (c=peekchr(vp))>='0' && c<='9')
|
||||||
{
|
{
|
||||||
op = A_DIG;
|
op = A_DIG;
|
||||||
goto keep;
|
goto keep;
|
||||||
|
|
|
@ -238,7 +238,7 @@ static void l_time(Sfio_t *outfile,register clock_t t,int precision)
|
||||||
if(hr)
|
if(hr)
|
||||||
sfprintf(outfile,"%dh",hr);
|
sfprintf(outfile,"%dh",hr);
|
||||||
if(precision)
|
if(precision)
|
||||||
sfprintf(outfile,"%dm%02d%c%0*ds",min,sec,GETDECIMAL(0),precision,frac);
|
sfprintf(outfile,"%dm%02d%c%0*ds",min,sec,sh.radixpoint,precision,frac);
|
||||||
else
|
else
|
||||||
sfprintf(outfile,"%dm%02ds",min,sec);
|
sfprintf(outfile,"%dm%02ds",min,sec);
|
||||||
}
|
}
|
||||||
|
@ -337,7 +337,7 @@ static void p_time(Sfio_t *out, const char *format, clock_t *tm)
|
||||||
for(n = 3 + (3 - precision); n > 0; --n)
|
for(n = 3 + (3 - precision); n > 0; --n)
|
||||||
frac /= 10;
|
frac /= 10;
|
||||||
if(precision)
|
if(precision)
|
||||||
sfprintf(stkp, "%d%c%0*d", tvp->tv_sec, GETDECIMAL(0), precision, frac);
|
sfprintf(stkp, "%d%c%0*d", tvp->tv_sec, sh.radixpoint, precision, frac);
|
||||||
else
|
else
|
||||||
sfprintf(stkp, "%d", tvp->tv_sec);
|
sfprintf(stkp, "%d", tvp->tv_sec);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue