** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
-** $Id: vdbe.c,v 1.252 2004/01/30 14:49:17 drh Exp $
+** $Id: vdbe.c,v 1.253 2004/01/31 19:22:56 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
** Convert the given stack entity into a string if it isn't one
** already.
*/
-#define Stringify(P,I) if((aStack[I].flags & MEM_Str)==0){hardStringify(P,I);}
-static int hardStringify(Vdbe *p, int i){
- Mem *pStack = &p->aStack[i];
+#define Stringify(P) if(((P)->flags & MEM_Str)==0){hardStringify(P);}
+static int hardStringify(Mem *pStack){
int fg = pStack->flags;
if( fg & MEM_Real ){
sqlite_snprintf(sizeof(pStack->zShort),pStack->zShort,"%.15g",pStack->r);
}else{
pStack->zShort[0] = 0;
}
- p->aStack[i].z = pStack->zShort;
+ pStack->z = pStack->zShort;
pStack->n = strlen(pStack->zShort)+1;
- pStack->flags = MEM_Str;
+ pStack->flags = MEM_Str | MEM_Short;
return 0;
}
** will fit but this routine always mallocs for space.
** Return non-zero if we run out of memory.
*/
-#define Dynamicify(P,I) ((aStack[I].flags & MEM_Dyn)==0 ? hardDynamicify(P,I):0)
-static int hardDynamicify(Vdbe *p, int i){
- Mem *pStack = &p->aStack[i];
+#define Dynamicify(P) (((P)->flags & MEM_Dyn)==0 ? hardDynamicify(P):0)
+static int hardDynamicify(Mem *pStack){
int fg = pStack->flags;
char *z;
if( (fg & MEM_Str)==0 ){
- hardStringify(p, i);
+ hardStringify(pStack);
}
assert( (fg & MEM_Dyn)==0 );
z = sqliteMallocRaw( pStack->n );
if( z==0 ) return 1;
- memcpy(z, p->aStack[i].z, pStack->n);
- p->aStack[i].z = z;
+ memcpy(z, pStack->z, pStack->n);
+ pStack->z = z;
pStack->flags |= MEM_Dyn;
return 0;
}
** string that the stack entry itself controls. In other words, it
** converts an MEM_Ephem string into an MEM_Dyn string.
*/
-#define Deephemeralize(P,I) \
- if( ((P)->aStack[I].flags&MEM_Ephem)!=0 && hardDeephem(P,I) ){ goto no_mem;}
-static int hardDeephem(Vdbe *p, int i){
- Mem *pStack = &p->aStack[i];
+#define Deephemeralize(P) \
+ if( ((P)->flags&MEM_Ephem)!=0 && hardDeephem(P) ){ goto no_mem;}
+static int hardDeephem(Mem *pStack){
char *z;
assert( (pStack->flags & MEM_Ephem)!=0 );
z = sqliteMallocRaw( pStack->n );
}
/*
-** Release the memory associated with the given stack level
+** Release the memory associated with the given stack level. This
+** leaves the Mem.flags field in an inconsistent state.
+*/
+#define Release(P) if((P)->flags&MEM_Dyn){ sqliteFree((P)->z); }
+
+/*
+** Pop the stack N times.
*/
-#define Release(P,I) if((P)->aStack[I].flags&MEM_Dyn){ hardRelease(P,I); }
-static void hardRelease(Vdbe *p, int i){
- sqliteFree(p->aStack[i].z);
- p->aStack[i].z = 0;
- p->aStack[i].flags &= ~(MEM_Str|MEM_Dyn|MEM_Static|MEM_Ephem);
+static void popStack(Mem **ppTos, int N){
+ Mem *pTos = *ppTos;
+ while( N>0 ){
+ N--;
+ Release(pTos);
+ pTos--;
+ }
+ *ppTos = pTos;
}
/*
** Any prior string or real representation is invalidated.
** NULLs are converted into 0.
*/
-#define Integerify(P,I) \
- if(((P)->aStack[(I)].flags&MEM_Int)==0){ hardIntegerify(P,I); }
-static void hardIntegerify(Vdbe *p, int i){
- if( p->aStack[i].flags & MEM_Real ){
- p->aStack[i].i = (int)p->aStack[i].r;
- Release(p, i);
- }else if( p->aStack[i].flags & MEM_Str ){
- toInt(p->aStack[i].z, &p->aStack[i].i);
- Release(p, i);
+#define Integerify(P) if(((P)->flags&MEM_Int)==0){ hardIntegerify(P); }
+static void hardIntegerify(Mem *pStack){
+ if( pStack->flags & MEM_Real ){
+ pStack->i = (int)pStack->r;
+ Release(pStack);
+ }else if( pStack->flags & MEM_Str ){
+ toInt(pStack->z, &pStack->i);
+ Release(pStack);
}else{
- p->aStack[i].i = 0;
+ pStack->i = 0;
}
- p->aStack[i].flags = MEM_Int;
+ pStack->flags = MEM_Int;
}
/*
** Any prior string or integer representation is retained.
** NULLs are converted into 0.0.
*/
-#define Realify(P,I) \
- if(((P)->aStack[(I)].flags&MEM_Real)==0){ hardRealify(P,I); }
-static void hardRealify(Vdbe *p, int i){
- if( p->aStack[i].flags & MEM_Str ){
- p->aStack[i].r = sqliteAtoF(p->aStack[i].z);
- }else if( p->aStack[i].flags & MEM_Int ){
- p->aStack[i].r = p->aStack[i].i;
+#define Realify(P) if(((P)->flags&MEM_Real)==0){ hardRealify(P); }
+static void hardRealify(Mem *pStack){
+ if( pStack->flags & MEM_Str ){
+ pStack->r = sqliteAtoF(pStack->z);
+ }else if( pStack->flags & MEM_Int ){
+ pStack->r = pStack->i;
}else{
- p->aStack[i].r = 0.0;
+ pStack->r = 0.0;
}
- p->aStack[i].flags |= MEM_Real;
+ pStack->flags |= MEM_Real;
}
/*
return sHead.pNext;
}
-/*
-** Code contained within the VERIFY() macro is not needed for correct
-** execution. It is there only to catch errors. So when we compile
-** with NDEBUG=1, the VERIFY() code is omitted.
-*/
-#ifdef NDEBUG
-# define VERIFY(X)
-#else
-# define VERIFY(X) X
-#endif
-
/*
** The following routine works like a replacement for the standard
** library routine fgets(). The difference is in how end-of-line (EOL)
Op *pOp; /* Current operation */
int rc = SQLITE_OK; /* Value to return */
sqlite *db = p->db; /* The database */
- Mem *aStack = p->aStack; /* The operand stack */
+ Mem *pTos; /* Top entry in the operand stack */
char zBuf[100]; /* Space to sprintf() an integer */
#ifdef VDBE_PROFILE
unsigned long long start; /* CPU clock count at start of opcode */
p->rc = SQLITE_OK;
assert( p->explain==0 );
if( sqlite_malloc_failed ) goto no_mem;
+ pTos = p->pTos;
if( p->popStack ){
- sqliteVdbePopStack(p, p->popStack);
+ popStack(&pTos, p->popStack);
p->popStack = 0;
}
for(pc=p->pc; rc==SQLITE_OK; pc++){
assert( pc>=0 && pc<p->nOp );
- assert( p->tos<=pc );
+ assert( pTos<=&p->aStack[pc] );
#ifdef VDBE_PROFILE
origPc = pc;
start = hwtime();
*/
case OP_Halt: {
p->magic = VDBE_MAGIC_HALT;
+ p->pTos = pTos;
if( pOp->p1!=SQLITE_OK ){
p->rc = pOp->p1;
p->errorAction = pOp->p2;
** then it is assumed to be a string representation of the same integer.
*/
case OP_Integer: {
- int i = ++p->tos;
- aStack[i].i = pOp->p1;
- aStack[i].flags = MEM_Int;
+ pTos++;
+ pTos->i = pOp->p1;
+ pTos->flags = MEM_Int;
if( pOp->p3 ){
- aStack[i].z = pOp->p3;
- aStack[i].flags |= MEM_Str | MEM_Static;
- aStack[i].n = strlen(pOp->p3)+1;
+ pTos->z = pOp->p3;
+ pTos->flags |= MEM_Str | MEM_Static;
+ pTos->n = strlen(pOp->p3)+1;
}
break;
}
** NULL is pushed onto the stack.
*/
case OP_String: {
- int i = ++p->tos;
- char *z;
- z = pOp->p3;
+ char *z = pOp->p3;
+ pTos++;
if( z==0 ){
- aStack[i].z = 0;
- aStack[i].n = 0;
- aStack[i].flags = MEM_Null;
+ pTos->flags = MEM_Null;
}else{
- aStack[i].z = z;
- aStack[i].n = strlen(z) + 1;
- aStack[i].flags = MEM_Str | MEM_Static;
+ pTos->z = z;
+ pTos->n = strlen(z) + 1;
+ pTos->flags = MEM_Str | MEM_Static;
}
break;
}
** sqlite_bind() API.
*/
case OP_Variable: {
- int i = ++p->tos;
int j = pOp->p1 - 1;
+ pTos++;
if( j>=0 && j<p->nVar && p->azVar[j]!=0 ){
- aStack[i].z = p->azVar[j];
- aStack[i].n = p->anVar[j];
- aStack[i].flags = MEM_Str | MEM_Static;
+ pTos->z = p->azVar[j];
+ pTos->n = p->anVar[j];
+ pTos->flags = MEM_Str | MEM_Static;
}else{
- aStack[i].z = 0;
- aStack[i].n = 0;
- aStack[i].flags = MEM_Null;
+ pTos->flags = MEM_Null;
}
break;
}
** P1 elements are popped off of the top of stack and discarded.
*/
case OP_Pop: {
- assert( p->tos+1>=pOp->p1 );
- sqliteVdbePopStack(p, pOp->p1);
+ assert( pOp->p1>=0 );
+ popStack(&pTos, pOp->p1);
+ assert( pTos>=&p->aStack[-1] );
break;
}
** Also see the Pull instruction.
*/
case OP_Dup: {
- int i = p->tos - pOp->p1;
- int j = ++p->tos;
- VERIFY( if( i<0 ) goto not_enough_stack; )
- memcpy(&aStack[j], &aStack[i], sizeof(aStack[i])-NBFS);
- if( aStack[j].flags & MEM_Str ){
- int isStatic = (aStack[j].flags & MEM_Static)!=0;
- if( pOp->p2 || isStatic ){
- aStack[j].z = aStack[i].z;
- aStack[j].flags &= ~MEM_Dyn;
- if( !isStatic ) aStack[j].flags |= MEM_Ephem;
- }else if( aStack[i].n<=NBFS ){
- memcpy(aStack[j].zShort, aStack[i].z, aStack[j].n);
- aStack[j].z = aStack[j].zShort;
- aStack[j].flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem);
- }else{
- aStack[j].z = sqliteMallocRaw( aStack[j].n );
- if( aStack[j].z==0 ) goto no_mem;
- memcpy(aStack[j].z, aStack[i].z, aStack[j].n);
- aStack[j].flags &= ~(MEM_Static|MEM_Ephem);
- aStack[j].flags |= MEM_Dyn;
+ Mem *pFrom = &pTos[-pOp->p1];
+ assert( pFrom<=pTos && pFrom>=p->aStack );
+ pTos++;
+ memcpy(pTos, pFrom, sizeof(*pFrom)-NBFS);
+ if( pTos->flags & MEM_Str ){
+ if( pOp->p2 && (pTos->flags & (MEM_Dyn|MEM_Ephem)) ){
+ pTos->flags &= ~MEM_Dyn;
+ pTos->flags |= MEM_Ephem;
+ }else if( pTos->flags & MEM_Short ){
+ memcpy(pTos->zShort, pFrom->zShort, pTos->n);
+ pTos->z = pTos->zShort;
+ }else if( (pTos->flags & MEM_Static)==0 ){
+ pTos->z = sqliteMallocRaw(pFrom->n);
+ if( sqlite_malloc_failed ) goto no_mem;
+ memcpy(pTos->z, pFrom->z, pFrom->n);
+ pTos->flags &= ~(MEM_Static|MEM_Ephem|MEM_Short);
+ pTos->flags |= MEM_Dyn;
}
}
break;
** See also the Dup instruction.
*/
case OP_Pull: {
- int from = p->tos - pOp->p1;
- int to = p->tos;
+ Mem *pFrom = &pTos[-pOp->p1];
int i;
Mem ts;
- VERIFY( if( from<0 ) goto not_enough_stack; )
- Deephemeralize(p, from);
- ts = aStack[from];
- Deephemeralize(p, to);
- for(i=from; i<to; i++){
- Deephemeralize(p, i+1);
- aStack[i] = aStack[i+1];
- assert( (aStack[i].flags & MEM_Ephem)==0 );
- if( aStack[i].flags & (MEM_Dyn|MEM_Static) ){
- aStack[i].z = aStack[i+1].z;
- }else{
- aStack[i].z = aStack[i].zShort;
+
+ /* Deephemeralize(pFrom); *** not needed */
+ ts = *pFrom;
+ Deephemeralize(pTos);
+ for(i=0; i<pOp->p1; i++, pFrom++){
+ Deephemeralize(&pFrom[1]);
+ *pFrom = pFrom[1];
+ assert( (pFrom->flags & MEM_Ephem)==0 );
+ if( pFrom->flags & MEM_Short ){
+ assert( pFrom->flags & MEM_Str );
+ assert( pFrom->z==pFrom[1].zShort );
+ assert( (pTos->flags & (MEM_Dyn|MEM_Static|MEM_Ephem))==0 );
+ pFrom->z = pFrom->zShort;
}
}
- aStack[to] = ts;
- assert( (aStack[to].flags & MEM_Ephem)==0 );
- if( (aStack[to].flags & (MEM_Dyn|MEM_Static))==0 ){
- aStack[to].z = aStack[to].zShort;
+ *pTos = ts;
+ /* assert( (pTos->flags & MEM_Ephem)==0 ); *** not needed */
+ if( pTos->flags & MEM_Short ){
+ assert( pTos->flags & MEM_Str );
+ assert( pTos->z==pTos[-pOp->p1].zShort );
+ assert( (pTos->flags & (MEM_Dyn|MEM_Static|MEM_Ephem))==0 );
+ pTos->z = pTos->zShort;
}
break;
}
** of the top of the stack. Then pop the top of the stack.
*/
case OP_Push: {
- int from = p->tos;
- int to = p->tos - pOp->p1;
+ Mem *pTo = &pTos[-pOp->p1];
- VERIFY( if( to<0 ) goto not_enough_stack; )
- if( aStack[to].flags & MEM_Dyn ){
- sqliteFree(aStack[to].z);
- }
- Deephemeralize(p, from);
- aStack[to] = aStack[from];
- if( aStack[to].flags & (MEM_Dyn|MEM_Static|MEM_Ephem) ){
- aStack[to].z = aStack[from].z;
- }else{
- aStack[to].z = aStack[to].zShort;
+ assert( pTo>=p->aStack );
+ Deephemeralize(pTos);
+ Release(pTo);
+ *pTo = *pTos;
+ if( pTo->flags & MEM_Short ){
+ assert( pTo->z==pTos->zShort );
+ pTo->z = pTo->zShort;
}
- aStack[from].flags = 0;
- p->tos--;
+ pTos--;
break;
}
+
/* Opcode: ColumnName P1 * P3
**
** P3 becomes the P1-th column name (first is 0). An array of pointers
** 3rd parameter.
*/
case OP_Callback: {
- int i = p->tos - pOp->p1 + 1;
- int j;
- VERIFY( if( i<0 ) goto not_enough_stack; )
- for(j=i; j<=p->tos; j++){
- if( aStack[j].flags & MEM_Null ){
- aStack[j].z = 0;
+ int i;
+ char **azArgv = p->zArgv;
+ Mem *pCol;
+
+ pCol = &pTos[1-pOp->p1];
+ assert( pCol>=p->aStack );
+ for(i=0; i<pOp->p1; i++, pCol++){
+ if( pCol->flags & MEM_Null ){
+ azArgv[i] = 0;
}else{
- Stringify(p, j);
+ Stringify(pCol);
+ azArgv[i] = pCol->z;
}
- p->zArgv[j] = aStack[j].z;
}
- p->zArgv[p->tos+1] = 0;
+ azArgv[i] = 0;
if( p->xCallback==0 ){
- p->azResColumn = &p->zArgv[i];
+ p->azResColumn = azArgv;
p->nResColumn = pOp->p1;
p->popStack = pOp->p1;
p->pc = pc + 1;
+ p->pTos = pTos;
return SQLITE_ROW;
}
if( sqliteSafetyOff(db) ) goto abort_due_to_misuse;
- if( p->xCallback(p->pCbArg, pOp->p1, &p->zArgv[i], p->azColName)!=0 ){
+ if( p->xCallback(p->pCbArg, pOp->p1, azArgv, p->azColName)!=0 ){
rc = SQLITE_ABORT;
}
if( sqliteSafetyOn(db) ) goto abort_due_to_misuse;
p->nCallback++;
- sqliteVdbePopStack(p, pOp->p1);
+ popStack(&pTos, pOp->p1);
+ assert( pTos>=&p->aStack[-1] );
if( sqlite_malloc_failed ) goto no_mem;
break;
}
int i, j;
char *zSep;
int nSep;
+ Mem *pTerm;
nField = pOp->p1;
zSep = pOp->p3;
if( zSep==0 ) zSep = "";
nSep = strlen(zSep);
- VERIFY( if( p->tos+1<nField ) goto not_enough_stack; )
+ assert( &pTos[1-nField] >= p->aStack );
nByte = 1 - nSep;
- for(i=p->tos-nField+1; i<=p->tos; i++){
- if( aStack[i].flags & MEM_Null ){
+ pTerm = &pTos[1-nField];
+ for(i=0; i<nField; i++, pTerm++){
+ if( pTerm->flags & MEM_Null ){
nByte = -1;
break;
}else{
- Stringify(p, i);
- nByte += aStack[i].n - 1 + nSep;
+ Stringify(pTerm);
+ nByte += pTerm->n - 1 + nSep;
}
}
if( nByte<0 ){
- if( pOp->p2==0 ) sqliteVdbePopStack(p, nField);
- p->tos++;
- aStack[p->tos].flags = MEM_Null;
- aStack[p->tos].z = 0;
+ if( pOp->p2==0 ){
+ popStack(&pTos, nField);
+ }
+ pTos++;
+ pTos->flags = MEM_Null;
break;
}
zNew = sqliteMallocRaw( nByte );
if( zNew==0 ) goto no_mem;
j = 0;
- for(i=p->tos-nField+1; i<=p->tos; i++){
- if( (aStack[i].flags & MEM_Null)==0 ){
- memcpy(&zNew[j], aStack[i].z, aStack[i].n-1);
- j += aStack[i].n-1;
- }
- if( nSep>0 && i<p->tos ){
+ pTerm = &pTos[1-nField];
+ for(i=j=0; i<nField; i++, pTerm++){
+ assert( pTerm->flags & MEM_Str );
+ memcpy(&zNew[j], pTerm->z, pTerm->n-1);
+ j += pTerm->n-1;
+ if( nSep>0 && i<nField-1 ){
memcpy(&zNew[j], zSep, nSep);
j += nSep;
}
}
zNew[j] = 0;
- if( pOp->p2==0 ) sqliteVdbePopStack(p, nField);
- p->tos++;
- aStack[p->tos].n = nByte;
- aStack[p->tos].flags = MEM_Str|MEM_Dyn;
- aStack[p->tos].z = zNew;
+ if( pOp->p2==0 ){
+ popStack(&pTos, nField);
+ }
+ pTos++;
+ pTos->n = nByte;
+ pTos->flags = MEM_Str|MEM_Dyn;
+ pTos->z = zNew;
break;
}
case OP_Multiply:
case OP_Divide:
case OP_Remainder: {
- int tos = p->tos;
- int nos = tos - 1;
- VERIFY( if( nos<0 ) goto not_enough_stack; )
- if( ((aStack[tos].flags | aStack[nos].flags) & MEM_Null)!=0 ){
- POPSTACK;
- Release(p, nos);
- aStack[nos].flags = MEM_Null;
- }else if( (aStack[tos].flags & aStack[nos].flags & MEM_Int)==MEM_Int ){
+ Mem *pNos = &pTos[-1];
+ assert( pNos>=p->aStack );
+ if( ((pTos->flags | pNos->flags) & MEM_Null)!=0 ){
+ Release(pTos);
+ pTos--;
+ Release(pTos);
+ pTos->flags = MEM_Null;
+ }else if( (pTos->flags & pNos->flags & MEM_Int)==MEM_Int ){
int a, b;
- a = aStack[tos].i;
- b = aStack[nos].i;
+ a = pTos->i;
+ b = pNos->i;
switch( pOp->opcode ){
case OP_Add: b += a; break;
case OP_Subtract: b -= a; break;
break;
}
}
- POPSTACK;
- Release(p, nos);
- aStack[nos].i = b;
- aStack[nos].flags = MEM_Int;
+ Release(pTos);
+ pTos--;
+ Release(pTos);
+ pTos->i = b;
+ pTos->flags = MEM_Int;
}else{
double a, b;
- Realify(p, tos);
- Realify(p, nos);
- a = aStack[tos].r;
- b = aStack[nos].r;
+ Realify(pTos);
+ Realify(pNos);
+ a = pTos->r;
+ b = pNos->r;
switch( pOp->opcode ){
case OP_Add: b += a; break;
case OP_Subtract: b -= a; break;
break;
}
}
- POPSTACK;
- Release(p, nos);
- aStack[nos].r = b;
- aStack[nos].flags = MEM_Real;
+ Release(pTos);
+ pTos--;
+ Release(pTos);
+ pTos->r = b;
+ pTos->flags = MEM_Real;
}
break;
divide_by_zero:
- sqliteVdbePopStack(p, 2);
- p->tos = nos;
- aStack[nos].flags = MEM_Null;
+ Release(pTos);
+ pTos--;
+ Release(pTos);
+ pTos->flags = MEM_Null;
break;
}
*/
case OP_Function: {
int n, i;
+ Mem *pArg;
+ char **azArgv;
sqlite_func ctx;
n = pOp->p1;
- VERIFY( if( n<0 ) goto bad_instruction; )
- VERIFY( if( p->tos+1<n ) goto not_enough_stack; )
- for(i=p->tos-n+1; i<=p->tos; i++){
- if( aStack[i].flags & MEM_Null ){
- aStack[i].z = 0;
+ pArg = &pTos[1-n];
+ azArgv = p->zArgv;
+ for(i=0; i<n; i++, pArg++){
+ if( pArg->flags & MEM_Null ){
+ azArgv[i] = 0;
}else{
- Stringify(p, i);
+ Stringify(pArg);
+ azArgv[i] = pArg->z;
}
- p->zArgv[i] = aStack[i].z;
}
ctx.pFunc = (FuncDef*)pOp->p3;
ctx.s.flags = MEM_Null;
ctx.isError = 0;
ctx.isStep = 0;
if( sqliteSafetyOff(db) ) goto abort_due_to_misuse;
- (*ctx.pFunc->xFunc)(&ctx, n, (const char**)&p->zArgv[p->tos-n+1]);
+ (*ctx.pFunc->xFunc)(&ctx, n, (const char**)azArgv);
if( sqliteSafetyOn(db) ) goto abort_due_to_misuse;
- sqliteVdbePopStack(p, n);
- p->tos++;
- aStack[p->tos] = ctx.s;
- if( ctx.s.flags & MEM_Dyn ){
- aStack[p->tos].z = ctx.s.z;
- }else if( ctx.s.flags & MEM_Str ){
- aStack[p->tos].z = aStack[p->tos].zShort;
- }else{
- aStack[p->tos].z = 0;
+ popStack(&pTos, n);
+ pTos++;
+ *pTos = ctx.s;
+ if( pTos->flags & MEM_Short ){
+ pTos->z = pTos->zShort;
}
if( ctx.isError ){
sqliteSetString(&p->zErrMsg,
- aStack[p->tos].z ? aStack[p->tos].z : "user function error", (char*)0);
+ (pTos->flags & MEM_Str)!=0 ? pTos->z : "user function error", (char*)0);
rc = SQLITE_ERROR;
}
break;
case OP_BitOr:
case OP_ShiftLeft:
case OP_ShiftRight: {
- int tos = p->tos;
- int nos = tos - 1;
+ Mem *pNos = &pTos[-1];
int a, b;
- VERIFY( if( nos<0 ) goto not_enough_stack; )
- if( (aStack[tos].flags | aStack[nos].flags) & MEM_Null ){
- POPSTACK;
- Release(p,nos);
- aStack[nos].flags = MEM_Null;
+
+ assert( pNos>=p->aStack );
+ if( (pTos->flags | pNos->flags) & MEM_Null ){
+ popStack(&pTos, 2);
+ pTos++;
+ pTos->flags = MEM_Null;
break;
}
- Integerify(p, tos);
- Integerify(p, nos);
- a = aStack[tos].i;
- b = aStack[nos].i;
+ Integerify(pTos);
+ Integerify(pNos);
+ a = pTos->i;
+ b = pNos->i;
switch( pOp->opcode ){
case OP_BitAnd: a &= b; break;
case OP_BitOr: a |= b; break;
case OP_ShiftRight: a >>= b; break;
default: /* CANT HAPPEN */ break;
}
- POPSTACK;
- Release(p, nos);
- aStack[nos].i = a;
- aStack[nos].flags = MEM_Int;
+ assert( (pTos->flags & MEM_Dyn)==0 );
+ assert( (pNos->flags & MEM_Dyn)==0 );
+ pTos--;
+ pTos->i = a;
+ assert( pTos->flags==MEM_Int );
break;
}
** To force the top of the stack to be an integer, just add 0.
*/
case OP_AddImm: {
- int tos = p->tos;
- VERIFY( if( tos<0 ) goto not_enough_stack; )
- Integerify(p, tos);
- aStack[tos].i += pOp->p1;
+ assert( pTos>=p->aStack );
+ Integerify(pTos);
+ pTos->i += pOp->p1;
break;
}
** greater than its current value if P1==1.
*/
case OP_ForceInt: {
- int tos = p->tos;
int v;
- VERIFY( if( tos<0 ) goto not_enough_stack; )
- if( (aStack[tos].flags & (MEM_Int|MEM_Real))==0
- && (aStack[tos].z==0 || sqliteIsNumber(aStack[tos].z)==0) ){
- POPSTACK;
+ assert( pTos>=p->aStack );
+ if( (pTos->flags & (MEM_Int|MEM_Real))==0
+ && ((pTos->flags & MEM_Str)==0 || sqliteIsNumber(pTos->z)==0) ){
+ Release(pTos);
+ pTos--;
pc = pOp->p2 - 1;
break;
}
- if( aStack[tos].flags & MEM_Int ){
- v = aStack[tos].i + (pOp->p1!=0);
+ if( pTos->flags & MEM_Int ){
+ v = pTos->i + (pOp->p1!=0);
}else{
- Realify(p, tos);
- v = (int)aStack[tos].r;
- if( aStack[tos].r>(double)v ) v++;
- if( pOp->p1 && aStack[tos].r==(double)v ) v++;
- }
- if( aStack[tos].flags & MEM_Dyn ) sqliteFree(aStack[tos].z);
- aStack[tos].z = 0;
- aStack[tos].i = v;
- aStack[tos].flags = MEM_Int;
+ Realify(pTos);
+ v = (int)pTos->r;
+ if( pTos->r>(double)v ) v++;
+ if( pOp->p1 && pTos->r==(double)v ) v++;
+ }
+ Release(pTos);
+ pTos->i = v;
+ pTos->flags = MEM_Int;
break;
}
** of the stack is unchanged.
*/
case OP_MustBeInt: {
- int tos = p->tos;
- VERIFY( if( tos<0 ) goto not_enough_stack; )
- if( aStack[tos].flags & MEM_Int ){
+ assert( pTos>=p->aStack );
+ if( pTos->flags & MEM_Int ){
/* Do nothing */
- }else if( aStack[tos].flags & MEM_Real ){
- int i = aStack[tos].r;
+ }else if( pTos->flags & MEM_Real ){
+ int i = (int)pTos->r;
double r = (double)i;
- if( r!=aStack[tos].r ){
+ if( r!=pTos->r ){
goto mismatch;
}
- aStack[tos].i = i;
- }else if( aStack[tos].flags & MEM_Str ){
+ pTos->i = i;
+ }else if( pTos->flags & MEM_Str ){
int v;
- if( !toInt(aStack[tos].z, &v) ){
+ if( !toInt(pTos->z, &v) ){
double r;
- if( !sqliteIsNumber(aStack[tos].z) ){
+ if( !sqliteIsNumber(pTos->z) ){
goto mismatch;
}
- Realify(p, tos);
- assert( (aStack[tos].flags & MEM_Real)!=0 );
- v = aStack[tos].r;
+ Realify(pTos);
+ v = (int)pTos->r;
r = (double)v;
- if( r!=aStack[tos].r ){
+ if( r!=pTos->r ){
goto mismatch;
}
}
- aStack[tos].i = v;
+ pTos->i = v;
}else{
goto mismatch;
}
- Release(p, tos);
- aStack[tos].flags = MEM_Int;
+ Release(pTos);
+ pTos->flags = MEM_Int;
break;
mismatch:
rc = SQLITE_MISMATCH;
goto abort_due_to_error;
}else{
- if( pOp->p1 ) POPSTACK;
+ if( pOp->p1 ) popStack(&pTos, 1);
pc = pOp->p2 - 1;
}
break;
case OP_Le:
case OP_Gt:
case OP_Ge: {
- int tos = p->tos;
- int nos = tos - 1;
+ Mem *pNos = &pTos[-1];
int c, v;
int ft, fn;
- VERIFY( if( nos<0 ) goto not_enough_stack; )
- ft = aStack[tos].flags;
- fn = aStack[nos].flags;
+ assert( pNos>=p->aStack );
+ ft = pTos->flags;
+ fn = pNos->flags;
if( (ft | fn) & MEM_Null ){
- POPSTACK;
- POPSTACK;
+ popStack(&pTos, 2);
if( pOp->p2 ){
if( pOp->p1 ) pc = pOp->p2-1;
}else{
- p->tos++;
- aStack[nos].flags = MEM_Null;
+ pTos++;
+ pTos->flags = MEM_Null;
}
break;
}else if( (ft & fn & MEM_Int)==MEM_Int ){
- c = aStack[nos].i - aStack[tos].i;
- }else if( (ft & MEM_Int)!=0 && (fn & MEM_Str)!=0 && toInt(aStack[nos].z,&v) ){
- Release(p, nos);
- aStack[nos].i = v;
- aStack[nos].flags = MEM_Int;
- c = aStack[nos].i - aStack[tos].i;
- }else if( (fn & MEM_Int)!=0 && (ft & MEM_Str)!=0 && toInt(aStack[tos].z,&v) ){
- Release(p, tos);
- aStack[tos].i = v;
- aStack[tos].flags = MEM_Int;
- c = aStack[nos].i - aStack[tos].i;
+ 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(p, tos);
- Stringify(p, nos);
- c = sqliteCompare(aStack[nos].z, aStack[tos].z);
+ Stringify(pTos);
+ Stringify(pNos);
+ c = sqliteCompare(pNos->z, pTos->z);
}
switch( pOp->opcode ){
case OP_Eq: c = c==0; break;
case OP_Gt: c = c>0; break;
default: c = c>=0; break;
}
- POPSTACK;
- POPSTACK;
+ popStack(&pTos, 2);
if( pOp->p2 ){
if( c ) pc = pOp->p2-1;
}else{
- p->tos++;
- aStack[nos].flags = MEM_Int;
- aStack[nos].i = c;
+ pTos++;
+ pTos->i = c;
+ pTos->flags = MEM_Int;
}
break;
}
case OP_StrLe:
case OP_StrGt:
case OP_StrGe: {
- int tos = p->tos;
- int nos = tos - 1;
+ Mem *pNos = &pTos[-1];
int c;
- VERIFY( if( nos<0 ) goto not_enough_stack; )
- if( (aStack[nos].flags | aStack[tos].flags) & MEM_Null ){
- POPSTACK;
- POPSTACK;
+ 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{
- p->tos++;
- aStack[nos].flags = MEM_Null;
+ pTos++;
+ pTos->flags = MEM_Null;
}
break;
}else{
- Stringify(p, tos);
- Stringify(p, nos);
- c = strcmp(aStack[nos].z, aStack[tos].z);
+ 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
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;
- POPSTACK;
+ popStack(&pTos, 2);
if( pOp->p2 ){
if( c ) pc = pOp->p2-1;
}else{
- p->tos++;
- aStack[nos].flags = MEM_Int;
- aStack[nos].i = c;
+ pTos++;
+ pTos->flags = MEM_Int;
+ pTos->i = c;
}
break;
}
*/
case OP_And:
case OP_Or: {
- int tos = p->tos;
- int nos = tos - 1;
+ Mem *pNos = &pTos[-1];
int v1, v2; /* 0==TRUE, 1==FALSE, 2==UNKNOWN or NULL */
- VERIFY( if( nos<0 ) goto not_enough_stack; )
- if( aStack[tos].flags & MEM_Null ){
+ assert( pNos>=p->aStack );
+ if( pTos->flags & MEM_Null ){
v1 = 2;
}else{
- Integerify(p, tos);
- v1 = aStack[tos].i==0;
+ Integerify(pTos);
+ v1 = pTos->i==0;
}
- if( aStack[nos].flags & MEM_Null ){
+ if( pNos->flags & MEM_Null ){
v2 = 2;
}else{
- Integerify(p, nos);
- v2 = aStack[nos].i==0;
+ 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 };
static const unsigned char or_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 };
v1 = or_logic[v1*3+v2];
}
- POPSTACK;
- Release(p, nos);
+ popStack(&pTos, 2);
+ pTos++;
if( v1==2 ){
- aStack[nos].flags = MEM_Null;
+ pTos->flags = MEM_Null;
}else{
- aStack[nos].i = v1==0;
- aStack[nos].flags = MEM_Int;
+ pTos->i = v1==0;
+ pTos->flags = MEM_Int;
}
break;
}
*/
case OP_Negative:
case OP_AbsValue: {
- int tos = p->tos;
- VERIFY( if( tos<0 ) goto not_enough_stack; )
- if( aStack[tos].flags & MEM_Real ){
- Release(p, tos);
- if( pOp->opcode==OP_Negative || aStack[tos].r<0.0 ){
- aStack[tos].r = -aStack[tos].r;
+ assert( pTos>=p->aStack );
+ if( pTos->flags & MEM_Real ){
+ Release(pTos);
+ if( pOp->opcode==OP_Negative || pTos->r<0.0 ){
+ pTos->r = -pTos->r;
}
- aStack[tos].flags = MEM_Real;
- }else if( aStack[tos].flags & MEM_Int ){
- Release(p, tos);
- if( pOp->opcode==OP_Negative || aStack[tos].i<0 ){
- aStack[tos].i = -aStack[tos].i;
+ pTos->flags = MEM_Real;
+ }else if( pTos->flags & MEM_Int ){
+ Release(pTos);
+ if( pOp->opcode==OP_Negative || pTos->i<0 ){
+ pTos->i = -pTos->i;
}
- aStack[tos].flags = MEM_Int;
- }else if( aStack[tos].flags & MEM_Null ){
+ pTos->flags = MEM_Int;
+ }else if( pTos->flags & MEM_Null ){
/* Do nothing */
}else{
- Realify(p, tos);
- Release(p, tos);
- if( pOp->opcode==OP_Negative || aStack[tos].r<0.0 ){
- aStack[tos].r = -aStack[tos].r;
+ Realify(pTos);
+ Release(pTos);
+ if( pOp->opcode==OP_Negative || pTos->r<0.0 ){
+ pTos->r = -pTos->r;
}
- aStack[tos].flags = MEM_Real;
+ pTos->flags = MEM_Real;
}
break;
}
** is unchanged.
*/
case OP_Not: {
- int tos = p->tos;
- VERIFY( if( p->tos<0 ) goto not_enough_stack; )
- if( aStack[tos].flags & MEM_Null ) break; /* Do nothing to NULLs */
- Integerify(p, tos);
- Release(p, tos);
- aStack[tos].i = !aStack[tos].i;
- aStack[tos].flags = MEM_Int;
+ assert( pTos>=p->aStack );
+ if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */
+ Integerify(pTos);
+ assert( pTos->flags==MEM_Int );
+ pTos->i = !pTos->i;
break;
}
** value is unchanged.
*/
case OP_BitNot: {
- int tos = p->tos;
- VERIFY( if( p->tos<0 ) goto not_enough_stack; )
- if( aStack[tos].flags & MEM_Null ) break; /* Do nothing to NULLs */
- Integerify(p, tos);
- Release(p, tos);
- aStack[tos].i = ~aStack[tos].i;
- aStack[tos].flags = MEM_Int;
+ assert( pTos>=p->aStack );
+ if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */
+ Integerify(pTos);
+ assert( pTos->flags==MEM_Int );
+ pTos->i = ~pTos->i;
break;
}
case OP_If:
case OP_IfNot: {
int c;
- VERIFY( if( p->tos<0 ) goto not_enough_stack; )
- if( aStack[p->tos].flags & MEM_Null ){
+ assert( pTos>=p->aStack );
+ if( pTos->flags & MEM_Null ){
c = pOp->p1;
}else{
- Integerify(p, p->tos);
- c = aStack[p->tos].i;
+ Integerify(pTos);
+ c = pTos->i;
if( pOp->opcode==OP_IfNot ) c = !c;
}
- POPSTACK;
+ assert( (pTos->flags & MEM_Dyn)==0 );
+ pTos--;
if( c ) pc = pOp->p2-1;
break;
}
*/
case OP_IsNull: {
int i, cnt;
+ Mem *pTerm;
cnt = pOp->p1;
if( cnt<0 ) cnt = -cnt;
- VERIFY( if( p->tos+1-cnt<0 ) goto not_enough_stack; )
- for(i=0; i<cnt; i++){
- if( aStack[p->tos-i].flags & MEM_Null ){
+ pTerm = &pTos[1-cnt];
+ assert( pTerm>=p->aStack );
+ for(i=0; i<cnt; i++, pTerm++){
+ if( pTerm->flags & MEM_Null ){
pc = pOp->p2-1;
break;
}
}
- if( pOp->p1>0 ) sqliteVdbePopStack(p, cnt);
+ if( pOp->p1>0 ) popStack(&pTos, cnt);
break;
}
int i, cnt;
cnt = pOp->p1;
if( cnt<0 ) cnt = -cnt;
- VERIFY( if( p->tos+1-cnt<0 ) goto not_enough_stack; )
- for(i=0; i<cnt && (aStack[p->tos-i].flags & MEM_Null)==0; i++){}
+ assert( &pTos[1-cnt] >= p->aStack );
+ for(i=0; i<cnt && (pTos[1+i-cnt].flags & MEM_Null)==0; i++){}
if( i>=cnt ) pc = pOp->p2-1;
- if( pOp->p1>0 ) sqliteVdbePopStack(p, cnt);
+ if( pOp->p1>0 ) popStack(&pTos, cnt);
break;
}
int i, j;
int idxWidth;
u32 addr;
+ Mem *pRec;
int addUnique = 0; /* True to cause bytes to be added to make the
** generated record distinct */
char zTemp[NBFS]; /* Temp space for small records */
** Idx(N) contains the total number of bytes in the record.
*/
nField = pOp->p1;
- VERIFY( if( p->tos+1<nField ) goto not_enough_stack; )
+ pRec = &pTos[1-nField];
+ assert( pRec>=p->aStack );
nByte = 0;
- for(i=p->tos-nField+1; i<=p->tos; i++){
- if( (aStack[i].flags & MEM_Null) ){
+ for(i=0; i<nField; i++, pRec++){
+ if( pRec->flags & MEM_Null ){
addUnique = pOp->p2;
}else{
- Stringify(p, i);
- nByte += aStack[i].n;
+ Stringify(pRec);
+ nByte += pRec->n;
}
}
if( addUnique ) nByte += sizeof(p->uniqueCnt);
}
j = 0;
addr = idxWidth*(nField+1) + addUnique*sizeof(p->uniqueCnt);
- for(i=p->tos-nField+1; i<=p->tos; i++){
+ for(i=0, pRec=&pTos[1-nField]; i<nField; i++, pRec++){
zNewRecord[j++] = addr & 0xff;
if( idxWidth>1 ){
zNewRecord[j++] = (addr>>8)&0xff;
zNewRecord[j++] = (addr>>16)&0xff;
}
}
- if( (aStack[i].flags & MEM_Null)==0 ){
- addr += aStack[i].n;
+ if( (pRec->flags & MEM_Null)==0 ){
+ addr += pRec->n;
}
}
zNewRecord[j++] = addr & 0xff;
p->uniqueCnt++;
j += sizeof(p->uniqueCnt);
}
- for(i=p->tos-nField+1; i<=p->tos; i++){
- if( (aStack[i].flags & MEM_Null)==0 ){
- memcpy(&zNewRecord[j], aStack[i].z, aStack[i].n);
- j += aStack[i].n;
+ for(i=0, pRec=&pTos[1-nField]; i<nField; i++, pRec++){
+ if( (pRec->flags & MEM_Null)==0 ){
+ memcpy(&zNewRecord[j], pRec->z, pRec->n);
+ j += pRec->n;
}
}
- sqliteVdbePopStack(p, nField);
- p->tos++;
- aStack[p->tos].n = nByte;
+ popStack(&pTos, nField);
+ pTos++;
+ pTos->n = nByte;
if( nByte<=NBFS ){
assert( zNewRecord==zTemp );
- memcpy(aStack[p->tos].zShort, zTemp, nByte);
- aStack[p->tos].z = aStack[p->tos].zShort;
- aStack[p->tos].flags = MEM_Str;
+ memcpy(pTos->zShort, zTemp, nByte);
+ pTos->z = pTos->zShort;
+ pTos->flags = MEM_Str | MEM_Short;
}else{
assert( zNewRecord!=zTemp );
- aStack[p->tos].flags = MEM_Str | MEM_Dyn;
- aStack[p->tos].z = zNewRecord;
+ pTos->z = zNewRecord;
+ pTos->flags = MEM_Str | MEM_Dyn;
}
break;
}
int addRowid;
int i, j;
int containsNull = 0;
+ Mem *pRec;
char zTemp[NBFS];
addRowid = pOp->opcode==OP_MakeIdxKey;
nField = pOp->p1;
- VERIFY( if( p->tos+1+addRowid<nField ) goto not_enough_stack; )
+ pRec = &pTos[1-nField];
+ assert( pRec>=p->aStack );
nByte = 0;
- for(j=0, i=p->tos-nField+1; i<=p->tos; i++, j++){
- int flags = aStack[i].flags;
+ for(j=0, i=0; i<nField; i++, j++, pRec++){
+ int flags = pRec->flags;
int len;
char *z;
if( flags & MEM_Null ){
nByte += 2;
containsNull = 1;
}else if( pOp->p3 && pOp->p3[j]=='t' ){
- Stringify(p, i);
- aStack[i].flags &= ~(MEM_Int|MEM_Real);
- nByte += aStack[i].n+1;
- }else if( (flags & (MEM_Real|MEM_Int))!=0 || sqliteIsNumber(aStack[i].z) ){
+ Stringify(pRec);
+ pRec->flags &= ~(MEM_Int|MEM_Real);
+ nByte += pRec->n+1;
+ }else if( (flags & (MEM_Real|MEM_Int))!=0 || sqliteIsNumber(pRec->z) ){
if( (flags & (MEM_Real|MEM_Int))==MEM_Int ){
- aStack[i].r = aStack[i].i;
+ pRec->r = pRec->i;
}else if( (flags & (MEM_Real|MEM_Int))==0 ){
- aStack[i].r = sqliteAtoF(aStack[i].z);
+ pRec->r = sqliteAtoF(pRec->z);
}
- Release(p, i);
- z = aStack[i].zShort;
- sqliteRealToSortable(aStack[i].r, z);
+ Release(pRec);
+ z = pRec->zShort;
+ sqliteRealToSortable(pRec->r, z);
len = strlen(z);
- aStack[i].z = 0;
- aStack[i].flags = MEM_Real;
- aStack[i].n = len+1;
- nByte += aStack[i].n+1;
+ pRec->z = 0;
+ pRec->flags = MEM_Real;
+ pRec->n = len+1;
+ nByte += pRec->n+1;
}else{
- nByte += aStack[i].n+1;
+ nByte += pRec->n+1;
}
}
if( nByte+sizeof(u32)>MAX_BYTES_PER_ROW ){
if( zNewKey==0 ) goto no_mem;
}
j = 0;
- for(i=p->tos-nField+1; i<=p->tos; i++){
- if( aStack[i].flags & MEM_Null ){
+ pRec = &pTos[1-nField];
+ for(i=0; i<nField; i++, pRec++){
+ if( pRec->flags & MEM_Null ){
zNewKey[j++] = 'a';
zNewKey[j++] = 0;
+ }else if( pRec->flags==MEM_Real ){
+ zNewKey[j++] = 'b';
+ memcpy(&zNewKey[j], pRec->zShort, pRec->n);
+ j += pRec->n;
}else{
- if( aStack[i].flags & (MEM_Int|MEM_Real) ){
- zNewKey[j++] = 'b';
- }else{
- zNewKey[j++] = 'c';
- }
- /*** Is this right? ****/
- memcpy(&zNewKey[j],aStack[i].z?aStack[i].z:aStack[i].zShort,aStack[i].n);
- j += aStack[i].n;
+ assert( pRec->flags & MEM_Str );
+ zNewKey[j++] = 'c';
+ memcpy(&zNewKey[j], pRec->z, pRec->n);
+ j += pRec->n;
}
}
if( addRowid ){
u32 iKey;
- Integerify(p, p->tos-nField);
- iKey = intToKey(aStack[p->tos-nField].i);
+ pRec = &pTos[-nField];
+ assert( pRec>=p->aStack );
+ Integerify(pRec);
+ iKey = intToKey(pRec->i);
memcpy(&zNewKey[j], &iKey, sizeof(u32));
- sqliteVdbePopStack(p, nField+1);
+ popStack(&pTos, nField+1);
if( pOp->p2 && containsNull ) pc = pOp->p2 - 1;
}else{
- if( pOp->p2==0 ) sqliteVdbePopStack(p, nField+addRowid);
+ if( pOp->p2==0 ) popStack(&pTos, nField);
}
- p->tos++;
- aStack[p->tos].n = nByte;
+ pTos++;
+ pTos->n = nByte;
if( nByte<=NBFS ){
assert( zNewKey==zTemp );
- aStack[p->tos].z = aStack[p->tos].zShort;
- memcpy(aStack[p->tos].z, zTemp, nByte);
- aStack[p->tos].flags = MEM_Str;
+ pTos->z = pTos->zShort;
+ memcpy(pTos->zShort, zTemp, nByte);
+ pTos->flags = MEM_Str | MEM_Short;
}else{
- aStack[p->tos].flags = MEM_Str|MEM_Dyn;
- aStack[p->tos].z = zNewKey;
+ pTos->z = zNewKey;
+ pTos->flags = MEM_Str | MEM_Dyn;
}
break;
}
** the key itself.
*/
case OP_IncrKey: {
- int tos = p->tos;
-
- VERIFY( if( tos<0 ) goto bad_instruction );
- Stringify(p, tos);
- if( aStack[tos].flags & (MEM_Static|MEM_Ephem) ){
- /* CANT HAPPEN. The IncrKey opcode is only applied to keys
- ** generated by MakeKey or MakeIdxKey and the results of those
- ** operands are always dynamic strings.
- */
- goto abort_due_to_error;
- }
- aStack[tos].z[aStack[tos].n-1]++;
+ assert( pTos>=p->aStack );
+ /* The IncrKey opcode is only applied to keys generated by
+ ** MakeKey or MakeIdxKey and the results of those operands
+ ** are always dynamic strings or zShort[] strings. So we
+ ** are always free to modify the string in place.
+ */
+ assert( pTos->flags & (MEM_Dyn|MEM_Short) );
+ pTos->z[pTos->n-1]++;
break;
}
p->pc = pc;
p->undoTransOnError = 1;
p->rc = SQLITE_BUSY;
+ p->pTos = pTos;
return SQLITE_BUSY;
}else if( (*db->xBusyCallback)(db->pBusyArg, "", busy++)==0 ){
sqliteSetString(&p->zErrMsg, sqlite_error_string(rc), (char*)0);
** executing this instruction.
*/
case OP_ReadCookie: {
- int i = ++p->tos;
int aMeta[SQLITE_N_BTREE_META];
assert( pOp->p2<SQLITE_N_BTREE_META );
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( db->aDb[pOp->p1].pBt!=0 );
rc = sqliteBtreeGetMeta(db->aDb[pOp->p1].pBt, aMeta);
- aStack[i].i = aMeta[1+pOp->p2];
- aStack[i].flags = MEM_Int;
+ pTos++;
+ pTos->i = aMeta[1+pOp->p2];
+ pTos->flags = MEM_Int;
break;
}
assert( pOp->p2<SQLITE_N_BTREE_META );
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( db->aDb[pOp->p1].pBt!=0 );
- VERIFY( if( p->tos<0 ) goto not_enough_stack; )
- Integerify(p, p->tos)
+ assert( pTos>=p->aStack );
+ Integerify(pTos)
rc = sqliteBtreeGetMeta(db->aDb[pOp->p1].pBt, aMeta);
if( rc==SQLITE_OK ){
- aMeta[1+pOp->p2] = aStack[p->tos].i;
+ aMeta[1+pOp->p2] = pTos->i;
rc = sqliteBtreeUpdateMeta(db->aDb[pOp->p1].pBt, aMeta);
}
- POPSTACK;
+ assert( pTos->flags==MEM_Int );
+ pTos--;
break;
}
case OP_OpenWrite: {
int busy = 0;
int i = pOp->p1;
- int tos = p->tos;
int p2 = pOp->p2;
int wrFlag;
Btree *pX;
int iDb;
- VERIFY( if( tos<0 ) goto not_enough_stack; );
- Integerify(p, tos);
- iDb = p->aStack[tos].i;
- tos--;
- VERIFY( if( iDb<0 || iDb>=db->nDb ) goto bad_instruction; );
- VERIFY( if( db->aDb[iDb].pBt==0 ) goto bad_instruction; );
+ assert( pTos>=p->aStack );
+ Integerify(pTos);
+ iDb = pTos->i;
+ pTos--;
+ assert( iDb>=0 && iDb<db->nDb );
pX = db->aDb[iDb].pBt;
+ assert( pX!=0 );
wrFlag = pOp->opcode==OP_OpenWrite;
if( p2<=0 ){
- VERIFY( if( tos<0 ) goto not_enough_stack; );
- Integerify(p, tos);
- p2 = p->aStack[tos].i;
- POPSTACK;
+ assert( pTos>=p->aStack );
+ Integerify(pTos);
+ p2 = pTos->i;
+ pTos--;
if( p2<2 ){
sqliteSetString(&p->zErrMsg, "root page number less than 2", (char*)0);
rc = SQLITE_INTERNAL;
break;
}
}
- VERIFY( if( i<0 ) goto bad_instruction; )
+ assert( i>=0 );
if( expandCursorArraySize(p, i) ) goto no_mem;
sqliteVdbeCleanupCursor(&p->aCsr[i]);
memset(&p->aCsr[i], 0, sizeof(Cursor));
if( db->xBusyCallback==0 ){
p->pc = pc;
p->rc = SQLITE_BUSY;
+ p->pTos = &pTos[1 + (pOp->p2<=0)]; /* Operands must remain on stack */
return SQLITE_BUSY;
}else if( (*db->xBusyCallback)(db->pBusyArg, pOp->p3, ++busy)==0 ){
sqliteSetString(&p->zErrMsg, sqlite_error_string(rc), (char*)0);
}
}
}while( busy );
- if( p2<=0 ){
- POPSTACK;
- }
- POPSTACK;
break;
}
case OP_OpenTemp: {
int i = pOp->p1;
Cursor *pCx;
- VERIFY( if( i<0 ) goto bad_instruction; )
+ assert( i>=0 );
if( expandCursorArraySize(p, i) ) goto no_mem;
pCx = &p->aCsr[i];
sqliteVdbeCleanupCursor(pCx);
case OP_OpenPseudo: {
int i = pOp->p1;
Cursor *pCx;
- VERIFY( if( i<0 ) goto bad_instruction; )
+ assert( i>=0 );
if( expandCursorArraySize(p, i) ) goto no_mem;
pCx = &p->aCsr[i];
sqliteVdbeCleanupCursor(pCx);
case OP_MoveLt:
case OP_MoveTo: {
int i = pOp->p1;
- int tos = p->tos;
Cursor *pC;
- VERIFY( if( tos<0 ) goto not_enough_stack; )
+ assert( pTos>=p->aStack );
assert( i>=0 && i<p->nCursor );
pC = &p->aCsr[i];
if( pC->pCursor!=0 ){
int res, oc;
pC->nullRow = 0;
- if( aStack[tos].flags & MEM_Int ){
- int iKey = intToKey(aStack[tos].i);
+ if( pTos->flags & MEM_Int ){
+ int iKey = intToKey(pTos->i);
if( pOp->p2==0 && pOp->opcode==OP_MoveTo ){
pC->movetoTarget = iKey;
pC->deferredMoveto = 1;
- POPSTACK;
+ Release(pTos);
+ pTos--;
break;
}
sqliteBtreeMoveto(pC->pCursor, (char*)&iKey, sizeof(int), &res);
- pC->lastRecno = aStack[tos].i;
+ pC->lastRecno = pTos->i;
pC->recnoIsValid = res==0;
}else{
- Stringify(p, tos);
- sqliteBtreeMoveto(pC->pCursor, aStack[tos].z, aStack[tos].n, &res);
+ Stringify(pTos);
+ sqliteBtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
pC->recnoIsValid = 0;
}
pC->deferredMoveto = 0;
}
}
}
- POPSTACK;
+ Release(pTos);
+ pTos--;
break;
}
case OP_NotFound:
case OP_Found: {
int i = pOp->p1;
- int tos = p->tos;
int alreadyExists = 0;
Cursor *pC;
- VERIFY( if( tos<0 ) goto not_enough_stack; )
- if( VERIFY( i>=0 && i<p->nCursor && ) (pC = &p->aCsr[i])->pCursor!=0 ){
+ assert( pTos>=p->aStack );
+ assert( i>=0 && i<p->nCursor );
+ if( (pC = &p->aCsr[i])->pCursor!=0 ){
int res, rx;
- Stringify(p, tos);
- rx = sqliteBtreeMoveto(pC->pCursor, aStack[tos].z, aStack[tos].n, &res);
+ Stringify(pTos);
+ rx = sqliteBtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
alreadyExists = rx==SQLITE_OK && res==0;
pC->deferredMoveto = 0;
}
if( !alreadyExists ) pc = pOp->p2 - 1;
}
if( pOp->opcode!=OP_Distinct ){
- POPSTACK;
+ Release(pTos);
+ pTos--;
}
break;
}
*/
case OP_IsUnique: {
int i = pOp->p1;
- int tos = p->tos;
- int nos = tos-1;
+ Mem *pNos = &pTos[-1];
BtCursor *pCrsr;
int R;
/* Pop the value R off the top of the stack
*/
- VERIFY( if( nos<0 ) goto not_enough_stack; )
- Integerify(p, tos);
- R = aStack[tos].i;
- POPSTACK;
- if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
+ assert( pNos>=p->aStack );
+ Integerify(pTos);
+ R = pTos->i;
+ pTos--;
+ assert( i>=0 && i<=p->nCursor );
+ if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
int res, rc;
int v; /* The record number on the P1 entry that matches K */
char *zKey; /* The value of K */
/* Make sure K is a string and make zKey point to K
*/
- Stringify(p, nos);
- zKey = aStack[nos].z;
- nKey = aStack[nos].n;
+ Stringify(pNos);
+ zKey = pNos->z;
+ nKey = pNos->n;
assert( nKey >= 4 );
/* Search for an entry in P1 where all but the last four bytes match K.
** stack. (These bytes are the record number of an entry that
** violates a UNIQUE constraint.)
*/
- p->tos++;
- aStack[tos].i = v;
- aStack[tos].flags = MEM_Int;
+ pTos++;
+ pTos->i = v;
+ pTos->flags = MEM_Int;
}
break;
}
*/
case OP_NotExists: {
int i = pOp->p1;
- int tos = p->tos;
BtCursor *pCrsr;
- VERIFY( if( tos<0 ) goto not_enough_stack; )
- if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
+ assert( pTos>=p->aStack );
+ assert( i>=0 && i<p->nCursor );
+ if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
int res, rx, iKey;
- assert( aStack[tos].flags & MEM_Int );
- iKey = intToKey(aStack[tos].i);
+ assert( pTos->flags & MEM_Int );
+ iKey = intToKey(pTos->i);
rx = sqliteBtreeMoveto(pCrsr, (char*)&iKey, sizeof(int), &res);
- p->aCsr[i].lastRecno = aStack[tos].i;
+ p->aCsr[i].lastRecno = pTos->i;
p->aCsr[i].recnoIsValid = res==0;
p->aCsr[i].nullRow = 0;
if( rx!=SQLITE_OK || res!=0 ){
p->aCsr[i].recnoIsValid = 0;
}
}
- POPSTACK;
+ Release(pTos);
+ pTos--;
break;
}
int i = pOp->p1;
int v = 0;
Cursor *pC;
- if( VERIFY( i<0 || i>=p->nCursor || ) (pC = &p->aCsr[i])->pCursor==0 ){
+ assert( i>=0 && i<p->nCursor );
+ if( (pC = &p->aCsr[i])->pCursor==0 ){
v = 0;
}else{
/* The next rowid or record number (different terms for the same
pC->recnoIsValid = 0;
pC->deferredMoveto = 0;
}
- p->tos++;
- aStack[p->tos].i = v;
- aStack[p->tos].flags = MEM_Int;
+ pTos++;
+ pTos->i = v;
+ pTos->flags = MEM_Int;
break;
}
*/
case OP_PutIntKey:
case OP_PutStrKey: {
- int tos = p->tos;
- int nos = p->tos-1;
+ Mem *pNos = &pTos[-1];
int i = pOp->p1;
Cursor *pC;
- VERIFY( if( nos<0 ) goto not_enough_stack; )
- if( VERIFY( i>=0 && i<p->nCursor && )
- ((pC = &p->aCsr[i])->pCursor!=0 || pC->pseudoTable) ){
+ assert( pNos>=p->aStack );
+ assert( i>=0 && i<p->nCursor );
+ if( ((pC = &p->aCsr[i])->pCursor!=0 || pC->pseudoTable) ){
char *zKey;
int nKey, iKey;
if( pOp->opcode==OP_PutStrKey ){
- Stringify(p, nos);
- nKey = aStack[nos].n;
- zKey = aStack[nos].z;
+ Stringify(pNos);
+ nKey = pNos->n;
+ zKey = pNos->z;
}else{
- assert( aStack[nos].flags & MEM_Int );
+ assert( pNos->flags & MEM_Int );
nKey = sizeof(int);
- iKey = intToKey(aStack[nos].i);
+ iKey = intToKey(pNos->i);
zKey = (char*)&iKey;
if( pOp->p2 ){
db->nChange++;
- db->lastRowid = aStack[nos].i;
+ db->lastRowid = pNos->i;
}
- if( pC->nextRowidValid && aStack[nos].i>=pC->nextRowid ){
+ if( pC->nextRowidValid && pTos->i>=pC->nextRowid ){
pC->nextRowidValid = 0;
}
}
assert( pOp->opcode==OP_PutIntKey );
sqliteFree(pC->pData);
pC->iKey = iKey;
- pC->nData = aStack[tos].n;
- if( aStack[tos].flags & MEM_Dyn ){
- pC->pData = aStack[tos].z;
- aStack[tos].z = 0;
- aStack[tos].flags = MEM_Null;
+ pC->nData = pTos->n;
+ if( pTos->flags & MEM_Dyn ){
+ pC->pData = pTos->z;
+ pTos->flags = MEM_Null;
}else{
pC->pData = sqliteMallocRaw( pC->nData );
if( pC->pData ){
- memcpy(pC->pData, aStack[tos].z, pC->nData);
+ memcpy(pC->pData, pTos->z, pC->nData);
}
}
pC->nullRow = 0;
}else{
- rc = sqliteBtreeInsert(pC->pCursor, zKey, nKey,
- aStack[tos].z, aStack[tos].n);
+ rc = sqliteBtreeInsert(pC->pCursor, zKey, nKey, pTos->z, pTos->n);
}
pC->recnoIsValid = 0;
pC->deferredMoveto = 0;
}
- POPSTACK;
- POPSTACK;
+ popStack(&pTos, 2);
break;
}
case OP_RowKey:
case OP_RowData: {
int i = pOp->p1;
- int tos = ++p->tos;
Cursor *pC;
int n;
+ pTos++;
assert( i>=0 && i<p->nCursor );
pC = &p->aCsr[i];
if( pC->nullRow ){
- aStack[tos].flags = MEM_Null;
+ pTos->flags = MEM_Null;
}else if( pC->pCursor!=0 ){
BtCursor *pCrsr = pC->pCursor;
sqliteVdbeCursorMoveto(pC);
if( pC->nullRow ){
- aStack[tos].flags = MEM_Null;
+ pTos->flags = MEM_Null;
break;
}else if( pC->keyAsData || pOp->opcode==OP_RowKey ){
sqliteBtreeKeySize(pCrsr, &n);
}else{
sqliteBtreeDataSize(pCrsr, &n);
}
- aStack[tos].n = n;
+ pTos->n = n;
if( n<=NBFS ){
- aStack[tos].flags = MEM_Str;
- aStack[tos].z = aStack[tos].zShort;
+ pTos->flags = MEM_Str | MEM_Short;
+ pTos->z = pTos->zShort;
}else{
char *z = sqliteMallocRaw( n );
if( z==0 ) goto no_mem;
- aStack[tos].flags = MEM_Str | MEM_Dyn;
- aStack[tos].z = z;
+ pTos->flags = MEM_Str | MEM_Dyn;
+ pTos->z = z;
}
if( pC->keyAsData || pOp->opcode==OP_RowKey ){
- sqliteBtreeKey(pCrsr, 0, n, aStack[tos].z);
+ sqliteBtreeKey(pCrsr, 0, n, pTos->z);
}else{
- sqliteBtreeData(pCrsr, 0, n, aStack[tos].z);
+ sqliteBtreeData(pCrsr, 0, n, pTos->z);
}
}else if( pC->pseudoTable ){
- aStack[tos].n = pC->nData;
- aStack[tos].z = pC->pData;
- aStack[tos].flags = MEM_Str|MEM_Ephem;
+ pTos->n = pC->nData;
+ pTos->z = pC->pData;
+ pTos->flags = MEM_Str|MEM_Ephem;
}else{
- aStack[tos].flags = MEM_Null;
+ pTos->flags = MEM_Null;
}
break;
}
int amt, offset, end, payloadSize;
int i = pOp->p1;
int p2 = pOp->p2;
- int tos = p->tos+1;
Cursor *pC;
char *zRec;
BtCursor *pCrsr;
unsigned char aHdr[10];
assert( i<p->nCursor );
+ pTos++;
if( i<0 ){
- VERIFY( if( tos+i<0 ) goto bad_instruction; )
- VERIFY( if( (aStack[tos+i].flags & MEM_Str)==0 ) goto bad_instruction; )
- zRec = aStack[tos+i].z;
- payloadSize = aStack[tos+i].n;
+ assert( &pTos[i]>=p->aStack );
+ assert( pTos[i].flags & MEM_Str );
+ zRec = pTos[i].z;
+ payloadSize = pTos[i].n;
}else if( (pC = &p->aCsr[i])->pCursor!=0 ){
sqliteVdbeCursorMoveto(pC);
zRec = 0;
** data begins.
*/
if( payloadSize==0 ){
- aStack[tos].flags = MEM_Null;
- p->tos = tos;
+ pTos->flags = MEM_Null;
break;
}else if( payloadSize<256 ){
idxWidth = 1;
/* amt and offset now hold the offset to the start of data and the
** amount of data. Go get the data and put it on the stack.
*/
+ pTos->n = amt;
if( amt==0 ){
- aStack[tos].flags = MEM_Null;
+ pTos->flags = MEM_Null;
}else if( zRec ){
- aStack[tos].flags = MEM_Str | MEM_Ephem;
- aStack[tos].n = amt;
- aStack[tos].z = &zRec[offset];
+ pTos->flags = MEM_Str | MEM_Ephem;
+ pTos->z = &zRec[offset];
}else{
if( amt<=NBFS ){
- aStack[tos].flags = MEM_Str;
- aStack[tos].z = aStack[tos].zShort;
- aStack[tos].n = amt;
+ pTos->flags = MEM_Str | MEM_Short;
+ pTos->z = pTos->zShort;
}else{
char *z = sqliteMallocRaw( amt );
if( z==0 ) goto no_mem;
- aStack[tos].flags = MEM_Str | MEM_Dyn;
- aStack[tos].z = z;
- aStack[tos].n = amt;
+ pTos->flags = MEM_Str | MEM_Dyn;
+ pTos->z = z;
}
if( pC->keyAsData ){
- sqliteBtreeKey(pCrsr, offset, amt, aStack[tos].z);
+ sqliteBtreeKey(pCrsr, offset, amt, pTos->z);
}else{
- sqliteBtreeData(pCrsr, offset, amt, aStack[tos].z);
+ sqliteBtreeData(pCrsr, offset, amt, pTos->z);
}
}
- p->tos = tos;
break;
}
*/
case OP_Recno: {
int i = pOp->p1;
- int tos = ++p->tos;
Cursor *pC;
int v;
assert( i>=0 && i<p->nCursor );
pC = &p->aCsr[i];
sqliteVdbeCursorMoveto(pC);
+ pTos++;
if( pC->recnoIsValid ){
v = pC->lastRecno;
}else if( pC->pseudoTable ){
v = keyToInt(pC->iKey);
}else if( pC->nullRow || pC->pCursor==0 ){
- aStack[tos].flags = MEM_Null;
+ pTos->flags = MEM_Null;
break;
}else{
assert( pC->pCursor!=0 );
sqliteBtreeKey(pC->pCursor, 0, sizeof(u32), (char*)&v);
v = keyToInt(v);
}
- aStack[tos].i = v;
- aStack[tos].flags = MEM_Int;
+ pTos->i = v;
+ pTos->flags = MEM_Int;
break;
}
*/
case OP_FullKey: {
int i = pOp->p1;
- int tos = ++p->tos;
BtCursor *pCrsr;
- VERIFY( if( !p->aCsr[i].keyAsData ) goto bad_instruction; )
- VERIFY( if( p->aCsr[i].pseudoTable ) goto bad_instruction; )
- if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
+ assert( p->aCsr[i].keyAsData );
+ assert( !p->aCsr[i].pseudoTable );
+ assert( i>=0 && i<p->nCursor );
+ pTos++;
+ if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
int amt;
char *z;
if( amt>NBFS ){
z = sqliteMallocRaw( amt );
if( z==0 ) goto no_mem;
- aStack[tos].flags = MEM_Str | MEM_Dyn;
+ pTos->flags = MEM_Str | MEM_Dyn;
}else{
- z = aStack[tos].zShort;
- aStack[tos].flags = MEM_Str;
+ z = pTos->zShort;
+ pTos->flags = MEM_Str | MEM_Short;
}
sqliteBtreeKey(pCrsr, 0, amt, z);
- aStack[tos].z = z;
- aStack[tos].n = amt;
+ pTos->z = z;
+ pTos->n = amt;
}
break;
}
*/
case OP_IdxPut: {
int i = pOp->p1;
- int tos = p->tos;
BtCursor *pCrsr;
- VERIFY( if( tos<0 ) goto not_enough_stack; )
- if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
- int nKey = aStack[tos].n;
- const char *zKey = aStack[tos].z;
+ assert( pTos>=p->aStack );
+ assert( i>=0 && i<p->nCursor );
+ assert( pTos->flags & MEM_Str );
+ if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
+ int nKey = pTos->n;
+ const char *zKey = pTos->z;
if( pOp->p2 ){
int res, n;
- assert( aStack[tos].n >= 4 );
+ assert( nKey >= 4 );
rc = sqliteBtreeMoveto(pCrsr, zKey, nKey-4, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
while( res!=0 ){
rc = sqliteBtreeInsert(pCrsr, zKey, nKey, "", 0);
assert( p->aCsr[i].deferredMoveto==0 );
}
- POPSTACK;
+ Release(pTos);
+ pTos--;
break;
}
*/
case OP_IdxDelete: {
int i = pOp->p1;
- int tos = p->tos;
BtCursor *pCrsr;
- VERIFY( if( tos<0 ) goto not_enough_stack; )
- if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
+ assert( pTos>=p->aStack );
+ assert( pTos->flags & MEM_Str );
+ assert( i>=0 && i<p->nCursor );
+ if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
int rx, res;
- rx = sqliteBtreeMoveto(pCrsr, aStack[tos].z, aStack[tos].n, &res);
+ rx = sqliteBtreeMoveto(pCrsr, pTos->z, pTos->n, &res);
if( rx==SQLITE_OK && res==0 ){
rc = sqliteBtreeDelete(pCrsr);
}
assert( p->aCsr[i].deferredMoveto==0 );
}
- POPSTACK;
+ Release(pTos);
+ pTos--;
break;
}
*/
case OP_IdxRecno: {
int i = pOp->p1;
- int tos = ++p->tos;
BtCursor *pCrsr;
- if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
+ assert( i>=0 && i<p->nCursor );
+ pTos++;
+ if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
int v;
int sz;
assert( p->aCsr[i].deferredMoveto==0 );
sqliteBtreeKeySize(pCrsr, &sz);
if( sz<sizeof(u32) ){
- aStack[tos].flags = MEM_Null;
+ pTos->flags = MEM_Null;
}else{
sqliteBtreeKey(pCrsr, sz - sizeof(u32), sizeof(u32), (char*)&v);
v = keyToInt(v);
- aStack[tos].i = v;
- aStack[tos].flags = MEM_Int;
+ pTos->i = v;
+ pTos->flags = MEM_Int;
}
+ }else{
+ pTos->flags = MEM_Null;
}
break;
}
case OP_IdxGT:
case OP_IdxGE: {
int i= pOp->p1;
- int tos = p->tos;
BtCursor *pCrsr;
- if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
+ assert( i>=0 && i<p->nCursor );
+ assert( pTos>=p->aStack );
+ if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
int res, rc;
- Stringify(p, tos);
+ Stringify(pTos);
assert( p->aCsr[i].deferredMoveto==0 );
- rc = sqliteBtreeKeyCompare(pCrsr, aStack[tos].z, aStack[tos].n, 4, &res);
+ rc = sqliteBtreeKeyCompare(pCrsr, pTos->z, pTos->n, 4, &res);
if( rc!=SQLITE_OK ){
break;
}
pc = pOp->p2 - 1 ;
}
}
- POPSTACK;
+ Release(pTos);
+ pTos--;
break;
}
*/
case OP_IdxIsNull: {
int i = pOp->p1;
- int tos = p->tos;
int k, n;
const char *z;
- assert( tos>=0 );
- assert( aStack[tos].flags & MEM_Str );
- z = aStack[tos].z;
- n = aStack[tos].n;
+ assert( pTos>=p->aStack );
+ assert( pTos->flags & MEM_Str );
+ z = pTos->z;
+ n = pTos->n;
for(k=0; k<n && i>0; i--){
if( z[k]=='a' ){
pc = pOp->p2-1;
while( k<n && z[k] ){ k++; }
k++;
}
- POPSTACK;
+ Release(pTos);
+ pTos--;
break;
}
*/
case OP_CreateIndex:
case OP_CreateTable: {
- int i = ++p->tos;
int pgno;
assert( pOp->p3!=0 && pOp->p3type==P3_POINTER );
assert( pOp->p2>=0 && pOp->p2<db->nDb );
}else{
rc = sqliteBtreeCreateIndex(db->aDb[pOp->p2].pBt, &pgno);
}
+ pTos++;
if( rc==SQLITE_OK ){
- aStack[i].i = pgno;
- aStack[i].flags = MEM_Int;
+ pTos->i = pgno;
+ pTos->flags = MEM_Int;
*(u32*)pOp->p3 = pgno;
pOp->p3 = 0;
}
case OP_IntegrityCk: {
int nRoot;
int *aRoot;
- int tos = ++p->tos;
int iSet = pOp->p1;
Set *pSet;
int j;
HashElem *i;
char *z;
- VERIFY( if( iSet<0 || iSet>=p->nSet ) goto bad_instruction; )
+ assert( iSet>=0 && iSet<p->nSet );
+ pTos++;
pSet = &p->aSet[iSet];
nRoot = sqliteHashCount(&pSet->hash);
aRoot = sqliteMallocRaw( sizeof(int)*(nRoot+1) );
z = sqliteBtreeIntegrityCheck(db->aDb[pOp->p2].pBt, aRoot, nRoot);
if( z==0 || z[0]==0 ){
if( z ) sqliteFree(z);
- aStack[tos].z = "ok";
- aStack[tos].n = 3;
- aStack[tos].flags = MEM_Str | MEM_Static;
+ pTos->z = "ok";
+ pTos->n = 3;
+ pTos->flags = MEM_Str | MEM_Static;
}else{
- aStack[tos].z = z;
- aStack[tos].n = strlen(z) + 1;
- aStack[tos].flags = MEM_Str | MEM_Dyn;
+ pTos->z = z;
+ pTos->n = strlen(z) + 1;
+ pTos->flags = MEM_Str | MEM_Dyn;
}
sqliteFree(aRoot);
break;
*/
case OP_ListWrite: {
Keylist *pKeylist;
- VERIFY( if( p->tos<0 ) goto not_enough_stack; )
+ assert( pTos>=p->aStack );
pKeylist = p->pList;
if( pKeylist==0 || pKeylist->nUsed>=pKeylist->nKey ){
pKeylist = sqliteMallocRaw( sizeof(Keylist)+999*sizeof(pKeylist->aKey[0]) );
pKeylist->pNext = p->pList;
p->pList = pKeylist;
}
- Integerify(p, p->tos);
- pKeylist->aKey[pKeylist->nUsed++] = aStack[p->tos].i;
- POPSTACK;
+ Integerify(pTos);
+ pKeylist->aKey[pKeylist->nUsed++] = pTos->i;
+ assert( pTos->flags==MEM_Int );
+ pTos--;
break;
}
CHECK_FOR_INTERRUPT;
pKeylist = p->pList;
if( pKeylist!=0 ){
- VERIFY(
- if( pKeylist->nRead<0
- || pKeylist->nRead>=pKeylist->nUsed
- || pKeylist->nRead>=pKeylist->nKey ) goto bad_instruction;
- )
- p->tos++;
- aStack[p->tos].i = pKeylist->aKey[pKeylist->nRead++];
- aStack[p->tos].flags = MEM_Int;
- aStack[p->tos].z = 0;
+ assert( pKeylist->nRead>=0 );
+ assert( pKeylist->nRead<pKeylist->nUsed );
+ assert( pKeylist->nRead<pKeylist->nKey );
+ pTos++;
+ pTos->i = pKeylist->aKey[pKeylist->nRead++];
+ pTos->flags = MEM_Int;
if( pKeylist->nRead>=pKeylist->nUsed ){
p->pList = pKeylist->pNext;
sqliteFree(pKeylist);
** made using SortMakeKey and SortMakeRec, respectively.
*/
case OP_SortPut: {
- int tos = p->tos;
- int nos = tos - 1;
+ Mem *pNos = &pTos[-1];
Sorter *pSorter;
- VERIFY( if( tos<1 ) goto not_enough_stack; )
- if( Dynamicify(p, tos) || Dynamicify(p, nos) ) goto no_mem;
+ assert( pNos>=p->aStack );
+ if( Dynamicify(pTos) || Dynamicify(pNos) ) goto no_mem;
pSorter = sqliteMallocRaw( sizeof(Sorter) );
if( pSorter==0 ) goto no_mem;
pSorter->pNext = p->pSort;
p->pSort = pSorter;
- assert( aStack[tos].flags & MEM_Dyn );
- pSorter->nKey = aStack[tos].n;
- pSorter->zKey = aStack[tos].z;
- pSorter->nData = aStack[nos].n;
- if( aStack[nos].flags & MEM_Dyn ){
- pSorter->pData = aStack[nos].z;
- }else{
- pSorter->pData = sqliteStrDup(aStack[nos].z);
- }
- aStack[tos].flags = 0;
- aStack[nos].flags = 0;
- aStack[tos].z = 0;
- aStack[nos].z = 0;
- p->tos -= 2;
+ assert( pTos->flags & MEM_Dyn );
+ pSorter->nKey = pTos->n;
+ pSorter->zKey = pTos->z;
+ assert( pNos->flags & MEM_Dyn );
+ pSorter->nData = pNos->n;
+ pSorter->pData = pNos->z;
+ pTos -= 2;
break;
}
char **azArg;
int nByte;
int nField;
- int i, j;
+ int i;
+ Mem *pRec;
nField = pOp->p1;
- VERIFY( if( p->tos+1<nField ) goto not_enough_stack; )
+ pRec = &pTos[1-nField];
+ assert( pRec>=p->aStack );
nByte = 0;
- for(i=p->tos-nField+1; i<=p->tos; i++){
- if( (aStack[i].flags & MEM_Null)==0 ){
- Stringify(p, i);
- nByte += aStack[i].n;
+ for(i=0; i<nField; i++, pRec++){
+ if( (pRec->flags & MEM_Null)==0 ){
+ Stringify(pRec);
+ nByte += pRec->n;
}
}
nByte += sizeof(char*)*(nField+1);
azArg = sqliteMallocRaw( nByte );
if( azArg==0 ) goto no_mem;
z = (char*)&azArg[nField+1];
- for(j=0, i=p->tos-nField+1; i<=p->tos; i++, j++){
- if( aStack[i].flags & MEM_Null ){
- azArg[j] = 0;
+ for(pRec=&pTos[1-nField], i=0; i<nField; i++, pRec++){
+ if( pRec->flags & MEM_Null ){
+ azArg[i] = 0;
}else{
- azArg[j] = z;
- strcpy(z, aStack[i].z);
- z += aStack[i].n;
+ azArg[i] = z;
+ memcpy(z, pRec->z, pRec->n);
+ z += pRec->n;
}
}
- sqliteVdbePopStack(p, nField);
- p->tos++;
- aStack[p->tos].n = nByte;
- aStack[p->tos].z = (char*)azArg;
- aStack[p->tos].flags = MEM_Str|MEM_Dyn;
+ popStack(&pTos, nField);
+ pTos++;
+ pTos->n = nByte;
+ pTos->z = (char*)azArg;
+ pTos->flags = MEM_Str | MEM_Dyn;
break;
}
int nByte;
int nField;
int i, j, k;
+ Mem *pRec;
nField = strlen(pOp->p3);
- VERIFY( if( p->tos+1<nField ) goto not_enough_stack; )
+ pRec = &pTos[1-nField];
nByte = 1;
- for(i=p->tos-nField+1; i<=p->tos; i++){
- if( (aStack[i].flags & MEM_Null)!=0 ){
+ for(i=0; i<nField; i++, pRec++){
+ if( pRec->flags & MEM_Null ){
nByte += 2;
}else{
- Stringify(p, i);
- nByte += aStack[i].n+2;
+ Stringify(pRec);
+ nByte += pRec->n+2;
}
}
zNewKey = sqliteMallocRaw( nByte );
if( zNewKey==0 ) goto no_mem;
j = 0;
k = 0;
- for(i=p->tos-nField+1; i<=p->tos; i++){
- if( (aStack[i].flags & MEM_Null)!=0 ){
+ for(pRec=&pTos[1-nField], i=0; i<nField; i++, pRec++){
+ if( pRec->flags & MEM_Null ){
zNewKey[j++] = 'N';
zNewKey[j++] = 0;
k++;
}else{
zNewKey[j++] = pOp->p3[k++];
- memcpy(&zNewKey[j], aStack[i].z, aStack[i].n-1);
- j += aStack[i].n-1;
+ memcpy(&zNewKey[j], pRec->z, pRec->n-1);
+ j += pRec->n-1;
zNewKey[j++] = 0;
}
}
zNewKey[j] = 0;
assert( j<nByte );
- sqliteVdbePopStack(p, nField);
- p->tos++;
- aStack[p->tos].n = nByte;
- aStack[p->tos].flags = MEM_Str|MEM_Dyn;
- aStack[p->tos].z = zNewKey;
+ popStack(&pTos, nField);
+ pTos++;
+ pTos->n = nByte;
+ pTos->flags = MEM_Str|MEM_Dyn;
+ pTos->z = zNewKey;
break;
}
CHECK_FOR_INTERRUPT;
if( pSorter!=0 ){
p->pSort = pSorter->pNext;
- p->tos++;
- aStack[p->tos].z = pSorter->pData;
- aStack[p->tos].n = pSorter->nData;
- aStack[p->tos].flags = MEM_Str|MEM_Dyn;
+ pTos++;
+ pTos->z = pSorter->pData;
+ pTos->n = pSorter->nData;
+ pTos->flags = MEM_Str|MEM_Dyn;
sqliteFree(pSorter->zKey);
sqliteFree(pSorter);
}else{
** callback on it.
*/
case OP_SortCallback: {
- int i = p->tos;
- VERIFY( if( i<0 ) goto not_enough_stack; )
+ assert( pTos>=p->aStack );
+ assert( pTos->flags & MEM_Str );
if( p->xCallback==0 ){
p->pc = pc+1;
- p->azResColumn = (char**)aStack[i].z;
+ p->azResColumn = (char**)pTos->z;
p->nResColumn = pOp->p1;
p->popStack = 1;
+ p->pTos = pTos;
return SQLITE_ROW;
}else{
if( sqliteSafetyOff(db) ) goto abort_due_to_misuse;
- if( p->xCallback(p->pCbArg, pOp->p1, (char**)aStack[i].z, p->azColName)!=0){
+ if( p->xCallback(p->pCbArg, pOp->p1, (char**)pTos->z, p->azColName)!=0){
rc = SQLITE_ABORT;
}
if( sqliteSafetyOn(db) ) goto abort_due_to_misuse;
p->nCallback++;
}
- POPSTACK;
+ Release(pTos);
+ pTos--;
if( sqlite_malloc_failed ) goto no_mem;
break;
}
** If P3 is "stdin" then open standard input for reading.
*/
case OP_FileOpen: {
- VERIFY( if( pOp->p3==0 ) goto bad_instruction; )
+ assert( pOp->p3!=0 );
if( p->pFile ){
if( p->pFile!=stdin ) fclose(p->pFile);
p->pFile = 0;
case OP_FileColumn: {
int i = pOp->p1;
char *z;
- if( VERIFY( i>=0 && i<p->nField && ) p->azField ){
+ assert( i>=0 && i<p->nField );
+ if( p->azField ){
z = p->azField[i];
}else{
z = 0;
}
- p->tos++;
+ pTos++;
if( z ){
- aStack[p->tos].n = strlen(z) + 1;
- aStack[p->tos].z = z;
- aStack[p->tos].flags = MEM_Str;
+ pTos->n = strlen(z) + 1;
+ pTos->z = z;
+ pTos->flags = MEM_Str | MEM_Ephem;
}else{
- aStack[p->tos].n = 0;
- aStack[p->tos].z = 0;
- aStack[p->tos].flags = MEM_Null;
+ pTos->flags = MEM_Null;
}
break;
}
*/
case OP_MemStore: {
int i = pOp->p1;
- int tos = p->tos;
char *zOld;
Mem *pMem;
int flags;
- VERIFY( if( tos<0 ) goto not_enough_stack; )
+ assert( pTos>=p->aStack );
if( i>=p->nMem ){
int nOld = p->nMem;
Mem *aMem;
if( aMem!=p->aMem ){
int j;
for(j=0; j<nOld; j++){
- if( aMem[j].z==p->aMem[j].zShort ){
+ if( aMem[j].flags & MEM_Short ){
aMem[j].z = aMem[j].zShort;
}
}
}else{
zOld = 0;
}
- *pMem = aStack[tos];
+ *pMem = *pTos;
flags = pMem->flags;
- if( flags & (MEM_Static|MEM_Dyn|MEM_Ephem) ){
- if( (flags & MEM_Static)!=0 || (pOp->p2 && (flags & MEM_Dyn)!=0) ){
- /* pMem->z = zStack[tos]; *** do nothing */
- }else if( flags & MEM_Str ){
+ if( flags & MEM_Dyn ){
+ if( pOp->p2 ){
+ pTos->flags = MEM_Null;
+ }else{
+ /* OR: perhaps just make the stack ephermeral */
pMem->z = sqliteMallocRaw( pMem->n );
if( pMem->z==0 ) goto no_mem;
- memcpy(pMem->z, aStack[tos].z, pMem->n);
- pMem->flags |= MEM_Dyn;
- pMem->flags &= ~(MEM_Static|MEM_Ephem);
+ memcpy(pMem->z, pTos->z, pMem->n);
}
- }else{
+ }else if( flags & MEM_Short ){
pMem->z = pMem->zShort;
}
if( zOld ) sqliteFree(zOld);
if( pOp->p2 ){
- aStack[tos].z = 0;
- aStack[tos].flags = 0;
- POPSTACK;
+ Release(pTos);
+ pTos--;
}
break;
}
** value pushed onto the stack will change too.
*/
case OP_MemLoad: {
- int tos = ++p->tos;
int i = pOp->p1;
- VERIFY( if( i<0 || i>=p->nMem ) goto bad_instruction; )
- memcpy(&aStack[tos], &p->aMem[i], sizeof(aStack[tos])-NBFS);;
- if( aStack[tos].flags & MEM_Str ){
- /* aStack[tos].z = p->aMem[i].z; */
- aStack[tos].flags |= MEM_Ephem;
- aStack[tos].flags &= ~(MEM_Dyn|MEM_Static);
+ assert( i>=0 && i<p->nMem );
+ pTos++;
+ memcpy(pTos, &p->aMem[i], sizeof(pTos[0])-NBFS);;
+ if( pTos->flags & MEM_Str ){
+ pTos->flags |= MEM_Ephem;
+ pTos->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short);
}
break;
}
case OP_MemIncr: {
int i = pOp->p1;
Mem *pMem;
- VERIFY( if( i<0 || i>=p->nMem ) goto bad_instruction; )
+ assert( i>=0 && i<p->nMem );
pMem = &p->aMem[i];
- VERIFY( if( pMem->flags != MEM_Int ) goto bad_instruction; )
+ assert( pMem->flags==MEM_Int );
pMem->i++;
if( pOp->p2>0 && pMem->i>0 ){
pc = pOp->p2 - 1;
*/
case OP_AggInit: {
int i = pOp->p2;
- VERIFY( if( i<0 || i>=p->agg.nMem ) goto bad_instruction; )
+ assert( i>=0 && i<p->agg.nMem );
p->agg.apFunc[i] = (FuncDef*)pOp->p3;
break;
}
case OP_AggFunc: {
int n = pOp->p2;
int i;
- Mem *pMem;
+ Mem *pMem, *pRec;
+ char **azArgv = p->zArgv;
sqlite_func ctx;
- VERIFY( if( n<0 ) goto bad_instruction; )
- VERIFY( if( p->tos+1<n ) goto not_enough_stack; )
- VERIFY( if( aStack[p->tos].flags!=MEM_Int ) goto bad_instruction; )
- for(i=p->tos-n; i<p->tos; i++){
- if( aStack[i].flags & MEM_Null ){
- aStack[i].z = 0;
+ assert( n>=0 );
+ assert( pTos->flags==MEM_Int );
+ pRec = &pTos[-n];
+ assert( pRec>=p->aStack );
+ for(i=0; i<n; i++, pRec++){
+ if( pRec->flags & MEM_Null ){
+ azArgv[i] = 0;
}else{
- Stringify(p, i);
+ Stringify(pRec);
+ azArgv[i] = pRec->z;
}
- p->zArgv[i] = aStack[i].z;
}
- i = aStack[p->tos].i;
- VERIFY( if( i<0 || i>=p->agg.nMem ) goto bad_instruction; )
+ i = pTos->i;
+ assert( i>=0 && i<p->agg.nMem );
ctx.pFunc = (FuncDef*)pOp->p3;
pMem = &p->agg.pCurrent->aMem[i];
ctx.s.z = pMem->zShort; /* Space used for small aggregate contexts */
ctx.cnt = ++pMem->i;
ctx.isError = 0;
ctx.isStep = 1;
- (ctx.pFunc->xStep)(&ctx, n, (const char**)&p->zArgv[p->tos-n]);
+ (ctx.pFunc->xStep)(&ctx, n, (const char**)azArgv);
pMem->z = ctx.pAgg;
pMem->flags = MEM_AggCtx;
- sqliteVdbePopStack(p, n+1);
+ popStack(&pTos, n+1);
if( ctx.isError ){
rc = SQLITE_ERROR;
}
** in between an AggNext and an AggReset.
*/
case OP_AggFocus: {
- int tos = p->tos;
AggElem *pElem;
char *zKey;
int nKey;
- VERIFY( if( tos<0 ) goto not_enough_stack; )
- Stringify(p, tos);
- zKey = aStack[tos].z;
- nKey = aStack[tos].n;
+ assert( pTos>=p->aStack );
+ Stringify(pTos);
+ zKey = pTos->z;
+ nKey = pTos->n;
pElem = sqliteHashFind(&p->agg.hash, zKey, nKey);
if( pElem ){
p->agg.pCurrent = pElem;
AggInsert(&p->agg, zKey, nKey);
if( sqlite_malloc_failed ) goto no_mem;
}
- POPSTACK;
+ Release(pTos);
+ pTos--;
break;
}
case OP_AggSet: {
AggElem *pFocus = AggInFocus(p->agg);
int i = pOp->p2;
- int tos = p->tos;
- VERIFY( if( tos<0 ) goto not_enough_stack; )
+ assert( pTos>=p->aStack );
if( pFocus==0 ) goto no_mem;
- if( VERIFY( i>=0 && ) i<p->agg.nMem ){
+ assert( i>=0 );
+ assert( i<p->agg.nMem );
+ if( i<p->agg.nMem ){
Mem *pMem = &pFocus->aMem[i];
char *zOld;
if( pMem->flags & MEM_Dyn ){
}else{
zOld = 0;
}
- Deephemeralize(p, tos);
- *pMem = aStack[tos];
+ Deephemeralize(pTos);
+ *pMem = *pTos;
if( pMem->flags & MEM_Dyn ){
- aStack[tos].z = 0;
- aStack[tos].flags = 0;
- }else if( pMem->flags & (MEM_Static|MEM_AggCtx) ){
- /* pMem->z = zStack[tos]; *** do nothing */
- }else if( pMem->flags & MEM_Str ){
+ pTos->flags = MEM_Null;
+ }else if( pMem->flags & MEM_Short ){
pMem->z = pMem->zShort;
}
if( zOld ) sqliteFree(zOld);
}
- POPSTACK;
+ Release(pTos);
+ pTos--;
break;
}
case OP_AggGet: {
AggElem *pFocus = AggInFocus(p->agg);
int i = pOp->p2;
- int tos = ++p->tos;
if( pFocus==0 ) goto no_mem;
- if( VERIFY( i>=0 && ) i<p->agg.nMem ){
+ assert( i>=0 );
+ pTos++;
+ assert( i<p->agg.nMem );
+ if( i<p->agg.nMem ){
Mem *pMem = &pFocus->aMem[i];
- aStack[tos] = *pMem;
- aStack[tos].flags &= ~MEM_Dyn;
- aStack[tos].flags |= MEM_Ephem;
+ *pTos = *pMem;
+ pTos->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short);
+ pTos->flags |= MEM_Ephem;
}
break;
}
sqliteFree( aMem[i].z );
}
aMem[i] = ctx.s;
- if( (aMem[i].flags & MEM_Str) &&
- (aMem[i].flags & (MEM_Dyn|MEM_Static|MEM_Ephem))==0 ){
+ if( aMem[i].flags & MEM_Short ){
aMem[i].z = aMem[i].zShort;
}
}
if( pOp->p3 ){
sqliteHashInsert(&p->aSet[i].hash, pOp->p3, strlen(pOp->p3)+1, p);
}else{
- int tos = p->tos;
- if( tos<0 ) goto not_enough_stack;
- Stringify(p, tos);
- sqliteHashInsert(&p->aSet[i].hash, aStack[tos].z, aStack[tos].n, p);
- POPSTACK;
+ assert( pTos>=p->aStack );
+ Stringify(pTos);
+ sqliteHashInsert(&p->aSet[i].hash, pTos->z, pTos->n, p);
+ Release(pTos);
+ pTos--;
}
if( sqlite_malloc_failed ) goto no_mem;
break;
*/
case OP_SetFound: {
int i = pOp->p1;
- int tos = p->tos;
- VERIFY( if( tos<0 ) goto not_enough_stack; )
- Stringify(p, tos);
- if( i>=0 && i<p->nSet &&
- sqliteHashFind(&p->aSet[i].hash, aStack[tos].z, aStack[tos].n)){
+ assert( pTos>=p->aStack );
+ Stringify(pTos);
+ if( i>=0 && i<p->nSet && sqliteHashFind(&p->aSet[i].hash, pTos->z, pTos->n)){
pc = pOp->p2 - 1;
}
- POPSTACK;
+ Release(pTos);
+ pTos--;
break;
}
*/
case OP_SetNotFound: {
int i = pOp->p1;
- int tos = p->tos;
- VERIFY( if( tos<0 ) goto not_enough_stack; )
- Stringify(p, tos);
+ assert( pTos>=p->aStack );
+ Stringify(pTos);
if( i<0 || i>=p->nSet ||
- sqliteHashFind(&p->aSet[i].hash, aStack[tos].z, aStack[tos].n)==0 ){
+ sqliteHashFind(&p->aSet[i].hash, pTos->z, pTos->n)==0 ){
pc = pOp->p2 - 1;
}
- POPSTACK;
+ Release(pTos);
+ pTos--;
break;
}
case OP_SetFirst:
case OP_SetNext: {
Set *pSet;
- int tos;
CHECK_FOR_INTERRUPT;
if( pOp->p1<0 || pOp->p1>=p->nSet ){
if( pOp->opcode==OP_SetFirst ) pc = pOp->p2 - 1;
break;
}
}else{
- VERIFY( if( pSet->prev==0 ) goto bad_instruction; )
+ assert( pSet->prev );
pSet->prev = sqliteHashNext(pSet->prev);
if( pSet->prev==0 ){
break;
pc = pOp->p2 - 1;
}
}
- tos = ++p->tos;
- aStack[tos].z = sqliteHashKey(pSet->prev);
- aStack[tos].n = sqliteHashKeysize(pSet->prev);
- aStack[tos].flags = MEM_Str | MEM_Ephem;
+ pTos++;
+ pTos->z = sqliteHashKey(pSet->prev);
+ pTos->n = sqliteHashKeysize(pSet->prev);
+ pTos->flags = MEM_Str | MEM_Ephem;
break;
}
sqliteSetString(&p->zErrMsg, "jump destination out of range", (char*)0);
rc = SQLITE_INTERNAL;
}
- if( p->trace && p->tos>=0 ){
+ if( p->trace && pTos>=p->aStack ){
int i;
fprintf(p->trace, "Stack:");
- for(i=p->tos; i>=0 && i>p->tos-5; i--){
- if( aStack[i].flags & MEM_Null ){
+ for(i=0; i>-5 && &pTos[i]>=p->aStack; i--){
+ if( pTos[i].flags & MEM_Null ){
fprintf(p->trace, " NULL");
- }else if( (aStack[i].flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){
- fprintf(p->trace, " si:%d", aStack[i].i);
- }else if( aStack[i].flags & MEM_Int ){
- fprintf(p->trace, " i:%d", aStack[i].i);
- }else if( aStack[i].flags & MEM_Real ){
- fprintf(p->trace, " r:%g", aStack[i].r);
- }else if( aStack[i].flags & MEM_Str ){
+ }else if( (pTos[i].flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){
+ fprintf(p->trace, " si:%d", pTos[i].i);
+ }else if( pTos[i].flags & MEM_Int ){
+ fprintf(p->trace, " i:%d", pTos[i].i);
+ }else if( pTos[i].flags & MEM_Real ){
+ fprintf(p->trace, " r:%g", pTos[i].r);
+ }else if( pTos[i].flags & MEM_Str ){
int j, k;
char zBuf[100];
zBuf[0] = ' ';
- if( aStack[i].flags & MEM_Dyn ){
+ if( pTos[i].flags & MEM_Dyn ){
zBuf[1] = 'z';
- assert( (aStack[i].flags & (MEM_Static|MEM_Ephem))==0 );
- }else if( aStack[i].flags & MEM_Static ){
+ assert( (pTos[i].flags & (MEM_Static|MEM_Ephem))==0 );
+ }else if( pTos[i].flags & MEM_Static ){
zBuf[1] = 't';
- assert( (aStack[i].flags & (MEM_Dyn|MEM_Ephem))==0 );
- }else if( aStack[i].flags & MEM_Ephem ){
+ assert( (pTos[i].flags & (MEM_Dyn|MEM_Ephem))==0 );
+ }else if( pTos[i].flags & MEM_Ephem ){
zBuf[1] = 'e';
- assert( (aStack[i].flags & (MEM_Static|MEM_Dyn))==0 );
+ assert( (pTos[i].flags & (MEM_Static|MEM_Dyn))==0 );
}else{
zBuf[1] = 's';
}
zBuf[2] = '[';
k = 3;
- for(j=0; j<20 && j<aStack[i].n; j++){
- int c = aStack[i].z[j];
- if( c==0 && j==aStack[i].n-1 ) break;
+ for(j=0; j<20 && j<pTos[i].n; j++){
+ int c = pTos[i].z[j];
+ if( c==0 && j==pTos[i].n-1 ) break;
if( isprint(c) && !isspace(c) ){
zBuf[k++] = c;
}else{
rc = SQLITE_DONE;
}
p->magic = VDBE_MAGIC_HALT;
+ p->pTos = pTos;
return rc;
/* Jump to here if a malloc() fails. It's hard to get a malloc()
}
sqliteSetString(&p->zErrMsg, sqlite_error_string(rc), (char*)0);
goto vdbe_halt;
-
- /* Jump to here if a operator is encountered that requires more stack
- ** operands than are currently available on the stack.
- */
-not_enough_stack:
- sqlite_snprintf(sizeof(zBuf),zBuf,"%d",pc);
- sqliteSetString(&p->zErrMsg, "too few operands on stack at ", zBuf, (char*)0);
- rc = SQLITE_INTERNAL;
- goto vdbe_halt;
-
- /* Jump here if an illegal or illformed instruction is executed.
- */
-VERIFY(
-bad_instruction:
- sqlite_snprintf(sizeof(zBuf),zBuf,"%d",pc);
- sqliteSetString(&p->zErrMsg, "illegal operation at ", zBuf, (char*)0);
- rc = SQLITE_INTERNAL;
- goto vdbe_halt;
-)
}