trick/bin/pm/parse_s_define.pm
2015-02-26 09:02:31 -06:00

935 lines
34 KiB
Perl
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package parse_s_define ;
# $Id: parse_s_define.pm 3676 2014-10-03 16:13:01Z dbankier $
use Exporter ();
@ISA = qw(Exporter);
@EXPORT = qw(parse_s_define handle_sim_object handle_integ_loop handle_collects
handle_user_code handle_user_header handle_user_inline) ;
use Cwd ;
use File::Basename ;
use strict ;
use Cwd 'abs_path';
use IPC::Open3 ;
use lib $ENV{"TRICK_HOME"} . "/bin/pm" ;
use ICG ;
use edit ;
use find_module ;
use gte ;
use trick_print ;
use trick_version ;
use Text::Balanced qw(extract_bracketed);
use html ;
my ($integ_loop_def , $collect_def , $vcollect_def);
my ($job_class_order_def ) ;
my ($sim_class_def , $sim_class_job_def , $instantiation_def , $create_connections_def) ;
my ($compiler_directive_def ) ;
my ($other_tag_def , $comment_def ) ;
my ($user_code_def ) ;
my ($user_header_def ) ;
my ($user_inline_def ) ;
my ($line_tag_def) ;
my $s_define_file ;
#------------------------------------------------------------
# IntegLoop statements
$integ_loop_def = qr/
(?:IntegLoop|integrate) # IntegLoop keyword
\s+
(?:[CcSs][\d]*\s+)? # child spec
\s*
(?:[\w_]+) # IntegLoopSimObject name
\s*
\( # Entry timing spec
\s*
(?:
(?:[\d\.]+) # cycle
|(?:[\d\.]+\s*,\s*[\d\.]+) # OR cycle,cycle
|(?:[\w_\.]+) # OR class
|(?:[\d\.]+\s*,\s*[\w_\.]+) # OR float,class
)
\s*
\) # close timing spec
\s*
(?:.*?) # name list
\s*; # terminating semicolon
/sx ;
#------------------------------------------------------------
# Collect statements
$collect_def = qr/
collect # Collect keyword
\s*
(?:[\w_\.\[\]]*) # Collect name
\s*
= # Equals sign
\s*
{ # entry
(?:.*?) # collect params
}\s*; # end args
/sx ;
#------------------------------------------------------------
# Vector collect statements
$vcollect_def = qr/
vcollect # Vcollect keyword
\s*
(?:[\w_\.\[\]]+) # Container name
\s*
(?:.*?) # Optional constructor
\s*
{\s* # entry
(?:.*?) # item list
\s*}\s*; # end args
/sx ;
$compiler_directive_def = qr/
\#\#[^\n]+ # compiler directive
/sx ;
$sim_class_def = qr/
(?:template\s+<[^>]+>\s*)?
class # the keyword class
[^{]+ # everything up to opening parenthesis
/sx ;
$sim_class_job_def = qr/
(?:
\s*(?:
(?:[Cc][\w\.\-\>]+) | # child spec
(?:[Pp][\w\.\-\>]+) | # phase spec
(?:
\(
(?:
(?:
\s*(?:[\w.]+)\s* # cycle time
(?:,\s*(?:[\w.]+)\s*)? # start time
(?:,\s*(?:[\w.]+)\s*)? # stop time
(?:,\s*(?:"?\w+"?)\s*) # class
)|
\s*(?:"?\w+"?)\s* # class (by itself)
(?:,\s*(&?[\w\.\-\>]+)\s*)? # integration object
)
\)
) | # timing spec
\{(?:[\w_.,\s]+)\} # job tag
)
)+\s+
(?:[A-Za-z_][\w\.\-\>]*\s*=)?\s* # optional return assignment variable
(?:[A-Za-z_]+[\w\.\:\-\>\[\]]*) # job name
\s*
\( # entry point
(?:.*?)\s* # arg list
\)\s*; # end arg list
/sx ;
$instantiation_def = qr/
(?:[A-Za-z_]+[\w_:\*]*(?:<[^>]+>)?)\s+ # type
(?:[A-Za-z_]+[\w_]*)\s* # name
(?:\(.*?;|\s*;) # arguments
/sx ;
#(?:\([^{\)]*\))?\s*; # arguments
$create_connections_def = qr/
void\s+create_connections # create_connections declaration
[^{]+ # everything up to opening parenthesis
/sx ;
$job_class_order_def = qr/
job_class_order # the word sim_object
(?:.*? # everything
})\s*; # to end of obj def
/sx ;
$user_code_def = qr/
%{\s*
.*?
%}
/sx ;
$user_header_def = qr/
%\s*header\s*{\s*
.*?
%}
/sx ;
$user_inline_def = qr/
%\s*inline\s*{\s*
.*?
%}
/sx ;
$other_tag_def = qr/\#(?:ident|pragma)?.*?\n/s ;
$comment_def = qr/ZZZYYYXXX\d+ZZZYYYXXX/s ;
$line_tag_def = qr/\#(?:line)?\s+\d+.*?(?:\n|$)/s ;
sub parse_s_define ($) {
my ($sim_ref) = @_ ;
my ($temp) ;
my ($CC, $contents) ;
my (@prescan_job_class_order) ;
my ($version, $thread, $year) ;
my @defines ;
my @comments ;
my @preprocess_output;
# Get Include Paths From $TRICK_CFLAGS
@{$$sim_ref{inc_paths}} = $ENV{"TRICK_CFLAGS"} =~ /-I\s*(\S+)/g ;
push @{$$sim_ref{inc_paths}} , ("$ENV{\"TRICK_HOME\"}/trick_source" , "../include") ;
my @valid_inc_paths ;
foreach (@{$$sim_ref{inc_paths}}) {
push @valid_inc_paths , $_ if ( -e $_ ) ;
}
@{$$sim_ref{inc_paths}} = @valid_inc_paths ;
foreach ( @valid_inc_paths ) {
$_ = abs_path($_) ;
}
foreach ( @{$$sim_ref{inc_paths}} ) {
s/\/+$// ;
s/\/+/\// ;
$_ = quotemeta (abs_path(dirname($_)) . "/" . basename($_)) ;
}
$s_define_file = "S_define" ;
$$sim_ref{line_num} = 1 ;
# Run S_define through C PreProcessor to handle #defines
$CC = gte("TRICK_CC") ;
chomp $CC ;
if (-e $s_define_file) {
my $cmd;
$cmd = "$CC -C -E -xc $ENV{TRICK_SFLAGS} $s_define_file";
#print "$cmd\n" ;
@preprocess_output = `$cmd`;
# The commented out code is what I would like to use, but it hangs on Macs (Alex 6/13/11)
# my($wtr, $rdr, $err);
# my($pid , @error_msg);
# use Symbol 'gensym'; $err = gensym;
# $pid = open3($wtr, $rdr, $err, $cmd);
#
# waitpid( $pid , 0 ) ;
# @preprocess_output = <$rdr> ;
if (($? >> 8) != 0) {
trick_print( $$sim_ref{fh}, "\nError in $s_define_file. Exit!\n\n", "title_red", $$sim_ref{args}{v} );
# my(@error_msg);
# @error_msg = <$err> ;
# trick_print( $$sim_ref{fh}, "@error_msg\n\n", "normal_white", $$sim_ref{args}{v} );
exit -1 ;
}
} else {
die "Couldn't find file: $s_define_file\n";
}
foreach my $each_item (@preprocess_output) {
$contents .= $each_item;
}
@comments = $contents =~ m/((?:\/\*(?:.*?)\*\/)|(?:\/\/(?:.*?)\n))/sg ;
foreach my $i (@comments) {
my %header ;
my @lib_list ;
%header = extract_trick_header("S_define", $i, 0, 0);
push @{$$sim_ref{default_data}} , $header{default_data} ;
$header{libdep} =~ s/\s+//sg ;
$header{libdep} =~ s/\(\(/\(/ ;
$header{libdep} =~ s/\)\)/\)/ ;
@lib_list = $header{libdep} =~ m/\((.+?)\)/sg ;
foreach my $object_file (@lib_list) {
#print " look for object $object_file\n" ;
if ( $object_file =~ /^\// ) {
push @{$$sim_ref{mis_entry_files}}, $object_file ;
} elsif ( $object_file =~ /^sim_lib(\S+)/i ) {
push @{$$sim_ref{sim_libraries}}, $1 ;
#print "found a sim_library $1\n" ;
} else {
my $found = 0 ;
foreach my $inc_path ( @valid_inc_paths ) {
if ( -f "$inc_path/$object_file" ) {
push @{$$sim_ref{mis_entry_files}}, "$inc_path/$object_file" ;
$found = 1 ;
last ;
}
}
if ( $found == 0 ) {
trick_print( $$sim_ref{fh}, "\nCould not find S_define LIBRARY_DEPENDENCY $object_file\n\n",
"title_red", $$sim_ref{args}{v} );
}
}
}
}
my $i = 0 ;
$contents =~ s/\/\*(.*?)\*\/|\/\/(.*?)(\n)/"ZZZYYYXXX" . $i++ . "ZZZYYYXXX" . ((defined $3) ? $3 : "")/esg ;
# substitue in environment variables in the S_define file.
# Do that with 1 line in C! This comment is longer than the code it took!
$contents =~ s/\$[({]\s*([\w_]+)\s*[)}]/$ENV{$1}/eg ;
#strip trailing spaces
$contents =~ s/\s*$// ;
#rip out define comments left by gcc 2.96
$contents =~ s/\/\*.*?\*+\///sg ;
$$sim_ref{sim_class_index}{"Trick::SimObject"} = 0 ;
# set the default job class order
@{$$sim_ref{user_class_order}} = qw(automatic random environment sensor sensor_emitter
sensor_reflector sensor_receiver scheduled effector
effector_emitter effector_receiver automatic_last logging
data_record system_checkpoint system_advance_sim_time
system_moding integ_loop) ;
# search and use a user class order
@prescan_job_class_order = $contents =~ m/($job_class_order_def)/sg ;
preparse_job_class_order( \@prescan_job_class_order , $sim_ref ) ;
while ($contents =~ s/^(\s*)(?:($sim_class_def)|
($integ_loop_def)|
($collect_def)|
($user_code_def) |
($user_header_def) |
($user_inline_def) |
($line_tag_def)|
($job_class_order_def)|
($vcollect_def)|
($create_connections_def)|
($instantiation_def)|
($compiler_directive_def)|
($other_tag_def)|
($comment_def)
)//sx ) {
if ( defined $1 and $1 ne "" ) {
$temp = $1 ;
#trick_print($$sim_ref{fh}, $temp, "debug_white" , $$sim_ref{args}{v});
$$sim_ref{line_num} += ($temp =~ s/\n/\n/g) ;
}
if ( defined $2 and $2 ne "" ) { handle_sim_class($2, \$contents, $sim_ref, \@comments) ; }
if ( defined $3 and $3 ne "" ) { handle_integ_loop($3, $sim_ref) ; }
if ( defined $4 and $4 ne "" ) { handle_collects($4, $sim_ref) ; }
if ( defined $5 and $5 ne "" ) { handle_user_code($5, $sim_ref) ; }
if ( defined $6 and $6 ne "" ) { handle_user_header($6, $sim_ref) ; }
if ( defined $7 and $7 ne "" ) { handle_user_inline($7, $sim_ref) ; }
if ( defined $8 and $8 ne "" ) { handle_line_tag($8, $sim_ref) ; } #line tag
if ( defined $9 and $9 ne "" ) { } #job class order... preparsed
if ( defined $10 and $10 ne "" ) { handle_vcollects($10, $sim_ref) ; }
if ( defined $11 and $11 ne "" ) { handle_create_connections($11, \$contents, $sim_ref) ; }
if ( defined $12 and $12 ne "" ) { handle_instantiation($12, $sim_ref) ; }
if ( defined $13 and $13 ne "" ) { handle_compiler_directive($13, $sim_ref) ; }
if ( defined $14 and $14 ne "" ) { } #ignore these lines
}
$contents =~ s/\cZ$//sx ;
$contents =~ s/^(\s*)//sx ;
$$sim_ref{line_num} += (($temp = $1) =~ s/\n/\n/g) ;
if ( $contents ne "" ) {
trick_print($$sim_ref{fh},"Syntax error in $$sim_ref{last_file}\n", "title_red", $$sim_ref{args}{v}) ;
my @temp_array = split /\n/ , $contents ;
my $temp = join "\n" , (splice ( @temp_array , 0 , 10 )) ;
trick_print($$sim_ref{fh},"Last 10 lines read:\n$temp\n", "title_red", $$sim_ref{args}{v}) ;
edit_and_exit("CP" , "$s_define_file" , $$sim_ref{line_num} ) ;
}
}
# Handle Integration Loop Statements
sub handle_integ_loop ($$) {
my ($integ_loop, $sim_ref) = @_ ;
my ($child_spec, $name, $cycle, $name_list ) ;
my %integ_loop_info ;
trick_print($$sim_ref{fh}, "IntegLoop: $integ_loop\n" , "debug_white" , $$sim_ref{args}{v});
# remove all comments
$integ_loop =~ s/ZZZYYYXXX(\d+)ZZZYYYXXX//g ;
( $child_spec, $name, $cycle, $name_list ) = $integ_loop =~ /
(?:IntegLoop|integrate) # IntegLoop keyword
\s+
(?:[CcSs]([\d])*\s+)? # child spec
([\w_]+) # IntegLoopSimObject name
\s*
\( # Entry timing spec
\s*
([\d\.]+) # cycle
\s*
\) # close timing spec
\s*
(.*?) # name list
\s*; # terminating semicolon
/sx ;
$integ_loop_info{name} = $name ;
$integ_loop_info{cycle} = $cycle ;
$child_spec = 0 if ( $child_spec eq "" ) ;
$integ_loop_info{child} = $child_spec ;
# @{$integ_loop_info{name_list}} = split(/\s*,\s*/, $name_list );
$integ_loop_info{name_list} = $name_list ;
$integ_loop_info{line_num} = $$sim_ref{line_num} ;
push @{$$sim_ref{integ_loop}}, \%integ_loop_info ;
$$sim_ref{line_num} += ($integ_loop =~ s/\n/\n/g) ;
}
# Handle Collect Statements
sub handle_collects ($$) {
my ( $collect , $sim_ref ) = @_ ;
my ( $collect_name, $collect_params ) ;
my %collect_info ;
trick_print($$sim_ref{fh}, "Collect: $collect\n" , "debug_white" , $$sim_ref{args}{v});
( $collect_name, $collect_params ) = $collect =~ /
collect # Collect keyword
\s*
([\w_\.\[\]]*) # Collect name
\s*
= # Equals sign
\s*
{\s* # entry
(.*?) # collect params
}\s*; # end args
/sx ;
# Setup collect params for a split (take out newlines and lead/trail space)
$collect_params =~ s/ZZZYYYXXX(\d+)ZZZYYYXXX//g ;
$collect_params =~ s,\n|^\s*|\s*$,,g ;
$collect_info{name} = $collect_name ;
@{$collect_info{params}} = split(/\s*,\s*/ , $collect_params ) ;
$collect_info{num_params} = $#{$collect_info{params}} + 1 ;
push @{$$sim_ref{collect}} , \%collect_info ;
$$sim_ref{line_num} += ($collect =~ s/\n/\n/g) ;
}
# Handle Vcollect Statements
sub handle_vcollects ($$) {
my ( $vcollect , $sim_ref ) = @_ ;
my ( $container_name, $constructor, $item_list );
my %collect_info ;
trick_print($$sim_ref{fh}, "Vcollect: $vcollect\n" , "debug_white" , $$sim_ref{args}{v}) ;
$vcollect =~ s/ZZZYYYXXX(\d+)ZZZYYYXXX//g ;
( $container_name, $constructor, $item_list ) = $vcollect =~ /
vcollect # Vcollect keyword
\s*
([\w_\.\[\]]+) # Container name
\s*
(.*?) # Optional constructor
\s*
{\s* # entry
(.*?) # item list
\s*}\s* # end args
/sx ;
# Setup collect params for a split (take out newlines and lead/trail spaces)
$item_list =~ s,\n|^\s*|\s*$,,g ;
$collect_info{name} = $container_name ;
$collect_info{constructor} = $constructor ;
@{$collect_info{items}} = split(/\s*, \s*/ , $item_list) ;
push @{$$sim_ref{vcollect}} , \%collect_info ;
$$sim_ref{line_num} += ($vcollect =~ s/\n/\n/g) ;
}
# Handle User code on Statements
sub handle_user_code ($$) {
my ($u, $sim_ref) = @_ ;
trick_print($$sim_ref{fh}, "User code: $u\n" , "debug_white" , $$sim_ref{args}{v});
$$sim_ref{line_num} += ($u =~ s/\n/\n/g) ;
$u =~ s/^##/#/mg ;
$u =~ /%{(.*?)%}/s ;
$u = $1 ;
$u =~ s/ZZZYYYXXX(\d+)ZZZYYYXXX//g ;
$$sim_ref{user_code} .= $u ;
}
sub handle_user_header ($$) {
my ($u, $sim_ref) = @_ ;
trick_print($$sim_ref{fh}, "User header: $u\n" , "debug_white" , $$sim_ref{args}{v});
$$sim_ref{line_num} += ($u =~ s/\n/\n/g) ;
$u =~ s/^##/#/mg ;
$u =~ /%\s*header\s*{(.*?)%}/s ;
$u = $1 ;
$u =~ s/^#\s+(\d+)\s+"S_define"\n//mg ;
$u =~ s/ZZZYYYXXX(\d+)ZZZYYYXXX//esg ;
$$sim_ref{user_header} .= $u ;
}
sub handle_user_inline ($$) {
my ($u, $sim_ref) = @_ ;
trick_print($$sim_ref{fh}, "Inline code: $u\n" , "debug_white" , $$sim_ref{args}{v});
$$sim_ref{line_num} += ($u =~ s/\n/\n/g) ;
$u =~ s/^##/#/mg ;
$u =~ /%\s*inline\s*{(.*?)%}/s ;
$u = $1 ;
$u =~ s/^#\s+(\d+)\s+"S_define"\n//mg ;
$u =~ s/ZZZYYYXXX(\d+)ZZZYYYXXX//esg ;
$$sim_ref{sim_class_code} .= $u ;
$$sim_ref{sim_class_code} .= "\n" ;
}
sub handle_sim_class ($$$$) {
my ($s, $file_contents, $sim_ref, $comments_ref) = @_;
my ($full_template_args, $template_args) ;
my ($class_contents , $constructor_contents) ;
my ($class_name , $inherit_class, $inherit_constructor) ;
my $final_contents ;
my $int_call_functions ;
my $double_call_functions ;
my $constructor_found = 0 ;
my $job ;
#my ($start_index, $ii) ;
my ($constructor_declare, $temp_content) ;
my ($job_push , $job_call, $is_dynamic_event) ;
# grab the class name and the name of the class we are inheriting from
($full_template_args) = $s =~ /template\s+<([^>]+)>/ ;
($class_name, $inherit_class) = $s =~ /class\s+(\S+)\s*:\s*public\s*(.*\S)/ ;
$template_args = $full_template_args ;
$template_args =~ s/class|typename//g ;
$template_args =~ s/\s//g ;
trick_print($$sim_ref{fh}, "Processing sim_class $class_name\n" , "normal white" , $$sim_ref{args}{v});
# grab the entire contents of the class out of the S_define file.
($class_contents, $$file_contents) = extract_bracketed($$file_contents,"{}");
$class_contents =~ s/$line_tag_def//g ;
$$file_contents =~ s/^\s*;\s*//s ;
#final_contents contains the processed class. Start if off with the incoming class name
$final_contents = $s ;
my ($unparameterized_name) = $inherit_class =~ /([^<]+)/ ;
# if this class is not a SimObject pass it whole to S_Source.cpp
if ( $inherit_class eq "" or !exists $$sim_ref{sim_class_index}{$unparameterized_name} ) {
$class_contents =~ s/ZZZYYYXXX(\d+)ZZZYYYXXX/@$comments_ref[$1]/g ;
$final_contents .= "$class_contents ;\n\n" ;
$$sim_ref{sim_class_code} .= $final_contents ;
return ;
}
if ( $full_template_args eq "" ) {
$int_call_functions = "int ${class_name}" ;
} else {
$int_call_functions = "template <$full_template_args> int $class_name<$template_args>" ;
}
$int_call_functions .= "::call_function ( Trick::JobData * curr_job ) {\n\n int trick_ret = 0 ;\n" ;
$int_call_functions .= " if ( curr_job->disabled ) return (trick_ret) ;\n\n" ;
$int_call_functions .= " switch ( curr_job->id ) {\n" ;
if ( $full_template_args eq "" ) {
$double_call_functions = "double ${class_name}" ;
} else {
$double_call_functions = "template <$full_template_args> double $class_name<$template_args>" ;
}
$double_call_functions .= "::call_function_double ( Trick::JobData * curr_job ) {\n\n" ;
$double_call_functions .= " double trick_ret = 0.0 ;\n" ;
$double_call_functions .= " if ( curr_job->disabled ) return (trick_ret) ;\n\n" ;
$double_call_functions .= " switch ( curr_job->id ) {\n" ;
$$sim_ref{sim_class_index}{$class_name} = $$sim_ref{sim_class_index}{$unparameterized_name} ;
# look for constructor
while ( $class_contents =~ /^(.*?)$class_name\s*\([^;]*{/s ) {
my (@int_job_calls, @double_job_calls) ;
$constructor_found = 1 ;
$class_contents =~ s/^(.*?$class_name[^{]+)//s ;
$temp_content = $1 ;
$final_contents .= $temp_content ;
($constructor_contents, $class_contents) = extract_bracketed($class_contents,"{}");
$constructor_contents =~ s/ZZZYYYXXX(\d+)ZZZYYYXXX//g ;
trick_print($$sim_ref{fh}, " Constructor found\n" , "debug_white" , $$sim_ref{args}{v});
$constructor_contents =~ s/\{(\s+)/\{\n Trick::JobData * job __attribute__((unused)) ;\n/ ;
#$constructor_contents =~ s/\{(\s+)/\{$1int ii __attribute__ ((unused)) = $$sim_ref{sim_class_index}{$class_name} ;\n/ ;
while ($constructor_contents =~ s/^(.*?)($sim_class_job_def)//s ) {
$final_contents .= $1 ;
$job = $2 ;
# check to see if what we matched is actually a placement new statement.
if ( $final_contents !~ /new\s*$/ ) {
# Not a placement new statement.
trick_print($$sim_ref{fh}, " Job found $job\n" , "debug_white" , $$sim_ref{args}{v});
($job_push , $job_call , $is_dynamic_event) = handle_sim_class_job($job, $$sim_ref{sim_class_index}{$class_name}, $sim_ref ) ;
$final_contents .= "\n $job_push" ;
if ( $is_dynamic_event == 1 ) {
push @double_job_calls , $job_call ;
$double_call_functions .= " case $$sim_ref{sim_class_index}{$class_name}:\n trick_ret = $job_call ;\n break ;\n" ;
} else {
push @int_job_calls , $job_call ;
$int_call_functions .= " case $$sim_ref{sim_class_index}{$class_name}:\n $job_call ;\n break ;\n" ;
}
$$sim_ref{sim_class_index}{$class_name}++ ;
} else {
# Is a placement new statement. Just copy contents to final_contents.
$final_contents .= $job ;
}
}
$final_contents .= $constructor_contents ;
}
if ( $constructor_found == 1 ) {
# if there is an inherited base class then the job id may reside in the base class
if ( $inherit_class eq "Trick::SimObject" or $inherit_class eq "SimObject" ) {
$int_call_functions .= " default:\n trick_ret = -1 ;\n break ;\n" ;
$double_call_functions .= " default:\n trick_ret = 0.0 ;\n break ;\n" ;
} else {
$int_call_functions .= " default:\n trick_ret = ${inherit_class}::call_function( curr_job ) ;\n break ;\n" ;
$double_call_functions .= " default:\n trick_ret = ${inherit_class}::call_function_double( curr_job ) ;\n break ;\n" ;
}
$int_call_functions .= " }\n\n return(trick_ret) ;\n}\n\n" ;
$double_call_functions .= " }\n\n return(trick_ret) ;\n}\n\n" ;
#TODO: This section should probably go into s_source.pm
$final_contents .= "\n\n public:\n" ;
$final_contents .= " virtual int call_function( Trick::JobData * curr_job ) ;\n" ;
$final_contents .= " virtual double call_function_double( Trick::JobData * curr_job ) ;\n" ;
$final_contents .= "$class_contents ;\n\n" ;
#print "$final_contents\n" ;
$final_contents =~ s/^##/#/mg ;
#$contents =~ s/\/\*(.*?)\*\/|\/\/(.*?)(\n)/"" . $i++ . " " . ((defined $3) ? $3 : "")/esg ;
$final_contents =~ s/ZZZYYYXXX(\d+)ZZZYYYXXX/@$comments_ref[$1]/esg ;
$$sim_ref{sim_class_code} .= $final_contents ;
$$sim_ref{sim_class_call_functions} .= $int_call_functions . $double_call_functions ;
} else {
$s =~ s/ZZZYYYXXX(\d+)ZZZYYYXXX/@$comments_ref[$1]/esg ;
$$sim_ref{sim_class_code} .= $s ;
$class_contents =~ s/}\s*$// ;
$class_contents .= "\n\n public:\n" ;
$class_contents .= " virtual int call_function( Trick::JobData * curr_job ) ;\n" ;
$class_contents .= " virtual double call_function_double( Trick::JobData * curr_job ) ;\n" ;
$class_contents .= "} ;\n\n" ;
$class_contents =~ s/ZZZYYYXXX(\d+)ZZZYYYXXX/@$comments_ref[$1]/esg ;
$$sim_ref{sim_class_code} .= $class_contents ;
if ( $full_template_args eq "" ) {
$int_call_functions = "int ${class_name}" ;
$double_call_functions = "double ${class_name}" ;
} else {
$int_call_functions = "template <$full_template_args> int ${class_name}<$template_args>" ;
$double_call_functions = "template <$full_template_args> double ${class_name}<$template_args>" ;
}
$int_call_functions .= "::call_function ( Trick::JobData * curr_job __attribute__ ((unused)) ) {return 0;}\n" ;
$double_call_functions .= "::call_function_double ( Trick::JobData * curr_job __attribute__ ((unused)) ) {return 0.0;}\n" ;
$$sim_ref{sim_class_call_functions} .= $int_call_functions . $double_call_functions ;
}
}
sub handle_sim_class_job($$$) {
my ($in_job, $job_id, $sim_ref) = @_ ;
my ($job_push, $is_dynamic_event) ;
my ( $child, $phase, $cycle, $start, $stop, $ov_class ,
$ov_class_self, $sup_class_data, $tag, $job_call, $job_ret, $job_name, $args , $class ) ;
my (@tags) ;
($child, $phase, $cycle, $start, $stop,
$ov_class , $ov_class_self , $sup_class_data, $tag, $job_call, $job_ret, $job_name, $args) = $in_job =~ /
(?:
\s*(?:
([Cc][\w\.\-\>]+) | # child spec
([Pp][\w\.\-\>]+) | # phase spec
(?:
\(
(?:
(?:
\s*([\w.]+)\s* # cycle time
(?:,\s*([\w.]+)\s*)? # start time
(?:,\s*([\w.]+)\s*)? # stop time
(?:,\s*("?\w+"?)\s*) # class
)|
\s*("?\w+"?)\s* # class (by itself)
(?:,\s*(&?[\w\.\-\>]+)\s*)? # integration object
)
\)
) | # timing spec
\{([\w_.,\s]+)\} # job tag
)
)+\s+
( # job call
([A-Za-z_][\w\.\-\>]*\s*=)?\s* # optional return assignment variable
([A-Za-z_][\w\.\:\-\>\[\]]*)\s* # job name
\((.*?)\s*\) # arg list
)\s*; # end job call
/sx ;
$child = 0 if ( $child eq "" ) ;
$child =~ s/^C// ;
$cycle = 1.0 if ( $cycle eq "" ) ;
if ( $ov_class ne "" ) {
$class = $ov_class ;
} else {
$class = $ov_class_self ;
}
if ($sup_class_data eq "") {
$sup_class_data = "NULL";
}
if ( $class =~ /dynamic_event/ ) {
$is_dynamic_event = 1 ;
} else {
$is_dynamic_event = 0 ;
}
if ( $tag ne "" ) {
$tag =~ s/\s+//g ;
@tags = split /,/ , $tag ;
}
$job_push = "job = add_job($child, $job_id, $class, $sup_class_data, $cycle, \"$job_name\", \"\"" ;
if ( $class =~ /^integration$/ ) {
if ($job_ret !~ /trick_ret/ ) {
$job_call = "trick_ret = " . $job_call ;
}
}
if ( $phase ne "" ) {
$phase =~ s/^P// ;
$job_push .= ", $phase" ;
} else {
$job_push .= ", 60000" ;
}
if ( $start ne "" ) {
$job_push .= ", $start" ;
}
if ( $stop ne "" ) {
$job_push .= ", $stop" ;
}
$job_push .= ") ;" ;
foreach my $t ( @tags ) {
$job_push .= "\n " ;
$job_push .= "job->add_tag(\"$t\") ;" ;
}
trick_print($$sim_ref{fh}," Job deconstruction:
Job_id: $job_id
Child: $child
Phase: $phase
Tag: $tag
Class: $class
Supplemental data: $sup_class_data
Cycle: $cycle
Start: $start
Stop: $stop
Job name: $job_name\n", "debug_white", $$sim_ref{args}{v}) ;
return $job_push , $job_call , $is_dynamic_event ;
}
sub handle_instantiation ($$) {
my ($s, $sim_ref) = @_;
my ($type , $name) ;
$s =~ s/ZZZYYYXXX(\d+)ZZZYYYXXX//g ;
#print "instance $s\n" ;
($type , $name) = $s =~ /([A-Za-z_]+[\w_:\*]*(?:<[^>]+>)?)\s+([A-Za-z_]+[\w_]*)/s ;
#print "instance type = $type , name = $name\n" ;
push @{$$sim_ref{instances}} , $name ;
$$sim_ref{instances_type}{$name} = $type ;
$$sim_ref{instance_declarations} .= "$s\n" ;
trick_print($$sim_ref{fh},"Instantiation: $s\n", "debug_white", $$sim_ref{args}{v}) ;
# remove constructor parameters
$s =~ s/\(.*/;/s ;
if ($type =~ /<[^>]+>/) {
$$sim_ref{template_instance_declarations} .= "$s\n" ;
}
$$sim_ref{extern_instance_declarations} .= "extern $s\n" ;
}
sub handle_create_connections($$$) {
my ($s, $file_contents, $sim_ref) = @_;
my ($cc_code) ;
($cc_code, $$file_contents) = extract_bracketed($$file_contents,"{}");
trick_print($$sim_ref{fh},"Create connections code: $cc_code\n", "debug_white", $$sim_ref{args}{v}) ;
$cc_code =~ s/^{//s ;
$cc_code =~ s/}$//s ;
$cc_code =~ s/ZZZYYYXXX(\d+)ZZZYYYXXX//g ;
$$sim_ref{create_connections} .= $cc_code ;
#print $$sim_ref{create_connections} ;
}
sub handle_line_tag($$) {
my ($s, $sim_ref) = @_;
my ($line_num , $file_name) = $s =~ /(\d+)\s*\"(.*?)\"/;
trick_print($$sim_ref{fh},"Line: $s\n", "debug_yellow", $$sim_ref{args}{v}) ;
if ( $file_name !~ /^\</ and $file_name ne $$sim_ref{last_file} ) {
if ( exists $$sim_ref{files_visited}{$file_name} ) {
trick_print($$sim_ref{fh},"Continuing $file_name\n", "normal_cyan", $$sim_ref{args}{v}) ;
} else {
trick_print($$sim_ref{fh},"Processing $file_name\n", "normal_cyan", $$sim_ref{args}{v}) ;
$$sim_ref{files_visited}{$file_name} = 1 ;
}
$$sim_ref{last_file} = $file_name ;
}
$$sim_ref{line_num} = $line_num ;
}
sub handle_compiler_directive($$) {
my ($s, $sim_ref) = @_;
my ($rel_file_name) ;
my ($file_name) ;
$s =~ s/^#// ;
trick_print($$sim_ref{fh},"Compiler directive: $s\n", "debug_white", $$sim_ref{args}{v}) ;
# system header
if ( $s =~ /^\#include\s+\</ ) {
$$sim_ref{system_headers} .= "$s\n" ;
} else {
#push @{$$sim_ref{sim_class_includes}} , $s ;
if ( $s =~ s/^\#include \"(\/.*)\"/$1/ ) {
$$sim_ref{headers_full_path}{$s} = $s ;
push @{$$sim_ref{sim_class_includes}} , $s ;
}
elsif ( $s =~ /include\s*\"([^\"]+)\"/ ) {
($rel_file_name) = $1 ;
$file_name = find_header_file($rel_file_name , \@{$$sim_ref{inc_paths}}) ;
if ( $file_name eq "" ) {
trick_print($$sim_ref{fh}, "could not find $rel_file_name\n" , "title_red", $$sim_ref{args}{v});
exit -1 ;
}
trick_print($$sim_ref{fh}," Found include: $file_name\n", "debug_white", $$sim_ref{args}{v}) ;
$$sim_ref{headers_full_path}{$rel_file_name} = $file_name ;
push @{$$sim_ref{sim_class_includes}} , $file_name ;
my $suffix ;
if ( $file_name =~ /\.h$/ ) {
# Try and determine language.
# extract the Trick header
my %header ;
local $/ = undef ;
open TEXT, '<', $file_name ;
my $file_contents = <TEXT> ;
%header = extract_trick_header( $file_name, $file_contents, 0 , 0 );
# set the language if an override in the header is found
if ( $header{language} eq "CPP" ) {
$suffix = "cpp" ;
}
else {
$suffix = "c" ;
}
} else {
$suffix = "cpp" ;
}
# save off suffix for make_makefile
$$sim_ref{headers_lang}{$file_name} = $suffix ;
} else {
trick_print($$sim_ref{fh},"ERROR: S_define:$$sim_ref{line_num}: ##include expects \"FILENAME\" (double quotes for FILENAME) \n", "title_red", $$sim_ref{args}{v}) ;
}
}
}
sub preparse_job_class_order($$) {
my ( $job_class_order_structs , $sim_ref ) = @_ ;
my $class_text ;
my @class_list ;
my %temp_hash ;
if ( scalar @{$job_class_order_structs} > 1 ) {
edit_and_exit("Multiple job order constructs found" , "$s_define_file" , 1 ) ;
} elsif ( scalar @{$job_class_order_structs} == 0 ) {
return ;
}
# get a list of classes
($class_text) = @{$job_class_order_structs}[0] =~ /{(.*?)}/sx ;
$class_text =~ s/^\s+|\s+$//gs ;
@class_list = split /\s*,\s*/ , $class_text ;
# check to make sure the class names are not duplicated
foreach my $c ( @class_list ) {
if ( exists $temp_hash{$c} ) {
trick_print($$sim_ref{fh}, "\nCP ERROR:\n Job class \"$c\" duplicated in new order.\n" , "title_red" , $$sim_ref{args}{v} ) ;
edit_and_exit("CP bad job class order" , "$s_define_file" , 1 ) ;
}
$temp_hash{$c}++ ;
}
# save the new order
@{$$sim_ref{user_class_order}} = @class_list ;
# push on the advance_sim_time class last if not specified
if ( !exists $temp_hash{data_record} ) {
push @{$$sim_ref{user_class_order}} , "data_record" ;
}
if ( !exists $temp_hash{system_checkpoint} ) {
push @{$$sim_ref{user_class_order}} , "system_checkpoint" ;
}
if ( !exists $temp_hash{system_advance_sim_time} ) {
push @{$$sim_ref{user_class_order}} , "system_advance_sim_time" ;
}
if ( !exists $temp_hash{system_moding} ) {
push @{$$sim_ref{user_class_order}} , "system_moding" ;
}
}
1;