improve locale support in scanner and write: basically, just hide current locale

This commit is contained in:
Vítor Santos Costa 2013-11-23 12:34:49 +00:00
parent 5013880fc5
commit d447d80fdb
2 changed files with 73 additions and 47 deletions

View File

@ -54,6 +54,9 @@
#if HAVE_WCTYPE_H
#include <wctype.h>
#endif
#if O_LOCALE
#include "locale.h"
#endif
/* You just can't trust some machines */
#define my_isxdigit(C,SU,SL) (chtype(C) == NU || (C >= 'A' && \
@ -95,28 +98,28 @@ EF,
/* 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 */
BS, BS, BS, BS, BS, BS, BS, BS, BS, BS, BS, BS, BS, BS, BS, BS,
/* 144 145 147 148 149 150 151 152 153 154 155 156 157 158 159 */
/* 144 145 ’ 147 148 149 150 151 152 153 154 155 156 157 158 159 */
BS, BS, BS, BS, BS, BS, BS, BS, BS, BS, BS, BS, BS, BS, BS, BS,
/*   ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ­ ® ¯ */
/*   ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ­ ® ¯ */
BS, SY, SY, SY, SY, SY, SY, SY, SY, SY, LC, SY, SY, SY, SY, SY,
/* ° ± ² ³ ´ µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿ */
/* ° ± ² ³ ´ µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿ */
SY, SY, LC, LC, SY, SY, SY, SY, SY, LC, LC, SY, SY, SY, SY, SY,
/* À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï */
/* À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï */
UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC,
/* Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß */
/* Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß */
#ifdef vms
UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, LC,
#else
UC, UC, UC, UC, UC, UC, UC, SY, UC, UC, UC, UC, UC, UC, UC, LC,
#endif
/* à á â ã ä å æ ç è é ê ë ì í î ï */
/* à á â ã ä å æ ç è é ê ë ì í î ï */
LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC,
/* ð ñ ò ó ô õ ö ÷ ø ù ú û ü cannot write the last three because of lcc */
/* ð ñ ò ó ô õ ö ÷ ø ù ú û ü cannot write the last three because of lcc */
#ifdef vms
LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC
#else
@ -234,7 +237,6 @@ float_send(char *s, int sign)
{
GET_LD
Float f = (Float)(sign*atof(s));
printf("buf=%s && f= %f\n", s, f);
#if HAVE_ISFINITE
if (truePrologFlag(PLFLAG_ISO)) { /* iso */
if (!isfinite(f)) {
@ -471,6 +473,7 @@ get_num(int *chp, int *chbuffp, IOSTREAM *inp_stream, char *s, UInt max_size, in
int ch = *chp;
Int val = 0L, base = ch - '0';
int might_be_float = TRUE, has_overflow = FALSE;
const unsigned char *decimalpoint;
*sp++ = ch;
ch = getchr(inp_stream);
@ -582,34 +585,50 @@ get_num(int *chp, int *chbuffp, IOSTREAM *inp_stream, char *s, UInt max_size, in
ch = getchr(inp_stream);
}
if (might_be_float && ( ch == '.' || ch == 'e' || ch == 'E')) {
if (truePrologFlag(PLFLAG_ISO) && (ch == 'e' || ch == 'E')) {
return num_send_error_message("Float format not allowed in ISO mode");
}
if (ch == '.') {
if (--max_size == 0) {
return num_send_error_message("Number Too Long");
}
*sp++ = '.';
int has_dot = ( ch == '.' );
if (has_dot) {
unsigned char * dp;
int dc;
if (chtype(ch = getchr(inp_stream)) != NU) {
*chbuffp = '.';
*chp = ch;
*--sp = '\0';
if (has_overflow)
return read_int_overflow(s,base,val,sign);
if (sign == -1)
return MkIntegerTerm(-val);
return MkIntegerTerm(val);
if ( ch == 'e' || ch == 'E') {
if (truePrologFlag(PLFLAG_ISO))
return num_send_error_message("Float format not allowed in ISO mode");
} else {/* followed by a letter, end of term? */
sp[0] = '\0';
*chbuffp = '.';
*chp = ch;
if (has_overflow)
return read_int_overflow(s,base,val,sign);
if (sign == -1)
return MkIntegerTerm(-val);
return MkIntegerTerm(val);
}
}
do {
#if O_LOCALE
if ((decimalpoint = (unsigned char*) ( localeconv()->decimal_point )) == NULL)
#endif
decimalpoint = (const unsigned char*)".";
dp =(unsigned char *)decimalpoint;
/* translate . to current locale */
while ((dc = *dp++) != '\0') {
*sp++ = dc;
if (--max_size == 0) {
return num_send_error_message("Number Too Long");
}
*sp++ = ch;
}
while (chtype(ch = getchr(inp_stream)) == NU);
/* numbers after . */
if (chtype(ch) == NU) {
do {
if (--max_size == 0) {
return num_send_error_message("Number Too Long");
}
*sp++ = ch;
}
while (chtype(ch = getchr(inp_stream)) == NU);
}
}
if (ch == 'e' || ch == 'E') {
char *sp0 = sp;
char cbuff = ch;
if (--max_size == 0) {
@ -629,15 +648,8 @@ get_num(int *chp, int *chbuffp, IOSTREAM *inp_stream, char *s, UInt max_size, in
ch = getchr(inp_stream);
}
if (chtype(ch) != NU) {
/* error */
char *sp;
*chp = ch;
*chbuffp = cbuff;
*sp0 = '\0';
for (sp = s; sp < sp0; sp++) {
if (*sp == '.')
return float_send(s,sign);
}
if (has_dot)
return float_send(s,sign);
return MkIntegerTerm(sign*val);
}
do {

View File

@ -36,6 +36,9 @@ static char SccsId[] = "%W% %G%";
#if HAVE_CTYPE_H
#include <ctype.h>
#endif
#if HAVE_LOCALE_H
#include <locale.h>
#endif
/* describe the type of the previous term to have been written */
typedef enum {
@ -331,6 +334,15 @@ wrputf(Float f, struct write_globs *wglb) /* writes a float */
int found_dot = FALSE;
char *pt = s;
int ch;
/* always use C locale for writing numbers */
#if O_LOCALE
const unsigned char *decimalpoint = (unsigned char*)
localeconv()->decimal_point;
size_t l1 = strlen(decimalpoint+1);
#else
const unsigned char *decimalpoint = ".";
l1 = 0;
#endif
if (lastw == symbol || lastw == alphanum) {
wrputc(' ', stream);
@ -345,24 +357,26 @@ wrputf(Float f, struct write_globs *wglb) /* writes a float */
pt++;
}
while ((ch = *pt) != '\0') {
switch (ch) {
case '.':
// skip locale
if (ch == decimalpoint[0] && !strncmp(pt+1, (char *)decimalpoint+1, l1)) {
found_dot = TRUE;
wrputc('.', stream);
break;
case 'e':
case 'E':
pt += l1;
ch = '.';
}
if (ch == 'e' || ch == 'E') {
if (!found_dot) {
found_dot = TRUE;
wrputs(".0", stream);
wrputs((char *)decimalpoint, stream);
wrputc('0', stream);
}
default:
wrputc(ch, stream);
found_dot = TRUE;
}
wrputc(ch, stream);
pt++;
}
if (!found_dot) {
wrputs(".0", stream);
wrputs((char *)decimalpoint, stream);
wrputc('0', stream);
}
#else
char *format_float(double f, char *buf);