################################################################################
# TSL-LIBRARY:	EMOS_STD_misc_lib
################################################################################
# Copyright (C) 2000  EMOS Computer Consulting GmbH
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# For further information please contact:
#
#	Dean Rajovic
#	EMOS Computer Consulting GmbH
#	Oskar-Messter-Straße 25
#	85737 Ismaning
#	Germany
#	tel.: +49 89 608 765-0
#	mailto:drajovic@emos.de
#	http://www.emos.de
################################################################################
# $Revision: 1.1.1.1 $
# $Author: drajovic $
# $Date: 2004/03/24 20:14:03 $
# $Archive: /MERCURY/TSL_PROJECTS/EMOS_GPL/STD/emos_std_misc_lib/script $
# $NoKeywords: $
################################################################################

#/***
#*	Contains some general-purpose miscellaneous function that do not seem to 
#*	fit nicely into any other EMOS library. 
#*<p> PUBLIC CONSTANTS:
#*<ul>
#* <li>	ARRSEP</li>
#*</ul>
#*/

static debug = TRUE;

#/**
#* 	Turns debug mode on/off.
#* @param mode (in)		TRUE = turn debug on, else turn debug off
#*/

public function set_debug( in mode )
{
	if ( mode == TRUE )
		debug = TRUE;
	else
		debug = FALSE;
}

#/**
#* 	Returns the debug mode.
#* @return
#*	TRUE = debug mode on
#*	FALSE = debug mode off
#*/

public function is_debug( )
{
	return debug;
}

#/**
#* 	In debug-mode produces a "report_msg" formated as "DEBUG: <code>msg</code>".
#*	Otherwise just returns (no message produced).
#* @param msg (in)	message to be reported in debug mode
#*/

public function debug_msg( in msg )
{
	auto txt;
	if ( !debug )
		return;
	txt = "DEBUG: " & msg;
	report_msg( txt );
}

#/**
#* 	In debug-mode produces a "report_msg" formated as "DEBUG: <code>msg</code>" if debug level >= 2.
#*	Otherwise just returns (no message produced).
#* @param msg (in)	message to be reported in debug mode
#*/

public function debug_msg2( in msg )
{
	auto txt;
	if ( debug < 2 )
		return;
	txt = "DEBUG: " & msg;
	report_msg( txt );
}

#/**
#* Defines the level for loggin call chains. Default=2 --> log short & full calls 
#*/
static log_call_level = 2;

#/**
#* Defines the level for logging call chains.
#* @param level (in)
#*		0 = no call logging;
#*		1 = log only full chains (in case of error);
#*		2 = log full chains and short chains (in case of E_OK)
#*/
public function set_log_call_level ( in level )
{
	log_call_level = level;
}

#/**
#* Returns the level for logging call chains.
#*/
public function get_log_call_level()
{
	return log_call_level;
}

#/**
#* 	Wrapper around GUI_load(). It makes sure that the <code>gui</code> is unloaded first
#*	before the load is attempted (avoids a message). Additionally it produces
#*	a tl_step() message documenting the outcome of invoked GUI_load() function.
#* @param gui (in)		filename/path of a GUI-map to be loaded
#* @return
#*	E_OK:		operation successfull
#*	otherwise:	see return values for GUI_load()
#*/

public function load_GUI ( in gui )
{
	auto rc, msg;
	GUI_unload( gui );
	rc = GUI_load( gui );
	msg = sprintf( "%s [rc=%s]", gui, rc);
	tl_step( "GUI-Map laden", rc, msg );
	return rc;
}

#/**
#* 	Converts a string "Y"/"Yes" or German equivalent "J"/"Ja" 
#*	(case-insensitive!) to boolean. 
#*	This function is particularly useful when reading user input (either
#*	interactivelly or from data-tables).
#*<p> NOTE!
#*	Blanks are trimmed from both sides of <str> before comparison.
#* @param str (in)	string to be evaluated
#* @return
#*	TRUE:		string resambles to "y","yes","j" or "ja"
#*	FALSE:		string resambles to anything else
#*/

public function yes ( in str ) 
{
	return Ja( str );
}

#/**
#* 	Converts a string "Y"/"Yes" or German equivalent "J"/"Ja" 
#*	(case-insensitive!) to boolean. 
#*	This function is particularly useful when reading user input (either
#*	interactivelly or from data-tables).
#*<p> NOTE!
#*	Blanks are trimmed from both sides of <str> before comparison.
#* @param str (in)	string to be evaluated
#* @return
#*	TRUE:		string resambles to "y","yes","j" or "ja"
#*	FALSE:		string resambles to anything else
#*/

public function Ja ( in str ) 
{
	switch ( tolower( strip_both( str ) ) )
	{
	case "j":
	case "ja":
	case "y":
	case "yes":
		return TRUE;
	default:
		return FALSE;
	}
#	return compare_text( jaNein, "ja", "JA", "ja" );	
}

#/**
#* Mercury has managed again to confuse "timeout" amd "timeout_msec".
#* In version 7.00 and 7.01 "timeout_msec" did not work properly.
#* As of Version 7.5 "timeout" does not work any more.
#* The following three variables are used to determine what behavior is currently
#* active on your machine in order to apply the correct logic. 
#*/

static const def_timeout = getvar("timeout_msec" );
static const tmp_timeout = setvar("timeout", 1 );
static const is_timeout_ok = getvar("timeout");
static const restore_timeout = setvar("timeout_msec", def_timeout);

#/**
#* Stores the current timeout value which is used in restore_timeout().
#*/
static timeout = getvar( is_timeout_ok ? "timeout" : "timeout_msec" );

#/**
#* 	Wrapper around setvar("timeout"). It saves the current timeout before
#*	setting it to the new value.
#* @param time (in)	timeout (in seconds) to be set
#*/

public function set_timeout( in time )
{
#printf( "set_timeout(%s)", time );
#printf( "\tbefore=%s", getvar( is_timeout_ok ? "timeout" : "timeout_msec" ) );
	timeout = getvar( is_timeout_ok ? "timeout" : "timeout_msec" );
	setvar( is_timeout_ok ? "timeout" : "timeout_msec", is_timeout_ok ? time : time*1000 );	
#printf( "\t after=%s", getvar( is_timeout_ok ? "timeout" : "timeout_msec" ) );
}

#/**
#* 	Restores the timeout that has been overriden by the last invocation of the
#*	set_timeout() function.
#*/

public function restore_timeout( )
{
#printf( "restore_timeout()" );
#printf( "\tbefore=%s", getvar( is_timeout_ok ? "timeout" : "timeout_msec" ) );
	setvar( is_timeout_ok ? "timeout" : "timeout_msec", timeout );	
#printf( "\t after=%s", getvar( is_timeout_ok ? "timeout" : "timeout_msec" ) );
}

#/**
#* WR has a nice bug with in-operator operating on multi-dimensional
#* arrays. For example <code>for ( i in arr )</code> returns different
#* occasionally returns different separators (mostly pipe | but simetimes
#* something else that appears as bold pipe)
#* With this function we determine the separator dynamically as it seems
#* to stay constant during the single WR invocation.
#*/

static function get_arrsep ()
{
	auto arr[], i;
	arr[0,0] = 0;
	for ( i in arr ) return substr( i, 2, 1 );
}
public const ARRSEP = get_arrsep();



static lastrc=0;

#/**
#* returns !0 if rc == E_OK
#*/

public function pass( in rc )
{
	lastrc=rc;
	return rc==E_OK;
}

#/**
# returns !0 if rc != E_OK
#*/

public function fail( in rc )
{
	lastrc=rc;
	return rc!=E_OK;
}

#/**
#* what was the last error  
#*/

public function getLastRc()
{
	return lastrc;
}

#----------------------------

static pathIdx;
static pathArr[];
#/**
#* Remembers all inquired paths for quicker access.  
#*/
static pathCache[];

static function addPath ( in path )
{
	if( path != "" )
		pathArr[pathIdx++] = path;
}

static function extractPath ( in searchPath )
{
	auto start, end;
	extern RSTART, RLENGTH;
	
	if( start = match( searchPath, "<.*>" ) )
	{
		end = RLENGTH;
		addPath( substr( searchPath, start+1, end-2 ) );
		extractPath( substr( searchPath, 1, start-1 ) );
		extractPath( substr( searchPath, start+end ) );		
	}
	else if( start = match( searchPath, "\".*\"" ) )
	{
		end = RLENGTH;
		addPath( substr( searchPath, start+1, end-2 ) );
		extractPath( substr( searchPath, 1, start-1 ) );
		extractPath( substr( searchPath, start+end ) );		
	}
	else if( end = index( searchPath, " " ) )
	{
		addPath( substr( searchPath, 1, end-1 ) );
		extractPath( substr( searchPath, end+1 ) );
	}
	else
	{
		addPath( searchPath );
	}
}

#/**
#* Returns true if specified test refers to a WinRunner compiled module
#* @param test (in) name of the test
#* @return true if test is the compiled module otherwise false
#*/

public function splitSearchPath ( out outArr[] )
{
	auto path = getvar("searchpath");
	auto i;
	pathIdx = 0;
	for( i in pathArr ) delete pathArr[i];
	extractPath( path );
	for( i in pathArr ) outArr[i] = pathArr[i];
}

# static function test_splitSearchPath ( in path )
# {
# 	auto i;
# 	pathIdx = 0;
# 	for( i in pathArr ) delete pathArr[i];
# 	extractPath( path );
# 	for( i in pathArr ) print pathArr[i];
# }
# test_splitSearchPath( "" );
# test_splitSearchPath( "a" );
# test_splitSearchPath( "a b c" );
# test_splitSearchPath( "<a>" );
# test_splitSearchPath( "<a><b><c>" );
# test_splitSearchPath( "<a> <b> <c>" );
# test_splitSearchPath( "a<b>c" );
# test_splitSearchPath( "a \"b b b\" <c>" );
# test_splitSearchPath( "[TD]a b <[TD]c>" );

#/**
#* Returns true if the given test name refers to a compiled module otherwise
#* false is returned. Search path is taken into account.
#* @param test (in) name of the test
#* @return true if the given test name refers to a compiled module otherwise
#* false
#*/

public function isCompiledModule( in test )
{
	auto pathArr[];
	auto i;
	auto rc;
	auto line;
	auto hdrFile;

	if ( test in pathCache )
		return pathCache[test];

	splitSearchPath( pathArr );
	for( i in pathArr )
	{
		hdrFile = join_path( pathArr[i], test, "\\" ) & "\\header";
		rc = file_open( hdrFile, FO_MODE_READ );
		if ( rc == E_OK )
		{
			while( file_getline( hdrFile, line ) == E_OK )
			{
				if ( match( line, "TYPE=CM" ) )
				{
					file_close( hdrFile );
					pathCache[test] = TRUE;
					return TRUE;
				}
			}
			file_close( hdrFile );
		}
	}
	pathCache[test] = FALSE;
	return FALSE;
}

#/**
#* Creates a new file.
#* @param dir directory name or full path name (second parameter must be empty)
#* @param name filename (if empty, fullpath assumed in first parameter)
#* @return E_OK success, else failire
#*/

public function create_file( in dir, in name )
{
	auto rc;
	auto file;
	if ( nargs() > 1 )
		file = join_path( dir,  name, "\\" );
	else
		file = dir;
	rc = file_open( file, FO_MODE_WRITE );
	file_close( file );
	return rc;
}

################################################################################
# TSL-LIBRARY:	EMOS_STD_misc_lib
################################################################################