-:    0:Source:/home/MPI/testing/mpich2/mpich2/src/mpi/errhan/errutil.c
        -:    0:Graph:errutil.gcno
        -:    0:Data:errutil.gcda
        -:    0:Runs:4383
        -:    0:Programs:1376
        -:    1:/* -*- Mode: C; c-basic-offset:4 ; -*- */
        -:    2:/*
        -:    3: *
        -:    4: *  (C) 2001 by Argonne National Laboratory.
        -:    5: *      See COPYRIGHT in top-level directory.
        -:    6: */
        -:    7:
        -:    8:/* style: allow:fprintf:4 sig:0 */
        -:    9:
        -:   10:/* stdarg is required to handle the variable argument lists for 
        -:   11:   MPIR_Err_create_code */
        -:   12:#include <stdarg.h>
        -:   13:/* Define USE_ERR_CODE_VALIST to get the prototype for the valist version
        -:   14:   of MPIR_Err_create_code in mpierror.h (without this definition,
        -:   15:   the prototype is not included.  The "valist" version of the function
        -:   16:   is used in only a few places, here and potentially in ROMIO) */
        -:   17:#define USE_ERR_CODE_VALIST
        -:   18:
        -:   19:#include "mpiimpl.h"
        -:   20:/* errcodes.h contains the macros used to access fields within an error
        -:   21:   code and a description of the bits in an error code.  A brief
        -:   22:   version of that description is included below */
        -:   23:
        -:   24:#include "errcodes.h"
        -:   25:
        -:   26:/* defmsg is generated automatically from the source files and contains
        -:   27:   all of the error messages, both the generic and specific.  Depending 
        -:   28:   on the value of MPICH_ERROR_MSG_LEVEL, different amounts of message
        -:   29:   information will be included from the file defmsg.h */
        -:   30:#include "defmsg.h" 
        -:   31:
        -:   32:/* stdio is needed for vsprintf and vsnprintf */
        -:   33:#include <stdio.h>
        -:   34:
        -:   35:/* TEMP TO KEEP COMPILER HAPPY */
        -:   36:void MPIR_Err_print_stack_string_ext(int errcode, char *str, int maxlen, 
        -:   37:				     MPIR_Err_get_class_string_func_t fn);
        -:   38:
        -:   39:/*
        -:   40: * Structure of this file
        -:   41: *
        -:   42: * This file contains several groups of routines user for error handling
        -:   43: * and reporting.  
        -:   44: *
        -:   45: * The first group provides memory for the MPID_Errhandler objects 
        -:   46: * and the routines to free and manipulate them
        -:   47: *
        -:   48: * MPIR_Err_return_xxx - For each of the MPI types on which an 
        -:   49: * error handler can be defined, there is an MPIR_Err_return_xxx routine
        -:   50: * that determines what error handler function to call and whether to 
        -:   51: * abort the program.  The comm and win versions are here; ROMIO
        -:   52: * provides its own routines for invoking the error handlers for Files.
        -:   53: *
        -:   54: * The next group of code handles the error messages.  There are three
        -:   55: * options, controlled by the value of MPICH_ERROR_MSG_LEVEL. 
        -:   56: *
        -:   57: * MPICH_ERROR_MSG_NONE - No text messages at all
        -:   58: * MPICH_ERROR_MSG_CLASS - Only messages for the MPI error classes
        -:   59: * MPICH_ERROR_MSG_GENERIC - Only predefiend messages for the MPI error codes
        -:   60: * MPICH_ERROR_MSG_ALL - Instance specific error messages (and error message
        -:   61: *                       stack)
        -:   62: *
        -:   63: * In only the latter (MPICH_ERROR_MSG_ALL) case are instance-specific
        -:   64: * messages maintained (including the error message "stack" that you may
        -:   65: * see mentioned in various places.  In the other cases, an error code 
        -:   66: * identifies a fixed message string (unless MPICH_ERROR_MSG_NONE,
        -:   67: * when there are no strings) from the "generic" strings defined in defmsg.h
        -:   68: *
        -:   69: * A major subgroup in this section is the code to handle the instance-specific
        -:   70: * messages (MPICH_ERROR_MSG_ALL only).  
        -:   71: *
        -:   72: * An MPI error code is made up of a number of fields (see errcodes.h)
        -:   73: * These ar 
        -:   74: *   is-dynamic? specific-msg-sequence# specific-msg-index 
        -:   75: *                                            generic-code is-fatal? class
        -:   76: *
        -:   77: * There are macros (defined in errcodes.h) that define these fields, 
        -:   78: * their sizes, and masks and shifts that may be used to extract them.
        -:   79: */
        -:   80:
        -:   81:/* A few prototypes.  These routines are called from the MPIR_Err_return 
        -:   82:   routines.  checkValidErrcode depends on the MPICH_ERROR_MSG_LEVEL */
        -:   83:
        -:   84:static int checkValidErrcode( int error_class, const char fcname[], 
        -:   85:			      int *errcode );
        -:   86:static void handleFatalError( MPID_Comm *comm_ptr, 
        -:   87:			      const char fcname[], int errcode );
        -:   88:
        -:   89:#if MPICH_ERROR_MSG_LEVEL >= MPICH_ERROR_MSG_ALL
        -:   90:static int ErrGetInstanceString( int errorcode, char *msg, int num_remaining, 
        -:   91:				 MPIR_Err_get_class_string_func_t fn );
        -:   92:static void MPIR_Err_stack_init( void );
        -:   93:static int checkForUserErrcode( int errcode );
        -:   94:#else
        -:   95:/* We only need special handling for user error codes when we support the
        -:   96:   error message stack */
        -:   97:#define checkForUserErrcode(_a) _a
        -:   98:#endif
        -:   99:
        -:  100:
        -:  101:/* ------------------------------------------------------------------------- */
        -:  102:/* Provide the MPID_Errhandler space and the routines to free and set them
        -:  103:   from C++  */
        -:  104:/* ------------------------------------------------------------------------- */
        -:  105:/*
        -:  106: * Error handlers.  These are handled just like the other opaque objects
        -:  107: * in MPICH
        -:  108: */
        -:  109:
        -:  110:#ifndef MPID_ERRHANDLER_PREALLOC 
        -:  111:#define MPID_ERRHANDLER_PREALLOC 8
        -:  112:#endif
        -:  113:
        -:  114:/* Preallocated errorhandler objects */
        -:  115:MPID_Errhandler MPID_Errhandler_builtin[3] = {
        -:  116:        { MPIU_OBJECT_HEADER_INITIALIZER(MPI_ERRORS_ARE_FATAL, 0), },
        -:  117:        { MPIU_OBJECT_HEADER_INITIALIZER(MPI_ERRORS_RETURN, 0), },
        -:  118:        { MPIU_OBJECT_HEADER_INITIALIZER(MPIR_ERRORS_THROW_EXCEPTIONS, 0) },
        -:  119:    };
        -:  120:MPID_Errhandler MPID_Errhandler_direct[MPID_ERRHANDLER_PREALLOC] = { { MPIU_OBJECT_HEADER_INITIALIZER(0,0) } };
        -:  121:MPIU_Object_alloc_t MPID_Errhandler_mem = { 0, 0, 0, 0, MPID_ERRHANDLER, 
        -:  122:					    sizeof(MPID_Errhandler), 
        -:  123:					    MPID_Errhandler_direct,
        -:  124:					    MPID_ERRHANDLER_PREALLOC, };
        -:  125:
        -:  126:void MPID_Errhandler_free(MPID_Errhandler *errhan_ptr)
       10:  127:{
       10:  128:    MPIU_Handle_obj_free(&MPID_Errhandler_mem, errhan_ptr);
       10:  129:}
        -:  130:
        -:  131:#ifdef HAVE_CXX_BINDING
        -:  132:/* This routine is used to install a callback used by the C++ binding
        -:  133: to invoke the (C++) error handler.  The callback routine is a C routine,
        -:  134: defined in the C++ binding. */
        -:  135:void MPIR_Errhandler_set_cxx( MPI_Errhandler errhand, void (*errcall)(void) )
        6:  136:{
        -:  137:    MPID_Errhandler *errhand_ptr;
        -:  138:    
        6:  139:    MPID_Errhandler_get_ptr( errhand, errhand_ptr );
        6:  140:    errhand_ptr->language		= MPID_LANG_CXX;
        6:  141:    MPIR_Process.cxx_call_errfn	= (void (*)( int, int *, int *, 
        -:  142:					    void (*)(void) ))errcall;
        6:  143:}
        -:  144:#endif
        -:  145:
        -:  146:/* ------------------------------------------------------------------------- */
        -:  147:/* 
        -:  148:   Nesting level for routines.
        -:  149:   Note that since these use per-thread data, no locks or atomic update
        -:  150:   routines are required.
        -:  151:
        -:  152:   In a single-threaded environment, these are replaced with
        -:  153:   MPIR_Thread.nest_count ++, --.  These are defined in the mpiimpl.h file.
        -:  154: */
        -:  155:/* ------------------------------------------------------------------------- */
        -:  156:
        -:  157:/* These routines export the nest increment and decrement for use in ROMIO */
        -:  158:void MPIR_Nest_incr_export( void )
  3379773:  159:{
  3379773:  160:    MPIU_THREADPRIV_DECL;
  3379773:  161:    MPIU_THREADPRIV_GET;
  3379773:  162:    MPIU_THREADPRIV_FIELD(nest_count) = MPIU_THREADPRIV_FIELD(nest_count) + 1;
  3379773:  163:}
        -:  164:void MPIR_Nest_decr_export( void )
  3379773:  165:{
  3379773:  166:    MPIU_THREADPRIV_DECL;
  3379773:  167:    MPIU_THREADPRIV_GET;
  3379773:  168:    MPIU_THREADPRIV_FIELD(nest_count) = MPIU_THREADPRIV_FIELD(nest_count) - 1;
  3379773:  169:}
        -:  170:#ifdef MPICH_DEBUG_NESTING
        -:  171:void MPIR_Nest_incr_export_dbg( const char *srcfile, int srcline )
        -:  172:{
        -:  173:    MPIU_THREADPRIV_DECL;
        -:  174:    MPIU_THREADPRIV_GET;
        -:  175:
        -:  176:    if (MPIU_THREADPRIV_FIELD(nest_count) >= MPICH_MAX_NESTINFO) { 
        -:  177:	MPIU_Internal_error_printf("nest stack exceeded at %s:%d\n",
        -:  178:				   srcfile, srcline );
        -:  179:    }
        -:  180:    else {
        -:  181:	MPIU_Strncpy(MPIU_THREADPRIV_FIELD(nestinfo)[MPIU_THREADPRIV_FIELD(nest_count)].file,srcfile, MPICH_MAX_NESTFILENAME);
        -:  182:	MPIU_THREADPRIV_FIELD(nestinfo)[MPIU_THREADPRIV_FIELD(nest_count)].line=srcline;
        -:  183:    }
        -:  184:     MPIU_THREADPRIV_FIELD(nest_count)++; 
        -:  185:}
        -:  186:void MPIR_Nest_decr_export_dbg( const char *srcfile, int srcline )
        -:  187:{
        -:  188:    MPIU_THREADPRIV_DECL;
        -:  189:    MPIU_THREADPRIV_GET;
        -:  190:
        -:  191:    if (MPIU_THREADPRIV_FIELD(nest_count) >= 0) {
        -:  192:	MPIU_THREADPRIV_FIELD(nestinfo)[MPIU_THREADPRIV_FIELD(nest_count)].line=-srcline;}
        -:  193:     MPIU_THREADPRIV_FIELD(nest_count)--;
        -:  194:     if (MPIU_THREADPRIV_FIELD(nest_count) < MPICH_MAX_NESTINFO && 
        -:  195:	 strcmp(MPIU_THREADPRIV_FIELD(nestinfo)[MPIU_THREADPRIV_FIELD(nest_count)].file,srcfile) != 0) {
        -:  196:         MPIU_Msg_printf( "Decremented nest count in file %s:%d but incremented in different file (%s:%d)\n", 
        -:  197:                          srcfile, srcline,
        -:  198:                          MPIU_THREADPRIV_FIELD(nestinfo)[MPIU_THREADPRIV_FIELD(nest_count)].file, \
        -:  199:                          MPIU_THREADPRIV_FIELD(nestinfo)[MPIU_THREADPRIV_FIELD(nest_count)].line);\
        -:  200:     }
        -:  201:     else if (MPIU_THREADPRIV_FIELD(nest_count) < 0) {
        -:  202:	 MPIU_Msg_printf("Decremented nest count in file %s:%d is negative\n", 
        -:  203:			 srcfile,srcline);
        -:  204:     }
        -:  205:}
        -:  206:#endif
        -:  207:/* ------------------------------------------------------------------------- */
        -:  208:/* These routines are called on error exit from most top-level MPI routines
        -:  209:   to invoke the appropriate error handler.  Also included is the routine
        -:  210:   to call if MPI has not been initialized (MPIR_Err_preinit) and to 
        -:  211:   determine if an error code represents a fatal error (MPIR_Err_is_fatal). */
        -:  212:/* ------------------------------------------------------------------------- */
        -:  213:/* Special error handler to call if we are not yet initialized, or if we
        -:  214:   have finalized */
        -:  215:void MPIR_Err_preOrPostInit( void )
        2:  216:{
        2:  217:    if (MPIR_Process.initialized == MPICH_PRE_INIT) {
    #####:  218:	MPIU_Error_printf("Attempting to use an MPI routine before initializing MPICH\n");
        -:  219:    }
        2:  220:    else if (MPIR_Process.initialized == MPICH_POST_FINALIZED) {
        2:  221:	MPIU_Error_printf("Attempting to use an MPI routine after finalizing MPICH\n");
        -:  222:    }
        -:  223:    else {
    #####:  224:	MPIU_Error_printf("Internal Error: Unknown state of MPI (neither initialized nor finalized)\n" );
        -:  225:    }
        2:  226:    exit(1);
        -:  227:}
        -:  228:
        -:  229:/* Return true if the error code indicates a fatal error */
        -:  230:int MPIR_Err_is_fatal(int errcode)
 16328608:  231:{
 16328608:  232:    return (errcode & ERROR_FATAL_MASK) ? TRUE : FALSE;
        -:  233:}
        -:  234:
        -:  235:/*
        -:  236: * This is the routine that is invoked by most MPI routines to 
        -:  237: * report an error.  It is legitimate to pass NULL for comm_ptr in order to get
        -:  238: * the default (MPI_COMM_WORLD) error handling.
        -:  239: */
        -:  240:int MPIR_Err_return_comm( MPID_Comm  *comm_ptr, const char fcname[], 
        -:  241:			  int errcode )
     6951:  242:{
     6951:  243:    const int error_class = ERROR_GET_CLASS(errcode);
        -:  244:    int rc;
     6951:  245:    MPIU_THREADPRIV_DECL;
        -:  246:
     6951:  247:    MPIU_THREADPRIV_GET; 
        -:  248:
     6951:  249:    rc = checkValidErrcode( error_class, fcname, &errcode );
        -:  250:    
        -:  251:    /* First, check the nesting level */
     6951:  252:    if (MPIR_Nest_value()) return errcode;
        -:  253:
        -:  254:    MPIU_DBG_MSG_FMT(ERRHAND, TERSE, (MPIU_DBG_FDEST, "MPIR_Err_return_comm(comm_ptr=%p, fcname=%s, errcode=%d)", comm_ptr, fcname, errcode));
        -:  255:
     6937:  256:    if (!comm_ptr || comm_ptr->errhandler == NULL) {
        -:  257:	/* Try to replace with the default handler, which is the one on 
        -:  258:	   MPI_COMM_WORLD.  This gives us correct behavior for the
        -:  259:	   case where the error handler on MPI_COMM_WORLD has been changed. */
      373:  260:	if (MPIR_Process.comm_world)
        -:  261:	{
      373:  262:	    comm_ptr = MPIR_Process.comm_world;
        -:  263:	}
        -:  264:    }
        -:  265:
     6937:  266:    if (MPIR_Err_is_fatal(errcode) ||
        -:  267:	comm_ptr == NULL || comm_ptr->errhandler == NULL || 
        -:  268:	comm_ptr->errhandler->handle == MPI_ERRORS_ARE_FATAL) {
        -:  269:	/* Calls MPID_Abort */
        5:  270:	handleFatalError( comm_ptr, fcname, errcode );
        -:  271:    }
        -:  272:
        -:  273:    /* Check for the special case of a user-provided error code */
     6932:  274:    errcode = checkForUserErrcode( errcode );
        -:  275:
     6932:  276:    if (comm_ptr->errhandler->handle == MPI_ERRORS_RETURN ||
        -:  277:	comm_ptr->errhandler->handle == MPIR_ERRORS_THROW_EXCEPTIONS)
        -:  278:    {
     6909:  279:	return errcode;
        -:  280:    }
        -:  281:    else
        -:  282:    {
        -:  283:	/* The user error handler may make calls to MPI routines, so the
        -:  284:	 * nesting counter must be incremented before the handler is called */
       23:  285:	MPIR_Nest_incr();
        -:  286:    
        -:  287:	/* We pass a final 0 (for a null pointer) to these routines
        -:  288:	   because MPICH-1 expected that */
       23:  289:	switch (comm_ptr->errhandler->language)
        -:  290:	{
        -:  291:	case MPID_LANG_C:
       22:  292:	    (*comm_ptr->errhandler->errfn.C_Comm_Handler_function)( 
        -:  293:		&comm_ptr->handle, &errcode, 0 );
       22:  294:	    break;
        -:  295:#ifdef HAVE_CXX_BINDING
        -:  296:	case MPID_LANG_CXX:
        1:  297:	    (*MPIR_Process.cxx_call_errfn)( 0, &comm_ptr->handle, &errcode, 
        -:  298:		    (void (*)(void))*comm_ptr->errhandler->errfn.C_Comm_Handler_function );
        -:  299:	    /* The C++ code throws an exception if the error handler 
        -:  300:	     returns something other than MPI_SUCCESS. There is no "return"
        -:  301:	     of an error code. */
        1:  302:	    errcode = MPI_SUCCESS;
        1:  303:	    break;
        -:  304:#endif
        -:  305:#ifdef HAVE_FORTRAN_BINDING
        -:  306:	case MPID_LANG_FORTRAN90:
        -:  307:	case MPID_LANG_FORTRAN:
    #####:  308:	    (*comm_ptr->errhandler->errfn.F77_Handler_function)( 
        -:  309:		(MPI_Fint *)&comm_ptr->handle, &errcode );
        -:  310:	    break;
        -:  311:#endif
        -:  312:	}
        -:  313:
       23:  314:	MPIR_Nest_decr();
        -:  315:    }
       23:  316:    return errcode;
        -:  317:}
        -:  318:
        -:  319:/* 
        -:  320: * MPI routines that detect errors on window objects use this to report errors
        -:  321: */
        -:  322:int MPIR_Err_return_win( MPID_Win  *win_ptr, const char fcname[], int errcode )
        8:  323:{
        8:  324:    const int error_class = ERROR_GET_CLASS(errcode);
        -:  325:    int rc ;
        8:  326:    MPIU_THREADPRIV_DECL;
        -:  327:
        8:  328:    MPIU_THREADPRIV_GET;
        -:  329:
        8:  330:    if (win_ptr == NULL || win_ptr->errhandler == NULL)
        2:  331:	return MPIR_Err_return_comm(NULL, fcname, errcode);
        -:  332:
        6:  333:    rc = checkValidErrcode( error_class, fcname, &errcode );
        -:  334:
        -:  335:    /* First, check the nesting level */
        6:  336:    if (MPIR_Nest_value()) return errcode;
        -:  337:
        -:  338:    MPIU_DBG_MSG_FMT(ERRHAND, TERSE, (MPIU_DBG_FDEST, "MPIR_Err_return_win(win_ptr=%p, fcname=%s, errcode=%d)", win_ptr, fcname, errcode));
        -:  339:
        6:  340:    if (MPIR_Err_is_fatal(errcode) ||
        -:  341:	win_ptr == NULL || win_ptr->errhandler == NULL || 
        -:  342:	win_ptr->errhandler->handle == MPI_ERRORS_ARE_FATAL) {
        -:  343:	/* Calls MPID_Abort */
    #####:  344:	handleFatalError( NULL, fcname, errcode );
        -:  345:    }
        -:  346:
        -:  347:    /* Check for the special case of a user-provided error code */
        6:  348:    errcode = checkForUserErrcode( errcode );
        -:  349:    
        6:  350:    if (win_ptr->errhandler->handle == MPI_ERRORS_RETURN ||
        -:  351:	win_ptr->errhandler->handle == MPIR_ERRORS_THROW_EXCEPTIONS)
        -:  352:    {
    #####:  353:	return errcode;
        -:  354:    }
        -:  355:    else
        -:  356:    {
        -:  357:	/* Now, invoke the error handler for the window */
        -:  358:
        -:  359:	/* The user error handler may make calls to MPI routines, so the
        -:  360:	 * nesting counter must be incremented before the handler is called */
        6:  361:	MPIR_Nest_incr();
        -:  362:    
        -:  363:	/* We pass a final 0 (for a null pointer) to these routines
        -:  364:	   because MPICH-1 expected that */
        6:  365:	switch (win_ptr->errhandler->language)
        -:  366:	{
        -:  367:	    case MPID_LANG_C:
        6:  368:		(*win_ptr->errhandler->errfn.C_Win_Handler_function)( 
        -:  369:		    &win_ptr->handle, &errcode, 0 );
        6:  370:		break;
        -:  371:#ifdef HAVE_CXX_BINDING
        -:  372:	    case MPID_LANG_CXX:
    #####:  373:	    (*MPIR_Process.cxx_call_errfn)( 2, &win_ptr->handle, &errcode, 
        -:  374:		    (void (*)(void))*win_ptr->errhandler->errfn.C_Win_Handler_function );
        -:  375:	    /* The C++ code throws an exception if the error handler 
        -:  376:	     returns something other than MPI_SUCCESS. There is no "return"
        -:  377:	     of an error code. */
    #####:  378:	    errcode = MPI_SUCCESS;
    #####:  379:	    break;
        -:  380:#endif
        -:  381:#ifdef HAVE_FORTRAN_BINDING
        -:  382:	    case MPID_LANG_FORTRAN90:
        -:  383:	    case MPID_LANG_FORTRAN:
    #####:  384:		(*win_ptr->errhandler->errfn.F77_Handler_function)( 
        -:  385:		    (MPI_Fint *)&win_ptr->handle, &errcode );
        -:  386:		break;
        -:  387:#endif
        -:  388:	}
        -:  389:
        6:  390:	MPIR_Nest_decr();
        -:  391:    }
        6:  392:    return errcode;
        -:  393:}
        -:  394:
        -:  395:
        -:  396:/* ------------------------------------------------------------------------- */
        -:  397:/* ------------------------------------------------------------------------- */
        -:  398:static int convertErrcodeToIndexes( int errcode, int *ring_idx, int *ring_id,
        -:  399:				    int *generic_idx );
        -:  400:static int checkErrcodeIsValid( int errcode );
        -:  401:static const char *ErrcodeInvalidReasonStr( int reason );
        -:  402:static const char *get_class_msg( int error_class );
        -:  403:
        -:  404:
        -:  405:void MPIR_Err_init( void )
     4383:  406:{
        -:  407:#   if MPICH_ERROR_MSG_LEVEL >= MPICH_ERROR_MSG_ALL
     4383:  408:    MPIR_Err_stack_init();
        -:  409:#   endif
     4383:  410:}
        -:  411:
        -:  412:
        -:  413:/* ------------------------------------------------------------------------- */
        -:  414:/* The following block of code manages the instance-specific error messages  */
        -:  415:/* ------------------------------------------------------------------------- */
        -:  416:
        -:  417: 
        -:  418:/* Check for a valid error code.  If the code is not valid, attempt to
        -:  419:   print out something sensible; reset the error code to have class 
        -:  420:   ERR_UNKNOWN */
        -:  421:/* FIXME: Now that error codes are chained, this does not produce a valid 
        -:  422:   error code since there is no valid ring index corresponding to this code */
        -:  423:static int checkValidErrcode( int error_class, const char fcname[], 
        -:  424:			      int *errcode_p )
     6957:  425:{
     6957:  426:    int errcode = *errcode_p;
     6957:  427:    int rc = 0;
        -:  428:
     6957:  429:    if (error_class > MPICH_ERR_LAST_CLASS)
        -:  430:    {
    #####:  431:	if (errcode & ~ERROR_CLASS_MASK)
        -:  432:	{
    #####:  433:	    MPIU_Error_printf("INTERNAL ERROR: Invalid error class (%d) encountered while returning from\n"
        -:  434:			      "%s.  Please file a bug report.\n", error_class, fcname);
        -:  435:	    /* Note that we don't try to print the error stack; if the 
        -:  436:	       error code is invalid, it can't be used to find
        -:  437:	       the error stack.  We could consider dumping the 
        -:  438:	       contents of the error ring instead (without trying
        -:  439:	       to interpret them) */
        -:  440:	}
        -:  441:	else
        -:  442:	{
    #####:  443:	    MPIU_Error_printf("INTERNAL ERROR: Invalid error class (%d) encountered while returning from\n"
        -:  444:			      "%s.  Please file a bug report.  No error stack is available.\n", error_class, fcname);
        -:  445:	}
        -:  446:	/* FIXME: We probably want to set this to MPI_ERR_UNKNOWN
        -:  447:	   and discard the rest of the bits */
    #####:  448:	errcode = (errcode & ~ERROR_CLASS_MASK) | MPI_ERR_UNKNOWN;
    #####:  449:	rc = 1;
        -:  450:    }
     6957:  451:    *errcode_p = errcode;
     6957:  452:    return rc;
        -:  453:}
        -:  454:
        -:  455:/* Check that an encoded error code is valid. Return 0 if valid, positive, 
        -:  456:   non-zero if invalid.  Value indicates reason; see 
        -:  457:   ErrcodeInvalidReasonStr() */
        -:  458:
        -:  459:#if MPICH_ERROR_MSG_LEVEL <= MPICH_ERROR_MSG_GENERIC
        -:  460:/* This is the shortened version when there are no error messages */
        -:  461:static int checkErrcodeIsValid( int errcode )
        -:  462:{
        -:  463:    /* MPICH_ERR_LAST_CLASS is the last of the *predefined* error classes. */
        -:  464:    /* FIXME: Should this check against dynamically-created error classes? */
        -:  465:    if (errcode < 0 || errcode >= MPICH_ERR_LAST_CLASS) {
        -:  466:	return 3;
        -:  467:    }
        -:  468:    return 0;
        -:  469:}
        -:  470:static const char *ErrcodeInvalidReasonStr( int reason )
        -:  471:{
        -:  472:    const char *str = 0;
        -:  473:
        -:  474:    /* FIXME: These strings need to be internationalized */
        -:  475:    switch (reason) {
        -:  476:    case 3:
        -:  477:	str = "Message class is out of range";
        -:  478:	break;
        -:  479:    default:
        -:  480:	str = "Unknown reason for invalid errcode";
        -:  481:	break;
        -:  482:    }
        -:  483:    return str;
        -:  484:}
        -:  485:#endif
        -:  486:
        -:  487:/* This routine is called when there is a fatal error */
        -:  488:static void handleFatalError( MPID_Comm *comm_ptr, 
        -:  489:			      const char fcname[], int errcode )
        5:  490:{
        -:  491:    /* Define length of the the maximum error message line (or string with 
        -:  492:       newlines?).  This definition is used only within this routine.  */
        -:  493:    /* FIXME: This should really be the same as MPI_MAX_ERROR_STRING, or in the
        -:  494:       worst case, defined in terms of that */
        -:  495:#define MAX_ERRMSG_STRING 4096
        -:  496:    char error_msg[ MAX_ERRMSG_STRING ];
        -:  497:    int len;
        -:  498:
        -:  499:    /* FIXME: Not internationalized */
        5:  500:    MPIU_Snprintf(error_msg, MAX_ERRMSG_STRING, "Fatal error in %s: ", fcname);
        5:  501:    len = (int)strlen(error_msg);
        5:  502:    MPIR_Err_get_string(errcode, &error_msg[len], MAX_ERRMSG_STRING-len, NULL);
        -:  503:    /* The third argument is a return code, a value of 1 usually indicates
        -:  504:       an error */
        5:  505:    MPID_Abort(comm_ptr, MPI_SUCCESS, 1, error_msg);
    #####:  506:}
        -:  507:
        -:  508:#if MPICH_ERROR_MSG_LEVEL >= MPICH_ERROR_MSG_GENERIC
        -:  509:/* 
        -:  510: * Given a message string abbreviation (e.g., one that starts "**"), return 
        -:  511: * the corresponding index.  For the generic (non
        -:  512: * parameterized messages), use idx = FindGenericMsgIndex( "**msg" );
        -:  513: */
        -:  514:static int FindGenericMsgIndex( const char *msg )
    10053:  515:{
        -:  516:    int i, c;
  2599886:  517:    for (i=0; i<generic_msgs_len; i++) {
        -:  518:	/* Check the sentinals to insure that the values are ok first */
  2599886:  519:	if (generic_err_msgs[i].sentinal1 != 0xacebad03 ||
        -:  520:	    generic_err_msgs[i].sentinal2 != 0xcb0bfa11) {
        -:  521:	    /* Something bad has happened! Don't risk trying the
        -:  522:	       short_name pointer; it may have been corrupted */
        -:  523:	    break;
        -:  524:	}
  2599886:  525:	c = strcmp( generic_err_msgs[i].short_name, msg );
  2599886:  526:	if (c == 0) return i;
  2589833:  527:	if (c > 0)
        -:  528:	{
        -:  529:	    /* don't return here if the string partially matches */
    #####:  530:	    if (strncmp(generic_err_msgs[i].short_name, msg, strlen(msg)) != 0)
    #####:  531:		return -1;
        -:  532:	}
        -:  533:    }
    #####:  534:    return -1;
        -:  535:}
        -:  536:
        -:  537:/* 
        -:  538:   Here is an alternate search routine based on bisection.
        -:  539:   int i_low, i_mid, i_high, c;
        -:  540:   i_low = 0; i_high = generic_msg_len - 1;
        -:  541:   while (i_high - i_low >= 0) {
        -:  542:       i_mid = (i_high + i_low) / 2;
        -:  543:       c = strcmp( generic_err_msgs[i].short_name, msg );
        -:  544:       if (c == 0) return i_mid;
        -:  545:       if (c < 0) { i_low = i_mid + 1; }
        -:  546:       else       { i_high = i_mid - 1; }
        -:  547:   }
        -:  548:   return -1;
        -:  549:*/
        -:  550:#endif
        -:  551:
        -:  552:#if MPICH_ERROR_MSG_LEVEL == MPICH_ERROR_MSG_ALL
        -:  553:/* 
        -:  554: * Given a message string abbreviation (e.g., one that starts "**"), return 
        -:  555: * the corresponding index.  For the specific
        -:  556: * (parameterized messages), use idx = FindSpecificMsgIndex( "**msg" );
        -:  557: */
        -:  558:static int FindSpecificMsgIndex( const char *msg )
     9511:  559:{
        -:  560:    int i, c;
  1437473:  561:    for (i=0; i<specific_msgs_len; i++) {
        -:  562:	/* Check the sentinals to insure that the values are ok first */
  1437473:  563:	if (specific_err_msgs[i].sentinal1 != 0xacebad03 ||
        -:  564:	    specific_err_msgs[i].sentinal2 != 0xcb0bfa11) {
        -:  565:	    /* Something bad has happened! Don't risk trying the
        -:  566:	       short_name pointer; it may have been corrupted */
        -:  567:	    break;
        -:  568:	}
  1437473:  569:	c = strcmp( specific_err_msgs[i].short_name, msg );
  1437473:  570:	if (c == 0) return i;
  1427962:  571:	if (c > 0)
        -:  572:	{
        -:  573:	    /* don't return here if the string partially matches */
    #####:  574:	    if (strncmp(specific_err_msgs[i].short_name, msg, strlen(msg)) != 0)
    #####:  575:		return -1;
        -:  576:	}
        -:  577:    }
    #####:  578:    return -1;
        -:  579:}
        -:  580:/* See FindGenericMsgIndex comments for a more efficient search routine that
        -:  581:   could be used here as well. */
        -:  582:#endif
        -:  583:
        -:  584:
        -:  585:/* ------------------------------------------------------------------------ */
        -:  586:/* The following routines create an MPI error code, handling optional,      */
        -:  587:/* instance-specific error message information.  There are two key routines:*/
        -:  588:/*    MPIR_Err_create_code - Create the error code; this is the routine used*/
        -:  589:/*                           by most routines                               */
        -:  590:/*    MPIR_Err_create_code_valist - Create the error code; accept a valist  */
        -:  591:/*                           instead of a variable argument list (this is   */
        -:  592:/*                           used to allow this routine to be used from     */
        -:  593:/*                           within another varargs routine)                */
        -:  594:/* ------------------------------------------------------------------------ */
        -:  595:
        -:  596:/* Err_create_code is just a shell that accesses the va_list and then
        -:  597:   calls the real routine.  */
        -:  598:int MPIR_Err_create_code( int lastcode, int fatal, const char fcname[], 
        -:  599:			  int line, int error_class, const char generic_msg[],
        -:  600:			  const char specific_msg[], ... )
     9293:  601:{
        -:  602:    int rc;
        -:  603:    va_list Argp;
     9293:  604:    va_start(Argp, specific_msg);
     9293:  605:    rc = MPIR_Err_create_code_valist( lastcode, fatal, fcname, line,
        -:  606:				      error_class, generic_msg, specific_msg,
        -:  607:				      Argp );
     9293:  608:    va_end(Argp);
     9293:  609:    return rc;
        -:  610:}
        -:  611:#if MPICH_ERROR_MSG_LEVEL < MPICH_ERROR_MSG_ALL
        -:  612:/* In this case, the routine ignores all but (possibly) the generic message */
        -:  613:int MPIR_Err_create_code_valist( int lastcode, int fatal, const char fcname[], 
        -:  614:				 int line, int error_class, 
        -:  615:				 const char generic_msg[],
        -:  616:				 const char specific_msg[], va_list Argp )
        -:  617:{
        -:  618:#if MPICH_ERROR_MSG_LEVEL == MPICH_ERROR_MSG_GENERIC
        -:  619:    int generic_idx;
        -:  620:    int errcode;
        -:  621:    generic_idx = FindGenericMsgIndex(generic_msg);
        -:  622:    if (generic_idx >= 0) {
        -:  623:	errcode = (generic_idx << ERROR_GENERIC_SHIFT) | error_class;
        -:  624:	if (fatal)
        -:  625:	    errcode |= ERROR_FATAL_MASK;
        -:  626:    }
        -:  627:    return errcode;
        -:  628:#else
        -:  629:    return error_class;
        -:  630:#endif    
        -:  631:}
        -:  632:#endif /* msg_level < msg_all */
        -:  633:
        -:  634:/*
        -:  635: * Accessor routines for the predefined mqessages.  These can be
        -:  636: * used by the other routines (such as MPI_Error_string) to
        -:  637: * access the messages in this file, or the messages that may be
        -:  638: * available through any message catalog facility 
        -:  639: */
        -:  640:static const char *get_class_msg( int error_class )
     1074:  641:{
        -:  642:#if MPICH_ERROR_MSG_LEVEL > MPICH_ERROR_MSG_NONE
     1074:  643:    if (error_class >= 0 && error_class < MPIR_MAX_ERROR_CLASS_INDEX) {
     1074:  644:	return generic_err_msgs[class_to_index[error_class]].long_name;
        -:  645:    }
        -:  646:    else {
    #####:  647:	return "Unknown error class";
        -:  648:    }
        -:  649:#else 
        -:  650:    /* FIXME: Not internationalized */
        -:  651:    return "Error message texts are not available";
        -:  652:#endif
        -:  653:}
        -:  654:
        -:  655:/* FIXME: This routine isn't quite right yet */
        -:  656:/*
        -:  657: * Notes:
        -:  658: * One complication is that in the instance-specific case, a 
        -:  659: */
        -:  660:void MPIR_Err_get_string( int errorcode, char * msg, int length, 
        -:  661:			  MPIR_Err_get_class_string_func_t fn )
     1273:  662:{
        -:  663:    int error_class;
     1273:  664:    int len, num_remaining = length;
        -:  665:    
     1273:  666:    if (num_remaining == 0)
    #####:  667:	num_remaining = MPI_MAX_ERROR_STRING;
        -:  668:
        -:  669:    /* Convert the code to a string.  The cases are:
        -:  670:       simple class.  Find the corresponding string.
        -:  671:       <not done>
        -:  672:       if (user code) { go to code that extracts user error messages }
        -:  673:       else {
        -:  674:           is specific message code set and available?  if so, use it
        -:  675:	   else use generic code (lookup index in table of messages)
        -:  676:       }
        -:  677:     */
     1273:  678:    if (errorcode & ERROR_DYN_MASK) {
        -:  679:	/* This is a dynamically created error code (e.g., with 
        -:  680:	   MPI_Err_add_class) */
        -:  681:	/* If a dynamic error code was created, the function to convert
        -:  682:	   them into strings has been set.  Check to see that it was; this 
        -:  683:	   is a safeguard against a bogus error code */
      199:  684:	if (!MPIR_Process.errcode_to_string) {
        -:  685:	    /* FIXME: not internationalized */
        -:  686:	    /* --BEGIN ERROR HANDLING-- */
    #####:  687:	    if (MPIU_Strncpy(msg, "Undefined dynamic error code", 
        -:  688:			     num_remaining))
        -:  689:	    {
    #####:  690:		msg[num_remaining - 1] = '\0';
        -:  691:	    }
        -:  692:	    /* --END ERROR HANDLING-- */
        -:  693:	}
        -:  694:	else
        -:  695:	{
      199:  696:	    if (MPIU_Strncpy(msg, MPIR_Process.errcode_to_string( errorcode ), 
        -:  697:			     num_remaining))
        -:  698:	    {
    #####:  699:		msg[num_remaining - 1] = '\0';
        -:  700:	    }
        -:  701:	}
        -:  702:    }
     1074:  703:    else if ( (errorcode & ERROR_CLASS_MASK) == errorcode) {
       39:  704:	error_class = MPIR_ERR_GET_CLASS(errorcode);
        -:  705:
       39:  706:	if (fn != NULL && error_class > MPICH_ERR_LAST_CLASS /*&& error_class < MPICH_ERR_MAX_EXT_CLASS*/)
        -:  707:	{
    #####:  708:	    fn(errorcode, msg, length);
        -:  709:	}
        -:  710:	else
        -:  711:	{
       39:  712:	    if (MPIU_Strncpy(msg, get_class_msg( errorcode ), num_remaining))
        -:  713:	    {
    #####:  714:		msg[num_remaining - 1] = '\0';
        -:  715:	    }
        -:  716:	}
        -:  717:    }
        -:  718:    else
        -:  719:    {
        -:  720:	/* print the class message first */
     1035:  721:	error_class = MPIR_ERR_GET_CLASS(errorcode);
        -:  722:
     1035:  723:	if (fn != NULL && error_class > MPICH_ERR_LAST_CLASS /*&& error_class < MPICH_ERR_MAX_EXT_CLASS*/)
        -:  724:	{
    #####:  725:	    fn(errorcode, msg, num_remaining);
        -:  726:	}
        -:  727:	else
        -:  728:	{
     1035:  729:	    MPIU_Strncpy(msg, get_class_msg(ERROR_GET_CLASS(errorcode)), num_remaining);
        -:  730:	}
     1035:  731:	msg[num_remaining - 1] = '\0';
     1035:  732:	len = (int)strlen(msg);
     1035:  733:	msg += len;
     1035:  734:	num_remaining -= len;
        -:  735:
        -:  736:	/* then print the stack or the last specific error message */
        -:  737:
        -:  738:#       if MPICH_ERROR_MSG_LEVEL >= MPICH_ERROR_MSG_ALL
     1035:  739:	if (ErrGetInstanceString( errorcode, msg, num_remaining, fn )) 
     1035:  740:	    goto fn_exit;
        -:  741:#elif MPICH_ERROR_MSG_LEVEL > MPICH_ERROR_MSG_NONE
        -:  742:	{
        -:  743:	    int generic_idx;
        -:  744:	    
        -:  745:	    generic_idx = ((errorcode & ERROR_GENERIC_MASK) >> ERROR_GENERIC_SHIFT) - 1;
        -:  746:	    
        -:  747:	    if (generic_idx >= 0) {
        -:  748:		MPIU_Snprintf(msg, num_remaining, ", %s", generic_err_msgs[generic_idx].long_name);
        -:  749:		msg[num_remaining - 1] = '\0';
        -:  750:		goto fn_exit;
        -:  751:	    }
        -:  752:	}
        -:  753:#           endif
        -:  754:    }
        -:  755:    
        -:  756:fn_exit:
        -:  757:    return;
        -:  758:}
        -:  759:
        -:  760:
        -:  761:/* ------------------------------------------------------------------------- */
        -:  762:/* Routines to convert instance-specific messages into a string              */
        -:  763:/* This is the only case that supports instance-specific messages            */
        -:  764:/* ------------------------------------------------------------------------- */
        -:  765:/* ------------------------------------------------------------------------ */
        -:  766:/* This block of code is used to convert various MPI values into descriptive*/
        -:  767:/* strings.  The routines are                                               */
        -:  768:/*     GetAssertString - handle MPI_MODE_xxx (RMA asserts)                  */
        -:  769:/*     GetDTypeString  - handle MPI_Datatypes                               */
        -:  770:/*     GetMPIOpString  - handle MPI_Op                                      */
        -:  771:/* These routines are used in vsnprintf_mpi                                 */
        -:  772:/* FIXME: These functions are not thread safe                               */
        -:  773:/* ------------------------------------------------------------------------ */
        -:  774:#define ASSERT_STR_MAXLEN 256
        -:  775:
        -:  776:static const char * GetAssertString(int d)
    #####:  777:{
        -:  778:    static char str[ASSERT_STR_MAXLEN] = "";
        -:  779:    char *cur;
    #####:  780:    size_t len = ASSERT_STR_MAXLEN;
        -:  781:    size_t n;
        -:  782:
    #####:  783:    if (d == 0)
        -:  784:    {
    #####:  785:	MPIU_Strncpy(str, "assert=0", ASSERT_STR_MAXLEN);
    #####:  786:	return str;
        -:  787:    }
    #####:  788:    cur = str;
    #####:  789:    if (d & MPI_MODE_NOSTORE)
        -:  790:    {
    #####:  791:	MPIU_Strncpy(cur, "MPI_MODE_NOSTORE", len);
    #####:  792:	n = strlen(cur);
    #####:  793:	cur += n;
    #####:  794:	len -= n;
    #####:  795:	d ^= MPI_MODE_NOSTORE;
        -:  796:    }
    #####:  797:    if (d & MPI_MODE_NOCHECK)
        -:  798:    {
    #####:  799:	if (len < ASSERT_STR_MAXLEN)
    #####:  800:	    MPIU_Strncpy(cur, " | MPI_MODE_NOCHECK", len);
        -:  801:	else
    #####:  802:	    MPIU_Strncpy(cur, "MPI_MODE_NOCHECK", len);
    #####:  803:	n = strlen(cur);
    #####:  804:	cur += n;
    #####:  805:	len -= n;
    #####:  806:	d ^= MPI_MODE_NOCHECK;
        -:  807:    }
    #####:  808:    if (d & MPI_MODE_NOPUT)
        -:  809:    {
    #####:  810:	if (len < ASSERT_STR_MAXLEN)
    #####:  811:	    MPIU_Strncpy(cur, " | MPI_MODE_NOPUT", len);
        -:  812:	else
    #####:  813:	    MPIU_Strncpy(cur, "MPI_MODE_NOPUT", len);
    #####:  814:	n = strlen(cur);
    #####:  815:	cur += n;
    #####:  816:	len -= n;
    #####:  817:	d ^= MPI_MODE_NOPUT;
        -:  818:    }
    #####:  819:    if (d & MPI_MODE_NOPRECEDE)
        -:  820:    {
    #####:  821:	if (len < ASSERT_STR_MAXLEN)
    #####:  822:	    MPIU_Strncpy(cur, " | MPI_MODE_NOPRECEDE", len);
        -:  823:	else
    #####:  824:	    MPIU_Strncpy(cur, "MPI_MODE_NOPRECEDE", len);
    #####:  825:	n = strlen(cur);
    #####:  826:	cur += n;
    #####:  827:	len -= n;
    #####:  828:	d ^= MPI_MODE_NOPRECEDE;
        -:  829:    }
    #####:  830:    if (d & MPI_MODE_NOSUCCEED)
        -:  831:    {
    #####:  832:	if (len < ASSERT_STR_MAXLEN)
    #####:  833:	    MPIU_Strncpy(cur, " | MPI_MODE_NOSUCCEED", len);
        -:  834:	else
    #####:  835:	    MPIU_Strncpy(cur, "MPI_MODE_NOSUCCEED", len);
    #####:  836:	n = strlen(cur);
    #####:  837:	cur += n;
    #####:  838:	len -= n;
    #####:  839:	d ^= MPI_MODE_NOSUCCEED;
        -:  840:    }
    #####:  841:    if (d)
        -:  842:    {
    #####:  843:	if (len < ASSERT_STR_MAXLEN)
    #####:  844:	    MPIU_Snprintf(cur, len, " | 0x%x", d);
        -:  845:	else
    #####:  846:	    MPIU_Snprintf(cur, len, "assert=0x%x", d);
        -:  847:    }
    #####:  848:    return str;
        -:  849:}
        -:  850:
        -:  851:static const char * GetDTypeString(MPI_Datatype d)
     1803:  852:{
        -:  853:    static char default_str[64];
     1803:  854:    int num_integers, num_addresses, num_datatypes, combiner = 0;
        -:  855:    char *str;
        -:  856:
     1803:  857:    if (HANDLE_GET_MPI_KIND(d) != MPID_DATATYPE ||      \
        -:  858:	(HANDLE_GET_KIND(d) == HANDLE_KIND_INVALID &&   \
        -:  859:	d != MPI_DATATYPE_NULL))
    #####:  860:        return "INVALID DATATYPE";
        -:  861:    
        -:  862:
     1803:  863:    if (d == MPI_DATATYPE_NULL)
      184:  864:	return "MPI_DATATYPE_NULL";
        -:  865:
     1619:  866:    if (d == 0)
        -:  867:    {
    #####:  868:	MPIU_Strncpy(default_str, "dtype=0x0", 64);
    #####:  869:	return default_str;
        -:  870:    }
        -:  871:
     1619:  872:    MPID_Type_get_envelope(d, &num_integers, &num_addresses, &num_datatypes, 
        -:  873:			   &combiner);
     1619:  874:    if (combiner == MPI_COMBINER_NAMED)
        -:  875:    {
     1606:  876:	str = MPIDU_Datatype_builtin_to_string(d);
     1606:  877:	if (str == NULL)
        -:  878:	{
    #####:  879:	    MPIU_Snprintf(default_str, 64, "dtype=0x%08x", d);
    #####:  880:	    return default_str;
        -:  881:	}
     1606:  882:	return str;
        -:  883:    }
        -:  884:    
        -:  885:    /* default is not thread safe */
       13:  886:    str = MPIDU_Datatype_combiner_to_string(combiner);
       13:  887:    if (str == NULL)
        -:  888:    {
    #####:  889:	MPIU_Snprintf(default_str, 64, "dtype=USER<0x%08x>", d);
    #####:  890:	return default_str;
        -:  891:    }
       13:  892:    MPIU_Snprintf(default_str, 64, "dtype=USER<%s>", str);
       13:  893:    return default_str;
        -:  894:}
        -:  895:
        -:  896:static const char * GetMPIOpString(MPI_Op o)
      326:  897:{
        -:  898:    static char default_str[64];
        -:  899:
      326:  900:    switch (o)
        -:  901:    {
        -:  902:    case MPI_OP_NULL:
       78:  903:	return "MPI_OP_NULL";
        -:  904:    case MPI_MAX:
       18:  905:	return "MPI_MAX";
        -:  906:    case MPI_MIN:
       16:  907:	return "MPI_MIN";
        -:  908:    case MPI_SUM:
       50:  909:	return "MPI_SUM";
        -:  910:    case MPI_PROD:
       16:  911:	return "MPI_PROD";
        -:  912:    case MPI_LAND:
       16:  913:	return "MPI_LAND";
        -:  914:    case MPI_BAND:
       24:  915:	return "MPI_BAND";
        -:  916:    case MPI_LOR:
       16:  917:	return "MPI_LOR";
        -:  918:    case MPI_BOR:
       24:  919:	return "MPI_BOR";
        -:  920:    case MPI_LXOR:
       16:  921:	return "MPI_LXOR";
        -:  922:    case MPI_BXOR:
       24:  923:	return "MPI_BXOR";
        -:  924:    case MPI_MINLOC:
       14:  925:	return "MPI_MINLOC";
        -:  926:    case MPI_MAXLOC:
       14:  927:	return "MPI_MAXLOC";
        -:  928:    case MPI_REPLACE:
    #####:  929:	return "MPI_REPLACE";
        -:  930:    }
        -:  931:    /* FIXME: default is not thread safe */
    #####:  932:    MPIU_Snprintf(default_str, 64, "op=0x%x", o);
    #####:  933:    return default_str;
        -:  934:}
        -:  935:
        -:  936:/* ------------------------------------------------------------------------ */
        -:  937:/* This routine takes an instance-specific string with format specifiers    */
        -:  938:/* This routine makes use of the above routines, along with some inlined    */
        -:  939:/* code, to process the format specifiers for the MPI objects               */
        -:  940:/* The current set of format specifiers is undocumented except for their
        -:  941:   use in this routine.  In addition, these choices do not permit the 
        -:  942:   use of GNU extensions to check the validity of these arguments.  
        -:  943:   At some point, a documented set that can exploit those GNU extensions
        -:  944:   will replace these. */
        -:  945:/* ------------------------------------------------------------------------ */
        -:  946:
        -:  947:static int vsnprintf_mpi(char *str, size_t maxlen, const char *fmt_orig, 
        -:  948:			 va_list list)
     9461:  949:{
        -:  950:    char *begin, *end, *fmt;
        -:  951:    size_t len;
        -:  952:    MPI_Comm C;
        -:  953:    MPI_Info I;
        -:  954:    MPI_Datatype D;
        -:  955:    MPI_Win W;
        -:  956:    MPI_Group G;
        -:  957:    MPI_Op O;
        -:  958:    MPI_Request R;
        -:  959:    MPI_Errhandler E;
        -:  960:    char *s;
     9461:  961:    int t, i, d, mpi_errno=MPI_SUCCESS;
        -:  962:    long long ll;
        -:  963:    void *p;
        -:  964:
     9461:  965:    fmt = MPIU_Strdup(fmt_orig);
     9461:  966:    if (fmt == NULL)
        -:  967:    {
    #####:  968:	if (maxlen > 0 && str != NULL)
    #####:  969:	    *str = '\0';
    #####:  970:	return 0;
        -:  971:    }
        -:  972:
     9461:  973:    begin = fmt;
     9461:  974:    end = strchr(fmt, '%');
    44230:  975:    while (end)
        -:  976:    {
    25308:  977:	len = maxlen;
    25308:  978:	if (len > (size_t)(end - begin)) {
    25308:  979:	    len = (size_t)(end - begin);
        -:  980:	}
    25308:  981:	if (len)
        -:  982:	{
    25308:  983:	    MPIU_Memcpy(str, begin, len);
    25308:  984:	    str += len;
    25308:  985:	    maxlen -= len;
        -:  986:	}
    25308:  987:	end++;
    25308:  988:	begin = end+1;
    25308:  989:	switch ((int)(*end))
        -:  990:	{
        -:  991:	case (int)'s':
     1258:  992:	    s = va_arg(list, char *);
     1258:  993:	    if (s) 
     1258:  994:	        MPIU_Strncpy(str, s, maxlen);
        -:  995:            else {
    #####:  996:		MPIU_Strncpy(str, "<NULL>", maxlen );
        -:  997:	    }
        -:  998:	    break;
        -:  999:	case (int)'d':
    14332: 1000:	    d = va_arg(list, int);
    14332: 1001:	    MPIU_Snprintf(str, maxlen, "%d", d);
    14332: 1002:	    break;
        -: 1003:	case (int)'L':
    #####: 1004:	    ll = va_arg(list, long long);
    #####: 1005:	    MPIU_Snprintf(str, maxlen, "%lld", ll);
    #####: 1006:	    break;
        -: 1007:        case (int)'x':
    #####: 1008:            d = va_arg(list, int);
    #####: 1009:            MPIU_Snprintf(str, maxlen, "%x", d);
    #####: 1010:            break;
        -: 1011:        case (int)'X':
    #####: 1012:            ll = va_arg(list, long long);
    #####: 1013:            MPIU_Snprintf(str, maxlen, "%llx", ll);
    #####: 1014:            break;
        -: 1015:	case (int)'i':
     1280: 1016:	    i = va_arg(list, int);
     1280: 1017:	    switch (i)
        -: 1018:	    {
        -: 1019:	    case MPI_ANY_SOURCE:
       24: 1020:		MPIU_Strncpy(str, "MPI_ANY_SOURCE", maxlen);
       24: 1021:		break;
        -: 1022:	    case MPI_PROC_NULL:
       46: 1023:		MPIU_Strncpy(str, "MPI_PROC_NULL", maxlen);
       46: 1024:		break;
        -: 1025:	    case MPI_ROOT:
       14: 1026:		MPIU_Strncpy(str, "MPI_ROOT", maxlen);
       14: 1027:		break;
        -: 1028:	    default:
     1196: 1029:		MPIU_Snprintf(str, maxlen, "%d", i);
        -: 1030:		break;
        -: 1031:	    }
        -: 1032:	    break;
        -: 1033:	case (int)'t':
     1280: 1034:	    t = va_arg(list, int);
     1280: 1035:	    switch (t)
        -: 1036:	    {
        -: 1037:	    case MPI_ANY_TAG:
       87: 1038:		MPIU_Strncpy(str, "MPI_ANY_TAG", maxlen);
       87: 1039:		break;
        -: 1040:	    case MPI_UNDEFINED:
    #####: 1041:		MPIU_Strncpy(str, "MPI_UNDEFINED", maxlen);
    #####: 1042:		break;
        -: 1043:	    default:
     1193: 1044:		MPIU_Snprintf(str, maxlen, "%d", t);
        -: 1045:		break;
        -: 1046:	    }
        -: 1047:	    break;
        -: 1048:	case (int)'p':
     3044: 1049:	    p = va_arg(list, void *);
        -: 1050:	    /* FIXME: A check for MPI_IN_PLACE should only be used 
        -: 1051:	       where that is valid */
     3044: 1052:	    if (p == MPI_IN_PLACE)
        -: 1053:	    {
    #####: 1054:		MPIU_Strncpy(str, "MPI_IN_PLACE", maxlen);
        -: 1055:	    }
        -: 1056:	    else
        -: 1057:	    {
        -: 1058:		/* FIXME: We may want to use 0x%p for systems that 
        -: 1059:		   (including Windows) that don't prefix %p with 0x. 
        -: 1060:		   This must be done with a capability, not a test on
        -: 1061:		   particular OS or header files */
     3044: 1062:		MPIU_Snprintf(str, maxlen, "%p", p);
        -: 1063:	    }
        -: 1064:	    break;
        -: 1065:	case (int)'C':
     1895: 1066:	    C = va_arg(list, MPI_Comm);
     1895: 1067:	    switch (C)
        -: 1068:	    {
        -: 1069:	    case MPI_COMM_WORLD:
     1563: 1070:		MPIU_Strncpy(str, "MPI_COMM_WORLD", maxlen);
     1563: 1071:		break;
        -: 1072:	    case MPI_COMM_SELF:
       23: 1073:		MPIU_Strncpy(str, "MPI_COMM_SELF", maxlen);
       23: 1074:		break;
        -: 1075:	    case MPI_COMM_NULL:
      151: 1076:		MPIU_Strncpy(str, "MPI_COMM_NULL", maxlen);
      151: 1077:		break;
        -: 1078:	    default:
      158: 1079:		MPIU_Snprintf(str, maxlen, "comm=0x%x", C);
        -: 1080:		break;
        -: 1081:	    }
        -: 1082:	    break;
        -: 1083:	case (int)'I':
        2: 1084:	    I = va_arg(list, MPI_Info);
        2: 1085:	    if (I == MPI_INFO_NULL)
        -: 1086:	    {
        2: 1087:		MPIU_Strncpy(str, "MPI_INFO_NULL", maxlen);
        -: 1088:	    }
        -: 1089:	    else
        -: 1090:	    {
    #####: 1091:		MPIU_Snprintf(str, maxlen, "info=0x%x", I);
        -: 1092:	    }
        -: 1093:	    break;
        -: 1094:	case (int)'D':
     1803: 1095:	    D = va_arg(list, MPI_Datatype);
     1803: 1096:	    MPIU_Snprintf(str, maxlen, "%s", GetDTypeString(D));
     1803: 1097:	    break;
        -: 1098:	    /* Include support for %F only if MPI-IO is enabled */
        -: 1099:#ifdef MPI_MODE_RDWR
        -: 1100:	case (int)'F':
        -: 1101:	    {
        -: 1102:	    MPI_File F;
        4: 1103:	    F = va_arg(list, MPI_File);
        4: 1104:	    if (F == MPI_FILE_NULL)
        -: 1105:	    {
    #####: 1106:		MPIU_Strncpy(str, "MPI_FILE_NULL", maxlen);
        -: 1107:	    }
        -: 1108:	    else
        -: 1109:	    {
        4: 1110:		MPIU_Snprintf(str, maxlen, "file=0x%lx", (unsigned long)F);
        -: 1111:	    }
        -: 1112:	    }
        -: 1113:	    break;
        -: 1114:#endif
        -: 1115:	case (int)'W':
       10: 1116:	    W = va_arg(list, MPI_Win);
       10: 1117:	    if (W == MPI_WIN_NULL)
        -: 1118:	    {
    #####: 1119:		MPIU_Strncpy(str, "MPI_WIN_NULL", maxlen);
        -: 1120:	    }
        -: 1121:	    else
        -: 1122:	    {
       10: 1123:		MPIU_Snprintf(str, maxlen, "win=0x%x", W);
        -: 1124:	    }
        -: 1125:	    break;
        -: 1126:	case (int)'A':
    #####: 1127:	    d = va_arg(list, int);
    #####: 1128:	    MPIU_Snprintf(str, maxlen, "%s", GetAssertString(d));
    #####: 1129:	    break;
        -: 1130:	case (int)'G':
       64: 1131:	    G = va_arg(list, MPI_Group);
       64: 1132:	    if (G == MPI_GROUP_NULL)
        -: 1133:	    {
       22: 1134:		MPIU_Strncpy(str, "MPI_GROUP_NULL", maxlen);
        -: 1135:	    }
        -: 1136:	    else
        -: 1137:	    {
       42: 1138:		MPIU_Snprintf(str, maxlen, "group=0x%x", G);
        -: 1139:	    }
        -: 1140:	    break;
        -: 1141:	case (int)'O':
      326: 1142:	    O = va_arg(list, MPI_Op);
      326: 1143:	    MPIU_Snprintf(str, maxlen, "%s", GetMPIOpString(O));
      326: 1144:	    break;
        -: 1145:	case (int)'R':
    #####: 1146:	    R = va_arg(list, MPI_Request);
    #####: 1147:	    if (R == MPI_REQUEST_NULL)
        -: 1148:	    {
    #####: 1149:		MPIU_Strncpy(str, "MPI_REQUEST_NULL", maxlen);
        -: 1150:	    }
        -: 1151:	    else
        -: 1152:	    {
    #####: 1153:		MPIU_Snprintf(str, maxlen, "req=0x%x", R);
        -: 1154:	    }
        -: 1155:	    break;
        -: 1156:	case (int)'E':
       10: 1157:	    E = va_arg(list, MPI_Errhandler);
       10: 1158:	    if (E == MPI_ERRHANDLER_NULL)
        -: 1159:	    {
        2: 1160:		MPIU_Strncpy(str, "MPI_ERRHANDLER_NULL", maxlen);
        -: 1161:	    }
        -: 1162:	    else
        -: 1163:	    {
        8: 1164:		MPIU_Snprintf(str, maxlen, "errh=0x%x", E);
        -: 1165:	    }
        -: 1166:	    break;
        -: 1167:	default:
        -: 1168:	    /* Error: unhandled output type */
    #####: 1169:	    return 0;
        -: 1170:	    /*
        -: 1171:	    if (maxlen > 0 && str != NULL)
        -: 1172:		*str = '\0';
        -: 1173:	    break;
        -: 1174:	    */
        -: 1175:	}
    25308: 1176:	len = strlen(str);
    25308: 1177:	maxlen -= len;
    25308: 1178:	str += len;
    25308: 1179:	end = strchr(begin, '%');
        -: 1180:    }
     9461: 1181:    if (*begin != '\0')
        -: 1182:    {
     2588: 1183:	MPIU_Strncpy(str, begin, maxlen);
        -: 1184:    }
        -: 1185:    /* Free the dup'ed format string */
     9461: 1186:    MPIU_Free( fmt );
        -: 1187:
     9461: 1188:    return mpi_errno;
        -: 1189:}
        -: 1190:
        -: 1191:/* ------------------------------------------------------------------------- */
        -: 1192:/* ------------------------------------------------------------------------- */
        -: 1193:/*
        -: 1194: * Instance-specific error messages are stored in a ring.  The elements of this
        -: 1195: * ring are MPIR_Err_msg_t structures, which contain the following fields:
        -: 1196: *    id - this is used to check that the entry is valid; it is computed from
        -: 1197: *         the error code and location in the ring.  The routine
        -: 1198: *           ErrcodeToId( errcode, &id ) is used to extract the id from an 
        -: 1199: *         error code and
        -: 1200: *           ErrcodeCreateID( class, generic, msg, &id, &seq ) is used to 
        -: 1201: *         create the id from an error class, generic index, and message 
        -: 1202: *         string.  The "seq" field is inserted into the error code as a 
        -: 1203: *         check.
        -: 1204: *
        -: 1205: *    prev_error - The full MPI error code of the previous error attached 
        -: 1206: *         to this list of errors, or MPI_SUCCESSS (which has value 0).
        -: 1207: *         This is the last error code, not the index in the ring of the last 
        -: 1208: *         error code.  That's the right choice, because we want to ensure 
        -: 1209: *         that the value is valid if the ring overflows.  In addition,
        -: 1210: *         we allow this to be an error CLASS (one of the predefined MPI
        -: 1211: *         error classes).  This is particularly important for 
        -: 1212: *         MPI_ERR_IN_STATUS, which may be returned as a valid error code.
        -: 1213: *         (classes are valid error codes).
        -: 1214: *         
        -: 1215: *    use_user_error_code and user_error_code - Used to handle a few cases 
        -: 1216: *         in MPI where a user-provided routine returns an error code; 
        -: 1217: *         this allows us to provide information about the chain of 
        -: 1218: *         routines that were involved, while returning the users prefered
        -: 1219: *         error value to the users environment.  See the note below
        -: 1220: *         on user error codes.
        -: 1221: *
        -: 1222: *    location - A string that indicates what function and line number
        -: 1223: *         where the error code was set.
        -: 1224: *
        -: 1225: *    msg - A message about the error.  This may be instance-specific (e.g.,
        -: 1226: *         it may have been created at the time the error was detected with
        -: 1227: *         information about the parameters that caused the error).
        -: 1228: *
        -: 1229: * Note that both location and msg are defined as length MAX_xxx+1.  This 
        -: 1230: * isn't really necessary (at least for msg), since the MPI standard 
        -: 1231: * requires that MAX_MPI_ERROR_STRING include the space for the trailing null,
        -: 1232: * but using the extra byte makes the code a little simpler.
        -: 1233: *
        -: 1234: * The "id" value is used to keep a sort of "checkvalue" to ensure that the
        -: 1235: * error code that points at this message is in fact for this particular 
        -: 1236: * message.  This is used to handle the unlikely but possible situation where 
        -: 1237: * so many error messages are generated that the ring is overlapped.
        -: 1238: *
        -: 1239: * The message arrays are preallocated to ensure that there is space for these
        -: 1240: * messages when an error occurs.  One variation would be to allow these
        -: 1241: * to be dynamically allocated, but it is probably better to either preallocate
        -: 1242: * these or turn off all error message generation (which will eliminate these
        -: 1243: * arrays).
        -: 1244: *
        -: 1245: * One possible alternative is to use the message ring *only* for instance
        -: 1246: * messages and use the predefined messages in-place for the generic
        -: 1247: * messages.  The approach used here provides uniform handling of all 
        -: 1248: * error messages.
        -: 1249: *
        -: 1250: * Note on user error codes
        -: 1251: *
        -: 1252: * The "user error codes" is used to handle an ambiguity in the MPI-1 
        -: 1253: * standard about the return value from the attribute callbacks.  The 
        -: 1254: * standard does not specify what values, other than 'MPI_SUCCESS', are
        -: 1255: * valid.  Because the Intel MPI-1 test suite expected 'MPI_Comm_dup' to
        -: 1256: * return the same non-zero value returned by the attribute callback routine,
        -: 1257: * this is the behavior that many (if not all) MPI implementations provide.
        -: 1258: * As a result, the return from those routines is 
        -: 1259: * 
        -: 1260: */
        -: 1261:#if MPICH_ERROR_MSG_LEVEL == MPICH_ERROR_MSG_ALL
        -: 1262:
        -: 1263:/* FIXME: Where is the documentation for this function?  What is it for?  */
        -: 1264:static void MPIR_Err_print_stack_string(int errcode, char *str, int maxlen);
        -: 1265:
        -: 1266:#define MAX_ERROR_RING ERROR_SPECIFIC_INDEX_SIZE
        -: 1267:#define MAX_LOCATION_LEN 63
        -: 1268:
        -: 1269:/* The maximum error string in this case may be a multi-line message,
        -: 1270:   constructed from multiple entries in the error message ring.  The 
        -: 1271:   individual ring messages should be shorter than MPI_MAX_ERROR_STRING,
        -: 1272:   perhaps as small a 256. We define a separate value for the error lines. 
        -: 1273: */
        -: 1274:#define MPIR_MAX_ERROR_LINE 256
        -: 1275:
        -: 1276:/* See the description above for the fields in this structure */
        -: 1277:typedef struct MPIR_Err_msg
        -: 1278:{
        -: 1279:    int  id;
        -: 1280:    int  prev_error;
        -: 1281:    int  use_user_error_code;
        -: 1282:    int  user_error_code;
        -: 1283:
        -: 1284:    char location[MAX_LOCATION_LEN+1];
        -: 1285:    char msg[MPIR_MAX_ERROR_LINE+1];
        -: 1286:}
        -: 1287:MPIR_Err_msg_t;
        -: 1288:
        -: 1289:static MPIR_Err_msg_t ErrorRing[MAX_ERROR_RING];
        -: 1290:static volatile unsigned int error_ring_loc     = 0;
        -: 1291:static volatile unsigned int max_error_ring_loc = 0;
        -: 1292:
        -: 1293:/* FIXME: This needs to be made consistent with the different thread levels, 
        -: 1294:   since in the "global" thread level, an extra thread mutex is not required. */
        -: 1295:#if defined(MPID_REQUIRES_THREAD_SAFETY)
        -: 1296:/* if the device requires internal MPICH routines to be thread safe, the
        -: 1297:   MPIU_THREAD_CHECK macros are not appropriate */
        -: 1298:static MPID_Thread_mutex_t error_ring_mutex;
        -: 1299:#define error_ring_mutex_create(_mpi_errno_p_)			\
        -: 1300:    MPID_Thread_mutex_create(&error_ring_mutex, _mpi_errno_p_)
        -: 1301:#define error_ring_mutex_destroy(_mpi_errno_p)				\
        -: 1302:    MPID_Thread_mutex_destroy(&error_ring_mutex, _mpi_errno_p_)
        -: 1303:#define error_ring_mutex_lock()			\
        -: 1304:    MPID_Thread_mutex_lock(&error_ring_mutex)
        -: 1305:#define error_ring_mutex_unlock()		\
        -: 1306:    MPID_Thread_mutex_unlock(&error_ring_mutex)
        -: 1307:#elif defined(MPICH_IS_THREADED)
        -: 1308:static MPID_Thread_mutex_t error_ring_mutex;
        -: 1309:#define error_ring_mutex_create(_mpi_errno_p) MPID_Thread_mutex_create(&error_ring_mutex,_mpi_errno_p)
        -: 1310:#define error_ring_mutex_destroy(_mpi_errno_p) MPID_Thread_mutex_destroy(&error_ring_mutex,_mpi_errno_p)
        -: 1311:#define error_ring_mutex_lock() \
        -: 1312:    MPIU_THREAD_CHECK_BEGIN \
        -: 1313:     MPID_Thread_mutex_lock(&error_ring_mutex) \
        -: 1314:    MPIU_THREAD_CHECK_END
        -: 1315:#define error_ring_mutex_unlock() \
        -: 1316:    MPIU_THREAD_CHECK_BEGIN \
        -: 1317:     MPID_Thread_mutex_unlock(&error_ring_mutex) \
        -: 1318:    MPIU_THREAD_CHECK_END
        -: 1319:#else
        -: 1320:#define error_ring_mutex_create(_a)
        -: 1321:#define error_ring_mutex_destroy(_a)
        -: 1322:#define error_ring_mutex_lock()
        -: 1323:#define error_ring_mutex_unlock()
        -: 1324:#endif
        -: 1325:
        -: 1326:/* Create the ring id from information about the message */
        -: 1327:static void ErrcodeCreateID( int error_class, int generic_idx, 
        -: 1328:			     const char *msg, int *id, int *seq )
    10053: 1329:{
        -: 1330:    int i;
    10053: 1331:    int ring_seq = 0, ring_id;
        -: 1332:
        -: 1333:    /* Create a simple hash function of the message to serve as the 
        -: 1334:       sequence number */
    10053: 1335:    ring_seq = 0;
   749788: 1336:    for (i=0; msg[i]; i++)
   739735: 1337:	ring_seq += (unsigned int) msg[i];
        -: 1338:
    10053: 1339:    ring_seq %= ERROR_SPECIFIC_SEQ_SIZE;
        -: 1340:
    10053: 1341:    ring_id = (error_class & ERROR_CLASS_MASK) |
        -: 1342:	((generic_idx + 1) << ERROR_GENERIC_SHIFT) |
        -: 1343:	(ring_seq << ERROR_SPECIFIC_SEQ_SHIFT);
        -: 1344:
    10053: 1345:    *id  = ring_id;
    10053: 1346:    *seq = ring_seq;
    10053: 1347:}
        -: 1348:
        -: 1349:/* Convert an error code into ring_idx, ring_id, and generic_idx.
        -: 1350:   Return non-zero if there is a problem with the decode values
        -: 1351:   (e.g., out of range for the ring index) */
        -: 1352:static int convertErrcodeToIndexes( int errcode, int *ring_idx, int *ring_id,
        -: 1353:				    int *generic_idx )
    15136: 1354:{
    15136: 1355:    *ring_idx = (errcode & ERROR_SPECIFIC_INDEX_MASK) >> 
        -: 1356:	ERROR_SPECIFIC_INDEX_SHIFT;
    15136: 1357:    *ring_id = errcode & (ERROR_CLASS_MASK | 
        -: 1358:			  ERROR_GENERIC_MASK | ERROR_SPECIFIC_SEQ_MASK);
    15136: 1359:    *generic_idx = ((errcode & ERROR_GENERIC_MASK) >> ERROR_GENERIC_SHIFT) - 1;
        -: 1360:    
        -: 1361:    /* Test on both the max_error_ring_loc and MAX_ERROR_RING to guard 
        -: 1362:       against memory overwrites */
    15136: 1363:    if (*ring_idx < 0 || *ring_idx >= MAX_ERROR_RING || 
    #####: 1364:	*ring_idx > max_error_ring_loc) return 1;
        -: 1365:
    15136: 1366:    return 0;
        -: 1367:}
        -: 1368:static int checkErrcodeIsValid( int errcode )
     2072: 1369:{
        -: 1370:    int ring_id, generic_idx, ring_idx;
        -: 1371:
        -: 1372:    /* If the errcode is a class, then it is valid */
     2072: 1373:    if (errcode <= MPIR_MAX_ERROR_CLASS_INDEX && errcode >= 0) return 0;
        -: 1374:
     2068: 1375:    convertErrcodeToIndexes( errcode, &ring_idx, &ring_id, &generic_idx );
     2068: 1376:    if (ring_idx < 0 || ring_idx >= MAX_ERROR_RING ||
    #####: 1377:	ring_idx > max_error_ring_loc) return 1;
     2068: 1378:    if (ErrorRing[ring_idx].id != ring_id) return 2;
        -: 1379:    /* It looks like the code uses a generic idx of -1 to indicate no
        -: 1380:       generic message */
     2068: 1381:    if (generic_idx < -1 || generic_idx > generic_msgs_len) return 3;
     2068: 1382:    return 0;
        -: 1383:}
        -: 1384:static const char *ErrcodeInvalidReasonStr( int reason )
    #####: 1385:{
    #####: 1386:    const char *str = 0;
    #####: 1387:    switch (reason) {
        -: 1388:    case 1:
    #####: 1389:	str = "Ring Index out of range";
    #####: 1390:	break;
        -: 1391:    case 2:
    #####: 1392:	str = "Ring ids do not match";
    #####: 1393:	break;
        -: 1394:    case 3:
    #####: 1395:	str = "Generic message index out of range";
    #####: 1396:	break;
        -: 1397:    default:
    #####: 1398:	str = "Unknown reason for invalid errcode";
        -: 1399:	break;
        -: 1400:    }
    #####: 1401:    return str;
        -: 1402:}
        -: 1403:/* Check to see if the error code is a user-specified error code
        -: 1404:   (e.g., from the attribute delete function) and if so, set the error code
        -: 1405:   to the value provide by the user */
        -: 1406:static int checkForUserErrcode( int errcode )
     6938: 1407:{
     6938: 1408:    error_ring_mutex_lock();
        -: 1409:    {
     6938: 1410:	if (errcode != MPI_SUCCESS) {
        -: 1411:	    int ring_idx;
        -: 1412:	    int ring_id;
        -: 1413:	    int generic_idx;
        -: 1414:	    
     6938: 1415:	    if (convertErrcodeToIndexes( errcode, &ring_idx, &ring_id,
        -: 1416:					 &generic_idx ) != 0) {
    #####: 1417:		MPIU_Error_printf( 
        -: 1418:		  "Invalid error code (%d) (error ring index %d invalid)\n", 
        -: 1419:		  errcode, ring_idx );
        -: 1420:	    }
        -: 1421:	    else {
        -: 1422:		/* Can we get a more specific error message */
     6938: 1423:		if (generic_idx >= 0 && 
        -: 1424:		    ErrorRing[ring_idx].id == ring_id && 
        -: 1425:		    ErrorRing[ring_idx].use_user_error_code)
        -: 1426:		    {
       25: 1427:			errcode = ErrorRing[ring_idx].user_error_code;
        -: 1428:		    }
        -: 1429:	    }
        -: 1430:	}
        -: 1431:    }
     6938: 1432:    error_ring_mutex_unlock();
     6938: 1433:    return errcode;
        -: 1434:}
        -: 1435:
        -: 1436:/*
        -: 1437: * This is the real routine for generating an error code.  It takes
        -: 1438: * a va_list so that it can be called by any routine that accepts a 
        -: 1439: * variable number of arguments.
        -: 1440: */
        -: 1441:int MPIR_Err_create_code_valist( int lastcode, int fatal, const char fcname[], 
        -: 1442:				 int line, int error_class, 
        -: 1443:				 const char generic_msg[],
        -: 1444:				 const char specific_msg[], va_list Argp )
    10055: 1445:{
        -: 1446:    int err_code;
        -: 1447:    int generic_idx;
    10055: 1448:    int use_user_error_code = 0;
    10055: 1449:    int user_error_code = -1;
        -: 1450:    char user_ring_msg[MPIR_MAX_ERROR_LINE+1];
        -: 1451:
        -: 1452:    /* Create the code from the class and the message ring index */
        -: 1453:
        -: 1454:    /* Check that lastcode is valid */
    10055: 1455:    if (lastcode != MPI_SUCCESS) {
        -: 1456:	int reason;
     2072: 1457:	reason = checkErrcodeIsValid(lastcode);
     2072: 1458:	if (reason) {
    #####: 1459:	    MPIU_Error_printf( "Internal Error: invalid error code %x (%s) in %s:%d\n", 
        -: 1460:			       lastcode, ErrcodeInvalidReasonStr( reason ), 
        -: 1461:			       fcname, line );
    #####: 1462:	    lastcode = MPI_SUCCESS;
        -: 1463:	}
        -: 1464:    }
        -: 1465:
        -: 1466:    /* FIXME: ERR_OTHER is overloaded; this may mean "OTHER" or it may
        -: 1467:       mean "No additional error, just routine stack info" */
    10055: 1468:    if (error_class == MPI_ERR_OTHER)
        -: 1469:    {
     2163: 1470:        if (MPIR_ERR_GET_CLASS(lastcode) > MPI_SUCCESS && 
        -: 1471:	    MPIR_ERR_GET_CLASS(lastcode) <= MPICH_ERR_LAST_CLASS)
        -: 1472:	{
        -: 1473:	    /* If the last class is more specific (and is valid), then pass it 
        -: 1474:	       through */
     2067: 1475:	    error_class = MPIR_ERR_GET_CLASS(lastcode);
        -: 1476:	}
        -: 1477:	else
        -: 1478:	{
       96: 1479:	    error_class = MPI_ERR_OTHER;
        -: 1480:	}
        -: 1481:    }
        -: 1482:
        -: 1483:    /* Handle special case of MPI_ERR_IN_STATUS.  According to the standard,
        -: 1484:       the code must be equal to the class. See section 3.7.5.  
        -: 1485:       Information on the particular error is in the MPI_ERROR field 
        -: 1486:       of the status. */
    10055: 1487:    if (error_class == MPI_ERR_IN_STATUS)
        -: 1488:    {
        2: 1489:	return MPI_ERR_IN_STATUS;
        -: 1490:    }
        -: 1491:
    10053: 1492:    err_code = error_class;
        -: 1493:
        -: 1494:    /* Handle the generic message.  This selects a subclass, based on a text 
        -: 1495:       string */
        -: 1496:#   if MPICH_ERROR_MSG_LEVEL >= MPICH_ERROR_MSG_GENERIC
        -: 1497:    {
    10053: 1498:	generic_idx = FindGenericMsgIndex(generic_msg);
    10053: 1499:	if (generic_idx >= 0) {
    10053: 1500:	    if (strcmp( generic_err_msgs[generic_idx].short_name, "**user" ) == 0)
        -: 1501:	    {
       25: 1502:		use_user_error_code = 1;
        -: 1503:		/* This is a special case.  The format is
        -: 1504:		   "**user", "**userxxx %d", intval
        -: 1505:		   (generic, specific, parameter).  In this
        -: 1506:		   case we must ... save the user value because
        -: 1507:		   we store it explicitly in the ring.  
        -: 1508:		   We do this here because we cannot both access the 
        -: 1509:		   user error code and pass the argp to vsnprintf_mpi . */
       25: 1510:		if (specific_msg) {
        -: 1511:		    const char *specific_fmt; 
        -: 1512:		    int specific_idx;
       25: 1513:		    user_error_code = va_arg(Argp,int);
        -: 1514:#if MPICH_ERROR_MSG_LEVEL > MPICH_ERROR_MSG_GENERIC
       25: 1515:		    specific_idx = FindSpecificMsgIndex(specific_msg);
       25: 1516:		    if (specific_idx >= 0) {
       25: 1517:			specific_fmt = specific_err_msgs[specific_idx].long_name;
        -: 1518:		    }
        -: 1519:		    else {
    #####: 1520:			specific_fmt = specific_msg;
        -: 1521:		    }
        -: 1522:#else
        -: 1523:			specific_fmt = specific_msg;
        -: 1524:#endif
       25: 1525:		    MPIU_Snprintf( user_ring_msg, sizeof(user_ring_msg),
        -: 1526:				   specific_fmt, user_error_code );
        -: 1527:		}
        -: 1528:		else {
    #####: 1529:		    user_ring_msg[0] = 0;
        -: 1530:		}
        -: 1531:	    }
    10053: 1532:	    err_code |= (generic_idx + 1) << ERROR_GENERIC_SHIFT;
        -: 1533:	}
        -: 1534:	else
        -: 1535:	{
        -: 1536:	    /* TODO: lookup index for class error message */
    #####: 1537:	    err_code &= ~ERROR_GENERIC_MASK;
        -: 1538:	    
        -: 1539:#           ifdef MPICH_DBG_OUTPUT
        -: 1540:	    {
        -: 1541:		if (generic_msg[0] == '*' && generic_msg[1] == '*')
        -: 1542:		{
        -: 1543:		    /* FIXME : Internal error.  Generate some debugging 
        -: 1544:		       information; Fix for the general release */
        -: 1545:		    fprintf( stderr, "Could not find %s in list of messages\n", generic_msg );
        -: 1546:		}
        -: 1547:	    }
        -: 1548:#           endif
        -: 1549:	}
        -: 1550:    }
        -: 1551:#   endif
        -: 1552:
        -: 1553:    /* Handle the instance-specific part of the error message */
        -: 1554:#   if MPICH_ERROR_MSG_LEVEL == MPICH_ERROR_MSG_ALL
        -: 1555:    {
        -: 1556:	int specific_idx;
    10053: 1557:	const char * specific_fmt = 0;
    10053: 1558:	int  ring_idx, ring_seq=0;
        -: 1559:	char * ring_msg;
        -: 1560:	
    10053: 1561:	error_ring_mutex_lock();
        -: 1562:	{
        -: 1563:	    /* Get the next entry in the ring; keep track of what part of the 
        -: 1564:	       ring is in use (max_error_ring_loc) */
    10053: 1565:	    ring_idx = error_ring_loc++;
    10053: 1566:	    if (error_ring_loc >= MAX_ERROR_RING) 
       48: 1567:		error_ring_loc %= MAX_ERROR_RING;
    10053: 1568:	    if (error_ring_loc > max_error_ring_loc)
     4243: 1569:		max_error_ring_loc = error_ring_loc;
        -: 1570:	
    10053: 1571:	    ring_msg = ErrorRing[ring_idx].msg;
        -: 1572:
    10053: 1573:	    if (specific_msg != NULL)
        -: 1574:	    {
     9486: 1575:		specific_idx = FindSpecificMsgIndex(specific_msg);
     9486: 1576:		if (specific_idx >= 0)
        -: 1577:		{
     9486: 1578:		    specific_fmt = specific_err_msgs[specific_idx].long_name;
        -: 1579:		}
        -: 1580:		else
        -: 1581:		{
    #####: 1582:		    specific_fmt = specific_msg;
        -: 1583:		}
        -: 1584:		/* See the code above for handling user errors */
     9486: 1585:		if (!use_user_error_code) {
     9461: 1586:		    vsnprintf_mpi( ring_msg, MPIR_MAX_ERROR_LINE, 
        -: 1587:				   specific_fmt, Argp );
        -: 1588:		}
        -: 1589:		else {
       25: 1590:		    MPIU_Strncpy( ring_msg, user_ring_msg, MPIR_MAX_ERROR_LINE );
        -: 1591:		}
        -: 1592:	    }
      567: 1593:	    else if (generic_idx >= 0)
        -: 1594:	    {
      567: 1595:		MPIU_Strncpy( ring_msg,generic_err_msgs[generic_idx].long_name,
        -: 1596:			      MPIR_MAX_ERROR_LINE );
        -: 1597:	    }
        -: 1598:	    else
        -: 1599:	    {
    #####: 1600:		MPIU_Strncpy( ring_msg, generic_msg, MPIR_MAX_ERROR_LINE );
        -: 1601:	    }
        -: 1602:
    10053: 1603:	    ring_msg[MPIR_MAX_ERROR_LINE] = '\0';
        -: 1604:	
        -: 1605:	    /* Get the ring sequence number and set the ring id */
    10053: 1606:	    ErrcodeCreateID( error_class, generic_idx, ring_msg, 
        -: 1607:			     &ErrorRing[ring_idx].id, &ring_seq );
        -: 1608:	    /* Set the previous code. */
    10053: 1609:	    ErrorRing[ring_idx].prev_error = lastcode;
        -: 1610:
        -: 1611:	    /* */
    10053: 1612:	    if (use_user_error_code)
        -: 1613:	    {
       25: 1614:		ErrorRing[ring_idx].use_user_error_code = 1;
       25: 1615:		ErrorRing[ring_idx].user_error_code     = user_error_code;
        -: 1616:	    }
    10028: 1617:	    else if (lastcode != MPI_SUCCESS)
        -: 1618:	    {
        -: 1619:		int last_ring_idx;
        -: 1620:		int last_ring_id;
        -: 1621:		int last_generic_idx;
        -: 1622:
     2070: 1623:		if (convertErrcodeToIndexes( lastcode, &last_ring_idx, 
        -: 1624:					     &last_ring_id,
        -: 1625:					     &last_generic_idx ) != 0) {
    #####: 1626:		    MPIU_Error_printf( 
        -: 1627:		  "Invalid error code (%d) (error ring index %d invalid)\n", 
        -: 1628:		  lastcode, last_ring_idx );
        -: 1629:		}
        -: 1630:		else {
     2070: 1631:		    if (last_generic_idx >= 0 && 
        -: 1632:			ErrorRing[last_ring_idx].id == last_ring_id) {
     2068: 1633:			if (ErrorRing[last_ring_idx].use_user_error_code) {
       36: 1634:			    ErrorRing[ring_idx].use_user_error_code = 1;
       36: 1635:			    ErrorRing[ring_idx].user_error_code = 
        -: 1636:				ErrorRing[last_ring_idx].user_error_code;
        -: 1637:			}
        -: 1638:		    }
        -: 1639:		}
        -: 1640:	    }
        -: 1641:
    10053: 1642:	    if (fcname != NULL)
        -: 1643:	    {
    10053: 1644:		MPIU_Snprintf(ErrorRing[ring_idx].location, MAX_LOCATION_LEN, "%s(%d)", fcname, line);
    10053: 1645:		ErrorRing[ring_idx].location[MAX_LOCATION_LEN] = '\0';
        -: 1646:	    }
        -: 1647:	    else
        -: 1648:	    {
    #####: 1649:		ErrorRing[ring_idx].location[0] = '\0';
        -: 1650:	    }
        -: 1651:	}
    10053: 1652:	error_ring_mutex_unlock();
        -: 1653:
    10053: 1654:	err_code |= ring_idx << ERROR_SPECIFIC_INDEX_SHIFT;
    10053: 1655:	err_code |= ring_seq << ERROR_SPECIFIC_SEQ_SHIFT;
        -: 1656:
        -: 1657:    }
        -: 1658:#   endif
        -: 1659:
    10053: 1660:    if (fatal || MPIR_Err_is_fatal(lastcode))
        -: 1661:    {
        6: 1662:	err_code |= ERROR_FATAL_MASK;
        -: 1663:    }
        -: 1664:    
    10053: 1665:    return err_code;
        -: 1666:}
        -: 1667:
        -: 1668:/* Append an error code, error2, to the end of a list of messages in the error
        -: 1669:   ring whose head endcoded in error1_code.  An error code pointing at the
        -: 1670:   combination is returned.  If the list of messages does not terminate cleanly
        -: 1671:   (i.e. ring wrap has occurred), then the append is not performed. and error1
        -: 1672:   is returned (although it may include the class of error2 if the class of
        -: 1673:   error1 was MPI_ERR_OTHER). */
        -: 1674:int MPIR_Err_combine_codes(int error1, int error2)
    #####: 1675:{
    #####: 1676:    int error1_code = error1;
    #####: 1677:    int error2_code = error2;
        -: 1678:    int error2_class;
        -: 1679:    
    #####: 1680:    if (error2_code == MPI_SUCCESS) return error1_code;
    #####: 1681:    if (error2_code & ERROR_DYN_MASK) return error2_code;
    #####: 1682:    if (error1_code == MPI_SUCCESS) return error2_code;
        -: 1683:	    
    #####: 1684:    error2_class = MPIR_ERR_GET_CLASS(error2_code);
    #####: 1685:    if (MPIR_ERR_GET_CLASS(error2_class) < MPI_SUCCESS ||
        -: 1686:	MPIR_ERR_GET_CLASS(error2_class) > MPICH_ERR_LAST_CLASS)
        -: 1687:    {
    #####: 1688:	error2_class = MPI_ERR_OTHER;
        -: 1689:    }
        -: 1690:
        -: 1691:#   if MPICH_ERROR_MSG_LEVEL >= MPICH_ERROR_MSG_ALL
        -: 1692:    {
        -: 1693:	int error_code;
        -: 1694:
    #####: 1695:	error_code = error1_code;
        -: 1696:	
    #####: 1697:	error_ring_mutex_lock();
        -: 1698:	{
        -: 1699:	    for (;;)
        -: 1700:	    {
        -: 1701:		int error_class;
        -: 1702:		int ring_idx;
        -: 1703:		int ring_id;
        -: 1704:		int generic_idx;
        -: 1705:		
    #####: 1706:		if (convertErrcodeToIndexes(error_code, &ring_idx, &ring_id,
        -: 1707:		    &generic_idx) != 0 || generic_idx < 0 ||
        -: 1708:		    ErrorRing[ring_idx].id != ring_id)
        -: 1709:		{
        -: 1710:		    break;
        -: 1711:		}
        -: 1712:
    #####: 1713:		error_code = ErrorRing[ring_idx].prev_error;
        -: 1714:
    #####: 1715:		if (error_code == MPI_SUCCESS)
        -: 1716:		{
    #####: 1717:		    ErrorRing[ring_idx].prev_error = error2;
    #####: 1718:		    break;
        -: 1719:		}
        -: 1720:		
    #####: 1721:		error_class = MPIR_ERR_GET_CLASS(error_code);
        -: 1722:		
    #####: 1723:		if (error_class == MPI_ERR_OTHER)
        -: 1724:		{
    #####: 1725:		    ErrorRing[ring_idx].prev_error &= ~(ERROR_CLASS_MASK);
    #####: 1726:		    ErrorRing[ring_idx].prev_error |= error2_class;
        -: 1727:		}
        -: 1728:	    }
        -: 1729:	}
    #####: 1730:	error_ring_mutex_unlock();
        -: 1731:    }
        -: 1732:#   endif
        -: 1733:
    #####: 1734:    if (MPIR_ERR_GET_CLASS(error1_code) == MPI_ERR_OTHER)
        -: 1735:    {
    #####: 1736:	error1_code = (error1_code & ~(ERROR_CLASS_MASK)) | error2_class;
        -: 1737:    }
        -: 1738:
    #####: 1739:    return error1_code;
        -: 1740:}
        -: 1741:
        -: 1742:
        -: 1743:/* ------------------------------------------------------------------------- */
        -: 1744:/* Manage the error reporting stack                                          */
        -: 1745:/* ------------------------------------------------------------------------- */
        -: 1746:/* FIXME: This flag wasn't documented in the release specs, and in any
        -: 1747:   event shouldn't be controlled through source-code changes (i.e.,
        -: 1748:   make it either a configure option or a runtime option) */
        -: 1749:/* turn this flag on until we debug and release mpich2 */
        -: 1750:static int MPIR_Err_print_stack_flag = TRUE;
        -: 1751:static int MPIR_Err_chop_error_stack = FALSE;
        -: 1752:static int MPIR_Err_chop_width = 80;
        -: 1753:
        -: 1754:static void MPIR_Err_stack_init( void )
     4383: 1755:{
     4383: 1756:    int n, rc, mpi_errno = MPI_SUCCESS;
        -: 1757:    
     4383: 1758:    error_ring_mutex_create(&mpi_errno);
     4383: 1759:    MPIR_Err_chop_error_stack = FALSE;
        -: 1760:    
     4383: 1761:    rc = MPIU_GetEnvBool( "MPICH_PRINT_ERROR_STACK", 
        -: 1762:			  &MPIR_Err_print_stack_flag );
        -: 1763:    
     4383: 1764:    rc = MPIU_GetEnvInt( "MPICH_CHOP_ERROR_STACK", &n );
     4383: 1765:    if (rc == 1) {
        -: 1766:#ifdef HAVE_WINDOWS_H
        -: 1767:	/* If windows, set the default width to the window size */
        -: 1768:	HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
        -: 1769:	if (hConsole != INVALID_HANDLE_VALUE)
        -: 1770:	{
        -: 1771:	    CONSOLE_SCREEN_BUFFER_INFO info;
        -: 1772:	    if (GetConsoleScreenBufferInfo(hConsole, &info))
        -: 1773:	    {
        -: 1774:		MPIR_Err_chop_width = info.dwMaximumWindowSize.X;
        -: 1775:	    }
        -: 1776:	}
        -: 1777:#endif
    #####: 1778:	if (n > 0) {
    #####: 1779:	    MPIR_Err_chop_error_stack = TRUE;
    #####: 1780:	    MPIR_Err_chop_width = n;
        -: 1781:	}
    #####: 1782:	else if (n == 0) {
        -: 1783:	    /* Use the default width */
    #####: 1784:	    MPIR_Err_chop_error_stack = TRUE;
        -: 1785:	}
        -: 1786:    }
     4383: 1787:}
        -: 1788:
        -: 1789:/**/
        -: 1790:/* Given an error code, print the stack of messages corresponding to this
        -: 1791:   error code. */
        -: 1792:void MPIR_Err_print_stack(FILE * fp, int errcode)
    #####: 1793:{
    #####: 1794:    error_ring_mutex_lock();
        -: 1795:    {
    #####: 1796:	while (errcode != MPI_SUCCESS) {
        -: 1797:	    int ring_idx;
        -: 1798:	    int ring_id;
        -: 1799:	    int generic_idx;
        -: 1800:	    
    #####: 1801:	    if (convertErrcodeToIndexes( errcode, &ring_idx, &ring_id,
        -: 1802:					 &generic_idx ) != 0) {
    #####: 1803:		MPIU_Error_printf( 
        -: 1804:		    "Invalid error code (%d) (error ring index %d invalid)\n", 
        -: 1805:		    errcode, ring_idx );
    #####: 1806:		break;
        -: 1807:	    }
        -: 1808:	    
    #####: 1809:	    if (generic_idx < 0)
        -: 1810:	    {
    #####: 1811:		break;
        -: 1812:	    }
        -: 1813:	    
    #####: 1814:	    if (ErrorRing[ring_idx].id == ring_id)
        -: 1815:	    {
    #####: 1816:		fprintf(fp, "%s: %s\n", ErrorRing[ring_idx].location, 
        -: 1817:			ErrorRing[ring_idx].msg);
    #####: 1818:		errcode = ErrorRing[ring_idx].prev_error;
        -: 1819:	    }
        -: 1820:	    else
        -: 1821:	    {
    #####: 1822:		break;
        -: 1823:	    }
        -: 1824:	}
        -: 1825:    }
    #####: 1826:    error_ring_mutex_unlock();
        -: 1827:	
        -: 1828:    /* FIXME: This is wrong.  The only way that you can get here without
        -: 1829:       errcode beign MPI_SUCCESS is if there is an error in the 
        -: 1830:       processing of the error codes.  Dropping through into the next
        -: 1831:       level of code (particularly when that code doesn't check for 
        -: 1832:       valid error codes!) is erroneous */
    #####: 1833:    if (errcode == MPI_SUCCESS)
        -: 1834:    {
    #####: 1835:	goto fn_exit;
        -: 1836:    }
        -: 1837:
        -: 1838:    {
        -: 1839:	int generic_idx;
        -: 1840:		    
    #####: 1841:	generic_idx = ((errcode & ERROR_GENERIC_MASK) >> ERROR_GENERIC_SHIFT) - 1;
        -: 1842:	
    #####: 1843:	if (generic_idx >= 0)
        -: 1844:	{
    #####: 1845:	    fprintf(fp, "(unknown)(): %s\n", generic_err_msgs[generic_idx].long_name);
    #####: 1846:	    goto fn_exit;
        -: 1847:	}
        -: 1848:    }
        -: 1849:    
        -: 1850:    {
        -: 1851:	int error_class;
        -: 1852:
    #####: 1853:	error_class = ERROR_GET_CLASS(errcode);
        -: 1854:	
    #####: 1855:	if (error_class <= MPICH_ERR_LAST_CLASS)
        -: 1856:	{
    #####: 1857:	    fprintf(fp, "(unknown)(): %s\n", get_class_msg(ERROR_GET_CLASS(errcode)));
        -: 1858:	}
        -: 1859:	else
        -: 1860:	{
        -: 1861:	    /* FIXME: Not internationalized */
    #####: 1862:	    fprintf(fp, "Error code contains an invalid class (%d)\n", error_class);
        -: 1863:	}
        -: 1864:    }
        -: 1865:    
        -: 1866:  fn_exit:
        -: 1867:    return;
        -: 1868:}
        -: 1869:
        -: 1870:/* FIXME: Shouldn't str be const char * ? */
        -: 1871:static void MPIR_Err_print_stack_string(int errcode, char *str, int maxlen )
     1035: 1872:{
     1035: 1873:    char *str_orig = str;
        -: 1874:    int len;
        -: 1875:
     1035: 1876:    error_ring_mutex_lock();
        -: 1877:    {
        -: 1878:	/* Find the longest fcname in the stack */
     1035: 1879:	int max_location_len = 0;
     1035: 1880:	int tmp_errcode = errcode;
     4100: 1881:	while (tmp_errcode != MPI_SUCCESS) {
        -: 1882:	    int ring_idx;
        -: 1883:	    int ring_id;
        -: 1884:	    int generic_idx;
        -: 1885:	    
     2030: 1886:	    if (convertErrcodeToIndexes( tmp_errcode, &ring_idx, &ring_id,
        -: 1887:					 &generic_idx ) != 0) {
    #####: 1888:		MPIU_Error_printf( 
        -: 1889:		    "Invalid error code (%d) (error ring index %d invalid)\n", 
        -: 1890:		    errcode, ring_idx );
    #####: 1891:		break;
        -: 1892:	    }
        -: 1893:
     2030: 1894:	    if (generic_idx < 0) {
    #####: 1895:		break;
        -: 1896:	    }
        -: 1897:	    
     2030: 1898:	    if (ErrorRing[ring_idx].id == ring_id) {
     2030: 1899:		len = (int)strlen(ErrorRing[ring_idx].location);
     2030: 1900:		max_location_len = MPIR_MAX(max_location_len, len);
     2030: 1901:		tmp_errcode = ErrorRing[ring_idx].prev_error;
        -: 1902:	    }
        -: 1903:	    else
        -: 1904:	    {
    #####: 1905:		break;
        -: 1906:	    }
        -: 1907:	}
     1035: 1908:	max_location_len += 2; /* add space for the ": " */
        -: 1909:	/* print the error stack */
     4100: 1910:	while (errcode != MPI_SUCCESS) {
        -: 1911:	    int ring_idx;
        -: 1912:	    int ring_id;
        -: 1913:	    int generic_idx;
        -: 1914:	    int i;
        -: 1915:	    char *cur_pos;
        -: 1916:	    
     2030: 1917:	    if (convertErrcodeToIndexes( errcode, &ring_idx, &ring_id,
        -: 1918:					 &generic_idx ) != 0) {
    #####: 1919:		MPIU_Error_printf( 
        -: 1920:		    "Invalid error code (%d) (error ring index %d invalid)\n", 
        -: 1921:		    errcode, ring_idx );
        -: 1922:	    }
        -: 1923:	    
     2030: 1924:	    if (generic_idx < 0)
        -: 1925:	    {
    #####: 1926:		break;
        -: 1927:	    }
        -: 1928:	    
     2030: 1929:	    if (ErrorRing[ring_idx].id == ring_id) {
        -: 1930:		int nchrs;
     2030: 1931:		MPIU_Snprintf(str, maxlen, "%s", ErrorRing[ring_idx].location);
     2030: 1932:		len     = (int)strlen(str);
     2030: 1933:		maxlen -= len;
     2030: 1934:		str    += len;
     2030: 1935:		nchrs   = max_location_len - 
        -: 1936:		    (int)strlen(ErrorRing[ring_idx].location) - 2;
     5921: 1937:		while (nchrs > 0 && maxlen > 0) {
     1861: 1938:		    *str++ = '.';
     1861: 1939:		    nchrs--;
     1861: 1940:		    maxlen--;
        -: 1941:		}
     2030: 1942:		if (maxlen > 0) {
     2030: 1943:		    *str++ = ':';
     2030: 1944:		    maxlen--;
        -: 1945:		}
     2030: 1946:		if (maxlen > 0) {
     2030: 1947:		    *str++ = ' ';
     2030: 1948:		    maxlen--;
        -: 1949:		}
        -: 1950:		
     2030: 1951:		if (MPIR_Err_chop_error_stack)
        -: 1952:		{
    #####: 1953:		    cur_pos = ErrorRing[ring_idx].msg;
    #####: 1954:		    len = (int)strlen(cur_pos);
    #####: 1955:		    if (len == 0 && maxlen > 0) {
    #####: 1956:			*str++ = '\n';
    #####: 1957:			maxlen--;
        -: 1958:		    }
    #####: 1959:		    while (len)
        -: 1960:		    {
    #####: 1961:			if (len >= MPIR_Err_chop_width - max_location_len)
        -: 1962:			{
    #####: 1963:			    if (len > maxlen)
    #####: 1964:				break;
        -: 1965:			    /* FIXME: Don't use Snprint to append a string ! */
    #####: 1966:			    MPIU_Snprintf(str, MPIR_Err_chop_width - 1 - max_location_len, "%s", cur_pos);
    #####: 1967:			    str[MPIR_Err_chop_width - 1 - max_location_len] = '\n';
    #####: 1968:			    cur_pos += MPIR_Err_chop_width - 1 - max_location_len;
    #####: 1969:			    str += MPIR_Err_chop_width - max_location_len;
    #####: 1970:			    maxlen -= MPIR_Err_chop_width - max_location_len;
    #####: 1971:			    if (maxlen < max_location_len)
    #####: 1972:				break;
    #####: 1973:			    for (i=0; i<max_location_len; i++)
        -: 1974:			    {
    #####: 1975:				MPIU_Snprintf(str, maxlen, " ");
    #####: 1976:				maxlen--;
    #####: 1977:				str++;
        -: 1978:			    }
    #####: 1979:			    len = (int)strlen(cur_pos);
        -: 1980:			}
        -: 1981:			else
        -: 1982:			{
    #####: 1983:			    MPIU_Snprintf(str, maxlen, "%s\n", cur_pos);
    #####: 1984:			    len = (int)strlen(str);
    #####: 1985:			    maxlen -= len;
    #####: 1986:			    str += len;
    #####: 1987:			    len = 0;
        -: 1988:			}
        -: 1989:		    }
        -: 1990:		}
        -: 1991:		else
        -: 1992:		{
     2030: 1993:		    MPIU_Snprintf(str, maxlen, "%s\n", ErrorRing[ring_idx].msg);
     2030: 1994:		    len = (int)strlen(str);
     2030: 1995:		    maxlen -= len;
     2030: 1996:		    str += len;
        -: 1997:		}
     2030: 1998:		errcode = ErrorRing[ring_idx].prev_error;
        -: 1999:	    }
        -: 2000:	    else
        -: 2001:	    {
    #####: 2002:		break;
        -: 2003:	    }
        -: 2004:	}
        -: 2005:    }
     1035: 2006:    error_ring_mutex_unlock();
        -: 2007:
     1035: 2008:    if (errcode == MPI_SUCCESS)
        -: 2009:    {
     1035: 2010:	goto fn_exit;
        -: 2011:    }
        -: 2012:
        -: 2013:    /* FIXME: The following code is broken as described above (if the errcode
        -: 2014:       is not valid, then this code is just going to cause more problems) */
        -: 2015:    {
        -: 2016:	int generic_idx;
        -: 2017:	
    #####: 2018:	generic_idx = ((errcode & ERROR_GENERIC_MASK) >> ERROR_GENERIC_SHIFT) - 1;
        -: 2019:	
    #####: 2020:	if (generic_idx >= 0)
        -: 2021:	{
        -: 2022:	    const char *p;
        -: 2023:	    /* FIXME: (Here and elsewhere)  Make sure any string is
        -: 2024:	       non-null before you use it */
    #####: 2025:	    p = generic_err_msgs[generic_idx].long_name;
    #####: 2026:	    if (!p) { p = "<NULL>"; }
    #####: 2027:	    MPIU_Snprintf(str, maxlen, "(unknown)(): %s\n", p );
    #####: 2028:	    len = (int)strlen(str);
    #####: 2029:	    maxlen -= len;
    #####: 2030:	    str += len;
    #####: 2031:	    goto fn_exit;
        -: 2032:	}
        -: 2033:    }
        -: 2034:    
        -: 2035:    {
        -: 2036:	int error_class;
        -: 2037:
    #####: 2038:	error_class = ERROR_GET_CLASS(errcode);
        -: 2039:	
    #####: 2040:	if (error_class <= MPICH_ERR_LAST_CLASS)
        -: 2041:	{
    #####: 2042:	    MPIU_Snprintf(str, maxlen, "(unknown)(): %s\n", 
        -: 2043:			  get_class_msg(ERROR_GET_CLASS(errcode)));
    #####: 2044:	    len = (int)strlen(str);
    #####: 2045:	    maxlen -= len;
    #####: 2046:	    str += len;
        -: 2047:	}
        -: 2048:	else
        -: 2049:	{
        -: 2050:	    /* FIXME: Not internationalized */
    #####: 2051:	    MPIU_Snprintf(str, maxlen, 
        -: 2052:			  "Error code contains an invalid class (%d)\n",
        -: 2053:			  error_class);
    #####: 2054:	    len = (int)strlen(str);
    #####: 2055:	    maxlen -= len;
    #####: 2056:	    str += len;
        -: 2057:	}
        -: 2058:    }
        -: 2059:    
     1035: 2060: fn_exit:
     1035: 2061:    if (str_orig != str)
        -: 2062:    {
     1035: 2063:	str--;
     1035: 2064:	*str = '\0';
        -: 2065:    }
        -: 2066:    return;
        -: 2067:}
        -: 2068:
        -: 2069:/* FIXME: Remove the bogus fn argument from all uses of this routine */
        -: 2070:static int ErrGetInstanceString( int errorcode, char *msg, int num_remaining, 
        -: 2071:				 MPIR_Err_get_class_string_func_t fn ATTRIBUTE((unused)) )
     1035: 2072:{
        -: 2073:    int len;
        -: 2074:
     1035: 2075:    if (MPIR_Err_print_stack_flag) {
     1035: 2076:	MPIU_Strncpy(msg, ", error stack:\n", num_remaining);
     1035: 2077:	msg[num_remaining - 1] = '\0';
     1035: 2078:	len = (int)strlen(msg);
     1035: 2079:	msg += len;
     1035: 2080:	num_remaining -= len;
        -: 2081:	/* note: this took the "fn" arg, but that appears to be unused
        -: 2082:	 and is undocumented.  */
     1035: 2083:	MPIR_Err_print_stack_string(errorcode, msg, num_remaining);
     1035: 2084:	msg[num_remaining - 1] = '\0';
        -: 2085:    }
        -: 2086:    else {
    #####: 2087:	error_ring_mutex_lock();
        -: 2088:	{
    #####: 2089:	    while (errorcode != MPI_SUCCESS) {
        -: 2090:		int ring_idx;
        -: 2091:		int ring_id;
        -: 2092:		int generic_idx;
        -: 2093:		
    #####: 2094:		if (convertErrcodeToIndexes( errorcode, &ring_idx, 
        -: 2095:					     &ring_id,
        -: 2096:					     &generic_idx ) != 0) {
    #####: 2097:		    MPIU_Error_printf( 
        -: 2098:	      "Invalid error code (%d) (error ring index %d invalid)\n", 
        -: 2099:	      errorcode, ring_idx );
    #####: 2100:		    break;
        -: 2101:		}
        -: 2102:		
    #####: 2103:		if (generic_idx < 0) {
    #####: 2104:		    break;
        -: 2105:		}
        -: 2106:		
    #####: 2107:		if (ErrorRing[ring_idx].id == ring_id) {
        -: 2108:		    /* just keep clobbering old values until the 
        -: 2109:		       end of the stack is reached */
    #####: 2110:		    MPIU_Snprintf(msg, num_remaining, ", %s", 
        -: 2111:				  ErrorRing[ring_idx].msg);
    #####: 2112:		    msg[num_remaining - 1] = '\0';
    #####: 2113:		    errorcode = ErrorRing[ring_idx].prev_error;
        -: 2114:		}
        -: 2115:		else {
    #####: 2116:		    break;
        -: 2117:		}
        -: 2118:	    }
        -: 2119:	}
    #####: 2120:	error_ring_mutex_unlock();
        -: 2121:    }
        -: 2122:    /* FIXME: How do we determine that we failed to unwind the stack? */
     1035: 2123:    if (errorcode != MPI_SUCCESS) return 1;
        -: 2124:
    #####: 2125:    return 0;
        -: 2126:}
        -: 2127:#endif