#!/usr/bin/tclsh## Generate the file opcodes.h.## This TCL script scans a concatenation of the parse.h output file from the# parser and the vdbe.c source file in order to generate the opcodes numbers# for all opcodes.## The lines of the vdbe.c that we are interested in are of the form:## case OP_aaaa: /* same as TK_bbbbb */## The TK_ comment is optional. If it is present, then the value assigned to# the OP_ is the same as the TK_ value. If missing, the OP_ value is assigned# a small integer that is different from every other OP_ value.## We go to the trouble of making some OP_ values the same as TK_ values# as an optimization. During parsing, things like expression operators# are coded with TK_ values such as TK_ADD, TK_DIVIDE, and so forth. Later# during code generation, we need to generate corresponding opcodes like# OP_Add and OP_Divide. By making TK_ADD==OP_Add and TK_DIVIDE==OP_Divide,# code to translate from one to the other is avoided. This makes the# code generator smaller and faster.## This script also scans for lines of the form:## case OP_aaaa: /* jump, in1, in2, in3, out2, out3 */## When such comments are found on an opcode, it means that certain# properties apply to that opcode. Set corresponding flags using the# OPFLG_INITIALIZER macro.#set in stdinset currentOp {}set prevName {}set nOp 0set nGroup 0while {![eof $in]} {set line [gets $in]# Remember the TK_ values from the parse.h file.# NB: The "TK_" prefix stands for "ToKen", not the graphical Tk toolkit# commonly associated with TCL.#if {[regexp {^#define TK_} $line]} {set tk([lindex $line 1]) [lindex $line 2]continue}# Find "/* Opcode: " lines in the vdbe.c file. Each one introduces# a new opcode. Remember which parameters are used.#if {[regexp {^.. Opcode: } $line]} {set currentOp OP_[lindex $line 2]set m 0foreach term $line {switch $term {P1 {incr m 1}P2 {incr m 2}P3 {incr m 4}P4 {incr m 8}P5 {incr m 16}}}set paramused($currentOp) $m}# Find "** Synopsis: " lines that follow Opcode:#if {[regexp {^.. Synopsis: (.*)} $line all x] && $currentOp!=""} {set synopsis($currentOp) [string trim $x]}# Scan for "case OP_aaaa:" lines in the vdbe.c file#if {[regexp {^case OP_} $line]} {set line [split $line]set name [string trim [lindex $line 1] :]if {$name=="OP_Abortable"} continue; # put OP_Abortable lastset op($name) -1set group($name) 0set jump($name) 0set in1($name) 0set in2($name) 0set in3($name) 0set out2($name) 0set out3($name) 0set ncycle($name) 0for {set i 3} {$i<[llength $line]-1} {incr i} {switch [string trim [lindex $line $i] ,] {same {incr iif {[lindex $line $i]=="as"} {incr iset sym [string trim [lindex $line $i] ,]set val $tk($sym)set op($name) $valset used($val) 1set sameas($val) $symset def($val) $name}}group {set group($name) 1}jump {set jump($name) 1}in1 {set in1($name) 1}in2 {set in2($name) 1}in3 {set in3($name) 1}out2 {set out2($name) 1}out3 {set out3($name) 1}ncycle {set ncycle($name) 1}}}if {$group($name)} {set newGroup 0if {[info exists groups($nGroup)]} {if {$prevName=="" || !$group($prevName)} {set newGroup 1}}lappend groups($nGroup) $nameif {$newGroup} {incr nGroup}} else {if {$prevName!="" && $group($prevName)} {incr nGroup}}set order($nOp) $nameset prevName $nameincr nOp}}# Assign numbers to all opcodes and output the result.#puts "/* Automatically generated. Do not edit */"puts "/* See the tool/mkopcodeh.tcl script for details */"foreach name {OP_Noop OP_Explain OP_Abortable} {set jump($name) 0set in1($name) 0set in2($name) 0set in3($name) 0set out2($name) 0set out3($name) 0set ncycle($name) 0set op($name) -1set order($nOp) $nameincr nOp}# The following are the opcodes that receive special processing in the# resolveP2Values() routine. Update this list whenever new cases are# added to the pOp->opcode switch within resolveP2Values().#set rp2v_ops {OP_TransactionOP_AutoCommitOP_SavepointOP_CheckpointOP_VacuumOP_JournalModeOP_VUpdateOP_VFilterOP_Init}# Assign the smallest values to opcodes that are processed by resolveP2Values()# to make code generation for the switch() statement smaller and faster.#set cnt -1for {set i 0} {$i<$nOp} {incr i} {set name $order($i)if {[lsearch $rp2v_ops $name]>=0} {incr cntwhile {[info exists used($cnt)]} {incr cnt}set op($name) $cntset used($cnt) 1set def($cnt) $name}}set mxCase1 $cnt# Assign the next group of values to JUMP opcodes#for {set i 0} {$i<$nOp} {incr i} {set name $order($i)if {$op($name)>=0} continueif {!$jump($name)} continueincr cntwhile {[info exists used($cnt)]} {incr cnt}set op($name) $cntset used($cnt) 1set def($cnt) $name}# Find the numeric value for the largest JUMP opcode#set mxJump -1for {set i 0} {$i<$nOp} {incr i} {set name $order($i)if {$jump($name) && $op($name)>$mxJump} {set mxJump $op($name)}}# Generate the numeric values for all remaining opcodes, while# preserving any groupings of opcodes (i.e. those that must be# together).#for {set g 0} {$g<$nGroup} {incr g} {set gLen [llength $groups($g)]set ok 0; set start -1set seek $cntwhile {!$ok} {incr seekwhile {[info exists used($seek)]} {incr seek}set ok 1; set start $seekfor {set j 0} {$j<$gLen} {incr j} {incr seekif {[info exists used($seek)]} {set ok 0; break}}}if {$ok} {set next $startfor {set j 0} {$j<$gLen} {incr j} {set name [lindex $groups($g) $j]if {$op($name)>=0} continueset op($name) $nextset used($next) 1set def($next) $nameincr next}} else {error "cannot find opcodes for group: $groups($g)"}}for {set i 0} {$i<$nOp} {incr i} {set name $order($i)if {$op($name)<0} {incr cntwhile {[info exists used($cnt)]} {incr cnt}set op($name) $cntset used($cnt) 1set def($cnt) $name}}set max [lindex [lsort -decr -integer [array names used]] 0]for {set i 0} {$i<=$max} {incr i} {if {![info exists used($i)]} {set def($i) "OP_NotUsed_$i"}if {$i>$max} {set max $i}set name $def($i)puts -nonewline [format {#define %-16s %3d} $name $i]set com {}if {[info exists jump($name)] && $jump($name)} {lappend com "jump"}if {[info exists sameas($i)]} {lappend com "same as $sameas($i)"}if {[info exists synopsis($name)]} {lappend com "synopsis: $synopsis($name)"}if {[llength $com]} {puts -nonewline [format " /* %-42s */" [join $com {, }]]}puts ""}if {$max>255} {error "More than 255 opcodes - VdbeOp.opcode is of type u8!"}# Generate the bitvectors:#set bv(0) 0for {set i 0} {$i<=$max} {incr i} {set x 0set name $def($i)if {[string match OP_NotUsed* $name]==0} {if {$jump($name)} {incr x 1}if {$in1($name)} {incr x 2}if {$in2($name)} {incr x 4}if {$in3($name)} {incr x 8}if {$out2($name)} {incr x 16}if {$out3($name)} {incr x 32}if {$ncycle($name)} {incr x 64}}set bv($i) $x}puts ""puts "/* Properties such as \"out2\" or \"jump\" that are specified in"puts "** comments following the \"case\" for each opcode in the vdbe.c"puts "** are encoded into bitvectors as follows:"puts "*/"puts "#define OPFLG_JUMP 0x01 /* jump: P2 holds jmp target */"puts "#define OPFLG_IN1 0x02 /* in1: P1 is an input */"puts "#define OPFLG_IN2 0x04 /* in2: P2 is an input */"puts "#define OPFLG_IN3 0x08 /* in3: P3 is an input */"puts "#define OPFLG_OUT2 0x10 /* out2: P2 is an output */"puts "#define OPFLG_OUT3 0x20 /* out3: P3 is an output */"puts "#define OPFLG_NCYCLE 0x40 /* ncycle:Cycles count against P1 */"puts "#define OPFLG_INITIALIZER 173円\\"for {set i 0} {$i<=$max} {incr i} {if {$i%8==0} {puts -nonewline [format "/* %3d */" $i]}puts -nonewline [format " 0x%02x," $bv($i)]if {$i%8==7} {puts "\\"}}puts "175円"puts ""puts "/* The resolve3P2Values() routine is able to run faster if it knows"puts "** the value of the largest JUMP opcode. The smaller the maximum"puts "** JUMP opcode the better, so the mkopcodeh.tcl script that"puts "** generated this include file strives to group all JUMP opcodes"puts "** together near the beginning of the list."puts "*/"puts "#define SQLITE_MX_JUMP_OPCODE $mxJump /* Maximum JUMP opcode */"
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。