#this little block of code sets the pdbHeader variable...
foreach dir $pdbPath {
    if { [file exists $dir/Params/Header] } {
	set pdbHeaderFile $dir/Params/Header
    }
}

foreach dir $pdbPath {
    if { [file exists $dir/Params/pdbHelpers]} {source $dir/Params/pdbHelpers}
}

foreach dir $pdbPath {
    if { [file exists $dir/Params/paramFunc]} {source $dir/Params/paramFunc}
}

if { ![info exists pdbHeaderFile] } {
    error "No pdbHeaderFile found - pdbPath is probably set wrong"
}

#set up global contexts
array set Global {Diffuse Diffuse}
array set Global {Etch Etch}
array set Global {Deposit Deposit}
array set Global {Implant Implant}

#this routine dumps modified parameters into the local storage area
proc pdbStore {WriteDir} {
    #get the list of all arrays currently in scope
    set AllArr [__pdbAllArrays]

    #dump out each array
    foreach arr $AllArr {
	global $arr

	#make sure this array has been modified
	set mod [array get $arr Modify]

	if { [llength $mod] == 2 } {
	    set list [lindex $mod 1]
	    if { [llength $mod] > 0 } {
		#build the directory structure
		set file [__pdbBuild $WriteDir $arr]

		#dump the array into the file we just built
		__pdbDumpParams $file $arr
	    }
	}
    }
}


#this routine removes all arrays and resets the data base
proc pdbClear {} {
    #get the list of all arrays currently in scope
    set AllArr [__pdbAllArrays]

    #dump out each array
    foreach arr $AllArr {
	global $arr
	unset $arr
    }
}


#used to set a double precision variable value
proc __pdbSetDouble {args} {
    #get all but the last arguments
    set len [llength $args]
    set arglist [lrange $args 0 [expr $len-2]]
    set parval [lindex $args [expr $len-1]]

    if {0} {
    #check and make sure we are dealing with an acceptable expression
    if { [catch "expr $parval"] } {
    	error "Error in Double: $parval"
    }
    }
    
    #now make sure we match the return of the existing variable, if present
    __pdbSetCheck Double $arglist

    lappend arglist [list Double $parval]
    eval __pdbSet $arglist
}


#used to set a boolean variable value
proc __pdbSetBoolean {args} {
    #get all but the last arguments
    set len [llength $args]
    set arglist [lrange $args 0 [expr $len-2]]
    set parval [lindex $args [expr $len-1]]

    #check and make sure we are dealing with an acceptable expression
    if { [catch "expr $parval"] } {
    	error "Error in Boolean: $parval"
    }

    #now make sure we match the return of the existing variable, if present
    __pdbSetCheck Boolean $arglist

    lappend arglist [list Boolean $parval]
    eval __pdbSet $arglist
}


#used to set a boolean variable value
proc __pdbSetFile {args} {
    #get all but the last arguments
    set len [llength $args]
    set arglist [lrange $args 0 [expr $len-2]]
    set parval [lindex $args [expr $len-1]]

    #check and make sure we are dealing with an acceptable expression
    if {[llength $parval] > 1} {set val [eval $parval]} else {set val $parval}
    if { ![file exists $val] } {
    	error "Error - File not readable: $parval"
    }

    #now make sure we match the return of the existing variable, if present
    __pdbSetCheck File $arglist

    lappend arglist [list File $parval]
    eval __pdbSet $arglist
}


#used to set a string variable value
proc __pdbSetString {args} {
    #get all but the last arguments
    set len [llength $args]
    set arglist [lrange $args 0 [expr $len-2]]
    set parval [lindex $args [expr $len-1]]

    #now make sure we match the return of the existing variable, if present
    __pdbSetCheck String $arglist

    lappend arglist [list String $parval]
    eval __pdbSet $arglist
}


#used to set a boolean variable value
proc __pdbSetSwitch {args} {
    #get all but the last arguments
    set len [llength $args]
    set arglist [lrange $args 0 [expr $len-2]]
    set parval [lindex $args [expr $len-1]]

    #now make sure we match the return of the existing variable, if present
    set val [__pdbSetCheck Switch $arglist]

    if { [llength $val] != 3 } {
	error "Switch value has wrong format: $val"
    }

    #get the legal values
    set vallist [lindex $val 2]
    if {[llength $parval] > 1} {set val [eval $parval]} else {set val $parval}
    set indx [lsearch -exact $vallist $val]
    if { $indx == -1 } {
	error "Switch value $parval not in legal list: $vallist"
    }

    lappend arglist [list Switch $indx $vallist]
    eval __pdbSet $arglist
}


#these are used to set parameters
proc pdbSetDouble {args} {
    eval __pdbSetDouble Params $args
}
proc pdbSetBoolean {args} {
    eval __pdbSetBoolean Params $args
}
proc pdbSetFile {args} {
    eval __pdbSetFile Params $args
}
proc pdbSetSwitch {args} {
    eval __pdbSetSwitch Params $args
}
#SMC make switches work more like enums
# if testval == pdbval return 1 else return 0
proc pdbCheckSwitch {args} {
    set len [llength $args]
    set arglist [lrange $args 0 [expr $len-2]]
    set val [__pdbCheckType Params Switch $arglist]
    set vallist [lindex $val 2]
    set indx [lindex $val 1]
    set testval [lindex $args [expr $len-1]]
    if { $indx < 0 } { return 0 }
    set pdbval [lindex $vallist $indx]
    if { $testval == $pdbval } { return 1 }
    return 0
}

proc pdbSetString {args} {
    eval __pdbSetString Params $args
}


#these are used to set parameters
proc simSetDouble {args} {
    eval __pdbSetDouble Global $args
}
proc simSetBoolean {args} {
    eval __pdbSetBoolean Global $args
}
proc simSetFile {args} {
    eval __pdbSetFile Global $args
}
proc simSetSwitch {args} {
    eval __pdbSetSwitch Global $args
}
proc simSetString {args} {
    eval __pdbSetString Global $args
}


#these are used to fetch a parameter
    #used to see if a parameter is in the data base
    proc pdbIsAvailable {args} {
	#now make sure we match the return of the existing variable, if present
	set ret [expr ![catch {eval __pdbGet Params $args}]]
	return $ret;
    }

    #used to return a defined alias of an entry
    proc pdbGetAlias {args} {
	set ret [catch {eval __pdbGet Params $args} a]
	if { ! $ret } {
	    return $a
	}
	return "";
    }

    #used to fetch a double precision variable
    proc pdbGetDouble {args} {
	#now make sure we match the return of the existing variable, if present
	set val [lindex [__pdbCheckType Params Double $args] 1]
	return $val
    }

    #used to get a boolean
    proc pdbGetBoolean {args} {
	#now make sure we match the return of the existing variable, if present
	set val [lindex [__pdbCheckType Params Boolean $args] 1]
	return [expr $val]
    }

    #used to get a file name
    proc pdbGetFile {args} {
	#now make sure we match the return of the existing variable, if present
	set val [lindex [__pdbCheckType Params File $args] 1]
	if {[llength $val] > 1} {set val [eval $val]}
	return $val
    }

    #used to get a string
    proc pdbGetString {args} {
	#now make sure we match the return of the existing variable, if present
	set val [lindex [__pdbCheckType Params String $args] 1]
	return $val
    }

    #used to get the value of a switch
    proc pdbGetSwitch {args} {
	#now make sure we match the return of the existing variable, if present
	set val [lindex [__pdbCheckType Params Switch $args] 1]
	if {[llength $val] > 1} {set val [eval $val]}
	return $val
    }

    #delayed fetch of a double precision variable
    proc pdbDelayDouble {args} {
	#now make sure we match the return of the existing variable, if present
	set val [lindex [__pdbCheckType Params Double $args] 1]
	return $val
    }

#used to fetch a simulator set global...
    proc simGetDouble {args} {
	#now make sure we match the return of the existing variable, if present
	set val [lindex [__pdbCheckType Global Double $args] 1]
#	return [expr $val]
	return $val
    }

    #delayed fetch of a double precision variable
    proc simDelayDouble {args} {
	#now make sure we match the return of the existing variable, if present
	set val [lindex [__pdbCheckType Global Double $args] 1]
	return [format {[simGetDouble %s]} $args]
    }

#used to fetch a simulator set global...

    #used to get a boolean
    proc simGetBoolean {args} {
	#now make sure we match the return of the existing variable, if present
	set val [lindex [__pdbCheckType Global Boolean $args] 1]
	return [expr $val]
    }

    #used to get a file name
    proc simGetFile {args} {
	#now make sure we match the return of the existing variable, if present
	set val [lindex [__pdbCheckType Global File $args] 1]
	if {[llength $val] > 1} {set val [eval $val]}
	return $val
    }

    #used to get a string
    proc simGetString {args} {
	#now make sure we match the return of the existing variable, if present
	set val [lindex [__pdbCheckType Global String $args] 1]
	return $val
    }

    #used to get the value of a switch
    proc simGetSwitch {args} {
	#now make sure we match the return of the existing variable, if present
	set val [lindex [__pdbCheckType Global Switch $args] 1]
	if {[llength $val] > 1} {set val [eval $val]}
	return $val
    }

#used to help create new materials
    proc pdbNewMaterial {New Like} {
	global Params
	if { ![array exists Params] } { __pdbReadParam Params }
	global Params&$New
	if { ![array exists Params&$New] } { array set Params "$New $New" }
	set Like [lindex [array get Params $Like] 1]
	global Params&$Like
	if { ![array exists Params&$Like] } { __pdbReadParam Params&$Like }
	array set Params&$New "Like $Like"
    }
    proc pdbNewMater {New} {
	global Params
	if { ![array exists Params] } { __pdbReadParam Params }
	global Params&$New
	if { ![array exists Params&$New] } { array set Params "$New $New" }
    }

    proc pdbAliases {New Names} {
	global Params
	foreach alias $Names {
	    array set Params "$alias $New"
	}
    }


proc pdbSetAlias {args} {
    #get all but the last arguments
    set len [llength $args]
    set arglist [lrange $args 0 [expr $len-2]]
    set parval [lindex $args [expr $len-1]]

    #check and make sure we are dealing with an acceptable expression
    if {[llength $parval] > 1} {set val [eval $parval]} else {set val $parval}

    lappend arglist $parval
    eval __pdbSet $arglist
}


#SMC make switches work more like enums
# if testval == pdbval return 1 else return 0
proc pdbCheckSwitch {args} {
    set len [llength $args]
    set arglist [lrange $args 0 [expr $len-2]]
    set val [__pdbCheckType Params Switch $arglist]
    set vallist [lindex $val 2]
    set indx [lindex $val 1]
    set testval [lindex $args [expr $len-1]]
    if { $indx < 0 } { return 0 }
    set pdbval [lindex $vallist $indx]
    if { $testval == $pdbval } { return 1 }
    return 0
}
