|
Packit |
0848f5 |
#! /usr/bin/env perl
|
|
Packit |
0848f5 |
# -*- Mode: perl; -*-
|
|
Packit |
0848f5 |
# This file contains the routines specific to extracting the states from
|
|
Packit |
0848f5 |
# the source files and writing them to the .states-cache files. This
|
|
Packit |
0848f5 |
# file is input into the "extractstrings" perl script that creates
|
|
Packit |
0848f5 |
# cache files in directory trees
|
|
Packit |
0848f5 |
#
|
|
Packit |
0848f5 |
# Creates the following files:
|
|
Packit |
0848f5 |
# src/include/mpiallstates.h - an enum of all of the states used in the
|
|
Packit |
0848f5 |
# code
|
|
Packit |
0848f5 |
# src/util/logging/common/state_names.h - a header file that provides an
|
|
Packit |
0848f5 |
# array of structures that map state
|
|
Packit |
0848f5 |
# value (from the enum in
|
|
Packit |
0848f5 |
# mpiallstates.h) to string names (and
|
|
Packit |
0848f5 |
# optional display colors).
|
|
Packit |
0848f5 |
# Replaces describe_states.c in the
|
|
Packit |
0848f5 |
# older version.
|
|
Packit |
0848f5 |
#
|
|
Packit |
0848f5 |
# Also allows an exceptions list on a per-directory basis. This file is
|
|
Packit |
0848f5 |
# describe_estates.txt, and contains
|
|
Packit |
0848f5 |
# statename routine-name [r g b]
|
|
Packit |
0848f5 |
# where [r g b] are optional and provide the color values as bytes, e.g.,
|
|
Packit |
0848f5 |
# 255 0 0
|
|
Packit |
0848f5 |
# is red
|
|
Packit |
0848f5 |
#
|
|
Packit |
0848f5 |
# FIXME: Add better error detection and reporting
|
|
Packit |
0848f5 |
# In the previous genstates.in script, a different set of problems in
|
|
Packit |
0848f5 |
# the source code was detected. Those included:
|
|
Packit |
0848f5 |
# Using STATE_DECL without FUNC_ENTER/EXIT
|
|
Packit |
0848f5 |
# Using FUNC_ENTER after FUNC_ENTER without FUNC_EXIT first
|
|
Packit |
0848f5 |
# Using FUNC_ENTER after FUNC_EXIT without a STATE_DECL first
|
|
Packit |
0848f5 |
#
|
|
Packit |
0848f5 |
# Some uses of these macros do not permit lexical scope checks. For
|
|
Packit |
0848f5 |
# example, code that has multiple "return"s, each of which has its
|
|
Packit |
0848f5 |
# own FUNC_EXIT, will defeat the check for FUNC_ENTER after FUNC_EXIT
|
|
Packit |
0848f5 |
# without a STATE_DECL
|
|
Packit |
0848f5 |
#
|
|
Packit |
0848f5 |
# Defaults for this step. These are globals variables that are used
|
|
Packit |
0848f5 |
# by routines in the extractstrings script.
|
|
Packit |
0848f5 |
# findStateDecl is the routine that is run to scan a file for information
|
|
Packit |
0848f5 |
use warnings;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
$scanFile = "findStateDecl";
|
|
Packit |
0848f5 |
$cachefile = '.state-cache';
|
|
Packit |
0848f5 |
$pattern = '\.[chi](pp){0,1}$';
|
|
Packit |
0848f5 |
$exceptionsFile = "estates.txt";
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
# Load in the routines to extract strings from files
|
|
Packit |
0848f5 |
$maintdir = "./maint";
|
|
Packit |
0848f5 |
require "$maintdir/extractstrings";
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
# These are "states" that are internal to a function, but still
|
|
Packit |
0848f5 |
# use FUNC_ENTER/EXIT
|
|
Packit |
0848f5 |
%exceptionState = ( # System Calls
|
|
Packit |
0848f5 |
'MPID_STATE_READ' => 'read',
|
|
Packit |
0848f5 |
'MPID_STATE_WRITE' => 'write',
|
|
Packit |
0848f5 |
'MPID_STATE_READV' => 'readv',
|
|
Packit |
0848f5 |
'MPID_STATE_WRITEV' => 'writev',
|
|
Packit |
0848f5 |
'MPID_STATE_MEMCPY' => 'memcpy',
|
|
Packit |
0848f5 |
'MPID_STATE_MPIDU_SOCK_LISTEN', # used in sock code
|
|
Packit |
0848f5 |
'MPID_STATE_MPIDU_SOCK_ACCEPT',
|
|
Packit |
0848f5 |
'MPID_STATE_POLL' => 'poll',
|
|
Packit |
0848f5 |
# MPICH internal implementation routines
|
|
Packit |
0848f5 |
'MPID_STATE_UPDATE_REQUEST' => 'update_request',
|
|
Packit |
0848f5 |
'MPID_STATE_CREATE_REQUEST' => 'create_request',
|
|
Packit |
0848f5 |
'MPID_STATE_MPIDU_YIELD' => 'MPIDU_Yield',
|
|
Packit |
0848f5 |
'MPID_STATE_MPIDU_SLEEP_YIELD' => 'MPIDU_Sleep_yield',
|
|
Packit |
0848f5 |
'MPID_STATE_GETQUEUEDCOMPLETIONSTATUS' =>
|
|
Packit |
0848f5 |
'GetQueuedCompletionStatus',
|
|
Packit |
0848f5 |
'MPID_STATE_CH3_CA_COMPLETE' => 'CH3_CA_Complete',
|
|
Packit |
0848f5 |
'MPID_STATE_VAPI_REGISTER_MR' => 'vapi_register_mr',
|
|
Packit |
0848f5 |
'MPID_STATE_VAPI_DEREGISTER_MR' => 'vapi_deregister_mr',
|
|
Packit |
0848f5 |
'MPID_STATE_VAPI_POST_SR' => 'vapi_post_sr',
|
|
Packit |
0848f5 |
);
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
# Set the default directories
|
|
Packit |
0848f5 |
$dirs = "src/include src/mpi src/mpid/ch3 src/mpid/common src/util src/pmi src/binding src/nameserv";
|
|
Packit |
0848f5 |
# Add mm for debugging
|
|
Packit |
0848f5 |
#$dirs .= " src/mpid/mm";
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
# Check for options
|
|
Packit |
0848f5 |
foreach (@ARGV) {
|
|
Packit |
0848f5 |
if (/-updateall/) { $gUpdateAll = 1; }
|
|
Packit |
0848f5 |
elsif (/-quiet/) { $gVerbose = 0; }
|
|
Packit |
0848f5 |
elsif (/-verbose=(\d+)/) { $gVerbose = $1; }
|
|
Packit |
0848f5 |
elsif (/-verbose/) { $gVerbose = 1; }
|
|
Packit |
0848f5 |
elsif (/-xxx/) {
|
|
Packit |
0848f5 |
# gUpdateAll and scanFile are used in the extractstrings file. To
|
|
Packit |
0848f5 |
# keep perl -w happy, we provide another use of these two
|
|
Packit |
0848f5 |
# symbols
|
|
Packit |
0848f5 |
print STDERR "gUpdateAll = $gUpdateAll, gVerbose = $gVerbose, and scanFile = $scanFile\n";
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
elsif (/-dirs=(.*)/) {
|
|
Packit |
0848f5 |
$dirs = $1;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else {
|
|
Packit |
0848f5 |
print STDERR "Unrecognized argument $_\n";
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
# First, update any cache files
|
|
Packit |
0848f5 |
# This step reads each cache file and rescans any files more recent than
|
|
Packit |
0848f5 |
# their cached information are rescanned and the cachefiles are updated
|
|
Packit |
0848f5 |
# Any file that needs to be updated is read with the routine given by
|
|
Packit |
0848f5 |
# the variable "scanFile", which is "findStateDecl" in this script.
|
|
Packit |
0848f5 |
foreach my $dir (split(/\s/,$dirs)) {
|
|
Packit |
0848f5 |
&processDirs( $dir, $cachefile, $pattern );
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
# Now, extract all of the info from the cachefiles into allInfo
|
|
Packit |
0848f5 |
# This reads the cached information. catState will also read any
|
|
Packit |
0848f5 |
# per-directory (allInfo is global and is accessed by catState)
|
|
Packit |
0848f5 |
%allInfo = ();
|
|
Packit |
0848f5 |
foreach my $dir (split(/\s/,$dirs)) {
|
|
Packit |
0848f5 |
&processDirsAndAction( $dir, "catState", $cachefile );
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
# Make sure that there are no inconsistencies in the list by
|
|
Packit |
0848f5 |
# ensuring that all keys have the same descriptions. Report on
|
|
Packit |
0848f5 |
# any problems
|
|
Packit |
0848f5 |
&CheckAllInfo;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
# Finally, use allInfo to create the final description.
|
|
Packit |
0848f5 |
# What we do first is to convert it from lines that hash to a location
|
|
Packit |
0848f5 |
# (which makes it easier to identify problems) to a hash that maps keys to
|
|
Packit |
0848f5 |
# values. This gives us one more opportunity to detect duplicate or
|
|
Packit |
0848f5 |
# mismatched values
|
|
Packit |
0848f5 |
%allKeys = ();
|
|
Packit |
0848f5 |
%allKeysLoc = ();
|
|
Packit |
0848f5 |
foreach my $key (keys(%allInfo)) {
|
|
Packit |
0848f5 |
# Split line into value
|
|
Packit |
0848f5 |
my $val = "";
|
|
Packit |
0848f5 |
my $origKey = $key;
|
|
Packit |
0848f5 |
if ($key =~ /(\S+)\s+(.*)/) {
|
|
Packit |
0848f5 |
$key = $1;
|
|
Packit |
0848f5 |
$val = $2;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
if (defined($allKeys{$key})) {
|
|
Packit |
0848f5 |
my $valForKey = $allKeys{$key};
|
|
Packit |
0848f5 |
if ($valForKey ne $val) {
|
|
Packit |
0848f5 |
print STDERR "\nInconsistent values for keys:\n";
|
|
Packit |
0848f5 |
print STDERR "In $allInfo{$origKey}, have\n";
|
|
Packit |
0848f5 |
print STDERR" $key -> $val\n";
|
|
Packit |
0848f5 |
print STDERR "also to $key -> $valForKey\n";
|
|
Packit |
0848f5 |
print STDERR "seen in $allKeysLoc{$key} .\n";
|
|
Packit |
0848f5 |
print STDERR "Using $key -> $val\n";
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
$allKeys{$key} = $val;
|
|
Packit |
0848f5 |
$allKeysLoc{$key} = $allInfo{$origKey};
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
#
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
# # FIXME: Who uses this now
|
|
Packit |
0848f5 |
# # This roughly reproduces the describe_states file
|
|
Packit |
0848f5 |
# open DS, ">src/describe_states.txt" || die "Cannot open src/describe_states.txt";
|
|
Packit |
0848f5 |
# foreach my $key (sort(keys(%allInfo))) {
|
|
Packit |
0848f5 |
# $key =~ s/\r?\n//;
|
|
Packit |
0848f5 |
# my $funcname = "";
|
|
Packit |
0848f5 |
# if ($key =~ /(\S+)\s+(\S+)/) {
|
|
Packit |
0848f5 |
# $key = $1;
|
|
Packit |
0848f5 |
# $funcname = $2;
|
|
Packit |
0848f5 |
# }
|
|
Packit |
0848f5 |
# else {
|
|
Packit |
0848f5 |
# $funcname = $key;
|
|
Packit |
0848f5 |
# if ($key =~ /^(MPID[A-Z]*_STATE_)+(MPI[A-Z]*)_(\w)(\S+)/) {
|
|
Packit |
0848f5 |
# $funcname = "$2_$3" . lc($4);
|
|
Packit |
0848f5 |
# }
|
|
Packit |
0848f5 |
# }
|
|
Packit |
0848f5 |
# print DS "$key $funcname\n";
|
|
Packit |
0848f5 |
# }
|
|
Packit |
0848f5 |
# close DS;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
open DH, ">src/include/mpiallstates.h" || die "Cannot open src/include/mpiallstates.h";
|
|
Packit |
0848f5 |
print DH "/* -*- Mode: C; c-basic-offset:4 ; -*- */
|
|
Packit |
0848f5 |
/*
|
|
Packit |
0848f5 |
* (C) 2005 by Argonne National Laboratory.
|
|
Packit |
0848f5 |
* See COPYRIGHT in top-level directory.
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* DO NOT EDIT: AUTOMATICALLY GENERATED BY extractstates */
|
|
Packit |
0848f5 |
#ifndef MPIALLSTATES_H_INCLUDED
|
|
Packit |
0848f5 |
#define MPIALLSTATES_H_INCLUDED\n";
|
|
Packit |
0848f5 |
# print the enum of states
|
|
Packit |
0848f5 |
print DH "\nenum MPID_TIMER_STATE {\n";
|
|
Packit |
0848f5 |
foreach my $key (sort(keys(%allKeys))) {
|
|
Packit |
0848f5 |
print DH "\t$key,\n";
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
print DH "\tMPID_NUM_TIMER_STATES };\n";
|
|
Packit |
0848f5 |
print DH "#endif\n";
|
|
Packit |
0848f5 |
close DH;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
# Create the description of the states
|
|
Packit |
0848f5 |
# This roughly reproduces the describe_states.c file
|
|
Packit |
0848f5 |
open DC, ">src/util/logging/common/state_names.h" ||
|
|
Packit |
0848f5 |
die "Cannot open new state_names.h file";
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
# Print header
|
|
Packit |
0848f5 |
# Note that we include only mpiallstates.h . It is important not to
|
|
Packit |
0848f5 |
# include mpiimpl.h, since this file may be used in code that wants to
|
|
Packit |
0848f5 |
# be well modularized and not be entangled with the general MPICH
|
|
Packit |
0848f5 |
# implementation header.
|
|
Packit |
0848f5 |
print DC "/* -*- Mode: C; c-basic-offset:4 ; -*- */
|
|
Packit |
0848f5 |
/*
|
|
Packit |
0848f5 |
* (C) 2005 by Argonne National Laboratory.
|
|
Packit |
0848f5 |
* See COPYRIGHT in top-level directory.
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
/* DO NOT EDIT: AUTOMATICALLY GENERATED BY extractstates */
|
|
Packit |
0848f5 |
#ifndef STATE_NAMES_H_INCLUDED
|
|
Packit |
0848f5 |
#define STATE_NAMES_H_INCLUDED
|
|
Packit |
0848f5 |
#include \"mpiallstates.h\"
|
|
Packit |
0848f5 |
/* STATES:SKIP */\n";
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
# Change in definition:
|
|
Packit |
0848f5 |
# We simply build an array of names and colors; the routine
|
|
Packit |
0848f5 |
# that is called will generate a color if none is provided.
|
|
Packit |
0848f5 |
print DC "typedef struct {
|
|
Packit |
0848f5 |
int state; const char *funcname; const char *color; } MPIU_State_defs;
|
|
Packit |
0848f5 |
static MPIU_State_defs mpich_states[] = {\n";
|
|
Packit |
0848f5 |
foreach my $key (sort(keys(%allInfo))) {
|
|
Packit |
0848f5 |
$key =~ s/\r?\n//;
|
|
Packit |
0848f5 |
my $funcname = "";
|
|
Packit |
0848f5 |
my $color = "";
|
|
Packit |
0848f5 |
if ($key =~ /(\S+)\s+(\S+)\s+(\S.*\S+)\s*/) {
|
|
Packit |
0848f5 |
# This allows colors to be either a name or a tuple
|
|
Packit |
0848f5 |
$key = $1;
|
|
Packit |
0848f5 |
$funcname = $2;
|
|
Packit |
0848f5 |
$color = $3;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
elsif ($key =~ /(\S+)\s+(\S+)/) {
|
|
Packit |
0848f5 |
$key = $1;
|
|
Packit |
0848f5 |
$funcname = $2;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else {
|
|
Packit |
0848f5 |
$funcname = $key;
|
|
Packit |
0848f5 |
if ($key =~ /^(MPID[A-Z]*_STATE_)+(MPI[A-Z]*)_(\w)(\S+)/) {
|
|
Packit |
0848f5 |
$funcname = "$2_$3" . lc($4);
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
# Turn color into a quoted string or null
|
|
Packit |
0848f5 |
if ($color ne "") {
|
|
Packit |
0848f5 |
$color = "\"$color\"";
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else {
|
|
Packit |
0848f5 |
$color = "(const char *)0";
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
print DC " { $key, \"$funcname\", $color },\n";
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
print DC " { -1, (const char *)0, (const char *)0 } };\n";
|
|
Packit |
0848f5 |
print DC "#endif\n";
|
|
Packit |
0848f5 |
close DC;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
# --------------------
|
|
Packit |
0848f5 |
# Read a file and find the state definitions
|
|
Packit |
0848f5 |
# This routine is invoked by the "ProcessFile" script in extractstates,
|
|
Packit |
0848f5 |
# which in turn is invoked by ProcessDir. It returns a string
|
|
Packit |
0848f5 |
# of newline-separated items which are simply the items that need to be
|
|
Packit |
0848f5 |
# added to the cache file for a given directory, for this particular file.
|
|
Packit |
0848f5 |
sub findStateDecl {
|
|
Packit |
0848f5 |
my $file = $_[0];
|
|
Packit |
0848f5 |
my $info = ""; # newline separate list of states in a file
|
|
Packit |
0848f5 |
my $linenum = 0; # Keep track of location in file
|
|
Packit |
0848f5 |
my $curfuncname = "";
|
|
Packit |
0848f5 |
my $lastFuncname = ""; # Last funcname and state are used to help with
|
|
Packit |
0848f5 |
my $lastState = ""; # routines that have multiple declaration
|
|
Packit |
0848f5 |
# blocks protected by ifdefs (to avoid false
|
|
Packit |
0848f5 |
# warnings about missing FUNCNAME definitions).
|
|
Packit |
0848f5 |
my %knownLines = (); # Hash used to detect duplicate lines
|
|
Packit |
0848f5 |
my %knownStates = (); # Hash used to detect known states, to avoid
|
|
Packit |
0848f5 |
# adding additional lines of the for "state"
|
|
Packit |
0848f5 |
# where "state name" has been already added
|
|
Packit |
0848f5 |
# (this can happen in places where there are
|
|
Packit |
0848f5 |
# multiple STATE_DECLS for a single FUNCNAME,
|
|
Packit |
0848f5 |
# which is discouraged but allowed.
|
|
Packit |
0848f5 |
my $inDecls = 0; # Keep track of whether we're still seeing
|
|
Packit |
0848f5 |
# state declarations or not.
|
|
Packit |
0848f5 |
my $inComment = 0;
|
|
Packit |
0848f5 |
my $showWarnings = 1; # Allow files to turn off warnings
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
open FD, "<$file" || die "Cannot open $file\n";
|
|
Packit |
0848f5 |
while (<FD>) {
|
|
Packit |
0848f5 |
$linenum++;
|
|
Packit |
0848f5 |
# This allows us to skip files that are, for example, generated
|
|
Packit |
0848f5 |
# from the states information (e.g., the describe_states.h file)
|
|
Packit |
0848f5 |
if (/\/\*\s+STATES:SKIP\s+\*\//) {
|
|
Packit |
0848f5 |
last;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
if (/\/\*\s+STATES:NO WARNINGS\s+\*\//) {
|
|
Packit |
0848f5 |
$showWarnings = 0;
|
|
Packit |
0848f5 |
next;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
# Skip commented out definitions. The complexity here handles
|
|
Packit |
0848f5 |
# multi-line comments
|
|
Packit |
0848f5 |
if ($inComment) {
|
|
Packit |
0848f5 |
if (/.*\*\/(.*)/) {
|
|
Packit |
0848f5 |
$_ = 1;
|
|
Packit |
0848f5 |
$inComment = 0;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else {
|
|
Packit |
0848f5 |
$_ = "";
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else {
|
|
Packit |
0848f5 |
$processed = "";
|
|
Packit |
0848f5 |
while (/(.*)\/\*(.*)/) {
|
|
Packit |
0848f5 |
$processed .= $1;
|
|
Packit |
0848f5 |
$_ = $2;
|
|
Packit |
0848f5 |
if (/.*\*\/(.*)/) {
|
|
Packit |
0848f5 |
$inComment = 0;
|
|
Packit |
0848f5 |
$_ = $1;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else {
|
|
Packit |
0848f5 |
$inComment = 1;
|
|
Packit |
0848f5 |
$_ = "";
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
$_ = $processed . $_;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
if (/^\#\s*define\s+FUNCNAME\s+(\S*)/) {
|
|
Packit |
0848f5 |
$curfuncname = $1;
|
|
Packit |
0848f5 |
$lastState = "";
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
elsif (/STATE_DECL\((.*)\)/ && !/^\#\s*define\s/) {
|
|
Packit |
0848f5 |
my $state = $1;
|
|
Packit |
0848f5 |
my $candidateLine = "";
|
|
Packit |
0848f5 |
$state =~ s/\s+//g; # Remove blanks
|
|
Packit |
0848f5 |
$candidateLine .= $state;
|
|
Packit |
0848f5 |
# Check for special cases (mostly system calls embedded within
|
|
Packit |
0848f5 |
# other routines that are not implemented by MPICH.
|
|
Packit |
0848f5 |
# In the long run, these should use a different macro instead
|
|
Packit |
0848f5 |
# of MPIxxx_STATE_DECL
|
|
Packit |
0848f5 |
if (!$inDecls) { $lastState = ""; }
|
|
Packit |
0848f5 |
$inDecls = 1;
|
|
Packit |
0848f5 |
if (defined($exceptionState{$state})) {
|
|
Packit |
0848f5 |
$candidateLine .= " " . $exceptionState{$state};
|
|
Packit |
0848f5 |
$lastState .= ":$state:";
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else {
|
|
Packit |
0848f5 |
# Check for (a) this state is known, (b) that state
|
|
Packit |
0848f5 |
# has an associated name, and (c) curfuncname is null
|
|
Packit |
0848f5 |
if (defined($knownStates{$state}) &&
|
|
Packit |
0848f5 |
$knownStates{$state} ne "" && $curfuncname eq "") {
|
|
Packit |
0848f5 |
print "Skipping state definition $state because already set to $knownStates{$state}\n" if $gVerbose;
|
|
Packit |
0848f5 |
# Skip this state
|
|
Packit |
0848f5 |
next;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
# Reload curfuncname if this is the same state as the last
|
|
Packit |
0848f5 |
# state
|
|
Packit |
0848f5 |
if ($curfuncname eq "" && $lastState eq ":$state:") {
|
|
Packit |
0848f5 |
$curfuncname = $lastFuncname;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
if ($curfuncname ne "") {
|
|
Packit |
0848f5 |
$candidateLine .= " $curfuncname";
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else {
|
|
Packit |
0848f5 |
print STDERR "Warning: no FUNCNAME defined for $state in $file\n" if $showWarnings;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
$lastState .= ":$state:";
|
|
Packit |
0848f5 |
if ($curfuncname ne "") {
|
|
Packit |
0848f5 |
$lastFuncname = $curfuncname;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
# Save this state and the associated function name
|
|
Packit |
0848f5 |
if (!defined($knownStates{$state})) {
|
|
Packit |
0848f5 |
$knownStates{$state} = $curfuncname;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
# Once we see the declaration of the state, set the
|
|
Packit |
0848f5 |
# state name to empty. The source code must be organized
|
|
Packit |
0848f5 |
# so that the state declarations only appear once LEXICALLY
|
|
Packit |
0848f5 |
# in the code.
|
|
Packit |
0848f5 |
if (! $showWarnings) {
|
|
Packit |
0848f5 |
$curfuncname = "";
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
if (!defined($knownLines{$candidateLine})) {
|
|
Packit |
0848f5 |
$info .= $candidateLine . "\n";
|
|
Packit |
0848f5 |
$knownLines{$candidateLine} = $linenum;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
elsif (/FUNC_ENTER\((.*)\)/ && !/^\#\s*define\s/) {
|
|
Packit |
0848f5 |
# Match with current state
|
|
Packit |
0848f5 |
my $state = $1;
|
|
Packit |
0848f5 |
$inDecls = 0;
|
|
Packit |
0848f5 |
if (! ($lastState =~ /:$state:/) &&
|
|
Packit |
0848f5 |
! defined($exceptionState{$state}) ) {
|
|
Packit |
0848f5 |
print STDERR "Warning: State in FUNC_ENTER($state) does not match STATE_DECL($lastState) in $file\n" if $showWarnings;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
elsif (/FUNC_EXIT\((.*)\)/ && !/^\#\s*define\s/) {
|
|
Packit |
0848f5 |
# Match with current state
|
|
Packit |
0848f5 |
my $state = $1;
|
|
Packit |
0848f5 |
$inDecls = 0;
|
|
Packit |
0848f5 |
if (! ($lastState =~ /:$state:/) &&
|
|
Packit |
0848f5 |
! defined($exceptionState{$state})) {
|
|
Packit |
0848f5 |
print STDERR "Warning: State in FUNC_EXIT($state) does not match STATE_DECL($lastState) in $file\n" if $showWarnings;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
# else {
|
|
Packit |
0848f5 |
# # Remove this state from the defined states
|
|
Packit |
0848f5 |
# $lastState =~ s/:$state://;
|
|
Packit |
0848f5 |
# }
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
close FD;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
return $info;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
# Read the cache file and add the information to the hash allInfo
|
|
Packit |
0848f5 |
# The key for allInfo is the specification line, the value is the location
|
|
Packit |
0848f5 |
# of the cache file where the value was found.
|
|
Packit |
0848f5 |
# For entries from the exceptions file, the value is the location of the
|
|
Packit |
0848f5 |
# exceptions file.
|
|
Packit |
0848f5 |
sub catState {
|
|
Packit |
0848f5 |
my ($dir,$cachefile) = @_;
|
|
Packit |
0848f5 |
if (-s "$dir/$cachefile") {
|
|
Packit |
0848f5 |
my %f = &ReadCacheContents( $dir, $cachefile );
|
|
Packit |
0848f5 |
foreach my $key (keys(%f)) {
|
|
Packit |
0848f5 |
foreach my $value (split/\n/,$f{$key}) {
|
|
Packit |
0848f5 |
$allInfo{$value} = "$dir/$cachefile";
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
if (-s "$dir/$exceptionsFile") {
|
|
Packit |
0848f5 |
print "Reading $dir/$exceptionsFile\n" if $gVerbose;
|
|
Packit |
0848f5 |
open CFD, "<$dir/$exceptionsFile" ||
|
|
Packit |
0848f5 |
die "Could not open $dir/$exceptionsFile";
|
|
Packit |
0848f5 |
while (<CFD>) {
|
|
Packit |
0848f5 |
s/#.*//;
|
|
Packit |
0848f5 |
if (/^(\S+)\s+(\S+)\s*(.*)/) {
|
|
Packit |
0848f5 |
# Found a conforming line.
|
|
Packit |
0848f5 |
my $key = $1;
|
|
Packit |
0848f5 |
my $name = $2;
|
|
Packit |
0848f5 |
my $color = $3;
|
|
Packit |
0848f5 |
my $defaultKey = $1 . " " . $2;
|
|
Packit |
0848f5 |
if (defined($allInfo{$defaultKey}) && $color ne "") {
|
|
Packit |
0848f5 |
# Replace this entry
|
|
Packit |
0848f5 |
delete $allInfo{$defaultKey};
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
$allInfo{$_} = "$dir/$exceptionsFile";
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
close CFD;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
# --------------------------------------------------------------------------
|
|
Packit |
0848f5 |
# Make sure that there are no inconsistencies in the list by
|
|
Packit |
0848f5 |
# ensuring that all keys have the same descriptions. Also
|
|
Packit |
0848f5 |
# synthesize the function names here
|
|
Packit |
0848f5 |
# Keys in allInfo are of the form "state [optional func]"
|
|
Packit |
0848f5 |
# The value is the cache file in which the key was defined.
|
|
Packit |
0848f5 |
# stateNames is used to keep track of all states, so that if the
|
|
Packit |
0848f5 |
# same state is defined in multiple cache files, but with different
|
|
Packit |
0848f5 |
# values, we can detect the inconsistency.
|
|
Packit |
0848f5 |
sub CheckAllInfo {
|
|
Packit |
0848f5 |
my %stateNames = ();
|
|
Packit |
0848f5 |
my %stateLoc = ();
|
|
Packit |
0848f5 |
foreach my $key (sort(keys(%allInfo))) {
|
|
Packit |
0848f5 |
my $val = "";
|
|
Packit |
0848f5 |
my $color = "";
|
|
Packit |
0848f5 |
my $origkey = $key;
|
|
Packit |
0848f5 |
my $origval = "";
|
|
Packit |
0848f5 |
if ($key =~ /(\S+)\s+(.+)/) {
|
|
Packit |
0848f5 |
$key = $1;
|
|
Packit |
0848f5 |
$val = $2;
|
|
Packit |
0848f5 |
$origval = $val;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
elsif ($key =~ /\s/) {
|
|
Packit |
0848f5 |
print STDERR "Key :$key: contains a blank, found in $allInfo{$origkey}\n";
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
# If there is no value (no function name to go with the state,
|
|
Packit |
0848f5 |
# synthesize one
|
|
Packit |
0848f5 |
if ($val eq "") {
|
|
Packit |
0848f5 |
$val = $key;
|
|
Packit |
0848f5 |
if ($val =~ /^(MPID[A-Z]*_STATE_)+(MPI[A-Z]*)_(\w)(\S+)/) {
|
|
Packit |
0848f5 |
$val = "$2_$3" . lc($4);
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
print "Setting value for state $key to $val for entry found in $allInfo{$origkey}\n" if $gVerbose;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
if (defined($stateNames{$key})) {
|
|
Packit |
0848f5 |
if ($stateNames{$key} ne $val) {
|
|
Packit |
0848f5 |
# There are two possibilities:
|
|
Packit |
0848f5 |
# One of the values is cached and the other is an exception
|
|
Packit |
0848f5 |
# value, in which case we reject the cached value
|
|
Packit |
0848f5 |
# The other possiblity is a conflict, which we report.
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
print STDERR "\nInconsistent value for state of $key:\n";
|
|
Packit |
0848f5 |
print STDERR "Old : $stateNames{$key} in $stateLoc{$key}\n";
|
|
Packit |
0848f5 |
print STDERR "New : $val in $allInfo{$origkey}\n";
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else {
|
|
Packit |
0848f5 |
$stateNames{$key} = $val;
|
|
Packit |
0848f5 |
$stateLoc{$key} = $allInfo{$origkey};
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|