From e56ea14ab8531ee3cec375460577d1b89bf62e26 Mon Sep 17 00:00:00 2001 From: Liong Sauw Ming Date: Thu, 16 Jan 2014 05:30:46 +0000 Subject: Closed #1723: Merging pjsua2 branch into trunk git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@4704 74dad513-b988-da41-8d7b-12977e46ad98 --- pjsip-apps/src/swig/importsym.py | 193 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 pjsip-apps/src/swig/importsym.py (limited to 'pjsip-apps/src/swig/importsym.py') diff --git a/pjsip-apps/src/swig/importsym.py b/pjsip-apps/src/swig/importsym.py new file mode 100644 index 00000000..32faf2cc --- /dev/null +++ b/pjsip-apps/src/swig/importsym.py @@ -0,0 +1,193 @@ +# $Id$ +# +# importsym.py: Import C symbol decls (structs, enums, etc) and write them +# to another file +# +# Copyright (C)2013 Teluu Inc. (http://www.teluu.com) +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +import pycparser +from pycparser import c_generator +import sys +import os + +def which(program): + import os + def is_exe(fpath): + return os.path.isfile(fpath) and os.access(fpath, os.X_OK) + + if sys.platform == 'win32' and not program.endswith(".exe"): + program += ".exe" + + fpath, fname = os.path.split(program) + if fpath: + if is_exe(program): + return program + else: + for path in os.environ["PATH"].split(os.pathsep): + path = path.strip('"') + exe_file = os.path.join(path, program) + if is_exe(exe_file): + return exe_file + return None + +# +PJ_ROOT_PATH = "../../../" + +# CPP is needed by pycparser. +CPP_PATH = which("cpp") +if not CPP_PATH: + print 'Error: need to have cpp in PATH' + sys.exit(1) + +# Hardcoded! +if sys.platform == 'win32': + PYCPARSER_DIR="C:/devs/tools/pycparser" +elif sys.platform == "linux2": + PYCPARSER_DIR="/home/bennylp/Desktop/opt/src/pycparser-master" +else: + PYCPARSER_DIR="/Library/Python/2.7/site-packages/pycparser" + +if not os.path.exists(PYCPARSER_DIR + '/utils/fake_libc_include'): + print "Error: couldn't find pycparser utils in '%s'" % PYPARSER_DIR + sys.exit(1) + +# Heading, to be placed before the source files +C_HEADING_SECTION = """ +#define PJ_AUTOCONF 1 +#define jmp_buf int +#define __attribute__(x) +""" + +# CPP (C preprocessor) settings +CPP_CFLAGS = [ + '-I' + PYCPARSER_DIR + '/utils/fake_libc_include', + "-I" + PJ_ROOT_PATH + "pjlib/include", + "-I" + PJ_ROOT_PATH + "pjlib-util/include", + "-I" + PJ_ROOT_PATH + "pjnath/include", + "-I" + PJ_ROOT_PATH + "pjmedia/include", + "-I" + PJ_ROOT_PATH + "pjsip/include" + ] + + +class SymbolVisitor(pycparser.c_ast.NodeVisitor): + def __init__(self, names): + self.nodeDict = {} + for name in names: + self.nodeDict[name] = None + + def _add(self, node): + if self.nodeDict.has_key(node.name): + self.nodeDict[node.name] = node + + def visit_Struct(self, node): + self._add(node) + + def visit_Enum(self, node): + self._add(node) + + def visit_Typename(self, node): + self._add(node) + + def visit_Typedef(self, node): + self._add(node) + + +TEMP_FILE="tmpsrc.h" + +class SymbolImporter: + """ + Import C selected declarations from C source file and move it + to another file. + + Parameters: + - listfile Path of file containing list of C source file + and identifier names to be imported. The format + of the listfile is: + + filename name1 name2 name3 + + for example: + + pj/sock_qos.h pj_qos_type pj_qos_flag + pj/types.h pj_status_t PJ_SUCCESS + """ + def __init__(self): + pass + + def process(self, listfile, outfile): + + # Read listfile + f = open(listfile) + lines = f.readlines() + f.close() + + # Process each line in list file, while generating the + # temporary C file to be processed by pycparser + f = open(TEMP_FILE, "w") + f.write(C_HEADING_SECTION) + names = [] + fcnt = 0 + for line in lines: + spec = line.split() + if len(spec) < 2: + continue + fcnt += 1 + f.write("#include <%s>\n" % spec[0]) + names.extend(spec[1:]) + f.close() + print 'Parsing %d symbols from %d files..' % (len(names), fcnt) + + # Parse the temporary C file + ast = pycparser.parse_file(TEMP_FILE, use_cpp=True, cpp_path=CPP_PATH, cpp_args=CPP_CFLAGS) + os.remove(TEMP_FILE) + + # Filter the declarations that we wanted + print 'Filtering..' + visitor = SymbolVisitor(names) + visitor.visit(ast) + + # Print symbol declarations to outfile + print 'Writing declarations..' + f = open(outfile, 'w') + f.write("// This file is autogenerated by importsym script, do not modify!\n\n") + gen = pycparser.c_generator.CGenerator() + for name in names: + node = visitor.nodeDict[name] + if not node: + print " ** Warning: declaration for '%s' is not found **" % k + else: + print " writing '%s'.." % name + output = gen.visit(node) + ";\n\n" + f.write(output) + f.close() + print "Done." + + +if __name__ == "__main__": + print "Importing symbols: 'symbols.lst' --> 'symbols.i'" + si = SymbolImporter() + si.process("symbols.lst", "symbols.i") + try: + os.remove("lextab.py") + except OSError: + pass + try: + os.remove("yacctab.py") + except OSError: + pass + + \ No newline at end of file -- cgit v1.2.3