123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- #
- # 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!
- # Note for win32:
- # - temporarily comment "#include <pj/compat/socket.h>" in pj/sock.h (line ~29)
- if sys.platform == 'win32':
- PYCPARSER_DIR="D:/work/tool/pycparser-master"
- 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'" % PYCPARSER_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
-
-
|