Mail Archives: djgpp-workers/2001/01/29/09:53:13
>> I've made a second approach to the locale under DJGPP v2. This version
>> provides support for is*() family of functions from ctype as well, so
>> now we have:
[...]
> To start with you need to send it unzipped in plain text. It's hard to
> read compressed... Plus, preferably NOT as an attachment.
-- setlocal.c
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
/* Portions copyright (C) 1994-1996 by Eberhard Mattes */
/* Modified 1999-2001 by Alexander S. Aganichev <aaganichev AT netscape DOT net> */
#include <locale.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <dpmi.h>
#include <sys/farptr.h>
#include <go32.h>
#include <limits.h>
static char lcn_collate[256] = "C";
static char lcn_ctype[256] = "C";
static char lcn_monetary[256] = "C";
static char lcn_numeric[256] = "C";
static char lcn_time[256] = "C";
static char currency_symbol[16] = "";
static char mon_decimal_point[16] = "";
static char mon_thousands_sep[16] = "";
static char decimal_point[16] = ".";
static char thousands_sep[16] = "";
static struct __loc2id {
int id;
const char *loc;
int len;
} loc2id[] = {
/* add your country here ;-) */
{1, "en_US", 5},
{7, "ru_RU", 5},
{33, "fr_FR", 5},
{49, "de_DE", 5}
};
static const int cat[5] =
{LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME};
extern unsigned char __dj_collate_table[];
extern char __dj_date_format[];
extern char __dj_time_format[];
static int setlocale2(int category, const char *locale)
{
int segment, selector;
__dpmi_regs regs;
struct lconv *lcnv = localeconv();
int i, rv = 0;
char buf[256];
if (category == LC_ALL) {
rv = !setlocale2(LC_COLLATE, locale);
rv += !setlocale2(LC_CTYPE, locale);
rv += !setlocale2(LC_MONETARY, locale);
rv += !setlocale2(LC_NUMERIC, locale);
rv += !setlocale2(LC_TIME, locale);
return !rv;
}
if (!strcmp(locale, "C") || !strcmp(locale, "POSIX")) {
switch(category) {
case LC_COLLATE:
for (i = 0; i < 256; i++)
__dj_collate_table[i] = i;
strcpy (lcn_collate, locale);
return 1;
case LC_CTYPE:
for (i = 128; i < 256; i++) {
tolower(i) = i;
toupper(i) = i;
__dj_ctype_flags[i+1] = 0;
}
strcpy (lcn_ctype, locale);
return 1;
case LC_MONETARY:
if(lcnv) {
strcpy (currency_symbol, "");
lcnv->int_curr_symbol = lcnv->currency_symbol = currency_symbol;
strcpy (mon_thousands_sep, "");
lcnv->mon_thousands_sep = mon_thousands_sep;
strcpy (mon_decimal_point, "");
lcnv->mon_decimal_point = mon_decimal_point;
/* lcnv->mon_grouping = ""; */
/* lcnv->negative_sign = ""; */
/* lcnv->positive_sign = ""; */
lcnv->int_frac_digits = lcnv->frac_digits = CHAR_MAX;
lcnv->p_cs_precedes = lcnv->n_cs_precedes = CHAR_MAX;
lcnv->p_sep_by_space = lcnv->n_sep_by_space = CHAR_MAX;
/* lcnv->p_sign_posn = lcnv->n_sign_posn = CHAR_MAX; */
strcpy (lcn_monetary, locale);
return 1;
} else
return 0;
case LC_NUMERIC:
if(lcnv) {
strcpy (thousands_sep, "");
lcnv->thousands_sep = thousands_sep;
strcpy (decimal_point, ".");
lcnv->decimal_point = decimal_point;
/* lcnv->grouping = ""; */
strcpy (lcn_numeric, locale);
return 1;
} else
return 0;
case LC_TIME:
strcpy(__dj_date_format, "%m/%d/%y");
strcpy(__dj_time_format, "%H:%M:%S");
strcpy (lcn_time, locale);
return 1;
}
}
if((segment = __dpmi_allocate_dos_memory(3, &selector)) != -1) {
int CID = 0xffff, CCP = 0xffff;
if(*locale) {
int len;
const char *p = strchr(locale, '.'); if(p == NULL) p = locale + strlen (locale);
len = p - locale;
for (i = 0; i < sizeof(loc2id)/sizeof(struct __loc2id); i++)
if(!strncmp (locale, loc2id[i].loc, len >= loc2id[i].len ? len : loc2id[i].len)) {
CID = loc2id[i].id;
break;
}
if(*p == '.')
CCP = atoi(p+1);
}
regs.h.ah = 0x65;
regs.h.al = 0x01;
regs.x.bx = CCP;
regs.x.dx = CID;
regs.x.cx = 41;
regs.x.es = segment;
regs.x.di = 0;
__dpmi_int(0x21, ®s);
if(!(regs.x.flags & 1) && regs.x.cx == 41) {
if (!*locale) {
CID = _farpeekw(selector, 3);
CCP = _farpeekw(selector, 5);
locale = buf;
strcpy (buf, "en_US.");
for (i = 0; i < sizeof(loc2id)/sizeof(struct __loc2id); i++)
if(loc2id[i].id == CID) {
strcpy (buf, loc2id[i].loc);
buf[loc2id[i].len] = '.';
break;
}
itoa (CCP, &buf[strlen (buf)], 10);
}
switch(category) {
case LC_COLLATE:
regs.h.ah = 0x65;
regs.h.al = 0x06;
regs.x.bx = CCP;
regs.x.dx = CID;
regs.x.cx = 5;
regs.x.es = segment;
regs.x.di = 0;
__dpmi_int(0x21, ®s);
if(!(regs.x.flags & 1) && (regs.x.cx == 5)) {
unsigned int table = _farpeekw(selector, 3) * 16 + _farpeekw(selector, 1);
int size = _farpeekw(_dos_ds, table);
movedata(_dos_ds, table + 2, _my_ds(), (unsigned int)__dj_collate_table, size);
rv = 1;
} else
rv = 0;
strcpy (lcn_collate, locale);
rv = 1;
break;
case LC_CTYPE:
regs.h.ah = 0x65;
regs.h.al = 0x02;
regs.x.bx = CCP;
regs.x.dx = CID;
regs.x.cx = 5;
regs.x.es = segment;
regs.x.di = 0;
__dpmi_int(0x21, ®s);
if(!(regs.x.flags & 1) && (regs.x.cx == 5)) {
unsigned int table = _farpeekw(selector, 3) * 16 + _farpeekw(selector, 1);
int size = _farpeekw(_dos_ds, table);
movedata(_dos_ds, table + 2, _my_ds(), (unsigned int)&(toupper(128)), size);
/* let's build lowercase table from uppercase... */
for(i = 0; i < size; i++) {
int c = toupper(i + 128);
if((c != i + 128) && (c > 127))
tolower(c) = i + 128;
}
for(i=128; i<256; i++) {
/* By this conversion we could break something like 0xe1 in CP437
* but in most cases it better works this way */
if((toupper(tolower(i)) != i) && (tolower(toupper(i)) != i))
tolower(i) = toupper(i) = i;
if(toupper(tolower(i)) != toupper(i))
toupper(i) = i;
if(tolower(toupper(i)) != tolower(i))
tolower(i) = i;
/* Actually isgraph(), ispunct() and isspace() will return wrong
* results for some letters like 0xff in CP866 but we can't
* detect them reliably */
__dj_ctype_flags[i+1] = __dj_ISPRINT | __dj_ISGRAPH;
if(tolower(i) != toupper(i))
__dj_ctype_flags[i+1] |= __dj_ISALPHA | __dj_ISALNUM | ((i == toupper(i)) ? __dj_ISUPPER : __dj_ISLOWER);
else
__dj_ctype_flags[i+1] |= __dj_ISPUNCT;
}
rv = 1;
} else
rv = 0;
strcpy (lcn_ctype, locale);
break;
case LC_MONETARY:
if(lcnv) {
movedata(selector, 9, _my_ds(), (unsigned)currency_symbol, 5);
lcnv->int_curr_symbol = lcnv->currency_symbol = currency_symbol;
movedata(selector, 14, _my_ds(), (unsigned)mon_thousands_sep, 2);
lcnv->mon_thousands_sep = mon_thousands_sep;
movedata(selector, 16, _my_ds(), (unsigned)mon_decimal_point, 2);
lcnv->mon_decimal_point = mon_decimal_point;
/* lcnv->mon_grouping = ""; */
/* lcnv->negative_sign = ""; */
/* lcnv->positive_sign = ""; */
lcnv->int_frac_digits = lcnv->frac_digits = _farpeekb (selector, 24);
lcnv->p_cs_precedes = lcnv->n_cs_precedes = _farpeekb (selector, 23) & 1;
lcnv->p_sep_by_space = lcnv->n_sep_by_space = _farpeekb (selector, 23) & 2;
/* lcnv->p_sign_posn = lcnv->n_sign_posn = CHAR_MAX; */
strcpy (lcn_monetary, locale);
rv = 1;
} else
rv = 0;
break;
case LC_NUMERIC:
if(lcnv) {
movedata(selector, 14, _my_ds(), (unsigned)thousands_sep, 2);
lcnv->thousands_sep = thousands_sep;
movedata(selector, 16, _my_ds(), (unsigned)decimal_point, 2);
lcnv->decimal_point = decimal_point;
/* lcnv->grouping = ""; */
strcpy (lcn_numeric, locale);
rv = 1;
} else
rv = 0;
break;
case LC_TIME:
switch(_farpeekw(selector, 7)) {
case 0:
default:
strcpy(__dj_date_format, "%m/%d/%y");
break;
case 1:
strcpy(__dj_date_format, "%d/%m/%y");
break;
case 2:
strcpy(__dj_date_format, "%y/%m/%d");
break;
}
__dj_date_format[2] = __dj_date_format[5] = _farpeekb(selector, 18);
if(_farpeekb(selector, 24) & 1)
strcpy(__dj_time_format, "%H:%M:%S");
else
strcpy(__dj_time_format, "%I:%M:%S %p");
__dj_time_format[2] = __dj_time_format[5] = _farpeekb(selector, 20);
strcpy (lcn_time, locale);
rv = 1;
break;
}
} else
rv = 0;
__dpmi_free_dos_memory(selector);
return rv;
}
else
return 0;
}
char *setlocale(int category, const char *locale)
{
int i;
char buf[256];
static char rv[256];
switch (category) {
case LC_ALL:
if (stricmp (lcn_collate, lcn_ctype) == 0
&& stricmp (lcn_collate, lcn_monetary) == 0
&& stricmp (lcn_collate, lcn_numeric) == 0
&& stricmp (lcn_collate, lcn_time) == 0)
strcpy(rv, lcn_collate);
else {
/* Create a comma-separated list of locales for all the
categories. */
strcpy (rv, lcn_collate); strcat (buf, ",");
strcat (rv, lcn_ctype); strcat (buf, ",");
strcat (rv, lcn_monetary); strcat (buf, ",");
strcat (rv, lcn_numeric); strcat (buf, ",");
strcat (rv, lcn_time);
}
break;
case LC_COLLATE:
strcpy(rv, lcn_collate);
break;
case LC_CTYPE:
strcpy(rv, lcn_ctype);
break;
case LC_MONETARY:
strcpy(rv, lcn_monetary);
break;
case LC_NUMERIC:
strcpy(rv, lcn_numeric);
break;
case LC_TIME:
strcpy(rv, lcn_time);
break;
default:
return NULL;
}
if(locale != 0) {
if(*locale == '\0') {
char *lc = getenv ("LANG");
if (lc != NULL)
locale = lc;
}
if ((category != LC_ALL) || (strchr (locale, ',') == NULL))
return setlocale2 (category, locale) ? rv : NULL;
else {
char *s1, *s2;
strcpy(buf, locale);
s1 = buf;
for (i = 0; i < 5; i++) {
s2 = strchr(s1, ',');
if(s2 != NULL)
*s2 = '\0';
if(!setlocale2 (cat[i], s1) || ((s2 == NULL) && (i != 4)))
return NULL;
}
}
}
return rv;
}
#ifdef TEST
#include <stdio.h>
unsigned char __dj_collate_table[256];
char __dj_date_format[10] = "%m/%d/%y";
char __dj_time_format[16] = "%H:%M:%S";
int main(int ac, char *av[])
{
int i;
const char *loc = (ac == 1) ? "" : av[1];
char *lc = setlocale(LC_ALL, loc);
lc = setlocale(LC_ALL, NULL);
printf("Locale: %s\n", lc ? lc : "not detected");
for(i = 0; i < 256; i++)
printf("%c%c%c|", (char)i, tolower(i), toupper(i));
printf("\n");
for(i = 0; i < 256; i++)
printf("%02xh ", __dj_collate_table[i]);
printf("\n%f\n%s %s\n", 1000456.23, __dj_date_format, __dj_time_format);
}
#endif
--
-- strcoll.c
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
/* Modified 1999 by Alexander S. Aganichev <aaganichev AT netscape DOT net> */
#include <string.h>
unsigned char __dj_collate_table[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
#define coll(c) __dj_collate_table[(unsigned char)c]
int
strcoll(const char *s1, const char *s2)
{
while (coll(*s1) == coll(*s2))
{
if (*s1 == 0)
return 0;
s1++;
s2++;
}
return coll(*s1) - coll(*s2);
}
--
diff -ru src/time/strftime.c src.localized/time/strftime.c
--- src/time/strftime.c Thu Jun 3 13:27:34 1999
+++ src.localized/time/strftime.c Mon Jan 29 17:48:43 2001
@@ -1,6 +1,7 @@
/* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
+/* Modified 1999 by Alexander S. Aganichev <aaganichev AT netscape DOT net> */
#include <string.h>
#include <time.h>
#include <ctype.h>
@@ -22,6 +23,8 @@
"January", "February", "March", "April", "May", "June", "July",
"August", "September", "October", "November", "December",
};
+char __dj_date_format[10] = "%m/%d/%y";
+char __dj_time_format[16] = "%H:%M:%S";
static size_t gsize;
static char *pt;
@@ -176,7 +179,6 @@
return 0;
continue;
case 'T':
- case 'X':
if (!_fmt("%H:%M:%S", t, upcase))
return 0;
continue;
@@ -203,8 +205,12 @@
if (!_conv(t->tm_wday, 1, pad))
return 0;
continue;
+ case 'X':
+ if (!_fmt(__dj_time_format, t, upcase))
+ return 0;
+ continue;
case 'x':
- if (!_fmt("%m/%d/%y", t, upcase))
+ if (!_fmt(__dj_date_format, t, upcase))
return 0;
continue;
case 'y':
--
Alexander Aganichev
Hypercom Europe Limited, Inc.
Software Engineer
__________________________________________________________________
Get your own FREE, personal Netscape Webmail account today at http://webmail.netscape.com/
- Raw text -