<title>SQLite Requirements</title>
<h2>SQLite Requirements</h2>
<p>This document is a work in progress.</p>
<p>The goal of this document is to provide an precise and exact
definition of what SQLite does, how it works, and what to expect
from SQLite for any given input. When completed, this document
will become the authoritative reference for using SQLite.</p>
<h3>The C/C++ Interface</h3>
<table cellspacing="20" border="0">
<tcl>
# Extract requirements from the sqlite3.h header file
#
set in [open sqlite3.h]
set title {} ;# Title of an interface
set body {} ;# human-readable description
set code {} ;# C code of the definition
set phase 0 ;# Phase used by the parser
set reqlist {} ;# List of requirements, on record per requirement entry
set dcnt 0 ;# Number of individual declarations
set lineno 0 ;# input file line number
# Split the input string $in at the first {...} marker. Store the text
# before the marker in the prefixvar. Store the content of the marker
# in tagvar. And store the text after the marker in tailvar.
#
proc split_text {in prefixvar tagvar tailvar} {
if {[regexp -indices {\{[\w.]+\}} $in i]} {
upvar 1 $prefixvar prefix
upvar 1 $tagvar tag
upvar 1 $tailvar tail
foreach {front back} $i break
set x0 [expr {$front-1}]
set prefix [string range $in 0 $x0]
set x1 [expr {$front+1}]
set x2 [expr {$back-1}]
set tag [string range $in $x1 $x2]
set x3 [expr {$back+1}]
set tail [string range $in $x3 end]
return 1
} else {
return 0
}
}
# Convert a tag name into the filename used for the
# multi-file version.
#
# Constants begin with SQLITE_. The names are converted
# to lower case and prefixed with "c_". If we did not
# do this, then the names "SQLITE_BLOB" and "sqlite3_blob"
# would collide.
#
proc convert_tag_name {oldname} {
set oldname [string tolower $oldname]
regsub {^sqlite_} $oldname {c_} oldname
regsub {^sqlite3_} $oldname {} name
return $name.html
}
# Read sqlite3.h line by line and extract interface definition
# information.
#
while {![eof $in]} {
set line [gets $in]
incr lineno
if {$phase==0} {
# Looking for the CAPI3REF: keyword
if {[regexp {^\*\* CAPI3REF: +(.*)} $line all tx]} {
set title $tx
set title_lineno $lineno
set phase 1
}
} elseif {$phase==1} {
if {[string range $line 0 1]=="**"} {
set lx [string trim [string range $line 3 end]]
if {[regexp {^CATEGORY: +([a-z]*)} $lx all cx]} {
set type $cx
} elseif {[regexp {^KEYWORDS: +(.*)} $lx all kx]} {
foreach k $kx {
set keyword($k) 1
}
} else {
append body $lx\n
}
} elseif {[string range $line 0 1]=="*/"} {
set phase 2
}
} elseif {$phase==2} {
if {$line==""} {
set kwlist [lsort [array names keyword]]
set docfile [convert_tag_name [lindex $kwlist 0]]
unset -nocomplain keyword
set key $type:$kwlist
if {[regexp {\{([\w.]+)\}} $title all tag]} {
regsub { *\{[\w.]+\}} $title {} title
if {$dcnt>1} {set d declarations} {set d {a declaration}}
set code [string map {& & < < > >} $code]
set req "The \"sqlite3.h\" header file\
shall contain $d equivalent to the following:\
\n<blockquote><pre>\n$code</pre></blockquote>"
regexp {\d+} $tag key
lappend reqlist [list $key $tag sqlite3.h $title_lineno $req $docfile]
}
set x $body
while {[split_text $x prefix tag suffix]} {
if {![split_text $suffix req endtag tail]} {
set req $suffix
set x {}
} elseif {$endtag=="END"} {
set x $tail
} else {
set x "{$endtag} $tail"
}
regsub -all {\[([^]|]+\|)?([^]]+)\]} $req {\2} req
#regsub -all {\s+} $req { } req
set req [string trim $req]
set req [string map \
{<todo> {<font color="red">(TODO: } </todo> )</font>} $req]
regexp {\d+} $tag key
lappend reqlist [list $key $tag sqlite3.h $title_lineno $req $docfile]
}
set title {}
set keywords {}
set type {}
set body {}
set code {}
set phase 0
set dcnt 0
} else {
if {[regexp {^#define (SQLITE_[A-Z0-9_]+)} $line all kx]} {
set type constant
set keyword($kx) 1
incr dcnt
} elseif {[regexp {^typedef .*(sqlite[0-9a-z_]+);} $line all kx]} {
set type datatype
set keyword($kx) 1
incr dcnt
} elseif {[regexp {^[a-z].*[ *](sqlite3_[a-z0-9_]+)\(} $line all kx]} {
set type function
set keyword($kx) 1
incr dcnt
} elseif {[regexp {^SQLITE_EXTERN .*(sqlite[0-9a-z_]+);} $line all kx]} {
set type datatype
set keyword($kx) 1
incr dcnt
}
append code $line\n
}
}
}
set dbfd [open reqdb.sql w]
foreach req [lsort -index 0 $reqlist] {
foreach {key tag file lineno text docfile} $req break
puts "<tr><td valign=\"top\"><a href=\"c3ref/$docfile\">$tag</a></td>"
puts "<td valign=\"top\">$text</td></tr>"
set qtext [string map {' ''} $text]
real_puts $dbfd "INSERT INTO req VALUES('$tag','$file',$lineno,'$qtext');"
}
close $dbfd
</tcl>
</table>