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**);