?? vdbe.c
字號(hào):
/* Opcode: Eq P1 P2 ***** Pop the top two elements from the stack. If they are equal, then** jump to instruction P2. Otherwise, continue to the next instruction.**** If either operand is NULL (and thus if the result is unknown) then** take the jump if P1 is true.**** If both values are numeric, they are converted to doubles using atof()** and compared for equality that way. Otherwise the strcmp() library** routine is used for the comparison. For a pure text comparison** use OP_StrEq.**** If P2 is zero, do not jump. Instead, push an integer 1 onto the** stack if the jump would have been taken, or a 0 if not. Push a** NULL if either operand was NULL.*//* Opcode: Ne P1 P2 ***** Pop the top two elements from the stack. If they are not equal, then** jump to instruction P2. Otherwise, continue to the next instruction.**** If either operand is NULL (and thus if the result is unknown) then** take the jump if P1 is true.**** If both values are numeric, they are converted to doubles using atof()** and compared in that format. Otherwise the strcmp() library** routine is used for the comparison. For a pure text comparison** use OP_StrNe.**** If P2 is zero, do not jump. Instead, push an integer 1 onto the** stack if the jump would have been taken, or a 0 if not. Push a** NULL if either operand was NULL.*//* Opcode: Lt P1 P2 ***** Pop the top two elements from the stack. If second element (the** next on stack) is less than the first (the top of stack), then** jump to instruction P2. Otherwise, continue to the next instruction.** In other words, jump if NOS<TOS.**** If either operand is NULL (and thus if the result is unknown) then** take the jump if P1 is true.**** If both values are numeric, they are converted to doubles using atof()** and compared in that format. Numeric values are always less than** non-numeric values. If both operands are non-numeric, the strcmp() library** routine is used for the comparison. For a pure text comparison** use OP_StrLt.**** If P2 is zero, do not jump. Instead, push an integer 1 onto the** stack if the jump would have been taken, or a 0 if not. Push a** NULL if either operand was NULL.*//* Opcode: Le P1 P2 ***** Pop the top two elements from the stack. If second element (the** next on stack) is less than or equal to the first (the top of stack),** then jump to instruction P2. In other words, jump if NOS<=TOS.**** If either operand is NULL (and thus if the result is unknown) then** take the jump if P1 is true.**** If both values are numeric, they are converted to doubles using atof()** and compared in that format. Numeric values are always less than** non-numeric values. If both operands are non-numeric, the strcmp() library** routine is used for the comparison. For a pure text comparison** use OP_StrLe.**** If P2 is zero, do not jump. Instead, push an integer 1 onto the** stack if the jump would have been taken, or a 0 if not. Push a** NULL if either operand was NULL.*//* Opcode: Gt P1 P2 ***** Pop the top two elements from the stack. If second element (the** next on stack) is greater than the first (the top of stack),** then jump to instruction P2. In other words, jump if NOS>TOS.**** If either operand is NULL (and thus if the result is unknown) then** take the jump if P1 is true.**** If both values are numeric, they are converted to doubles using atof()** and compared in that format. Numeric values are always less than** non-numeric values. If both operands are non-numeric, the strcmp() library** routine is used for the comparison. For a pure text comparison** use OP_StrGt.**** If P2 is zero, do not jump. Instead, push an integer 1 onto the** stack if the jump would have been taken, or a 0 if not. Push a** NULL if either operand was NULL.*//* Opcode: Ge P1 P2 ***** Pop the top two elements from the stack. If second element (the next** on stack) is greater than or equal to the first (the top of stack),** then jump to instruction P2. In other words, jump if NOS>=TOS.**** If either operand is NULL (and thus if the result is unknown) then** take the jump if P1 is true.**** If both values are numeric, they are converted to doubles using atof()** and compared in that format. Numeric values are always less than** non-numeric values. If both operands are non-numeric, the strcmp() library** routine is used for the comparison. For a pure text comparison** use OP_StrGe.**** If P2 is zero, do not jump. Instead, push an integer 1 onto the** stack if the jump would have been taken, or a 0 if not. Push a** NULL if either operand was NULL.*/case OP_Eq:case OP_Ne:case OP_Lt:case OP_Le:case OP_Gt:case OP_Ge: { Mem *pNos = &pTos[-1]; int c, v; int ft, fn; assert( pNos>=p->aStack ); ft = pTos->flags; fn = pNos->flags; if( (ft | fn) & MEM_Null ){ popStack(&pTos, 2); if( pOp->p2 ){ if( pOp->p1 ) pc = pOp->p2-1; }else{ pTos++; pTos->flags = MEM_Null; } break; }else if( (ft & fn & MEM_Int)==MEM_Int ){ c = pNos->i - pTos->i; }else if( (ft & MEM_Int)!=0 && (fn & MEM_Str)!=0 && toInt(pNos->z,&v) ){ c = v - pTos->i; }else if( (fn & MEM_Int)!=0 && (ft & MEM_Str)!=0 && toInt(pTos->z,&v) ){ c = pNos->i - v; }else{ Stringify(pTos); Stringify(pNos); c = sqliteCompare(pNos->z, pTos->z); } switch( pOp->opcode ){ case OP_Eq: c = c==0; break; case OP_Ne: c = c!=0; break; case OP_Lt: c = c<0; break; case OP_Le: c = c<=0; break; case OP_Gt: c = c>0; break; default: c = c>=0; break; } popStack(&pTos, 2); if( pOp->p2 ){ if( c ) pc = pOp->p2-1; }else{ pTos++; pTos->i = c; pTos->flags = MEM_Int; } break;}/* INSERT NO CODE HERE!**** The opcode numbers are extracted from this source file by doing**** grep '^case OP_' vdbe.c | ... >opcodes.h**** The opcodes are numbered in the order that they appear in this file.** But in order for the expression generating code to work right, the** string comparison operators that follow must be numbered exactly 6** greater than the numeric comparison opcodes above. So no other** cases can appear between the two.*//* Opcode: StrEq P1 P2 ***** Pop the top two elements from the stack. If they are equal, then** jump to instruction P2. Otherwise, continue to the next instruction.**** If either operand is NULL (and thus if the result is unknown) then** take the jump if P1 is true.**** The strcmp() library routine is used for the comparison. For a** numeric comparison, use OP_Eq.**** If P2 is zero, do not jump. Instead, push an integer 1 onto the** stack if the jump would have been taken, or a 0 if not. Push a** NULL if either operand was NULL.*//* Opcode: StrNe P1 P2 ***** Pop the top two elements from the stack. If they are not equal, then** jump to instruction P2. Otherwise, continue to the next instruction.**** If either operand is NULL (and thus if the result is unknown) then** take the jump if P1 is true.**** The strcmp() library routine is used for the comparison. For a** numeric comparison, use OP_Ne.**** If P2 is zero, do not jump. Instead, push an integer 1 onto the** stack if the jump would have been taken, or a 0 if not. Push a** NULL if either operand was NULL.*//* Opcode: StrLt P1 P2 ***** Pop the top two elements from the stack. If second element (the** next on stack) is less than the first (the top of stack), then** jump to instruction P2. Otherwise, continue to the next instruction.** In other words, jump if NOS<TOS.**** If either operand is NULL (and thus if the result is unknown) then** take the jump if P1 is true.**** The strcmp() library routine is used for the comparison. For a** numeric comparison, use OP_Lt.**** If P2 is zero, do not jump. Instead, push an integer 1 onto the** stack if the jump would have been taken, or a 0 if not. Push a** NULL if either operand was NULL.*//* Opcode: StrLe P1 P2 ***** Pop the top two elements from the stack. If second element (the** next on stack) is less than or equal to the first (the top of stack),** then jump to instruction P2. In other words, jump if NOS<=TOS.**** If either operand is NULL (and thus if the result is unknown) then** take the jump if P1 is true.**** The strcmp() library routine is used for the comparison. For a** numeric comparison, use OP_Le.**** If P2 is zero, do not jump. Instead, push an integer 1 onto the** stack if the jump would have been taken, or a 0 if not. Push a** NULL if either operand was NULL.*//* Opcode: StrGt P1 P2 ***** Pop the top two elements from the stack. If second element (the** next on stack) is greater than the first (the top of stack),** then jump to instruction P2. In other words, jump if NOS>TOS.**** If either operand is NULL (and thus if the result is unknown) then** take the jump if P1 is true.**** The strcmp() library routine is used for the comparison. For a** numeric comparison, use OP_Gt.**** If P2 is zero, do not jump. Instead, push an integer 1 onto the** stack if the jump would have been taken, or a 0 if not. Push a** NULL if either operand was NULL.*//* Opcode: StrGe P1 P2 ***** Pop the top two elements from the stack. If second element (the next** on stack) is greater than or equal to the first (the top of stack),** then jump to instruction P2. In other words, jump if NOS>=TOS.**** If either operand is NULL (and thus if the result is unknown) then** take the jump if P1 is true.**** The strcmp() library routine is used for the comparison. For a** numeric comparison, use OP_Ge.**** If P2 is zero, do not jump. Instead, push an integer 1 onto the** stack if the jump would have been taken, or a 0 if not. Push a** NULL if either operand was NULL.*/case OP_StrEq:case OP_StrNe:case OP_StrLt:case OP_StrLe:case OP_StrGt:case OP_StrGe: { Mem *pNos = &pTos[-1]; int c; assert( pNos>=p->aStack ); if( (pNos->flags | pTos->flags) & MEM_Null ){ popStack(&pTos, 2); if( pOp->p2 ){ if( pOp->p1 ) pc = pOp->p2-1; }else{ pTos++; pTos->flags = MEM_Null; } break; }else{ Stringify(pTos); Stringify(pNos); c = strcmp(pNos->z, pTos->z); } /* The asserts on each case of the following switch are there to verify ** that string comparison opcodes are always exactly 6 greater than the ** corresponding numeric comparison opcodes. The code generator depends ** on this fact. */ switch( pOp->opcode ){ case OP_StrEq: c = c==0; assert( pOp->opcode-6==OP_Eq ); break; case OP_StrNe: c = c!=0; assert( pOp->opcode-6==OP_Ne ); break; case OP_StrLt: c = c<0; assert( pOp->opcode-6==OP_Lt ); break; case OP_StrLe: c = c<=0; assert( pOp->opcode-6==OP_Le ); break; case OP_StrGt: c = c>0; assert( pOp->opcode-6==OP_Gt ); break; default: c = c>=0; assert( pOp->opcode-6==OP_Ge ); break; } popStack(&pTos, 2); if( pOp->p2 ){ if( c ) pc = pOp->p2-1; }else{ pTos++; pTos->flags = MEM_Int; pTos->i = c; } break;}/* Opcode: And * * ***** Pop two values off the stack. Take the logical AND of the** two values and push the resulting boolean value back onto the** stack. *//* Opcode: Or * * ***** Pop two values off the stack. Take the logical OR of the** two values and push the resulting boolean value back onto the** stack. */case OP_And:case OP_Or: { Mem *pNos = &pTos[-1]; int v1, v2; /* 0==TRUE, 1==FALSE, 2==UNKNOWN or NULL */ assert( pNos>=p->aStack ); if( pTos->flags & MEM_Null ){ v1 = 2; }else{ Integerify(pTos); v1 = pTos->i==0; } if( pNos->flags & MEM_Null ){ v2 = 2; }else{ Integerify(pNos); v2 = pNos->i==0; } if( pOp->opcode==OP_And ){ static const unsigned char and_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 }; v1 = and_logic[v1*3+v2]; }else{ static const unsigned char or_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 }; v1 = or_logic[v1*3+v2]; } popStack(&pTos, 2); pTos++; if( v1==2 ){ pTos->flags = MEM_Null; }else{ pTos->i = v1==0; pTos->flags = MEM_Int; } break;}/* Opcode: Negative * * ***** Treat the top of the stack as a numeric quantity. Replace it** with its additive inverse. If the top of the stack is NULL** its value is unchanged.*//* Opcode: AbsValue * * ***** Treat the top of the stack as a numeric quantity. Replace it** with its absolute value. If the top of the stack is NULL** its value is unchanged.*/case OP_Negative:case OP_AbsValue: { assert( pTos>=p->aStack ); if( pTos->flags & MEM_Real ){ Release(pTos); if( pOp->opcode==OP_Negative || pTos->r<0.0 ){ pTos->r = -pTos->r; } pTos->flags = MEM_Real; }else if( pTos->flags & MEM_Int ){ Release(pTos); if( pOp->opcode==OP_Negative || pTos->i<0 ){ pTos->i = -pTos->i; } pTos->flags = MEM_Int; }else if( pTos->flags & MEM_Null ){ /* Do nothing */ }else{ Realify(pTos); Release(pTos); if( pOp->opcode==OP_Negative || pTos->r<0.0 ){ pTos->r = -pTos->r; } pTos->flags = MEM_Real; } break;}/* Opcode: Not * * ***** Interpret the top of the stack as a boolean value. Replace it** with its complement. If the top of the stack is NULL its value** is unchanged.*/case OP_Not: { assert( pTos>=p->aStack ); if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */ Integerify(pTos); Release(pTos); pTos->i = !pTos->i; pTos->flags = MEM_Int; break;}/* Opcode: BitNot * * *** Interpret the top of the stack as an value. Replace it** with its ones-complement. If the top of the stack is NULL its** value is unchanged.*/case OP_BitNot: { assert( pTos>=p->aStack ); if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */ Integerify(pTos); Release(pTos);
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -