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 !~ /^\ ; %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;