<commit_before>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You may
 * obtain a copy of the License at
 * 
 *    http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************/
#include "condor_common.h"
#include "compat_classad.h"

#include "condor_classad.h"
#include "classad_oldnew.h"
#include "condor_attributes.h"
#include "classad/xmlSink.h"
#include "condor_config.h"
#include "Regex.h"
#include "classad/classadCache.h"
#include "env.h"
#include "condor_arglist.h"
#define CLASSAD_USER_MAP_RETURNS_STRINGLIST 1

class MapFile;
extern int reconfig_user_maps();
extern bool user_map_do_mapping(const char * mapname, const char * input, MyString & output);

#if defined(HAVE_DLOPEN)
#include <dlfcn.h>
#endif

using namespace std;

// gcc 4.3.4 doesn't seem to define FLT_MIN on OpenSolaris 2009.06
#if !defined(FLT_MIN) && defined(__FLT_MIN__)
  #define FLT_MIN  __FLT_MIN__
#endif
#if !defined(FLT_MAX) && defined(__FLT_MAX__)
  #define FLT_MAX  __FLT_MAX__
#endif

// Utility to clarify a couple of evaluations
static inline bool
IsStringEnd(const char *str, unsigned off)
{
	return (  (str[off] == '\0') || (str[off] == '\n') || (str[off] == '\r')  );
}

namespace compat_classad {

static StringList ClassAdUserLibs;

static void registerClassadFunctions();
static void classad_debug_dprintf(const char *s);

// The Windows compiler doesn't like this C++11 style of object
// initialization.
#if !defined(WIN32)
classad::References ClassAdPrivateAttrs = { ATTR_CAPABILITY,
		ATTR_CHILD_CLAIM_IDS, ATTR_CLAIM_ID, ATTR_CLAIM_ID_LIST,
		ATTR_CLAIM_IDS, ATTR_PAIRED_CLAIM_ID, ATTR_TRANSFER_KEY };
#else
static const std::string private_attrs[] = { ATTR_CAPABILITY,
		ATTR_CHILD_CLAIM_IDS, ATTR_CLAIM_ID, ATTR_CLAIM_ID_LIST,
		ATTR_CLAIM_IDS, ATTR_PAIRED_CLAIM_ID, ATTR_TRANSFER_KEY };
classad::References ClassAdPrivateAttrs( private_attrs, private_attrs + COUNTOF(private_attrs) );
#endif

bool ClassAd::m_initConfig = false;
bool ClassAd::m_strictEvaluation = false;

void ClassAd::
Reconfig()
{
	m_strictEvaluation = param_boolean( "STRICT_CLASSAD_EVALUATION", false );
	classad::SetOldClassAdSemantics( !m_strictEvaluation );

	classad::ClassAdSetExpressionCaching( param_boolean( "ENABLE_CLASSAD_CACHING", false ) );

	char *new_libs = param( "CLASSAD_USER_LIBS" );
	if ( new_libs ) {
		StringList new_libs_list( new_libs );
		free( new_libs );
		new_libs_list.rewind();
		char *new_lib;
		while ( (new_lib = new_libs_list.next()) ) {
			if ( !ClassAdUserLibs.contains( new_lib ) ) {
				if ( classad::FunctionCall::RegisterSharedLibraryFunctions( new_lib ) ) {
					ClassAdUserLibs.append( new_lib );
				} else {
					dprintf( D_ALWAYS, "Failed to load ClassAd user library %s: %s\n",
							 new_lib, classad::CondorErrMsg.c_str() );
				}
			}
		}
	}

	reconfig_user_maps();

	char *user_python_char = param("CLASSAD_USER_PYTHON_MODULES");
	if (user_python_char)
	{
		std::string user_python(user_python_char);
		free(user_python_char); user_python_char = NULL;
		char *loc_char = param("CLASSAD_USER_PYTHON_LIB");
		if (loc_char && !ClassAdUserLibs.contains(loc_char))
		{
			std::string loc(loc_char);
			if (classad::FunctionCall::RegisterSharedLibraryFunctions(loc.c_str()))
			{
				ClassAdUserLibs.append(loc.c_str());
#if defined(HAVE_DLOPEN)
				void *dl_hdl = dlopen(loc.c_str(), RTLD_LAZY);
				if (dl_hdl) // Not warning on failure as the RegisterSharedLibraryFunctions should have done that.
				{
					void (*registerfn)(void) = (void (*)(void))dlsym(dl_hdl, "Register");
					if (registerfn) {registerfn();}
					dlclose(dl_hdl);
				}
#endif
			}
			else
			{
				dprintf(D_ALWAYS, "Failed to load ClassAd user python library %s: %s\n",
					loc.c_str(), classad::CondorErrMsg.c_str());
			}
		}
		if (loc_char) {free(loc_char);}
	}
	if (!m_initConfig)
	{
		registerClassadFunctions();
		classad::ExprTree::set_user_debug_function(classad_debug_dprintf);
		m_initConfig = true;
	}
}

static classad::MatchClassAd the_match_ad;
static bool the_match_ad_in_use = false;
classad::MatchClassAd *getTheMatchAd( classad::ClassAd *source,
									  classad::ClassAd *target )
{
	ASSERT( !the_match_ad_in_use );
	the_match_ad_in_use = true;

	the_match_ad.ReplaceLeftAd( source );
	the_match_ad.ReplaceRightAd( target );

	if ( !ClassAd::m_strictEvaluation ) {
		source->alternateScope = target;
		target->alternateScope = source;
	}

	return &the_match_ad;
}

void releaseTheMatchAd()
{
	ASSERT( the_match_ad_in_use );

	classad::ClassAd *ad;
	ad = the_match_ad.RemoveLeftAd();
	ad->alternateScope = NULL;
	ad = the_match_ad.RemoveRightAd();
	ad->alternateScope = NULL;

	the_match_ad_in_use = false;
}


static
bool stringListSize_func( const char * /*name*/,
						  const classad::ArgumentList &arg_list,
						  classad::EvalState &state, classad::Value &result )
{
	classad::Value arg0, arg1;
	std::string list_str;
	std::string delim_str = ", ";

	// Must have one or two arguments<commit_msg>Remove redundant setting of alternateScope when matching ClassAds<commit_after>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You may
 * obtain a copy of the License at
 * 
 *    http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************/
#include "condor_common.h"
#include "compat_classad.h"

#include "condor_classad.h"
#include "classad_oldnew.h"
#include "condor_attributes.h"
#include "classad/xmlSink.h"
#include "condor_config.h"
#include "Regex.h"
#include "classad/classadCache.h"
#include "env.h"
#include "condor_arglist.h"
#define CLASSAD_USER_MAP_RETURNS_STRINGLIST 1

class MapFile;
extern int reconfig_user_maps();
extern bool user_map_do_mapping(const char * mapname, const char * input, MyString & output);

#if defined(HAVE_DLOPEN)
#include <dlfcn.h>
#endif

using namespace std;

// gcc 4.3.4 doesn't seem to define FLT_MIN on OpenSolaris 2009.06
#if !defined(FLT_MIN) && defined(__FLT_MIN__)
  #define FLT_MIN  __FLT_MIN__
#endif
#if !defined(FLT_MAX) && defined(__FLT_MAX__)
  #define FLT_MAX  __FLT_MAX__
#endif

// Utility to clarify a couple of evaluations
static inline bool
IsStringEnd(const char *str, unsigned off)
{
	return (  (str[off] == '\0') || (str[off] == '\n') || (str[off] == '\r')  );
}

namespace compat_classad {

static StringList ClassAdUserLibs;

static void registerClassadFunctions();
static void classad_debug_dprintf(const char *s);

// The Windows compiler doesn't like this C++11 style of object
// initialization.
#if !defined(WIN32)
classad::References ClassAdPrivateAttrs = { ATTR_CAPABILITY,
		ATTR_CHILD_CLAIM_IDS, ATTR_CLAIM_ID, ATTR_CLAIM_ID_LIST,
		ATTR_CLAIM_IDS, ATTR_PAIRED_CLAIM_ID, ATTR_TRANSFER_KEY };
#else
static const std::string private_attrs[] = { ATTR_CAPABILITY,
		ATTR_CHILD_CLAIM_IDS, ATTR_CLAIM_ID, ATTR_CLAIM_ID_LIST,
		ATTR_CLAIM_IDS, ATTR_PAIRED_CLAIM_ID, ATTR_TRANSFER_KEY };
classad::References ClassAdPrivateAttrs( private_attrs, private_attrs + COUNTOF(private_attrs) );
#endif

bool ClassAd::m_initConfig = false;
bool ClassAd::m_strictEvaluation = false;

void ClassAd::
Reconfig()
{
	m_strictEvaluation = param_boolean( "STRICT_CLASSAD_EVALUATION", false );
	classad::SetOldClassAdSemantics( !m_strictEvaluation );

	classad::ClassAdSetExpressionCaching( param_boolean( "ENABLE_CLASSAD_CACHING", false ) );

	char *new_libs = param( "CLASSAD_USER_LIBS" );
	if ( new_libs ) {
		StringList new_libs_list( new_libs );
		free( new_libs );
		new_libs_list.rewind();
		char *new_lib;
		while ( (new_lib = new_libs_list.next()) ) {
			if ( !ClassAdUserLibs.contains( new_lib ) ) {
				if ( classad::FunctionCall::RegisterSharedLibraryFunctions( new_lib ) ) {
					ClassAdUserLibs.append( new_lib );
				} else {
					dprintf( D_ALWAYS, "Failed to load ClassAd user library %s: %s\n",
							 new_lib, classad::CondorErrMsg.c_str() );
				}
			}
		}
	}

	reconfig_user_maps();

	char *user_python_char = param("CLASSAD_USER_PYTHON_MODULES");
	if (user_python_char)
	{
		std::string user_python(user_python_char);
		free(user_python_char); user_python_char = NULL;
		char *loc_char = param("CLASSAD_USER_PYTHON_LIB");
		if (loc_char && !ClassAdUserLibs.contains(loc_char))
		{
			std::string loc(loc_char);
			if (classad::FunctionCall::RegisterSharedLibraryFunctions(loc.c_str()))
			{
				ClassAdUserLibs.append(loc.c_str());
#if defined(HAVE_DLOPEN)
				void *dl_hdl = dlopen(loc.c_str(), RTLD_LAZY);
				if (dl_hdl) // Not warning on failure as the RegisterSharedLibraryFunctions should have done that.
				{
					void (*registerfn)(void) = (void (*)(void))dlsym(dl_hdl, "Register");
					if (registerfn) {registerfn();}
					dlclose(dl_hdl);
				}
#endif
			}
			else
			{
				dprintf(D_ALWAYS, "Failed to load ClassAd user python library %s: %s\n",
					loc.c_str(), classad::CondorErrMsg.c_str());
			}
		}
		if (loc_char) {free(loc_char);}
	}
	if (!m_initConfig)
	{
		registerClassadFunctions();
		classad::ExprTree::set_user_debug_function(classad_debug_dprintf);
		m_initConfig = true;
	}
}

static classad::MatchClassAd the_match_ad;
static bool the_match_ad_in_use = false;
classad::MatchClassAd *getTheMatchAd( classad::ClassAd *source,
									  classad::ClassAd *target )
{
	ASSERT( !the_match_ad_in_use );
	the_match_ad_in_use = true;

	the_match_ad.ReplaceLeftAd( source );
	the_match_ad.ReplaceRightAd( target );

	return &the_match_ad;
}

void releaseTheMatchAd()
{
	ASSERT( the_match_ad_in_use );

	the_match_ad.RemoveLeftAd();
	the_match_ad.RemoveRightAd();

	the_match_ad_in_use = false;
}


static
bool stringListSize_func( const char * /*name*/,
						  const classad::ArgumentList &arg_list,
						  classad::EvalState &state, classad::Value &result )
{
	classad::Value arg0, arg1;
	std::string list_str;
	std::string delim_str = ", ";

	// Must have one or two arguments
{'fraction_non_alphanumeric': 0.13618995633187772, 'fraction_numerical': 0.005276564774381368, 'mean_word_length': 5.175842696629213, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5155191', 'n_tokens_mistral': 4184, 'n_tokens_neox': 3773, 'n_words': 870}