18e4296c2SFrank Rowand#!/usr/bin/perl 28e4296c2SFrank Rowand# SPDX-License-Identifier: GPL-2.0 38e4296c2SFrank Rowand# 48e4296c2SFrank Rowand# Copyright 2020, 2022 Sony Corporation 58e4296c2SFrank Rowand# 68e4296c2SFrank Rowand# Author: Frank Rowand 78e4296c2SFrank Rowand 88e4296c2SFrank Rowand# This program is meant to be an aid to reading the verbose output of 98e4296c2SFrank Rowand# on the console log that results from executing the Linux kernel 108e4296c2SFrank Rowand# devicetree unittest (drivers/of/unitest.c). 118e4296c2SFrank Rowand 12*511f3aa7SFrank Rowand$VUFX = "230121a"; 138e4296c2SFrank Rowand 148e4296c2SFrank Rowanduse strict 'refs'; 158e4296c2SFrank Rowanduse strict subs; 168e4296c2SFrank Rowand 178e4296c2SFrank Rowanduse Getopt::Long; 188e4296c2SFrank Rowanduse Text::Wrap; 198e4296c2SFrank Rowand 208e4296c2SFrank Rowand# strip off everything before final "/" 218e4296c2SFrank Rowand(undef, $script_name) = split(/^.*\//, $0); 228e4296c2SFrank Rowand 238e4296c2SFrank Rowand# following /usr/include/sysexits.h 248e4296c2SFrank Rowand$EX_OK=0; 258e4296c2SFrank Rowand$EX_USAGE=64; 268e4296c2SFrank Rowand 278e4296c2SFrank Rowand 288e4296c2SFrank Rowand#______________________________________________________________________________ 298e4296c2SFrank Rowandsub compare { 308e4296c2SFrank Rowand my ($expect, $got) = @_; 318e4296c2SFrank Rowand my $expect_next; 328e4296c2SFrank Rowand my $expect_next_lit; 338e4296c2SFrank Rowand my $got_next; 348e4296c2SFrank Rowand my $type; 358e4296c2SFrank Rowand 368e4296c2SFrank Rowand while ($expect) { 378e4296c2SFrank Rowand 388e4296c2SFrank Rowand ($expect_next, $type) = split(/<</, $expect); 398e4296c2SFrank Rowand ($type) = split(/>>/, $type); 408e4296c2SFrank Rowand $expect =~ s/^.*?>>//; # '?' is non-greedy, minimal match 418e4296c2SFrank Rowand 428e4296c2SFrank Rowand # literal, ignore all metacharacters when used in a regex 438e4296c2SFrank Rowand $expect_next_lit = quotemeta($expect_next); 448e4296c2SFrank Rowand 458e4296c2SFrank Rowand $got_next = $got; 468e4296c2SFrank Rowand $got_next =~ s/^($expect_next_lit).*/\1/; 478e4296c2SFrank Rowand $got =~ s/^$expect_next_lit//; 488e4296c2SFrank Rowand 498e4296c2SFrank Rowand if ($expect_next ne $got_next) { 508e4296c2SFrank Rowand return 0; 518e4296c2SFrank Rowand } 528e4296c2SFrank Rowand 538e4296c2SFrank Rowand if ($type eq "int") { 548e4296c2SFrank Rowand if ($got =~ /^[+-]*[0-9]+/) { 558e4296c2SFrank Rowand $got =~ s/^[+-]*[0-9]+//; 568e4296c2SFrank Rowand } else { 578e4296c2SFrank Rowand return 0; 588e4296c2SFrank Rowand } 598e4296c2SFrank Rowand } elsif ($type eq "hex") { 608e4296c2SFrank Rowand if ($got =~ /^(0x)*[0-9a-f]+/) { 618e4296c2SFrank Rowand $got =~ s/^(0x)*[0-9a-f]+//; 628e4296c2SFrank Rowand } else { 638e4296c2SFrank Rowand return 0; 648e4296c2SFrank Rowand } 658e4296c2SFrank Rowand } elsif ($type eq "") { 668e4296c2SFrank Rowand if ($expect_next ne $got_next) { 678e4296c2SFrank Rowand return 0; 688e4296c2SFrank Rowand } else { 698e4296c2SFrank Rowand return 1; 708e4296c2SFrank Rowand } 718e4296c2SFrank Rowand } else { 728e4296c2SFrank Rowand $internal_err++; 738e4296c2SFrank Rowand print "** ERROR: special pattern not recognized: <<$type>>, CONSOLE_LOG line: $.\n"; 748e4296c2SFrank Rowand return 0; 758e4296c2SFrank Rowand } 768e4296c2SFrank Rowand 778e4296c2SFrank Rowand } 788e4296c2SFrank Rowand 798e4296c2SFrank Rowand # should not get here 808e4296c2SFrank Rowand $internal_err++; 818e4296c2SFrank Rowand print "** ERROR: $script_name internal error, at end of compare(), CONSOLE_LOG line: $.\n"; 828e4296c2SFrank Rowand 838e4296c2SFrank Rowand return 0; 848e4296c2SFrank Rowand} 858e4296c2SFrank Rowand 868e4296c2SFrank Rowand 878e4296c2SFrank Rowand#______________________________________________________________________________ 888e4296c2SFrank Rowandsub usage { 898e4296c2SFrank Rowand 908e4296c2SFrank Rowand# ***** when editing, be careful to not put tabs in the string printed: 918e4296c2SFrank Rowand 928e4296c2SFrank Rowand print STDERR 938e4296c2SFrank Rowand" 948e4296c2SFrank Rowandusage: 958e4296c2SFrank Rowand 968e4296c2SFrank Rowand $script_name CONSOLE_LOG 978e4296c2SFrank Rowand 988e4296c2SFrank Rowand -h print program usage 998e4296c2SFrank Rowand --help print program usage 1008e4296c2SFrank Rowand --hide-expect suppress output of EXPECTed lines 1018e4296c2SFrank Rowand --line-num report line number of CONSOLE_LOG 1028e4296c2SFrank Rowand --no-expect-stats do not report EXPECT statistics 1038e4296c2SFrank Rowand --no-strip-ts do not strip leading console timestamps 1048e4296c2SFrank Rowand --verbose do not suppress EXPECT begin and end lines 1058e4296c2SFrank Rowand --version print program version and exit 1068e4296c2SFrank Rowand 1078e4296c2SFrank Rowand 1088e4296c2SFrank Rowand Process a console log for EXPECTed test related messages to either 1098e4296c2SFrank Rowand highlight expected devicetree unittest related messages or suppress 1108e4296c2SFrank Rowand the messages. Leading console timestamps will be stripped. 1118e4296c2SFrank Rowand 1128e4296c2SFrank Rowand Various unittests may trigger kernel messages from outside the 1138e4296c2SFrank Rowand unittest code. The unittest annotates that it expects the message 1148e4296c2SFrank Rowand to occur with an 'EXPECT \\ : text' (begin) before triggering the 1158e4296c2SFrank Rowand message, and an 'EXPECT / : text' (end) after triggering the message. 1168e4296c2SFrank Rowand 1178e4296c2SFrank Rowand If an expected message does not occur, that will be reported. 1188e4296c2SFrank Rowand 1198e4296c2SFrank Rowand For each expected message, the 'EXPECT \\ : text' (begin) and 1208e4296c2SFrank Rowand 'EXPECT / : text' (end), 'text' will contain the message text. 1218e4296c2SFrank Rowand 1228e4296c2SFrank Rowand If 'EXPECT \\' (begin) and 'EXPECT /' (end) lines do not contain 1238e4296c2SFrank Rowand matching 'text', that will be reported. 1248e4296c2SFrank Rowand 1258e4296c2SFrank Rowand If EXPECT lines are nested, 'EXPECT /' (end) lines must be in the 1268e4296c2SFrank Rowand reverse order of the corresponding 'EXPECT \\' (begin) lines. 1278e4296c2SFrank Rowand 1288e4296c2SFrank Rowand 'EXPECT \\ : text' (begin) and 'EXPECT / : text' (end) lines can 1298e4296c2SFrank Rowand contain special patterns in 'text': 1308e4296c2SFrank Rowand 1318e4296c2SFrank Rowand <<int>> matches: [+-]*[0-9]+ 1328e4296c2SFrank Rowand <<hex>> matches: (0x)*[0-9a-f]+ 1338e4296c2SFrank Rowand 1348e4296c2SFrank Rowand 'EXPECT \\' (begin) and 'EXPECT /' (end) lines are suppressed. 1358e4296c2SFrank Rowand 1368e4296c2SFrank Rowand A prefix is added to every line of output: 1378e4296c2SFrank Rowand 1388e4296c2SFrank Rowand 'ok ' Line matches an enclosing EXPECT begin/end pair 1398e4296c2SFrank Rowand 1408e4296c2SFrank Rowand '** ' Line reports $script_name warning or error 1418e4296c2SFrank Rowand 1428e4296c2SFrank Rowand '-> ' Line reports start or end of the unittests 1438e4296c2SFrank Rowand 1448e4296c2SFrank Rowand '>> ' Line reports a unittest test FAIL 1458e4296c2SFrank Rowand 1468e4296c2SFrank Rowand ' ' Lines that are not otherwise prefixed 1478e4296c2SFrank Rowand 1488e4296c2SFrank Rowand Issues detected in CONSOLE_LOG are reported to STDOUT, not to STDERR. 1498e4296c2SFrank Rowand 1508e4296c2SFrank Rowand Known Issues: 1518e4296c2SFrank Rowand 1528e4296c2SFrank Rowand --line-num causes the CONSOLE_LOG line number to be printed in 4 columns. 1538e4296c2SFrank Rowand If CONSOLE_LOG contains more than 9999 lines then more columns will be 1548e4296c2SFrank Rowand used to report the line number for lines greater than 9999 (eg for 1558e4296c2SFrank Rowand lines 10000 - 99999, 5 columns will be used). 1568e4296c2SFrank Rowand"; 1578e4296c2SFrank Rowand 1588e4296c2SFrank Rowand return {}; 1598e4296c2SFrank Rowand} 1608e4296c2SFrank Rowand 1618e4296c2SFrank Rowand#______________________________________________________________________________ 1628e4296c2SFrank Rowand#______________________________________________________________________________ 1638e4296c2SFrank Rowand 1648e4296c2SFrank Rowandif (!GetOptions( 1658e4296c2SFrank Rowand "h" => \$help, 1668e4296c2SFrank Rowand "help" => \$help, 1678e4296c2SFrank Rowand "hide-expect" => \$hide_expect, 1688e4296c2SFrank Rowand "line-num" => \$print_line_num, 1698e4296c2SFrank Rowand "no-expect-stats" => \$no_expect_stats, 1708e4296c2SFrank Rowand "no-strip-ts" => \$no_strip_ts, 1718e4296c2SFrank Rowand "verbose" => \$verbose, 1728e4296c2SFrank Rowand "version" => \$version, 1738e4296c2SFrank Rowand )) { 1748e4296c2SFrank Rowand print STDERR "\n"; 1758e4296c2SFrank Rowand print STDERR "ERROR processing command line options\n"; 1768e4296c2SFrank Rowand print STDERR "\n"; 1778e4296c2SFrank Rowand print STDERR "For help, type '$script_name --help'\n"; 1788e4296c2SFrank Rowand print STDERR "\n"; 1798e4296c2SFrank Rowand 1808e4296c2SFrank Rowand exit $EX_OK; 1818e4296c2SFrank Rowand} 1828e4296c2SFrank Rowand 1838e4296c2SFrank Rowand 1848e4296c2SFrank Rowandif ($no_strip_ts) { 1858e4296c2SFrank Rowand $strip_ts = 1; 1868e4296c2SFrank Rowand $no_strip_ts = 0; 1878e4296c2SFrank Rowand} else { 1888e4296c2SFrank Rowand $strip_ts = 0; 1898e4296c2SFrank Rowand $no_strip_ts = 1; 1908e4296c2SFrank Rowand} 1918e4296c2SFrank Rowand 1928e4296c2SFrank Rowand 1938e4296c2SFrank Rowand# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1948e4296c2SFrank Rowandif ($help){ 1958e4296c2SFrank Rowand 1968e4296c2SFrank Rowand &usage; 1978e4296c2SFrank Rowand 1988e4296c2SFrank Rowand exit $EX_OK; 1998e4296c2SFrank Rowand} 2008e4296c2SFrank Rowand 2018e4296c2SFrank Rowand 2028e4296c2SFrank Rowand# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2038e4296c2SFrank Rowand 2048e4296c2SFrank Rowandif ($version) { 2058e4296c2SFrank Rowand print STDERR "\n$script_name $VUFX\n\n"; 2068e4296c2SFrank Rowand print STDERR "\n"; 2078e4296c2SFrank Rowand 2088e4296c2SFrank Rowand exit $EX_OK; 2098e4296c2SFrank Rowand} 2108e4296c2SFrank Rowand 2118e4296c2SFrank Rowand 2128e4296c2SFrank Rowand# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2138e4296c2SFrank Rowandif ($#ARGV != 0) { 2148e4296c2SFrank Rowand 2158e4296c2SFrank Rowand # Limit input files to exactly one. 2168e4296c2SFrank Rowand # 2178e4296c2SFrank Rowand # 'while ($line = <ARGV>) {' in the code below supports multiple file 2188e4296c2SFrank Rowand # names on the command line, but the EXPECT statistics are reported 2198e4296c2SFrank Rowand # once for all input - it is not an expected use case to generate one 2208e4296c2SFrank Rowand # set of statistics for multiple input files. 2218e4296c2SFrank Rowand 2228e4296c2SFrank Rowand print STDERR "\n"; 2238e4296c2SFrank Rowand print STDERR "Required arguments: CONSOLE_LOG\n"; 2248e4296c2SFrank Rowand print STDERR "\n"; 2258e4296c2SFrank Rowand 2268e4296c2SFrank Rowand exit $EX_USAGE; 2278e4296c2SFrank Rowand} 2288e4296c2SFrank Rowand 2298e4296c2SFrank Rowand 2308e4296c2SFrank Rowand#______________________________________________________________________________ 2318e4296c2SFrank Rowand 2328e4296c2SFrank Rowand# Patterns to match 'EXPECT \ : ' (begin) and 'EXPECT / : ' (end) 2338e4296c2SFrank Rowand# 2348e4296c2SFrank Rowand# $exp_* are used as regex match patterns, 2358e4296c2SFrank Rowand# so '\\\\' in $exp_begin matches a single '\' 2368e4296c2SFrank Rowand# quotemeta() does not do the right thing in this case 2378e4296c2SFrank Rowand# 2388e4296c2SFrank Rowand# $pr_fmt is the prefix that unittest prints for every message 2398e4296c2SFrank Rowand 2408e4296c2SFrank Rowand$pr_fmt = "### dt-test ### "; 2418e4296c2SFrank Rowand$exp_begin = "${pr_fmt}EXPECT \\\\ : "; 2428e4296c2SFrank Rowand$exp_end = "${pr_fmt}EXPECT / : "; 2438e4296c2SFrank Rowand 2448e4296c2SFrank Rowand 2458e4296c2SFrank Rowand$line_num = ""; 2468e4296c2SFrank Rowand$timestamp = ""; 2478e4296c2SFrank Rowand 2488e4296c2SFrank RowandLINE: 2498e4296c2SFrank Rowandwhile ($line = <ARGV>) { 2508e4296c2SFrank Rowand 2518e4296c2SFrank Rowand chomp $line; 2528e4296c2SFrank Rowand 2538e4296c2SFrank Rowand $prefix = " "; ## 2 characters 2548e4296c2SFrank Rowand 2558e4296c2SFrank Rowand 2568e4296c2SFrank Rowand if ($strip_ts) { 2578e4296c2SFrank Rowand 2588e4296c2SFrank Rowand $timestamp = $line; 2598e4296c2SFrank Rowand 2608e4296c2SFrank Rowand if ($timestamp =~ /^\[\s*[0-9]+\.[0-9]*\] /) { 2618e4296c2SFrank Rowand ($timestamp, $null) = split(/]/, $line); 2628e4296c2SFrank Rowand $timestamp = $timestamp . "] "; 2638e4296c2SFrank Rowand 2648e4296c2SFrank Rowand } else { 2658e4296c2SFrank Rowand $timestamp = ""; 2668e4296c2SFrank Rowand } 2678e4296c2SFrank Rowand } 2688e4296c2SFrank Rowand 2698e4296c2SFrank Rowand $line =~ s/^\[\s*[0-9]+\.[0-9]*\] //; 2708e4296c2SFrank Rowand 2718e4296c2SFrank Rowand 2728e4296c2SFrank Rowand # ----- find EXPECT begin 2738e4296c2SFrank Rowand 2748e4296c2SFrank Rowand if ($line =~ /^\s*$exp_begin/) { 2758e4296c2SFrank Rowand $data = $line; 2768e4296c2SFrank Rowand $data =~ s/^\s*$exp_begin//; 277*511f3aa7SFrank Rowand push @exp_begin_stack, $data; 2788e4296c2SFrank Rowand 2798e4296c2SFrank Rowand if ($verbose) { 2808e4296c2SFrank Rowand if ($print_line_num) { 2818e4296c2SFrank Rowand $line_num = sprintf("%4s ", $.); 2828e4296c2SFrank Rowand } 2838e4296c2SFrank Rowand printf "%s %s%s%s\n", $prefix, $line_num, $timestamp, $line; 2848e4296c2SFrank Rowand } 2858e4296c2SFrank Rowand 2868e4296c2SFrank Rowand next LINE; 2878e4296c2SFrank Rowand } 2888e4296c2SFrank Rowand 2898e4296c2SFrank Rowand 2908e4296c2SFrank Rowand # ----- find EXPECT end 2918e4296c2SFrank Rowand 2928e4296c2SFrank Rowand if ($line =~ /^\s*$exp_end/) { 2938e4296c2SFrank Rowand $data = $line; 2948e4296c2SFrank Rowand $data =~ s/^\s*$exp_end//; 2958e4296c2SFrank Rowand 2968e4296c2SFrank Rowand if ($verbose) { 2978e4296c2SFrank Rowand if ($print_line_num) { 2988e4296c2SFrank Rowand $line_num = sprintf("%4s ", $.); 2998e4296c2SFrank Rowand } 3008e4296c2SFrank Rowand printf "%s %s%s%s\n", $prefix, $line_num, $timestamp, $line; 3018e4296c2SFrank Rowand } 3028e4296c2SFrank Rowand 3038e4296c2SFrank Rowand $found = 0; 3048e4296c2SFrank Rowand $no_begin = 0; 305*511f3aa7SFrank Rowand if (@exp_found_or_begin > 0) { 306*511f3aa7SFrank Rowand $begin = pop @exp_found_or_begin; 3078e4296c2SFrank Rowand if (compare($data, $begin)) { 3088e4296c2SFrank Rowand $found = 1; 3098e4296c2SFrank Rowand } 3108e4296c2SFrank Rowand } elsif (@begin > 0) { 311*511f3aa7SFrank Rowand $begin = pop @exp_begin_stack; 3128e4296c2SFrank Rowand } else { 3138e4296c2SFrank Rowand $no_begin = 1; 3148e4296c2SFrank Rowand } 3158e4296c2SFrank Rowand 3168e4296c2SFrank Rowand if ($no_begin) { 3178e4296c2SFrank Rowand 318*511f3aa7SFrank Rowand $exp_missing_begin++; 3198e4296c2SFrank Rowand print "** ERROR: EXPECT end without any EXPECT begin:\n"; 3208e4296c2SFrank Rowand print " end ---> $line\n"; 3218e4296c2SFrank Rowand 3228e4296c2SFrank Rowand } elsif (! $found) { 3238e4296c2SFrank Rowand 3248e4296c2SFrank Rowand if ($print_line_num) { 3258e4296c2SFrank Rowand $line_num = sprintf("%4s ", $.); 3268e4296c2SFrank Rowand } 3278e4296c2SFrank Rowand 328*511f3aa7SFrank Rowand $exp_missing++; 3298e4296c2SFrank Rowand printf "** %s%s$script_name WARNING - not found ---> %s\n", 3308e4296c2SFrank Rowand $line_num, $timestamp, $data; 3318e4296c2SFrank Rowand 3328e4296c2SFrank Rowand } elsif (! compare($data, $begin)) { 3338e4296c2SFrank Rowand 334*511f3aa7SFrank Rowand $exp_missing_end++; 3358e4296c2SFrank Rowand print "** ERROR: EXPECT end does not match EXPECT begin:\n"; 3368e4296c2SFrank Rowand print " begin -> $begin\n"; 3378e4296c2SFrank Rowand print " end ---> $line\n"; 3388e4296c2SFrank Rowand 3398e4296c2SFrank Rowand } else { 3408e4296c2SFrank Rowand 341*511f3aa7SFrank Rowand $exp_found++; 3428e4296c2SFrank Rowand 3438e4296c2SFrank Rowand } 3448e4296c2SFrank Rowand 3458e4296c2SFrank Rowand next LINE; 3468e4296c2SFrank Rowand } 3478e4296c2SFrank Rowand 3488e4296c2SFrank Rowand 3498e4296c2SFrank Rowand # ----- not an EXPECT line 3508e4296c2SFrank Rowand 3518e4296c2SFrank Rowand if (($line =~ /^${pr_fmt}start of unittest - you will see error messages$/) || 3528e4296c2SFrank Rowand ($line =~ /^${pr_fmt}end of unittest - [0-9]+ passed, [0-9]+ failed$/ ) ) { 3538e4296c2SFrank Rowand $prefix = "->"; # 2 characters 3548e4296c2SFrank Rowand } elsif ($line =~ /^${pr_fmt}FAIL /) { 3558e4296c2SFrank Rowand $unittest_fail++; 3568e4296c2SFrank Rowand $prefix = ">>"; # 2 characters 3578e4296c2SFrank Rowand } 3588e4296c2SFrank Rowand 3598e4296c2SFrank Rowand $found = 0; 360*511f3aa7SFrank Rowand foreach $begin (@exp_begin_stack) { 3618e4296c2SFrank Rowand if (compare($begin, $line)) { 3628e4296c2SFrank Rowand $found = 1; 3638e4296c2SFrank Rowand last; 3648e4296c2SFrank Rowand } 3658e4296c2SFrank Rowand } 3668e4296c2SFrank Rowand 3678e4296c2SFrank Rowand if ($found) { 368*511f3aa7SFrank Rowand $begin = shift @exp_begin_stack; 3698e4296c2SFrank Rowand while (! compare($begin, $line)) { 370*511f3aa7SFrank Rowand push @exp_found_or_begin, $begin; 371*511f3aa7SFrank Rowand $begin = shift @exp_begin_stack; 3728e4296c2SFrank Rowand } 373*511f3aa7SFrank Rowand push @exp_found_or_begin, $line; 3748e4296c2SFrank Rowand 3758e4296c2SFrank Rowand if ($hide_expect) { 3768e4296c2SFrank Rowand $suppress_line = 1; 3778e4296c2SFrank Rowand next LINE; 3788e4296c2SFrank Rowand } 3798e4296c2SFrank Rowand $prefix = "ok"; # 2 characters 3808e4296c2SFrank Rowand } 3818e4296c2SFrank Rowand 3828e4296c2SFrank Rowand 3838e4296c2SFrank Rowand if ($print_line_num) { 3848e4296c2SFrank Rowand $line_num = sprintf("%4s ", $.); 3858e4296c2SFrank Rowand } 3868e4296c2SFrank Rowand 3878e4296c2SFrank Rowand printf "%s %s%s%s\n", $prefix, $line_num, $timestamp, $line; 3888e4296c2SFrank Rowand} 3898e4296c2SFrank Rowand 3908e4296c2SFrank Rowandif (! $no_expect_stats) { 3918e4296c2SFrank Rowand print "\n"; 3928e4296c2SFrank Rowand print "** EXPECT statistics:\n"; 3938e4296c2SFrank Rowand print "**\n"; 394*511f3aa7SFrank Rowand printf "** EXPECT found : %4i\n", $exp_found; 395*511f3aa7SFrank Rowand printf "** EXPECT not found : %4i\n", $exp_missing; 396*511f3aa7SFrank Rowand printf "** missing EXPECT begin : %4i\n", $exp_missing_begin; 397*511f3aa7SFrank Rowand printf "** missing EXPECT end : %4i\n", $exp_missing_end; 3988e4296c2SFrank Rowand printf "** unittest FAIL : %4i\n", $unittest_fail; 3998e4296c2SFrank Rowand printf "** internal error : %4i\n", $internal_err; 4008e4296c2SFrank Rowand} 4018e4296c2SFrank Rowand 402*511f3aa7SFrank Rowandif (@exp_begin_stack) { 4038e4296c2SFrank Rowand print "** ERROR: EXPECT begin without any EXPECT end:\n"; 4048e4296c2SFrank Rowand print " This list may be misleading.\n"; 405*511f3aa7SFrank Rowand foreach $begin (@exp_begin_stack) { 4068e4296c2SFrank Rowand print " begin ---> $begin\n"; 4078e4296c2SFrank Rowand } 4088e4296c2SFrank Rowand} 409