Commit 5c660bd6 authored by Sergio Costas's avatar Sergio Costas

First changes to separate the code in several classes

parent b5dd96eb
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
#!/usr/bin/env python3
# Copyright 2017 (C) Raster Software Vigo (Sergio Costas)
#
# This file is part of CRUST
#
# CRUST 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 3 of the License.
#
# CRUST 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, see <http://www.gnu.org/licenses/>
class crust_definitions(object):
version = "0.1a1"
# when a variable hasn't been assigned yet
VALUE_UNINITIALIZED = 0
# when a variable has been initialized to a non NULL value
VALUE_NULL = 1
# when a variable has been initialized to a NULL value
VALUE_NOT_NULL = 2
# when a variable has been initialized to a value that can be NULL or not NULL
VALUE_NOT_NULL_OR_NULL = 3
# when a variable NOT NULL is presumed to have been freed after have been passed on to a function
VALUE_FREED = 4
# when a variable NULL_OR_NOT_NULL is presumed to have been freed after have been passed on to a function
VALUE_FREED_OR_NULL = 5
# the variable is global, so it is presumed that, when used, it is INITIALIZED_OR_NULL, and when assigned is FREED
VALUE_GLOBAL = 6
# the variable is a function
VALUE_FUNCTION = 7
CONDITION_FALSE = 0
CONDITION_TRUE = 1
CONDITION_FALSE_TRUE = 2
MSG_NORMAL = 0
MSG_WARNING = 1
MSG_ERROR = 2
MSG_CRITICAL = 3
TYPE_NO_MATTER = 0
TYPE_NO_CRUST = 1
TYPE_CRUST = 2
state_str = ["VALUE_UNINITIALIZED", "VALUE_NULL", "VALUE_NOT_NULL", "VALUE_NOT_NULL_OR_NULL", "VALUE_FREED", "VALUE_FREED_OR_NULL", "VALUE_GLOBAL", "VALUE_FUNCTION" ]
\ No newline at end of file
#!/usr/bin/env python3
# Copyright 2017 (C) Raster Software Vigo (Sergio Costas)
#
# This file is part of CRUST
#
# CRUST 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 3 of the License.
#
# CRUST 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, see <http://www.gnu.org/licenses/>
from ctypes import *
from crust import tokens
import sys
import subprocess
import gettext
import glob
import os
import pkg_resources
import copy
from crust.crust_definitions import crust_definitions
_ = gettext.gettext
class crust_open(crust_definitions):
""" Manages the source file to be read """
def __init__(self, headerpath, libpath):
self.id_counter = 0
with open(headerpath, "r") as header:
do_process = False
self.fields = []
for line in header.readlines():
line = line.strip()
if line == "":
continue
if line == "struct AST {":
do_process = True
continue
if line == "};":
do_process = False
break
if not do_process:
continue
line = line.replace(";", "")
if line.startswith("int "):
ctype = c_int
name = line[4:].strip()
elif line.startswith("char *"):
ctype = c_char_p
name = line[6:].strip()
elif line.startswith("bool "):
ctype = c_bool
name = line[5:].strip()
elif line.startswith("struct AST *"):
ctype = POINTER(self.AST_leaf)
name = line[12:].strip()
elif line.startswith("long long int"):
ctype = c_int64
name = line[13:].strip()
elif line.startswith("double"):
ctype = c_double
name = line[6:].strip()
else:
print("Unknown type '{:s}'".format(line))
sys.exit(0)
self.fields.append( (name, ctype) )
try:
self.AST_leaf._fields_ = self.fields[:]
except:
pass
cdll.LoadLibrary(libpath)
self.libcrust = CDLL(libpath)
self.libcrust.parse_file.restype = POINTER(self.AST_leaf)
self.libcrust.parse_file.argtypes = [c_bool, c_char_p]
self.libcrust.parse_data.restype = POINTER(self.AST_leaf)
self.libcrust.parse_data.argtypes = [c_bool, c_char_p, c_void_p, c_int]
self.libcrust.set_debug_values.argtypes = [c_int, c_int]
class VarNotFoundException(Exception):
pass
class FunctionNotFoundException(Exception):
pass
class AST_leaf(Structure):
pass
class AST_node(object):
def __init__(self):
super().__init__()
self.status = crust_definitions.VALUE_UNINITIALIZED
self.init_line = None
self.type = ""
self.name = ""
self.line = -1
self.next = None
self.intval = 0
self.floatval = 0.0
self.uid = None
def copy(self):
retval = crust_open.AST_node()
for element in self.__dict__:
setattr(retval, element, getattr(self, element))
return retval
def __str__(self):
first = True
salida = ""
for element in self.__dict__:
if not first:
salida += ", "
first = False
dato = getattr(self, element)
salida += "{:s}: ".format(element)
if dato is None:
salida += "None"
continue
if isinstance(dato, list):
salida += "pointer"
continue
salida += str(dato)
return salida
def read_file(self, filename, verbose, includes, defines, include_files, disable_cpp = False, write_preprocesed = None):
self.filename = os.path.abspath(filename)
if disable_cpp:
with open(filename,"r") as source_file:
datacode = ""
for line in source_file.readlines():
line = line.strip()
if line == "":
datacode += "\n"
continue
datacode += line+"\n"
datacode = datacode.encode("latin-1")
else:
params = ["cpp", filename, "-DENABLE_CRUST_TAGS -DENABLE_CRUST"]
for p in includes:
params.append("-I{:s}".format(p))
for p in defines:
params.append("-D{:s}".format(p))
for p in include_files:
params.append("-include")
params.append(p)
rv = subprocess.run(params, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if (rv.returncode != 0):
print (rv.stderr.decode("utf-8"))
return None
datacode = rv.stdout
datasize = len(datacode)
if write_preprocesed is not None:
with open(write_preprocesed,"wb") as preproc:
preproc.write(datacode)
retval = self.libcrust.parse_data(c_bool(verbose), c_char_p(filename.encode("utf8")), datacode, datasize)
if retval:
tree = self._fix_tree(retval)
retval = None
self.libcrust.free_all()
else:
sys.exit(-1)
return tree
def _fix_tree(self, node):
""" Creates a list with each statement in order, ready to be "executed" """
retval = []
while(node):
node = node.contents
newnode = self.AST_node()
for element in self.fields:
name = element[0]
data = getattr(node, name)
if data is not None:
if (name == "type"):
data = tokens.tokens.get_token(data)
if data == "END_BLOCK":
newnode.uid = self.id_counter
self.id_counter += 1
elif isinstance(data, bytes):
data = data.decode("utf8")
elif isinstance(data, POINTER(self.AST_leaf)):
if name == "next":
data = None
elif (name == "function_params"):
tmpdata = self._fix_tree(data)
if tmpdata is not None:
data = []
# if this node is a function call or a function definition, ensure
# that there is always a list here, even if it has no params
for tmp in tmpdata:
if tmp.type != "EMPTY_DECLARATOR":
data.append(tmp)
else:
data = None
else:
data = self._fix_tree(data)
setattr(newnode, element[0], data)
retval.append(newnode)
node = node.next
if len(retval) == 0:
retval = None
return retval
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment