#!/usr/bin/env python # # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # # # transform_sql.py -- create a header file with the appropriate SQL variables # from an SQL file # import os import re import sys DEFINE_END = ' ""\n\n' def usage_and_exit(msg): if msg: sys.stderr.write('%s\n\n' % msg) sys.stderr.write( 'USAGE: %s SQLITE_FILE [OUTPUT_FILE]\n' ' stdout will be used if OUTPUT_FILE is not provided.\n' % os.path.basename(sys.argv[0])) sys.stderr.flush() sys.exit(1) def main(input, output, filename): input = input.read() var_name = re.sub('[-.]', '_', filename).upper() output.write( '/* This file is automatically generated from %s.\n' ' * Do not edit this file -- edit the source and rerun gen-make.py */\n' '\n' % (filename,)) var_printed = False stmt_count = 0 # only used once, but we need the flags. so re.compile it is! re_comments = re.compile(r'/\*.*?\*/', re.MULTILINE|re.DOTALL) input = re_comments.sub('', input) # a couple SQL comments that act as directives for this transform system re_format = re.compile('-- *format: *([0-9]+)') re_statement = re.compile('-- *STMT_([A-Z_]+)') for line in input.split('\n'): line = line.replace('"', '\\"') if line.strip(): match = re_format.match(line) if match: vsn = match.group(1) if var_printed: # end the previous #define output.write(DEFINE_END) output.write('#define %s_%s \\\n' % (var_name, match.group(1))) var_printed = True # no need to put the directive into the file. skip this line. continue match = re_statement.match(line) if match: name = match.group(1) if var_printed: # end the previous #define output.write(DEFINE_END) output.write('#define STMT_%s %d\n' % (match.group(1), stmt_count)) output.write('#define STMT_%d \\\n' % (stmt_count,)) var_printed = True stmt_count += 1 # no need to put the directive into the file. skip this line. continue if not var_printed: output.write('#define %s \\\n' % var_name) var_printed = True # got something besides whitespace. write it out. include some whitespace # to separate the SQL commands. and a backslash to continue the string # onto the next line. output.write(' "%s " \\\n' % line) # previous line had a continuation. end the madness. assert var_printed output.write(DEFINE_END) ### the STMT_%d naming precludes *multiple* transform_sql headers from ### being used within the same .c file. for now, that's more than fine. ### in the future, we can always add a var_name discriminator or use ### the statement name itself (which should hopefully be unique across ### all names in use; or can easily be made so) if stmt_count > 0: output.write('#define %s_DECLARE_STATEMENTS(varname) \\\n' % (var_name,) + ' static const char * const varname[] = { \\\n' + ', \\\n'.join(' STMT_%d' % (i,) for i in range(stmt_count)) + ' \\\n }\n') if __name__ == '__main__': if len(sys.argv) < 2 or len(sys.argv) > 3: usage_and_exit('Incorrect number of arguments') # Note: we could use stdin, but then we'd have no var_name input_file = open(sys.argv[1], 'r') if len(sys.argv) > 2: output_file = open(sys.argv[2], 'w') else: output_file = sys.stdout main(input_file, output_file, os.path.basename(sys.argv[1]))