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 #if HAVE_WCTYPE_H
#include <wctype.h> #include <wctype.h>
#endif #endif
#if O_LOCALE
#include "locale.h"
#endif
/* You just can't trust some machines */ /* You just can't trust some machines */
#define my_isxdigit(C,SU,SL) (chtype(C) == NU || (C >= 'A' && \ #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 */ /* 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, 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, 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, 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, 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, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC,
/* Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß */ /* Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß */
#ifdef vms #ifdef vms
UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, LC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, UC, LC,
#else #else
UC, UC, UC, UC, UC, UC, UC, SY, UC, UC, UC, UC, UC, UC, UC, LC, UC, UC, UC, UC, UC, UC, UC, SY, UC, UC, UC, UC, UC, UC, UC, LC,
#endif #endif
/* à á â ã ä å æ ç è é ê ë ì í î ï */ /* à á â ã ä å æ ç è é ê ë ì í î ï */
LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, 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 #ifdef vms
LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC, LC
#else #else
@ -234,7 +237,6 @@ float_send(char *s, int sign)
{ {
GET_LD GET_LD
Float f = (Float)(sign*atof(s)); Float f = (Float)(sign*atof(s));
printf("buf=%s && f= %f\n", s, f);
#if HAVE_ISFINITE #if HAVE_ISFINITE
if (truePrologFlag(PLFLAG_ISO)) { /* iso */ if (truePrologFlag(PLFLAG_ISO)) { /* iso */
if (!isfinite(f)) { 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 ch = *chp;
Int val = 0L, base = ch - '0'; Int val = 0L, base = ch - '0';
int might_be_float = TRUE, has_overflow = FALSE; int might_be_float = TRUE, has_overflow = FALSE;
const unsigned char *decimalpoint;
*sp++ = ch; *sp++ = ch;
ch = getchr(inp_stream); 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); ch = getchr(inp_stream);
} }
if (might_be_float && ( ch == '.' || ch == 'e' || ch == 'E')) { if (might_be_float && ( ch == '.' || ch == 'e' || ch == 'E')) {
if (truePrologFlag(PLFLAG_ISO) && (ch == 'e' || ch == 'E')) { int has_dot = ( ch == '.' );
return num_send_error_message("Float format not allowed in ISO mode"); if (has_dot) {
} unsigned char * dp;
if (ch == '.') { int dc;
if (--max_size == 0) {
return num_send_error_message("Number Too Long");
}
*sp++ = '.';
if (chtype(ch = getchr(inp_stream)) != NU) { if (chtype(ch = getchr(inp_stream)) != NU) {
*chbuffp = '.'; if ( ch == 'e' || ch == 'E') {
*chp = ch; if (truePrologFlag(PLFLAG_ISO))
*--sp = '\0'; return num_send_error_message("Float format not allowed in ISO mode");
if (has_overflow) } else {/* followed by a letter, end of term? */
return read_int_overflow(s,base,val,sign); sp[0] = '\0';
if (sign == -1) *chbuffp = '.';
return MkIntegerTerm(-val); *chp = ch;
return MkIntegerTerm(val); 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) { if (--max_size == 0) {
return num_send_error_message("Number Too Long"); 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') { if (ch == 'e' || ch == 'E') {
char *sp0 = sp;
char cbuff = ch; char cbuff = ch;
if (--max_size == 0) { 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); ch = getchr(inp_stream);
} }
if (chtype(ch) != NU) { if (chtype(ch) != NU) {
/* error */ if (has_dot)
char *sp; return float_send(s,sign);
*chp = ch;
*chbuffp = cbuff;
*sp0 = '\0';
for (sp = s; sp < sp0; sp++) {
if (*sp == '.')
return float_send(s,sign);
}
return MkIntegerTerm(sign*val); return MkIntegerTerm(sign*val);
} }
do { do {

View File

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