Commit 86c7bc0f authored by Sergio Costas's avatar Sergio Costas

Now allows to include files with the preprocessor, using the -include directive in the command line

Now allows to store the preprocessed code in a file to be able to analyze it and discover why some code fails to be processed by the FLEX/BISON analyzer

Support for __signed__ statement

Support for __asm__ __volatile__

Support for multiples declarations inside struct ( struct AA { struct BB *a1, *a2; } -> multiple declaration for a1 and a2 )
parent 7f4a7ea2
......@@ -186,7 +186,7 @@ class crust(object):
self.libcrust.set_debug_values(start_line, end_line)
def read_file(self, filename, verbose, includes, defines, disable_cpp = False):
def read_file(self, filename, verbose, includes, defines, include_files, disable_cpp = False, write_preprocesed = None):
if disable_cpp:
with open(filename,"r") as source_file:
......@@ -204,12 +204,18 @@ class crust(object):
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)
......@@ -1704,7 +1710,7 @@ def process_file(lib, filename, parameters):
if (parameters["debug1"] is not None) and (parameters["debug2"] is not None):
lib.set_debug_lines(parameters["debug1"], parameters["debug2"])
try:
tree = lib.read_file(filename, False, parameters["includes"], parameters["defines"], parameters["nocpp"])
tree = lib.read_file(filename, False, parameters["includes"], parameters["defines"], parameters["include_files"], parameters["nocpp"], parameters["preprocessed"])
if tree is None:
return
variables = lib.process_tree(tree, parameters["verbose"])
......@@ -1718,14 +1724,25 @@ def process_file(lib, filename, parameters):
def get_parameters():
parameters = { "includes":[], "files":{}, "defines":[], "warnings":True, "verbose":True, "nocpp":False, "debug1":None, "debug2":None }
parameters = { "includes":[], "include_files":[], "files":{}, "defines":[], "warnings":True, "verbose":True, "nocpp":False, "debug1":None, "debug2":None, "preprocessed":None }
exclude_files = []
store_next = None
for parameter in sys.argv[1:]:
if store_next is not None:
if isinstance(parameters[store_next], list):
parameters[store_next].append(parameter)
else:
parameters[store_next] = parameter
store_next = None
continue
if parameter[0] != '-':
files = glob.glob(parameter)
for f in files:
parameters["files"][f] = True
continue
if parameter == "-include":
store_next = "include_files"
continue
if parameter.startswith("-I"):
parameters["includes"].append(parameter[2:])
continue
......@@ -1738,35 +1755,45 @@ def get_parameters():
if (parameter == "-h") or (parameter == "--help"):
print("CRUST {:s}".format(crust.version))
print("Usage:")
print(" crust [-Iinclude_path] [-I...] [-Ddefine] [-D...] [--nowarnings] [--nocpp] [--quiet] [-eexclude_filename] file.c [file.c] ...")
print(" crust [-Iinclude_path] [-I...] [-Ddefine] [-D...] [-include filename] [-include...] [--nowarnings] [--nocpp] [--quiet] [-eexclude_filename] file.c [file.c] ...")
print()
print(" -I allows to specify paths where the C preprocessor will search for header files. Can be repeated as many times as paths have to be added")
print(" -D allows to specify #defines from command line that the C preprocessor must consider defined. Can be repeated as many times as defines are needed")
print(" --nowarnings will hide the WARNING messages, showing only ERROR and CRITICAL messages")
print(" --nocpp will pass the source code directly to the parser, instead of pass it before through the C preprocessor")
print(" --quiet will not show extra information")
print(" -e allows to specify file names to exclude. This is useful when a filename contains wildcards")
print(" -I allows to specify paths where the C preprocessor will search for header files. Can be repeated as many times as paths have to be added")
print(" -D allows to specify #defines from command line that the C preprocessor must consider defined. Can be repeated as many times as defines are needed")
print(" -include allows to include a file in the final preprocessed code. Can be repeated as many times as defines are needed")
print(" --nowarnings will hide the WARNING messages, showing only ERROR and CRITICAL messages")
print(" --nocpp will pass the source code directly to the parser, instead of pass it before through the C preprocessor")
print(" --quiet will not show extra information")
print(" -e allows to specify file names to exclude. This is useful when a filename contains wildcards")
print(" --preprocessed stores the preprocessed code (this is, after being passed through the C PreProcessor) with the specified filename")
print(" file.c the path to the file or files to analyze. It can contain wildcards, and it is possible to also specify several files")
print()
sys.exit(0)
if parameter == "--preprocessed":
store_next = "preprocessed"
if parameter == "--nocpp":
parameters["nocpp"] = True
continue
if parameter == "--nowarnings":
parameters["warnings"] = False
continue
if parameter == "--quiet":
parameters["verbose"] = False
continue
if parameter.startswith("-e"):
exclude_files.append(parameter[2:])
continue
if parameter.startswith("--debug1="):
try:
parameters["debug1"] = int(parameter[8:])
except:
pass
continue
if parameter.startswith("--debug2="):
try:
parameters["debug2"] = int(parameter[8:])
except:
pass
continue
for f in parameters["files"]:
f2 = os.path.basename(f)
if 0 != exclude_files.count(f2):
......
......@@ -96,13 +96,15 @@ char do_verbose = 0;
"while" { return prepare_leaf(0,0.0,WHILE); }
"NULL" { return prepare_leaf(0,0.0,T_NULL); }
"__builtin_va_list" { return prepare_leaf(0,0.0,VA_LIST); }
"__signed__" { return prepare_leaf(0,0.0,SIGNED); }
"__extension__" { count(); }
"__prog__" { count(); }
"__restrict" { count(); }
"__inline" { count(); }
"__attribute__"{WS}*"((".*"))" { count(); }
"__asm__"{WS}*"(".*")" { count(); }
"__asm__"{WS}*"volatile"{WS}*"(".*")" { count(); }
"__asm__"{WS}+"volatile"{WS}*"(".*")" { count(); }
"__asm__"{WS}+"__volatile__"{WS}*"(".*")" { count(); }
"__crust_t__" { return prepare_leaf(0,0.0,CRUST_T); }
"__crust_borrow__" { return prepare_leaf(0,0.0,CRUST_BORROW); }
"__crust_recycle__" { return prepare_leaf(0,0.0,CRUST_RECYCLE); }
......
......@@ -451,7 +451,9 @@ struct_declaration
: specifier_qualifier_list ';' { $$ = $1; show_debug(__LINE__, $$, "struct_declaration");
free_tree($2); }
| specifier_qualifier_list struct_declarator_list ';' { $$ = $2; show_debug(__LINE__, $$, "struct_declaration");
mix_ast_leaves($$,$1);
for(tmpleaf = $2; tmpleaf != NULL; tmpleaf = tmpleaf->next) {
mix_ast_leaves($$,$1);
}
free_tree($1);
free_tree($3); }
;
......@@ -469,7 +471,9 @@ specifier_qualifier_list
struct_declarator_list
: struct_declarator { $$ = $1; show_debug(__LINE__, $$, "struct_declarator_list"); }
| struct_declarator_list ',' struct_declarator { $$ = $1; show_error(__LINE__, $$); }
| struct_declarator_list ',' struct_declarator { $$ = $1; show_debug(__LINE__, $$, "struct_declarator_list");
append_next($$,$3);
free_tree($2); }
;
struct_declarator
......
......@@ -69,7 +69,7 @@ class Test(unittest.TestCase):
if self.do_print_debug:
print("Running test {:s}".format(filename))
lib = self.open_crust()
tree = lib.read_file(filename, False, [], [])
tree = lib.read_file(filename, False, [], [], [])
self.assertIsNot(tree, None)
variables = lib.process_tree(tree)
lib.process_functions(tree, variables)
......@@ -87,7 +87,7 @@ class Test(unittest.TestCase):
if self.do_print_debug:
print("Running test {:s}".format(filename))
lib = self.open_crust()
tree = lib.read_file(filename, False, [], [])
tree = lib.read_file(filename, False, [], [], [])
self.assertIsNot(tree, None)
variables = lib.process_tree(tree)
lib.process_functions(tree, variables)
......@@ -99,7 +99,7 @@ class Test(unittest.TestCase):
if self.do_print_debug:
print("Running test {:s}".format(filename))
lib = self.open_crust()
tree = lib.read_file(filename, False, [], [])
tree = lib.read_file(filename, False, [], [], [])
self.assertIsNot(tree, None)
variables = lib.process_tree(tree)
with self.assertRaises(exception_class):
......
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