set doc_section Info
set doc_type Global

# DICTIONARY SECTION

# FIXME - Document
fset DICT " \0030,7 DICT \003 %0-" [flocation current]

# /dict
doc add "Aliases ($doc_type)/$doc_section/dict" "/dict <word>

Looks up the given word in a variety of dictionaries.  For details on the protocol, or for web based lookups, see www.dict.org."

alias dict {
    if { $::dictstate!="closed" } {
	fdisplay DICT Lookup of $::dictword aborted.
	close $::dictfd
	set ::dictstate closed
	if { $arg == "" } { return }
    }
    if {$arg == ""} {
	fdisplay DICT /dict <word>
	return
    }
    # server1.shopthenet.net (from dict.org)
    if {[catch {set ::dictfd [socket -async 206.74.122.3 2628]}]} {
	fdisplay DICT Error connecting to server
	return
    }
    set ::dictword $arg
    set ::dictstate "opening"
    if { [info exists ::dicts] } { unset ::dicts }
    if { [info exists ::dictspell] } { unset ::dictspell }
    echo [fparse DICT defining ($arg)]
    fconfigure $::dictfd -blocking 0 -buffering line
    puts $::dictfd "DEFINE * \"$arg\""
    #fconfigure $::dictfd -buffering line
    fileevent $::dictfd readable [list adict $::dictfd $arg]
}

set ::dictstate closed

proc adict {dict word} {
    global bdict
    if {[eof $dict]} { 
	close $dict
	set ::dictstate closed
	return
    }
    set data [gets $dict]
    switch -glob -- $data {
	"150 *" {
	    set ::dictstate definitions
	}
	"151 *" {
	    fdisplay DICT "From [lindex [split $data \"] 3]:"
	}
	"152 *" {}
	"220 *" {}
	"250 *" {
	    close $dict
	    set ::dictstate closed
	}
	"552 *" {
	    if { $::dictstate=="match" } {
		fdisplay DICT "No definition found for $::dictword."
		close $dict
		set ::dictstate closed
	    } else {
		puts $::dictfd "MATCH * . \"$::dictword\""
		set ::dictstate match
	    }
	}
	"." {
	    if { $::dictstate=="match" } {
		fdisplay DICT "No definition found for $::dictword.  Perhaps you meant:"
		foreach d [uniq $::dicts] {
		    fdisplay DICT "From $d:"
		    fdisplay DICT " [join $::dictspell($d) {, }]"
		}
	    }
	}
	default {
	    if { $::dictstate=="definitions" } {
		fdisplay DICT $data
	    } elseif { $::dictstate=="match" } {
		set dictname [lindex [split $data " "] 0]
		lappend ::dicts $dictname
		lappend ::dictspell($dictname) [lindex [split $data \"] 1]
	    } else {
		close $dict
		set ::dictstate closed
		error "Unknown reply from dictionary server. ($data)"
	    }
	}
    }
}


# CONVERSION SECTION

fset CONVERT " \0030,7 CONVERT \003 %0" [flocation current]

# The following array is used to retrieve proper names given an abbreviation.

set convert_name(F) "Fahrenheit"
set convert_name(R) "Rankine"
set convert_name(C) "Celcius"
set convert_name(K) "Kelvin"
set convert_name(CODE) "ASCII Character Code"
set convert_name(CHAR) "Character"
set convert_name(ROT13) "Rotate-13"
set convert_name(MORSE) "Morse Code"
for { set i 2 } { $i < 36 } { incr i } {
    set convert_name($i) "Base-$i"
}

# The following array is used to convert between various types.  The code given
# is placed between square brackets and is evaluated.  For example, with
# ROT13_to_TEXT, the code that is run to get the value is: [rot13 $value]
# $value is replaced with the value to be converted.

set convert_code(C_to_K) {expr $value+273.15}
set convert_code(K_to_C) {expr $value-273.15}
set convert_code(F_to_C) {expr 5/9.0*($value-32)}
set convert_code(C_to_F) {expr $value*9/5.0+32}
set convert_code(ROT13_to_TEXT) {rot13 $value}
set convert_code(TEXT_to_ROT13) {rot13 $value}
set convert_code(CHAR_to_CODE) {from_char $value}
set convert_code(CODE_to_CHAR) {to_char $value}
set convert_code(F_to_R) {expr $value+459.67}
set convert_code(R_to_F) {expr $value-459.67}
set convert_code(TEXT_to_MORSE) {convert_to_morse $value}
set convert_code(MORSE_to_TEXT) {convert_from_morse $value}
set convert_code(TEXT_to_BINARY) {convert_to_binary $value}
set convert_code(BINARY_to_TEXT) {convert_from_binary $value}
set convert_code(TEXT_to_HEX) {convert_to_hex $value}
set convert_code(HEX_to_TEXT) {convert_from_hex $value}
for { set i 2 } { $i < 36 } { incr i } {
    set convert_code(${i}_to_10) "base $i 10 \$value"
    set convert_code(10_to_$i) "base 10 $i \$value"
}

proc convert_currency_callback { from to value script token } {
    # The callback for currency.dat http retrieval completion.
    upvar #0 $token state
    set file [open $::env(HOME)/.quirc/currency.dat w]
    puts -nonewline $file $state(body)
    close $file
    convert_currency_conversion $from $to $value $script
}

proc convert_currency_get_file { from to value script } {
    # Get the file and call the callback
    ::http::geturl http://quirc.org/currency.dat -command "::convert_currency_callback [escape $from] [escape $to] [escape $value] [escape $script]"
}

proc convert_currency_conversion { from to value script } {
    # Open up the file, grab the rate, convert to canadian, convert to other
    set file [open $::env(HOME)/.quirc/currency.dat r]
    while { ![eof $file] } {
	gets $file line
 	if { $line!="" } {
	    set ::convert_currency([lindex $line 0]) [lindex $line 2]
	}
	set ::convert_name([lindex $line 0]) "[lindex $line 0] ([lindex $line 1])"
    }
    close $file
    if { ![info exists ::convert_currency($from)] ||
	 ![info exists ::convert_currency($to)] } {
	error "Do not know how to convert from $from to $to.  Please feel free to contribute the information on how to do so to the author."
    }
    set num [expr $value*$::convert_currency($to)/$::convert_currency($from)]
    set script [parseformat $script [list [list e $num]]]
    eval $script
}

proc convert_currency { from to value script } {
    # Check the date on the file.  If it's more than a day, fetch the new file.
    # If not, use this file.
    if { [file exists $::env(HOME)/.quirc/currency.dat] } {
	file stat $::env(HOME)/.quirc/currency.dat filedata
	if { [clock seconds]-$filedata(mtime) > 86400 } {
	    convert_currency_get_file $from $to $value $script
	} else {
	    convert_currency_conversion $from $to $value $script
	}
    } else {
	convert_currency_get_file $from $to $value $script
    }
}

proc convert_bg { from to value script } {
    # Any %e in $script will be replaced with the converted value.
    set from [string toupper $from]
    set to [string toupper $to]
    set path [convert_path $from $to]
    set fromvalue $value
    if { $path!="" } {
	# We have a direct path, call callback immediately.
	foreach item $path {
	    set value [eval $::convert_code($item)]
	}
	set script [parseformat $script [list [list e [escape $value]]]]
	eval $script
    } else {
	# We have no direct path, try the currency convertor.
	convert_currency $from $to $value $script
    }
}

proc convert { from to value } {
    set from [string toupper $from]
    set to [string toupper $to]
    set path [convert_path $from $to]
    if { $path=="" } {
	error "Do not know how to convert from $from to $to immediately.  Try doing a convert_bg."
    }
    foreach item $path {
	set value [eval $::convert_code($item)]
    }
    return $value
}

# The following two procs find a conversion path given a source and dest.

proc convert_path { from to } {
    set result [convert_search $from $to]
    if { [info exists ::convert_searched] } {
	unset ::convert_searched
    }
    return $result
}

proc convert_search { from to } {
    set ::convert_searched($from) 1
    # If we have an exact match, return it.
    if { [info exists ::convert_code(${from}_to_$to)] } {
	return ${from}_to_$to
    }
    foreach item [array names ::convert_code ${from}_to_*] {
	# If we haven't already searched the "to" side, search it.
	if { [regexp ${from}_to_(.*) $item junk match] } {
	    if { ![info exists ::convert_searched($match)] } {
		# Do search based on $match and $to
		set result [convert_search $match $to]
		# Return result checking for ""
		if { $result=="" } {
		    return ""
		} else {
		    return [concat ${from}_to_$match $result]
		}
	    }
	}
    }
    # No path was found.
    return ""
}

# This is called when a conversion is completed.

proc convert_callback { intype outtype invalue outvalue flags } {
    if { [member $flags say] } {
	if { [member $flags terse] } {
	    say $outvalue
	} else {
	    say "QuICK Convert: $invalue converted from \"[convert_name $intype]\" to \"[convert_name $outtype]\" is $outvalue"
	}
    } else {
	if { [member $flags terse] } {
	    fdisplay CONVERT $outvalue
	} else {
	    fdisplay CONVERT "$invalue converted from \"[convert_name $intype]\" to \"[convert_name $outtype]\" is $outvalue"
	}
    }
}

# This is called to get the full name of an abbreviation.

proc convert_name { abbreviation } {
    set abbreviation [string toupper $abbreviation]
    if { [info exists ::convert_name($abbreviation)] } {
	return $::convert_name($abbreviation)
    } else {
	return [string index $abbreviation 0][string tolower [string range $abbreviation 1 end]]
    }
}


alias convert {
    if { $arg=="" } {
	foreach key [lsort [array names ::convert_code]] {
	    set from [lindex [split $key "_"] 0]
	    set to [lindex [split $key "_"] 2]
	    fdisplay CONVERT "$from ([convert_name $from]) -> $to ([convert_name $to])"
	}
	fdisplay CONVERT "/convert <from> <to> <value>"
	fdisplay CONVERT "The conversion system can chain together conversions to get the desired conversion, for example from C to R."
	fdisplay CONVERT "The currency conversion codes are not listed here.  The codes are the standard 3 character currency codes, for example USD or CAD.  You can find a list in ~/.quirc/currency.dat (if you have run a conversion before and it retrieved the file)."
	return
    }
    set flags ""
    set arg [getopts $arg say terse]
    if { $say } { lappend flags say }
    if { $terse } { lappend flags terse }
    set from [lindex [split $arg " "] 0]
    set to [lindex [split $arg " "] 1]
    set value [join [lrange [split $arg " "] 2 end]]
    convert_bg $from $to $value "::convert_callback [escape $from] [escape $to] [escape $value] %e [escape $flags]"
}

proc ::decimal { char } {
    set number [from_char $char]
    if { $number>=[from_char "0"] && $number<=[from_char "9"] } {
	return [expr $number-48];
    }
    if { $number>=[from_char "a"] && $number<=[from_char "z"] } {
	return [expr $number-87];
    }
    if { $number>=[from_char "A"] && $number<=[from_char "Z"] } {
	return [expr $number-55];
    }
    error "Invalid character given to convert to a decimal!"
}

proc ::actual { decimal } {
    if { $decimal<0 || $decimal>35 } {
	error "Invalid decimal givem to convert to a character!"
    } else {
	if { $decimal>9 } {
	    return [to_char [expr $decimal+55]]
	} else {
	    return $decimal
	}
    }
}

# This proc only handles numbers that are not over 1<<31.
proc ::base { base newbase number } {
    if { $base<2 || $base>36 || $newbase<2 || $newbase>36 } {
	error "Valid bases are between 2 and 36."
    }
    set total 0
    for { set c 0 } { $c < [string length $number] } { incr c } {
	set total [expr $total+[decimal [string index $number $c]]*int(pow($base,[string length $number]-$c-1))]
    }
    set outputstring ""
    while { $total!=0 && $total!=-1 } {
	set remainder [expr $total%$newbase]
	set total [expr $total/$newbase]
	set tempstring [actual $remainder]
	append tempstring $outputstring
	set outputstring $tempstring
    }
    if { $outputstring == "" } { set outputstring 0 }
    return $outputstring
}

proc char_to_hex { char } {
    scan $char %c value
    return "[format %x [expr $value/16]][format %x [expr $value%16]]"
}

proc hex_to_char { data } {
    if { [string length $data]!=2 } { return "*" }
    scan [string index $data 0] %x first
    scan [string index $data 1] %x second
    return [format %c [expr $first*16+$second]]
}

proc char_to_binary { char } {
    set returnvalue ""
    scan $char %c value
    for { set n 7 } { $n >= 0 } { incr n -1 } {
	if { [expr int(pow(2,$n))&$value] } {
	    append returnvalue "1"
	} else {
	    append returnvalue "0"
	}
    }
    return $returnvalue
}

proc binary_to_char { data } {
    set returnvalue 0
    for { set n 7 } { $n >= 0 } { incr n -1 } {
        if { [string index $data [expr 7-$n]]=="0" || [string index $data [expr 7-$n]]=="1" } {
	    set returnvalue [expr $returnvalue+[string index $data [expr 7-$n]]*int(pow(2,$n))]
	} else {
	    return "*"
	}
    }
    return [format %c $returnvalue]
}

proc convert_to_binary { arg } {
    set thedata ""
    for { set n 0 } { $n < [string length $arg] } { incr n } {
	append thedata [char_to_binary [string index $arg $n]]
    }
    return $thedata
}

proc convert_from_binary { arg } {
    if { [expr [string length $arg] % 8] != 0 || [regexp "\[^01]" $arg] } {
	error "Binary strings must consist of sets of 8 zeros or ones."
    }
    while { $arg!="" } {
	append returnvalue [binary_to_char [string range $arg 0 7]]
	set arg [string range $arg 8 end]
    }
    return $returnvalue
}

proc convert_to_hex { data } {
    for { set n 0 } { $n < [string length $data] } { incr n } {
	append thedata [char_to_hex [string index $data $n]]
    }
    return $thedata
}

proc convert_from_hex { arg } {
    if { [expr [string length $arg] % 2] != 0 || [regexp "\[^0-9a-fA-F]" $arg] } {
	error "Hex strings must consist of sets of 2 digits or letters from A to F."
    }
    while { $arg!="" } {
	append returnvalue [hex_to_char [string range $arg 0 1]]
	set arg [string range $arg 2 end]
    }
    return $returnvalue
}

proc rot13_char { char } {
    scan $char %c value
    if { $value>=0x41 && $value<=0x5a } {
	return [format %c [expr ((($value-0x41)+13)%26)+0x41]]
    }
    if { $value>=0x61 && $value<=0x7a } {
	return [format %c [expr ((($value-0x61)+13)%26)+0x61]]
    }
    return $char
}

proc rot13 { arg } {
    set data ""
    for { set n 0 } { $n < [string length $arg] } { incr n } {
	append data [rot13_char [string index $arg $n]]
    }
    return $data
}

# /hex
doc add "Aliases ($doc_type)/$doc_section/hex" "/hex <text>

Converts the text to hex, then sends it to the current session."

alias hex {
    say "Hex: [convert TEXT HEX $arg]"
}

# /binary
doc add "Aliases ($doc_type)/$doc_section/binary" "/binary <text>

Converts the text to binary, then sends it to the current session."

alias binary {
    say "Binary: [convert TEXT BINARY $arg]"
}

# /rot13
doc add "Aliases ($doc_type)/$doc_section/rot13" "/rot13 <text>

Rotate 13 the text, then send it to the current session."

alias rot13 {
    say "Rot13: [convert TEXT ROT13 $arg]"
}

# /morse
doc add "Aliases ($doc_type)/$doc_section/morse" "/morse <text>

Convert the text to morse code, then send it to the current session."

alias morse {
    say "Morse: [convert TEXT MORSE $arg]"
}


# Morse Code Conversion

# A .-
# Ä .-.-
# Á .--.-
# Å .--.-
# B -...
# C -.-.
# Ch ----
# D -..
# E .
# É ..-..
# F ..-.
# G --.
# H ....
# I ..
# J .---
# K -.-
# L .-..
# M --
# N -.
# Ñ --.--
# O ---
# Ö ---.
# P .--.
# Q --.-
# R .-.
# S ...
# T -
# U ..-
# Ü ..--
# V ...-
# W .--
# X -..-
# Y -.--
# Z --..
# 1 .----
# 2 ..---
# 3 ...--
# 4 ....-
# 5 .....
# 6 -....
# 7 --...
# 8 ---..
# 9 ----.
# 0 -----
# . .-.-.-
# , --..--
# : ---...
# ? ..--..
# ' .----.
# - -....-
# / -..-. 
# ( -.--.-
# ) -.--.-
# " .-..-.

# If the duration of a dot is taken to be one unit then that of a dash is three units. The space between the components of one character is one unit, between characters is three units and between words seven units. To indicate that a mistake has been made and for the receiver to delete the last word send ........ (eight dots).

proc convert_from_morse { data } {
    set odd 1
    set result ""
    foreach data [split $data] {
	switch -exact -- $data {
	    ".-.-.-" { set data . }
	    "-....-" { set data - }
	    ".-" { set data a }
	    ".-.-" { set data ä }
	    ".--.-" { set data á }
	    "-..." { set data b }
	    "----" { set data ch }
	    "-.-." { set data c }
	    "-.." { set data d }
	    "." { set data e }
	    "..-.." { set data é }
	    "..-." { set data f }
	    "--." { set data g }
	    "...." { set data h }
	    ".." { set data i }
	    ".---" { set data j }
	    "-.-" { set data k }
	    ".-.." { set data l }
	    "--" { set data m }
	    "-." { set data n }
	    "--.--" { set data ñ }
	    "---" { set data o }
	    "---." { set data ö }
	    ".--." { set data p }
	    "--.-" { set data q }
	    ".-." { set data r }
	    "..." { set data s }
	    "-" { set data t }
	    "..-" { set data u }
	    "..--" { set data ü }
	    "...-" { set data v }
	    ".--" { set data w }
	    "-..-" { set data x }
	    "-.--" { set data y }
	    "--.." { set data z }
	    ".----" { set data 1 }
	    "..---" { set data 2 }
	    "...--" { set data 3 }
	    "....-" { set data 4 }
	    "....." { set data 5 }
	    "-...." { set data 6 }
	    "--..." { set data 7 }
	    "---.." { set data 8 }
	    "----." { set data 9 }
	    "-----" { set data 0 }
	    "--..--" { set data , }
	    "---..." { set data : }
	    "..--.." { set data ? }
	    ".----." { set data ' }
	    "-..-." { set data / }
	    ".-..-." { set data \" }
	    "-.--.-" {
		if $odd {
		    set data \(
		    set odd 0
		} else {
		    set data \)
		    set odd 1
		}
	    }
	    "" { set data " " }
	}
	lappend result $data
    }
    return [join $result {}]
}

proc convert_to_morse { data } {
    set newdata ""
    for { set n 0 } { $n < [string length $data] } { incr n } {
	if { [string index $data $n]=="." } {
	    append newdata ".-.-.- "
	} elseif { [string index $data $n]=="-" } {
	    append newdata "-....- "
	} else {
	    append newdata [string index $data $n]
	}
    }
    set data $newdata
    regsub -all -nocase -- A $data ".- " data
    regsub -all -nocase -- Ä $data ".-.- " data
    regsub -all -nocase -- Á $data ".--.- " data
    regsub -all -nocase -- Å $data ".--.- " data
    regsub -all -nocase -- B $data "-... " data
    regsub -all -nocase -- Ch $data "---- " data
    regsub -all -nocase -- C $data "-.-. " data
    regsub -all -nocase -- D $data "-.. " data
    regsub -all -nocase -- E $data ". " data
    regsub -all -nocase -- É $data "..-.. " data
    regsub -all -nocase -- F $data "..-. " data
    regsub -all -nocase -- G $data "--. " data
    regsub -all -nocase -- H $data ".... " data
    regsub -all -nocase -- I $data ".. " data
    regsub -all -nocase -- J $data ".--- " data
    regsub -all -nocase -- K $data "-.- " data
    regsub -all -nocase -- L $data ".-.. " data
    regsub -all -nocase -- M $data "-- " data
    regsub -all -nocase -- N $data "-. " data
    regsub -all -nocase -- Ñ $data "--.-- " data
    regsub -all -nocase -- O $data "--- " data
    regsub -all -nocase -- Ö $data "---. " data
    regsub -all -nocase -- P $data ".--. " data
    regsub -all -nocase -- Q $data "--.- " data
    regsub -all -nocase -- R $data ".-. " data
    regsub -all -nocase -- S $data "... " data
    regsub -all -nocase -- T $data "- " data
    regsub -all -nocase -- U $data "..- " data
    regsub -all -nocase -- Ü $data "..-- " data
    regsub -all -nocase -- V $data "...- " data
    regsub -all -nocase -- W $data ".-- " data
    regsub -all -nocase -- X $data "-..- " data
    regsub -all -nocase -- Y $data "-.-- " data
    regsub -all -nocase -- Z $data "--.. " data
    regsub -all -nocase -- 1 $data ".---- " data
    regsub -all -nocase -- 2 $data "..--- " data
    regsub -all -nocase -- 3 $data "...-- " data
    regsub -all -nocase -- 4 $data "....- " data
    regsub -all -nocase -- 5 $data "..... " data
    regsub -all -nocase -- 6 $data "-.... " data
    regsub -all -nocase -- 7 $data "--... " data
    regsub -all -nocase -- 8 $data "---.. " data
    regsub -all -nocase -- 9 $data "----. " data
    regsub -all -nocase -- 0 $data "----- " data
    regsub -all -nocase -- , $data "--..-- " data
    regsub -all -nocase -- : $data "---... " data
    regsub -all -nocase -- \\? $data "..--.. " data
    regsub -all -nocase -- ' $data ".----. " data
    regsub -all -nocase -- / $data "-..-. " data
    regsub -all -nocase -- \\\( $data "-.--.- " data
    regsub -all -nocase -- \\\) $data "-.--.- " data
    regsub -all -nocase -- \" $data ".-..-. " data
    if { [string index $data end]==" " } {
	set data [string range $data 0 [expr [string length $data]-2]]
    }
    return $data
}

# CURRENCY SECTION

package require http

# COUNTRY SECTION

# This section contains an associative array of domain postfixes with their
# unabreviated counterparts, either the type of domain, or the country of the
# domain.  Some of the entries are missing.  If anyone knows what they are,
# please fire off the info to quirc@patearl.net.

set country(AF) "AFGHANISTAN"
set country(AL) "ALBANIA"
set country(DZ) "ALGERIA"
set country(AS) "AMERICAN SAMOA"
set country(AD) "ANDORRA"
set country(AO) "ANGOLA"
set country(AI) "ANGUILLA"
set country(AQ) "ANTARCTICA"
set country(AG) "ANTIGUA AND BARBUDA"
set country(AR) "ARGENTINA"
set country(AM) "ARMENIA"
set country(AW) "ARUBA"
set country(AC) "ASCENSION ISLAND"
set country(AU) "AUSTRALIA"
set country(AT) "AUSTRIA"
set country(AZ) "AZERBAIJAN"
set country(BS) "BAHAMAS"
set country(BH) "BAHRAIN"
set country(BD) "BANGLADESH"
set country(BB) "BARBADOS"
set country(BY) "BELARUS"
set country(BE) "BELGIUM"
set country(BZ) "BELIZE"
set country(BJ) "BENIN"
set country(BM) "BERMUDA"
set country(BT) "BHUTAN"
set country(BO) "BOLIVIA"
set country(BA) "BOSNIA AND HERZEGOWINA"
set country(BW) "BOTSWANA"
set country(BV) "BOUVET ISLAND"
set country(BR) "BRAZIL"
set country(IO) "BRITISH INDIAN OCEAN TERRITORY"
set country(BN) "BRUNEI DARUSSALAM"
set country(BG) "BULGARIA"
set country(BF) "BURKINA FASO"
set country(BI) "BURUNDI"
#set country(BY) "BYELORUSSIAN SSR"
set country(KH) "CAMBODIA"
set country(CM) "CAMEROON"
set country(CA) "CANADA"
set country(CV) "CAP VERDE"
set country(KY) "CAYMAN ISLANDS"
set country(CF) "CENTRAL AFRICAN REPUBLIC"
set country(TD) "CHAD"
set country(CS) "CZECHOSLOVAKIA (FORMER)"
set country(CL) "CHILE"
set country(CN) "CHINA"
set country(CX) "CHRISTMAS ISLAND"
set country(CC) "COCOS (KEELING) ISLANDS"
set country(CO) "COLOMBIA"
set country(KM) "COMOROS"
set country(CG) "CONGO"
set country(CK) "COOK ISLANDS"
set country(CR) "COSTA RICA"
set country(CI) "COTE D'IVOIRE"
set country(HR) "CROATIA"
#set country(HR) "HRVATSKA"
set country(CU) "CUBA"
set country(CY) "CYPRUS"
set country(CZ) "CZECH REPUBLIC"
set country(DK) "DENMARK"
set country(DJ) "DJIBOUTI"
set country(DM) "DOMINICA"
set country(DO) "DOMINICAN REPUBLIC"
set country(TP) "EAST TIMOR"
set country(EC) "ECUADOR"
set country(EG) "EGYPT"
set country(SV) "EL SALVADOR"
set country(GQ) "EQUATORIAL GUINEA"
set country(ER) "ERITREA"
set country(EE) "ESTONIA"
set country(ET) "ETHIOPIA"
# Left off here
set country(FK) "FALKLAND ISLANDS"
set country(FK) "MALVINAS"
set country(FO) "FAROE ISLANDS"
set country(FJ) "FIJI"
set country(FI) "FINLAND"
set country(FR) "FRANCE"
set country(GF) "FRENCH GUIANA"
set country(PF) "FRENCH POLYNESIA"
set country(TF) "FRENCH SOUTHERN TERRITORIES"
set country(GA) "GABON"
set country(GM) "GAMBIA"
set country(GE) "GEORGIA"
set country(DE) "GERMANY"
set country(DE) "DEUTSCHLAND"
set country(GH) "GHANA"
set country(GI) "GIBRALTAR"
set country(GR) "GREECE"
set country(GL) "GREENLAND"
set country(GD) "GRENADA"
set country(GP) "GUADELOUPE"
set country(GU) "GUAM"
set country(GT) "GUATEMALA"
set country(GN) "GUINEA"
set country(GW) "GUINEA BISSAU"
set country(GY) "GYANA"
set country(HT) "HAITI"
set country(HM) "HEARD AND MC DONALD ISLANDS"
set country(HN) "HONDURAS"
set country(HK) "HONG KONG"
set country(HU) "HUNGARY"
set country(IS) "ICELAND"
set country(IN) "INDIA"
set country(ID) "INDONESIA"
set country(IR) "IRAN"
set country(IQ) "IRAQ"
set country(IE) "IRELAND"
set country(IL) "ISRAEL"
set country(IT) "ITALY"
set country(JM) "JAMAICA"
set country(JP) "JAPAN"
set country(JO) "JORDAN"
set country(KZ) "KAZAKHSTAN"
set country(KE) "KENYA"
set country(KI) "KIRIBATI"
set country(KP) "NORTH KOREA"
set country(KR) "SOUTH KOREA"
set country(KW) "KUWAIT"
set country(KG) "KYRGYZSTAN"
set country(LA) "LAO"
set country(LA) "LAOS"
set country(LV) "LATVIA"
set country(LB) "LEBANON"
set country(LS) "LESOTHO"
set country(LR) "LIBERIA"
set country(LY) "LIBYAN ARAB JAMAHIRIYA"
set country(LY) "LYBIA"
set country(LI) "LIECHTENSTEIN"
set country(LT) "LITHUANIA"
set country(LU) "LUXEMBOURG"
set country(MO) "MACAU"
set country(MK) "MACEDONIA"
set country(MG) "MADAGASCAR"
set country(MW) "MALAWI"
set country(MY) "MALAYSIA"
set country(MV) "MALDIVES"
set country(ML) "MALI"
set country(MT) "MALTA"
set country(MH) "MARSHALL ISLANDS"
set country(MQ) "MARTINIQUE"
set country(MR) "MAURITANIA"
set country(MU) "MAURITIUS"
set country(MX) "MEXICO"
set country(FM) "MICRONESIA"
set country(MD) "MOLDOVA"
set country(MC) "MONACO"
set country(MN) "MONGOLIA"
set country(MS) "MONTSERRAT"
set country(MA) "MOROCCO"
set country(MZ) "MOZAMBIQUE"
set country(MM) "MYANMAR"
set country(NA) "NAMIBIA"
set country(NR) "NAURU"
set country(NP) "NEPAL"
set country(NL) "NETHERLANDS"
set country(AN) "NETHERLANDS ANTILLES"
set country(NT) "NEUTRAL ZONE"
set country(NC) "NEW CALEDONIA"
set country(NZ) "NEW ZEALAND"
set country(NI) "NICARAGUA"
set country(NE) "NIGER"
set country(NG) "NIGERIA"
set country(NU) "NIUE"
set country(NF) "NORFOLK ISLAND"
set country(MP) "NORTHERN MARIANA ISLANDS"
set country(NO) "NORWAY"
set country(OM) "OMAN"
set country(PK) "PAKISTAN"
set country(PW) "PALAU"
set country(PA) "PANAMA"
set country(PG) "PAPUA NEW GUINEA"
set country(PG) "PAPUA"
set country(PG) "NEW GUINEA"
set country(PY) "PARAGUAY"
set country(PE) "PERU"
set country(PH) "PHILIPPINES"
set country(PN) "PITCAIRN"
set country(PL) "POLAND"
set country(PT) "PORTUGAL"
set country(PR) "PUERTO RICO"
set country(QA) "QATAR"
set country(RE) "REUNION"
set country(RO) "ROMANIA"
set country(RU) "RUSSIAN FEDERATION"
set country(RW) "RWANDA"
set country(KN) "SAINT KITTS AND NEVIS"
set country(LC) "SAINT LUCIA"
set country(VC) "SAINT VINCENT AND THE GRENADINES"
set country(WS) "SAMOA"
set country(SM) "SAN MARINO"
set country(ST) "SAO TOME AND PRINCIPE"
set country(SA) "SAUDI ARABIA"
set country(SN) "SENEGAL"
set country(SC) "SEYCHELLES"
set country(SL) "SIERRA LEONE"
set country(SG) "SINGAPORE"
set country(SI) "SLOVENIA"
set country(SB) "SOLOMON ISLANDS"
set country(SO) "SOMALIA"
set country(ZA) "SOUTH AFRICA"
set country(ES) "SPAIN"
set country(LK) "SRI LANKA"
set country(SH) "ST. HELENA"
set country(PM) "ST. PIERRE AND MIQUELON"
set country(SD) "SUDAN"
set country(SR) "SURINAME"
set country(SJ) "SVALBARD AND JAN MAYEN ISLANDS"
set country(SZ) "SWAZILAND"
set country(SE) "SWEDEN"
set country(CH) "SWITZERLAND"
set country(CH) "CANTONS OF HELVETIA"
set country(CH) "CONFEDERATION HELVETIQUE"
set country(SY) "SYRIAN ARAB REPUBLIC"
set country(SY) "SYRIA"
set country(TW) "TAIWAN"
set country(TJ) "TAJIKISTAN"
set country(TZ) "TANZANIA"
set country(TH) "THAILAND"
set country(TG) "TOGO"
set country(TK) "TOKELAU"
set country(TO) "TONGA"
set country(TT) "TRINIDAD AND TOBAGO"
set country(TN) "TUNISIA"
set country(TR) "TURKEY"
set country(TM) "TURKMENISTAN"
set country(TC) "TURKS AND CAICOS ISLANDS"
set country(TV) "TUVALU"
set country(UG) "UGANDA"
set country(UA) "UKRAINIAN SSR"
set country(AE) "UNITED ARAB EMIRATES"
set country(UK) "UNITED KINGDOM"
set country(GB) "GREAT BRITAIN"
set country(US) "UNITED STATES OF AMERICA"
set country(US) "UNITED STATES"
set country(UM) "UNITED STATES MINOR OUTLYING ISLANDS"
set country(UY) "URUGUAY"
set country(SU) "USSR"
set country(SU) "SOVIET UNION"
set country(UZ) "UZBEKISTAN"
set country(VU) "VANUATU"
set country(VA) "VATICAN"
set country(VA) "VATICAN CITY STATE"
set country(VE) "VENEZUELA"
set country(VN) "VIET NAM"
set country(VI) "VIRGIN ISLANDS (US)"
set country(VG) "VIRGIN ISLANDS (UK)"
set country(WF) "WALLIS AND FUTUNA ISLANDS"
set country(EH) "WESTERN SAHARA"
set country(YE) "YEMEN"
set country(YU) "YUGOSLAVIA"
set country(ZR) "ZAIRE"
set country(ZM) "ZAMBIA"
set country(ZW) "ZIMBABWE"
set country(COM) "COMMERCIAL ORGANIZATION"
set country(EDU) "EDUCATIONAL INSTITUTION"
set country(GOV) "US GOVERNMENT"
set country(INT) "INTERNATIONAL ORGANIZATION"
set country(MIL) "US DEPARTMENT OF DEFENSE"
set country(NET) "NETWORKING ORGANIZATION"
set country(ORG) "NON-PROFIT ORGANIZATION"
set country(ARPA) "ARPANET (US MILITARY)"
set country(KP) "KOREA - DEMOCRATIC PEOPLE\"S REPUBLIC OF"
set country(KR) "KOREA - REPUBLIC OF"
set country(LA) "LAO PEOPLES\" DEMOCRATIC REPUBLIC"
set country(SU) "RUSSIA"
set country(SK) "SLOVAKIA"
set country(CZ) "CZECH"
