2008-07-09 06:04:10 -07:00
#!/usr/bin/perl -w
# vim: set et sts=4 sw=4:
package CG ;
use strict ;
# Code generator for C code to load contents of the SQL tables from an SQLite
# database into the C struct definitions.
2008-07-09 07:47:16 -07:00
my $ filename = "" ;
my $ outfile = "" ;
2008-07-09 06:04:10 -07:00
sub printComments
{
my ( $ output , $ comments , $ indent ) = @ _ ;
2008-11-23 05:32:02 -08:00
return unless @$ comments ;
2008-07-09 06:04:10 -07:00
2008-11-23 05:32:02 -08:00
$$ output . = "$indent/*$comments->[0]\n" ;
2008-07-09 06:04:10 -07:00
2008-11-23 05:32:02 -08:00
for ( my $ i = 1 ; $ i < @$ comments ; $ i + + )
2008-07-09 06:04:10 -07:00
{
2008-11-23 05:32:02 -08:00
my $ comment = $ comments - > [ $ i ] ;
2008-07-09 06:04:10 -07:00
$$ output . = "$indent *${comment}\n" ;
}
$$ output . = "$indent */\n" ;
}
sub printSqlComments
{
my ( $ output , $ comments , $ indent ) = @ _ ;
2008-11-23 05:32:02 -08:00
return unless @$ comments ;
2008-07-09 06:04:10 -07:00
2008-11-23 05:32:02 -08:00
foreach ( @$ comments )
2008-07-09 06:04:10 -07:00
{
my $ comment = $ _ ;
$ comment =~ s/\"/\\\"/g ;
$$ output . = "$indent\"--${comment}\\n\"\n" ;
}
}
sub printEnum ()
{
}
sub getStructName
{
2008-07-10 14:11:24 -07:00
my ( $ name , $ struct , $ structMap , $ prefix , $ suffix ) = @ _ ;
2008-07-09 06:04:10 -07:00
2008-11-23 05:32:02 -08:00
foreach ( keys % { $ struct - > { "qualifiers" } } )
2008-07-09 06:04:10 -07:00
{
2008-11-23 05:32:02 -08:00
$$ prefix = $ struct - > { "qualifiers" } { $ _ } if /prefix/ and not $$ prefix ;
$$ suffix = $ struct - > { "qualifiers" } { $ _ } if /suffix/ and not $$ suffix ;
2008-07-09 06:04:10 -07:00
2008-11-23 05:32:02 -08:00
getStructName ( $ name , $ struct - > { "qualifiers" } { "inherit" } , $ structMap , $ prefix , $ suffix ) if /inherit/ ;
2008-07-09 06:04:10 -07:00
}
2008-11-23 05:32:02 -08:00
$$ name = "$$prefix$struct->{name}$$suffix" ;
2008-07-09 06:04:10 -07:00
}
sub printFuncHeader
{
my ( $ output , $ struct , $ structName ) = @ _ ;
2008-11-23 05:32:02 -08:00
$$ output . = "/** Load the contents of the $struct->{name} table from the given SQLite database.\n"
2008-07-09 06:04:10 -07:00
. " *\n"
. " * \@param db represents the database to load from\n"
. " *\n"
2009-03-11 04:51:40 -07:00
. " * \@return true if we successfully loaded all available rows from the table,\n"
2008-07-09 06:04:10 -07:00
. " * false otherwise.\n"
. " */\n"
2008-07-09 10:55:18 -07:00
. "bool\n"
2008-11-23 05:32:02 -08:00
. "#line $struct->{qualifiers}{loadFunc}{line} \"$filename\"\n"
. "$struct->{qualifiers}{loadFunc}{name}\n" ;
2008-07-09 07:47:16 -07:00
my $ line = $$ output =~ s/\n/\n/sg ;
$ line += 2 ;
2008-07-09 10:55:18 -07:00
$$ output . = "#line $line \"$outfile\"\n"
. "\t(sqlite3* db)\n" ;
2008-07-09 06:04:10 -07:00
}
sub printFuncFooter
{
my ( $ output ) = @ _ ;
$$ output . = "\n"
. "\tretval = true;\n"
. "\n"
. "in_statement_err:\n"
. "\tsqlite3_finalize(stmt);\n"
. "\n"
. "\treturn retval;\n" ;
}
sub printColNums
{
my ( $ output , $ struct , $ structMap , $ enumMap ) = @ _ ;
foreach ( keys % { $ { $ struct } { "qualifiers" } } )
{
if ( /inherit/ )
{
2008-11-23 05:32:02 -08:00
my $ inheritStruct = $ struct - > { "qualifiers" } { "inherit" } ;
2008-07-09 06:04:10 -07:00
printColNums ( $ output , $ inheritStruct , $ structMap , $ enumMap ) ;
}
elsif ( /abstract/ )
{
$$ output . = "\t\tint unique_inheritance_id;\n" ;
}
}
2008-11-23 05:32:02 -08:00
foreach my $ field ( @ { $ struct - > { "fields" } } )
2008-07-09 06:04:10 -07:00
{
2008-11-23 05:32:02 -08:00
my $ fieldName = $ field - > { "name" } ;
2008-07-09 06:04:10 -07:00
2008-11-23 05:32:02 -08:00
if ( $ field - > { "type" } and $ field - > { "type" } =~ /set/ )
2008-07-09 06:04:10 -07:00
{
2008-11-23 05:32:02 -08:00
my $ enum = $ field - > { "enum" } ;
2008-07-09 06:04:10 -07:00
2008-11-23 05:32:02 -08:00
foreach my $ value ( @ { $ enum - > { "values" } } )
2008-07-09 06:04:10 -07:00
{
2008-11-23 05:32:02 -08:00
$$ output . = "\t\tint $field->{name}_$value->{name};\n" ;
2008-07-09 06:04:10 -07:00
}
}
2008-11-23 05:32:02 -08:00
elsif ( $ field - > { "type" } and $ field - > { "type" } =~ /C-only-field/ )
2008-07-12 13:36:45 -07:00
{
# Ignore: this is a user defined field type, the user code (%postLoadRow) can deal with it
}
2008-07-09 06:04:10 -07:00
else
{
$$ output . = "\t\tint $fieldName;\n" ;
}
}
}
sub printSqlQueryVariables
{
my ( $ output , $ struct , $ structMap , $ enumMap ) = @ _ ;
$$ output . = "\tbool retval = false;\n"
. "\tsqlite3_stmt* stmt;\n"
. "\tint rc;\n"
2008-11-15 19:33:43 -08:00
. "\tunsigned int CUR_ROW_NUM = 0;\n"
2008-07-09 06:04:10 -07:00
. "\tstruct\n"
. "\t{\n" ;
printColNums ( $ output , $ struct , $ structMap , $ enumMap ) ;
$$ output . = "\t} cols;\n"
. "\n" ;
}
sub printStructFields
{
my ( $ output , $ struct , $ enumMap , $ indent ) = @ _ ;
2008-11-23 05:32:02 -08:00
my @ fields = @ { $ struct - > { "fields" } } ;
my $ structName = $ struct - > { "name" } ;
2008-07-09 06:04:10 -07:00
2008-11-16 09:43:32 -08:00
my $ first = 1 ;
FIELD:
2008-07-09 06:04:10 -07:00
while ( @ fields )
{
my $ field = shift ( @ fields ) ;
2008-11-16 09:43:32 -08:00
# Ignore: this is a user defined field type, the user code (%postLoadRow) can deal with it
2008-11-23 05:32:02 -08:00
next FIELD if $ field - > { "type" } and $ field - > { "type" } =~ /C-only-field/ ;
2008-11-16 09:43:32 -08:00
$$ output . = ",\\n\"\n\n" unless $ first ;
$ first = 0 ;
2008-11-23 05:32:02 -08:00
printSqlComments ( $ output , $ field - > { "comment" } , $ indent ) ;
2008-07-09 06:04:10 -07:00
2008-11-23 05:32:02 -08:00
if ( $ field - > { "type" } and $ field - > { "type" } =~ /set/ )
2008-07-09 06:04:10 -07:00
{
2008-11-23 05:32:02 -08:00
my $ enum = $ field - > { "enum" } ;
my @ values = @ { $ enum - > { "values" } } ;
2008-07-09 06:04:10 -07:00
while ( @ values )
{
my $ value = shift ( @ values ) ;
2009-02-21 13:09:37 -08:00
$$ output . = "$indent\"$field->{name}_$value->{name}" ;
2008-07-09 06:04:10 -07:00
$$ output . = ",\\n\"\n" if @ values ;
}
}
else
{
2009-02-21 13:09:37 -08:00
$$ output . = "$indent\"$field->{name}" ;
2008-07-09 06:04:10 -07:00
}
}
}
sub printStructContent
{
my ( $ output , $ struct , $ structMap , $ enumMap , $ indent , $ first ) = @ _ ;
2008-11-23 05:32:02 -08:00
foreach ( keys % { $ struct - > { "qualifiers" } } )
2008-07-09 06:04:10 -07:00
{
if ( /inherit/ )
{
2008-11-23 05:32:02 -08:00
my $ inheritStruct = $ struct - > { "qualifiers" } { "inherit" } ;
2008-07-09 06:04:10 -07:00
printStructContent ( $ output , $ inheritStruct , $ structMap , $ enumMap , $ indent , 0 ) ;
}
elsif ( /abstract/ )
{
2008-11-23 05:32:02 -08:00
my $ tableName = $ struct - > { "name" } ;
2008-07-09 06:04:10 -07:00
$$ output . = "$indent\"-- Automatically generated ID to link the inheritance hierarchy.\\n\"\n"
2009-02-15 04:32:29 -08:00
. "$indent\"unique_inheritance_id,\\n\"\n" ;
2008-07-09 06:04:10 -07:00
}
}
printStructFields ( $ output , $ struct , $ enumMap , $ indent ) ;
$$ output . = "," unless $ first ;
$$ output . = "\\n\"\n" ;
$$ output . = "\n" unless $ first ;
}
sub printParameterLoadCode
{
my ( $ output , $ struct , $ structMap , $ parameter ) = @ _ ;
2008-11-23 05:32:02 -08:00
my $ tableName = $ struct - > { "name" } ;
2008-07-09 06:04:10 -07:00
$$ output . = "\t\t/* Prepare this SQL statement for execution */\n"
. "\t\tif (!prepareStatement(db, &stmt, \"SELECT " ;
$ _ = $ parameter ;
if ( /\bmaxId\b/ ) { $$ output . = "MAX" ; }
elsif ( /\browCount\b/ ) { $$ output . = "COUNT" ; }
else { die "UKNOWN PARAMETER TYPE: $_" ; }
2009-02-15 04:32:29 -08:00
$$ output . = "(unique_inheritance_id) " ;
2008-07-09 06:04:10 -07:00
2009-02-15 04:32:29 -08:00
$$ output . = "FROM `${tableName}S`;\"))\n"
2008-07-09 06:04:10 -07:00
. "\t\t\treturn false;\n"
. "\n"
. "\t\t/* Execute and process the results of the above SQL statement */\n"
. "\t\tif (sqlite3_step(stmt) != SQLITE_ROW\n"
. "\t\t || sqlite3_data_count(stmt) != 1)\n"
. "\t\t\tgoto in_statement_err;\n"
. "\t\t" ;
if ( /\bmaxId\b/ ) { $$ output . = "MAX_ID_VAR" ; }
elsif ( /\browCount\b/ ) { $$ output . = "ROW_COUNT_VAR" ; }
else { die "UKNOWN PARAMETER TYPE: $_" ; }
$$ output . = " = sqlite3_column_int(stmt, 0);\n"
. "\t\tsqlite3_finalize(stmt);\n"
. "\n" ;
}
sub printPreLoadTableCode
{
my ( $ output , $ struct , $ structMap , $ enumMap ) = @ _ ;
2008-11-23 05:32:02 -08:00
return unless exists ( $ struct - > { "qualifiers" } { "preLoadTable" } ) ;
2008-07-09 06:04:10 -07:00
2008-11-23 05:32:02 -08:00
my $ line = $ struct - > { "qualifiers" } { "preLoadTable" } { "line" } ;
2008-07-09 08:25:46 -07:00
2008-07-09 06:04:10 -07:00
$$ output . = "\t{\n" ;
2008-11-23 05:32:02 -08:00
foreach ( @ { $ struct - > { "qualifiers" } { "preLoadTable" } { "parameters" } } )
2008-07-09 06:04:10 -07:00
{
if ( /\bmaxId\b/ )
{
$$ output . = "\t\tint MAX_ID_VAR;\n" ;
}
elsif ( /\browCount\b/ )
{
$$ output . = "\t\tunsigned int ROW_COUNT_VAR;\n" ;
}
else
{
die "UKNOWN PARAMETER TYPE: $_" ;
}
}
2008-11-23 05:32:02 -08:00
$$ output . = "\n" if ( @ { $ struct - > { "qualifiers" } { "preLoadTable" } { "parameters" } } ) ;
2008-07-09 06:04:10 -07:00
2008-11-23 05:32:02 -08:00
foreach ( @ { $ struct - > { "qualifiers" } { "preLoadTable" } { "parameters" } } )
2008-07-09 06:04:10 -07:00
{
printParameterLoadCode ( $ output , $ struct , $ structMap , $ _ ) ;
}
2008-07-09 08:25:46 -07:00
$$ output . = "#line " . ( $ line + 1 ) . " \"$filename\"\n" ;
2008-11-23 05:32:02 -08:00
foreach ( @ { $ struct - > { "qualifiers" } { "preLoadTable" } { "code" } } )
2008-07-09 06:04:10 -07:00
{
s/^ //g ;
s/ /\t/g ;
s/\$maxId\b/MAX_ID_VAR/g ;
s/\$rowCount\b/ROW_COUNT_VAR/g ;
s/\bABORT\b/return false/g ;
$$ output . = "\t\t$_\n" ;
}
2008-07-09 08:25:46 -07:00
$ line = $$ output =~ s/\n/\n/sg ;
$ line += 2 ;
$$ output . = "#line $line \"$outfile\"\n" ;
2008-07-09 06:04:10 -07:00
$$ output . = "\t}\n"
. "\n" ;
}
sub printSqlFetchColName
{
my ( $ output , $ colname ) = @ _ ;
$$ output . = "\tcols.$colname = getColNumByName(stmt, \"$colname\");\n"
. "\t\tASSERT(cols.$colname != -1, \"Column $colname not found in result set!\");\n"
. "\t\tif (cols.$colname == -1)\n"
. "\t\t\tgoto in_statement_err;\n" ;
}
sub printSqlColNameFetchCode
{
my ( $ output , $ struct , $ structMap , $ enumMap ) = @ _ ;
2008-11-23 05:32:02 -08:00
foreach ( keys % { $ struct - > { "qualifiers" } } )
2008-07-09 06:04:10 -07:00
{
if ( /inherit/ )
{
2008-11-23 05:32:02 -08:00
my $ inheritStruct = $ struct - > { "qualifiers" } { "inherit" } ;
my $ inheritName = $ inheritStruct - > { "name" } ;
2008-07-09 06:04:10 -07:00
$$ output . = "\t/* BEGIN of inherited \"$inheritName\" definition */\n" ;
printSqlColNameFetchCode ( $ output , $ inheritStruct , $ structMap , $ enumMap ) ;
$$ output . = "\t/* END of inherited \"$inheritName\" definition */\n" ;
}
elsif ( /abstract/ )
{
printSqlFetchColName ( $ output , "unique_inheritance_id" ) ;
}
}
2008-11-23 05:32:02 -08:00
foreach my $ field ( @ { $ struct - > { "fields" } } )
2008-07-09 06:04:10 -07:00
{
2008-11-23 05:32:02 -08:00
if ( $ field - > { "type" } and $ field - > { "type" } =~ /set/ )
2008-07-09 06:04:10 -07:00
{
2008-11-23 05:32:02 -08:00
my $ enum = $ field - > { "enum" } ;
2008-07-09 06:04:10 -07:00
2008-11-23 05:32:02 -08:00
foreach my $ value ( @ { $ enum - > { "values" } } )
2008-07-09 06:04:10 -07:00
{
2008-11-23 05:32:02 -08:00
printSqlFetchColName ( $ output , "$field->{name}_$value->{name}" ) ;
2008-07-09 06:04:10 -07:00
}
}
2008-11-23 05:32:02 -08:00
elsif ( $ field - > { "type" } and $ field - > { "type" } =~ /C-only-field/ )
2008-07-12 13:36:45 -07:00
{
# Ignore: this is a user defined field type, the user code (%postLoadRow) can deal with it
}
2008-07-09 06:04:10 -07:00
else
{
2008-11-23 05:32:02 -08:00
printSqlFetchColName ( $ output , $ field - > { "name" } ) ;
2008-07-09 06:04:10 -07:00
}
}
}
sub printStartSelectQuery
{
my ( $ output , $ structName , $ struct , $ structMap , $ enumMap ) = @ _ ;
$$ output . = "\t/* Prepare the query to start fetching all rows */\n"
. "\tif (!prepareStatement(db, &stmt,\n"
. "\t " ;
my $ indent ;
$ indent = "\t " ;
# Start printing the select statement
$$ output . = "\"SELECT\\n\"\n" ;
printStructContent ( $ output , $ struct , $ structMap , $ enumMap , $ indent . " " , 1 ) ;
2009-02-15 04:32:29 -08:00
$$ output . = "${indent}\"FROM `$struct->{name}S`;\"))\n"
2008-07-09 06:04:10 -07:00
. "\t\treturn false;\n"
. "\n"
. "\t/* Fetch the first row */\n"
2008-11-15 19:08:04 -08:00
. "\tif ((rc = sqlite3_step(stmt)) != SQLITE_ROW)\n"
2008-07-09 06:04:10 -07:00
. "\t{\n"
. "\t\t/* Apparently we fetched no rows at all, this is a non-failure, terminal condition. */\n"
. "\t\tsqlite3_finalize(stmt);\n"
. "\t\treturn true;\n"
. "\t}\n"
. "\n"
. "\t/* Fetch and cache column numbers */\n" ;
printSqlColNameFetchCode ( $ output , $ struct , $ structMap , $ enumMap ) ;
$$ output . = "\n" ;
}
sub printRowProcessCode
{
my ( $ output , $ struct , $ structMap , $ enumMap ) = @ _ ;
2008-11-23 05:32:02 -08:00
foreach ( keys % { $ struct - > { "qualifiers" } } )
2008-07-09 06:04:10 -07:00
{
if ( /inherit/ )
{
2008-11-23 05:32:02 -08:00
my $ inheritStruct = $ struct - > { "qualifiers" } { "inherit" } ;
my $ inheritName = $ inheritStruct - > { "name" } ;
2008-07-09 06:04:10 -07:00
$$ output . = "\t\t/* BEGIN of inherited \"$inheritName\" definition */\n" ;
printRowProcessCode ( $ output , $ inheritStruct , $ structMap , $ enumMap ) ;
$$ output . = "\t\t/* END of inherited \"$inheritName\" definition */\n" ;
}
}
foreach my $ field ( @ { $ { $ struct } { "fields" } } )
{
printComments ( $ output , $ { $ field } { "comment" } , "\t\t" ) ;
2008-11-23 05:32:02 -08:00
my $ fieldName = $ field - > { "name" } ;
$ _ = $ field - > { "type" } ;
2008-07-09 06:04:10 -07:00
if ( /set/ )
{
2008-11-23 05:32:02 -08:00
my $ enum = $ field - > { "enum" } ;
2008-07-09 06:04:10 -07:00
2008-11-23 05:32:02 -08:00
for ( my $ i = 0 ; $ i < @ { $ enum - > { "values" } } ; $ i + + )
2008-07-09 06:04:10 -07:00
{
2008-11-23 05:32:02 -08:00
my $ value = $ enum - > { "values" } [ $ i ] ;
my $ valueName = $ value - > { "name" } ;
2008-07-09 06:04:10 -07:00
$$ output . = "\t\tstats->$fieldName\[$i] = sqlite3_column_int(stmt, cols.${fieldName}_${valueName}) ? true : false;\n" ;
}
}
elsif ( /count/ )
{
$$ output . = "\t\tstats->$fieldName = sqlite3_column_int(stmt, cols.$fieldName);\n" ;
}
2008-07-11 14:53:10 -07:00
elsif ( /([US]D?WORD|[US]BYTE)/ )
2008-07-11 08:30:32 -07:00
{
$$ output . = "\t\tstats->$fieldName = sqlite3_column_int(stmt, cols.$fieldName);\n" ;
}
2008-07-09 06:04:10 -07:00
elsif ( /real/ )
{
$$ output . = "\t\tstats->$fieldName = sqlite3_column_double(stmt, cols.$fieldName);\n" ;
}
elsif ( /bool/ )
{
$$ output . = "\t\tstats->$fieldName = sqlite3_column_int(stmt, cols.$fieldName) ? true : false;\n" ;
}
elsif ( /enum/ )
{
2008-11-23 05:32:02 -08:00
my $ enum = $ field - > { "enum" } ;
my $ enumSize = @ { $ enum - > { "values" } } ;
2008-07-09 06:04:10 -07:00
2008-11-23 05:32:02 -08:00
my $ valprefix = $ enum - > { "qualifiers" } { "valprefix" } || "" ;
my $ valsuffix = $ enum - > { "qualifiers" } { "valsuffix" } || "" ;
2008-11-15 17:20:02 -08:00
2008-11-23 05:32:02 -08:00
$ valprefix = "$enum->{name}_" if not exists ( $ enum - > { "qualifiers" } { "valprefix" } ) and not exists ( $ enum - > { "qualifiers" } { "valsuffix" } ) ;
2008-11-15 17:20:02 -08:00
for ( my $ i = 0 ; $ i < @ { $ { $ enum } { "values" } } ; $ i + + )
{
2008-11-23 05:32:02 -08:00
my $ value = $ enum - > { "values" } [ $ i ] ;
my $ valueName = $ value - > { "name" } ;
my @ strings = @ { $ value - > { "value_strings" } } ;
2008-11-16 09:25:40 -08:00
push @ strings , $ valueName unless @ strings ;
2008-11-15 17:20:02 -08:00
if ( $ i == 0 )
{
2008-11-16 08:28:17 -08:00
$$ output . = "\t\tif (" ;
2008-11-15 17:20:02 -08:00
}
else
{
2008-11-16 08:28:17 -08:00
$$ output . = "\t\telse if (" ;
2008-11-15 17:20:02 -08:00
}
2008-11-16 08:28:17 -08:00
my $ first = 1 ;
foreach my $ string ( @ strings )
2008-11-15 19:08:04 -08:00
{
2008-11-16 08:28:17 -08:00
$$ output . = "\n\t\t || " unless $ first ;
$ first = 0 ;
$$ output . = "strcmp((const char*)sqlite3_column_text(stmt, cols.$fieldName), \"$string\") == 0" ;
2008-11-15 19:08:04 -08:00
}
2008-11-16 08:28:17 -08:00
$$ output . = ")\n\t\t\tstats->$fieldName = $valprefix$valueName$valsuffix;\n" ;
2008-11-15 17:20:02 -08:00
}
$$ output . = "\t\telse\n"
. "\t\t{\n"
. "\t\t\tdebug(LOG_ERROR, \"Unknown enumerant (%s) for field $fieldName\", (const char*)sqlite3_column_text(stmt, cols.$fieldName));\n"
. "\t\t\tgoto in_statement_err;\n"
. "\t\t}\n"
2008-07-09 06:04:10 -07:00
}
elsif ( /string/ )
{
my $ indent = "\t\t" ;
2008-11-23 05:32:02 -08:00
if ( grep ( /optional/ , @ { $ field - > { "qualifiers" } } ) )
2008-07-09 06:04:10 -07:00
{
$ indent . = "\t" ;
2008-07-11 07:48:39 -07:00
$$ output . = "\t\tif (sqlite3_column_type(stmt, cols.$fieldName) != SQLITE_NULL)\n"
. "\t\t{\n" ;
2008-07-09 06:04:10 -07:00
}
2008-07-11 07:48:39 -07:00
$$ output . = "${indent}stats->$fieldName = strdup((const char*)sqlite3_column_text(stmt, cols.$fieldName));\n"
. "${indent}if (stats->$fieldName == NULL)\n"
. "${indent}{\n"
. "${indent}\tdebug(LOG_ERROR, \"Out of memory\");\n"
. "${indent}\tabort();\n"
. "${indent}\tgoto in_statement_err;\n"
. "${indent}}\n" ;
2008-07-09 06:04:10 -07:00
2008-11-23 05:32:02 -08:00
if ( grep ( /optional/ , @ { $ field - > { "qualifiers" } } ) )
2008-07-09 06:04:10 -07:00
{
2008-07-11 07:48:39 -07:00
$$ output . = "\t\t}\n"
. "\t\telse\n"
. "\t\t{\n"
. "\t\t\tstats->$fieldName = NULL;\n"
. "\t\t}\n" ;
2008-07-09 06:04:10 -07:00
}
}
elsif ( /IMD_model/ )
{
my $ indent = "\t\t" ;
2008-11-23 05:32:02 -08:00
if ( grep ( /optional/ , @ { $ field - > { "qualifiers" } } ) )
2008-07-09 06:04:10 -07:00
{
$ indent . = "\t" ;
$$ output . = "\t\tif (sqlite3_column_type(stmt, cols.$fieldName) != SQLITE_NULL)\n"
. "\t\t{\n" ;
}
2008-07-12 14:30:05 -07:00
$$ output . = "${indent}stats->$fieldName = (iIMDShape *) resGetData(\"IMD\", (const char*)sqlite3_column_text(stmt, cols.$fieldName));\n" ;
2008-11-23 05:32:02 -08:00
unless ( grep ( /optional/ , @ { $ field - > { "qualifiers" } } ) )
2008-07-12 14:30:05 -07:00
{
$$ output . = "${indent}if (stats->$fieldName == NULL)\n"
. "${indent}{\n"
. "${indent}\tdebug(LOG_ERROR, \"Cannot find the IMD for field \\\"$fieldName\\\" of record num %u\", (unsigned int)sqlite3_column_int(stmt, cols.unique_inheritance_id));\n"
. "${indent}\tabort();\n"
. "${indent}\tgoto in_statement_err;\n"
. "${indent}}\n" ;
}
2008-11-23 05:32:02 -08:00
if ( grep ( /optional/ , @ { $ field - > { "qualifiers" } } ) )
2008-07-12 14:30:05 -07:00
{
$$ output . = "\t\t}\n"
. "\t\telse\n"
. "\t\t{\n"
. "\t\t\tstats->$fieldName = NULL;\n"
. "\t\t}\n" ;
}
}
elsif ( /struct/ )
{
2008-11-23 05:32:02 -08:00
my $ struct = $ field - > { "struct" } ;
2008-07-12 14:30:05 -07:00
my $ indent = "\t\t" ;
2008-11-23 05:32:02 -08:00
if ( grep ( /optional/ , @ { $ field - > { "qualifiers" } } ) )
2008-07-12 14:30:05 -07:00
{
$ indent . = "\t" ;
$$ output . = "\t\tif (sqlite3_column_type(stmt, cols.$fieldName) != SQLITE_NULL)\n"
. "\t\t{\n" ;
}
2008-11-23 05:32:02 -08:00
die "error:$outfile:$field->{line}: Cannot use struct \"$struct->{name}\" as it doesn't have a fetchRowById function declared" unless exists ( $ struct - > { "qualifiers" } { "fetchRowById" } ) ;
2008-07-12 14:30:05 -07:00
2008-11-23 05:32:02 -08:00
$$ output . = "$indent\{\n" ;
2008-07-12 14:30:05 -07:00
2008-11-23 05:32:02 -08:00
my $ line = $ struct - > { "qualifiers" } { "fetchRowById" } { "line" } ;
2008-07-12 14:30:05 -07:00
$$ output . = "#line " . ( $ line + 1 ) . " \"$filename\"\n" ;
2008-11-23 05:32:02 -08:00
foreach ( @ { $ struct - > { "qualifiers" } { "fetchRowById" } { "code" } } )
2008-07-12 14:30:05 -07:00
{
s/^ //g ;
s/ /\t/g ;
s/\$Id\b/((unsigned int)sqlite3_column_int(stmt, cols.$fieldName))/g ;
s/\$Row\b/(stats->$fieldName)/g ;
s/\bABORT\b/goto in_statement_err/g ;
2008-11-23 05:32:02 -08:00
$$ output . = "$indent\t$_\n" ;
2008-07-12 14:30:05 -07:00
}
$ line = $$ output =~ s/\n/\n/sg ;
$ line += 2 ;
$$ output . = "#line $line \"$outfile\"\n" ;
2008-11-23 05:32:02 -08:00
$$ output . = "$indent}\n"
2008-07-12 14:30:05 -07:00
. "\n" ;
2008-11-23 05:32:02 -08:00
unless ( grep ( /optional/ , @ { $ field - > { "qualifiers" } } ) )
2008-07-12 14:30:05 -07:00
{
$$ output . = "${indent}if (stats->$fieldName == NULL)\n"
. "${indent}{\n"
. "${indent}\tdebug(LOG_ERROR, \"User code failed to retrieve struct instance for \\\"$fieldName\\\" with struct ID number %u\", (unsigned int)sqlite3_column_int(stmt, cols.$fieldName));\n"
. "${indent}\tabort();\n"
. "${indent}\tgoto in_statement_err;\n"
. "${indent}}\n" ;
}
2008-07-09 06:04:10 -07:00
2008-11-23 05:32:02 -08:00
if ( grep ( /optional/ , @ { $ field - > { "qualifiers" } } ) )
2008-07-09 06:04:10 -07:00
{
$$ output . = "\t\t}\n"
. "\t\telse\n"
. "\t\t{\n"
. "\t\t\tstats->$fieldName = NULL;\n"
. "\t\t}\n" ;
}
}
2008-07-09 13:47:17 -07:00
elsif ( /C-only-field/ )
{
# Ignore: this is a user defined field type, the user code (%postLoadRow) can deal with it
}
2008-07-09 06:04:10 -07:00
else
{
2008-11-23 05:32:02 -08:00
die "error:$filename:$field->{line}: UKNOWN TYPE: $_" ;
2008-07-09 06:04:10 -07:00
}
$$ output . = "\n" ;
}
}
sub printLoadFunc
{
my ( $ output , $ struct , $ structMap , $ enumMap ) = @ _ ;
2008-11-23 05:32:02 -08:00
return unless exists ( $ struct - > { "qualifiers" } { "loadFunc" } ) ;
2008-07-09 06:04:10 -07:00
my $ structName = "" ;
my $ prefix = "" ;
2008-07-10 14:11:24 -07:00
my $ suffix = "" ;
getStructName ( \ $ structName , $ struct , $ structMap , \ $ prefix , \ $ suffix ) ;
2008-07-09 06:04:10 -07:00
# Open the function
$$ output . = "\n" ;
printFuncHeader ( $ output , $ struct , $ structName ) ;
2008-07-09 07:47:16 -07:00
$$ output . = "{\n" ;
2008-07-09 06:04:10 -07:00
printSqlQueryVariables ( $ output , $ struct , $ structMap , $ enumMap ) ;
printPreLoadTableCode ( $ output , $ struct , $ structMap , $ enumMap ) ;
printStartSelectQuery ( $ output , $ structName , $ struct , $ structMap , $ enumMap ) ;
$$ output . = "\twhile (rc == SQLITE_ROW)\n"
. "\t{\n"
. "\t\t$structName sStats, * const stats = &sStats;\n"
. "\n"
. "\t\tmemset(stats, 0, sizeof(*stats));\n"
. "\n" ;
printRowProcessCode ( $ output , $ struct , $ structMap , $ enumMap ) ;
2008-11-23 05:32:02 -08:00
if ( exists ( $ struct - > { "qualifiers" } { "postLoadRow" } ) )
2008-07-09 06:04:10 -07:00
{
$$ output . = "\t\t{\n" ;
2008-11-23 05:32:02 -08:00
$$ output . = "\t\t\tconst int CUR_ROW_ID = sqlite3_column_int(stmt, cols.unique_inheritance_id);\n" if grep ( /curId/ , @ { $ struct - > { "qualifiers" } { "postLoadRow" } { "parameters" } } ) ;
2008-07-09 06:04:10 -07:00
$$ output . = "\n" ;
2008-11-23 05:32:02 -08:00
my $ line = $ struct - > { "qualifiers" } { "postLoadRow" } { "line" } ;
2008-07-09 08:25:46 -07:00
$$ output . = "#line " . ( $ line + 1 ) . " \"$filename\"\n" ;
2008-11-23 05:32:02 -08:00
foreach ( @ { $ struct - > { "qualifiers" } { "postLoadRow" } { "code" } } )
2008-07-09 06:04:10 -07:00
{
s/^ //g ;
s/ /\t/g ;
s/\$curId\b/CUR_ROW_ID/g ;
s/\$curRow\b/stats/g ;
2008-11-15 19:33:43 -08:00
s/\$rowNum\b/CUR_ROW_NUM/g ;
2008-07-09 06:04:10 -07:00
s/\bABORT\b/goto in_statement_err/g ;
2008-11-16 08:28:20 -08:00
$$ output . = "\t\t\t$_" if /\S/ ;
$$ output . = "\n" ;
2008-07-09 06:04:10 -07:00
}
2008-07-09 08:25:46 -07:00
$ line = $$ output =~ s/\n/\n/sg ;
$ line += 2 ;
$$ output . = "#line $line \"$outfile\"\n" ;
2008-07-09 06:04:10 -07:00
$$ output . = "\t\t}\n"
. "\n" ;
}
$$ output . = "\t\t/* Retrieve the next row */\n"
. "\t\trc = sqlite3_step(stmt);\n"
2008-11-15 19:33:43 -08:00
. "\t\t++CUR_ROW_NUM;\n"
2008-07-09 06:04:10 -07:00
. "\t}\n" ;
# Close the function
printFuncFooter ( $ output ) ;
$$ output . = "}\n" ;
}
sub printStruct ()
{
my ( $ output , $ struct , $ structMap , $ enumMap ) = @ _ ;
printLoadFunc ( $ output , $ struct , $ structMap , $ enumMap ) ;
}
my $ startTpl = "" ;
sub processCmdLine ()
{
my ( $ argv ) = @ _ ;
2008-07-09 06:49:49 -07:00
$ startTpl = shift ( @$ argv ) if @$ argv > 1 ;
2008-07-09 06:04:10 -07:00
}
sub startFile ()
{
2008-07-09 09:05:41 -07:00
my ( $ output , $ name , $ outputfile ) = @ _ ;
2008-07-09 06:04:10 -07:00
2008-07-10 13:44:14 -07:00
$$ output . = "/* This file is generated automatically, do not edit, change the source ($name) instead. */\n"
. "\n"
2008-09-16 13:21:50 -07:00
. "#include <sqlite3.h>\n"
2008-07-10 13:44:14 -07:00
. "\n" ;
2008-07-09 06:04:10 -07:00
2008-07-09 07:47:16 -07:00
$ filename = $ name ;
2008-07-09 09:05:41 -07:00
if ( $ outputfile )
{
$ outfile = $ outputfile ;
}
else
{
$ outfile = $ name ;
$ outfile =~ s/\.[^.]*$/.c/ ;
}
2008-07-09 07:47:16 -07:00
2008-07-09 06:49:49 -07:00
return unless $ startTpl ;
2008-07-09 06:04:10 -07:00
# Replace the extension with ".h" so that we can use it to #include the header
2008-07-09 09:05:41 -07:00
my $ header = $ outfile ;
2008-07-09 06:04:10 -07:00
$ header =~ s/\.[^.]*$/.h/ ;
2008-07-09 08:01:02 -07:00
$$ output . = "#line 1 \"$startTpl\"\n" ;
2008-07-09 06:04:10 -07:00
open ( TEMPL , $ startTpl ) ;
while ( <TEMPL> )
{
s/\$name\b/$name/g ;
s/\$header\b/$header/g ;
$$ output . = $ _ ;
}
close ( TEMPL ) ;
2008-07-09 08:01:02 -07:00
my $ count = $$ output =~ s/\n/\n/sg ;
$ count += 2 ;
$$ output . = "#line $count \"$outfile\"\n" ;
2008-07-09 06:04:10 -07:00
}
sub endFile ()
{
}
1 ;