Modify the build process so that the VDBE opcode numbers and the table
that contains the opcode names are both automatically generated. This makes
it much easier to create new VDBE opcodes. (CVS 746)
FossilOrigin-Name: eb54d455b0325d3be96daf6c220c4ee3e0da1a85
diff --git a/src/expr.c b/src/expr.c
index 9a358c9..0aaaf0e 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -12,7 +12,7 @@
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
-** $Id: expr.c,v 1.80 2002/08/24 18:24:54 drh Exp $
+** $Id: expr.c,v 1.81 2002/09/08 00:04:52 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -1369,7 +1369,13 @@
case TK_NE:
case TK_EQ: {
if( pParse->db->file_format>=4 && sqliteExprType(pExpr)==SQLITE_SO_TEXT ){
- op += 6; /* Convert numeric opcodes to text opcodes */
+ /* Convert numeric comparison opcodes into text comparison opcodes.
+ ** This step depends on the fact that the text comparision opcodes are
+ ** always 6 greater than their corresponding numeric comparison
+ ** opcodes.
+ */
+ assert( OP_Eq+6 == OP_StrEq );
+ op += 6;
}
sqliteExprCode(pParse, pExpr->pLeft);
sqliteExprCode(pParse, pExpr->pRight);
diff --git a/src/vdbe.c b/src/vdbe.c
index 1f0ac36..c227ef9 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -30,12 +30,20 @@
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
-** $Id: vdbe.c,v 1.175 2002/09/03 19:43:24 drh Exp $
+** $Id: vdbe.c,v 1.176 2002/09/08 00:04:52 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
/*
+** The makefile scans this source file and creates the following
+** array of string constants which are the names of all VDBE opcodes.
+** This array is defined in a separate source code file named opcode.c
+** which is automatically generated by the makefile.
+*/
+extern char *sqliteOpcodeNames[];
+
+/*
** The following global variable is incremented every time a cursor
** moves, either by the OP_MoveTo or the OP_Next opcode. The test
** procedures use this information to make sure that indices are
@@ -1067,65 +1075,6 @@
}
/*
-** A translation from opcode numbers to opcode names. Used for testing
-** and debugging only.
-**
-** If any of the numeric OP_ values for opcodes defined in sqliteVdbe.h
-** change, be sure to change this array to match. You can use the
-** "opNames.awk" awk script which is part of the source tree to regenerate
-** this array, then copy and paste it into this file, if you want.
-*/
-static char *zOpName[] = { 0,
- "Transaction", "Checkpoint", "Commit", "Rollback",
- "ReadCookie", "SetCookie", "VerifyCookie", "Open",
- "OpenTemp", "OpenWrite", "OpenAux", "OpenWrAux",
- "RenameCursor", "Close", "MoveTo", "NewRecno",
- "PutIntKey", "PutStrKey", "Distinct", "Found",
- "NotFound", "IsUnique", "NotExists", "Delete",
- "Column", "KeyAsData", "Recno", "FullKey",
- "NullRow", "Last", "Rewind", "Next",
- "Destroy", "Clear", "CreateIndex", "CreateTable",
- "IntegrityCk", "IdxPut", "IdxDelete", "IdxRecno",
- "IdxGT", "IdxGE", "MemLoad", "MemStore",
- "MemIncr", "ListWrite", "ListRewind", "ListRead",
- "ListReset", "ListPush", "ListPop", "SortPut",
- "SortMakeRec", "SortMakeKey", "Sort", "SortNext",
- "SortCallback", "SortReset", "FileOpen", "FileRead",
- "FileColumn", "AggReset", "AggFocus", "AggNext",
- "AggSet", "AggGet", "AggFunc", "AggInit",
- "AggPush", "AggPop", "SetInsert", "SetFound",
- "SetNotFound", "SetFirst", "SetNext", "MakeRecord",
- "MakeKey", "MakeIdxKey", "IncrKey", "Goto",
- "If", "IfNot", "Halt", "Gosub",
- "Return", "ColumnCount", "ColumnName", "Callback",
- "NullCallback", "Integer", "String", "Pop",
- "Dup", "Pull", "Push", "MustBeInt",
- "Add", "AddImm", "Subtract", "Multiply",
- "Divide", "Remainder", "BitAnd", "BitOr",
- "BitNot", "ShiftLeft", "ShiftRight", "AbsValue",
- "Eq", "Ne", "Lt", "Le",
- "Gt", "Ge", "StrEq", "StrNe",
- "StrLt", "StrLe", "StrGt", "StrGe",
- "IsNull", "NotNull", "Negative", "And",
- "Or", "Not", "Concat", "Noop",
- "Function",
-};
-
-/*
-** Given the name of an opcode, return its number. Return 0 if
-** there is no match.
-**
-** This routine is used for testing and debugging.
-*/
-int sqliteVdbeOpcode(const char *zName){
- int i;
- for(i=1; i<=OP_MAX; i++){
- if( sqliteStrICmp(zName, zOpName[i])==0 ) return i;
- }
- return 0;
-}
-
-/*
** Give a listing of the program in the virtual machine.
**
** The interface is the same as sqliteVdbeExec(). But instead of
@@ -1175,7 +1124,7 @@
}else{
azValue[4] = p->aOp[i].p3;
}
- azValue[1] = zOpName[p->aOp[i].opcode];
+ azValue[1] = sqliteOpcodeNames[p->aOp[i].opcode];
if( sqliteSafetyOff(db) ){
rc = SQLITE_MISUSE;
break;
@@ -1310,7 +1259,7 @@
}
if( pOut==0 ) pOut = stdout;
fprintf(pOut,"%4d %-12s %4d %4d %s\n",
- pc, zOpName[pOp->opcode], pOp->p1, pOp->p2, zP3 ? zP3 : "");
+ pc, sqliteOpcodeNames[pOp->opcode], pOp->p1, pOp->p2, zP3 ? zP3 : "");
fflush(pOut);
}
#endif
@@ -2283,7 +2232,18 @@
}
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
@@ -2403,13 +2363,18 @@
if( Stringify(p, tos) || Stringify(p, nos) ) goto no_mem;
c = strcmp(zStack[nos], zStack[tos]);
}
+ /* 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; break;
- case OP_StrNe: c = c!=0; break;
- case OP_StrLt: c = c<0; break;
- case OP_StrLe: c = c<=0; break;
- case OP_StrGt: c = c>0; break;
- default: c = c>=0; break;
+ 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;
POPSTACK;
@@ -3789,6 +3754,9 @@
break;
}
+/* Opcode: Extract * * *
+*/
+
/* Opcode: Recno P1 * *
**
** Push onto the stack an integer which is the first 4 bytes of the
diff --git a/src/vdbe.h b/src/vdbe.h
index 39a2aa5..53d6a1c 100644
--- a/src/vdbe.h
+++ b/src/vdbe.h
@@ -15,7 +15,7 @@
** or VDBE. The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database.
**
-** $Id: vdbe.h,v 1.59 2002/08/28 03:01:01 drh Exp $
+** $Id: vdbe.h,v 1.60 2002/09/08 00:04:53 drh Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
@@ -59,165 +59,10 @@
#define ADDR(X) (-1-(X))
/*
-** These are the available opcodes.
-**
-** If any of the values changes or if opcodes are added or removed,
-** be sure to also update the zOpName[] array in sqliteVdbe.c to
-** mirror the change.
-**
-** The source tree contains an AWK script named renumberOps.awk that
-** can be used to renumber these opcodes when new opcodes are inserted.
+** The makefile scans the vdbe.c source file and creates the "opcodes.h"
+** header file that defines a number for each opcode used by the VDBE.
*/
-#define OP_Transaction 1
-#define OP_Checkpoint 2
-#define OP_Commit 3
-#define OP_Rollback 4
-
-#define OP_ReadCookie 5
-#define OP_SetCookie 6
-#define OP_VerifyCookie 7
-
-#define OP_Open 8
-#define OP_OpenTemp 9
-#define OP_OpenWrite 10
-#define OP_OpenAux 11
-#define OP_OpenWrAux 12
-#define OP_RenameCursor 13
-#define OP_Close 14
-#define OP_MoveTo 15
-#define OP_NewRecno 16
-#define OP_PutIntKey 17
-#define OP_PutStrKey 18
-#define OP_Distinct 19
-#define OP_Found 20
-#define OP_NotFound 21
-#define OP_IsUnique 22
-#define OP_NotExists 23
-#define OP_Delete 24
-#define OP_Column 25
-#define OP_KeyAsData 26
-#define OP_Recno 27
-#define OP_FullKey 28
-#define OP_NullRow 29
-#define OP_Last 30
-#define OP_Rewind 31
-#define OP_Next 32
-
-#define OP_Destroy 33
-#define OP_Clear 34
-#define OP_CreateIndex 35
-#define OP_CreateTable 36
-#define OP_IntegrityCk 37
-
-#define OP_IdxPut 38
-#define OP_IdxDelete 39
-#define OP_IdxRecno 40
-#define OP_IdxGT 41
-#define OP_IdxGE 42
-
-#define OP_MemLoad 43
-#define OP_MemStore 44
-#define OP_MemIncr 45
-
-#define OP_ListWrite 46
-#define OP_ListRewind 47
-#define OP_ListRead 48
-#define OP_ListReset 49
-#define OP_ListPush 50
-#define OP_ListPop 51
-
-#define OP_SortPut 52
-#define OP_SortMakeRec 53
-#define OP_SortMakeKey 54
-#define OP_Sort 55
-#define OP_SortNext 56
-#define OP_SortCallback 57
-#define OP_SortReset 58
-
-#define OP_FileOpen 59
-#define OP_FileRead 60
-#define OP_FileColumn 61
-
-#define OP_AggReset 62
-#define OP_AggFocus 63
-#define OP_AggNext 64
-#define OP_AggSet 65
-#define OP_AggGet 66
-#define OP_AggFunc 67
-#define OP_AggInit 68
-#define OP_AggPush 69
-#define OP_AggPop 70
-
-#define OP_SetInsert 71
-#define OP_SetFound 72
-#define OP_SetNotFound 73
-#define OP_SetFirst 74
-#define OP_SetNext 75
-
-#define OP_MakeRecord 76
-#define OP_MakeKey 77
-#define OP_MakeIdxKey 78
-#define OP_IncrKey 79
-
-#define OP_Goto 80
-#define OP_If 81
-#define OP_IfNot 82
-#define OP_Halt 83
-#define OP_Gosub 84
-#define OP_Return 85
-
-#define OP_ColumnCount 86
-#define OP_ColumnName 87
-#define OP_Callback 88
-#define OP_NullCallback 89
-
-#define OP_Integer 90
-#define OP_String 91
-#define OP_Pop 92
-#define OP_Dup 93
-#define OP_Pull 94
-#define OP_Push 95
-#define OP_MustBeInt 96
-
-#define OP_Add 97
-#define OP_AddImm 98
-#define OP_Subtract 99
-#define OP_Multiply 100
-#define OP_Divide 101
-#define OP_Remainder 102
-#define OP_BitAnd 103
-#define OP_BitOr 104
-#define OP_BitNot 105
-#define OP_ShiftLeft 106
-#define OP_ShiftRight 107
-#define OP_AbsValue 108
-
-/***** IMPORTANT NOTE: The code generator assumes that OP_XX+6==OP_StrXX *****/
-#define OP_Eq 109
-#define OP_Ne 110
-#define OP_Lt 111
-#define OP_Le 112
-#define OP_Gt 113
-#define OP_Ge 114
-#define OP_StrEq 115
-#define OP_StrNe 116
-#define OP_StrLt 117
-#define OP_StrLe 118
-#define OP_StrGt 119
-#define OP_StrGe 120
-/***** IMPORTANT NOTE: the code generator assumes that OP_XX+6==OP_StrXX *****/
-
-#define OP_IsNull 121
-#define OP_NotNull 122
-#define OP_Negative 123
-#define OP_And 124
-#define OP_Or 125
-#define OP_Not 126
-#define OP_Concat 127
-#define OP_Noop 128
-#define OP_Function 129
-
-#define OP_MAX 129
+#include "opcodes.h"
/*
** Prototypes for the VDBE interface. See comments on the implementation
@@ -234,7 +79,6 @@
int sqliteVdbeFindOp(Vdbe*, int, int);
int sqliteVdbeMakeLabel(Vdbe*);
void sqliteVdbeDelete(Vdbe*);
-int sqliteVdbeOpcode(const char *zName);
int sqliteVdbeExec(Vdbe*,sqlite_callback,void*,char**,void*,
int(*)(void*,const char*,int));
int sqliteVdbeList(Vdbe*,sqlite_callback,void*,char**);