⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vdbeaux.c

📁 一个小型的嵌入式数据库
💻 C
📖 第 1 页 / 共 4 页
字号:
/*** 2003 September 6**** The author disclaims copyright to this source code.  In place of** a legal notice, here is a blessing:****    May you do good and not evil.**    May you find forgiveness for yourself and forgive others.**    May you share freely, never taking more than you give.***************************************************************************** This file contains code used for creating, destroying, and populating** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.)  Prior** to version 2.8.7, all this code was combined into the vdbe.c source file.** But that file was getting too big so this subroutines were split out.*/#include "sqliteInt.h"#include "os.h"#include <ctype.h>#include "vdbeInt.h"/*** When debugging the code generator in a symbolic debugger, one can** set the sqlite3_vdbe_addop_trace to 1 and all opcodes will be printed** as they are added to the instruction stream.*/#ifndef NDEBUGint sqlite3_vdbe_addop_trace = 0;#endif/*** Create a new virtual database engine.*/Vdbe *sqlite3VdbeCreate(sqlite3 *db){  Vdbe *p;  p = sqliteMalloc( sizeof(Vdbe) );  if( p==0 ) return 0;  p->db = db;  if( db->pVdbe ){    db->pVdbe->pPrev = p;  }  p->pNext = db->pVdbe;  p->pPrev = 0;  db->pVdbe = p;  p->magic = VDBE_MAGIC_INIT;  return p;}/*** Turn tracing on or off*/void sqlite3VdbeTrace(Vdbe *p, FILE *trace){  p->trace = trace;}/*** Resize the Vdbe.aOp array so that it contains at least N** elements.*/static void resizeOpArray(Vdbe *p, int N){  if( p->nOpAlloc<N ){    int oldSize = p->nOpAlloc;    p->nOpAlloc = N+100;    p->aOp = sqliteRealloc(p->aOp, p->nOpAlloc*sizeof(Op));    if( p->aOp ){      memset(&p->aOp[oldSize], 0, (p->nOpAlloc-oldSize)*sizeof(Op));    }  }}/*** Add a new instruction to the list of instructions current in the** VDBE.  Return the address of the new instruction.**** Parameters:****    p               Pointer to the VDBE****    op              The opcode for this instruction****    p1, p2          First two of the three possible operands.**** Use the sqlite3VdbeResolveLabel() function to fix an address and** the sqlite3VdbeChangeP3() function to change the value of the P3** operand.*/int sqlite3VdbeAddOp(Vdbe *p, int op, int p1, int p2){  int i;  VdbeOp *pOp;  i = p->nOp;  p->nOp++;  assert( p->magic==VDBE_MAGIC_INIT );  resizeOpArray(p, i+1);  if( p->aOp==0 ){    return 0;  }  pOp = &p->aOp[i];  pOp->opcode = op;  pOp->p1 = p1;  pOp->p2 = p2;  pOp->p3 = 0;  pOp->p3type = P3_NOTUSED;#ifdef SQLITE_DEBUG  if( sqlite3_vdbe_addop_trace ) sqlite3VdbePrintOp(0, i, &p->aOp[i]);#endif  return i;}/*** Add an opcode that includes the p3 value.*/int sqlite3VdbeOp3(Vdbe *p, int op, int p1, int p2, const char *zP3,int p3type){  int addr = sqlite3VdbeAddOp(p, op, p1, p2);  sqlite3VdbeChangeP3(p, addr, zP3, p3type);  return addr;}/*** Create a new symbolic label for an instruction that has yet to be** coded.  The symbolic label is really just a negative number.  The** label can be used as the P2 value of an operation.  Later, when** the label is resolved to a specific address, the VDBE will scan** through its operation list and change all values of P2 which match** the label into the resolved address.**** The VDBE knows that a P2 value is a label because labels are** always negative and P2 values are suppose to be non-negative.** Hence, a negative P2 value is a label that has yet to be resolved.**** Zero is returned if a malloc() fails.*/int sqlite3VdbeMakeLabel(Vdbe *p){  int i;  i = p->nLabel++;  assert( p->magic==VDBE_MAGIC_INIT );  if( i>=p->nLabelAlloc ){    p->nLabelAlloc = p->nLabelAlloc*2 + 10;    p->aLabel = sqliteRealloc( p->aLabel, p->nLabelAlloc*sizeof(p->aLabel[0]));  }  if( p->aLabel ){    p->aLabel[i] = -1;  }  return -1-i;}/*** Resolve label "x" to be the address of the next instruction to** be inserted.  The parameter "x" must have been obtained from** a prior call to sqlite3VdbeMakeLabel().*/void sqlite3VdbeResolveLabel(Vdbe *p, int x){  int j = -1-x;  assert( p->magic==VDBE_MAGIC_INIT );  assert( j>=0 && j<p->nLabel );  if( p->aLabel ){    p->aLabel[j] = p->nOp;  }}/*** Loop through the program looking for P2 values that are negative.** Each such value is a label.  Resolve the label by setting the P2** value to its correct non-zero value.**** This routine is called once after all opcodes have been inserted.*/static void resolveP2Values(Vdbe *p){  int i;  Op *pOp;  int *aLabel = p->aLabel;  if( aLabel==0 ) return;  for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){    if( pOp->p2>=0 ) continue;    assert( -1-pOp->p2<p->nLabel );    pOp->p2 = aLabel[-1-pOp->p2];  }  sqliteFree(p->aLabel);  p->aLabel = 0;}/*** Return the address of the next instruction to be inserted.*/int sqlite3VdbeCurrentAddr(Vdbe *p){  assert( p->magic==VDBE_MAGIC_INIT );  return p->nOp;}/*** Add a whole list of operations to the operation stack.  Return the** address of the first operation added.*/int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){  int addr;  assert( p->magic==VDBE_MAGIC_INIT );  resizeOpArray(p, p->nOp + nOp);  if( p->aOp==0 ){    return 0;  }  addr = p->nOp;  if( nOp>0 ){    int i;    VdbeOpList const *pIn = aOp;    for(i=0; i<nOp; i++, pIn++){      int p2 = pIn->p2;      VdbeOp *pOut = &p->aOp[i+addr];      pOut->opcode = pIn->opcode;      pOut->p1 = pIn->p1;      pOut->p2 = p2<0 ? addr + ADDR(p2) : p2;      pOut->p3 = pIn->p3;      pOut->p3type = pIn->p3 ? P3_STATIC : P3_NOTUSED;#ifdef SQLITE_DEBUG      if( sqlite3_vdbe_addop_trace ){        sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]);      }#endif    }    p->nOp += nOp;  }  return addr;}/*** Change the value of the P1 operand for a specific instruction.** This routine is useful when a large program is loaded from a** static array using sqlite3VdbeAddOpList but we want to make a** few minor changes to the program.*/void sqlite3VdbeChangeP1(Vdbe *p, int addr, int val){  assert( p->magic==VDBE_MAGIC_INIT );  if( p && addr>=0 && p->nOp>addr && p->aOp ){    p->aOp[addr].p1 = val;  }}/*** Change the value of the P2 operand for a specific instruction.** This routine is useful for setting a jump destination.*/void sqlite3VdbeChangeP2(Vdbe *p, int addr, int val){  assert( val>=0 );  assert( p->magic==VDBE_MAGIC_INIT );  if( p && addr>=0 && p->nOp>addr && p->aOp ){    p->aOp[addr].p2 = val;  }}/*** Change the value of the P3 operand for a specific instruction.** This routine is useful when a large program is loaded from a** static array using sqlite3VdbeAddOpList but we want to make a** few minor changes to the program.**** If n>=0 then the P3 operand is dynamic, meaning that a copy of** the string is made into memory obtained from sqliteMalloc().** A value of n==0 means copy bytes of zP3 up to and including the** first null byte.  If n>0 then copy n+1 bytes of zP3.**** If n==P3_STATIC  it means that zP3 is a pointer to a constant static** string and we can just copy the pointer.  n==P3_POINTER means zP3 is** a pointer to some object other than a string.  n==P3_COLLSEQ and** n==P3_KEYINFO mean that zP3 is a pointer to a CollSeq or KeyInfo** structure.  A copy is made of KeyInfo structures into memory obtained** from sqliteMalloc.**** If addr<0 then change P3 on the most recently inserted instruction.*/void sqlite3VdbeChangeP3(Vdbe *p, int addr, const char *zP3, int n){  Op *pOp;  assert( p->magic==VDBE_MAGIC_INIT );  if( p==0 || p->aOp==0 ) return;  if( addr<0 || addr>=p->nOp ){    addr = p->nOp - 1;    if( addr<0 ) return;  }  pOp = &p->aOp[addr];  if( pOp->p3 && pOp->p3type==P3_DYNAMIC ){    sqliteFree(pOp->p3);    pOp->p3 = 0;  }  if( zP3==0 ){    pOp->p3 = 0;    pOp->p3type = P3_NOTUSED;  }else if( n==P3_KEYINFO ){    KeyInfo *pKeyInfo;    int nField, nByte;    nField = ((KeyInfo*)zP3)->nField;    nByte = sizeof(*pKeyInfo) + (nField-1)*sizeof(pKeyInfo->aColl[0]);    pKeyInfo = sqliteMallocRaw( nByte );    pOp->p3 = (char*)pKeyInfo;    if( pKeyInfo ){      memcpy(pKeyInfo, zP3, nByte);      pOp->p3type = P3_KEYINFO;    }else{      pOp->p3type = P3_NOTUSED;    }  }else if( n==P3_KEYINFO_HANDOFF ){    pOp->p3 = (char*)zP3;    pOp->p3type = P3_KEYINFO;  }else if( n<0 ){    pOp->p3 = (char*)zP3;    pOp->p3type = n;  }else{    if( n==0 ) n = strlen(zP3);    pOp->p3 = sqliteStrNDup(zP3, n);    pOp->p3type = P3_DYNAMIC;  }}#ifndef NDEBUG/*** Replace the P3 field of the most recently coded instruction with** comment text.*/void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){  va_list ap;  assert( p->nOp>0 );  assert( p->aOp==0 || p->aOp[p->nOp-1].p3==0 );  va_start(ap, zFormat);  sqlite3VdbeChangeP3(p, -1, sqlite3VMPrintf(zFormat, ap), P3_DYNAMIC);  va_end(ap);}#endif/*** If the P3 operand to the specified instruction appears** to be a quoted string token, then this procedure removes ** the quotes.**** The quoting operator can be either a grave ascent (ASCII 0x27)** or a double quote character (ASCII 0x22).  Two quotes in a row** resolve to be a single actual quote character within the string.*/void sqlite3VdbeDequoteP3(Vdbe *p, int addr){  Op *pOp;  assert( p->magic==VDBE_MAGIC_INIT );  if( p->aOp==0 ) return;  if( addr<0 || addr>=p->nOp ){    addr = p->nOp - 1;    if( addr<0 ) return;  }  pOp = &p->aOp[addr];  if( pOp->p3==0 || pOp->p3[0]==0 ) return;  if( pOp->p3type==P3_STATIC ){    pOp->p3 = sqliteStrDup(pOp->p3);    pOp->p3type = P3_DYNAMIC;  }  assert( pOp->p3type==P3_DYNAMIC );  sqlite3Dequote(pOp->p3);}/*** Search the current program starting at instruction addr for the given** opcode and P2 value.  Return the address plus 1 if found and 0 if not** found.*/int sqlite3VdbeFindOp(Vdbe *p, int addr, int op, int p2){  int i;  assert( p->magic==VDBE_MAGIC_INIT );  for(i=addr; i<p->nOp; i++){    if( p->aOp[i].opcode==op && p->aOp[i].p2==p2 ) return i+1;  }  return 0;}/*** Return the opcode for a given address.*/VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){  assert( p->magic==VDBE_MAGIC_INIT );  assert( addr>=0 && addr<p->nOp );  return &p->aOp[addr];}#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \     || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)/*** Compute a string that describes the P3 parameter for an opcode.** Use zTemp for any required temporary buffer space.*/static char *displayP3(Op *pOp, char *zTemp, int nTemp){  char *zP3;  assert( nTemp>=20 );  switch( pOp->p3type ){    case P3_POINTER: {      sprintf(zTemp, "ptr(%#x)", (int)pOp->p3);      zP3 = zTemp;      break;    }    case P3_KEYINFO: {      int i, j;      KeyInfo *pKeyInfo = (KeyInfo*)pOp->p3;      sprintf(zTemp, "keyinfo(%d", pKeyInfo->nField);      i = strlen(zTemp);      for(j=0; j<pKeyInfo->nField; j++){        CollSeq *pColl = pKeyInfo->aColl[j];        if( pColl ){          int n = strlen(pColl->zName);          if( i+n>nTemp-6 ){            strcpy(&zTemp[i],",...");            break;          }          zTemp[i++] = ',';          if( pKeyInfo->aSortOrder && pKeyInfo->aSortOrder[j] ){            zTemp[i++] = '-';          }          strcpy(&zTemp[i], pColl->zName);          i += n;        }else if( i+4<nTemp-6 ){          strcpy(&zTemp[i],",nil");          i += 4;        }      }      zTemp[i++] = ')';      zTemp[i] = 0;      assert( i<nTemp );      zP3 = zTemp;      break;    }    case P3_COLLSEQ: {      CollSeq *pColl = (CollSeq*)pOp->p3;      sprintf(zTemp, "collseq(%.20s)", pColl->zName);      zP3 = zTemp;      break;    }    case P3_FUNCDEF: {      FuncDef *pDef = (FuncDef*)pOp->p3;      char zNum[30];      sprintf(zTemp, "%.*s", nTemp, pDef->zName);      sprintf(zNum,"(%d)", pDef->nArg);      if( strlen(zTemp)+strlen(zNum)+1<=nTemp ){        strcat(zTemp, zNum);      }      zP3 = zTemp;      break;    }    default: {      zP3 = pOp->p3;      if( zP3==0 || pOp->opcode==OP_Noop ){        zP3 = "";      }    }  }  return zP3;}#endif#if defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)/*** Print a single opcode.  This routine is used for debugging only.*/void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){  char *zP3;  char zPtr[50];  static const char *zFormat1 = "%4d %-13s %4d %4d %s\n";  if( pOut==0 ) pOut = stdout;  zP3 = displayP3(pOp, zPtr, sizeof(zPtr));  fprintf(pOut, zFormat1,      pc, sqlite3OpcodeNames[pOp->opcode], pOp->p1, pOp->p2, zP3);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -