def extract_header(filepath): """ Called from our call to walk_files. It extract just the preprocessor crap and saves it into a file in our project's include folder. """ incfile = os.path.basename(filepath) log(bright(' Processing', 'white'), incfile + '..') content = extract_preprocessor(read_text(filepath)) outpath = env.root_file('include', incfile) write_lines(env.root_file('include', 'python', incfile), remove_blanks(split_lines_rtrim(content))) return outpath
def extract_exports(tabbase, source, arch): """ Extract our exported items from our preprocessed source code. The tabbase argument specifies the resulting filename to write our generated code to. (src/tabbase.c and include/tabbase.h) Afterwards, we'll return the source code, with all the export declarations removed. """ # A collection of indexes to remove from the source removal_queue = [] # Get our python DLL exports. dllname = 'python27.%s.dll' % arch log(bright('Build:', 'green'), bright('Processing','white'), dllname, bright('exports..\n', 'white')) exports = get_dllexports(dllname) # Generate the appropriate prototypes. We'll only keep stuff found exported from # our DLL log(bright('Build:', 'green'), bright('Processing export declarations..\n','white')) protos = filter(lambda p: p.name in exports, parse_declarations(source)) # Generate our source files. macros = [] entries = [] for proto in protos: macro, entry = generate_tab(proto) macros.append(macro) entries.append(entry) if proto.valid_indexes: removal_queue.insert(0, [proto.start_index, proto.end_index]) # Write the files. write_lines(env.root_file('src', tabbase+'.c'), entries) write_lines(env.root_file('include', tabbase+'.h'), macros) # Remove our declarations from the initial source code. buffer = filter(lambda c: ord(c) != 13, list(source)) for removal in removal_queue: del buffer[removal[0]:removal[1]] return ''.join(buffer)
def preprocess_sources(*srcs): """ Preprocess python.c, filter out the crap, clean it up, and get the result as a string. """ args = [ os.path.join(env.bin_dir, 'msvcpp.bat')] + \ [ '-I%s' % env.root_file('include') ] + \ [ env.data_file(s) for s in srcs ] print ' '.join(args) try: processed = subproc.check_output(args, stderr=subproc.VOID) except subproc.CalledProcessError: print 'Command Args:', args raise processed_parts = processed.split('void landmark();') if len(processed_parts) == 1: raise Exception('Could not find our landmark in pyport.h') filtered = '\n'.join(filter( lambda l: not l.startswith('#pragma') and len(l) > 0, split_lines_trim(processed_parts[1]) )) # Some formatting issues. filtered = re.sub( r"(?m)PythonDynLoad_(\w+)\s*\(([^)]+)\)\s*([^\s])", r"PythonDynLoad_\1(\2) \3", re.sub( r"(?m)\r?\n\)", ")", re.sub("(?m)([^;\r{])\r?\n", r"\1 ", filtered) ) ) # Compress structs, etc down to a single line. filtered = re.sub( r"(?sm)\{[\t ]*\r?\n(.+?)\r?\n\}", linearize_struct, re.sub( r"(?m)\{\s*\r?\n([^{}]+?)\}", linearize_struct, filtered ) ) # Filter out extra spaces. return condense_space(filtered)
def extract_typedecls(source): """ Extract type definitions from the remaining source. NOTE: This function will be written into the existing state machine that handles extracting the preprocessor crap. """ typedecls = ['typedef', 'union', 'struct'] src_template = """ #ifndef _DYNPYTHON_TYPES_H_ #define _DYNPYTHON_TYPES_H_ #pragma once #ifdef __cplusplus extern "C" { #endif # if defined (_WIN64) typedef __int64 ssize_t; #elif defined (_WIN32) typedef int ssize_t; #endif %(decls)s #ifdef __cplusplus } #endif #endif /* _DYNPYTHON_TYPES_H_ */ """ # Our filter function. def is_typedecl(line): for t in typedecls: if line.startswith(t): return True return False log(bright('Build:', 'green'), bright('Processing type declarations..\n','white')) lines = src_template % { 'decls' : '\n'.join(filter(is_typedecl, split_lines_clean(source))) } write_text(env.root_file('include', 'dynpython_types.h'), lines)