blob: 94377d881a827375ada1237d6e4916342b0aed87 [file] [log] [blame]
# $Id: importsym.py 4704 2014-01-16 05:30:46Z ming $
#
# 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