summaryrefslogtreecommitdiff
path: root/strings
diff options
context:
space:
mode:
Diffstat (limited to 'strings')
-rw-r--r--strings/Makefile.am8
-rw-r--r--strings/ctype-big5.c3
-rw-r--r--strings/ctype-bin.c7
-rw-r--r--strings/ctype-czech.c1
-rw-r--r--strings/ctype-euc_kr.c5
-rw-r--r--strings/ctype-gb2312.c3
-rw-r--r--strings/ctype-gbk.c3
-rw-r--r--strings/ctype-latin1_de.c1
-rw-r--r--strings/ctype-mb.c2
-rw-r--r--strings/ctype-simple.c188
-rw-r--r--strings/ctype-sjis.c3
-rw-r--r--strings/ctype-tis620.c3
-rw-r--r--strings/ctype-ujis.c3
-rw-r--r--strings/ctype-utf8.c38
-rw-r--r--strings/ctype-win1250ch.c3
-rw-r--r--strings/ctype.c257
-rw-r--r--strings/my_vsnprintf.c166
-rw-r--r--strings/xml.c374
18 files changed, 913 insertions, 155 deletions
diff --git a/strings/Makefile.am b/strings/Makefile.am
index ac0b6d7f1e0..dea9effdfeb 100644
--- a/strings/Makefile.am
+++ b/strings/Makefile.am
@@ -22,19 +22,19 @@ pkglib_LIBRARIES = libmystrings.a
# Exact one of ASSEMBLER_X
if ASSEMBLER_x86
ASRCS = strings-x86.s longlong2str-x86.s
-CSRCS = bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c atof.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-latin1_de.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-win1250ch.c ctype-bin.c
+CSRCS = bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c atof.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-latin1_de.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-win1250ch.c ctype-bin.c my_vsnprintf.c xml.c
else
if ASSEMBLER_sparc32
# These file MUST all be on the same line!! Otherwise automake
# generats a very broken makefile
ASRCS = bmove_upp-sparc.s strappend-sparc.s strend-sparc.s strinstr-sparc.s strmake-sparc.s strmov-sparc.s strnmov-sparc.s strstr-sparc.s
-CSRCS = strcont.c strfill.c strcend.c is_prefix.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c atof.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c strxmov.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-latin1_de.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-win1250ch.c ctype-bin.c
+CSRCS = strcont.c strfill.c strcend.c is_prefix.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c atof.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c strxmov.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-latin1_de.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-win1250ch.c ctype-bin.c my_vsnprintf.c xml.c
else
#no assembler
ASRCS =
# These file MUST all be on the same line!! Otherwise automake
# generats a very broken makefile
-CSRCS = strxmov.c bmove_upp.c strappend.c strcont.c strend.c strfill.c strcend.c is_prefix.c strstr.c strinstr.c strmake.c strnmov.c strmov.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c atof.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-latin1_de.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-win1250ch.c ctype-bin.c
+CSRCS = strxmov.c bmove_upp.c strappend.c strcont.c strend.c strfill.c strcend.c is_prefix.c strstr.c strinstr.c strmake.c strnmov.c strmov.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c atof.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-latin1_de.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-win1250ch.c ctype-bin.c my_vsnprintf.c xml.c
endif
endif
@@ -44,7 +44,7 @@ noinst_PROGRAMS = conf_to_src
EXTRA_DIST = ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-win1250ch.c \
ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-utf8.c \
ctype-tis620.c ctype-ujis.c ctype-latin1_de.c \
- strto.c strings-x86.s \
+ xml.c strto.c strings-x86.s \
longlong2str.c longlong2str-x86.s \
strxmov.c bmove_upp.c strappend.c strcont.c strend.c \
strfill.c strcend.c is_prefix.c strstr.c strinstr.c \
diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c
index 573c3c67db0..408c7f8fe35 100644
--- a/strings/ctype-big5.c
+++ b/strings/ctype-big5.c
@@ -6218,7 +6218,8 @@ my_mb_wc_big5(CHARSET_INFO *cs __attribute__((unused)),
CHARSET_INFO my_charset_big5 =
{
1, /* number */
- MY_CS_COMPILED, /* state */
+ MY_CS_COMPILED|MY_CS_PRIMARY, /* state */
+ "big5", /* cs name */
"big5", /* name */
"", /* comment */
ctype_big5,
diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c
index 7848862a0db..e20afff1470 100644
--- a/strings/ctype-bin.c
+++ b/strings/ctype-bin.c
@@ -47,8 +47,8 @@ static int my_strnncoll_binary(CHARSET_INFO * cs __attribute__((unused)),
const uchar *s, uint slen,
const uchar *t, uint tlen)
{
- int len = ( slen > tlen ) ? tlen : slen;
- return memcmp(s,t,len);
+ int cmp= memcmp(s,t,min(slen,tlen));
+ return cmp ? cmp : (int) (slen - tlen);
}
static void my_caseup_str_bin(CHARSET_INFO *cs __attribute__((unused)),
@@ -259,7 +259,8 @@ static int my_wildcmp_bin(CHARSET_INFO *cs,
static CHARSET_INFO my_charset_bin_st =
{
63, /* number */
- MY_CS_COMPILED|MY_CS_BINSORT,/* state */
+ MY_CS_COMPILED|MY_CS_BINSORT|MY_CS_PRIMARY,/* state */
+ "binary", /* cs name */
"binary", /* name */
"", /* comment */
ctype_bin, /* ctype */
diff --git a/strings/ctype-czech.c b/strings/ctype-czech.c
index d309ddc80c8..bb0afe98032 100644
--- a/strings/ctype-czech.c
+++ b/strings/ctype-czech.c
@@ -597,6 +597,7 @@ CHARSET_INFO my_charset_czech =
{
2, /* number */
MY_CS_COMPILED, /* state */
+ "latin2", /* cs name */
"czech", /* name */
"", /* comment */
ctype_czech,
diff --git a/strings/ctype-euc_kr.c b/strings/ctype-euc_kr.c
index 2fe8db85369..814f43166c4 100644
--- a/strings/ctype-euc_kr.c
+++ b/strings/ctype-euc_kr.c
@@ -8636,8 +8636,9 @@ my_mb_wc_euc_kr(CHARSET_INFO *cs __attribute__((unused)),
CHARSET_INFO my_charset_euc_kr =
{
19, /* number */
- MY_CS_COMPILED, /* state */
- "euc_kr", /* name */
+ MY_CS_COMPILED|MY_CS_PRIMARY, /* state */
+ "euckr", /* cs name */
+ "euckr", /* name */
"", /* comment */
ctype_euc_kr,
to_lower_euc_kr,
diff --git a/strings/ctype-gb2312.c b/strings/ctype-gb2312.c
index c06b70011df..d575e48a59a 100644
--- a/strings/ctype-gb2312.c
+++ b/strings/ctype-gb2312.c
@@ -5686,7 +5686,8 @@ my_mb_wc_gb2312(CHARSET_INFO *cs __attribute__((unused)),
CHARSET_INFO my_charset_gb2312 =
{
24, /* number */
- MY_CS_COMPILED, /* state */
+ MY_CS_COMPILED|MY_CS_PRIMARY, /* state */
+ "gb2312", /* cs name */
"gb2312", /* name */
"", /* comment */
ctype_gb2312,
diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c
index 82a75188c24..0094a93e5f8 100644
--- a/strings/ctype-gbk.c
+++ b/strings/ctype-gbk.c
@@ -9873,7 +9873,8 @@ my_mb_wc_gbk(CHARSET_INFO *cs __attribute__((unused)),
CHARSET_INFO my_charset_gbk =
{
28, /* number */
- MY_CS_COMPILED, /* state */
+ MY_CS_COMPILED|MY_CS_PRIMARY, /* state */
+ "gbk", /* cs name */
"gbk", /* name */
"", /* comment */
ctype_gbk,
diff --git a/strings/ctype-latin1_de.c b/strings/ctype-latin1_de.c
index 49acd3fa8a8..166e059ef42 100644
--- a/strings/ctype-latin1_de.c
+++ b/strings/ctype-latin1_de.c
@@ -415,6 +415,7 @@ CHARSET_INFO my_charset_latin1_de =
{
31, /* number */
MY_CS_COMPILED, /* state */
+ "latin1", /* cs name */
"latin1_de", /* name */
"", /* comment */
ctype_latin1_de,
diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c
index 092b7aa4f0f..5b963e74db9 100644
--- a/strings/ctype-mb.c
+++ b/strings/ctype-mb.c
@@ -201,7 +201,7 @@ int my_wildcmp_mb(CHARSET_INFO *cs,
{ // Found w_many
uchar cmp;
const char* mb = wildstr;
- int mblen;
+ int mblen=0;
wildstr++;
/* Remove any '%' and '_' from the wild search string */
diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c
index fa1ece20b3e..9bcafa9f164 100644
--- a/strings/ctype-simple.c
+++ b/strings/ctype-simple.c
@@ -110,88 +110,40 @@ int my_mb_wc_8bit(CHARSET_INFO *cs,my_wc_t *wc,
}
int my_wc_mb_8bit(CHARSET_INFO *cs,my_wc_t wc,
- unsigned char *s,
- unsigned char *e __attribute__((unused)))
+ unsigned char *str,
+ unsigned char *end __attribute__((unused)))
{
MY_UNI_IDX *idx;
- for(idx=cs->tab_from_uni; idx->tab ; idx++){
- if(idx->from<=wc && idx->to>=wc){
- s[0]=idx->tab[wc-idx->from];
- return (!s[0] && wc) ? MY_CS_ILUNI : 1;
+ for (idx=cs->tab_from_uni; idx->tab ; idx++)
+ {
+ if (idx->from <= wc && idx->to >= wc)
+ {
+ str[0]= idx->tab[wc - idx->from];
+ return (!str[0] && wc) ? MY_CS_ILUNI : 1;
}
}
return MY_CS_ILUNI;
}
-#ifdef NOT_USED
-static int my_vsnprintf_8bit(char *to, size_t n, const char* fmt, va_list ap)
-{
- char *start=to, *end=to+n-1;
- for (; *fmt ; fmt++)
- {
- if (fmt[0] != '%')
- {
- if (to == end) /* End of buffer */
- break;
- *to++= *fmt; /* Copy ordinary char */
- continue;
- }
- /* Skip if max size is used (to be compatible with printf) */
- fmt++;
- while (my_isdigit(system_charset_info,*fmt) || *fmt == '.' || *fmt == '-')
- fmt++;
- if (*fmt == 'l')
- fmt++;
- if (*fmt == 's') /* String parameter */
- {
- reg2 char *par = va_arg(ap, char *);
- uint plen,left_len = (uint)(end-to);
- if (!par) par = (char*)"(null)";
- plen = (uint) strlen(par);
- if (left_len <= plen)
- plen = left_len - 1;
- to=strnmov(to,par,plen);
- continue;
- }
- else if (*fmt == 'd' || *fmt == 'u') /* Integer parameter */
- {
- register int iarg;
- if ((uint) (end-to) < 16)
- break;
- iarg = va_arg(ap, int);
- if (*fmt == 'd')
- to=int10_to_str((long) iarg,to, -10);
- else
- to=int10_to_str((long) (uint) iarg,to,10);
- continue;
- }
- /* We come here on '%%', unknown code or too long parameter */
- if (to == end)
- break;
- *to++='%'; /* % used as % or unknown code */
- }
- DBUG_ASSERT(to <= end);
- *to='\0'; /* End of errmessage */
- return (uint) (to - start);
-}
-#endif
+/*
+ We can't use vsprintf here as it's not guaranteed to return
+ the length on all operating systems.
+ This function is also not called in a safe environment, so the
+ end buffer must be checked.
+*/
int my_snprintf_8bit(CHARSET_INFO *cs __attribute__((unused)),
char* to, uint n __attribute__((unused)),
const char* fmt, ...)
{
va_list args;
+ int result;
va_start(args,fmt);
-#ifdef NOT_USED
- return my_vsnprintf_8bit(to, n, fmt, args);
-#endif
- /*
- FIXME: generally not safe, but it is OK for now
- FIXME: as far as it's not called unsafely in the current code
- */
- return vsprintf(to,fmt,args); /* FIXME */
+ result= my_vsnprintf(to, n, fmt, args);
+ va_end(args);
+ return result;
}
@@ -432,7 +384,7 @@ ulong my_strntoul_8bit(CHARSET_INFO *cs,
c -= '0';
else if (c>='A' && c<='F')
c = c - 'A' + 10;
- else if (c>='a' && c<='a')
+ else if (c>='a' && c<='f')
c = c - 'a' + 10;
else
break;
@@ -690,28 +642,48 @@ noconv:
return 0L;
}
-double my_strntod_8bit(CHARSET_INFO *cs __attribute__((unused)),
- const char *s, uint l, char **e)
+/*
+ Read double from string
+
+ SYNOPSIS:
+ my_strntod_8bit()
+ cs Character set information
+ str String to convert to double
+ length Optional length for string.
+ end pointer to end of converted string
+
+ NOTES:
+ If length is not INT_MAX32 or str[length] != 0 then the given str must
+ be writeable
+ If length == INT_MAX32 the str must be \0 terminated.
+
+ It's implemented this way to save a buffer allocation and a memory copy.
+
+ RETURN
+ value of number in string
+*/
+
+
+double my_strntod_8bit(CHARSET_INFO *cs __attribute__((unused)),
+ char *str, uint length, char **end)
{
- char buf[256];
- double res;
- if((l+1)>sizeof(buf))
- {
- if (e)
- memcpy(*e,s,sizeof(s));
- return 0;
- }
- strncpy(buf,s,l);
- buf[l]='\0';
- res=strtod(buf,e);
- if (e)
- memcpy(*e,*e-buf+s,sizeof(s));
- return res;
+ char end_char;
+ double result;
+
+ if (length == INT_MAX32 || str[length] == 0)
+ return strtod(str, end);
+ end_char= str[length];
+ str[length]= 0;
+ result= strtod(str, end);
+ str[length]= end_char; /* Restore end char */
+ return result;
}
/*
This is a fast version optimized for the case of radix 10 / -10
+
+ Assume len >= 1
*/
int my_l10tostr_8bit(CHARSET_INFO *cs __attribute__((unused)),
@@ -720,18 +692,19 @@ int my_l10tostr_8bit(CHARSET_INFO *cs __attribute__((unused)),
char buffer[66];
register char *p, *e;
long int new_val;
- int sl=0;
- uint l;
-
+ uint sign=0;
+
e = p = &buffer[sizeof(buffer)-1];
- *e='\0';
+ *p= 0;
if (radix < 0)
{
if (val < 0)
{
- sl = 1;
- val = -val;
+ val= -val;
+ *dst++= '-';
+ len--;
+ sign= 1;
}
}
@@ -746,41 +719,38 @@ int my_l10tostr_8bit(CHARSET_INFO *cs __attribute__((unused)),
val= new_val;
}
- if (sl)
- {
- *--p='-';
- }
-
- l=e-p;
- l=(l>len)?len:l;
- memcpy(dst,p,l);
- return (int)l;
+ len= min(len, (uint) (e-p));
+ memcpy(dst, p, len);
+ return (int) len+sign;
}
+
int my_ll10tostr_8bit(CHARSET_INFO *cs __attribute__((unused)),
char *dst, uint len, int radix, longlong val)
{
char buffer[65];
register char *p, *e;
long long_val;
- int sl=0;
- uint l;
+ uint sign= 0;
if (radix < 0)
{
if (val < 0)
{
- sl=1;
val = -val;
+ *dst++= '-';
+ len--;
+ sign= 1;
}
}
e = p = &buffer[sizeof(buffer)-1];
- *p='\0';
+ *p= 0;
if (val == 0)
{
- *--p='0';
+ *--p= '0';
+ len= 1;
goto cnv;
}
@@ -800,16 +770,10 @@ int my_ll10tostr_8bit(CHARSET_INFO *cs __attribute__((unused)),
long_val= quo;
}
+ len= min(len, (uint) (e-p));
cnv:
- if (sl)
- {
- *--p='-';
- }
-
- l=e-p;
- l=(l>len)?len:l;
- memcpy(dst,p,l);
- return (int)(e-p);
+ memcpy(dst, p, len);
+ return len+sign;
}
diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c
index 43db7ebc24a..3949be5e215 100644
--- a/strings/ctype-sjis.c
+++ b/strings/ctype-sjis.c
@@ -4460,7 +4460,8 @@ my_mb_wc_sjis(CHARSET_INFO *cs __attribute__((unused)),
CHARSET_INFO my_charset_sjis =
{
13, /* number */
- MY_CS_COMPILED, /* state */
+ MY_CS_COMPILED|MY_CS_PRIMARY, /* state */
+ "sjis", /* cs name */
"sjis", /* name */
"", /* comment */
ctype_sjis,
diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c
index 2dae3036426..7168026eea5 100644
--- a/strings/ctype-tis620.c
+++ b/strings/ctype-tis620.c
@@ -688,7 +688,8 @@ void ThNormalize(uchar* ptr, uint field_length, const uchar* from, uint length)
CHARSET_INFO my_charset_tis620 =
{
18, /* number */
- MY_CS_COMPILED, /* state */
+ MY_CS_COMPILED|MY_CS_PRIMARY, /* state */
+ "tis620", /* cs name */
"tis620", /* name */
"", /* comment */
ctype_tis620,
diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c
index 9d970005c85..0a0024594e4 100644
--- a/strings/ctype-ujis.c
+++ b/strings/ctype-ujis.c
@@ -8430,7 +8430,8 @@ my_wc_mb_euc_jp(CHARSET_INFO *c,my_wc_t wc, unsigned char *s, unsigned char *e)
CHARSET_INFO my_charset_ujis =
{
12, /* number */
- MY_CS_COMPILED, /* state */
+ MY_CS_COMPILED|MY_CS_PRIMARY, /* state */
+ "ujis", /* cs name */
"ujis", /* name */
"", /* comment */
ctype_ujis,
diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c
index c32592dafec..4f72a4c2334 100644
--- a/strings/ctype-utf8.c
+++ b/strings/ctype-utf8.c
@@ -1958,7 +1958,8 @@ static int my_mbcharlen_utf8(CHARSET_INFO *cs __attribute__((unused)) , uint c)
CHARSET_INFO my_charset_utf8 =
{
33, /* number */
- MY_CS_COMPILED, /* state */
+ MY_CS_COMPILED|MY_CS_PRIMARY, /* state */
+ "utf8", /* cs name */
"utf8", /* name */
"", /* comment */
ctype_utf8, /* ctype */
@@ -2873,37 +2874,31 @@ bs:
double my_strntod_ucs2(CHARSET_INFO *cs __attribute__((unused)),
- const char *nptr, uint l, char **endptr)
+ char *nptr, uint length, char **endptr)
{
char buf[256];
double res;
register char *b=buf;
register const char *s=nptr;
- register const char *e=nptr+l;
+ register const char *end;
my_wc_t wc;
int cnv;
- if((l+1)>sizeof(buf))
- {
- if (endptr)
- *endptr=(char*)nptr;
- my_errno=ERANGE;
- return 0;
- }
-
- while ((cnv=cs->mb_wc(cs,&wc,s,e))>0)
+ /* Cut too long strings */
+ if (length >= sizeof(buf))
+ length= sizeof(buf)-1;
+ end=nptr+length;
+
+ while ((cnv=cs->mb_wc(cs,&wc,s,end)) > 0)
{
s+=cnv;
- if (wc < 128)
- {
- *b++=wc;
- }
- else
- break;
+ if (wc > (int) (uchar) 'e' || !wc)
+ break; /* Can't be part of double */
+ *b++=wc;
}
- *b='\0';
+ *b= 0;
- res=strtod(buf,endptr);
+ res=strtod(buf, endptr);
if (endptr)
*endptr=(char*) (*endptr-buf+nptr);
return res;
@@ -3024,7 +3019,8 @@ cnv:
CHARSET_INFO my_charset_ucs2 =
{
35, /* number */
- MY_CS_COMPILED, /* state */
+ MY_CS_COMPILED|MY_CS_PRIMARY, /* state */
+ "ucs2", /* cs name */
"ucs2", /* name */
"", /* comment */
ctype_ucs2, /* ctype */
diff --git a/strings/ctype-win1250ch.c b/strings/ctype-win1250ch.c
index b7a6b21cf4a..358cede442c 100644
--- a/strings/ctype-win1250ch.c
+++ b/strings/ctype-win1250ch.c
@@ -623,7 +623,8 @@ CHARSET_INFO my_charset_win1250ch =
{
34, /* number */
MY_CS_COMPILED, /* state */
- "win1250ch", /* name */
+ "cp1250", /* cs name */
+ "cp1250_czech", /* name */
"", /* comment */
ctype_win1250ch,
to_lower_win1250ch,
diff --git a/strings/ctype.c b/strings/ctype.c
index 8e7d8ad939c..c2a7e928493 100644
--- a/strings/ctype.c
+++ b/strings/ctype.c
@@ -16,6 +16,7 @@
#include <my_global.h>
#include <m_ctype.h>
+#include <my_xml.h>
#ifndef SCO
#include <m_string.h>
#endif
@@ -2810,7 +2811,8 @@ static CHARSET_INFO compiled_charsets[] = {
#ifdef HAVE_CHARSET_latin1
{
8, /* number */
- MY_CS_COMPILED, /* state */
+ MY_CS_COMPILED|MY_CS_PRIMARY, /* state */
+ "latin1", /* cs name */
"latin1", /* name */
"", /* comment */
ctype_latin1,
@@ -2856,6 +2858,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
14, /* number */
MY_CS_COMPILED, /* state */
+ "cp1251", /* cs name */
"cp1251", /* name */
"", /* comment */
ctype_cp1251,
@@ -2900,6 +2903,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
29, /* number */
MY_CS_COMPILED, /* state */
+ "cp1257", /* cs name */
"cp1257", /* name */
"", /* comment */
ctype_cp1257,
@@ -2944,6 +2948,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
27, /* number */
MY_CS_COMPILED, /* state */
+ "latin2", /* cs name */
"croat", /* name */
"", /* comment */
ctype_croat,
@@ -2989,6 +2994,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
15, /* number */
MY_CS_COMPILED, /* state */
+ "latin1", /* cs name */
"danish", /* name */
"", /* comment */
ctype_danish,
@@ -3033,6 +3039,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
3, /* number */
MY_CS_COMPILED, /* state */
+ "dec8", /* cs name */
"dec8", /* name */
"", /* comment */
ctype_dec8,
@@ -3077,6 +3084,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
4, /* number */
MY_CS_COMPILED, /* state */
+ "cp850", /* cs name */
"dos", /* name */
"", /* comment */
ctype_dos,
@@ -3121,6 +3129,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
20, /* number */
MY_CS_COMPILED, /* state */
+ "latin7", /* cs name */
"estonia", /* name */
"", /* comment */
ctype_estonia,
@@ -3166,6 +3175,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
5, /* number */
MY_CS_COMPILED, /* state */
+ "latin1", /* cs name */
"german1", /* name */
"", /* comment */
ctype_german1,
@@ -3210,6 +3220,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
25, /* number */
MY_CS_COMPILED, /* state */
+ "greek", /* cs name */
"greek", /* name */
"", /* comment */
ctype_greek,
@@ -3254,6 +3265,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
16, /* number */
MY_CS_COMPILED, /* state */
+ "hebrew", /* cs name */
"hebrew", /* name */
"", /* comment */
ctype_hebrew,
@@ -3298,6 +3310,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
6, /* number */
MY_CS_COMPILED, /* state */
+ "hp8", /* cs name */
"hp8", /* name */
"", /* comment */
ctype_hp8,
@@ -3342,6 +3355,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
21, /* number */
MY_CS_COMPILED, /* state */
+ "latin2", /* cs name */
"hungarian", /* name */
"", /* comment */
ctype_hungarian,
@@ -3386,7 +3400,8 @@ static CHARSET_INFO compiled_charsets[] = {
{
7, /* number */
MY_CS_COMPILED, /* state */
- "koi8_ru", /* name */
+ "koi8r", /* cs name */
+ "koi8r", /* name */
"", /* comment */
ctype_koi8_ru,
to_lower_koi8_ru,
@@ -3430,7 +3445,8 @@ static CHARSET_INFO compiled_charsets[] = {
{
22, /* number */
MY_CS_COMPILED, /* state */
- "koi8_ukr", /* name */
+ "koi8u", /* cs name */
+ "koi8u", /* name */
"", /* comment */
ctype_koi8_ukr,
to_lower_koi8_ukr,
@@ -3475,6 +3491,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
9, /* number */
MY_CS_COMPILED, /* state */
+ "latin2", /* cs name */
"latin2", /* name */
"", /* comment */
ctype_latin2,
@@ -3519,6 +3536,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
30, /* number */
MY_CS_COMPILED, /* state */
+ "latin5", /* cs name */
"latin5", /* name */
"", /* comment */
ctype_latin5,
@@ -3564,6 +3582,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
10, /* number */
MY_CS_COMPILED, /* state */
+ "swe7", /* cs name */
"swe7", /* name */
"", /* comment */
ctype_swe7,
@@ -3609,7 +3628,8 @@ static CHARSET_INFO compiled_charsets[] = {
{
11, /* number */
MY_CS_COMPILED, /* state */
- "usa7", /* name */
+ "ascii", /* cs name */
+ "ascii", /* name */
"", /* comment */
ctype_usa7,
to_lower_usa7,
@@ -3653,7 +3673,8 @@ static CHARSET_INFO compiled_charsets[] = {
{
26, /* number */
MY_CS_COMPILED, /* state */
- "win1250", /* name */
+ "cp1250", /* cs name */
+ "cp1250", /* name */
"", /* comment */
ctype_win1250,
to_lower_win1250,
@@ -3697,6 +3718,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
23, /* number */
MY_CS_COMPILED, /* state */
+ "cp1251", /* cs name */
"win1251ukr", /* name */
"", /* comment */
ctype_win1251ukr,
@@ -3741,6 +3763,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
32, /* number */
MY_CS_COMPILED, /* state */
+ "armscii8", /* cs name */
"armscii8", /* name */
"", /* comment */
ctype_armscii8,
@@ -3785,6 +3808,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
17, /* number */
MY_CS_COMPILED, /* state */
+ "cp1251", /* cs name */
"win1251", /* name */
"", /* comment */
ctype_win1251,
@@ -3828,6 +3852,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
0, /* end-of-list marker */
0, /* state */
+ NullS, /* cs name */
NullS, /* name */
NullS, /* comment */
NULL,
@@ -3871,6 +3896,228 @@ static CHARSET_INFO compiled_charsets[] = {
};
+static char *mstr(char *str,const char *src,uint l1,uint l2)
+{
+ l1= l1<l2 ? l1 : l2;
+ memcpy(str,src,l1);
+ str[l1]='\0';
+ return str;
+}
+
+
+struct my_cs_file_section_st
+{
+ int state;
+ const char *str;
+};
+
+#define _CS_MISC 1
+#define _CS_ID 2
+#define _CS_CSNAME 3
+#define _CS_FAMILY 4
+#define _CS_ORDER 5
+#define _CS_COLNAME 6
+#define _CS_FLAG 7
+#define _CS_CHARSET 8
+#define _CS_COLLATION 9
+#define _CS_UPPERMAP 10
+#define _CS_LOWERMAP 11
+#define _CS_UNIMAP 12
+#define _CS_COLLMAP 13
+#define _CS_CTYPEMAP 14
+
+static struct my_cs_file_section_st sec[] =
+{
+ {_CS_MISC, "xml"},
+ {_CS_MISC, "xml.version"},
+ {_CS_MISC, "xml.encoding"},
+ {_CS_MISC, "charsets"},
+ {_CS_MISC, "charsets.max-id"},
+ {_CS_MISC, "charsets.description"},
+ {_CS_CHARSET, "charsets.charset"},
+ {_CS_CSNAME, "charsets.charset.name"},
+ {_CS_FAMILY, "charsets.charset.family"},
+ {_CS_MISC, "charsets.charset.alias"},
+ {_CS_MISC, "charsets.charset.ctype"},
+ {_CS_CTYPEMAP, "charsets.charset.ctype.map"},
+ {_CS_MISC, "charsets.charset.upper"},
+ {_CS_UPPERMAP, "charsets.charset.upper.map"},
+ {_CS_MISC, "charsets.charset.lower"},
+ {_CS_LOWERMAP, "charsets.charset.lower.map"},
+ {_CS_MISC, "charsets.charset.unicode"},
+ {_CS_UNIMAP, "charsets.charset.unicode.map"},
+ {_CS_COLLATION, "charsets.charset.collation"},
+ {_CS_COLNAME, "charsets.charset.collation.name"},
+ {_CS_ID, "charsets.charset.collation.id"},
+ {_CS_ORDER, "charsets.charset.collation.order"},
+ {_CS_FLAG, "charsets.charset.collation.flag"},
+ {_CS_COLLMAP, "charsets.charset.collation.map"},
+ {0, NULL}
+};
+
+static struct my_cs_file_section_st * cs_file_sec(const char *attr, uint len)
+{
+ struct my_cs_file_section_st *s;
+ for (s=sec; s->str; s++)
+ {
+ if (!strncmp(attr,s->str,len))
+ return s;
+ }
+ return NULL;
+}
+
+typedef struct my_cs_file_info
+{
+ char csname[MY_CS_NAME_SIZE];
+ char name[MY_CS_NAME_SIZE];
+ uchar ctype[MY_CS_CTYPE_TABLE_SIZE];
+ uchar to_lower[MY_CS_TO_LOWER_TABLE_SIZE];
+ uchar to_upper[MY_CS_TO_UPPER_TABLE_SIZE];
+ uchar sort_order[MY_CS_SORT_ORDER_TABLE_SIZE];
+ uint16 tab_to_uni[MY_CS_TO_UNI_TABLE_SIZE];
+ CHARSET_INFO cs;
+ int (*add_collation)(CHARSET_INFO *cs);
+} MY_CHARSET_LOADER;
+
+
+
+static int fill_uchar(uchar *a,uint size,const char *str, uint len)
+{
+ uint i= 0;
+ const char *s, *b, *e=str+len;
+
+ for (s=str ; s < e ; i++)
+ {
+ for ( ; (s < e) && strchr(" \t\r\n",s[0]); s++) ;
+ b=s;
+ for ( ; (s < e) && !strchr(" \t\r\n",s[0]); s++) ;
+ if (s == b || i > size)
+ break;
+ a[i]= my_strntoul(my_charset_latin1,b,s-b,NULL,16);
+ }
+ return 0;
+}
+
+static int fill_uint16(uint16 *a,uint size,const char *str, uint len)
+{
+ uint i= 0;
+ const char *s, *b, *e=str+len;
+ for (s=str ; s < e ; i++)
+ {
+ for ( ; (s < e) && strchr(" \t\r\n",s[0]); s++) ;
+ b=s;
+ for ( ; (s < e) && !strchr(" \t\r\n",s[0]); s++) ;
+ if (s == b || i > size)
+ break;
+ a[i]= my_strntol(my_charset_latin1,b,s-b,NULL,16);
+ }
+ return 0;
+}
+
+
+static int cs_enter(MY_XML_PARSER *st,const char *attr, uint len)
+{
+ struct my_cs_file_info *i= (struct my_cs_file_info *)st->user_data;
+ struct my_cs_file_section_st *s= cs_file_sec(attr,len);
+
+ if ( s && (s->state == _CS_CHARSET))
+ {
+ bzero(&i->cs,sizeof(i->cs));
+ }
+ return MY_XML_OK;
+}
+
+
+static int cs_leave(MY_XML_PARSER *st,const char *attr, uint len)
+{
+ struct my_cs_file_info *i= (struct my_cs_file_info *)st->user_data;
+ struct my_cs_file_section_st *s= cs_file_sec(attr,len);
+ int state= s ? s->state : 0;
+ int rc;
+
+ switch(state){
+ case _CS_COLLATION:
+ rc= i->add_collation ? i->add_collation(&i->cs) : MY_XML_OK;
+ break;
+ default:
+ rc=MY_XML_OK;
+ }
+ return rc;
+}
+
+
+static int cs_value(MY_XML_PARSER *st,const char *attr, uint len)
+{
+ struct my_cs_file_info *i= (struct my_cs_file_info *)st->user_data;
+ struct my_cs_file_section_st *s;
+ int state= (s=cs_file_sec(st->attr,strlen(st->attr))) ? s->state : 0;
+
+#ifndef DBUG_OFF
+ if(0){
+ char str[1024];
+ mstr(str,attr,len,sizeof(str)-1);
+ printf("VALUE %d %s='%s'\n",state,st->attr,str);
+ }
+#endif
+
+ switch (state) {
+ case _CS_ID:
+ i->cs.number= my_strntoul(my_charset_latin1,attr,len,(char**)NULL,0);
+ break;
+ case _CS_COLNAME:
+ i->cs.name=mstr(i->name,attr,len,MY_CS_NAME_SIZE-1);
+ break;
+ case _CS_CSNAME:
+ i->cs.csname=mstr(i->csname,attr,len,MY_CS_NAME_SIZE-1);
+ break;
+ case _CS_FLAG:
+ if (!strncmp("primary",attr,len))
+ i->cs.state|= MY_CS_PRIMARY;
+ break;
+ case _CS_UPPERMAP:
+ fill_uchar(i->to_upper,MY_CS_TO_UPPER_TABLE_SIZE,attr,len);
+ i->cs.to_upper=i->to_upper;
+ break;
+ case _CS_LOWERMAP:
+ fill_uchar(i->to_lower,MY_CS_TO_LOWER_TABLE_SIZE,attr,len);
+ i->cs.to_lower=i->to_lower;
+ break;
+ case _CS_UNIMAP:
+ fill_uint16(i->tab_to_uni,MY_CS_TO_UNI_TABLE_SIZE,attr,len);
+ i->cs.tab_to_uni=i->tab_to_uni;
+ break;
+ case _CS_COLLMAP:
+ fill_uchar(i->sort_order,MY_CS_SORT_ORDER_TABLE_SIZE,attr,len);
+ i->cs.sort_order=i->sort_order;
+ break;
+ case _CS_CTYPEMAP:
+ fill_uchar(i->ctype,MY_CS_CTYPE_TABLE_SIZE,attr,len);
+ i->cs.ctype=i->ctype;
+ break;
+ }
+ return MY_XML_OK;
+}
+
+
+my_bool my_parse_charset_xml(const char *buf, uint len,
+ int (*add_collation)(CHARSET_INFO *cs))
+{
+ MY_XML_PARSER p;
+ struct my_cs_file_info i;
+ my_bool rc;
+
+ my_xml_parser_create(&p);
+ my_xml_set_enter_handler(&p,cs_enter);
+ my_xml_set_value_handler(&p,cs_value);
+ my_xml_set_leave_handler(&p,cs_leave);
+ i.add_collation= add_collation;
+ my_xml_set_user_data(&p,(void*)&i);
+ rc= (my_xml_parse(&p,buf,len) == MY_XML_OK) ? FALSE : TRUE;
+ my_xml_parser_free(&p);
+ return rc;
+}
+
+
CHARSET_INFO *my_charset_latin1 = &compiled_charsets[0];
CHARSET_INFO *all_charsets[256];
CHARSET_INFO *default_charset_info = &compiled_charsets[0];
diff --git a/strings/my_vsnprintf.c b/strings/my_vsnprintf.c
new file mode 100644
index 00000000000..a67523af7bc
--- /dev/null
+++ b/strings/my_vsnprintf.c
@@ -0,0 +1,166 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <my_global.h>
+#include <m_string.h>
+#include <stdarg.h>
+#include <m_ctype.h>
+#include <assert.h>
+
+/*
+ Limited snprintf() implementations
+
+ IMPLEMENTION:
+ Supports following formats:
+ %#d
+ %#u
+ %#.#s Note #.# is skiped
+
+ RETURN
+ length of result string
+*/
+
+int my_snprintf(char* to, size_t n, const char* fmt, ...)
+{
+ va_list args;
+ int result;
+ va_start(args,fmt);
+ result= my_vsnprintf(to, n, fmt, args);
+ va_end(args);
+ return result;
+}
+
+
+int my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap)
+{
+ char *start=to, *end=to+n-1;
+ uint length, num_state, pre_zero;
+
+ for (; *fmt ; fmt++)
+ {
+ if (fmt[0] != '%')
+ {
+ if (to == end) /* End of buffer */
+ break;
+ *to++= *fmt; /* Copy ordinary char */
+ continue;
+ }
+ fmt++; /* skip '%' */
+ /* Read max fill size (only used with %d and %u) */
+ if (*fmt == '-')
+ fmt++;
+ length= num_state= pre_zero= 0;
+ for (;; fmt++)
+ {
+ if (my_isdigit(system_charset_info,*fmt))
+ {
+ if (!num_state)
+ {
+ length=length*10+ (uint) (*fmt-'0');
+ if (!length)
+ pre_zero= 1; /* first digit was 0 */
+ }
+ continue;
+ }
+ if (*fmt != '.' || num_state)
+ break;
+ num_state= 1;
+ }
+ if (*fmt == 'l')
+ fmt++;
+ if (*fmt == 's') /* String parameter */
+ {
+ reg2 char *par = va_arg(ap, char *);
+ uint plen,left_len = (uint)(end-to);
+ if (!par) par = (char*)"(null)";
+ plen = (uint) strlen(par);
+ if (left_len <= plen)
+ plen = left_len - 1;
+ to=strnmov(to,par,plen);
+ continue;
+ }
+ else if (*fmt == 'd' || *fmt == 'u') /* Integer parameter */
+ {
+ register int iarg;
+ char *to_start= to;
+ if ((uint) (end-to) < max(16,length))
+ break;
+ iarg = va_arg(ap, int);
+ if (*fmt == 'd')
+ to=int10_to_str((long) iarg,to, -10);
+ else
+ to=int10_to_str((long) (uint) iarg,to,10);
+ /* If %#d syntax was used, we have to pre-zero/pre-space the string */
+ if (length)
+ {
+ uint res_length= (uint) (to - to_start);
+ if (res_length < length)
+ {
+ uint diff= (length- res_length);
+ bmove_upp(to+diff, to, res_length);
+ bfill(to-res_length, diff, pre_zero ? '0' : ' ');
+ to+= diff;
+ }
+ }
+ continue;
+ }
+ /* We come here on '%%', unknown code or too long parameter */
+ if (to == end)
+ break;
+ *to++='%'; /* % used as % or unknown code */
+ }
+ DBUG_ASSERT(to <= end);
+ *to='\0'; /* End of errmessage */
+ return (uint) (to - start);
+}
+
+#ifdef MAIN
+#define OVERRUN_SENTRY 250
+static void my_printf(const char * fmt, ...)
+{
+ char buf[33];
+ int n;
+ va_list ar;
+ va_start(ar, fmt);
+ buf[sizeof(buf)-1]=OVERRUN_SENTRY;
+ n = my_vsnprintf(buf, sizeof(buf)-1,fmt, ar);
+ printf(buf);
+ printf("n=%d, strlen=%d\n", n, strlen(buf));
+ if (buf[sizeof(buf)-1] != OVERRUN_SENTRY)
+ {
+ fprintf(stderr, "Buffer overrun\n");
+ abort();
+ }
+ va_end(ar);
+}
+
+int main()
+{
+
+ my_printf("Hello\n");
+ my_printf("Hello int, %d\n", 1);
+ my_printf("Hello string '%s'\n", "I am a string");
+ my_printf("Hello hack hack hack hack hack hack hack %d\n", 1);
+ my_printf("Hello %d hack %d\n", 1, 4);
+ my_printf("Hello %d hack hack hack hack hack %d\n", 1, 4);
+ my_printf("Hello '%s' hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh\n", "hack");
+ my_printf("Hello hhhhhhhhhhhhhh %d sssssssssssssss\n", 1);
+ my_printf("Hello %u\n", 1);
+ my_printf("conn %ld to: '%-.64s' user: '%-.32s' host:\
+ `%-.64s' (%-.64s)", 1, 0,0,0,0);
+ return 0;
+}
+#endif
diff --git a/strings/xml.c b/strings/xml.c
new file mode 100644
index 00000000000..4f6301249ae
--- /dev/null
+++ b/strings/xml.c
@@ -0,0 +1,374 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "my_global.h"
+#include "m_string.h"
+#include "my_xml.h"
+
+
+#define MY_XML_EOF 'E'
+#define MY_XML_STRING 'S'
+#define MY_XML_IDENT 'I'
+#define MY_XML_EQ '='
+#define MY_XML_LT '<'
+#define MY_XML_GT '>'
+#define MY_XML_SLASH '/'
+#define MY_XML_COMMENT 'C'
+#define MY_XML_TEXT 'T'
+#define MY_XML_QUESTION '?'
+#define MY_XML_EXCLAM '!'
+
+typedef struct xml_attr_st
+{
+ const char *beg;
+ const char *end;
+} MY_XML_ATTR;
+
+static const char *lex2str(int lex)
+{
+ switch(lex)
+ {
+ case MY_XML_EOF: return "EOF";
+ case MY_XML_STRING: return "STRING";
+ case MY_XML_IDENT: return "IDENT";
+ case MY_XML_EQ: return "'='";
+ case MY_XML_LT: return "'<'";
+ case MY_XML_GT: return "'>'";
+ case MY_XML_SLASH: return "'/'";
+ case MY_XML_COMMENT: return "COMMENT";
+ case MY_XML_TEXT: return "TEXT";
+ case MY_XML_QUESTION: return "'?'";
+ case MY_XML_EXCLAM: return "'!'";
+ }
+ return "UNKNOWN";
+}
+
+static void my_xml_norm_text(MY_XML_ATTR *a)
+{
+ for ( ; (a->beg < a->end) && strchr(" \t\r\n",a->beg[0]) ; a->beg++ );
+ for ( ; (a->beg < a->end) && strchr(" \t\r\n",a->end[-1]) ; a->end-- );
+}
+
+
+static int my_xml_scan(MY_XML_PARSER *p,MY_XML_ATTR *a)
+{
+ int lex;
+
+ for( ; ( p->cur < p->end) && strchr(" \t\r\n",p->cur[0]) ; p->cur++);
+
+ if (p->cur >= p->end)
+ {
+ a->beg=p->end;
+ a->end=p->end;
+ lex=MY_XML_EOF;
+ goto ret;
+ }
+
+ a->beg=p->cur;
+ a->end=p->cur;
+
+ if (!memcmp(p->cur,"<!--",4))
+ {
+ for( ; (p->cur < p->end) && memcmp(p->cur, "-->", 3); p->cur++);
+ if(!memcmp(p->cur, "-->", 3))
+ p->cur+=3;
+ a->end=p->cur;
+ lex=MY_XML_COMMENT;
+ }
+ else if (strchr("?=/<>!",p->cur[0]))
+ {
+ p->cur++;
+ a->end=p->cur;
+ lex=a->beg[0];
+ }
+ else if ( (p->cur[0]=='"') || (p->cur[0]=='\'') )
+ {
+ p->cur++;
+ for( ; ( p->cur < p->end ) && (p->cur[0]!=a->beg[0]); p->cur++);
+ a->end=p->cur;
+ if (a->beg[0]==p->cur[0])p->cur++;
+ a->beg++;
+ my_xml_norm_text(a);
+ lex=MY_XML_STRING;
+ }
+ else
+ {
+ for( ; (p->cur < p->end) && !strchr("?'\"=/<> \t\r\n", p->cur[0]); p->cur++);
+ a->end=p->cur;
+ my_xml_norm_text(a);
+ lex=MY_XML_IDENT;
+ }
+
+#if 0
+ printf("LEX=%s[%d]\n",lex2str(lex),a->end-a->beg);
+#endif
+
+ret:
+ return lex;
+}
+
+
+static int my_xml_value(MY_XML_PARSER *st, const char *str, uint len)
+{
+ return (st->value) ? (st->value)(st,str,len) : MY_XML_OK;
+}
+
+
+static int my_xml_enter(MY_XML_PARSER *st, const char *str, uint len)
+{
+ if ( (st->attrend-st->attr+len+1)>sizeof(st->attr))
+ {
+ sprintf(st->errstr,"To deep XML");
+ return MY_XML_ERROR;
+ }
+ if (st->attrend > st->attr)
+ {
+ st->attrend[0]='.';
+ st->attrend++;
+ }
+ memcpy(st->attrend,str,len);
+ st->attrend+=len;
+ st->attrend[0]='\0';
+ return st->enter ? st->enter(st,st->attr,st->attrend-st->attr) : MY_XML_OK;
+}
+
+static void mstr(char *s,const char *src,uint l1, uint l2)
+{
+ l1 = l1<l2 ? l1 : l2;
+ memcpy(s,src,l1);
+ s[l1]='\0';
+}
+
+static int my_xml_leave(MY_XML_PARSER *p, const char *str, uint slen)
+{
+ char *e;
+ uint glen;
+ char s[32];
+ char g[32];
+ int rc;
+
+ /* Find previous '.' or beginning */
+ for( e=p->attrend; (e>p->attr) && (e[0]!='.') ; e--);
+ glen = (e[0]=='.') ? (p->attrend-e-1) : p->attrend-e;
+
+ if (str && (slen != glen))
+ {
+ mstr(s,str,sizeof(s)-1,slen);
+ mstr(g,e+1,sizeof(g)-1,glen),
+ sprintf(p->errstr,"'</%s>' unexpected ('</%s>' wanted)",s,g);
+ return MY_XML_ERROR;
+ }
+
+ rc = p->leave ? p->leave(p,p->attr,p->attrend-p->attr) : MY_XML_OK;
+
+ *e='\0';
+ p->attrend=e;
+
+ return rc;
+}
+
+
+int my_xml_parse(MY_XML_PARSER *p,const char *str, uint len)
+{
+ p->attrend=p->attr;
+ p->beg=str;
+ p->cur=str;
+ p->end=str+len;
+
+ while ( p->cur < p->end )
+ {
+ MY_XML_ATTR a;
+ if(p->cur[0]=='<')
+ {
+ int lex;
+ int question=0;
+ int exclam=0;
+
+ lex=my_xml_scan(p,&a);
+
+ if (MY_XML_COMMENT==lex)
+ {
+ continue;
+ }
+
+ lex=my_xml_scan(p,&a);
+
+ if (MY_XML_SLASH==lex)
+ {
+ if(MY_XML_IDENT!=(lex=my_xml_scan(p,&a)))
+ {
+ sprintf(p->errstr,"1: %s unexpected (ident wanted)",lex2str(lex));
+ return MY_XML_ERROR;
+ }
+ if(MY_XML_OK!=my_xml_leave(p,a.beg,a.end-a.beg))
+ return MY_XML_ERROR;
+ lex=my_xml_scan(p,&a);
+ goto gt;
+ }
+
+ if (MY_XML_EXCLAM==lex)
+ {
+ lex=my_xml_scan(p,&a);
+ exclam=1;
+ }
+ else if (MY_XML_QUESTION==lex)
+ {
+ lex=my_xml_scan(p,&a);
+ question=1;
+ }
+
+ if (MY_XML_IDENT==lex)
+ {
+ if(MY_XML_OK!=my_xml_enter(p,a.beg,a.end-a.beg))
+ return MY_XML_ERROR;
+ }
+ else
+ {
+ sprintf(p->errstr,"3: %s unexpected (ident or '/' wanted)",lex2str(lex));
+ return MY_XML_ERROR;
+ }
+
+ while ((MY_XML_IDENT==(lex=my_xml_scan(p,&a))) || (MY_XML_STRING==lex))
+ {
+ MY_XML_ATTR b;
+ if(MY_XML_EQ==(lex=my_xml_scan(p,&b)))
+ {
+ lex=my_xml_scan(p,&b);
+ if ( (lex==MY_XML_IDENT) || (lex=MY_XML_STRING) )
+ {
+ if((MY_XML_OK!=my_xml_enter(p,a.beg,a.end-a.beg)) ||
+ (MY_XML_OK!=my_xml_value(p,b.beg,b.end-b.beg)) ||
+ (MY_XML_OK!=my_xml_leave(p,a.beg,a.end-a.beg)))
+ return MY_XML_ERROR;
+ }
+ else
+ {
+ sprintf(p->errstr,"4: %s unexpected (ident or string wanted)",lex2str(lex));
+ return MY_XML_ERROR;
+ }
+ }
+ else if ( (MY_XML_STRING==lex) || (MY_XML_IDENT==lex) )
+ {
+ if((MY_XML_OK!=my_xml_enter(p,a.beg,a.end-a.beg)) ||
+ (MY_XML_OK!=my_xml_leave(p,a.beg,a.end-a.beg)))
+ return MY_XML_ERROR;
+ }
+ else
+ break;
+ }
+
+ if (lex==MY_XML_SLASH)
+ {
+ if(MY_XML_OK!=my_xml_leave(p,NULL,0))
+ return MY_XML_ERROR;
+ lex=my_xml_scan(p,&a);
+ }
+
+gt:
+ if (question)
+ {
+ if (lex!=MY_XML_QUESTION)
+ {
+ sprintf(p->errstr,"6: %s unexpected ('?' wanted)",lex2str(lex));
+ return MY_XML_ERROR;
+ }
+ if(MY_XML_OK!=my_xml_leave(p,NULL,0))
+ return MY_XML_ERROR;
+ lex=my_xml_scan(p,&a);
+ }
+
+ if (exclam)
+ {
+ if(MY_XML_OK!=my_xml_leave(p,NULL,0))
+ return MY_XML_ERROR;
+ }
+
+ if (lex!=MY_XML_GT)
+ {
+ sprintf(p->errstr,"5: %s unexpected ('>' wanted)",lex2str(lex));
+ return MY_XML_ERROR;
+ }
+ }
+ else
+ {
+ a.beg=p->cur;
+ for ( ; (p->cur < p->end) && (p->cur[0]!='<') ; p->cur++);
+ a.end=p->cur;
+
+ my_xml_norm_text(&a);
+ if (a.beg!=a.end)
+ {
+ my_xml_value(p,a.beg,a.end-a.beg);
+ }
+ }
+ }
+ return MY_XML_OK;
+}
+
+void my_xml_parser_create(MY_XML_PARSER *p)
+{
+ bzero((void*)p,sizeof(p[0]));
+}
+
+void my_xml_parser_free(MY_XML_PARSER *p __attribute__((unused)))
+{
+}
+
+void my_xml_set_value_handler(MY_XML_PARSER *p, int (*action)(MY_XML_PARSER *p, const char *s, uint l))
+{
+ p->value=action;
+}
+
+void my_xml_set_enter_handler(MY_XML_PARSER *p, int (*action)(MY_XML_PARSER *p, const char *s, uint l))
+{
+ p->enter=action;
+}
+
+void my_xml_set_leave_handler(MY_XML_PARSER *p, int (*action)(MY_XML_PARSER *p, const char *s, uint l))
+{
+ p->leave=action;
+}
+
+void my_xml_set_user_data(MY_XML_PARSER *p, void *user_data)
+{
+ p->user_data=user_data;
+}
+
+const char *my_xml_error_string(MY_XML_PARSER *p)
+{
+ return p->errstr;
+}
+
+
+uint my_xml_error_pos(MY_XML_PARSER *p)
+{
+ const char *beg=p->beg;
+ const char *s;
+ for ( s=p->beg ; s<p->cur; s++)
+ if (s[0]=='\n')
+ beg=s;
+ return p->cur-beg;
+}
+
+uint my_xml_error_lineno(MY_XML_PARSER *p)
+{
+ uint res=0;
+ const char *s;
+ for ( s=p->beg ; s<p->cur; s++)
+ if (s[0]=='\n')
+ res++;
+ return res;
+}