You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
300 lines
8.5 KiB
300 lines
8.5 KiB
15 years ago
|
#!/bin/bash
|
||
|
################################################################################
|
||
|
# sql_keywords.sh
|
||
|
#
|
||
|
# Generate sets of driver-specific keywords.
|
||
|
# This program generates files that can be used as part of KexiDB drivers
|
||
|
# that list keywords specific to that driver, i.e. words that have to be
|
||
|
# escaped if they are to be used as identifiers in the database.
|
||
|
#
|
||
|
# It extracts keywords from the lexer of the DB sources, deletes keywords that
|
||
|
# are already going to be escaped because they are part of Kexi's SQL dialect,
|
||
|
# and writes the resulting keywords to a "char *keywords[]" construct in a .cpp
|
||
|
# file that can then be used in the driver.
|
||
|
#
|
||
|
# To use:
|
||
|
# Put the DB source tarballs (e.g. mysql-4.1.7.tar.gz,
|
||
|
# postgresql-base-7.4.6.tar.gz) in the current directory
|
||
|
# then run. (Makefile provided for installs)
|
||
|
#
|
||
|
# Sed, awk, grep have been used without much thought -
|
||
|
# CHECK THE OUTPUT BEFORE INCLUDING IT IN A DRIVER!
|
||
|
#
|
||
|
# Martin Ellis <martin.ellis@kdemail.net>
|
||
|
# 11/2004
|
||
|
|
||
|
set -e
|
||
|
progname="sql_keywords.sh"
|
||
|
|
||
|
################################################################################
|
||
|
# C++ file generator
|
||
|
# params : array - scoped name of the array to generate
|
||
|
# include - a file to include (or "" if none)
|
||
|
# inFile - file containing raw keywords
|
||
|
# outfile - file to write
|
||
|
header () {
|
||
|
local array="$1"
|
||
|
local include="$2"
|
||
|
local inFile="$3"
|
||
|
local outFile="$4"
|
||
|
echo "Writing keywords in $inFile to $outFile"
|
||
|
cat <<EOF1 > "$outFile";
|
||
|
/*
|
||
|
* This file has been automatically generated from
|
||
|
* koffice/kexi/tools/sql_keywords/$progname and
|
||
|
* $inFile.
|
||
|
*
|
||
|
* Please edit the $progname, not this file!
|
||
|
*/
|
||
|
EOF1
|
||
|
if [ "$include" != "" ] ; then
|
||
|
echo "#include <$include>" >> "$outFile"
|
||
|
fi
|
||
|
cat <<EOF2 >> "$outFile";
|
||
|
|
||
|
namespace KexiDB {
|
||
|
const char* ${array}[] = {
|
||
|
EOF2
|
||
|
}
|
||
|
|
||
|
body() {
|
||
|
local inFile="$1"
|
||
|
local outFile="$2"
|
||
|
awk '/^[a-zA-Z_0-9]*/ { print "\t\t\""$$1"\","; } ' "$inFile" >> "$outFile"
|
||
|
}
|
||
|
|
||
|
footer() {
|
||
|
local outFile="$1"
|
||
|
cat <<EOF >> "$outFile";
|
||
|
0
|
||
|
};
|
||
|
}
|
||
|
EOF
|
||
|
|
||
|
}
|
||
|
|
||
|
################################################################################
|
||
|
# Keyword comparison functions
|
||
|
# Globals: keywords
|
||
|
|
||
|
# readKeywords
|
||
|
# params: filename - file of keywords to read
|
||
|
# sets: keywords - array of keywords in the file
|
||
|
readKeywords () {
|
||
|
local filename="$1"
|
||
|
local kexiSQL="$2"
|
||
|
i=0
|
||
|
while read keyword ; do
|
||
|
keywords[$i]="$keyword"
|
||
|
(( i++ ))
|
||
|
done < "$filename"
|
||
|
}
|
||
|
|
||
|
# compareKeywords
|
||
|
# reads: kexiSQL -
|
||
|
# driverSQL
|
||
|
# sets: keywords - driver keywords that are not keywords in Kexi
|
||
|
compareKeywords () {
|
||
|
numFound=0
|
||
|
for(( i=0; i < ${#driverSQL[@]}; i++ )) ; do
|
||
|
found="no"
|
||
|
for(( j=0; j < ${#kexiSQL[@]}; j++ )) ; do
|
||
|
if [ "${driverSQL[$i]}" == "${kexiSQL[$j]}" ] ; then
|
||
|
found="yes"
|
||
|
fi
|
||
|
done
|
||
|
if [ "$found" == "no" ] ; then
|
||
|
keywords[$numFound]="${driverSQL[$i]}"
|
||
|
(( numFound++ ))
|
||
|
fi
|
||
|
done
|
||
|
}
|
||
|
|
||
|
|
||
|
# getDriverKeywords
|
||
|
# params : kexi -
|
||
|
# driver -
|
||
|
# outFile -
|
||
|
getDriverKeywords () {
|
||
|
local kexi="$1"
|
||
|
local driver="$2"
|
||
|
local outFile="$3"
|
||
|
|
||
|
declare -a kexiSQL
|
||
|
declare -a driverSQL
|
||
|
|
||
|
echo "Looking for driver-specific keywords in \"$driver\""
|
||
|
readKeywords $kexi
|
||
|
for(( i=0; i < ${#keywords[@]}; i++ )) ; do
|
||
|
kexiSQL[$i]=${keywords[$i]}
|
||
|
done
|
||
|
unset keywords
|
||
|
|
||
|
readKeywords $driver
|
||
|
for(( i=0; i < ${#keywords[@]}; i++ )) ; do
|
||
|
driverSQL[$i]=${keywords[$i]}
|
||
|
done
|
||
|
unset keywords
|
||
|
|
||
|
compareKeywords
|
||
|
echo "Writing driver-specific keywords for \"$driver\" to \"$outFile\""
|
||
|
rm -f $outFile
|
||
|
for(( i=0; i < ${#keywords[@]}; i++ )) ; do
|
||
|
echo ${keywords[$i]} >> $outFile
|
||
|
done
|
||
|
unset keywords
|
||
|
}
|
||
|
################################################################################
|
||
|
|
||
|
|
||
|
################################################################################
|
||
|
# Kexi lexer
|
||
|
|
||
|
checkKexiKeywords () {
|
||
|
local scanner="../../kexidb/parser/sqlscanner.l"
|
||
|
if [ ! -r kexi.all -o "$scanner" -nt "kexi.all" ] ; then
|
||
|
echo "Getting Kexi keywords"
|
||
|
grep '^(\?"[a-zA-Z_0-9]' "$scanner" | \
|
||
|
sed 's/(\?"\([^"]*\)"[^"]*/\1\n/g' | \
|
||
|
awk '/^[a-zA-Z_0-9]+$/ {print $1;}' |
|
||
|
sort | uniq > "kexi.all"
|
||
|
awk '/^[a-zA-Z_0-9]+$/ {print $1;}' kexi_reserved >> "kexi.all"
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
################################################################################
|
||
|
# DB lexer functions
|
||
|
# These functions munge the extracted lexers from DBs and write the collected
|
||
|
# keywords to file
|
||
|
|
||
|
# getSQLiteKeywords
|
||
|
# params : inFile - SQLite3 lexer file
|
||
|
# outFile - all SQLite3 keywords
|
||
|
getSQLiteKeywords () {
|
||
|
local inFile="$1"
|
||
|
local outFile="$2"
|
||
|
|
||
|
echo "Getting SQLite keywords ($inFile -> $outFile)"
|
||
|
sed -n '/^static Keyword aKeywordTable/,/};/p' $inFile | \
|
||
|
awk '/ { "[a-zA-Z_0-9]*"/ { print $2;}' | \
|
||
|
sed 's/"\(.*\)".*/\1/g' > $outFile
|
||
|
}
|
||
|
|
||
|
getPostgreSQLKeywords () {
|
||
|
local inFile="$1"
|
||
|
local outFile="$2"
|
||
|
|
||
|
echo "Getting PostgreSQL keywords ($inFile -> $outFile)"
|
||
|
sed -n '/^static const ScanKeyword ScanKeywords/,/};/p' $inFile | \
|
||
|
awk '/\t{"[a-zA-Z_0-9]*"/ { print $1;}' | \
|
||
|
sed 's/.*"\(.*\)".*/\1/g' | tr 'a-z' 'A-Z' > $outFile
|
||
|
}
|
||
|
|
||
|
# getMySQLKeywords
|
||
|
# params : inFile - MySQL lexer file
|
||
|
# outFile - all MySQL keywords
|
||
|
getMySQLKeywords () {
|
||
|
local inFile="$1"
|
||
|
local outFile="$2"
|
||
|
|
||
|
echo "Getting MySQL keywords ($inFile -> $outFile)"
|
||
|
sed -n '/^static SYMBOL symbols/,/};/p' $inFile | \
|
||
|
awk '/ { "[a-zA-Z_0-9]*"/ { print $2;}' | \
|
||
|
sed 's/"\(.*\)".*/\1/g' > $outFile
|
||
|
}
|
||
|
|
||
|
################################################################################
|
||
|
# DB tarball functions
|
||
|
# These functions extract the lexer files from the DB source tarballs
|
||
|
|
||
|
# checkExtracted
|
||
|
# params : tarball - tarball containing backend DB source
|
||
|
# file - file in tarball containing DB's lexer
|
||
|
checkExtracted () {
|
||
|
local tarball="$1"
|
||
|
local file="$2"
|
||
|
|
||
|
if [ ! -r "$file" ] ; then
|
||
|
echo "Getting file \"$file\" from \"$tarball\""
|
||
|
tar -zxf "$tarball" "$file"
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
# checkTarballs
|
||
|
checkTarballs () {
|
||
|
local pathInTar
|
||
|
local appName
|
||
|
local appVer
|
||
|
|
||
|
# SQLite (native DB backend) keywords
|
||
|
appName="SQLite"
|
||
|
appVer=sqlite
|
||
|
inFile="../../3rdparty/kexisql3/src/tokenize.c"
|
||
|
filePrefix="sqlite"
|
||
|
if [ ! -r "$appVer.all" ] || [ ! -r "$appVer.new" ] ; then
|
||
|
getSQLiteKeywords "$inFile" "$appVer.all"
|
||
|
fi
|
||
|
if [ "$appVer.all" -nt "$appVer.new" ] ; then
|
||
|
getDriverKeywords "kexi.all" "$appVer.all" "$appVer.new"
|
||
|
header "${appName}Driver::keywords" "${filePrefix}driver.h" "$inFile" "${filePrefix}keywords.cpp"
|
||
|
body "$appVer.new" "${filePrefix}keywords.cpp"
|
||
|
footer "${filePrefix}keywords.cpp"
|
||
|
fi
|
||
|
|
||
|
ls mysql-*.tar.gz postgresql-*.tar.gz 2>/dev/null | while read tarball ; do
|
||
|
case "$tarball" in
|
||
|
mysql-4.1.[0-9\.]*.tar.gz)
|
||
|
pathInTar="sql/lex.h"
|
||
|
appName="MySql"
|
||
|
filePrefix="mysql"
|
||
|
appVer="${tarball%.tar.gz}"
|
||
|
if [ ! -r "$appVer.all" ] || [ ! -r "$appVer.new" ] ; then
|
||
|
checkExtracted "$tarball" "$appVer/$pathInTar"
|
||
|
getMySQLKeywords "$appVer/$pathInTar" "$appVer.all"
|
||
|
rm -rf "$appVer"
|
||
|
fi
|
||
|
|
||
|
if [ "$appVer.all" -nt "$appVer.new" ] ; then
|
||
|
getDriverKeywords "kexi.all" "$appVer.all" "$appVer.new"
|
||
|
header "${appName}Driver::keywords" "${filePrefix}driver.h" "$appVer/$pathInTar" "${filePrefix}keywords.cpp"
|
||
|
body "$appVer.new" "${filePrefix}keywords.cpp"
|
||
|
footer "${filePrefix}keywords.cpp"
|
||
|
fi
|
||
|
;;
|
||
|
|
||
|
postgresql-base-7.4.[0-9\.]*.tar.gz)
|
||
|
pathInTar="src/backend/parser/keywords.c"
|
||
|
appName="pqxxSql"
|
||
|
filePrefix="pqxx"
|
||
|
appVer=`echo "${tarball%.tar.gz}" | sed 's/-base//'`
|
||
|
if [ ! -r "$appVer.all" ] || [ ! -r "$appVer.new" ] ; then
|
||
|
checkExtracted "$tarball" "$appVer/$pathInTar"
|
||
|
getPostgreSQLKeywords "$appVer/$pathInTar" "$appVer.all"
|
||
|
rm -rf "$appVer"
|
||
|
fi
|
||
|
|
||
|
if [ "$appVer.all" -nt "$appVer.new" ] ; then
|
||
|
getDriverKeywords "kexi.all" "$appVer.all" "$appVer.new"
|
||
|
header "${appName}Driver::keywords" "${filePrefix}driver.h" "$appVer/$pathInTar" "${filePrefix}keywords.cpp"
|
||
|
body "$appVer.new" "${filePrefix}keywords.cpp"
|
||
|
footer "${filePrefix}keywords.cpp"
|
||
|
fi
|
||
|
;;
|
||
|
|
||
|
*)
|
||
|
echo "Don't know how to deal with $tarball - ignoring"
|
||
|
;;
|
||
|
esac
|
||
|
done
|
||
|
}
|
||
|
|
||
|
checkKexiKeywords
|
||
|
src=`printf "koffice/kexi/kexidb/parser/sqlscanner.l\n"\
|
||
|
" * and koffice/kexi/tools/sql_keywords/kexi__reserved"`
|
||
|
header "DriverPrivate::kexiSQLKeywords" "driver_p.h" "$src" "keywords.cpp"
|
||
|
body "kexi.all" "keywords.cpp"
|
||
|
footer "keywords.cpp"
|
||
|
|
||
|
checkTarballs
|
||
|
wc -l *.all *.new | awk '{print $2" "$1}' |sort|awk '{print $1"\t"$2}'
|