//  Copyright 2006 Hewlett-Packard Development Company, L.P.
//
//  An example of using $dclexh, and an exit handler.
//
//  Author: Stephen Hoffman, HP OpenVMS Engineering
//
#include <lib$routines.h>
#include <ssdef.h>
#include <stddef.h>
#include <stdio.h>
#include <starlet.h>
#include <stsdef.h>

/* 
// Declare the Exit control block 
*/

main() 
  {
  int ExitHandlerRtn( int *, int );
  unsigned int RetStat;
  /*
  //  Declare the variables used by the exit handler.
  //  Because of the environment the exit handler is
  //  invoked in, the use of static variables or other
  //  (non-stack local) storage is required.
  */
  static unsigned int ConditionValue;
  static struct ECB
    {
    unsigned int *Reserved;
    int (*HandlerRtn)(int *, int);
    unsigned int ArgCount;
    unsigned int *CondVal;
    unsigned int ApplVal;
    } ExitControlBlock;

  /* 
  //  The following initializes the exit control block.
  //  The initialization of the argument count cell be 
  //  easily replaced by an explicit specification of 2
  //  (as only the CondVal and ApplVal longwords exist),
  //  but the calculation accounts (transparently) for 
  //  any user arguments added or removed from the end 
  //  of the block.  The minimum value for the argument
  //  count is 1 longword, for the CondVal pointer...
  //  ApplVal is initialized with a random value...
  */
  ExitControlBlock.Reserved = NULL;
  ExitControlBlock.HandlerRtn = ExitHandlerRtn;
  ExitControlBlock.ArgCount = ((sizeof( ExitControlBlock ) - 
    offsetof( struct ECB, CondVal )) / sizeof( int ));
  ExitControlBlock.CondVal = &ConditionValue;
  ExitControlBlock.ApplVal = 303147;
  
  /*
  // Now declare the exit handler routine.
  */
  RetStat = sys$dclexh( &ExitControlBlock );
  if (!$VMS_STATUS_SUCCESS( RetStat ))
    return RetStat;

  /*
  //  Now exit...  
  //  (We should not get to the return statement...)
  */
  RetStat = sys$exit( SS$_NORMAL );
  return RetStat;
  }

/*
//  Now for the exit handler routine.  This shows the one
//  value that is always passed, plus another value that
//  is application specific -- application-specific values
//  can be created by incrementing the argument count and 
//  lengthening the exit control block.
*/
int ExitHandlerRtn( int *CondVal, int ApplVal ) 
  {
  printf("The exit handler is running...\n");
  printf("The condition value is: ...... %d\n", *CondVal );
  printf("A user-specified value is: ... %d\n", ApplVal );
  return SS$_NORMAL;
  }

