#!/bin/ksh93
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
# 61haes_r714 src/43haes/lib/ksh93/log_entry.sh 1.3 
#  
# Licensed Materials - Property of IBM 
#  
# Restricted Materials of IBM 
#  
# COPYRIGHT International Business Machines Corp. 2012 
# All Rights Reserved 
#  
# US Government Users Restricted Rights - Use, duplication or 
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
#  
# IBM_PROLOG_END_TAG 

##############################################################################
#
# Name: log_entry
#
# Description:
#
#     This file is intended to be sourced in, not directly executed. At the
#     top of the file/function that you want to add tracing support to,
#     insert something like this:
#
#         . /usr/es/lib/ksh93/log_entry "$0()" $CL
#
# Inputs:
#
#     LE_FN  The name of the function being entered. For a file, "$0". For
#            a function, "$0()".
#
#     LE_INV_LINE   The line number from the *previous* function, that invoked
#                   the function being entered (i.e. the function name in
#                   "$fn"). This is optional, but helps make the call stack
#                   more useful.
#
#                   As an alternative to passing in the value as an argument,
#                   to your functions, it can also be passed in via the
#                   environment variable "CL". This is a bit less invasive for
#                   existing code. In order to make this work, the "CL"
#                   variable from the example must be passed in to the function
#                   that is being traced. So for example, if I am invoking
#                   function "bb()" from function "aa()", in "aa()" I would do
#                   this:
#
#                       CL=$LINENO bb
#
#     LE_MIN_TRC    The minimum CLMGR_LOGGING level which will initiate
#                   tracing.
#
# Outputs:
#
#     There are direct outputs from this function; nothing gets printed to
#     STDOUT/STDERR. However, the side effect of this function is to update
#     the global call stack, "CLMGR_STACK", the PS4 variable, and to invoke
#     tracing (i.e. "set -x") as needed based upon the current value of the
#     "CLMGR_LOGGING" variable.
#
##############################################################################

#===============================================================
# Avoid using this function if it not being called from within
# the clmgr/clvt context. The PS4 format cannot be guaranteed
# in that case, and might get a little... mangled.
#===============================================================
[[ $PS4 != CL@(MGR|VT):* ]] && return

set +x
typeset LE_FN=$1         # The new function that is being entered
typeset LE_INV_LINE=$2   # Line number that the new function was invoked from
typeset -l LE_MIN_TRC=$3 # Minimum tracing level

if [[ $LE_INV_LINE != *([[:space:]]) && \
      $LE_INV_LINE != +([[:digit:]]) && \
      $LE_MIN_TRC == *([[:space:]]) ]]
then
    LE_MIN_TRC=$LE_INV_LINE
    unset LE_INV_LINE
fi
[[ $LE_MIN_TRC == *([[:space:]]) ]] && LE_MIN_TRC="low"

if [[ $LE_INV_LINE == *([[:space:]]) && \
      $CL == +([[:digit:]]) ]]
then
    LE_INV_LINE=$CL
fi
unset CL  # Since this is global (if used), it has to be removed each time

if [[ -n $CLMGR_TMPLOG ]]; then
    if [[ $LE_INV_LINE != +([[:digit:]]) && $0 != */sa/* ]]; then
        print "\nWarning: clmgr internal error (log_entry): missing invoking line number ($0; $LE_FN; $*)\n" >>$CLMGR_TMPLOG
    fi
fi

#=====================================================
: Update the call stack, and the PS4 trace formatter
#=====================================================
[[ -n $LE_INV_LINE ]] && LE_INV_LINE=" at line #$LE_INV_LINE"
if [[ $LE_FN != *([[:space:]]) ]]; then
    CLMGR_STACK=${CLMGR_STACK%%+([[:space:]])}
    if [[ ${CLMGR_STACK##*${NL}} != $LE_FN* ]]; then
        CLMGR_STACK="${CLMGR_STACK}${LE_INV_LINE}${NL}$LE_FN"

        : If we updated the stack, we should update PS4, as well
        print -- "$PS4" |IFS=: read LE_SENTINEL LE_TID LE_RC LE_FUNC LE_REM
        LE_FUNC=${LE_FUNC#*\[}  # Remove old function
        LE_FUNC="${LE_FN}[${LE_FUNC}"  # Insert new function
        PS4="$LE_SENTINEL:$LE_TID:$LE_RC:$LE_FUNC:$LE_REM"
        unset LE_SENTINEL LE_TID LE_RC LE_FUNC LE_REM
    fi

    #=======================
    : Update the FFDC file
    #=======================
    if [[ -n $FFDC_DIR && -d $FFDC_DIR ]]; then
        print "\
=====================
  clmgr Call Stack:
=====================
$CLMGR_STACK" >$FFDC_CS_FILE
    fi
fi

if [[ $CLMGR_LOGGING == @(low|med|high|max) ]]; then
    LE_INV_LINE=${LE_INV_LINE##*\#}
    typeset OUT=$(print -- ${PS4/\$?/0})
    if [[ $LE_FN == *\(\) ]]; then
        OUT=${OUT/\$LINENO/1}
    else
        OUT=${OUT/\$LINENO/$LE_INV_LINE}
    fi
    OUT=${OUT/\$SECONDS/$SECONDS}

    typeset LE_SPACER=$NL
    typeset LE_LAST_LINE=$(/usr/bin/tail -n 1 $CLMGR_ERRLOG)
    [[ $LE_LAST_LINE == +([[:space:]]) ]] && LE_NEED_SPACER=""

    if [[ $LE_FN == *\(\) ]]; then
        print -u2 -- "${LE_SPACER}${OUT}${TAB} ENTERING FUNCTION \"$LE_FN\" at $($HAUTILS/cltime)"
    else
        print -u2 -- "${LE_SPACER}${OUT}${TAB} ENTERING FILE \"$LE_FN\" at $($HAUTILS/cltime)"
    fi
    unset OUT LE_SPACER LE_LAST_LINE

    #if [[ $CLMGR_LOGGING == "med"  && $LE_MIN_TRC == @(low|med)      ]] || \
    #   [[ $CLMGR_LOGGING == "high" && $LE_MIN_TRC == @(low|med|high) ]] || \
    #   [[ $CLMGR_LOGGING == "max" ]]
    if [[ $CLMGR_LOGGING == @(med|high|max) ]]
    then
        unset LE_FN LE_INV_LINE LE_MIN_TRC
        set -x
    else
        unset LE_FN LE_INV_LINE LE_MIN_TRC
    fi
fi
