mirror of
https://github.com/Z3Prover/z3
synced 2025-04-24 01:25:31 +00:00
Integrated structured branch into unstable branch (the official 'working in progress' branch)
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
commit
3da69a4f1b
1502 changed files with 2524 additions and 5113 deletions
14
scripts/config-debug.mk.in
Normal file
14
scripts/config-debug.mk.in
Normal file
|
@ -0,0 +1,14 @@
|
|||
|
||||
|
||||
CXX=@CXX@
|
||||
CXXFLAGS=@CPPFLAGS@ @CXXFLAGS@ -c -g -Wall -fopenmp -msse -msse2 -mfpmath=sse -fPIC
|
||||
CXX_OUT_FLAG=-o
|
||||
OBJ_EXT=.o
|
||||
LIB_EXT=.a
|
||||
AR=@AR@
|
||||
AR_FLAGS=rcs
|
||||
AR_OUTFLAG=
|
||||
EXE_EXT=
|
||||
LINK=@CXX@
|
||||
LINK_FLAGS=-lpthread -fopenmp
|
||||
LINK_OUT_FLAG=-o
|
14
scripts/config-release.mk.in
Normal file
14
scripts/config-release.mk.in
Normal file
|
@ -0,0 +1,14 @@
|
|||
|
||||
|
||||
CXX=@CXX@
|
||||
CXXFLAGS=@CPPFLAGS@ @CXXFLAGS@ -c -O3 -fomit-frame-pointer -Wall -fopenmp -msse -msse2 -mfpmath=sse -fPIC
|
||||
CXX_OUT_FLAG=-o
|
||||
OBJ_EXT=.o
|
||||
LIB_EXT=.a
|
||||
AR=@AR@
|
||||
AR_FLAGS=rcs
|
||||
AR_OUTFLAG=
|
||||
EXE_EXT=
|
||||
LINK=@CXX@
|
||||
LINK_FLAGS=-lpthread -fopenmp
|
||||
LINK_OUT_FLAG=-o
|
15
scripts/config-vs-debug.mk
Normal file
15
scripts/config-vs-debug.mk
Normal file
|
@ -0,0 +1,15 @@
|
|||
CXX=cl
|
||||
CXXFLAGS=/c /ZI /nologo /W3 /WX- /Od /Oy- /D "WIN32" /D "_DEBUG" /D "Z3DEBUG" /D "_CONSOLE" /D "_TRACE" /D "_WINDOWS" /Gm /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /openmp /Gd /analyze-
|
||||
CXX_OUT_FLAG=/Fo
|
||||
OBJ_EXT=.obj
|
||||
LIB_EXT=.lib
|
||||
AR=lib
|
||||
AR_FLAGS=/nologo
|
||||
AR_OUTFLAG=/OUT:
|
||||
EXE_EXT=.exe
|
||||
LINK=cl
|
||||
LINK_FLAGS=/nologo /MDd
|
||||
LINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X86 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:"8388608" /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT
|
||||
LINK_OUT_FLAG=/Fe
|
||||
|
||||
|
15
scripts/config-vs-release.mk
Normal file
15
scripts/config-vs-release.mk
Normal file
|
@ -0,0 +1,15 @@
|
|||
CXX=cl
|
||||
CXXFLAGS=/nologo /c /W3 /WX- /O2 /Oy- /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_WINDOWS" /D "ASYNC_COMMANDS" /Gm- /EHsc /GS /fp:precise /Zc:wchar_t /Zc:forScope /openmp /Gd /analyze-
|
||||
CXX_OUT_FLAG=/Fo
|
||||
OBJ_EXT=.obj
|
||||
LIB_EXT=.lib
|
||||
AR=lib
|
||||
AR_FLAGS=/nologo
|
||||
AR_OUTFLAG=/OUT:
|
||||
EXE_EXT=.exe
|
||||
LINK=cl
|
||||
LINK_FLAGS=/nologo /MD
|
||||
LINK_EXTRA_FLAGS=/link /MACHINE:X86 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:"8388608" /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT
|
||||
LINK_OUT_FLAG=/Fe
|
||||
|
||||
|
12
scripts/mk_exception.py
Normal file
12
scripts/mk_exception.py
Normal file
|
@ -0,0 +1,12 @@
|
|||
############################################
|
||||
# Copyright (c) 2012 Microsoft Corporation
|
||||
#
|
||||
# Author: Leonardo de Moura (leonardo)
|
||||
############################################
|
||||
|
||||
class MKException(Exception):
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
def __str__(self):
|
||||
return repr(self.value)
|
||||
|
85
scripts/mk_make.py
Normal file
85
scripts/mk_make.py
Normal file
|
@ -0,0 +1,85 @@
|
|||
############################################
|
||||
# Copyright (c) 2012 Microsoft Corporation
|
||||
#
|
||||
# Scripts for generating Makefiles and Visual
|
||||
# Studio project files.
|
||||
#
|
||||
# Author: Leonardo de Moura (leonardo)
|
||||
############################################
|
||||
from mk_util import *
|
||||
|
||||
parse_options()
|
||||
|
||||
# set_build_dir('build')
|
||||
# set_src_dir('src')
|
||||
# set_modes(['Debug', 'Release'])
|
||||
# set_platforms(['Win32', 'x64'])
|
||||
# set_vs_options('WIN32;_WINDOWS;ASYNC_COMMANDS',
|
||||
# 'Z3DEBUG;_TRACE;_DEBUG',
|
||||
# 'NDEBUG;_EXTERNAL_RELEASE')
|
||||
|
||||
add_lib('util', [])
|
||||
add_lib('polynomial', ['util'], 'math/polynomial')
|
||||
add_lib('sat', ['util'])
|
||||
# nlsat only reuses the file sat_types.h from sat
|
||||
add_lib('nlsat', ['polynomial', 'sat'])
|
||||
add_lib('subpaving', ['util'], 'math/subpaving')
|
||||
add_lib('ast', ['util', 'polynomial'])
|
||||
add_lib('rewriter', ['ast', 'polynomial'], 'ast/rewriter')
|
||||
# array_property is only used in test exe
|
||||
add_lib('array_property', ['ast', 'rewriter'], 'ast/array_property')
|
||||
# Simplifier module will be deleted in the future.
|
||||
# It has been replaced with rewriter module.
|
||||
add_lib('simplifier', ['rewriter'], 'ast/simplifier')
|
||||
# Model module should not depend on simplifier module.
|
||||
# We must replace all occurrences of simplifier with rewriter.
|
||||
add_lib('model', ['rewriter', 'simplifier'])
|
||||
add_lib('tactic', ['ast', 'model'])
|
||||
# Old (non-modular) parameter framework. It has been subsumed by util\params.h.
|
||||
# However, it is still used by many old components.
|
||||
add_lib('old_params', ['model', 'simplifier'])
|
||||
add_lib('cmd_context', ['tactic', 'rewriter', 'model', 'old_params', 'simplifier'])
|
||||
# Assertion set is the old tactic framework used in Z3 3.x. It will be deleted as soon as we finish the porting old
|
||||
# code to the new tactic framework.
|
||||
add_lib('assertion_set', ['cmd_context'])
|
||||
add_lib('substitution', ['ast'], 'ast/substitution')
|
||||
add_lib('normal_forms', ['tactic', 'assertion_set'])
|
||||
add_lib('pattern', ['normal_forms'], 'ast/pattern')
|
||||
add_lib('spc', ['simplifier', 'substitution', 'old_params', 'pattern'])
|
||||
add_lib('parser_util', ['ast'])
|
||||
add_lib('smt2parser', ['cmd_context', 'parser_util'])
|
||||
add_lib('macros', ['simplifier', 'old_params'], 'ast/macros')
|
||||
add_lib('grobner', ['ast'], 'math/grobner')
|
||||
add_lib('euclid', ['util'], 'math/euclid')
|
||||
add_lib('proof_checker', ['rewriter', 'spc'], 'ast/proof_checker')
|
||||
add_lib('bit_blaster', ['rewriter', 'simplifier', 'old_params', 'tactic', 'assertion_set'], 'tactic/bit_blaster')
|
||||
add_lib('smt', ['assertion_set', 'bit_blaster', 'macros', 'normal_forms', 'cmd_context',
|
||||
'substitution', 'grobner', 'euclid', 'proof_checker', 'pattern', 'parser_util'])
|
||||
add_lib('user_plugin', ['smt'], 'smt/user_plugin')
|
||||
add_lib('core_tactics', ['tactic', 'normal_forms'], 'tactic/core_tactics')
|
||||
add_lib('sat_tactic', ['tactic', 'sat'], 'tactic/sat_tactic')
|
||||
add_lib('sat_strategy', ['assertion_set', 'sat_tactic'], 'assertion_set/sat_strategy')
|
||||
add_lib('arith_tactics', ['core_tactics', 'assertion_set', 'sat', 'sat_strategy'], 'tactic/arith_tactics')
|
||||
add_lib('nlsat_tactic', ['nlsat', 'sat_tactic', 'arith_tactics'], 'tactic/nlsat_tactic')
|
||||
add_lib('subpaving_tactic', ['core_tactics', 'subpaving'], 'math/subpaving/tactic')
|
||||
add_lib('bv_tactics', ['tactic', 'bit_blaster'], 'tactic/bv_tactics')
|
||||
add_lib('fuzzing', ['ast'], 'test/fuzzing')
|
||||
add_lib('fpa', ['core_tactics', 'bv_tactics', 'sat_tactic'], 'tactic/fpa')
|
||||
add_lib('smt_tactic', ['smt'], 'smt/tactic')
|
||||
add_lib('extra_cmds', ['cmd_context', 'subpaving_tactic', 'arith_tactics'], 'cmd_context/extra_cmds')
|
||||
add_lib('sls_tactic', ['tactic', 'normal_forms', 'core_tactics', 'bv_tactics'], 'tactic/sls_tactic')
|
||||
add_lib('aig', ['cmd_context', 'assertion_set'], 'tactic/aig')
|
||||
# TODO: split muz_qe into muz, qe. Perhaps, we should also consider breaking muz into muz and pdr.
|
||||
add_lib('muz_qe', ['smt', 'sat', 'smt2parser'])
|
||||
add_lib('smtlogic_tactics', ['arith_tactics', 'bv_tactics', 'nlsat_tactic', 'smt_tactic', 'aig', 'muz_qe'], 'tactic/smtlogic_tactics')
|
||||
# TODO: rewrite ufbv_strategy as a tactic and move to smtlogic_tactics.
|
||||
add_lib('ufbv_tactic', ['normal_forms', 'core_tactics', 'macros', 'smt_tactic', 'rewriter'], 'tactic/ufbv_tactic')
|
||||
add_lib('portfolio', ['smtlogic_tactics', 'ufbv_tactic', 'fpa', 'aig', 'muz_qe', 'sls_tactic', 'subpaving_tactic'], 'tactic/portfolio')
|
||||
# TODO: delete SMT 1.0 frontend
|
||||
add_lib('api', ['portfolio', 'user_plugin'])
|
||||
add_exe('shell', ['api', 'sat', 'extra_cmds'], exe_name='z3')
|
||||
add_exe('test', ['api', 'fuzzing', 'array_property'], exe_name='test-z3')
|
||||
|
||||
# mk_vs_solution()
|
||||
|
||||
mk_makefile()
|
370
scripts/mk_util.py
Normal file
370
scripts/mk_util.py
Normal file
|
@ -0,0 +1,370 @@
|
|||
############################################
|
||||
# Copyright (c) 2012 Microsoft Corporation
|
||||
#
|
||||
# Auxiliary scripts for generating Makefiles
|
||||
# and Visual Studio project files.
|
||||
#
|
||||
# Author: Leonardo de Moura (leonardo)
|
||||
############################################
|
||||
import os
|
||||
import glob
|
||||
import sets
|
||||
import re
|
||||
import getopt
|
||||
import sys
|
||||
import shutil
|
||||
from mk_exception import *
|
||||
|
||||
BUILD_DIR='build'
|
||||
REV_BUILD_DIR='..'
|
||||
SRC_DIR='src'
|
||||
IS_WINDOW=False
|
||||
VERBOSE=False
|
||||
DEBUG_MODE=False
|
||||
SHOW_CPPS = True
|
||||
VS_X64 = False
|
||||
|
||||
LIB_KIND = 0
|
||||
EXE_KIND = 1
|
||||
|
||||
if os.name == 'nt':
|
||||
IS_WINDOW=True
|
||||
# Visual Studio already displays the files being compiled
|
||||
SHOW_CPPS=False
|
||||
|
||||
def display_help():
|
||||
print "mk_make.py: Z3 Makefile generator\n"
|
||||
print "This script generates the Makefile for the Z3 theorem prover."
|
||||
print "It must be executed from the Z3 root directory."
|
||||
print "\nOptions:"
|
||||
print " -h, --help display this message"
|
||||
print " -v, --verbose be verbose"
|
||||
print " -b <sudir>, --build=<subdir> subdirectory where Z3 will be built (default: build)."
|
||||
print " -d, --debug compile Z3 in debug mode."
|
||||
print " -x, --x64 create 64 binary when using Visual Studio."
|
||||
exit(0)
|
||||
|
||||
# Parse configuration option for mk_make script
|
||||
def parse_options():
|
||||
global VERBOSE, DEBUG_MODE, IS_WINDOW, VS_X64
|
||||
options, remainder = getopt.gnu_getopt(sys.argv[1:], 'b:dvxh', ['build=',
|
||||
'debug',
|
||||
'verbose',
|
||||
'x64',
|
||||
'help'
|
||||
])
|
||||
for opt, arg in options:
|
||||
if opt in ('-b', '--build'):
|
||||
if arg == 'src':
|
||||
raise MKException('The src directory should not be used to host the Makefile')
|
||||
set_build_dir(arg)
|
||||
elif opt in ('-v', '--verbose'):
|
||||
VERBOSE = True
|
||||
elif opt in ('-d', '--debug'):
|
||||
DEBUG_MODE = True
|
||||
elif opt in ('-x', '--x64'):
|
||||
if not IS_WINDOW:
|
||||
raise MKException('x64 compilation mode can only be specified when using Visual Studio')
|
||||
VS_X64 = True
|
||||
elif opt in ('-h', '--help'):
|
||||
display_help()
|
||||
else:
|
||||
raise MKException("Invalid command line option '%s'" % opt)
|
||||
|
||||
# Return a list containing a file names included using '#include' in
|
||||
# the given C/C++ file named fname.
|
||||
def extract_c_includes(fname):
|
||||
result = []
|
||||
# We look for well behaved #include directives
|
||||
std_inc_pat = re.compile("[ \t]*#include[ \t]*\"(.*)\"[ \t]*")
|
||||
system_inc_pat = re.compile("[ \t]*#include[ \t]*\<.*\>[ \t]*")
|
||||
# We should generate and error for any occurrence of #include that does not match the previous pattern.
|
||||
non_std_inc_pat = re.compile(".*#include.*")
|
||||
|
||||
f = open(fname, 'r')
|
||||
linenum = 1
|
||||
for line in f:
|
||||
m1 = std_inc_pat.match(line)
|
||||
if m1:
|
||||
result.append(m1.group(1))
|
||||
elif not system_inc_pat.match(line) and non_std_inc_pat.match(line):
|
||||
raise MKException("Invalid #include directive at '%s':%s" % (fname, line))
|
||||
linenum = linenum + 1
|
||||
return result
|
||||
|
||||
|
||||
# Given a path dir1/subdir2/subdir3 returns ../../..
|
||||
def reverse_path(p):
|
||||
l = p.split('/')
|
||||
n = len(l)
|
||||
r = '..'
|
||||
for i in range(1, n):
|
||||
r = '%s/%s' % (r, '..')
|
||||
return r
|
||||
|
||||
def mk_dir(d):
|
||||
if not os.path.exists(d):
|
||||
os.makedirs(d)
|
||||
|
||||
def set_build_dir(d):
|
||||
global BUILD_DIR, REV_BUILD_DIR
|
||||
BUILD_DIR = d
|
||||
REV_BUILD_DIR = reverse_path(d)
|
||||
|
||||
_UNIQ_ID = 0
|
||||
|
||||
def mk_fresh_name(prefix):
|
||||
global _UNIQ_ID
|
||||
r = '%s_%s' % (prefix, _UNIQ_ID)
|
||||
_UNIQ_ID = _UNIQ_ID + 1
|
||||
return r
|
||||
|
||||
_Id = 0
|
||||
_Components = []
|
||||
_ComponentNames = sets.Set()
|
||||
_Name2Component = {}
|
||||
_Processed_Headers = sets.Set()
|
||||
|
||||
def get_cpp_files(path):
|
||||
return filter(lambda f: f.endswith('.cpp'), os.listdir(path))
|
||||
|
||||
def find_all_deps(name, deps):
|
||||
new_deps = []
|
||||
for dep in deps:
|
||||
if dep in _ComponentNames:
|
||||
if not (dep in new_deps):
|
||||
new_deps.append(dep)
|
||||
for dep_dep in _Name2Component[dep].deps:
|
||||
if not (dep_dep in new_deps):
|
||||
new_deps.append(dep_dep)
|
||||
else:
|
||||
raise MKException("Unknown component '%s' at '%s'." % (dep, name))
|
||||
return new_deps
|
||||
|
||||
class Component:
|
||||
def __init__(self, name, kind, path, deps):
|
||||
global BUILD_DIR, SRC_DIR, REV_BUILD_DIR
|
||||
if name in _ComponentNames:
|
||||
raise MKException("Component '%s' was already defined." % name)
|
||||
if path == None:
|
||||
path = name
|
||||
self.kind = kind
|
||||
self.name = name
|
||||
self.path = path
|
||||
self.deps = find_all_deps(name, deps)
|
||||
self.build_dir = path
|
||||
self.src_dir = '%s/%s' % (SRC_DIR, path)
|
||||
self.to_src_dir = '%s/%s' % (REV_BUILD_DIR, self.src_dir)
|
||||
|
||||
# Find fname in the include paths for the given component.
|
||||
# ownerfile is only used for creating error messages.
|
||||
# That is, we were looking for fname when processing ownerfile
|
||||
def find_file(self, fname, ownerfile):
|
||||
global _Name2Component
|
||||
full_fname = '%s/%s' % (self.src_dir, fname)
|
||||
if os.path.exists(full_fname):
|
||||
return self
|
||||
for dep in self.deps:
|
||||
c_dep = _Name2Component[dep]
|
||||
full_fname = '%s/%s' % (c_dep.src_dir, fname)
|
||||
if os.path.exists(full_fname):
|
||||
return c_dep
|
||||
raise MKException("Failed to find include file '%s' for '%s' when processing '%s'." % (fname, ownerfile, self.name))
|
||||
|
||||
# Display all dependencies of file basename located in the given component directory.
|
||||
# The result is displayed at out
|
||||
def add_cpp_h_deps(self, out, basename):
|
||||
includes = extract_c_includes('%s/%s' % (self.src_dir, basename))
|
||||
out.write('%s/%s' % (self.to_src_dir, basename))
|
||||
for include in includes:
|
||||
owner = self.find_file(include, basename)
|
||||
out.write(' %s/%s.node' % (owner.build_dir, include))
|
||||
|
||||
# Add a rule for each #include directive in the file basename located at the current component.
|
||||
def add_rule_for_each_include(self, out, basename):
|
||||
fullname = '%s/%s' % (self.src_dir, basename)
|
||||
includes = extract_c_includes(fullname)
|
||||
for include in includes:
|
||||
owner = self.find_file(include, fullname)
|
||||
owner.add_h_rule(out, include)
|
||||
|
||||
# Display a Makefile rule for an include file located in the given component directory.
|
||||
# 'include' is something of the form: ast.h, polynomial.h
|
||||
# The rule displayed at out is of the form
|
||||
# ast/ast_pp.h.node : ../src/util/ast_pp.h util/util.h.node ast/ast.h.node
|
||||
# @echo "done" > ast/ast_pp.h.node
|
||||
def add_h_rule(self, out, include):
|
||||
include_src_path = '%s/%s' % (self.to_src_dir, include)
|
||||
if include_src_path in _Processed_Headers:
|
||||
return
|
||||
_Processed_Headers.add(include_src_path)
|
||||
self.add_rule_for_each_include(out, include)
|
||||
include_node = '%s/%s.node' % (self.build_dir, include)
|
||||
out.write('%s: ' % include_node)
|
||||
self.add_cpp_h_deps(out, include)
|
||||
out.write('\n')
|
||||
out.write('\t@echo done > %s\n' % include_node)
|
||||
|
||||
def add_cpp_rules(self, out, include_defs, cppfile):
|
||||
self.add_rule_for_each_include(out, cppfile)
|
||||
objfile = '%s/%s$(OBJ_EXT)' % (self.build_dir, os.path.splitext(cppfile)[0])
|
||||
srcfile = '%s/%s' % (self.to_src_dir, cppfile)
|
||||
out.write('%s: ' % objfile)
|
||||
self.add_cpp_h_deps(out, cppfile)
|
||||
out.write('\n')
|
||||
if SHOW_CPPS:
|
||||
out.write('\t@echo %s/%s\n' % (self.src_dir, cppfile))
|
||||
out.write('\t@$(CXX) $(CXXFLAGS) $(%s) $(CXX_OUT_FLAG)%s %s\n' % (include_defs, objfile, srcfile))
|
||||
|
||||
def mk_makefile(self, out):
|
||||
include_defs = mk_fresh_name('includes')
|
||||
out.write('%s =' % include_defs)
|
||||
for dep in self.deps:
|
||||
out.write(' -I%s' % _Name2Component[dep].to_src_dir)
|
||||
out.write('\n')
|
||||
mk_dir('%s/%s' % (BUILD_DIR, self.build_dir))
|
||||
for cppfile in get_cpp_files(self.src_dir):
|
||||
self.add_cpp_rules(out, include_defs, cppfile)
|
||||
|
||||
# Return true if the component should be included in the all: rule
|
||||
def main_component(self):
|
||||
return False
|
||||
|
||||
class LibComponent(Component):
|
||||
def __init__(self, name, path, deps):
|
||||
Component.__init__(self, name, LIB_KIND, path, deps)
|
||||
|
||||
def mk_makefile(self, out):
|
||||
Component.mk_makefile(self, out)
|
||||
# generate rule for lib
|
||||
objs = []
|
||||
for cppfile in get_cpp_files(self.src_dir):
|
||||
objfile = '%s/%s$(OBJ_EXT)' % (self.build_dir, os.path.splitext(cppfile)[0])
|
||||
objs.append(objfile)
|
||||
|
||||
libfile = '%s/%s$(LIB_EXT)' % (self.build_dir, self.name)
|
||||
out.write('%s:' % libfile)
|
||||
for obj in objs:
|
||||
out.write(' ')
|
||||
out.write(obj)
|
||||
out.write('\n')
|
||||
out.write('\t@$(AR) $(AR_FLAGS) $(AR_OUTFLAG)%s' % libfile)
|
||||
for obj in objs:
|
||||
out.write(' ')
|
||||
out.write(obj)
|
||||
out.write('\n')
|
||||
out.write('%s: %s\n\n' % (self.name, libfile))
|
||||
|
||||
# Auxiliary function for sort_components
|
||||
def comp_components(c1, c2):
|
||||
id1 = _Name2Component[c1].id
|
||||
id2 = _Name2Component[c2].id
|
||||
return id2 - id1
|
||||
|
||||
# Sort components based on (reverse) definition time
|
||||
def sort_components(cnames):
|
||||
return sorted(cnames, cmp=comp_components)
|
||||
|
||||
class ExeComponent(Component):
|
||||
def __init__(self, name, exe_name, path, deps):
|
||||
Component.__init__(self, name, EXE_KIND, path, deps)
|
||||
if exe_name == None:
|
||||
exe_name = name
|
||||
self.exe_name = exe_name
|
||||
|
||||
def mk_makefile(self, out):
|
||||
global _Name2Component
|
||||
Component.mk_makefile(self, out)
|
||||
# generate rule for exe
|
||||
|
||||
exefile = '%s$(EXE_EXT)' % self.exe_name
|
||||
out.write('%s:' % exefile)
|
||||
deps = sort_components(self.deps)
|
||||
objs = []
|
||||
for cppfile in get_cpp_files(self.src_dir):
|
||||
objfile = '%s/%s$(OBJ_EXT)' % (self.build_dir, os.path.splitext(cppfile)[0])
|
||||
objs.append(objfile)
|
||||
for obj in objs:
|
||||
out.write(' ')
|
||||
out.write(obj)
|
||||
for dep in deps:
|
||||
c_dep = _Name2Component[dep]
|
||||
out.write(' %s/%s$(LIB_EXT)' % (c_dep.build_dir, c_dep.name))
|
||||
out.write('\n')
|
||||
out.write('\t$(LINK) $(LINK_OUT_FLAG)%s $(LINK_FLAGS)' % exefile)
|
||||
for obj in objs:
|
||||
out.write(' ')
|
||||
out.write(obj)
|
||||
for dep in deps:
|
||||
c_dep = _Name2Component[dep]
|
||||
out.write(' %s/%s$(LIB_EXT)' % (c_dep.build_dir, c_dep.name))
|
||||
out.write(' $(LINK_EXTRA_FLAGS)\n')
|
||||
out.write('%s: %s\n\n' % (self.name, exefile))
|
||||
|
||||
# All executables are included in the all: rule
|
||||
def main_component(self):
|
||||
return True
|
||||
|
||||
def reg_component(name, c):
|
||||
global _Id, _Components, _ComponentNames, _Name2Component
|
||||
c.id = _Id
|
||||
_Id = _Id + 1
|
||||
_Components.append(c)
|
||||
_ComponentNames.add(name)
|
||||
_Name2Component[name] = c
|
||||
if VERBOSE:
|
||||
print "Processed '%s'" % name
|
||||
|
||||
def add_lib(name, deps=[], path=None):
|
||||
c = LibComponent(name, path, deps)
|
||||
reg_component(name, c)
|
||||
|
||||
def add_exe(name, deps=[], path=None, exe_name=None):
|
||||
c = ExeComponent(name, exe_name, path, deps)
|
||||
reg_component(name, c)
|
||||
|
||||
# Copy configuration correct file to BUILD_DIR
|
||||
def cp_config_mk():
|
||||
if IS_WINDOW:
|
||||
if VS_X64:
|
||||
# TODO
|
||||
return
|
||||
else:
|
||||
if DEBUG_MODE:
|
||||
shutil.copyfile('scripts/config-vs-debug.mk', '%s/config.mk' % BUILD_DIR)
|
||||
else:
|
||||
shutil.copyfile('scripts/config-vs-release.mk', '%s/config.mk' % BUILD_DIR)
|
||||
else:
|
||||
if DEBUG_MODE:
|
||||
shutil.copyfile('scripts/config-debug.mk', '%s/config.mk' % BUILD_DIR)
|
||||
else:
|
||||
shutil.copyfile('scripts/config-release.mk', '%s/config.mk' % BUILD_DIR)
|
||||
|
||||
# Generate the Z3 makefile
|
||||
def mk_makefile():
|
||||
mk_dir(BUILD_DIR)
|
||||
cp_config_mk()
|
||||
if VERBOSE:
|
||||
print "Writing %s/Makefile" % BUILD_DIR
|
||||
out = open('%s/Makefile' % BUILD_DIR, 'w')
|
||||
out.write('# Automatically generated file. Generator: scripts/mk_make.py\n')
|
||||
out.write('include config.mk\n')
|
||||
# Generate :all rule
|
||||
out.write('all:')
|
||||
for c in _Components:
|
||||
if c.main_component:
|
||||
out.write(' %s' % c.name)
|
||||
out.write('\n\n')
|
||||
# Generate components
|
||||
for c in _Components:
|
||||
c.mk_makefile(out)
|
||||
# Finalize
|
||||
if VERBOSE:
|
||||
print "Makefile was successfully generated."
|
||||
if DEBUG_MODE:
|
||||
print " compilation mode: Debug"
|
||||
else:
|
||||
print " compilation mode: Release"
|
||||
print "Type 'cd %s; make' to build Z3" % BUILD_DIR
|
||||
|
||||
|
308
scripts/mk_util_old.py
Normal file
308
scripts/mk_util_old.py
Normal file
|
@ -0,0 +1,308 @@
|
|||
############################################
|
||||
# Copyright (c) 2012 Microsoft Corporation
|
||||
#
|
||||
# Auxiliary scripts for generating Makefiles
|
||||
# and Visual Studio project files.
|
||||
#
|
||||
# Author: Leonardo de Moura (leonardo)
|
||||
############################################
|
||||
import os
|
||||
import glob
|
||||
|
||||
BUILD_DIR='build'
|
||||
SRC_DIR='src'
|
||||
MODES=[]
|
||||
PLATFORMS=[]
|
||||
|
||||
class MKException(Exception):
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
def __str__(self):
|
||||
return repr(self.value)
|
||||
|
||||
def set_build_dir(d):
|
||||
global BUILD_DIR
|
||||
BUILD_DIR = d
|
||||
mk_dir(BUILD_DIR)
|
||||
|
||||
def set_src_dir(d):
|
||||
global SRC_DIR
|
||||
SRC_DIR = d
|
||||
|
||||
def set_modes(l):
|
||||
global MODES
|
||||
MODES=l
|
||||
|
||||
def set_platforms(l):
|
||||
global PLATFORMS
|
||||
PLATFORMS=l
|
||||
|
||||
VS_COMMON_OPTIONS='WIN32'
|
||||
VS_DBG_OPTIONS='_DEBUG'
|
||||
VS_RELEASE_OPTIONS='NDEBUG'
|
||||
|
||||
GUI = 0
|
||||
Name2GUI = {}
|
||||
|
||||
def mk_gui_str(id):
|
||||
return '4D2F40D8-E5F9-473B-B548-%012d' % id
|
||||
|
||||
MODULES = []
|
||||
HEADERS = []
|
||||
LIBS = []
|
||||
EXES = []
|
||||
DEPS = {}
|
||||
|
||||
def set_vs_options(common, dbg, release):
|
||||
global VS_COMMON_OPTIONS, VS_DBG_OPTIONS, VS_RELEASE_OPTIONS
|
||||
VS_COMMON_OPTIONS = common
|
||||
VS_DBG_OPTIONS = dbg
|
||||
VS_RELEASE_OPTIONS = release
|
||||
|
||||
def is_debug(mode):
|
||||
return mode == 'Debug'
|
||||
|
||||
def is_x64(platform):
|
||||
return platform == 'x64'
|
||||
|
||||
def mk_dir(d):
|
||||
if not os.path.exists(d):
|
||||
os.makedirs(d)
|
||||
|
||||
def module_src_dir(name):
|
||||
return '%s%s%s' % (SRC_DIR, os.sep, name)
|
||||
|
||||
def module_build_dir(name):
|
||||
return '%s%s%s' % (BUILD_DIR, os.sep, name)
|
||||
|
||||
LIB_KIND = 0
|
||||
EXE_KIND = 1
|
||||
|
||||
def get_extension(kind):
|
||||
if kind == LIB_KIND:
|
||||
return 'lib'
|
||||
elif kind == EXE_KIND:
|
||||
return 'exe'
|
||||
else:
|
||||
raise MKException('unknown kind %s' % kind)
|
||||
|
||||
def vs_header(f):
|
||||
f.write(
|
||||
'<?xml version="1.0" encoding="utf-8"?>\n'
|
||||
'<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\n')
|
||||
|
||||
def vs_project_configurations(f, name):
|
||||
global GUI, Name2GUI
|
||||
f.write(' <ItemGroup Label="ProjectConfigurations">\n')
|
||||
for mode in MODES:
|
||||
for platform in PLATFORMS:
|
||||
f.write(' <ProjectConfiguration Include="%s|%s">\n' % (mode, platform))
|
||||
f.write(' <Configuration>%s</Configuration>\n' % mode)
|
||||
f.write(' <Platform>%s</Platform>\n' % platform)
|
||||
f.write(' </ProjectConfiguration>\n')
|
||||
f.write(' </ItemGroup>\n')
|
||||
|
||||
f.write(' <PropertyGroup Label="Globals">\n')
|
||||
f.write(' <ProjectGuid>{%s}</ProjectGuid>\n' % mk_gui_str(GUI))
|
||||
f.write(' <ProjectName>%s</ProjectName>\n' % name)
|
||||
f.write(' <Keyword>Win32Proj</Keyword>\n')
|
||||
f.write(' </PropertyGroup>\n')
|
||||
f.write(' <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\n')
|
||||
Name2GUI[name] = GUI
|
||||
GUI = GUI + 1
|
||||
|
||||
def vs_configurations(f, name, kind):
|
||||
for mode in MODES:
|
||||
for platform in PLATFORMS:
|
||||
f.write(' <PropertyGroup Condition="\'$(Configuration)|$(Platform)\'==\'%s|%s\'" Label="Configuration">\n' % (mode, platform))
|
||||
if kind == LIB_KIND:
|
||||
f.write(' <ConfigurationType>StaticLibrary</ConfigurationType>\n')
|
||||
elif kind == EXE_KIND:
|
||||
f.write(' <ConfigurationType>Application</ConfigurationType>\n')
|
||||
else:
|
||||
raise MKException("unknown kind %s" % kind)
|
||||
f.write(' <CharacterSet>Unicode</CharacterSet>\n')
|
||||
f.write(' <UseOfMfc>false</UseOfMfc>\n')
|
||||
f.write(' </PropertyGroup>\n')
|
||||
|
||||
f.write(' <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\n')
|
||||
f.write(' <ImportGroup Label="ExtensionSettings">\n')
|
||||
f.write(' </ImportGroup>\n')
|
||||
f.write(' <ImportGroup Label="PropertySheets">\n')
|
||||
f.write(' <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists(\'$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props\')" Label="LocalAppDataPlatform" /> </ImportGroup>\n')
|
||||
f.write(' <PropertyGroup Label="UserMacros" />\n')
|
||||
|
||||
f.write(' <PropertyGroup>\n')
|
||||
for mode in MODES:
|
||||
for platform in PLATFORMS:
|
||||
if is_x64(platform):
|
||||
f.write(' <OutDir Condition="\'$(Configuration)|$(Platform)\'==\'%s|%s\'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>\n' %
|
||||
(mode, platform))
|
||||
else:
|
||||
f.write(' <OutDir Condition="\'$(Configuration)|$(Platform)\'==\'%s|%s\'">$(SolutionDir)$(Configuration)\</OutDir>\n' % (mode, platform))
|
||||
for mode in MODES:
|
||||
for platform in PLATFORMS:
|
||||
f.write(' <TargetName Condition="\'$(Configuration)|$(Platform)\'==\'%s|%s\'">%s</TargetName>\n' % (mode, platform, name))
|
||||
f.write(' <TargetExt Condition="\'$(Configuration)|$(Platform)\'==\'%s|%s\'">.%s</TargetExt>\n' % (mode, platform, get_extension(kind)))
|
||||
f.write(' </PropertyGroup>\n')
|
||||
|
||||
def vs_compilation_options(f, name, deps, kind):
|
||||
for mode in MODES:
|
||||
for platform in PLATFORMS:
|
||||
f.write(' <ItemDefinitionGroup Condition="\'$(Configuration)|$(Platform)\'==\'%s|%s\'">\n' % (mode, platform))
|
||||
if is_x64(platform):
|
||||
f.write(' <Midl>\n')
|
||||
f.write(' <TargetEnvironment>X64</TargetEnvironment>\n')
|
||||
f.write(' </Midl>\n')
|
||||
f.write(' <ClCompile>\n')
|
||||
if is_debug(mode):
|
||||
f.write(' <Optimization>Disabled</Optimization>\n')
|
||||
else:
|
||||
f.write(' <Optimization>Full</Optimization>\n')
|
||||
options = VS_COMMON_OPTIONS
|
||||
if is_debug(mode):
|
||||
options = "%s;%s" % (options, VS_DBG_OPTIONS)
|
||||
else:
|
||||
options = "%s;%s" % (options, VS_RELEASE_OPTIONS)
|
||||
if is_x64(platform):
|
||||
options = "%s;_AMD64_" % options
|
||||
f.write(' <PreprocessorDefinitions>%s;%%(PreprocessorDefinitions)</PreprocessorDefinitions>\n' % options)
|
||||
if is_debug(mode):
|
||||
f.write(' <MinimalRebuild>true</MinimalRebuild>\n')
|
||||
f.write(' <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n')
|
||||
f.write(' <WarningLevel>Level3</WarningLevel>\n')
|
||||
f.write(' <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\n')
|
||||
f.write(' <OpenMPSupport>true</OpenMPSupport>\n')
|
||||
f.write(' <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\n')
|
||||
f.write(' <AdditionalIncludeDirectories>')
|
||||
f.write('..\..\src\%s' % name)
|
||||
for dep in deps:
|
||||
f.write(';..\..\src\%s' % dep)
|
||||
f.write('</AdditionalIncludeDirectories>\n')
|
||||
f.write(' </ClCompile>\n')
|
||||
f.write(' <Link>\n')
|
||||
f.write(' <OutputFile>$(OutDir)%s.%s</OutputFile>\n' % (name, get_extension(kind)))
|
||||
f.write(' <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\n')
|
||||
if is_x64(platform):
|
||||
f.write(' <TargetMachine>MachineX64</TargetMachine>\n')
|
||||
else:
|
||||
f.write(' <TargetMachine>MachineX86</TargetMachine>\n')
|
||||
if kind == EXE_KIND:
|
||||
f.write('<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib')
|
||||
for dep in deps:
|
||||
f.write(';$(OutDir)%s.lib' % dep)
|
||||
# if is_x64(platform):
|
||||
# f.write(';..\%s\%s\%s\%s.lib' % (dep, platform, mode, dep))
|
||||
# else:
|
||||
# f.write(';..\%s\%s\%s.lib' % (dep, mode, dep))
|
||||
f.write(';%(AdditionalDependencies)</AdditionalDependencies>\n')
|
||||
f.write(' </Link>\n')
|
||||
f.write(' </ItemDefinitionGroup>\n')
|
||||
|
||||
def add_vs_cpps(f, name):
|
||||
f.write(' <ItemGroup>\n')
|
||||
srcs = module_src_dir(name)
|
||||
for cppfile in glob.glob(os.path.join(srcs, '*.cpp')):
|
||||
f.write(' <ClCompile Include="..%s..%s%s" />\n' % (os.sep, os.sep, cppfile))
|
||||
f.write(' </ItemGroup>\n')
|
||||
|
||||
def vs_footer(f):
|
||||
f.write(
|
||||
' <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\n'
|
||||
' <ImportGroup Label="ExtensionTargets">\n'
|
||||
' </ImportGroup>\n'
|
||||
'</Project>\n')
|
||||
|
||||
def check_new_component(name):
|
||||
if (name in HEADERS) or (name in LIBS) or (name in EXES):
|
||||
raise MKException("Component '%s' was already defined" % name)
|
||||
|
||||
# Add a directory containing only .h files
|
||||
def add_header(name):
|
||||
check_new_component(name)
|
||||
HEADERS.append(name)
|
||||
|
||||
def find_all_deps(name, deps):
|
||||
new_deps = []
|
||||
for dep in deps:
|
||||
if dep in LIBS:
|
||||
if not (dep in new_deps):
|
||||
new_deps.append(dep)
|
||||
for dep_dep in DEPS[dep]:
|
||||
if not (dep_dep in new_deps):
|
||||
new_deps.append(dep_dep)
|
||||
elif dep in HEADERS:
|
||||
if not (dep in new_deps):
|
||||
new_deps.append(dep)
|
||||
else:
|
||||
raise MKException("Unknown component '%s' at '%s'." % (dep, name))
|
||||
return new_deps
|
||||
|
||||
def add_component(name, deps, kind):
|
||||
check_new_component(name)
|
||||
if kind == LIB_KIND:
|
||||
LIBS.append(name)
|
||||
elif kind == EXE_KIND:
|
||||
EXES.append(name)
|
||||
else:
|
||||
raise MKException("unknown kind %s" % kind)
|
||||
MODULES.append(name)
|
||||
deps = find_all_deps(name, deps)
|
||||
DEPS[name] = deps
|
||||
print "Dependencies for '%s': %s" % (name, deps)
|
||||
|
||||
module_dir = module_build_dir(name)
|
||||
mk_dir(module_dir)
|
||||
|
||||
vs_proj = open('%s%s%s.vcxproj' % (module_dir, os.sep, name), 'w')
|
||||
vs_header(vs_proj)
|
||||
vs_project_configurations(vs_proj, name)
|
||||
vs_configurations(vs_proj, name, kind)
|
||||
vs_compilation_options(vs_proj, name, deps, kind)
|
||||
add_vs_cpps(vs_proj, name)
|
||||
vs_footer(vs_proj)
|
||||
|
||||
def add_lib(name, deps):
|
||||
add_component(name, deps, LIB_KIND)
|
||||
|
||||
def add_exe(name, deps):
|
||||
add_component(name, deps, EXE_KIND)
|
||||
|
||||
def is_lib(name):
|
||||
# Add DLL dependency
|
||||
return name in LIBS
|
||||
|
||||
def mk_vs_solution():
|
||||
sln = open('%s%sz3.sln' % (BUILD_DIR, os.sep), 'w')
|
||||
sln.write('\n')
|
||||
sln.write("Microsoft Visual Studio Solution File, Format Version 11.00\n")
|
||||
sln.write("# Visual Studio 2010\n")
|
||||
for module in MODULES:
|
||||
gui = Name2GUI[module]
|
||||
deps = DEPS[module]
|
||||
sln.write('Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "%s", "%s%s%s.vcxproj", "{%s}"\n' %
|
||||
(module, module, os.sep, module, mk_gui_str(gui)))
|
||||
if len(deps) > 0:
|
||||
sln.write(' ProjectSection(ProjectDependencies) = postProject\n')
|
||||
for dep in deps:
|
||||
if is_lib(dep):
|
||||
i = Name2GUI[dep]
|
||||
sln.write(' {%s} = {%s}\n' % (mk_gui_str(i), mk_gui_str(i)))
|
||||
sln.write(' EndProjectSection\n')
|
||||
sln.write('EndProject\n')
|
||||
sln.write('Global\n')
|
||||
sln.write('GlobalSection(SolutionConfigurationPlatforms) = preSolution\n')
|
||||
for mode in MODES:
|
||||
for platform in PLATFORMS:
|
||||
sln.write(' %s|%s = %s|%s\n' % (mode, platform, mode, platform))
|
||||
sln.write('EndGlobalSection\n')
|
||||
sln.write('GlobalSection(ProjectConfigurationPlatforms) = postSolution\n')
|
||||
for module in MODULES:
|
||||
gui = Name2GUI[module]
|
||||
for mode in MODES:
|
||||
for platform in PLATFORMS:
|
||||
sln.write(' {%s}.%s|%s.ActiveCfg = %s|%s\n' % (mk_gui_str(gui), mode, platform, mode, platform))
|
||||
sln.write(' {%s}.%s|%s.Build.0 = %s|%s\n' % (mk_gui_str(gui), mode, platform, mode, platform))
|
||||
sln.write('EndGlobalSection\n')
|
||||
|
||||
print "Visual Solution was generated."
|
20
scripts/update-version.sh
Normal file
20
scripts/update-version.sh
Normal file
|
@ -0,0 +1,20 @@
|
|||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Update Z3 version
|
||||
#
|
||||
|
||||
if [ $# -ne 1 ]; then
|
||||
echo "Usage: update-version.sh MAJOR.MINOR.BUILD.REVISION"
|
||||
fi
|
||||
|
||||
sd edit lib/version.h
|
||||
sd edit release.cmd
|
||||
sd edit shell/shell.rc
|
||||
sd edit dll/dll.rc
|
||||
sd edit shell/main.cpp
|
||||
sd edit Z3Inspector/Properties/AssemblyInfo.cs
|
||||
sd edit Microsoft.Z3/Properties/AssemblyInfo.cs
|
||||
sd edit Microsoft.Z3V3/AssemblyInfo.cpp
|
||||
|
||||
scripts/perl scripts/update-version.pl "$1"
|
871
scripts/update_api.py
Normal file
871
scripts/update_api.py
Normal file
|
@ -0,0 +1,871 @@
|
|||
############################################
|
||||
# Copyright (c) 2012 Microsoft Corporation
|
||||
#
|
||||
# Scripts for generate API bindings and definitions
|
||||
#
|
||||
# Author: Leonardo de Moura (leonardo)
|
||||
############################################
|
||||
import re
|
||||
import sys
|
||||
import os
|
||||
from sets import Set
|
||||
|
||||
API_FILES = []
|
||||
|
||||
def add_api_file(dir, file):
|
||||
API_FILES.append("%s%s%s" % (dir, os.sep, file))
|
||||
|
||||
add_api_file('lib', 'z3_api.h')
|
||||
add_api_file('lib', 'z3_internal_types.h')
|
||||
add_api_file('lib', 'z3_poly.h')
|
||||
|
||||
# Extract enumeration types from z3_api.h, and add .Net definitions
|
||||
def mk_z3consts_donet():
|
||||
blank_pat = re.compile("^ *$")
|
||||
comment_pat = re.compile("^ *//.*$")
|
||||
typedef_pat = re.compile("typedef enum *")
|
||||
typedef2_pat = re.compile("typedef enum { *")
|
||||
openbrace_pat = re.compile("{ *")
|
||||
closebrace_pat = re.compile("}.*;")
|
||||
|
||||
DeprecatedEnums = { 'Z3_search_failure' }
|
||||
z3consts = open('Microsoft.Z3%sEnumerations.cs' % os.sep, 'w')
|
||||
z3consts.write('// Automatically generated file, generator: update_api.py\n\n')
|
||||
z3consts.write('using System;\n\n'
|
||||
'#pragma warning disable 1591\n\n'
|
||||
'namespace Microsoft.Z3\n'
|
||||
'{\n');
|
||||
|
||||
for api_file in API_FILES:
|
||||
api = open(api_file, 'r')
|
||||
|
||||
SEARCHING = 0
|
||||
FOUND_ENUM = 1
|
||||
IN_ENUM = 2
|
||||
|
||||
mode = SEARCHING
|
||||
decls = {}
|
||||
idx = 0
|
||||
|
||||
linenum = 1
|
||||
for line in api:
|
||||
m1 = blank_pat.match(line)
|
||||
m2 = comment_pat.match(line)
|
||||
if m1 or m2:
|
||||
# skip blank lines and comments
|
||||
linenum = linenum + 1
|
||||
elif mode == SEARCHING:
|
||||
m = typedef_pat.match(line)
|
||||
if m:
|
||||
mode = FOUND_ENUM
|
||||
m = typedef2_pat.match(line)
|
||||
if m:
|
||||
mode = IN_ENUM
|
||||
decls = {}
|
||||
idx = 0
|
||||
elif mode == FOUND_ENUM:
|
||||
m = openbrace_pat.match(line)
|
||||
if m:
|
||||
mode = IN_ENUM
|
||||
decls = {}
|
||||
idx = 0
|
||||
else:
|
||||
assert False, "Invalid %s, line: %s" % (api_file, linenum)
|
||||
else:
|
||||
assert mode == IN_ENUM
|
||||
words = re.split('[^\-a-zA-Z0-9_]+', line)
|
||||
m = closebrace_pat.match(line)
|
||||
if m:
|
||||
name = words[1]
|
||||
if name not in DeprecatedEnums:
|
||||
z3consts.write(' /// <summary>%s</summary>\n' % name)
|
||||
z3consts.write(' public enum %s {\n' % name)
|
||||
z3consts.write
|
||||
for k, i in decls.iteritems():
|
||||
z3consts.write(' %s = %s,\n' % (k, i))
|
||||
z3consts.write(' }\n\n')
|
||||
mode = SEARCHING
|
||||
else:
|
||||
if words[2] != '':
|
||||
if len(words[2]) > 1 and words[2][1] == 'x':
|
||||
idx = int(words[2], 16)
|
||||
else:
|
||||
idx = int(words[2])
|
||||
decls[words[1]] = idx
|
||||
idx = idx + 1
|
||||
linenum = linenum + 1
|
||||
z3consts.write('}\n');
|
||||
|
||||
|
||||
# Extract enumeration types from z3_api.h, and add python definitions.
|
||||
def mk_z3consts_py():
|
||||
blank_pat = re.compile("^ *$")
|
||||
comment_pat = re.compile("^ *//.*$")
|
||||
typedef_pat = re.compile("typedef enum *")
|
||||
typedef2_pat = re.compile("typedef enum { *")
|
||||
openbrace_pat = re.compile("{ *")
|
||||
closebrace_pat = re.compile("}.*;")
|
||||
|
||||
z3consts = open('python%sz3consts.py' % (os.sep), 'w')
|
||||
z3consts.write('# Automatically generated file, generator: update_api.py\n\n')
|
||||
|
||||
for api_file in API_FILES:
|
||||
api = open(api_file, 'r')
|
||||
|
||||
SEARCHING = 0
|
||||
FOUND_ENUM = 1
|
||||
IN_ENUM = 2
|
||||
|
||||
mode = SEARCHING
|
||||
decls = {}
|
||||
idx = 0
|
||||
|
||||
linenum = 1
|
||||
for line in api:
|
||||
m1 = blank_pat.match(line)
|
||||
m2 = comment_pat.match(line)
|
||||
if m1 or m2:
|
||||
# skip blank lines and comments
|
||||
linenum = linenum + 1
|
||||
elif mode == SEARCHING:
|
||||
m = typedef_pat.match(line)
|
||||
if m:
|
||||
mode = FOUND_ENUM
|
||||
m = typedef2_pat.match(line)
|
||||
if m:
|
||||
mode = IN_ENUM
|
||||
decls = {}
|
||||
idx = 0
|
||||
elif mode == FOUND_ENUM:
|
||||
m = openbrace_pat.match(line)
|
||||
if m:
|
||||
mode = IN_ENUM
|
||||
decls = {}
|
||||
idx = 0
|
||||
else:
|
||||
assert False, "Invalid %s, line: %s" % (api_file, linenum)
|
||||
else:
|
||||
assert mode == IN_ENUM
|
||||
words = re.split('[^\-a-zA-Z0-9_]+', line)
|
||||
m = closebrace_pat.match(line)
|
||||
if m:
|
||||
name = words[1]
|
||||
z3consts.write('# enum %s\n' % name)
|
||||
for k, i in decls.iteritems():
|
||||
z3consts.write('%s = %s\n' % (k, i))
|
||||
z3consts.write('\n')
|
||||
mode = SEARCHING
|
||||
else:
|
||||
if words[2] != '':
|
||||
if len(words[2]) > 1 and words[2][1] == 'x':
|
||||
idx = int(words[2], 16)
|
||||
else:
|
||||
idx = int(words[2])
|
||||
decls[words[1]] = idx
|
||||
idx = idx + 1
|
||||
linenum = linenum + 1
|
||||
|
||||
# Extract tactic and probe definitions from lib\install_tactics.cpp, and
|
||||
# Add python function definitions for them.
|
||||
def mk_z3tactics_py():
|
||||
tactic_pat = re.compile("^[ \t]*ADD_TACTIC_CMD")
|
||||
probe_pat = re.compile("^[ \t]*ADD_PROBE")
|
||||
|
||||
cppfile = open('lib%sinstall_tactics.cpp' % os.sep, 'r')
|
||||
z3tactics = open('python%sz3tactics.py' % os.sep, 'w')
|
||||
|
||||
z3tactics.write('# Automatically generated file, generator: update_api.py\n')
|
||||
z3tactics.write('import z3core\n')
|
||||
z3tactics.write('import z3\n\n')
|
||||
|
||||
for line in cppfile:
|
||||
m1 = tactic_pat.match(line)
|
||||
m2 = probe_pat.match(line)
|
||||
if m1:
|
||||
words = re.split('[^\-a-zA-Z0-9_]+', line)
|
||||
tactic = words[2]
|
||||
py_tactic = tactic.replace('-', '_')
|
||||
z3tactics.write('def %s_tactic(ctx=None):\n' % py_tactic)
|
||||
z3tactics.write(' ctx = z3._get_ctx(ctx)\n')
|
||||
z3tactics.write(' return z3.Tactic(z3core.Z3_mk_tactic(ctx.ref(), \'%s\'), ctx)\n\n' % tactic)
|
||||
elif m2:
|
||||
words = re.split('[^\-a-zA-Z0-9_]+', line)
|
||||
probe = words[2]
|
||||
py_probe = probe.replace('-', '_')
|
||||
z3tactics.write('def %s_probe(ctx=None):\n' % py_probe)
|
||||
z3tactics.write(' ctx = z3._get_ctx(ctx)\n')
|
||||
z3tactics.write(' return z3.Probe(z3core.Z3_mk_probe(ctx.ref(), \'%s\'), ctx)\n\n' % probe)
|
||||
|
||||
# Create .def files for DLL generation
|
||||
def mk_dll_defs():
|
||||
pat1 = re.compile(".*Z3_API.*")
|
||||
z3def = open('dll%sz3.def' % os.sep, 'w')
|
||||
z3def.write('LIBRARY "Z3"\nEXPORTS\n')
|
||||
num = 1
|
||||
for api_file in API_FILES:
|
||||
api = open(api_file, 'r')
|
||||
for line in api:
|
||||
m = pat1.match(line)
|
||||
if m:
|
||||
words = re.split('\W+', line)
|
||||
i = 0
|
||||
for w in words:
|
||||
if w == 'Z3_API':
|
||||
f = words[i+1]
|
||||
z3def.write('\t%s @%s\n' % (f, num))
|
||||
i = i + 1
|
||||
num = num + 1
|
||||
|
||||
#
|
||||
# Generate logging support and bindings
|
||||
#
|
||||
|
||||
log_h = open('lib%sapi_log_macros.h' % os.sep, 'w')
|
||||
log_c = open('lib%sapi_log_macros.cpp' % os.sep, 'w')
|
||||
exe_c = open('lib%sapi_commands.cpp' % os.sep, 'w')
|
||||
core_py = open('python%sz3core.py' % os.sep, 'w')
|
||||
dotnet_fileout = 'Microsoft.Z3%sNative.cs' % os.sep
|
||||
##
|
||||
log_h.write('// Automatically generated file, generator: update_api.py\n')
|
||||
log_h.write('#include\"z3.h\"\n')
|
||||
##
|
||||
log_c.write('// Automatically generated file, generator: update_api.py\n')
|
||||
log_c.write('#include<iostream>\n')
|
||||
log_c.write('#include\"z3.h\"\n')
|
||||
log_c.write('#include\"api_log_macros.h\"\n')
|
||||
log_c.write('#include\"z3_logger.h\"\n')
|
||||
##
|
||||
exe_c.write('// Automatically generated file, generator: update_api.py\n')
|
||||
exe_c.write('#include\"z3.h\"\n')
|
||||
exe_c.write('#include\"z3_internal.h\"\n')
|
||||
exe_c.write('#include\"z3_replayer.h\"\n')
|
||||
##
|
||||
log_h.write('extern std::ostream * g_z3_log;\n')
|
||||
log_h.write('extern bool g_z3_log_enabled;\n')
|
||||
log_h.write('class z3_log_ctx { bool m_prev; public: z3_log_ctx():m_prev(g_z3_log_enabled) { g_z3_log_enabled = false; } ~z3_log_ctx() { g_z3_log_enabled = m_prev; } bool enabled() const { return m_prev; } };\n')
|
||||
log_h.write('inline void SetR(void * obj) { *g_z3_log << "= " << obj << "\\n"; }\ninline void SetO(void * obj, unsigned pos) { *g_z3_log << "* " << obj << " " << pos << "\\n"; } \ninline void SetAO(void * obj, unsigned pos, unsigned idx) { *g_z3_log << "@ " << obj << " " << pos << " " << idx << "\\n"; }\n')
|
||||
log_h.write('#define RETURN_Z3(Z3RES) if (_LOG_CTX.enabled()) { SetR(Z3RES); } return Z3RES\n')
|
||||
log_h.write('void _Z3_append_log(char const * msg);\n')
|
||||
##
|
||||
exe_c.write('void Z3_replacer_error_handler(Z3_context ctx, Z3_error_code c) { printf("[REPLAYER ERROR HANDLER]: %s\\n", Z3_get_error_msg_ex(ctx, c)); }\n')
|
||||
##
|
||||
core_py.write('# Automatically generated file, generator: update_api.py\n')
|
||||
core_py.write('import sys, os\n')
|
||||
core_py.write('import ctypes\n')
|
||||
core_py.write('from z3types import *\n')
|
||||
core_py.write('from z3consts import *\n')
|
||||
core_py.write("""
|
||||
def _find_lib():
|
||||
_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
libs = ['z3.dll', 'libz3.so', 'libz3.dylib']
|
||||
if sys.maxsize > 2**32:
|
||||
locs = [_dir, '%s%s..%sx64%sexternal' % (_dir, os.sep, os.sep, os.sep), '%s%s..%sbin%sexternal' % (_dir, os.sep, os.sep, os.sep)]
|
||||
else:
|
||||
locs = [_dir, '%s%s..%sexternal' % (_dir, os.sep, os.sep), '%s%s..%sbin%sexternal' % (_dir, os.sep, os.sep, os.sep)]
|
||||
for loc in locs:
|
||||
for lib in libs:
|
||||
f = '%s%s%s' % (loc, os.sep, lib)
|
||||
if os.path.exists(f):
|
||||
return f
|
||||
return None
|
||||
|
||||
_lib = None
|
||||
def lib():
|
||||
if _lib == None:
|
||||
l = _find_lib()
|
||||
if l == None:
|
||||
raise Z3Exception("init(Z3_LIBRARY_PATH) must be invoked before using Z3-python")
|
||||
init(l)
|
||||
assert _lib != None
|
||||
return _lib
|
||||
|
||||
def init(PATH):
|
||||
global _lib
|
||||
_lib = ctypes.CDLL(PATH)
|
||||
""")
|
||||
|
||||
IN = 0
|
||||
OUT = 1
|
||||
INOUT = 2
|
||||
IN_ARRAY = 3
|
||||
OUT_ARRAY = 4
|
||||
INOUT_ARRAY = 5
|
||||
|
||||
# Primitive Types
|
||||
VOID = 0
|
||||
VOID_PTR = 1
|
||||
INT = 2
|
||||
UINT = 3
|
||||
INT64 = 4
|
||||
UINT64 = 5
|
||||
STRING = 6
|
||||
STRING_PTR = 7
|
||||
BOOL = 8
|
||||
SYMBOL = 9
|
||||
PRINT_MODE = 10
|
||||
ERROR_CODE = 11
|
||||
DOUBLE = 12
|
||||
|
||||
FIRST_OBJ_ID = 100
|
||||
|
||||
def is_obj(ty):
|
||||
return ty >= FIRST_OBJ_ID
|
||||
|
||||
Type2Str = { VOID : 'void', VOID_PTR : 'void*', INT : 'int', UINT : 'unsigned', INT64 : '__int64', UINT64 : '__uint64', DOUBLE : 'double',
|
||||
STRING : 'Z3_string', STRING_PTR : 'Z3_string_ptr', BOOL : 'Z3_bool', SYMBOL : 'Z3_symbol',
|
||||
PRINT_MODE : 'Z3_ast_print_mode', ERROR_CODE : 'Z3_error_code',
|
||||
}
|
||||
|
||||
Type2PyStr = { VOID_PTR : 'ctypes.c_void_p', INT : 'ctypes.c_int', UINT : 'ctypes.c_uint', INT64 : 'ctypes.c_longlong',
|
||||
UINT64 : 'ctypes.c_ulonglong', DOUBLE : 'ctypes.c_double',
|
||||
STRING : 'ctypes.c_char_p', STRING_PTR : 'ctypes.POINTER(ctypes.c_char_p)', BOOL : 'ctypes.c_bool', SYMBOL : 'Symbol',
|
||||
PRINT_MODE : 'ctypes.c_uint', ERROR_CODE : 'ctypes.c_uint',
|
||||
}
|
||||
|
||||
# Mapping to .NET types
|
||||
Type2Dotnet = { VOID : 'void', VOID_PTR : 'IntPtr', INT : 'int', UINT : 'uint', INT64 : 'Int64', UINT64 : 'UInt64', DOUBLE : 'double',
|
||||
STRING : 'string', STRING_PTR : 'byte**', BOOL : 'int', SYMBOL : 'IntPtr',
|
||||
PRINT_MODE : 'uint', ERROR_CODE : 'uint' }
|
||||
|
||||
next_type_id = FIRST_OBJ_ID
|
||||
|
||||
def def_Type(var, c_type, py_type):
|
||||
global next_type_id
|
||||
exec ('%s = %s' % (var, next_type_id)) in globals()
|
||||
Type2Str[next_type_id] = c_type
|
||||
Type2PyStr[next_type_id] = py_type
|
||||
next_type_id = next_type_id + 1
|
||||
|
||||
def def_Types():
|
||||
pat1 = re.compile(" *def_Type.*")
|
||||
for api_file in API_FILES:
|
||||
api = open(api_file, 'r')
|
||||
for line in api:
|
||||
m = pat1.match(line)
|
||||
if m:
|
||||
print line.strip()
|
||||
eval(line)
|
||||
for k, v in Type2Str.iteritems():
|
||||
if is_obj(k):
|
||||
Type2Dotnet[k] = v
|
||||
|
||||
def type2str(ty):
|
||||
global Type2Str
|
||||
return Type2Str[ty]
|
||||
|
||||
def type2pystr(ty):
|
||||
global Type2PyStr
|
||||
return Type2PyStr[ty]
|
||||
|
||||
def type2dotnet(ty):
|
||||
global Type2Dotnet
|
||||
return Type2Dotnet[ty]
|
||||
|
||||
def _in(ty):
|
||||
return (IN, ty);
|
||||
|
||||
def _in_array(sz, ty):
|
||||
return (IN_ARRAY, ty, sz);
|
||||
|
||||
def _out(ty):
|
||||
return (OUT, ty);
|
||||
|
||||
def _out_array(sz, ty):
|
||||
return (OUT_ARRAY, ty, sz, sz);
|
||||
|
||||
# cap contains the position of the argument that stores the capacity of the array
|
||||
# sz contains the position of the output argument that stores the (real) size of the array
|
||||
def _out_array2(cap, sz, ty):
|
||||
return (OUT_ARRAY, ty, cap, sz)
|
||||
|
||||
def _inout_array(sz, ty):
|
||||
return (INOUT_ARRAY, ty, sz, sz);
|
||||
|
||||
def param_kind(p):
|
||||
return p[0]
|
||||
|
||||
def param_type(p):
|
||||
return p[1]
|
||||
|
||||
def param_array_capacity_pos(p):
|
||||
return p[2]
|
||||
|
||||
def param_array_size_pos(p):
|
||||
return p[3]
|
||||
|
||||
def param2str(p):
|
||||
if param_kind(p) == IN_ARRAY:
|
||||
return "%s const *" % type2str(param_type(p))
|
||||
elif param_kind(p) == OUT_ARRAY or param_kind(p) == IN_ARRAY or param_kind(p) == INOUT_ARRAY:
|
||||
return "%s*" % type2str(param_type(p))
|
||||
elif param_kind(p) == OUT:
|
||||
return "%s*" % type2str(param_type(p))
|
||||
else:
|
||||
return type2str(param_type(p))
|
||||
|
||||
|
||||
def param2dotnet(p):
|
||||
k = param_kind(p)
|
||||
if k == OUT:
|
||||
if param_type(p) == STRING:
|
||||
return "out IntPtr"
|
||||
else:
|
||||
return "[In, Out] ref %s" % type2dotnet(param_type(p))
|
||||
if k == IN_ARRAY:
|
||||
return "[In] %s[]" % type2dotnet(param_type(p))
|
||||
if k == INOUT_ARRAY:
|
||||
return "[In, Out] %s[]" % type2dotnet(param_type(p))
|
||||
if k == OUT_ARRAY:
|
||||
return "[Out] %s[]" % type2dotnet(param_type(p))
|
||||
else:
|
||||
return type2dotnet(param_type(p))
|
||||
|
||||
def param2pystr(p):
|
||||
if param_kind(p) == IN_ARRAY or param_kind(p) == OUT_ARRAY or param_kind(p) == IN_ARRAY or param_kind(p) == INOUT_ARRAY or param_kind(p) == OUT:
|
||||
return "ctypes.POINTER(%s)" % type2pystr(param_type(p))
|
||||
else:
|
||||
return type2pystr(param_type(p))
|
||||
|
||||
# Save name, result, params to generate wrapper
|
||||
_API2PY = []
|
||||
|
||||
def mk_py_binding(name, result, params):
|
||||
global core_py
|
||||
global _API2PY
|
||||
_API2PY.append((name, result, params))
|
||||
if result != VOID:
|
||||
core_py.write(" _lib.%s.restype = %s\n" % (name, type2pystr(result)))
|
||||
core_py.write(" _lib.%s.argtypes = [" % name)
|
||||
first = True
|
||||
for p in params:
|
||||
if first:
|
||||
first = False
|
||||
else:
|
||||
core_py.write(", ")
|
||||
core_py.write(param2pystr(p))
|
||||
core_py.write("]\n")
|
||||
|
||||
def extra_API(name, result, params):
|
||||
print 'extra_API(%s)' % name
|
||||
mk_py_binding(name, result, params)
|
||||
reg_dotnet(name, result, params)
|
||||
|
||||
def display_args(num):
|
||||
for i in range(num):
|
||||
if i > 0:
|
||||
core_py.write(", ")
|
||||
core_py.write("a%s" % i)
|
||||
|
||||
def mk_py_wrappers():
|
||||
core_py.write("\n")
|
||||
for sig in _API2PY:
|
||||
name = sig[0]
|
||||
result = sig[1]
|
||||
params = sig[2]
|
||||
num = len(params)
|
||||
core_py.write("def %s(" % name)
|
||||
display_args(num)
|
||||
core_py.write("):\n")
|
||||
if result != VOID:
|
||||
core_py.write(" r = lib().%s(" % name)
|
||||
else:
|
||||
core_py.write(" lib().%s(" % name)
|
||||
display_args(num)
|
||||
core_py.write(")\n")
|
||||
if len(params) > 0 and param_type(params[0]) == CONTEXT:
|
||||
core_py.write(" err = lib().Z3_get_error_code(a0)\n")
|
||||
core_py.write(" if err != Z3_OK:\n")
|
||||
core_py.write(" raise Z3Exception(lib().Z3_get_error_msg_ex(a0, err))\n")
|
||||
if result != VOID:
|
||||
core_py.write(" return r\n")
|
||||
core_py.write("\n")
|
||||
|
||||
|
||||
## .NET API native interface
|
||||
_dotnet_decls = []
|
||||
def reg_dotnet(name, result, params):
|
||||
global _dotnet_decls
|
||||
_dotnet_decls.append((name, result, params))
|
||||
|
||||
def mk_dotnet():
|
||||
global Type2Str
|
||||
global dotnet_fileout
|
||||
dotnet = open(dotnet_fileout, 'w')
|
||||
dotnet.write('// Automatically generated file, generator: api.py\n')
|
||||
dotnet.write('using System;\n')
|
||||
dotnet.write('using System.Collections.Generic;\n')
|
||||
dotnet.write('using System.Text;\n')
|
||||
dotnet.write('using System.Runtime.InteropServices;\n\n')
|
||||
dotnet.write('#pragma warning disable 1591\n\n');
|
||||
dotnet.write('namespace Microsoft.Z3\n')
|
||||
dotnet.write('{\n')
|
||||
for k, v in Type2Str.iteritems():
|
||||
if is_obj(k):
|
||||
dotnet.write(' using %s = System.IntPtr;\n' % v)
|
||||
dotnet.write('\n');
|
||||
dotnet.write(' public class Native\n')
|
||||
dotnet.write(' {\n\n')
|
||||
dotnet.write(' [UnmanagedFunctionPointer(CallingConvention.Cdecl)]\n')
|
||||
dotnet.write(' public delegate void Z3_error_handler(Z3_context c, Z3_error_code e);\n\n')
|
||||
dotnet.write(' public unsafe class LIB\n')
|
||||
dotnet.write(' {\n')
|
||||
dotnet.write(' '
|
||||
' const string Z3_DLL_NAME = \"z3.dll\";\n'
|
||||
' \n');
|
||||
dotnet.write(' [DllImport(Z3_DLL_NAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]\n')
|
||||
dotnet.write(' public extern static void Z3_set_error_handler(Z3_context a0, Z3_error_handler a1);\n\n')
|
||||
for name, result, params in _dotnet_decls:
|
||||
dotnet.write(' [DllImport(Z3_DLL_NAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]\n')
|
||||
dotnet.write(' ')
|
||||
if result == STRING:
|
||||
dotnet.write('public extern static IntPtr %s(' % (name))
|
||||
else:
|
||||
dotnet.write('public extern static %s %s(' % (type2dotnet(result), name))
|
||||
first = True
|
||||
i = 0;
|
||||
for param in params:
|
||||
if first:
|
||||
first = False
|
||||
else:
|
||||
dotnet.write(', ')
|
||||
dotnet.write('%s a%d' % (param2dotnet(param), i))
|
||||
i = i + 1
|
||||
dotnet.write(');\n\n')
|
||||
dotnet.write(' }\n')
|
||||
|
||||
|
||||
DotnetUnwrapped = { 'Z3_del_context' }
|
||||
|
||||
def mk_dotnet_wrappers():
|
||||
global Type2Str
|
||||
global dotnet_fileout
|
||||
dotnet = open(dotnet_fileout, 'a')
|
||||
dotnet.write("\n")
|
||||
dotnet.write(" public static void Z3_set_error_handler(Z3_context a0, Z3_error_handler a1) {\n")
|
||||
dotnet.write(" LIB.Z3_set_error_handler(a0, a1);\n")
|
||||
dotnet.write(" Z3_error_code err = (Z3_error_code)LIB.Z3_get_error_code(a0);\n")
|
||||
dotnet.write(" if (err != Z3_error_code.Z3_OK)\n")
|
||||
dotnet.write(" throw new Z3Exception(Marshal.PtrToStringAnsi(LIB.Z3_get_error_msg_ex(a0, (uint)err)));\n")
|
||||
dotnet.write(" }\n\n")
|
||||
for name, result, params in _dotnet_decls:
|
||||
if result == STRING:
|
||||
dotnet.write(' public static string %s(' % (name))
|
||||
else:
|
||||
dotnet.write(' public static %s %s(' % (type2dotnet(result), name))
|
||||
first = True
|
||||
i = 0;
|
||||
for param in params:
|
||||
if first:
|
||||
first = False
|
||||
else:
|
||||
dotnet.write(', ')
|
||||
dotnet.write('%s a%d' % (param2dotnet(param), i))
|
||||
i = i + 1
|
||||
dotnet.write(') {\n')
|
||||
dotnet.write(' ')
|
||||
if result == STRING:
|
||||
dotnet.write('IntPtr r = ');
|
||||
elif result != VOID:
|
||||
dotnet.write('%s r = ' % type2dotnet(result));
|
||||
dotnet.write('LIB.%s(' % (name))
|
||||
first = True
|
||||
i = 0
|
||||
for param in params:
|
||||
if first:
|
||||
first = False
|
||||
else:
|
||||
dotnet.write(', ')
|
||||
if param_kind(param) == OUT:
|
||||
if param_type(param) == STRING:
|
||||
dotnet.write('out ');
|
||||
else:
|
||||
dotnet.write('ref ')
|
||||
dotnet.write('a%d' % i)
|
||||
i = i + 1
|
||||
dotnet.write(');\n');
|
||||
if name not in DotnetUnwrapped:
|
||||
if len(params) > 0 and param_type(params[0]) == CONTEXT:
|
||||
dotnet.write(" Z3_error_code err = (Z3_error_code)LIB.Z3_get_error_code(a0);\n")
|
||||
dotnet.write(" if (err != Z3_error_code.Z3_OK)\n")
|
||||
dotnet.write(" throw new Z3Exception(Marshal.PtrToStringAnsi(LIB.Z3_get_error_msg_ex(a0, (uint)err)));\n")
|
||||
if result == STRING:
|
||||
dotnet.write(" return Marshal.PtrToStringAnsi(r);\n")
|
||||
elif result != VOID:
|
||||
dotnet.write(" return r;\n")
|
||||
dotnet.write(" }\n\n")
|
||||
dotnet.write(" }\n\n")
|
||||
dotnet.write("}\n\n")
|
||||
|
||||
def mk_log_header(file, name, params):
|
||||
file.write("void log_%s(" % name)
|
||||
i = 0
|
||||
for p in params:
|
||||
if i > 0:
|
||||
file.write(", ");
|
||||
file.write("%s a%s" % (param2str(p), i))
|
||||
i = i + 1
|
||||
file.write(")");
|
||||
|
||||
def log_param(p):
|
||||
kind = param_kind(p)
|
||||
ty = param_type(p)
|
||||
return is_obj(ty) and (kind == OUT or kind == INOUT or kind == OUT_ARRAY or kind == INOUT_ARRAY)
|
||||
|
||||
def log_result(result, params):
|
||||
for p in params:
|
||||
if log_param(p):
|
||||
return True
|
||||
return False
|
||||
|
||||
def mk_log_macro(file, name, params):
|
||||
file.write("#define LOG_%s(" % name)
|
||||
i = 0
|
||||
for p in params:
|
||||
if i > 0:
|
||||
file.write(", ")
|
||||
file.write("_ARG%s" % i)
|
||||
i = i + 1
|
||||
file.write(") z3_log_ctx _LOG_CTX; ")
|
||||
auxs = Set([])
|
||||
i = 0
|
||||
for p in params:
|
||||
if log_param(p):
|
||||
kind = param_kind(p)
|
||||
if kind == OUT_ARRAY or kind == INOUT_ARRAY:
|
||||
cap = param_array_capacity_pos(p)
|
||||
if cap not in auxs:
|
||||
auxs.add(cap)
|
||||
file.write("unsigned Z3ARG%s; " % cap)
|
||||
sz = param_array_size_pos(p)
|
||||
if sz not in auxs:
|
||||
auxs.add(sz)
|
||||
file.write("unsigned * Z3ARG%s; " % sz)
|
||||
file.write("%s Z3ARG%s; " % (param2str(p), i))
|
||||
i = i + 1
|
||||
file.write("if (_LOG_CTX.enabled()) { log_%s(" % name)
|
||||
i = 0
|
||||
for p in params:
|
||||
if (i > 0):
|
||||
file.write(', ')
|
||||
file.write("_ARG%s" %i)
|
||||
i = i + 1
|
||||
file.write("); ")
|
||||
auxs = Set([])
|
||||
i = 0
|
||||
for p in params:
|
||||
if log_param(p):
|
||||
kind = param_kind(p)
|
||||
if kind == OUT_ARRAY or kind == INOUT_ARRAY:
|
||||
cap = param_array_capacity_pos(p)
|
||||
if cap not in auxs:
|
||||
auxs.add(cap)
|
||||
file.write("Z3ARG%s = _ARG%s; " % (cap, cap))
|
||||
sz = param_array_size_pos(p)
|
||||
if sz not in auxs:
|
||||
auxs.add(sz)
|
||||
file.write("Z3ARG%s = _ARG%s; " % (sz, sz))
|
||||
file.write("Z3ARG%s = _ARG%s; " % (i, i))
|
||||
i = i + 1
|
||||
file.write("}\n")
|
||||
|
||||
def mk_log_result_macro(file, name, result, params):
|
||||
file.write("#define RETURN_%s" % name)
|
||||
if is_obj(result):
|
||||
file.write("(Z3RES)")
|
||||
file.write(" ")
|
||||
file.write("if (_LOG_CTX.enabled()) { ")
|
||||
if is_obj(result):
|
||||
file.write("SetR(Z3RES); ")
|
||||
i = 0
|
||||
for p in params:
|
||||
if log_param(p):
|
||||
kind = param_kind(p)
|
||||
if kind == OUT_ARRAY or kind == INOUT_ARRAY:
|
||||
cap = param_array_capacity_pos(p)
|
||||
sz = param_array_size_pos(p)
|
||||
if cap == sz:
|
||||
file.write("for (unsigned i = 0; i < Z3ARG%s; i++) { SetAO(Z3ARG%s[i], %s, i); } " % (sz, i, i))
|
||||
else:
|
||||
file.write("for (unsigned i = 0; Z3ARG%s && i < *Z3ARG%s; i++) { SetAO(Z3ARG%s[i], %s, i); } " % (sz, sz, i, i))
|
||||
if kind == OUT or kind == INOUT:
|
||||
file.write("SetO((Z3ARG%s == 0 ? 0 : *Z3ARG%s), %s); " % (i, i, i))
|
||||
i = i + 1
|
||||
file.write("} ")
|
||||
if is_obj(result):
|
||||
file.write("return Z3RES\n")
|
||||
else:
|
||||
file.write("return\n")
|
||||
|
||||
def mk_exec_header(file, name):
|
||||
file.write("void exec_%s(z3_replayer & in)" % name)
|
||||
|
||||
def error(msg):
|
||||
sys.stderr.write(msg)
|
||||
exit(-1)
|
||||
|
||||
next_id = 0
|
||||
API2Id = {}
|
||||
|
||||
def def_API(name, result, params):
|
||||
global API2Id, next_id
|
||||
global log_h, log_c
|
||||
print 'def_API(%s)' % name
|
||||
# print "generating ", name
|
||||
mk_py_binding(name, result, params)
|
||||
reg_dotnet(name, result, params)
|
||||
API2Id[next_id] = name
|
||||
mk_log_header(log_h, name, params)
|
||||
log_h.write(';\n')
|
||||
mk_log_header(log_c, name, params)
|
||||
log_c.write(' {\n R();\n')
|
||||
mk_exec_header(exe_c, name)
|
||||
exe_c.write(' {\n')
|
||||
# Create Log function & Function call
|
||||
i = 0
|
||||
exe_c.write(" ")
|
||||
if is_obj(result):
|
||||
exe_c.write("%s result = " % type2str(result))
|
||||
exe_c.write("%s(\n " % name)
|
||||
for p in params:
|
||||
kind = param_kind(p)
|
||||
ty = param_type(p)
|
||||
if (i > 0):
|
||||
exe_c.write(",\n ")
|
||||
if kind == IN:
|
||||
if is_obj(ty):
|
||||
log_c.write(" P(a%s);\n" % i)
|
||||
exe_c.write("reinterpret_cast<%s>(in.get_obj(%s))" % (param2str(p), i))
|
||||
elif ty == STRING:
|
||||
log_c.write(" S(a%s);\n" % i)
|
||||
exe_c.write("in.get_str(%s)" % i)
|
||||
elif ty == SYMBOL:
|
||||
log_c.write(" Sy(a%s);\n" % i)
|
||||
exe_c.write("in.get_symbol(%s)" % i)
|
||||
elif ty == UINT:
|
||||
log_c.write(" U(a%s);\n" % i)
|
||||
exe_c.write("in.get_uint(%s)" % i)
|
||||
elif ty == UINT64:
|
||||
log_c.write(" U(a%s);\n" % i)
|
||||
exe_c.write("in.get_uint64(%s)" % i)
|
||||
elif ty == INT:
|
||||
log_c.write(" I(a%s);\n" % i)
|
||||
exe_c.write("in.get_int(%s)" % i)
|
||||
elif ty == INT64:
|
||||
log_c.write(" I(a%s);\n" % i)
|
||||
exe_c.write("in.get_int64(%s)" % i)
|
||||
elif ty == DOUBLE:
|
||||
log_c.write(" D(a%s);\n" % i)
|
||||
exe_c.write("in.get_double(%s)" % i)
|
||||
elif ty == BOOL:
|
||||
log_c.write(" I(a%s);\n" % i)
|
||||
exe_c.write("in.get_bool(%s)" % i)
|
||||
elif ty == PRINT_MODE or ty == ERROR_CODE:
|
||||
log_c.write(" U(static_cast<unsigned>(a%s));\n" % i);
|
||||
exe_c.write("static_cast<%s>(in.get_uint(%s))" % (type2str(ty), i))
|
||||
else:
|
||||
error("unsupported parameter for %s, %s" % (name, p))
|
||||
elif kind == INOUT:
|
||||
error("unsupported parameter for %s, %s" % (name, p))
|
||||
elif kind == OUT:
|
||||
if is_obj(ty):
|
||||
log_c.write(" P(0);\n")
|
||||
exe_c.write("reinterpret_cast<%s>(in.get_obj_addr(%s))" % (param2str(p), i))
|
||||
elif ty == STRING:
|
||||
log_c.write(" S(\"\");\n")
|
||||
exe_c.write("in.get_str_addr(%s)" % i)
|
||||
elif ty == UINT:
|
||||
log_c.write(" U(0);\n")
|
||||
exe_c.write("in.get_uint_addr(%s)" % i)
|
||||
elif ty == UINT64:
|
||||
log_c.write(" U(0);\n")
|
||||
exe_c.write("in.get_uint64_addr(%s)" % i)
|
||||
elif ty == INT:
|
||||
log_c.write(" I(0);\n")
|
||||
exe_c.write("in.get_int_addr(%s)" % i)
|
||||
elif ty == INT64:
|
||||
log_c.write(" I(0);\n")
|
||||
exe_c.write("in.get_int64_addr(%s)" % i)
|
||||
else:
|
||||
error("unsupported parameter for %s, %s" % (name, p))
|
||||
elif kind == IN_ARRAY or kind == INOUT_ARRAY:
|
||||
sz = param_array_capacity_pos(p)
|
||||
log_c.write(" for (unsigned i = 0; i < a%s; i++) { " % sz)
|
||||
if is_obj(ty):
|
||||
log_c.write("P(a%s[i]);" % i)
|
||||
log_c.write(" }\n")
|
||||
log_c.write(" Ap(a%s);\n" % sz)
|
||||
exe_c.write("reinterpret_cast<%s*>(in.get_obj_array(%s))" % (type2str(ty), i))
|
||||
elif ty == SYMBOL:
|
||||
log_c.write("Sy(a%s[i]);" % i)
|
||||
log_c.write(" }\n")
|
||||
log_c.write(" Asy(a%s);\n" % sz)
|
||||
exe_c.write("in.get_symbol_array(%s)" % i)
|
||||
elif ty == UINT:
|
||||
log_c.write("U(a%s[i]);" % i)
|
||||
log_c.write(" }\n")
|
||||
log_c.write(" Au(a%s);\n" % sz)
|
||||
exe_c.write("in.get_uint_array(%s)" % i)
|
||||
else:
|
||||
error ("unsupported parameter for %s, %s" % (name, p))
|
||||
elif kind == OUT_ARRAY:
|
||||
sz = param_array_capacity_pos(p)
|
||||
log_c.write(" for (unsigned i = 0; i < a%s; i++) { " % sz)
|
||||
if is_obj(ty):
|
||||
log_c.write("P(0);")
|
||||
log_c.write(" }\n")
|
||||
log_c.write(" Ap(a%s);\n" % sz)
|
||||
exe_c.write("reinterpret_cast<%s*>(in.get_obj_array(%s))" % (type2str(ty), i))
|
||||
elif ty == UINT:
|
||||
log_c.write("U(0);")
|
||||
log_c.write(" }\n")
|
||||
log_c.write(" Au(a%s);\n" % sz)
|
||||
exe_c.write("in.get_uint_array(%s)" % i)
|
||||
else:
|
||||
error ("unsupported parameter for %s, %s" % (name, p))
|
||||
else:
|
||||
error ("unsupported parameter for %s, %s" % (name, p))
|
||||
i = i + 1
|
||||
log_c.write(" C(%s);\n" % next_id)
|
||||
exe_c.write(");\n")
|
||||
if is_obj(result):
|
||||
exe_c.write(" in.store_result(result);\n")
|
||||
if name == 'Z3_mk_context' or name == 'Z3_mk_context_rc':
|
||||
exe_c.write(" Z3_set_error_handler(result, Z3_replacer_error_handler);")
|
||||
log_c.write('}\n')
|
||||
exe_c.write('}\n')
|
||||
mk_log_macro(log_h, name, params)
|
||||
if log_result(result, params):
|
||||
mk_log_result_macro(log_h, name, result, params)
|
||||
next_id = next_id + 1
|
||||
|
||||
def mk_bindings():
|
||||
exe_c.write("void register_z3_replayer_cmds(z3_replayer & in) {\n")
|
||||
for key, val in API2Id.items():
|
||||
exe_c.write(" in.register_cmd(%s, exec_%s);\n" % (key, val))
|
||||
exe_c.write("}\n")
|
||||
|
||||
# Collect API(...) commands from
|
||||
def def_APIs():
|
||||
pat1 = re.compile(" *def_API.*")
|
||||
pat2 = re.compile(" *extra_API.*")
|
||||
for api_file in API_FILES:
|
||||
api = open(api_file, 'r')
|
||||
for line in api:
|
||||
m = pat1.match(line)
|
||||
if m:
|
||||
eval(line)
|
||||
m = pat2.match(line)
|
||||
if m:
|
||||
eval(line)
|
||||
|
||||
mk_z3consts_donet()
|
||||
mk_z3consts_py()
|
||||
mk_z3tactics_py()
|
||||
mk_dll_defs()
|
||||
def_Types()
|
||||
def_APIs()
|
||||
mk_bindings()
|
||||
mk_py_wrappers()
|
||||
mk_dotnet()
|
||||
mk_dotnet_wrappers()
|
||||
|
11
scripts/update_api.txt
Normal file
11
scripts/update_api.txt
Normal file
|
@ -0,0 +1,11 @@
|
|||
Instructions for updating external Z3 API
|
||||
-----------------------------------------
|
||||
|
||||
The python "macros": def_Type() and def_API() are used to add new types and function definitions to the Z3 API.
|
||||
The .h files listed at update_api.py contain these definitions.
|
||||
See lib\z3_api.py for many examples.
|
||||
|
||||
To generate bindings and the API logging infrastructure, the following command must be used:
|
||||
|
||||
python update_api.py
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue