Commit b2f0a87b authored by venu@myvenu.com's avatar venu@myvenu.com

Merge bk-internal.mysql.com:/home/bk/mysql-4.1

into myvenu.com:/home/venu/work/sql/dev-4.1
parents 077d7e81 03f3b340
...@@ -118,8 +118,11 @@ extern int NEAR my_errno; /* Last error in mysys */ ...@@ -118,8 +118,11 @@ extern int NEAR my_errno; /* Last error in mysys */
#define MY_KEEP_PREALLOC 1 #define MY_KEEP_PREALLOC 1
#define MY_MARK_BLOCKS_FREE 2 /* move used to free list and reuse them */ #define MY_MARK_BLOCKS_FREE 2 /* move used to free list and reuse them */
/* defines when allocating data */ /* Internal error numbers (for assembler functions) */
#define MY_ERRNO_EDOM 33
#define MY_ERRNO_ERANGE 34
/* defines when allocating data */
#ifdef SAFEMALLOC #ifdef SAFEMALLOC
#define my_malloc(SZ,FLAG) _mymalloc((SZ), __FILE__, __LINE__, FLAG ) #define my_malloc(SZ,FLAG) _mymalloc((SZ), __FILE__, __LINE__, FLAG )
#define my_malloc_ci(SZ,FLAG) _mymalloc((SZ), sFile, uLine, FLAG ) #define my_malloc_ci(SZ,FLAG) _mymalloc((SZ), sFile, uLine, FLAG )
......
...@@ -14,18 +14,18 @@ insert into t1 values (3,9,"D","c"); ...@@ -14,18 +14,18 @@ insert into t1 values (3,9,"D","c");
select grp,group_concat(c) from t1 group by grp; select grp,group_concat(c) from t1 group by grp;
grp group_concat(c) grp group_concat(c)
1 a 1 a
2 b c 2 b,c
3 E C D d d D 3 E,C,D,d,d,D
select grp,group_concat(a,c) from t1 group by grp; select grp,group_concat(a,c) from t1 group by grp;
grp group_concat(a,c) grp group_concat(a,c)
1 1a 1 1a
2 2b 3c 2 2b,3c
3 4E 5C 6D 7d 8d 9D 3 4E,5C,6D,7d,8d,9D
select grp,group_concat("(",a,":",c,")") from t1 group by grp; select grp,group_concat("(",a,":",c,")") from t1 group by grp;
grp group_concat("(",a,":",c,")") grp group_concat("(",a,":",c,")")
1 (1:a) 1 (1:a)
2 (2:b) (3:c) 2 (2:b),(3:c)
3 (4:E) (5:C) (6:D) (7:d) (8:d) (9:D) 3 (4:E),(5:C),(6:D),(7:d),(8:d),(9:D)
select grp,group_concat(c separator ",") from t1 group by grp; select grp,group_concat(c separator ",") from t1 group by grp;
grp group_concat(c separator ",") grp group_concat(c separator ",")
1 a 1 a
...@@ -39,48 +39,48 @@ grp group_concat(c separator "---->") ...@@ -39,48 +39,48 @@ grp group_concat(c separator "---->")
select grp,group_concat(c order by c) from t1 group by grp; select grp,group_concat(c order by c) from t1 group by grp;
grp group_concat(c order by c) grp group_concat(c order by c)
1 a 1 a
2 b c 2 b,c
3 C D d d D E 3 C,D,d,d,D,E
select grp,group_concat(c order by c desc) from t1 group by grp; select grp,group_concat(c order by c desc) from t1 group by grp;
grp group_concat(c order by c desc) grp group_concat(c order by c desc)
1 a 1 a
2 c b 2 c,b
3 E D d d D C 3 E,D,d,d,D,C
select grp,group_concat(d order by a) from t1 group by grp; select grp,group_concat(d order by a) from t1 group by grp;
grp group_concat(d order by a) grp group_concat(d order by a)
1 a 1 a
2 a b 2 a,b
3 a b b d d c 3 a,b,b,d,d,c
select grp,group_concat(d order by a desc) from t1 group by grp; select grp,group_concat(d order by a desc) from t1 group by grp;
grp group_concat(d order by a desc) grp group_concat(d order by a desc)
1 a 1 a
2 b a 2 b,a
3 c d d b b a 3 c,d,d,b,b,a
select grp,group_concat(a order by a,d+c) from t1 group by grp; select grp,group_concat(a order by a,d+c) from t1 group by grp;
grp group_concat(a order by a,d+c) grp group_concat(a order by a,d+c)
1 1 1 1
2 2 3 2 2,3
3 4 5 6 7 8 9 3 4,5,6,7,8,9
select grp,group_concat(c order by 1) from t1 group by grp; select grp,group_concat(c order by 1) from t1 group by grp;
grp group_concat(c order by 1) grp group_concat(c order by 1)
1 a 1 a
2 b c 2 b,c
3 C D d d D E 3 C,D,d,d,D,E
select grp,group_concat(c order by "c") from t1 group by grp; select grp,group_concat(c order by "c") from t1 group by grp;
grp group_concat(c order by "c") grp group_concat(c order by "c")
1 a 1 a
2 b c 2 b,c
3 C D d d D E 3 C,D,d,d,D,E
select grp,group_concat(distinct c order by c) from t1 group by grp; select grp,group_concat(distinct c order by c) from t1 group by grp;
grp group_concat(distinct c order by c) grp group_concat(distinct c order by c)
1 a 1 a
2 b c 2 b,c
3 C D E 3 C,D,E
select grp,group_concat(distinct c order by c desc) from t1 group by grp; select grp,group_concat(distinct c order by c desc) from t1 group by grp;
grp group_concat(distinct c order by c desc) grp group_concat(distinct c order by c desc)
1 a 1 a
2 c b 2 c,b
3 E D C 3 E,D,C
select grp,group_concat(c order by c separator ",") from t1 group by grp; select grp,group_concat(c order by c separator ",") from t1 group by grp;
grp group_concat(c order by c separator ",") grp group_concat(c order by c separator ",")
1 a 1 a
...@@ -104,8 +104,8 @@ grp group_concat(distinct c order by c desc separator ",") ...@@ -104,8 +104,8 @@ grp group_concat(distinct c order by c desc separator ",")
select grp,group_concat(c order by grp desc) from t1 group by grp order by grp; select grp,group_concat(c order by grp desc) from t1 group by grp order by grp;
grp group_concat(c order by grp desc) grp group_concat(c order by grp desc)
1 a 1 a
2 c b 2 c,b
3 D d d D C E 3 D,d,d,D,C,E
select grp, group_concat(a separator "")+0 from t1 group by grp; select grp, group_concat(a separator "")+0 from t1 group by grp;
grp group_concat(a separator "")+0 grp group_concat(a separator "")+0
1 1 1 1
...@@ -138,7 +138,7 @@ select grp,group_concat(c order by c) from t1 group by grp; ...@@ -138,7 +138,7 @@ select grp,group_concat(c order by c) from t1 group by grp;
grp group_concat(c order by c) grp group_concat(c order by c)
1 NULL 1 NULL
2 b 2 b
3 D D E 3 D,D,E
4 4
5 NULL 5 NULL
set group_concat_max_len = 5; set group_concat_max_len = 5;
...@@ -146,7 +146,7 @@ select grp,group_concat(c) from t1 group by grp; ...@@ -146,7 +146,7 @@ select grp,group_concat(c) from t1 group by grp;
grp group_concat(c) grp group_concat(c)
1 NULL 1 NULL
2 b 2 b
3 E D D 3 E,D,D
4 4
5 NULL 5 NULL
Warnings: Warnings:
......
...@@ -174,7 +174,8 @@ void load_defaults(const char *conf_file, const char **groups, ...@@ -174,7 +174,8 @@ void load_defaults(const char *conf_file, const char **groups,
res= (char**) (ptr+sizeof(alloc)); res= (char**) (ptr+sizeof(alloc));
/* copy name + found arguments + command line arguments to new array */ /* copy name + found arguments + command line arguments to new array */
res[0]=argv[0][0]; res[0]=*argc ? argv[0][0] : "";
memcpy((gptr) (res+1), args.buffer, args.elements*sizeof(char*)); memcpy((gptr) (res+1), args.buffer, args.elements*sizeof(char*));
/* Skipp --defaults-file and --defaults-extra-file */ /* Skipp --defaults-file and --defaults-extra-file */
(*argc)-= args_used; (*argc)-= args_used;
...@@ -187,8 +188,9 @@ void load_defaults(const char *conf_file, const char **groups, ...@@ -187,8 +188,9 @@ void load_defaults(const char *conf_file, const char **groups,
--*argc; ++*argv; /* skipp argument */ --*argc; ++*argv; /* skipp argument */
} }
memcpy((gptr) (res+1+args.elements), (char*) ((*argv)+1), if (*argc)
(*argc-1)*sizeof(char*)); memcpy((gptr) (res+1+args.elements), (char*) ((*argv)+1),
(*argc-1)*sizeof(char*));
res[args.elements+ *argc]=0; /* last null */ res[args.elements+ *argc]=0; /* last null */
(*argc)+=args.elements; (*argc)+=args.elements;
......
...@@ -697,6 +697,7 @@ class Item_func_group_concat : public Item_sum ...@@ -697,6 +697,7 @@ class Item_func_group_concat : public Item_sum
enum Sumfunctype sum_func () const {return GROUP_CONCAT_FUNC;} enum Sumfunctype sum_func () const {return GROUP_CONCAT_FUNC;}
const char *func_name() const { return "group_concat"; } const char *func_name() const { return "group_concat"; }
enum Type type() const { return SUM_FUNC_ITEM; } enum Type type() const { return SUM_FUNC_ITEM; }
void fix_length_and_dec() { max_length=group_concat_max_len; }
virtual Item_result result_type () const { return STRING_RESULT; } virtual Item_result result_type () const { return STRING_RESULT; }
void reset(); void reset();
bool add(); bool add();
...@@ -715,4 +716,5 @@ class Item_func_group_concat : public Item_sum ...@@ -715,4 +716,5 @@ class Item_func_group_concat : public Item_sum
return res ? strtoll(res->c_ptr(),(char**) 0,10) : (longlong) 0; return res ? strtoll(res->c_ptr(),(char**) 0,10) : (longlong) 0;
} }
String* val_str(String* str); String* val_str(String* str);
Item *copy_or_same(THD* thd) { return new Item_func_group_concat(thd, *this); }
}; };
...@@ -209,7 +209,7 @@ static SYMBOL symbols[] = { ...@@ -209,7 +209,7 @@ static SYMBOL symbols[] = {
{ "INT4", SYM(INT_SYM),0,0}, { "INT4", SYM(INT_SYM),0,0},
{ "INT8", SYM(BIGINT),0,0}, { "INT8", SYM(BIGINT),0,0},
{ "INTO", SYM(INTO),0,0}, { "INTO", SYM(INTO),0,0},
{ "IO_THREAD", SYM(IO_THREAD),0,0}, { "IO_THREAD", SYM(RELAY_THREAD),0,0},
{ "IF", SYM(IF),0,0}, { "IF", SYM(IF),0,0},
{ "IS", SYM(IS),0,0}, { "IS", SYM(IS),0,0},
{ "ISOLATION", SYM(ISOLATION),0,0}, { "ISOLATION", SYM(ISOLATION),0,0},
...@@ -313,6 +313,7 @@ static SYMBOL symbols[] = { ...@@ -313,6 +313,7 @@ static SYMBOL symbols[] = {
{ "REFERENCES", SYM(REFERENCES),0,0}, { "REFERENCES", SYM(REFERENCES),0,0},
{ "RELAY_LOG_FILE", SYM(RELAY_LOG_FILE_SYM),0,0}, { "RELAY_LOG_FILE", SYM(RELAY_LOG_FILE_SYM),0,0},
{ "RELAY_LOG_POS", SYM(RELAY_LOG_POS_SYM),0,0}, { "RELAY_LOG_POS", SYM(RELAY_LOG_POS_SYM),0,0},
{ "RELAY_THREAD", SYM(RELAY_THREAD),0,0},
{ "RELOAD", SYM(RELOAD),0,0}, { "RELOAD", SYM(RELOAD),0,0},
{ "REGEXP", SYM(REGEXP),0,0}, { "REGEXP", SYM(REGEXP),0,0},
{ "RENAME", SYM(RENAME),0,0}, { "RENAME", SYM(RENAME),0,0},
......
...@@ -201,6 +201,8 @@ public: ...@@ -201,6 +201,8 @@ public:
*new_list.last=current->next; *new_list.last=current->next;
current->info=new_list.first->info; current->info=new_list.first->info;
current->next=new_list.first->next; current->next=new_list.first->next;
if ((list->last == &current->next) && (new_list.elements > 1))
list->last= new_list.last;
list->elements+=new_list.elements-1; list->elements+=new_list.elements-1;
} }
return ret_value; // return old element return ret_value; // return old element
......
...@@ -138,7 +138,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -138,7 +138,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token FLUSH_SYM %token FLUSH_SYM
%token HELP_SYM %token HELP_SYM
%token INSERT %token INSERT
%token IO_THREAD %token RELAY_THREAD
%token KILL_SYM %token KILL_SYM
%token LOAD %token LOAD
%token LOCKS_SYM %token LOCKS_SYM
...@@ -1688,7 +1688,7 @@ slave_thread_opt_list: ...@@ -1688,7 +1688,7 @@ slave_thread_opt_list:
slave_thread_opt: slave_thread_opt:
/*empty*/ {} /*empty*/ {}
| SQL_THREAD { Lex->slave_thd_opt|=SLAVE_SQL; } | SQL_THREAD { Lex->slave_thd_opt|=SLAVE_SQL; }
| IO_THREAD { Lex->slave_thd_opt|=SLAVE_IO; } | RELAY_THREAD { Lex->slave_thd_opt|=SLAVE_IO; }
; ;
restore: restore:
...@@ -2588,7 +2588,7 @@ opt_distinct: ...@@ -2588,7 +2588,7 @@ opt_distinct:
|DISTINCT { $$ = 1; }; |DISTINCT { $$ = 1; };
opt_gconcat_separator: opt_gconcat_separator:
/* empty */ { $$ = new String(" ",1,default_charset_info); } /* empty */ { $$ = new String(",",1,default_charset_info); }
|SEPARATOR_SYM text_string { $$ = $2; }; |SEPARATOR_SYM text_string { $$ = $2; };
...@@ -4230,7 +4230,7 @@ keyword: ...@@ -4230,7 +4230,7 @@ keyword:
| ISSUER_SYM {} | ISSUER_SYM {}
| INNOBASE_SYM {} | INNOBASE_SYM {}
| INSERT_METHOD {} | INSERT_METHOD {}
| IO_THREAD {} | RELAY_THREAD {}
| LAST_SYM {} | LAST_SYM {}
| LEVEL_SYM {} | LEVEL_SYM {}
| LINESTRING {} | LINESTRING {}
......
# Copyright (C) 2003 MySQL AB
# This program is free software; you can resistribute 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
# Implemention of my_strtoll(): Converting a string to a 64 bit integer.
.file "my_strtoll10-x86.s"
.version "01.01"
.data
.align 32
.type lfactor,@object
.size lfactor,36
lfactor:
.long 1
.long 10
.long 100
.long 1000
.long 10000
.long 100000
.long 1000000
.long 10000000
.long 100000000
.text
.align 4
.globl my_strtoll10
.type my_strtoll10,@function
# Used stack variables
# ebp-4 dummy for storing endptr if endptr = 0
# ebp-8 First 9 digits of return values
# ebp-12 Pointer to first digit of second part
# ebp-16 Store lowest 2 digits
# ebp-20 != 0 if value was negative
# ebp-24 High max value
# ebp-28 Middle max value
# ebp-32 Low max value
# ebp-36 Temp value
# esi Pointer to input string
# ebx End of string
my_strtoll10:
pushl %ebp
movl %esp,%ebp
subl $48,%esp
pushl %esi
pushl %edi
pushl %ebx
movl 8(%ebp),%esi # esi= nptr
movl 16(%ebp),%ecx # ecx= error (Will be overwritten later)
movl 12(%ebp),%eax # eax= endptr
cld # Move forward in esi
cmpl $0,%eax # if (endptr)
je .L110
# Fixed length string
movl (%eax),%ebx # bx= end-of-string
.p2align 4,,7
.L100:
cmpl %ebx,%esi
je .Lno_conv
lodsb # al= next byte
cmpb $32,%al # Skip space
je .L100
cmpb $9,%al # Skip tab
je .L100
jmp .L130
# String that ends with \0
.L110:
leal -4(%ebp),%edi
movl %edi,12(%ebp) # endptr= &dummy, for easier end check
.p2align 4,,7
.L120:
lodsb # al= next byte
cmpb $32,%al
je .L120
cmpb $9,%al
je .L120
testb %al,%al # Test if we found end \0
je .Lno_conv
leal 65535(%esi),%ebx # ebx = end-of-string
.L130:
cmpb $45,%al # Test if '-'
jne .Lpositive
# negative number
movl $-1,(%ecx) # error = -1 (mark that number is negative)
movl $1,-20(%ebp) # negative= 1
movl $92233720,-24(%ebp)
movl $368547758,-28(%ebp)
movl $8,-32(%ebp)
jmp .L460
.p2align 4,,7
.Lpositive:
movl $0,(%ecx) # error=0
movl $0,-20(%ebp) # negative= 0
movl $184467440,-24(%ebp)
movl $737095516,-28(%ebp)
movl $15,-32(%ebp)
cmpb $43,%al # Check if '+'
jne .L462
.L460:
cmpl %ebx,%esi # Check if overflow
je .Lno_conv
lodsb # al= next byte after sign
# Remove pre zero to be able to handle a lot of pre-zero
.L462:
cmpb $48,%al
jne .L475 # Number doesn't start with 0
movl %esi, %edi
.p2align 4,,7
.L481: # Skip pre zeros
cmpl %ebx,%esi
je .Lms_return_zero
scasb
je .L481
movl %edi, %esi
decl %esi # Point to last non '0' digit
leal 9(%esi),%ecx # ecx = end-of-current-part
xorl %edi,%edi # Store first 9 digits in edi
jmp .L482
.p2align 4,,7
# Check if first char is a valid number
.L475:
addb $-48,%al
cmpb $9,%al
ja .Lno_conv
.L477:
movzbl %al,%edi # edi = first digit
leal 8(%esi),%ecx # ecx = end-of-current-part
# Handle first 8/9 digits and store them in edi
.L482:
cmpl %ebx,%ecx
jbe .L522
movl %ebx,%ecx # ecx = min(end-of-current-part, end-of-string)
jmp .L522
.p2align 4,,7
.L488:
lodsb # al= next byte
addb $-48,%al
cmpb $9,%al
ja .Lend_i_dec_esi
# Calculate edi= edi*10 + al
leal (%edi,%edi,4),%edx
movzbl %al,%eax
leal (%eax,%edx,2),%edi
.L522:
cmpl %ecx,%esi # If more digits at this level
jne .L488
cmpl %ebx,%esi # If end of string
je .Lend_i
movl %edi,-8(%ebp) # Store first 9 digits
movl %esi,-12(%ebp) # store pos to first digit of second part
# Calculate next 9 digits and store them in edi
xorl %edi,%edi
leal 9(%esi),%ecx # ecx= end-of-current-part
movl %ecx,-36(%ebp) # Store max length
cmpl %ebx,%ecx
jbe .L498
movl %ebx,%ecx # ecx = min(end-of-current-part, end-of-string)
.p2align 4,,7
.L498:
lodsb # al= next byte
addb $-48,%al
cmpb $9,%al
ja .Lend_i_and_j_decl_esi
# Calculate edi= edi*10 + al
leal (%edi,%edi,4),%edx
movzbl %al,%eax
leal (%eax,%edx,2),%edi
cmpl %ecx,%esi # If end of current part
jne .L498
cmpl %ebx,%esi # If end of string
jne .L500
cmpl -36(%ebp),%esi # Test if string is less than 18 digits
jne .Lend_i_and_j
jmp .Lend3 # 18 digit string
# Handle the possible next to last digit and store in ecx
.L500:
movb (%esi),%al
addb $-48,%al
cmpb $9,%al
ja .Lend3
incl %esi
movzbl %al,%ecx
cmpl %ebx,%esi # If end of string
je .Lend4
movb (%esi),%al # Read last digit
addb $-48,%al
cmpb $9,%al
ja .Lend4
# ecx= ecx*10 + al
leal (%ecx,%ecx,4),%edx
movzbl %al,%eax
leal (%eax,%edx,2),%ecx
movl 12(%ebp),%eax # eax = endptr
incl %esi
movl %esi,(%eax) # *endptr = end-of-string
cmpl %ebx,%esi
je .L505 # At end of string
movb (%esi),%al # check if extra digits
addb $-48,%al
cmpb $9,%al
jbe .Loverflow
# At this point we have:
# -8(%ebp) First 9 digits
# edi Next 9 digits
# ecx Last 2 digits
# *endpos end-of-string
.L505: # Check that we are not going to get overflow for unsigned long long
movl -8(%ebp),%eax # First 9 digits
cmpl -24(%ebp),%eax
ja .Loverflow
jne .L507
cmpl -28(%ebp),%edi
ja .Loverflow
jne .L507
cmpl -32(%ebp),%ecx
ja .Loverflow
.L507:
movl %edi,-4(%ebp) # Save middle bytes
movl %ecx,%esi # esi = 2 last digits
movl $1215752192,%ecx # %ecx= lower_32_bits(100000000000)
mull %ecx
imull $23,-8(%ebp),%ecx
movl $0,-36(%ebp)
movl %eax,%ebx
imull $1215752192,-36(%ebp),%eax
movl %edx,%edi
addl %ecx,%edi
addl %eax,%edi # Temp in edi:ebx
movl $100,%eax # j= j*100
mull -4(%ebp)
addl %ebx,%eax # edx:eax+= edi:ebx
adcl %edi,%edx
addl %esi,%eax
adcl $0,%edx
jmp .Lms_return
.Loverflow:
# When we come here, *endptr is already updated
movl 16(%ebp),%edx # edx= error
movl $34,(%edx) # *error = 34
movl $-1,%eax
movl %eax,%edx
cmpl $0,-20(%ebp) # If negative
je .Lms_return
xor %eax,%eax # edx:eax = LONGLONG_LMIN
movl $-2147483648,%edx
jmp .Lms_return
# Return value that is in %edi as long long
.p2align 4,,7
.Lend_i_dec_esi:
decl %esi # Fix so that it points at last digit
.Lend_i:
xorl %edx,%edx
movl %edi,%eax
cmpl $0,-20(%ebp)
je .Lreturn_save_endptr # Positive number
negl %eax
cltd # Negetive result in edx:eax
jmp .Lreturn_save_endptr
# Return value (%ebp-8) * lfactor[(uint) (edx-start)] + edi
.p2align 4,,7
.Lend_i_and_j_decl_esi:
decl %esi # Fix so that it points at last digit
.Lend_i_and_j:
movl %esi,%ecx
subl -12(%ebp),%ecx # ecx= number of digits in second part
movl lfactor(,%ecx,4),%eax
jmp .L523
# Return -8(%ebp) * $1000000000 + edi
.p2align 4,,7
.Lend3:
movl $1000000000,%eax
.L523:
mull -8(%ebp)
addl %edi,%eax
adcl $0,%edx
cmpl $0,-20(%ebp) # if negative
je .Lreturn_save_endptr
negl %eax # Neg edx:%eax
adcl $0,%edx
negl %edx
jmp .Lreturn_save_endptr
# Return -8(%ebp) * $10000000000 + edi*10 + ecx
.p2align 4,,7
.Lend4:
movl %ecx,-16(%ebp) # store lowest digits
movl 12(%ebp),%ebx
movl %esi,(%ebx) # *endpos = end-of-string
movl -8(%ebp),%eax # First 9 digits
movl $1410065408,%ecx # ecx= lower_32_bits(10000000000)
mull %ecx
movl $0,-36(%ebp)
movl %eax,%ebx # Store lowest 32 byte from multiplication
imull $1410065408,-36(%ebp),%eax
movl -8(%ebp),%ecx # First 9 digits
movl %edx,%esi
addl %ecx,%ecx
addl %ecx,%esi
addl %eax,%esi # %esi:%ebx now has -8(%ebp) * $10000000000
movl $10,%eax # Calc edi*10
mull %edi
addl %ebx,%eax # And add to result
adcl %esi,%edx
addl -16(%ebp),%eax # Add lowest digit
adcl $0,%edx
cmpl $0,-20(%ebp) # if negative
je .Lms_return
cmpl $-2147483648,%edx # Test if too big signed integer
ja .Loverflow
jne .L516
testl %eax,%eax
ja .Loverflow
.L516:
negl %eax
adcl $0,%edx
negl %edx
jmp .Lms_return
.p2align 4,,7
.Lno_conv: # Not a legal number
movl 16(%ebp),%eax
movl $33,(%eax) # error= edom
.Lms_return_zero:
xorl %eax,%eax # Return zero
xorl %edx,%edx
.p2align 4,,7
.Lreturn_save_endptr:
movl 12(%ebp),%ecx # endptr= end-of-string
movl %esi,(%ecx) # *endptr= end-of-string
.Lms_return:
popl %ebx
popl %edi
popl %esi
movl %ebp,%esp
popl %ebp
ret
my_strtoll10_end:
.size my_strtoll10,.my_strtoll10_end-my_strtoll10
.comm res,240,32
.comm end_ptr,120,32
.comm error,120,32
.ident "Monty"
/* Copyright (C) 2003 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>
#define ULONGLONG_MAX (~(ulonglong) 0)
#define MAX_NEGATIVE_NUMBER ((ulonglong) 0x8000000000000000LL)
#define INIT_CNT 9
#define LFACTOR LL(1000000000)
#define LFACTOR1 LL(10000000000)
#define LFACTOR2 LL(100000000000)
static unsigned long lfactor[9]=
{
1L, 10L, 100L, 1000L, 10000L, 100000L, 1000000L, 10000000L, 100000000L
};
/*
Convert a string to an to unsigned long long integer value
SYNOPSYS
str2ull10(char *nptr, char **enptr, *long error)
nptr in pointer to the string to be converted
endptr in/out pointer to the end of the string/
pointer to the stop character
error out returned error code
DESCRIPTION
This function takes the decimal representation of integer number
from string nptr and converts it to an signed or unsigned
long long integer value.
Space characters and tab are ignored.
A sign character might precede the the digit characters. The number
may have any number of pre-zero digits.
The function stops reading the string nptr at the first character
that is not a decimal digit. If endptr is not NULL then the function
will not read characters after *endptr.
RETURN VALUES
Value of string as a signed/unsigned longlong integer
if no error and endptr != NULL, it will be set to point at the character
after the number
The error parameter contains information how things went:
-1 Number was an ok negative number
0 ok
ERANGE If the the value of the converted number exceeded the
maximum negative/unsigned long long integer.
In this case the return value is ~0 if value was
positive and LONGLONG_MIN if value was negative.
EDOM If the string didn't contain any digits. In this case
the return value is 0.
If endptr is not NULL the function will store the end pointer to
the stop character here.
*/
longlong my_strtoll10(const char *nptr, char **endptr, int *error)
{
const char *s, *end, *start, *n_end, *true_end;
char *dummy;
unsigned char c;
unsigned long i, j, k;
ulonglong li;
int negative;
long cutoff, cutoff2, cutoff3;
s= nptr;
/* If fixed length string */
if (endptr)
{
end= *endptr;
while (s != end && (*s == ' ' || *s == '\t'))
s++;
if (s == end)
goto no_conv;
}
else
{
endptr= &dummy; /* Easier end test */
while (*s == ' ' || *s == '\t')
s++;
if (!*s)
goto no_conv;
/* This number must be big to guard against a lot of pre-zeros */
end= s+65535; /* Can't be longer than this */
}
/* Check for a sign. */
negative= 0;
if (*s == '-')
{
*error= -1; /* Mark as negative number */
negative= 1;
if (++s == end)
goto no_conv;
cutoff= MAX_NEGATIVE_NUMBER / LL(100000000000);
cutoff2= (MAX_NEGATIVE_NUMBER % LL(100000000000)) / 100;
cutoff3= MAX_NEGATIVE_NUMBER % 100;
}
else
{
*error= 0;
if (*s == '+')
{
if (++s == end)
goto no_conv;
}
cutoff= ULONGLONG_MAX / LL(100000000000);
cutoff2= ULONGLONG_MAX % LL(100000000000) / 100;
cutoff3= ULONGLONG_MAX % 100;
}
/* Handle case where we have a lot of pre-zero */
if (*s == '0')
{
i= 0;
do
{
if (++s == end)
goto end_i; /* Return 0 */
}
while (*s == '0');
n_end= s+ INIT_CNT;
}
else
{
/* Read first digit to check that it's a valid number */
if ((c= (*s-'0')) > 9)
goto no_conv;
i= c;
n_end= ++s+ INIT_CNT-1;
}
/* Handle first 9 digits and store them in i */
if (n_end > end)
n_end= end;
for (; s != n_end ; s++)
{
if ((c= (*s-'0')) > 9)
goto end_i;
i= i*10+c;
}
if (s == end)
goto end_i;
/* Handle next 9 digits and store them in j */
j= 0;
start= s; /* Used to know how much to shift i */
n_end= true_end= s + INIT_CNT;
if (n_end > end)
n_end= end;
do
{
if ((c= (*s-'0')) > 9)
goto end_i_and_j;
j= j*10+c;
} while (++s != n_end);
if (s == end)
{
if (s != true_end)
goto end_i_and_j;
goto end3;
}
if ((c= (*s-'0')) > 9)
goto end3;
/* Handle the next 1 or 2 digits and store them in k */
k=c;
if (++s == end || (c= (*s-'0')) > 9)
goto end4;
k= k*10+c;
*endptr= (char*) ++s;
/* number string should have ended here */
if (s != end && (c= (*s-'0')) <= 9)
goto overflow;
/* Check that we didn't get an overflow with the last digit */
if (i > cutoff || i == cutoff && (j > cutoff2 || j == cutoff2 &&
k > cutoff3))
goto overflow;
li=i*LFACTOR2+ (ulonglong) j*100 + k;
return (longlong) li;
overflow: /* *endptr is set here */
*error= MY_ERRNO_ERANGE;
return negative ? LONGLONG_MIN : ULONGLONG_MAX;
end_i:
*endptr= (char*) s;
return (negative ? ((longlong) -(long) i) : (longlong) i);
end_i_and_j:
li= (ulonglong) i * lfactor[(uint) (s-start)] + j;
*endptr= (char*) s;
return (negative ? -((longlong) li) : (longlong) li);
end3:
li=(ulonglong) i*LFACTOR+ (ulonglong) j;
*endptr= (char*) s;
return (negative ? -((longlong) li) : (longlong) li);
end4:
li=(ulonglong) i*LFACTOR1+ (ulonglong) j * 10 + k;
*endptr= (char*) s;
if (negative)
{
if (li > MAX_NEGATIVE_NUMBER)
goto overflow;
return -((longlong) li);
}
return (longlong) li;
no_conv:
/* There was no number to convert. */
*error= MY_ERRNO_EDOM;
*endptr= (char *) nptr;
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment