<commit_before># ex:ts=4
#
# Insert some license text here at some point soon.
#

package provide portutil 1.0
package require Pextlib 1.0

global targets

namespace eval portutil {
    variable uniqid 0
}

########### External High Level Procedures ###########

# options
# Exports options in an array as externally callable procedures
# Thus, "options myarray name date" would create procedures named "name"
# and "date" that set the array items keyed by "name" and "date"
# Arguments: <array for export> <options (keys in array) to export>
proc options {args} {
    foreach option $args {
    	eval "proc $option {args} \{ \n\
	    global ${option} user_options \n\
		\if \{!\[info exists user_options(${option})\]\} \{ \n\
		     set ${option} \$args \n\
		\} \n\
	\}"
    }
}

# default
# Checks if variable is set, if not, sets to supplied value
proc default {option args} {
    global $option
    if {![info exists $option]} {
	set $option $args
    }
}

########### Misc Utility Functions ###########

proc tbool {key} {
    upvar $key upkey
    if {[info exists upkey]} {
	if {$upkey == "yes"} {
	    return 1
	}
    }
    return 0
}

# makeuserproc
# This procedure re-writes the user-defined custom target to include
# all the globals in its scope.  This is undeniably ugly, but I haven't
# thought of any other way to do this.
proc makeuserproc {name body} {
    regsub -- "^\{(.*)" $body "\{ \n foreach g \[info globals\] \{ \n global \$g \n \} \n \\1 " body
    eval "proc $name {} $body"
}

########### External Dependancy Manipulation Procedures ###########
# register
# Creates a target in the global target list using the internal dependancy
#     functions
# Arguments: <identifier> <mode> <args ...>
# The following modes are supported:
#	<identifier> target <procedure to execute> <init procedure> [run type]
#	<identifier> provides <list of target names>
#	<identifier> requires <list of target names>
#	<identifier> uses <list of target names>
#	<identifier> preflight <target name>
#	<identifier> postflight <target name>
proc register {name mode args} {
    global targets
    dlist_add_item targets $name

    if {[string equal target $mode]} {
        set procedure [lindex $args 0]
        set init [lindex $args 1]
        if {[dlist_has_key targets $name procedure]} {
            ui_info "Warning: target '$name' re-registered (new procedure: '$procedure')"
        }
        dlist_set_key targets $name procedure $procedure
        dlist_set_key targets $name init $init

	# Set runtype {always,once} if available
	if {[llength $args] == 3} {
	    dlist_set_key targets $name runtype [lindex $args 2]
	}
    } elseif {[string equal requires $mode] || [string equal uses $mode] || [string equal provides $mode]} {
        if {[dlist_has_item targets $name]} {
            dlist_append_key targets $name $mode $args
        } else {
            ui_info "Warning: target '$name' not-registered in register $mode"
        }
        
        if {[string equal provides $mode]} {
            # If it's a provides, register the pre-/post- hooks for use in Portfile.
            # Portfile syntax: pre-fetch { puts "hello world" }
            # User-code exceptions are caught and returned as a result of the target.
            # Thus if the user code breaks, dependent targets will not execute.
            foreach target $args {
		if {[info commands $target] != ""} {
		    ui_error "$name attempted to register provide \'$target\' which is a pre-existing procedure. Ignoring register."
		    continue;
		}
                set id [incr portutil::uniqid]
                set ident [lindex [dlist_get_matches targets provides $args] 0]<commit_msg>Change target re-registration warning to a debug message, as it is a fairly standard occurance<commit_after># ex:ts=4
#
# Insert some license text here at some point soon.
#

package provide portutil 1.0
package require Pextlib 1.0

global targets

namespace eval portutil {
    variable uniqid 0
}

########### External High Level Procedures ###########

# options
# Exports options in an array as externally callable procedures
# Thus, "options myarray name date" would create procedures named "name"
# and "date" that set the array items keyed by "name" and "date"
# Arguments: <array for export> <options (keys in array) to export>
proc options {args} {
    foreach option $args {
    	eval "proc $option {args} \{ \n\
	    global ${option} user_options \n\
		\if \{!\[info exists user_options(${option})\]\} \{ \n\
		     set ${option} \$args \n\
		\} \n\
	\}"
    }
}

# default
# Checks if variable is set, if not, sets to supplied value
proc default {option args} {
    global $option
    if {![info exists $option]} {
	set $option $args
    }
}

########### Misc Utility Functions ###########

proc tbool {key} {
    upvar $key upkey
    if {[info exists upkey]} {
	if {$upkey == "yes"} {
	    return 1
	}
    }
    return 0
}

# makeuserproc
# This procedure re-writes the user-defined custom target to include
# all the globals in its scope.  This is undeniably ugly, but I haven't
# thought of any other way to do this.
proc makeuserproc {name body} {
    regsub -- "^\{(.*)" $body "\{ \n foreach g \[info globals\] \{ \n global \$g \n \} \n \\1 " body
    eval "proc $name {} $body"
}

########### External Dependancy Manipulation Procedures ###########
# register
# Creates a target in the global target list using the internal dependancy
#     functions
# Arguments: <identifier> <mode> <args ...>
# The following modes are supported:
#	<identifier> target <procedure to execute> <init procedure> [run type]
#	<identifier> provides <list of target names>
#	<identifier> requires <list of target names>
#	<identifier> uses <list of target names>
#	<identifier> preflight <target name>
#	<identifier> postflight <target name>
proc register {name mode args} {
    global targets
    dlist_add_item targets $name

    if {[string equal target $mode]} {
        set procedure [lindex $args 0]
        set init [lindex $args 1]
        if {[dlist_has_key targets $name procedure]} {
            ui_debug "Warning: target '$name' re-registered (new procedure: '$procedure')"
        }
        dlist_set_key targets $name procedure $procedure
        dlist_set_key targets $name init $init

	# Set runtype {always,once} if available
	if {[llength $args] == 3} {
	    dlist_set_key targets $name runtype [lindex $args 2]
	}
    } elseif {[string equal requires $mode] || [string equal uses $mode] || [string equal provides $mode]} {
        if {[dlist_has_item targets $name]} {
            dlist_append_key targets $name $mode $args
        } else {
            ui_info "Warning: target '$name' not-registered in register $mode"
        }
        
        if {[string equal provides $mode]} {
            # If it's a provides, register the pre-/post- hooks for use in Portfile.
            # Portfile syntax: pre-fetch { puts "hello world" }
            # User-code exceptions are caught and returned as a result of the target.
            # Thus if the user code breaks, dependent targets will not execute.
            foreach target $args {
		if {[info commands $target] != ""} {
		    ui_error "$name attempted to register provide \'$target\' which is a pre-existing procedure. Ignoring register."
		    continue;
		}
                set id [incr portutil::uniqid]
                set ident [lindex [dlist_get_matches targets provides $args] 0]
{'fraction_non_alphanumeric': 0.12173444653918664, 'fraction_numerical': 0.0037705359547535685, 'mean_word_length': 2.9379639448568398, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, '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': '5798183', 'n_tokens_mistral': 2251, 'n_tokens_neox': 2157, 'n_words': 879}