[Synopsis-cvs] Synopsis/Synopsis/Synopsis/Parser/C Makefile,NONE,1.1 Trace.hh,NONE,1.1 Translator.cc,NONE,1.1 Translator.hh,NONE,1.1 __init__.py,NONE,1.1 ctool.cc,NONE,1.1
Stefan Seefeld stefan at users.sourceforge.netWed Aug 20 01:14:04 UTC 2003
- Previous message: [Synopsis-cvs] Synopsis/Synopsis/Synopsis/Parser Makefile,1.15,1.16
- Next message: [Synopsis-cvs] Synopsis/Synopsis local.mk.in,1.10,1.11 configure.in,1.16,1.17
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Update of /cvsroot/synopsis/Synopsis/Synopsis/Parser/C
In directory sc8-pr-cvs1:/tmp/cvs-serv2431/Synopsis/Parser/C
Added Files:
Makefile Trace.hh Translator.cc Translator.hh __init__.py
ctool.cc
Log Message:
first steps towards a C parser backend (based on the ctool)
--- NEW FILE: Makefile ---
# $Id: Makefile,v 1.1 2003/08/20 02:16:37 stefan Exp $
#
# This source file is a part of the Synopsis Project
# Copyright (C) 2003 Stefan Seefeld
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library 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
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
# MA 02139, USA.
SHELL = /bin/sh
ifeq (,$(findstring $(MAKECMDGOALS), clean distclean))
ifeq (,$(findstring $(action), clean distclean))
include ../../../local.mk
endif
endif
ifeq '$(python_prefix)' '/usr'
CPPFLAGS+= -D PYTHON_INCLUDE="$(python_include)"
else
CPPFLAGS+= -I $(python_prefix)/include -D PYTHON_INCLUDE="$(python_include)"
endif
SRC := Translator.cc ctool.cc
OBJ := $(patsubst %.cc, %.o, $(SRC))
DEP := $(patsubst %.cc, %.d, $(SRC))
MODULE := ctool.$(LIBRARY_EXT)
PY := __init__.py __init__.pyc $(MODULE)
all: $(MODULE)
$(MODULE): $(OBJ)
$(CXX) -shared $(CPPFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
clean:
distclean: clean
install:
mkdir -p $(packagedir)/Synopsis/Parser/C
install -m 644 $(PY) $(packagedir)/Synopsis/Parser/C
%.o : %.cc
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
%.d : %.cc
$(SHELL) -ec '$(MAKEDEP) $(CPPFLAGS) $< \
| sed "s/$*\\.o[ :]*/$*\\.d $*\\.o : /g" > $@'
ifeq (,$(filter $(MAKECMDGOALS), depend doc clean distclean maintainer-clean))
-include $(DEP)
endif
--- NEW FILE: Trace.hh ---
// $Id: Trace.hh,v 1.1 2003/08/20 02:16:37 stefan Exp $
//
// This file is a part of Synopsis.
// Copyright (C) 2003 Stefan Seefeld
//
// Synopsis 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.
//
// $Log: Trace.hh,v $
// Revision 1.1 2003/08/20 02:16:37 stefan
// first steps towards a C parser backend (based on the ctool)
//
//
#ifndef _Trace_hh
#define _Trace_hh
#include <iostream>
#include <string>
#if 1
class Trace
{
public:
Trace(const std::string &s) : scope(s)
{
std::cout << indent() << "entering " << scope << std::endl;
++level;
}
~Trace()
{
--level;
std::cout << indent() << "leaving " << scope << std::endl;
}
private:
std::string indent() { return std::string(level, ' ');}
static int level;
std::string scope;
};
#else
class Trace
{
public:
Trace(const std::string &) {}
~Trace() {}
};
#endif
#endif
--- NEW FILE: Translator.cc ---
// $Id: Translator.cc,v 1.1 2003/08/20 02:16:37 stefan Exp $
//
// This file is a part of Synopsis.
// Copyright (C) 2003 Stefan Seefeld
//
// Synopsis 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.
//
// $Log: Translator.cc,v $
// Revision 1.1 2003/08/20 02:16:37 stefan
// first steps towards a C parser backend (based on the ctool)
//
//
#include <ctool/ctool.h>
#include "Translator.hh"
Translator::Translator()
{
}
Translator::~Translator()
{
}
void Translator::traverse_base(BaseType *)
{
}
void Translator::traverse_ptr(PtrType *)
{
}
void Translator::traverse_array(ArrayType *)
{
}
void Translator::traverse_bit_field(BitFieldType *)
{
}
void Translator::traverse_function(FunctionType *)
{
}
void Translator::traverse_symbol(Symbol *)
{
}
void Translator::traverse_int(IntConstant *)
{
}
void Translator::traverse_uint(UIntConstant *)
{
}
void Translator::traverse_float(FloatConstant *)
{
}
void Translator::traverse_char(CharConstant *)
{
}
void Translator::traverse_string(StringConstant *)
{
}
void Translator::traverse_array(ArrayConstant *)
{
}
void Translator::traverse_enum(EnumConstant *)
{
}
void Translator::traverse_variable(Variable *)
{
}
void Translator::traverse_call(FunctionCall *)
{
}
void Translator::traverse_unary(UnaryExpr *)
{
}
void Translator::traverse_binary(BinaryExpr *)
{
}
void Translator::traverse_trinary(TrinaryExpr *)
{
}
void Translator::traverse_assign(AssignExpr *)
{
}
void Translator::traverse_rel(RelExpr *)
{
}
void Translator::traverse_cast(CastExpr *)
{
}
void Translator::traverse_sizeof(SizeofExpr *)
{
}
void Translator::traverse_index(IndexExpr *)
{
}
void Translator::traverse_label(Label *)
{
}
void Translator::traverse_decl(Decl *)
{
}
void Translator::traverse_statement(Statement *)
{
}
void Translator::traverse_file_line(FileLineStemnt *)
{
}
void Translator::traverse_include(InclStemnt *)
{
}
void Translator::traverse_end_include(EndInclStemnt *)
{
}
void Translator::traverse_expression(ExpressionStemnt *)
{
}
void Translator::traverse_if(IfStemnt *)
{
}
void Translator::traverse_switch(SwitchStemnt *)
{
}
void Translator::traverse_for(ForStemnt *)
{
}
void Translator::traverse_while(WhileStemnt *)
{
}
void Translator::traverse_do_while(DoWhileStemnt *)
{
}
void Translator::traverse_goto(GotoStemnt *)
{
}
void Translator::traverse_return(ReturnStemnt *)
{
}
void Translator::traverse_declaration(DeclStemnt *)
{
}
void Translator::traverse_typedef(TypedefStemnt *)
{
}
void Translator::traverse_block(Block *)
{
}
void Translator::traverse_function_definition(FunctionDef *)
{
}
void Translator::traverse_unit(TransUnit *)
{
}
--- NEW FILE: Translator.hh ---
// $Id: Translator.hh,v 1.1 2003/08/20 02:16:37 stefan Exp $
//
// This file is a part of Synopsis.
// Copyright (C) 2003 Stefan Seefeld
//
// Synopsis 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.
//
// $Log: Translator.hh,v $
// Revision 1.1 2003/08/20 02:16:37 stefan
// first steps towards a C parser backend (based on the ctool)
//
//
#ifndef _Translator_hh
#define _Translator_hh
#include <iostream>
#include <string>
#include <vector>
#include <ctool/Traversal.h>
class Translator : public Traversal
{
public:
Translator();
virtual ~Translator();
virtual void traverse_base(BaseType *);
virtual void traverse_ptr(PtrType *);
virtual void traverse_array(ArrayType *);
virtual void traverse_bit_field(BitFieldType *);
virtual void traverse_function(FunctionType *);
virtual void traverse_symbol(Symbol *);
virtual void traverse_int(IntConstant *);
virtual void traverse_uint(UIntConstant *);
virtual void traverse_float(FloatConstant *);
virtual void traverse_char(CharConstant *);
virtual void traverse_string(StringConstant *);
virtual void traverse_array(ArrayConstant *);
virtual void traverse_enum(EnumConstant *);
virtual void traverse_variable(Variable *);
virtual void traverse_call(FunctionCall *);
virtual void traverse_unary(UnaryExpr *);
virtual void traverse_binary(BinaryExpr *);
virtual void traverse_trinary(TrinaryExpr *);
virtual void traverse_assign(AssignExpr *);
virtual void traverse_rel(RelExpr *);
virtual void traverse_cast(CastExpr *);
virtual void traverse_sizeof(SizeofExpr *);
virtual void traverse_index(IndexExpr *);
virtual void traverse_label(Label *);
virtual void traverse_decl(Decl *);
virtual void traverse_statement(Statement *);
virtual void traverse_file_line(FileLineStemnt *);
virtual void traverse_include(InclStemnt *);
virtual void traverse_end_include(EndInclStemnt *);
virtual void traverse_expression(ExpressionStemnt *);
virtual void traverse_if(IfStemnt *);
virtual void traverse_switch(SwitchStemnt *);
virtual void traverse_for(ForStemnt *);
virtual void traverse_while(WhileStemnt *);
virtual void traverse_do_while(DoWhileStemnt *);
virtual void traverse_goto(GotoStemnt *);
virtual void traverse_return(ReturnStemnt *);
virtual void traverse_declaration(DeclStemnt *);
virtual void traverse_typedef(TypedefStemnt *);
virtual void traverse_block(Block *);
virtual void traverse_function_definition(FunctionDef *);
virtual void traverse_unit(TransUnit *);
private:
};
#endif
--- NEW FILE: __init__.py ---
"""Parser for C using CTool for low-level parsing.
This parser is written entirely in C++, and compiled into shared libraries for
use by python.
"""
#
# configure for the parser you want here...
#
try:
from ctool import parse, usage
except:
import sys
print sys.exc_type, sys.exc_value
# THIS-IS-A-PARSER
--- NEW FILE: ctool.cc ---
// $Id: ctool.cc,v 1.1 2003/08/20 02:16:37 stefan Exp $
//
// This file is a part of Synopsis.
// Copyright (C) 2003 Stefan Seefeld
//
// Synopsis 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.
//
// $Log: ctool.cc,v $
// Revision 1.1 2003/08/20 02:16:37 stefan
// first steps towards a C parser backend (based on the ctool)
//
//
#include <ctool/ctool.h>
#include "Translator.hh"
#include "Trace.hh"
#include <signal.h>
#include <sys/wait.h>
#ifdef PYTHON_INCLUDE
# include PYTHON_INCLUDE
#else
# include <Python.h>
#endif
#include <fstream>
bool verbose;
// If true then everything but what's in the main file will be stripped
bool syn_main_only;
bool syn_extract_tails;
std::string syn_cpp;
bool syn_multi_files;
// If set then this is stripped from the start of all filenames
const char* syn_basename = "";
// If set then this is the prefix for the filename to store links to
const char* syn_syntax_prefix = 0;
// A place to temporarily store Python's thread state
PyThreadState *pythread_save;
namespace
{
//. Override unexpected() to print a message before we abort
void unexpected()
{
std::cout << "Warning: Aborting due to unexpected exception." << std::endl;
throw std::bad_exception();
}
void getopts(PyObject *args, std::vector<const char *> &cppflags,
std::vector<const char *> &ctflags,
PyObject* config)
{
verbose = false;
syn_main_only = false;
syn_extract_tails = false;
syn_multi_files = false;
#define IsType(obj, type) (Py##type##_Check(obj))
#define OPT_FLAG(syn_flag, config_name) \
if ((value = PyObject_GetAttrString(config, config_name)) != 0)\
syn_flag = PyObject_IsTrue(value);\
Py_XDECREF(value);
#define OPT_STRING(syn_name, config_name) \
if ((value = PyObject_GetAttrString(config, config_name)) != 0)\
{ if (!IsType(value, String)) throw "Error: " config_name " must be a string.";\
syn_name = PyString_AsString(value);\
}\
Py_XDECREF(value);
// Check config object first
if (config)
{
PyObject* value;
OPT_FLAG(verbose, "verbose");
OPT_FLAG(syn_main_only, "main_file");
// Grab the include paths
if ((value = PyObject_GetAttrString(config, "include_path")) != 0)
{
if (!IsType(value, List))
{
std::cerr << "Error: include_path must be a list of strings." << std::endl;
exit(1);
}
// Loop through the include paths
for (int i=0, end=PyList_Size(value); i < end; i++)
{
PyObject* item = PyList_GetItem(value, i);
if (!item || !IsType(item, String))
{
std::cerr << "Error: include_path must be a list of strings." << std::endl;
exit(1);
}
// mem leak.. how to fix?
char* buf = new char[PyString_Size(item)+3];
strcpy(buf, "-I");
strcat(buf, PyString_AsString(item));
cppflags.push_back(buf);
} // for
}
Py_XDECREF(value);
// Grab the list of defines
if ((value = PyObject_GetAttrString(config, "defines")) != 0)
{
if (!IsType(value, List))
{
std::cerr << "Error: defines must be a list of strings." << std::endl;
exit(1);
}
// Loop through the include paths
for (int i=0, end=PyList_Size(value); i < end; i++)
{
PyObject* item = PyList_GetItem(value, i);
if (!item || !IsType(item, String))
{
std::cerr << "Error: defines must be a list of strings." << std::endl;
exit(1);
}
// mem leak.. how to fix?
char* buf = new char[PyString_Size(item)+3];
strcpy(buf, "-D");
strcat(buf, PyString_AsString(item));
cppflags.push_back(buf);
} // for
}
Py_XDECREF(value);
// Basename is the prefix to strip from filenames
OPT_STRING(syn_basename, "basename");
// Extract tails tells the parser to find tail comments
OPT_FLAG(syn_extract_tails, "extract_tails");
// 'syntax_prefix' defines the prefix for the filename to write syntax hilite info to
OPT_STRING(syn_syntax_prefix, "syntax_prefix");
// 'preprocessor' defines the preprocessor string
char *temp_string = 0;
OPT_STRING(temp_string, "preprocessor");
syn_cpp = temp_string ? temp_string : "cpp";
// If multiple_files is set then the parser handles multiple files
// included from the main one at the same time (they get into the AST
OPT_FLAG(syn_multi_files, "multiple_files");
} // if config
#undef OPT_STRING
#undef OPT_FLAG
#undef IsType
// Now check command line args
size_t argsize = PyList_Size(args);
for (size_t i = 0; i != argsize; ++i)
{
const char *argument = PyString_AsString(PyList_GetItem(args, i));
if (strncmp(argument, "-I", 2) == 0)
{
cppflags.push_back(argument);
if (strlen(argument) == 2)
cppflags.push_back(PyString_AsString(PyList_GetItem(args, ++i)));
}
else if (strncmp(argument, "-D", 2) == 0)
{
cppflags.push_back(argument);
if (strlen(argument) == 2)
cppflags.push_back(PyString_AsString(PyList_GetItem(args, ++i)));
}
else if (strcmp(argument, "-v") == 0)
verbose = true;
else if (strcmp(argument, "-m") == 0)
syn_main_only = true;
else if (strcmp(argument, "-b") == 0)
syn_basename = PyString_AsString(PyList_GetItem(args, ++i));
else if (strcmp(argument, "-t") == 0)
syn_extract_tails = true;
}
}
char *RunPreprocessor(const char *file, const std::vector<const char *> &flags)
{
static char dest[1024];
strcpy(dest, "/tmp/synopsis-XXXXXX");
int temp_fd = mkstemp(dest);
if (temp_fd == -1)
{
perror("RunPreprocessor");
exit(1);
}
// Not interested in the open file, just the unique filename
close(temp_fd);
// Release Python's global interpreter lock
pythread_save = PyEval_SaveThread();
switch(fork())
{
case 0:
{
std::vector<const char *> args;
char *cc = getenv("CC");
if (cc)
{
// separate command and arguments
do
{
args.push_back(cc);
cc = strchr(cc, ' '); // find next whitespace...
while (cc && *cc == ' ') *cc++ = '\0'; // ...and skip to next non-ws
}
while (cc && *cc != '\0');
}
else
{
args.push_back("cpp");
}
args.insert(args.end(), flags.begin(), flags.end());
args.push_back("-C"); // keep comments
args.push_back("-E"); // stop after preprocessing
args.push_back("-o"); // output to...
args.push_back(dest);
//args.push_back("-x"); // language c++
//args.push_back("c++");
args.push_back(file);
if (verbose)
{
std::cout << "calling external preprocessor\n" << args[0];
for (std::vector<const char *>::iterator i = args.begin(); i != args.end(); ++i)
std::cout << ' ' << *i;
std::cout << std::endl;
}
args.push_back(0);
execvp(args[0], (char **)&*args.begin());
perror("cannot invoke compiler");
exit(-1);
break;
}
case -1:
perror("RunPreprocessor");
exit(-1);
break;
default:
{
int status;
wait(&status);
if (status != 0)
{
if (WIFEXITED(status))
std::cout << "exited with status " << WEXITSTATUS(status) << std::endl;
else if (WIFSIGNALED(status))
std::cout << "stopped with status " << WTERMSIG(status) << std::endl;
exit(1);
}
}
} // switch
return dest;
}
void sighandler(int signo)
{
std::string signame;
switch (signo)
{
case SIGABRT:
signame = "Abort";
break;
case SIGBUS:
signame = "Bus error";
break;
case SIGSEGV:
signame = "Segmentation Violation";
break;
default:
signame = "unknown";
break;
};
// SWalker *instance = SWalker::instance();
#if 0
std::cerr << signame << " caught while processing " << instance->current_file()->filename()
<< " at line " << instance->current_lineno()
<< std::endl;
#endif
std::cerr << signame << " caught" << std::endl;
exit(-1);
}
void RunCTool(const char *src, const char *file,
const std::vector<const char *> &args,
PyObject *ast, PyObject *types, PyObject *declarations,
PyObject* files)
{
Trace trace("RunCTool");
std::set_unexpected(unexpected);
struct sigaction olda;
struct sigaction newa;
newa.sa_handler = &sighandler;
sigaction(SIGSEGV, &newa, &olda);
sigaction(SIGBUS, &newa, &olda);
sigaction(SIGABRT, &newa, &olda);
Project *prj = new Project();
// TransUnit *unit = prj->parse(file_list[i], use_cpp, cpp_dir,
// keep_cpp_file, cpp_file, cpp_cmmd, cd_cmmd);
sigaction(SIGABRT, &olda, 0);
sigaction(SIGBUS, &olda, 0);
sigaction(SIGSEGV, &olda, 0);
}
void do_parse(const char *src,
const std::vector<const char *>& cppargs,
const std::vector<const char *>& ctargs,
PyObject *ast, PyObject *types, PyObject *declarations,
PyObject* files)
{
// Run the preprocessor
char *cppfile = RunPreprocessor(src, cppargs);
// Run CTool to generate the AST
RunCTool(src, cppfile, ctargs, ast, types, declarations, files);
unlink(cppfile);
}
PyObject *ctoolParse(PyObject *self, PyObject *args)
{
Trace trace("ctoolParse");
char *src;
PyObject *parserargs, *types, *declarations, *config, *ast;
if (!PyArg_ParseTuple(args, "sO!O", &src, &PyList_Type, &parserargs, &config))
return 0;
std::vector<const char *> cppargs;
std::vector<const char *> ctargs;
getopts(parserargs, cppargs, ctargs, config);
if (!src || *src == '\0')
{
std::cerr << "No source file" << std::endl;
exit(-1);
}
// Make AST object
#define assertObject(pyo) if (!pyo) PyErr_Print(); assert(pyo)
PyObject* ast_module = PyImport_ImportModule("Synopsis.Core.AST");
assertObject(ast_module);
ast = PyObject_CallMethod(ast_module, "AST", "");
assertObject(ast);
PyObject* files = PyObject_CallMethod(ast, "files", "");
assertObject(files);
declarations = PyObject_CallMethod(ast, "declarations", "");
assertObject(declarations);
types = PyObject_CallMethod(ast, "types", "");
assertObject(types);
#undef assertObject
do_parse(src, cppargs, ctargs, ast, types, declarations, files);
Py_DECREF(ast_module);
Py_DECREF(declarations);
Py_DECREF(files);
Py_DECREF(types);
return ast;
}
PyObject *ctoolUsage(PyObject *self, PyObject *)
{
Trace trace("ctoolUsage");
std::cout
<< " -I<path> Specify include path to be used by the preprocessor\n"
<< " -D<macro> Specify macro to be used by the preprocessor\n"
<< " -m Unly keep declarations from the main file\n"
<< " -b basepath Strip basepath from start of filenames" << std::endl;
Py_INCREF(Py_None);
return Py_None;
}
PyMethodDef ctool_methods[] =
{
{(char*)"parse", ctoolParse, METH_VARARGS},
{(char*)"usage", ctoolUsage, METH_VARARGS},
{0, 0}
};
};
extern "C" void initctool()
{
PyObject *m = Py_InitModule((char*)"ctool", ctool_methods);
PyObject_SetAttrString(m, (char*)"version", PyString_FromString("0.1"));
}
- Previous message: [Synopsis-cvs] Synopsis/Synopsis/Synopsis/Parser Makefile,1.15,1.16
- Next message: [Synopsis-cvs] Synopsis/Synopsis local.mk.in,1.10,1.11 configure.in,1.16,1.17
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the Synopsis-changes mailing list