#include "mysccs.h"
SCCSID("@(#)verbose.c   %E%   SAP   %I%")

static char * this_File GNU_UNUSED = __FILE__;

/************************************************************************/
/* $Id: //tools/src/freeware/gsstest/verbose.c#3 $
 ************************************************************************
 *
 * Copyright (c) 1998-2000  SAP AG.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer. 
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. All advertising materials mentioning features or use of this
 *    software must display the following acknowledgment:
 *    "This product includes software developed by SAP AG"
 *
 * 4. The name "SAP AG" must not be used to endorse or promote products
 *    derived from this software without prior written permission.
 *    For written permission, please contact www.press@sap.com
 *
 * 5. Redistributions of any form whatsoever must retain the following
 *    acknowledgment:
 *    "This product includes software developed by SAP AG"
 *
 * THIS SOFTWARE IS PROVIDED BY SAP AG ``AS IS'' AND ANY EXPRESSED
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. SAP AG SHALL BE LIABLE FOR ANY DAMAGES
 * ARISING OUT OF THE USE OF THIS SOFTWARE ONLY IF CAUSED BY SAP AG'S
 * INTENT OR GROSS NEGLIGENCE. IN CASE SAP AG IS LIABLE UNDER THIS
 * AGREEMENT FOR DAMAGES CAUSED BY SAP AG'S GROSS NEGLIGENCE SAP AG
 * FURTHER SHALL NOT BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT, AND SHALL NOT BE LIABLE IN EXCESS OF THE AMOUNT OF
 * DAMAGES TYPICALLY FORESEEABLE FOR SAP AG, WHICH SHALL IN NO EVENT
 * EXCEED US$ 500.000.- 
 *
 ************************************************************************/


#include "common.h"
#include "verbose.h"

/* global variables */
int      verbose_level         = 0;
int	 there_was_output      = FALSE;
int      show_error_location   = FALSE;
int	 duplicate_to_stdout   = FALSE;
int      sap_constraints_count = 0;

char   * first_message         = NULL;
char   * last_message          = NULL;

/* local variables */

static int     verbose_initialized     = FALSE;
FILE         * outfp[3];

/*****************************************************/
/* OS/390 vfprintf() will consume its va_list object */ 
/* so that we need to vsprintf() into linebuffer[]   */
/* and use fprintf() twice when we want to write     */
/* to both, screen and logfile.			     */
/*****************************************************/
static  char  linebuffer[10240];  

void
verbose_init( int p_level, FILE * p_fp, char * p_filename, int quiet )
{
   char     * where	     = "";
   char     * fmt            = "%s\n";

   verbose_initialized       = TRUE;
   verbose_level             = p_level;

   if ( quiet!=FALSE ) {
      fprintf(stderr, "Sending verbose output to ");
   }

   if ( p_fp==NULL || p_fp==stderr ) {

      vfp   = stderr;
      where = "STDERR";

   } else if ( p_fp==stdout ) {

      vfp   = stdout;
      where = "STDOUT";

   } else {

      vfp   = p_fp;
      where = p_filename;
      fmt   = "file \"%s\"\n";

   }

   outfp[0] = vfp;
   outfp[1] = stdout;
   outfp[2] = NULL;

   if ( quiet!=FALSE ) {
      fprintf( stderr, fmt, where );
      fflush( stderr );
   }

   return;
 
} /* verbose_init() */




void
set_verbose_level( int p_level )
{
   if ( p_level>=0 && p_level<=4 )
      verbose_level = p_level;

} /* set_verbose_level() */



#define DFPRINTF(x)  \
   for( fpc=0 ; (ffp=outfp[fpc])!=NULL ; fpc++ ) {	\
      if ( duplicate_to_stdout==FALSE ) { fpc++; }	\
      fprintf x;					\
   }


#define DVSPRINTF(x)  \
   {							\
      vsprintf x;					\
      for( fpc=0 ; (ffp=outfp[fpc])!=NULL ; fpc++ ) {	\
         if ( duplicate_to_stdout==FALSE ) { fpc++; }	\
         fprintf(ffp, "%s", linebuffer);		\
      }							\
   }


#define DFFLUSH(x) \
   for( fpc=0 ; (ffp=outfp[fpc])!=NULL ; fpc++ ) {	\
      if ( duplicate_to_stdout==FALSE ) { fpc++; }	\
      fflush x;						\
   }


void
verbose_print( veb_class_et p_class, int p_int_arg, ... )
{
   FILE     * ffp;
   int	      fpc;
   va_list    args;
   char     * label;
   char	    * prefix = NULL;
   char       prefix_buf[128];
   char     * fmt1 = NULL;
   char	    * fmt2 = NULL;
   char     * file = "";
   Uint       line = 0;
   int        routine_rc;
   int	      expected_rc;
   int	      section;
   char       rc_string[32];

   if ( vfp==NULL ) {
      checkin_message();
      fprintf(stderr, "WAAA! I don't have a valid FILE * for verbose output!\n");
      abort();
   }

   va_start(args, p_int_arg);

   switch( p_class ) {

      case VEB_CLASS_RESULT:
	 routine_rc  = p_int_arg;
	 expected_rc = (int)    va_arg(args, int);
	 label       = (char *) va_arg(args, char *);
	 sprintf(rc_string, " (rc=%u)", (Uint) routine_rc);
	 checkin_message();
	 DFPRINTF((ffp, "RESULT  %s%s%s%s\n%s",
	    label!=NULL ? label : "",
	    label!=NULL ? "(): " : "",
	    (routine_rc==expected_rc) ? "OK" : "NOT ok",
	    (routine_rc==expected_rc) ? "" : rc_string,
	    (verbose_level>0 || routine_rc>0) ? "-------\n" : ""
	 ));
	 break;

      case VEB_CLASS_SECTION:
	   section = p_int_arg;
	   label   = (char *) va_arg(args, char *);
	   DFPRINTF((ffp,"\n(( %d %s ))\n", section, label));
	   break;
	 
      case VEB_CLASS_ERR:  file   = va_arg(args, char *);
			   line   = va_arg(args, Uint  );
			   if ( show_error_location!=FALSE ) {
			      sprintf(prefix_buf, "%.96s(%u): ERROR: ", file, line);
			      prefix = prefix_buf;
			   } else {
			      prefix = "ERROR: ";
			   }
			   goto print_with_prefix;

      case VEB_CLASS_STATUS: prefix = "Status:  ";	 goto print_with_prefix;
      case VEB_CLASS_TEST: prefix = "TEST: ";		 goto print_with_prefix;
      case VEB_CLASS_BUG:  prefix = "INTERNAL BUG: ";	 goto print_with_prefix;
      case VEB_CLASS_TRIN: prefix = "  ==> ";		 goto print_with_prefix;
      case VEB_CLASS_TIMING: prefix = "  ... ";		 goto print_with_prefix;

      case VEB_CLASS_SAPERR:
			   prefix = "*FAILING* SAP constraint:\n==> ";
			   sap_constraints_count++;	 goto print_with_prefix;

      case VEB_CLASS_TROUT: prefix = "  <== ";

print_with_prefix:
	 checkin_message();
	 if ( prefix!=NULL ) { DFPRINTF((ffp, prefix)); }
	 fmt1  = (char *) va_arg(args, char *);
	 DVSPRINTF((linebuffer, fmt1, args));
	 break;


      default:
	 if ( p_int_arg>0  ) {

	    checkin_message();

	    switch( p_class ) {
	       case VEB_CLASS_OK:					break;
	       case VEB_CLASS_STRING: fmt2 = "\t%.50s =\"%.150s\"\n";	break;
	       case VEB_CLASS_INFO:   DFPRINTF((ffp, "  "));		break;
	       default:		      break;
	    }
   
	    if ( fmt1!=NULL ) {
	       DVSPRINTF((linebuffer, fmt1, args));
	    }

	    if ( fmt2==NULL ) {
	       fmt2 = va_arg( args, char * );
	    }

	    DVSPRINTF((linebuffer, fmt2, args));

	 }

   }

   va_end(args);

   DFFLUSH((ffp));

   return;

} /* verbose_print() */




/*
 * verbose_dupmem()
 *
 *
 */
void *
verbose_dupmem( char * module_name, Uint line_of_code,
	        void * orig_ptr, size_t orig_len,  size_t * new_len )
{
   void * ptr = NULL;
   
   if ( orig_ptr==NULL  ||  orig_len==0 ) {

      (*new_len) = 0;

   } else {

      ptr = malloc( orig_len + 256 );

      if (ptr==NULL) {
	 *new_len = 0;
	 XVEB((V_ERR, "File %s(line %u): malloc(%lu) FAILED: %s\n",
		      module_name, line_of_code,
		      (Ulong) orig_len + 256, strerror(errno) ));
	 return(NULL);
      }

      *new_len = orig_len;
      memset( ptr, 'X', orig_len + 256 );
      memcpy( ptr, orig_ptr, orig_len );

   }

   return(ptr);

} /* verbose_dupmem() */




/*
 * verbose_freemem()
 *
 *
 */
void
verbose_freemem( void ** ptr, size_t * len )
{
   if ( ptr!=NULL && *ptr!=NULL ) {
      if ( len!=NULL && *len!=0 ) {
	 memset( *ptr, 0, *len );
	 *len = 0;
      }
      free( *ptr );
      *ptr = NULL;
   }

   return;

} /* verbose_freemem() */



void
set_enter_leave_messages( char * enter_msg, char * leave_msg )
{
   first_message = enter_msg;
   last_message  = leave_msg;

   return;

} /* set_first_message() */



void
checkin_message( void )
{
   FILE     * ffp;
   int	      fpc;

   if ( there_was_output==FALSE && first_message!=NULL ) {
      DFPRINTF((ffp, "%s", first_message));
   }
   there_was_output = TRUE;

   return;

} /* checkin_message() */



void
checkout_message( void )
{
   FILE     * ffp;
   int	      fpc;

   if ( there_was_output!=FALSE && last_message!=NULL ) {
      DFPRINTF((ffp, "%s", last_message));
   }

   return;

} /* check_leave_message() */
