summaryrefslogtreecommitdiff
path: root/pjsip-apps/src/swig/importsym.py
diff options
context:
space:
mode:
Diffstat (limited to 'pjsip-apps/src/swig/importsym.py')
-rw-r--r--pjsip-apps/src/swig/importsym.py193
1 files changed, 193 insertions, 0 deletions
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