trick/bin/pm/MIS.pm
Alex Lin 14a75508a3 Cleaning up once include variables and copyright cleanup.
Changed all header file once include variables to follow the same naming
convention and not start with any underscores.  Also deleted old
incorrect copyright notices.  Also removed $Id: tags from all files.

Fixes #14.  Fixes #22.
2015-03-23 16:03:14 -05:00

292 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 Data::Dumper ;
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;