From deb53eb019e66fa77d6de2c042fb8f2192f498e6 Mon Sep 17 00:00:00 2001 From: Diomidis Spinellis Date: Sat, 27 Jul 2024 20:05:03 +0300 Subject: [PATCH] Analyze macro parameters for non-object values (WIP) --- src/call.cpp | 7 +++++ src/call.h | 2 +- src/cscout.cpp | 69 ++++++++++++++++++++++++++++++++++++++++++++++---- src/ctoken.cpp | 9 +++++++ src/ctoken.h | 4 +++ src/metrics.h | 2 ++ 6 files changed, 87 insertions(+), 6 deletions(-) diff --git a/src/call.cpp b/src/call.cpp index 81ba4822..dc880d40 100644 --- a/src/call.cpp +++ b/src/call.cpp @@ -158,6 +158,13 @@ Call::contains(Eclass *e) const return false; } +void +populate_namers() +{ + for (Call::const_fmap_iterator_type i = Call::fbegin(); i != Call::fend(); i++) { + } +} + void Call::clear_visit_flags() { diff --git a/src/call.h b/src/call.h index c1ddbcdf..1fa48616 100644 --- a/src/call.h +++ b/src/call.h @@ -60,7 +60,7 @@ class Pltoken; class Call { private: - // Container for storing all declared functions + // Container for storing called and calling functions typedef set fun_container; /* * When processing the program a Call * is stored with each Id diff --git a/src/cscout.cpp b/src/cscout.cpp index cb6052f1..fd21b1cc 100644 --- a/src/cscout.cpp +++ b/src/cscout.cpp @@ -286,6 +286,7 @@ file_analyze(Fileid fi) const string &fname = fi.get_path(); int line_number = 0; + FCallSet &fc = Filedetails::get_functions(fi); // File's functions FCallSet::iterator fci = fc.begin(); // Iterator through them Call *cfun = NULL; // Current function @@ -297,6 +298,15 @@ file_analyze(Fileid fi) perror(fname.c_str()); exit(1); } + + bool analyze_param = false; // True if analyzing macro parameters + int bracket_nesting = 0; // Nesting during the analysis + int non_obj_param = 0; // Number of non-object parameters + // Check this or next parameter token for prohibited values + bool check_param_token = false; + bool check_next_param_token = false; + vector macro_name_ecs; + // Go through the file character by character for (;;) { Tokid ti; @@ -318,6 +328,7 @@ file_analyze(Fileid fi) fun_nesting.pop(); } } + // See if entering a new function if (fci != fc.end() && ti >= (*fci)->get_begin().get_tokid()) { if (cfun) fun_nesting.push(cfun); @@ -328,6 +339,36 @@ file_analyze(Fileid fi) char c = (char)val; mapTokidEclass::iterator ei; enum e_cfile_state cstate = Filedetails::get_pre_cpp_metrics(fi).get_state(); + + /* + * Analyze macro parameters for arguments that make them + * unsuitable for converting into a C function. + */ + if (analyze_param && + cstate != s_block_comment && + cstate != s_string && + cstate != s_cpp_comment) { + // cout << "Got " << c << "\n"; + if (check_next_param_token) + check_param_token = true; + check_next_param_token = false; + if (c == '(') { + if (bracket_nesting == 0) + check_next_param_token = true; + bracket_nesting++; + } else if (c == ')') { + bracket_nesting--; + if (bracket_nesting == 0) { + analyze_param = false; + Call* macro = Call::get_macro(macr_name_ecs); + if (macro) + macro->get_pre_cpp_metrics().add_metric(FunMetrics::em_nnoparam, non_obj_param); + + } else if (c == ',' && bracket_nesting == 1) + check_next_param_token = true; + } + + // Mark identifiers if (cstate != s_block_comment && cstate != s_string && cstate != s_cpp_comment && @@ -343,15 +384,17 @@ file_analyze(Fileid fi) continue; } } + + string s(1, c); + int len = ec->get_len(); + for (int j = 1; j < len; j++) + s += (char)in.get(); + // Identifiers we can mark if (ec->is_identifier()) { // Update metrics id_msum.add_pre_cpp_id(ec); // Add to the map - string s(1, c); - int len = ec->get_len(); - for (int j = 1; j < len; j++) - s += (char)in.get(); Filedetails::get_pre_cpp_metrics(fi).process_identifier(s, ec); if (cfun) cfun->get_pre_cpp_metrics().process_identifier(s, ec); @@ -367,7 +410,10 @@ file_analyze(Fileid fi) has_unused = true; else ; // TODO fi.set_associated_files(ec); - continue; + + if (check_param_token + && ec->get_attribute(is_macro)) { + } else { /* * This equivalence class is not needed. @@ -377,7 +423,20 @@ file_analyze(Fileid fi) */ ec->remove_from_tokid_map(); delete ec; + ec = NULL; + } + + + if (ec && !analyze_param + && ec->get_attribute(is_macro)) { + cout << "Macro " << *ec << "\n"; + analyze_param = true; + bracket_nesting = 0; + non_obj_param = 0; + macro_ecs.clear(); } + if (ec && analyze_param) + macro_name_ecs.push_back(ec); } Filedetails::get_pre_cpp_metrics(fi).process_char((char)val); if (cfun) diff --git a/src/ctoken.cpp b/src/ctoken.cpp index 05db9de5..e6a45b3a 100644 --- a/src/ctoken.cpp +++ b/src/ctoken.cpp @@ -397,6 +397,15 @@ parse_lex_real() } } +int +Ctoken::lookup_keyword(const string& s) +{ + auto ik = keymap.find(s); + if (ik == keymap.end()) + return -1; + return ik->second; +} + // Lexical analysis function for yacc // Used for debugging int diff --git a/src/ctoken.h b/src/ctoken.h index 401d527b..86035586 100644 --- a/src/ctoken.h +++ b/src/ctoken.h @@ -46,6 +46,10 @@ class Ctoken: public Token { Ctoken() {} Ctoken(Pdtoken& t) : Token(t) {}; + /* + * Return the string's keyword token value or -1 if the string + * isn't a keyword. + */ static int lookup_keyword(const string& s); void getnext(); }; diff --git a/src/metrics.h b/src/metrics.h index 2f7375a4..0e99bcc6 100644 --- a/src/metrics.h +++ b/src/metrics.h @@ -255,6 +255,8 @@ class Metrics { // Return metric i (by lookup or calculation) double get_metric(int n) const; void set_metric(int n, int val) { count[n] = val; } + + void add_metric(int n, int val) { count[n] += val; } void summarize_operators(); // Update the maxumum level of statement nesting