[Synopsis-changes] Synopsis/Synopsis/Synopsis/Parsers/Cpp Parser.py,1.1,1.2 cpp.cc,1.2,1.3
Stefan Seefeld stefan at synopsis.fresco.orgSun Jan 4 02:08:34 UTC 2004
- Previous message: [Synopsis-changes] Synopsis/Synopsis/Synopsis/Parsers/Cpp Parser.py,NONE,1.1 __init__.py,NONE,1.1
- Next message: [Synopsis-changes] Synopsis/Synopsis/include - New directory
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Update of /cvs/synopsis/Synopsis/Synopsis/Parsers/Cpp
In directory frida:/tmp/cvs-serv29668/Synopsis/Parsers/Cpp
Modified Files:
Parser.py cpp.cc
Log Message:
create SourceFile, Macro, Include nodes, as well as a macro map store.
Index: Parser.py
===================================================================
RCS file: /cvs/synopsis/Synopsis/Synopsis/Parsers/Cpp/Parser.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -p -d -r1.1 -r1.2
--- Parser.py 2 Jan 2004 03:58:47 -0000 1.1
+++ Parser.py 4 Jan 2004 02:08:26 -0000 1.2
@@ -17,6 +17,10 @@ class Parser(Processor):
preprocessor = Parameter(None, 'the preprocessor to use')
emulate_compiler = Parameter('c++', 'a compiler to emulate')
flags = Parameter([], 'list of preprocessor flags such as -I or -D')
+ cpp_output = Parameter(None, 'filename for preprocessed file')
+ cpp_mmap = Parameter(None, 'output macro calls for the given file')
+ prefix = Parameter(None, 'prefix to strip off from the filename')
+ language = Parameter('C', 'source code programming language of the given input file')
def process(self, ast, **kwds):
@@ -30,7 +34,9 @@ class Parser(Processor):
flags += map(lambda x:'-I%s'%x, info.include_paths)
flags += map(lambda x:'-D%s=%s'%(x[0], x[1]), info.macros)
for file in self.input:
- self.ast = ucpp.parse(self.ast, file, self.output, flags, self.verbose, self.debug)
+ self.ast = ucpp.parse(self.ast, file, self.prefix,
+ self.cpp_output, self.cpp_mmap,
+ self.language, flags, self.verbose, self.debug)
else:
print 'not implemented yet: spawn external preprocessor'
return self.output_and_return_ast()
Index: cpp.cc
===================================================================
RCS file: /cvs/synopsis/Synopsis/Synopsis/Parsers/Cpp/cpp.cc,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -p -d -r1.2 -r1.3
--- cpp.cc 2 Jan 2004 03:58:05 -0000 1.2
+++ cpp.cc 4 Jan 2004 02:08:26 -0000 1.3
@@ -8,83 +8,171 @@
#include <Python.h>
#include <vector>
+#include <map>
+#include <set>
+#include <string>
#include <iostream>
+#include <fstream>
#include <cstring>
#include <cstdio>
+namespace
+{
+
int verbose = 0;
int debug = 0;
+PyObject *ast;
+const char *prefix = 0;
+PyObject *language = 0;
+PyObject *source_file = 0;
+const char *input = 0;
-extern "C"
+//. MacroMap is a map from preprocessed file positions to input file positions.
+//. This may eventually be part of the AST (if more than just declarations are
+//. supported), but for now it is persisted into a file in parallel so it can be
+//. read in by C/C++ parsers for correct symbol cross referencing.
+struct MacroMap
{
- // ucpp_main is the renamed main() func of ucpp, since it is included in this
- // module
- int ucpp_main(int argc, char** argv);
-
- //. This function is a callback from the ucpp code to store macro
- //. expansions
- void synopsis_macro_hook(const char *name, int line, int start, int end, int diff)
+ struct Node
{
- if (debug)
- std::cout << "macro : " << name << ' ' << line << ' ' << start << ' ' << end << ' ' << diff << std::endl;
-#if 0
- LinkMap::instance()->add(name, line, start, end, diff);
-#endif
- }
+ std::string name;
+ int start;
+ int end;
+ enum Type { START, END } type;
+ int diff;
+ bool operator <(const Node &other) const
+ {
+ return start < other.start;
+ }
+ };
+ typedef std::set<Node> Line;
+ typedef std::map<int, Line> LineMap;
- //. This function is a callback from the ucpp code to store includes
- void synopsis_include_hook(const char *source_file, const char *target_file, int is_macro, int is_next)
+ //. Adds a map at the given line. out_{start,end} define the start and
+ //. past-the-end markers for the macro in the output file. diff defines
+ //. the signed difference to add to the pos.
+ void add(const char *name, int linenum, int start, int end, int diff)
{
- if (debug)
- std::cout << "include : " << source_file << ' ' << target_file << ' ' << is_macro << ' ' << is_next << std::endl;
-#if 0
- // There is not enough code here to make another class..
- FileFilter *filter = FileFilter::instance();
- if (!filter) return;
-
- // Add another Include to the source's SourceFile
- // We don't deal with duplicates here. The Linker's Unduplicator will
- // take care of that.
- //std::cout << "Include: " << source_file << " -> " << target_file << std::endl;
- AST::SourceFile *file = filter->get_sourcefile(source_file);
- AST::SourceFile *target = filter->get_sourcefile(target_file);
- AST::Include *include = new AST::Include(target, is_macro, is_next);
- file->includes().push_back(include);
-#endif
+ Line &line = lines[linenum];
+ Node node;
+ node.name = name; // name isn't really needed. For now keep it for debugging...
+ node.start = start;
+ node.end = end;
+ node.type = Node::START;
+ node.diff = diff;
+ line.insert(node);
}
-
- //. This function is a callback from the ucpp code to store macro
- //. definitions
- void synopsis_define_hook(const char* filename, int line, const char *name, int num_args, const char **args, int vaarg, const char *text)
+ void write(const char *filename)
{
- if (debug)
- std::cout << "define : " << filename << ' ' << line << ' ' << name << ' ' << num_args << ' ' << text << std::endl;
-#if 0
- FileFilter *filter = FileFilter::instance();
- if (!filter) return;
- AST::SourceFile *file = filter->get_sourcefile(filename);
- if (!file->is_main()) return;
- if (!syn_macro_defines) syn_macro_defines = new std::vector<AST::Macro*>;
- AST::Macro::Parameters *params = 0;
- if (args)
- {
- params = new AST::Macro::Parameters;
- for (int i = 0; i < num_args; i++)
- params->push_back(args[i]);
- if (vaarg) params->push_back("...");
- }
- ScopedName macro_name;
- macro_name.push_back(name);
- AST::Macro* macro = new AST::Macro(file, line, macro_name, params, text);
- //. Don't know global NS yet.. Will have to extract these later
- file->declarations().push_back(macro);
- syn_macro_defines->push_back(macro);
-#endif
+ std::ofstream ofs(filename);
+ for (LineMap::iterator i = lines.begin();
+ i != lines.end(); ++i)
+ for (MacroMap::Line::iterator j = (*i).second.begin();
+ j != (*i).second.end(); ++j)
+ ofs << (*i).first << ' '
+ << (*j).name << ' '
+ << (*j).start << ' '
+ << (*j).end << ' '
+ << (*j).type << ' '
+ << (*j).diff << '\n';
}
-};
-namespace
+ LineMap lines;
+} mmap;
+
+const char *strip_prefix(const char *filename, const char *prefix)
{
+ if (!prefix) return filename;
+ size_t length = strlen(prefix);
+ if (length > strlen(filename)) return filename; // ??
+ if (strncmp(filename, prefix, length) == 0)
+ return filename + length;
+ return filename;
+}
+
+//. creates new SourceFile object
+PyObject *create_source_file(const char *filename, bool is_main)
+{
+ PyObject *short_filename = PyString_FromString(strip_prefix(filename, prefix));
+ PyObject *long_filename = PyString_FromString(filename);
+ PyObject *ast_module = PyImport_ImportModule("Synopsis.AST");
+ PyObject *source_file = PyObject_CallMethod(ast_module, "SourceFile", "OOO",
+ short_filename, long_filename, language);
+ Py_DECREF(ast_module);
+ if (is_main) PyObject_CallMethod(source_file, "set_is_main", "i", 1);
+ PyObject *pyfiles = PyObject_CallMethod(ast, "files", 0);
+ PyDict_SetItem(pyfiles, short_filename, source_file);
+ Py_DECREF(short_filename);
+ Py_DECREF(long_filename);
+ Py_DECREF(pyfiles);
+ return source_file;
+}
+
+//. creates new or returns existing SourceFile object
+//. with the given filename
+PyObject *lookup_source_file(const char *filename)
+{
+ PyObject *short_filename = PyString_FromString(strip_prefix(filename, prefix));
+ PyObject *pyfiles = PyObject_CallMethod(ast, "files", 0);
+ PyObject *source_file = PyDict_GetItem(pyfiles, short_filename);
+ if (source_file) Py_INCREF(source_file);
+ Py_DECREF(pyfiles);
+ Py_DECREF(short_filename);
+ return source_file ? source_file : create_source_file(filename, false);
+}
+
+void create_include(PyObject *source, PyObject *target,
+ bool is_macro, bool is_next)
+{
+ PyObject *ast_module = PyImport_ImportModule("Synopsis.AST");
+ PyObject *include = PyObject_CallMethod(ast_module, "Include", "Oii",
+ target, is_macro, is_next);
+ Py_DECREF(ast_module);
+ PyObject *includes = PyObject_CallMethod(source, "includes", 0);
+ PyObject_CallMethod(includes, "append", "O", include);
+ Py_DECREF(includes);
+ Py_DECREF(include);
+}
+
+//. creates new Macro object
+void create_macro(const char *filename, int line,
+ const char *macro_name, int num_args, const char **args,
+ int vaarg, const char *text)
+{
+ PyObject *file = lookup_source_file(filename);
+ PyObject *type = PyString_FromString("macro");
+ PyObject *name = PyTuple_New(1);
+ PyTuple_SET_ITEM(name, 0, PyString_FromString(macro_name));
+ PyObject *params = 0;
+ if (args)
+ {
+ params = PyList_New(vaarg ? num_args + 1 : num_args);
+ for (int i = 0; i < num_args; i++)
+ PyList_SET_ITEM(params, i, PyString_FromString(args[i]));
+ if (vaarg)
+ PyList_SET_ITEM(params, num_args, PyString_FromString("..."));
+ }
+ else
+ {
+ params = Py_None;
+ Py_INCREF(Py_None);
+ }
+ PyObject *pytext = PyString_FromString(text);
+ PyObject *ast_module = PyImport_ImportModule("Synopsis.AST");
+ PyObject *macro = PyObject_CallMethod(ast_module, "Macro", "OiOOOOO",
+ file, line, language, type,
+ name, params, pytext);
+ Py_DECREF(ast_module);
+ Py_DECREF(pytext);
+ Py_DECREF(params);
+ Py_DECREF(name);
+ Py_DECREF(type);
+ Py_DECREF(file);
+ PyObject *declarations = PyObject_CallMethod(ast, "declarations", 0);
+ PyObject_CallMethod(declarations, "append", "O", macro);
+ Py_DECREF(macro);
+ Py_DECREF(declarations);
+}
bool extract(PyObject *list, std::vector<const char *> &out)
{
@@ -98,16 +186,26 @@ bool extract(PyObject *list, std::vector
return true;
}
+extern "C"
+{
+ // ucpp_main is the renamed main() func of ucpp, since it is included in this
+ // module
+ int ucpp_main(int argc, char** argv);
+}
+
PyObject *ucpp_parse(PyObject *self, PyObject *args)
{
- PyObject *ast;
- char *input, *output;
+ char *output;
+ char *mmap_file;
PyObject *py_cppflags;
std::vector<const char *> cppflags;
- if (!PyArg_ParseTuple(args, "OszO!ii",
+ if (!PyArg_ParseTuple(args, "OszszOO!ii",
&ast,
&input,
+ &prefix,
&output,
+ &mmap_file,
+ &language,
&PyList_Type, &py_cppflags,
&verbose,
&debug)
@@ -115,7 +213,7 @@ PyObject *ucpp_parse(PyObject *self, PyO
return 0;
Py_INCREF(ast);
-
+ source_file = create_source_file(input, true);
cppflags.insert(cppflags.begin(), "ucpp");
cppflags.push_back("-C"); // keep comments
@@ -138,9 +236,48 @@ PyObject *ucpp_parse(PyObject *self, PyO
int status = ucpp_main(cppflags.size(), (char **)&*cppflags.begin());
if (status != 0)
std::cerr << "ucpp returned error flag. ignoring error." << std::endl;
+
+ if (mmap_file) mmap.write(mmap_file);
+
return ast;
}
+extern "C"
+{
+ //. This function is a callback from the ucpp code to store macro
+ //. expansions
+ void synopsis_macro_hook(const char *name, int line, int start, int end, int diff)
+ {
+ if (debug)
+ std::cout << "macro : " << name << ' ' << line << ' ' << start << ' ' << end << ' ' << diff << std::endl;
+
+ mmap.add(name, line, start, end, diff);
+ }
+
+ //. This function is a callback from the ucpp code to store includes
+ void synopsis_include_hook(const char *source, const char *target, int is_macro, int is_next)
+ {
+ if (debug)
+ std::cout << "include : " << source << ' ' << target << ' ' << is_macro << ' ' << is_next << std::endl;
+
+ if (strcmp(input, source) != 0) return;
+ PyObject *target_file = lookup_source_file(target);
+ create_include(source_file, target_file, is_macro, is_next);
+ Py_DECREF(target_file);
+ }
+
+ //. This function is a callback from the ucpp code to store macro
+ //. definitions
+ void synopsis_define_hook(const char *filename, int line, const char *name, int num_args, const char **args, int vaarg, const char *text)
+ {
+ if (debug)
+ std::cout << "define : " << filename << ' ' << line << ' ' << name << ' ' << num_args << ' ' << text << std::endl;
+
+ if (strcmp(input, filename) != 0) return;
+ create_macro(filename, line, name, num_args, args, vaarg, text);
+ }
+};
+
PyMethodDef ucpp_methods[] = {{(char*)"parse", ucpp_parse, METH_VARARGS},
{0, 0}};
};
- Previous message: [Synopsis-changes] Synopsis/Synopsis/Synopsis/Parsers/Cpp Parser.py,NONE,1.1 __init__.py,NONE,1.1
- Next message: [Synopsis-changes] Synopsis/Synopsis/include - New directory
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the Synopsis-changes mailing list