| OLD | NEW | 
 | (Empty) | 
|    1 #!/usr/bin/awk -f |  | 
|    2 # |  | 
|    3 # Generate the file opcodes.h. |  | 
|    4 # |  | 
|    5 # This AWK script scans a concatenation of the parse.h output file from the |  | 
|    6 # parser and the vdbe.c source file in order to generate the opcodes numbers |  | 
|    7 # for all opcodes.   |  | 
|    8 # |  | 
|    9 # The lines of the vdbe.c that we are interested in are of the form: |  | 
|   10 # |  | 
|   11 #       case OP_aaaa:      /* same as TK_bbbbb */ |  | 
|   12 # |  | 
|   13 # The TK_ comment is optional.  If it is present, then the value assigned to |  | 
|   14 # the OP_ is the same as the TK_ value.  If missing, the OP_ value is assigned |  | 
|   15 # a small integer that is different from every other OP_ value. |  | 
|   16 # |  | 
|   17 # We go to the trouble of making some OP_ values the same as TK_ values |  | 
|   18 # as an optimization.  During parsing, things like expression operators |  | 
|   19 # are coded with TK_ values such as TK_ADD, TK_DIVIDE, and so forth.  Later |  | 
|   20 # during code generation, we need to generate corresponding opcodes like |  | 
|   21 # OP_Add and OP_Divide.  By making TK_ADD==OP_Add and TK_DIVIDE==OP_Divide, |  | 
|   22 # code to translate from one to the other is avoided.  This makes the |  | 
|   23 # code generator run (infinitesimally) faster and more importantly it makes |  | 
|   24 # the library footprint smaller. |  | 
|   25 # |  | 
|   26 # This script also scans for lines of the form: |  | 
|   27 # |  | 
|   28 #       case OP_aaaa:       /* no-push */ |  | 
|   29 # |  | 
|   30 # When the no-push comment is found on an opcode, it means that that |  | 
|   31 # opcode does not leave a result on the stack.  By identifying which |  | 
|   32 # opcodes leave results on the stack it is possible to determine a |  | 
|   33 # much smaller upper bound on the size of the stack.  This allows |  | 
|   34 # a smaller stack to be allocated, which is important to embedded |  | 
|   35 # systems with limited memory space.  This script generates a series |  | 
|   36 # of "NOPUSH_MASK" defines that contain bitmaps of opcodes that leave |  | 
|   37 # results on the stack.  The NOPUSH_MASK defines are used in vdbeaux.c |  | 
|   38 # to help determine the maximum stack size. |  | 
|   39 # |  | 
|   40  |  | 
|   41  |  | 
|   42 # Remember the TK_ values from the parse.h file |  | 
|   43 /^#define TK_/ { |  | 
|   44   tk[$2] = 0+$3 |  | 
|   45 } |  | 
|   46  |  | 
|   47 # Scan for "case OP_aaaa:" lines in the vdbe.c file |  | 
|   48 /^case OP_/ { |  | 
|   49   name = $2 |  | 
|   50   sub(/:/,"",name) |  | 
|   51   sub("\r","",name) |  | 
|   52   op[name] = -1 |  | 
|   53   jump[name] = 0 |  | 
|   54   out2_prerelease[name] = 0 |  | 
|   55   in1[name] = 0 |  | 
|   56   in2[name] = 0 |  | 
|   57   in3[name] = 0 |  | 
|   58   out3[name] = 0 |  | 
|   59   for(i=3; i<NF; i++){ |  | 
|   60     if($i=="same" && $(i+1)=="as"){ |  | 
|   61       sym = $(i+2) |  | 
|   62       sub(/,/,"",sym) |  | 
|   63       op[name] = tk[sym] |  | 
|   64       used[op[name]] = 1 |  | 
|   65       sameas[op[name]] = sym |  | 
|   66     } |  | 
|   67     x = $i |  | 
|   68     sub(",","",x) |  | 
|   69     if(x=="jump"){ |  | 
|   70       jump[name] = 1 |  | 
|   71     }else if(x=="out2-prerelease"){ |  | 
|   72       out2_prerelease[name] = 1 |  | 
|   73     }else if(x=="in1"){ |  | 
|   74       in1[name] = 1 |  | 
|   75     }else if(x=="in2"){ |  | 
|   76       in2[name] = 1 |  | 
|   77     }else if(x=="in3"){ |  | 
|   78       in3[name] = 1 |  | 
|   79     }else if(x=="out3"){ |  | 
|   80       out3[name] = 1 |  | 
|   81     } |  | 
|   82   } |  | 
|   83 } |  | 
|   84  |  | 
|   85 # Assign numbers to all opcodes and output the result. |  | 
|   86 END { |  | 
|   87   cnt = 0 |  | 
|   88   max = 0 |  | 
|   89   print "/* Automatically generated.  Do not edit */" |  | 
|   90   print "/* See the mkopcodeh.awk script for details */" |  | 
|   91   op["OP_Noop"] = -1; |  | 
|   92   op["OP_Explain"] = -1; |  | 
|   93   for(name in op){ |  | 
|   94     if( op[name]<0 ){ |  | 
|   95       cnt++ |  | 
|   96       while( used[cnt] ) cnt++ |  | 
|   97       op[name] = cnt |  | 
|   98     } |  | 
|   99     used[op[name]] = 1; |  | 
|  100     if( op[name]>max ) max = op[name] |  | 
|  101     printf "#define %-25s %15d", name, op[name] |  | 
|  102     if( sameas[op[name]] ) { |  | 
|  103       printf "   /* same as %-12s*/", sameas[op[name]] |  | 
|  104     }  |  | 
|  105     printf "\n" |  | 
|  106  |  | 
|  107   } |  | 
|  108   seenUnused = 0; |  | 
|  109   for(i=1; i<max; i++){ |  | 
|  110     if( !used[i] ){ |  | 
|  111       if( !seenUnused ){ |  | 
|  112         printf "\n/* The following opcode values are never used */\n" |  | 
|  113         seenUnused = 1 |  | 
|  114       } |  | 
|  115       printf "#define %-25s %15d\n", sprintf( "OP_NotUsed_%-3d", i ), i |  | 
|  116     } |  | 
|  117   } |  | 
|  118  |  | 
|  119   # Generate the bitvectors: |  | 
|  120   # |  | 
|  121   #  bit 0:     jump |  | 
|  122   #  bit 1:     pushes a result onto stack |  | 
|  123   #  bit 2:     output to p1.  release p1 before opcode runs |  | 
|  124   # |  | 
|  125   for(i=0; i<=max; i++) bv[i] = 0; |  | 
|  126   for(name in op){ |  | 
|  127     x = op[name] |  | 
|  128     a0 = a1 = a2 = a3 = a4 = a5 = a6 = a7 = 0 |  | 
|  129     # a8 = a9 = a10 = a11 = a12 = a13 = a14 = a15 = 0 |  | 
|  130     if( jump[name] ) a0 = 1; |  | 
|  131     if( out2_prerelease[name] ) a1 = 2; |  | 
|  132     if( in1[name] ) a2 = 4; |  | 
|  133     if( in2[name] ) a3 = 8; |  | 
|  134     if( in3[name] ) a4 = 16; |  | 
|  135     if( out3[name] ) a5 = 32; |  | 
|  136     # bv[x] = a0+a1+a2+a3+a4+a5+a6+a7+a8+a9+a10+a11+a12+a13+a14+a15; |  | 
|  137     bv[x] = a0+a1+a2+a3+a4+a5+a6+a7; |  | 
|  138   } |  | 
|  139   print "\n" |  | 
|  140   print "/* Properties such as \"out2\" or \"jump\" that are specified in" |  | 
|  141   print "** comments following the \"case\" for each opcode in the vdbe.c" |  | 
|  142   print "** are encoded into bitvectors as follows:" |  | 
|  143   print "*/" |  | 
|  144   print "#define OPFLG_JUMP            0x0001  /* jump:  P2 holds jmp target */" |  | 
|  145   print "#define OPFLG_OUT2_PRERELEASE 0x0002  /* out2-prerelease: */" |  | 
|  146   print "#define OPFLG_IN1             0x0004  /* in1:   P1 is an input */" |  | 
|  147   print "#define OPFLG_IN2             0x0008  /* in2:   P2 is an input */" |  | 
|  148   print "#define OPFLG_IN3             0x0010  /* in3:   P3 is an input */" |  | 
|  149   print "#define OPFLG_OUT3            0x0020  /* out3:  P3 is an output */" |  | 
|  150   print "#define OPFLG_INITIALIZER {\\" |  | 
|  151   for(i=0; i<=max; i++){ |  | 
|  152     if( i%8==0 ) printf("/* %3d */",i) |  | 
|  153     printf " 0x%02x,", bv[i] |  | 
|  154     if( i%8==7 ) printf("\\\n"); |  | 
|  155   } |  | 
|  156   print "}" |  | 
|  157 } |  | 
| OLD | NEW |