mirror of
https://github.com/nasa/trick.git
synced 2024-12-23 06:52:26 +00:00
291 lines
11 KiB
Perl
291 lines
11 KiB
Perl
|
package MIS ;
|
||
|
|
||
|
use Exporter ();
|
||
|
@ISA = qw(Exporter);
|
||
|
@EXPORT = qw(mis_c mis_all_c process_args);
|
||
|
|
||
|
use strict ;
|
||
|
use lib $ENV{"TRICK_HOME"} . "/bin/pm" ;
|
||
|
use File::Basename ;
|
||
|
use Cwd ;
|
||
|
use Cwd 'abs_path' ;
|
||
|
use html ;
|
||
|
use mis_dep ;
|
||
|
use trick_print ;
|
||
|
use auto_doc ;
|
||
|
|
||
|
my @includes ;
|
||
|
my %this_dir ;
|
||
|
my $rel_path_curr_file ;
|
||
|
my @files_to_mis_dep ;
|
||
|
my @class_names = qw( initialization restart derivative
|
||
|
integration dynamic_event post_integration
|
||
|
automatic environment asynchronous_mustfinish asynchronous
|
||
|
random sensor sensor_emitter sensor_reflector
|
||
|
sensor_receiver scheduled effector effector_emitter
|
||
|
effector_receiver automatic_last malfunction
|
||
|
malfunction_trigger logging shutdown freeze_init freeze
|
||
|
unfreeze checkpoint pre_load_checkpoint
|
||
|
monte_master_init monte_master_pre
|
||
|
monte_master_post monte_master_shutdown
|
||
|
monte_slave_init monte_slave_pre
|
||
|
monte_slave_post monte_slave_shutdown
|
||
|
N/A) ;
|
||
|
|
||
|
sub mis_all_c($$) {
|
||
|
my ( $all_src_files_ref , $sim_ref ) = @_ ;
|
||
|
my ( @all_lines , $contents ) ;
|
||
|
my ( $file_path_dir , $xml_file ) ;
|
||
|
my ( $name , $path ) ;
|
||
|
my ( $xml_time , $src_time ) ;
|
||
|
|
||
|
foreach my $f ( @$all_src_files_ref ) {
|
||
|
# determine the xml file name
|
||
|
$file_path_dir = dirname($f) ;
|
||
|
($name, $path) = fileparse($f, ("h" , "c" , "f", "cpp" , "cxx" , "C" , "cc" , "c\\+\\+" ));
|
||
|
$file_path_dir =~ s/\/src$// ;
|
||
|
$xml_file = $file_path_dir . "/xml/" . $name . "xml" ;
|
||
|
|
||
|
# skip this file if the xml file is newer than the source file
|
||
|
if ( -e $xml_file ) {
|
||
|
$xml_time = (stat $xml_file)[9] ;
|
||
|
$src_time = (stat $f)[9] ;
|
||
|
next if ( $xml_time > $src_time ) ;
|
||
|
}
|
||
|
|
||
|
# read in the file and MIS parse it
|
||
|
open FILE , "$f" ;
|
||
|
@all_lines = <FILE> ;
|
||
|
$contents = join "" , @all_lines ;
|
||
|
mis_c( $f , $contents , $sim_ref ) ;
|
||
|
}
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
sub mis_c($$$) {
|
||
|
|
||
|
my ($curr_file , $contents, $sim_ref) = @_ ;
|
||
|
my ($object_file , @entry_names);
|
||
|
my (@comments , @entries ) ;
|
||
|
my ($num_valid_entries ,$num_args_left) ;
|
||
|
my @all_lines ;
|
||
|
my $nm ;
|
||
|
my %header ;
|
||
|
my $i ;
|
||
|
my $entry ;
|
||
|
my @split_args ;
|
||
|
my $language ;
|
||
|
|
||
|
trick_print($$sim_ref{fh}, " Processing $curr_file\n", "debug_cyan" , $$sim_ref{args}{v}) ;
|
||
|
|
||
|
($object_file = $curr_file) =~ s/(?:src\/)?(\w+)\.c$/object_$ENV{"TRICK_HOST_CPU"}\/$1.o/ ;
|
||
|
|
||
|
($rel_path_curr_file) = $curr_file =~ /([^\/]+)$/ ;
|
||
|
|
||
|
%header = extract_trick_header($curr_file , $contents , $sim_ref , 0 );
|
||
|
|
||
|
if ( exists $header{language} ) {
|
||
|
# if the language specified is c++ cpp cxx c<something> then set the language as cpp
|
||
|
if ( $header{language} =~ /c[\w\+]+/i ) {
|
||
|
$language = "CPP" ;
|
||
|
}
|
||
|
else {
|
||
|
$language = "C" ;
|
||
|
}
|
||
|
}
|
||
|
elsif ($curr_file =~ /\.c$/ ) {
|
||
|
# else if the current file ends in .c set the language to c
|
||
|
$language = "C" ;
|
||
|
}
|
||
|
else {
|
||
|
# all other extensions are cpp
|
||
|
$language = "CPP" ;
|
||
|
}
|
||
|
|
||
|
#Pull out comments
|
||
|
$i = 0;
|
||
|
while ($contents =~ /(?:\/\*(.*?)\*\/)|(?:\/\/(.*?)\n)/sg) {
|
||
|
push @comments , $+ ;
|
||
|
}
|
||
|
$contents =~ s/\/\*(.*?)\*\/|\/\/(.*?)(\n)/" " . $i++ . " " . $3/esg ;
|
||
|
|
||
|
@includes = $contents =~ /(#include\s*["<][^">]+[">])/g ;
|
||
|
|
||
|
# The next loop finds all of the function entry points in the file.
|
||
|
while ( $contents =~ /
|
||
|
(?:(auto|register|static|extern)\s+)? # optional keywords = $1
|
||
|
(?:(enum|class|struct|const|volatile|signed|unsigned|long|unsigned\s+long)\s+)? # optional keywords = $2
|
||
|
(\#?[A-Za-z]\w*|(?:[A-Za-z]\w*\s*<\s+[A-Za-z]\w*\s+>)) # type name = $3
|
||
|
([\*\s]+) # pointers or spaces = $4 (at least 1 space or pointer)
|
||
|
(\w[\:\-\w]*)\s* # function name = $5
|
||
|
\(\s* # open paren
|
||
|
([^)]*) # everything to close paren = $6
|
||
|
\) # close paren
|
||
|
\s*(\d+)?\s* # optional comment = $7
|
||
|
(?:(const|volatile)\s+)?\s* # optional const|volatile = $8
|
||
|
(throw\s*\(.*?\))?\s* # optional throw
|
||
|
(?:\d+\s*)* # extra comments discarded
|
||
|
{ # open brace , balance }
|
||
|
/sgx ) {
|
||
|
|
||
|
|
||
|
my $return_type = $1 ;
|
||
|
$return_type .= ( $return_type eq "" ) ? $2 : " $2" ;
|
||
|
$return_type .= ( $return_type eq "" ) ? $3 : " $3" ;
|
||
|
my $pointers = $4 ;
|
||
|
if ( $pointers ne "" ) {
|
||
|
$pointers =~ s/(^\s+|\s+$)//g ;# remove leading & trailing whitespaces
|
||
|
$pointers = " $pointers" ;
|
||
|
}
|
||
|
$return_type .= $pointers ;
|
||
|
my $name = $5 ;
|
||
|
my $raw_args = $6 ;
|
||
|
$raw_args .= " $7" if ( $7 ne "" ) ;
|
||
|
|
||
|
# skip this entry point because it's actulally a macro
|
||
|
next if ( $return_type =~ /\#/ ) ;
|
||
|
|
||
|
if ( $name eq "if" or $name eq "for" or
|
||
|
$name eq "while" or $name eq "switch" or
|
||
|
$name eq "do" or $name =~ /operator[^\w]/ ) {
|
||
|
next ;
|
||
|
}
|
||
|
else {
|
||
|
push @entries , { 'return_type' => $return_type ,
|
||
|
'name' => $name ,
|
||
|
'file_name' => $curr_file ,
|
||
|
'raw_args' => $raw_args ,
|
||
|
'language' => $language } ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$num_valid_entries = 0 ;
|
||
|
|
||
|
foreach $entry (@entries) {
|
||
|
trick_print($$sim_ref{fh}, " Processing $$entry{name}\n" , "debug_cyan" , $$sim_ref{args}{v}) ;
|
||
|
if ( process_args ($entry, \@comments, 6 , $sim_ref) == 0 ) {
|
||
|
add_proto_to_cat( $entry , $sim_ref , 6 ) ;
|
||
|
$num_valid_entries++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( $num_valid_entries eq 0 ) {
|
||
|
trick_print($$sim_ref{fh}, " WARNING: No entry points found\n", "debug_yellow" , $$sim_ref{args}{v});
|
||
|
}
|
||
|
else {
|
||
|
print_xml_mis($curr_file , \@entries , \%header, \@includes) ;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
sub process_args($$$$) {
|
||
|
|
||
|
my ($entry, $comments, $indent , $sim_ref) = @_ ;
|
||
|
my ($entry_comment , $hdr_comment ) ;
|
||
|
my @arg_list ;
|
||
|
|
||
|
$hdr_comment = -1 ;
|
||
|
|
||
|
$$entry{valid} = 0 ;
|
||
|
|
||
|
# clear out leading spaces
|
||
|
$$entry{raw_args} =~ s/^\s+//s ;
|
||
|
|
||
|
$$entry{raw_args} =~ s/\s+(\*+)/$1 /g ;
|
||
|
if ($$entry{raw_args} =~ s/^\s*(\d+)\s*//s ) {
|
||
|
$entry_comment = $1 ;
|
||
|
$hdr_comment = $entry_comment - 1 ;
|
||
|
($$entry{units} , $$entry{desc}) =
|
||
|
@$comments[$entry_comment] =~ /\s*RETURN:\s*(?:((?:[-*\/\w^|\.]+)|(?:\(.*?\))))\s+\s*(.*)/six ;
|
||
|
}
|
||
|
else {
|
||
|
$$entry{units} = "--" ;
|
||
|
$$entry{desc} = "Not Specified" ;
|
||
|
}
|
||
|
$$entry{raw_args} =~ s/^\s*void\s*$// ;
|
||
|
|
||
|
$$entry{class} = "" ;
|
||
|
while ( $$entry{class} eq "" and $hdr_comment >= 0 ) {
|
||
|
($$entry{class}) = @$comments[$hdr_comment] =~ /CLASS:.*?\(\s*([\w\/]+)/si ;
|
||
|
$hdr_comment -= 1 ;
|
||
|
}
|
||
|
if ( !(grep /^$$entry{class}$/ , @class_names )) {
|
||
|
$$entry{class} = "N/A" ;
|
||
|
}
|
||
|
|
||
|
my $arg_count = 1 ;
|
||
|
while ( $$entry{raw_args} =~ s/^(?:
|
||
|
(?:
|
||
|
((?:(?:enum|class|struct|const|volatile|signed|unsigned|long|unsigned\s+long)\s+)?.*?) # argument type = $1
|
||
|
(<.*?>)?\s* # c++ template = $2
|
||
|
(\**)\s+ # argument pointers = $3
|
||
|
(?:(const)\s+)?\s* # c++ const keyword = $4
|
||
|
(\&)?\s* # c++ reference symbol = $5
|
||
|
(\w+)?\s* # name (optional in c++ method decl.) = $6
|
||
|
(\[[^,=]*\])?\s* # optional array specs = $7
|
||
|
(\s*=\s*[\w\.]+)?[\s,]* # optional default value = $8
|
||
|
)
|
||
|
|
|
||
|
(\.\.\.)\s* # variable argument spec = $9
|
||
|
)
|
||
|
(\d+)?\s* # in|inout|out comment = $10
|
||
|
(?:\d+\s*)* # optional extra comments discarded
|
||
|
//six ) {
|
||
|
my %func_arg ;
|
||
|
my $comment_index ;
|
||
|
|
||
|
$func_arg{type} = $1 ;
|
||
|
$func_arg{cpp_template} = ( $2 ne "" ) ? $2 : "" ;
|
||
|
$func_arg{pointers} = ( $3 ne "" ) ? $3 : "" ;
|
||
|
$func_arg{cpp_const} = $4 ;
|
||
|
$func_arg{cpp_ref} = $5 ;
|
||
|
|
||
|
$func_arg{name} = ( $6 ne "" ) ? $6 : "" ;
|
||
|
$func_arg{array} = ( $7 ne "" ) ? $7 : "" ;
|
||
|
$func_arg{optional} = ( $8 ne "" ) ? 1 : 0 ;
|
||
|
$func_arg{type} = $9 if ( $9 ne "" ) ;
|
||
|
$comment_index = $10 ;
|
||
|
|
||
|
if ( $comment_index ne "" ) {
|
||
|
($func_arg{comment} = @$comments[$comment_index]) =~ s/(IN|INOUT|OUT):\s*// ;
|
||
|
( $func_arg{inout} , $func_arg{unit} , $func_arg{desc} ) =
|
||
|
@$comments[$comment_index] =~ /^\s*(?:(IN|INOUT|OUT):)?\s*
|
||
|
(?:((?:[-*\/\w^|\.]+)|(?:\(.*?\))))\s+
|
||
|
\s*(.*)
|
||
|
/six ;
|
||
|
}
|
||
|
else {
|
||
|
$func_arg{comment} = "-- Not specified" ;
|
||
|
$func_arg{inout} = "" ;
|
||
|
$func_arg{unit} = "--" ;
|
||
|
$func_arg{desc} = "Not specified" ;
|
||
|
}
|
||
|
|
||
|
trick_print($$sim_ref{fh}, " "x($indent+3) . "Arg $arg_count\n" , "debug_white" , $$sim_ref{args}{v} ) ;
|
||
|
trick_print($$sim_ref{fh}, " "x($indent+6) . "type = $func_arg{type} $func_arg{pointers} $func_arg{array}\n" ,
|
||
|
"debug_white" , $$sim_ref{args}{v} ) ;
|
||
|
trick_print($$sim_ref{fh}, " "x($indent+6) . "name = $func_arg{name}\n" , "debug_white" , $$sim_ref{args}{v} ) ;
|
||
|
trick_print($$sim_ref{fh}, " "x($indent+6) . "comm = $func_arg{comment}\n" , "debug_white" , $$sim_ref{args}{v} ) ;
|
||
|
$arg_count++ ;
|
||
|
|
||
|
push @arg_list , \%func_arg ;
|
||
|
}
|
||
|
|
||
|
if ( $$entry{raw_args} ne "" ) {
|
||
|
trick_print($$sim_ref{fh}, "Could not process argument for $entry->{name}\n" , "title_red" , $$sim_ref{args}{v} ) ;
|
||
|
trick_print($$sim_ref{fh}, "Last Read:\n$entry->{args_list}\n" , "title_red" , $$sim_ref{args}{v} ) ;
|
||
|
return -1 ;
|
||
|
}
|
||
|
else {
|
||
|
|
||
|
# set the values to return
|
||
|
$$entry{valid} = 1 ;
|
||
|
@{$$entry{arg_list}} = @arg_list ;
|
||
|
}
|
||
|
|
||
|
return 0 ;
|
||
|
|
||
|
}
|
||
|
|
||
|
1;
|