diff --git a/include/my_sys.h b/include/my_sys.h index b3be3588b2f6131bb90f2466177895802adff4df..86ca6ec6a1f922681078ccdb630cb7afa5687c8b 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -118,8 +118,11 @@ extern int NEAR my_errno; /* Last error in mysys */ #define MY_KEEP_PREALLOC 1 #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 #define my_malloc(SZ,FLAG) _mymalloc((SZ), __FILE__, __LINE__, FLAG ) #define my_malloc_ci(SZ,FLAG) _mymalloc((SZ), sFile, uLine, FLAG ) diff --git a/sql/lex.h b/sql/lex.h index 9311f2c3ecde39ef7a1a920bf15132bd9e7fbd7c..b5a81a30991cd5f9e48d190df1fbc8513c0f59f0 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -209,7 +209,7 @@ static SYMBOL symbols[] = { { "INT4", SYM(INT_SYM),0,0}, { "INT8", SYM(BIGINT),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}, { "IS", SYM(IS),0,0}, { "ISOLATION", SYM(ISOLATION),0,0}, @@ -313,6 +313,7 @@ static SYMBOL symbols[] = { { "REFERENCES", SYM(REFERENCES),0,0}, { "RELAY_LOG_FILE", SYM(RELAY_LOG_FILE_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}, { "REGEXP", SYM(REGEXP),0,0}, { "RENAME", SYM(RENAME),0,0}, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 745d0a8e7d20f49264a5baac785592f4ef22e401..23e997096485e9c140986fcdaf897146568c0390 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -138,7 +138,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token FLUSH_SYM %token HELP_SYM %token INSERT -%token IO_THREAD +%token RELAY_THREAD %token KILL_SYM %token LOAD %token LOCKS_SYM @@ -1688,7 +1688,7 @@ slave_thread_opt_list: slave_thread_opt: /*empty*/ {} | 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: @@ -4230,7 +4230,7 @@ keyword: | ISSUER_SYM {} | INNOBASE_SYM {} | INSERT_METHOD {} - | IO_THREAD {} + | RELAY_THREAD {} | LAST_SYM {} | LEVEL_SYM {} | LINESTRING {} diff --git a/strings/my_strtoll10-x86.s b/strings/my_strtoll10-x86.s new file mode 100644 index 0000000000000000000000000000000000000000..4d0072116226901d10a2148aef39ed1178f15c32 --- /dev/null +++ b/strings/my_strtoll10-x86.s @@ -0,0 +1,396 @@ +# 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" diff --git a/strings/my_strtoll10.c b/strings/my_strtoll10.c new file mode 100644 index 0000000000000000000000000000000000000000..0bef961f770b65bd66067fbd85451851b923a36d --- /dev/null +++ b/strings/my_strtoll10.c @@ -0,0 +1,237 @@ +/* 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; +}